• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#  Copyright (C) 2023 The Android Open Source Project
2#
3#  Licensed under the Apache License, Version 2.0 (the "License");
4#  you may not use this file except in compliance with the License.
5#  You may obtain a copy of the License at
6#
7#       http://www.apache.org/licenses/LICENSE-2.0
8#
9#  Unless required by applicable law or agreed to in writing, software
10#  distributed under the License is distributed on an "AS IS" BASIS,
11#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12#  See the License for the specific language governing permissions and
13#  limitations under the License.
14
15import xml.etree.ElementTree as ET
16import datetime
17import os
18
19
20class AdServicesUiUtil:
21    PUBLIC_XML_DIR = '../apk/publicres/values/public.xml'
22    STRINGS_XML_DIR = '../apk/res/values/strings.xml'
23    COPYRIGHT_TEXT = f'''<?xml version="1.0" encoding="utf-8"?>
24<!-- Copyright (C) {datetime.date.today().year} The Android Open Source Project
25
26    Licensed under the Apache License, Version 2.0 (the "License");
27    you may not use this file except in compliance with the License.
28    You may obtain a copy of the License at
29
30    http://www.apache.org/licenses/LICENSE-2.0
31
32    Unless required by applicable law or agreed to in writing, software
33    distributed under the License is distributed on an "AS IS" BASIS,
34    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35    See the License for the specific language governing permissions and
36    limitations under the License.
37-->
38<!-- DO NOT MODIFY. This file is automatically generated by generate_adservices_public_xml.py -->\n'''
39
40    def __init__(self):
41        pass
42
43    def _get_min_id(self, existing_mapping):
44        return int(min(existing_mapping.values()), 0)
45
46    def _get_existing_tree(self, dir):
47        if not os.path.exists(dir):
48            return None, {}
49        else:
50            root = ET.parse(dir).getroot()
51            return root, {
52                node.attrib['name']: node.attrib['id']
53                for node in root
54            }
55
56    def _overwrite_public_xml(self, root, public_xml_dir):
57        if os.path.exists(public_xml_dir):
58            os.remove(public_xml_dir)
59
60        ET.indent(root, space='    ')
61        with open(public_xml_dir, "w+") as file:
62            file.write(self.COPYRIGHT_TEXT)
63            file.write(ET.tostring(root, encoding="unicode"))
64
65    def update_public_xml(self, strings_xml_dir=STRINGS_XML_DIR, public_xml_dir=PUBLIC_XML_DIR):
66        if not os.path.exists(strings_xml_dir):
67            return
68
69        new_strings = [node.attrib['name'] for node in ET.parse(strings_xml_dir).getroot()]
70        root, mapping = self._get_existing_tree(public_xml_dir)
71
72        added_strings = [string for string in new_strings if string not in mapping]
73        # TO-DO: add code to remove exsting elements when needed.
74        new_strings = set(new_strings)
75        deleted_strings = set(string for string in mapping if string not in new_strings)
76
77        if not added_strings:
78            return
79
80        i_min = self._get_min_id(mapping)
81        for string in added_strings:
82            i_min -= 1
83            added_element = ET.SubElement(root, 'public')
84            added_element.set('type', 'string')
85            added_element.set('name', string)
86            added_element.set('id', hex(i_min))
87
88        self._overwrite_public_xml(root, public_xml_dir)
89
90
91if __name__ == '__main__':
92    util = AdServicesUiUtil()
93    util.update_public_xml()
94