• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.libcore.timezone.telephonylookup;
17 
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.OutputStreamWriter;
21 import java.io.StringReader;
22 import java.io.StringWriter;
23 import java.io.Writer;
24 import java.nio.charset.StandardCharsets;
25 import java.util.List;
26 import java.util.Objects;
27 
28 import javax.xml.stream.XMLOutputFactory;
29 import javax.xml.stream.XMLStreamException;
30 import javax.xml.stream.XMLStreamWriter;
31 import javax.xml.transform.OutputKeys;
32 import javax.xml.transform.Transformer;
33 import javax.xml.transform.TransformerException;
34 import javax.xml.transform.TransformerFactory;
35 import javax.xml.transform.stream.StreamResult;
36 import javax.xml.transform.stream.StreamSource;
37 
38 /**
39  * A class that knows about the structure of the telephonylookup.xml file.
40  */
41 final class TelephonyLookupXmlFile {
42 
43     // <telephony_lookup>
44     private static final String TELEPHONY_LOOKUP_ELEMENT = "telephony_lookup";
45 
46     // <networks>
47     private static final String NETWORKS_ELEMENT = "networks";
48 
49     // <network mcc="123" mnc="456" country="gu">
50     private static final String NETWORK_ELEMENT = "network";
51     private static final String MOBILE_COUNTRY_CODE_ATTRIBUTE = "mcc";
52     private static final String MOBILE_NETWORK_CODE_ATTRIBUTE = "mnc";
53     private static final String COUNTRY_ISO_CODE_ATTRIBUTE = "country";
54 
55     // <mobile_countries>
56     private static final String MOBILE_COUNTRIES_ELEMENT = "mobile_countries";
57 
58     // <mobile_country mcc="123" [default="gu"]>
59     private static final String MOBILE_COUNTRY_ELEMENT = "mobile_country";
60     private static final String DEFAULT_ATTRIBUTE = "default";
61 
write(TelephonyLookup telephonyLookup, String outputFile)62     static void write(TelephonyLookup telephonyLookup, String outputFile)
63             throws XMLStreamException, IOException {
64         /*
65          * The required XML structure is:
66          * <telephony_lookup>
67          *   <networks>
68          *     <network mcc="123" mnc="456" country="zz"/>
69          *     <network mcc="123" mnc="789" country="zz"/>
70          *   </networks>
71          *
72          *   <mobile_countries>
73          *     <mobile_country mcc="310"/>
74          *       <country>us</country>
75          *     </mobile_country>
76          *     <mobile_country mcc="340" default="gp">
77          *       <country>gp</country>
78          *       <country>gf</country>
79          *     </mobile_country>
80          *   </mobile_countries>
81          * </telephony_lookup>
82          */
83 
84         StringWriter writer = new StringWriter();
85         writeRaw(telephonyLookup, writer);
86         String rawXml = writer.getBuffer().toString();
87 
88         TransformerFactory factory = TransformerFactory.newInstance();
89         try (Writer fileWriter = new OutputStreamWriter(
90                 new FileOutputStream(outputFile), StandardCharsets.UTF_8)) {
91 
92             // Transform the XML with the identity transform but with indenting
93             // so it's more human-readable.
94             Transformer transformer = factory.newTransformer();
95             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
96             transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "1");
97             transformer.transform(
98                     new StreamSource(new StringReader(rawXml)), new StreamResult(fileWriter));
99         } catch (TransformerException e) {
100             throw new XMLStreamException(e);
101         }
102     }
103 
writeRaw(TelephonyLookup telephonyLookup, Writer fileWriter)104     private static void writeRaw(TelephonyLookup telephonyLookup, Writer fileWriter)
105             throws XMLStreamException {
106         XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
107         XMLStreamWriter xmlWriter = xmlOutputFactory.createXMLStreamWriter(fileWriter);
108         xmlWriter.writeStartDocument();
109         xmlWriter.writeComment("\n\n **** Autogenerated file - DO NOT EDIT ****\n\n");
110         TelephonyLookup.writeXml(telephonyLookup, xmlWriter);
111         xmlWriter.writeEndDocument();
112     }
113 
114     static class TelephonyLookup {
115         private final List<Network> networks;
116         private final List<MobileCountry> mobileCountries;
117 
TelephonyLookup(List<Network> networks, List<MobileCountry> mobileCountries)118         TelephonyLookup(List<Network> networks, List<MobileCountry> mobileCountries) {
119             this.networks = networks;
120             this.mobileCountries = mobileCountries;
121         }
122 
writeXml(TelephonyLookup telephonyLookup, XMLStreamWriter writer)123         static void writeXml(TelephonyLookup telephonyLookup, XMLStreamWriter writer)
124                 throws XMLStreamException {
125             writer.writeStartElement(TELEPHONY_LOOKUP_ELEMENT);
126 
127             // Networks
128             writer.writeStartElement(NETWORKS_ELEMENT);
129             for (Network network : telephonyLookup.networks) {
130                 network.writeXml(network, writer);
131             }
132             writer.writeEndElement(); // NETWORKS_ELEMENT
133 
134             // Mobile Countries
135             writer.writeStartElement(MOBILE_COUNTRIES_ELEMENT);
136             for (MobileCountry mobileCountry : telephonyLookup.mobileCountries) {
137                 mobileCountry.writeXml(mobileCountry, writer);
138             }
139             writer.writeEndElement(); // MOBILE_COUNTRIES_ELEMENT
140 
141             writer.writeEndElement(); // TELEPHONY_LOOKUP_ELEMENT
142         }
143     }
144 
145     static class Network {
146 
147         private final String mcc;
148         private final String mnc;
149         private final String countryIsoCode;
150 
Network(String mcc, String mnc, String countryIsoCode)151         Network(String mcc, String mnc, String countryIsoCode) {
152             this.mcc = Objects.requireNonNull(mcc);
153             this.mnc = Objects.requireNonNull(mnc);
154             this.countryIsoCode = Objects.requireNonNull(countryIsoCode);
155         }
156 
writeXml(Network network, XMLStreamWriter writer)157         static void writeXml(Network network, XMLStreamWriter writer)
158                 throws XMLStreamException {
159             writer.writeStartElement(NETWORK_ELEMENT);
160             writer.writeAttribute(MOBILE_COUNTRY_CODE_ATTRIBUTE, network.mcc);
161             writer.writeAttribute(MOBILE_NETWORK_CODE_ATTRIBUTE, network.mnc);
162             writer.writeAttribute(COUNTRY_ISO_CODE_ATTRIBUTE, network.countryIsoCode);
163             writer.writeEndElement(); // NETWORK_ELEMENT
164         }
165     }
166 
167     static class MobileCountry {
168 
169         private final String mcc;
170         private final List<String> countryIsoCodes;
171 
MobileCountry(String mcc, List<String> countryIsoCodes)172         MobileCountry(String mcc, List<String> countryIsoCodes) {
173             this.mcc = Objects.requireNonNull(mcc);
174             this.countryIsoCodes = Objects.requireNonNull(countryIsoCodes);
175         }
176 
writeXml(MobileCountry mobileCountry, XMLStreamWriter writer)177         static void writeXml(MobileCountry mobileCountry, XMLStreamWriter writer)
178                 throws XMLStreamException {
179             writer.writeStartElement(MOBILE_COUNTRY_ELEMENT);
180             writer.writeAttribute(MOBILE_COUNTRY_CODE_ATTRIBUTE, mobileCountry.mcc);
181 
182             if (mobileCountry.countryIsoCodes.size() > 1) {
183                 writer.writeAttribute(DEFAULT_ATTRIBUTE, mobileCountry.countryIsoCodes.getFirst());
184             }
185 
186             for (String countryIsoCode : mobileCountry.countryIsoCodes) {
187                 writer.writeStartElement(COUNTRY_ISO_CODE_ATTRIBUTE);
188                 writer.writeCharacters(countryIsoCode);
189                 writer.writeEndElement(); // COUNTRY_ISO_CODE_ATTRIBUTE
190             }
191 
192             writer.writeEndElement(); // MOBILE_COUNTRY_ELEMENT
193         }
194     }
195 }
196