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 write(TelephonyLookup telephonyLookup, String outputFile)55 static void write(TelephonyLookup telephonyLookup, String outputFile) 56 throws XMLStreamException, IOException { 57 /* 58 * The required XML structure is: 59 * <telephony_lookup> 60 * <networks> 61 * <network mcc="123" mnc="456" country="zz"/> 62 * <network mcc="123" mnc="789" country="zz"/> 63 * </network> 64 * </networks> 65 * </telephony_lookup> 66 */ 67 68 StringWriter writer = new StringWriter(); 69 writeRaw(telephonyLookup, writer); 70 String rawXml = writer.getBuffer().toString(); 71 72 TransformerFactory factory = TransformerFactory.newInstance(); 73 try (Writer fileWriter = new OutputStreamWriter( 74 new FileOutputStream(outputFile), StandardCharsets.UTF_8)) { 75 76 // Transform the XML with the identity transform but with indenting 77 // so it's more human-readable. 78 Transformer transformer = factory.newTransformer(); 79 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 80 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "1"); 81 transformer.transform( 82 new StreamSource(new StringReader(rawXml)), new StreamResult(fileWriter)); 83 } catch (TransformerException e) { 84 throw new XMLStreamException(e); 85 } 86 } 87 writeRaw(TelephonyLookup telephonyLookup, Writer fileWriter)88 private static void writeRaw(TelephonyLookup telephonyLookup, Writer fileWriter) 89 throws XMLStreamException { 90 XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory(); 91 XMLStreamWriter xmlWriter = xmlOutputFactory.createXMLStreamWriter(fileWriter); 92 xmlWriter.writeStartDocument(); 93 xmlWriter.writeComment("\n\n **** Autogenerated file - DO NOT EDIT ****\n\n"); 94 TelephonyLookup.writeXml(telephonyLookup, xmlWriter); 95 xmlWriter.writeEndDocument(); 96 } 97 98 static class TelephonyLookup { 99 private final List<Network> networks; 100 TelephonyLookup(List<Network> networks)101 TelephonyLookup(List<Network> networks) { 102 this.networks = networks; 103 } 104 writeXml(TelephonyLookup telephonyLookup, XMLStreamWriter writer)105 static void writeXml(TelephonyLookup telephonyLookup, XMLStreamWriter writer) 106 throws XMLStreamException { 107 writer.writeStartElement(TELEPHONY_LOOKUP_ELEMENT); 108 writer.writeStartElement(NETWORKS_ELEMENT); 109 for (Network network : telephonyLookup.networks) { 110 network.writeXml(network, writer); 111 } 112 writer.writeEndElement(); // NETWORKS_ELEMENT 113 writer.writeEndElement(); // TELEPHONY_LOOKUP_ELEMENT 114 } 115 } 116 117 static class Network { 118 119 private final String mcc; 120 private final String mnc; 121 private final String countryIsoCode; 122 Network(String mcc, String mnc, String countryIsoCode)123 Network(String mcc, String mnc, String countryIsoCode) { 124 this.mcc = Objects.requireNonNull(mcc); 125 this.mnc = Objects.requireNonNull(mnc); 126 this.countryIsoCode = Objects.requireNonNull(countryIsoCode); 127 } 128 writeXml(Network network, XMLStreamWriter writer)129 static void writeXml(Network network, XMLStreamWriter writer) 130 throws XMLStreamException { 131 writer.writeStartElement(NETWORK_ELEMENT); 132 writer.writeAttribute(MOBILE_COUNTRY_CODE_ATTRIBUTE, network.mcc); 133 writer.writeAttribute(MOBILE_NETWORK_CODE_ATTRIBUTE, network.mnc); 134 writer.writeAttribute(COUNTRY_ISO_CODE_ATTRIBUTE, network.countryIsoCode); 135 writer.writeEndElement(); // NETWORK_ELEMENT 136 } 137 } 138 } 139