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