1. Patrick Mézard
  2. libphonenumber-csharp

Commits

Patrick Mézard  committed 00324a5 Merge

Merge with r485

  • Participants
  • Parent commits 8bc21de, 457fa63
  • Branches csharp

Comments (0)

Files changed (5)

File csharp/PhoneNumbers/Properties/AssemblyInfo.cs

View file
 //
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
-// [assembly: AssemblyVersion("4.9.0.40")]
-[assembly: AssemblyVersion("4.9.0.40")]
-[assembly: AssemblyFileVersion("4.9.0.40")]
+// [assembly: AssemblyVersion("4.9.0.41")]
+[assembly: AssemblyVersion("4.9.0.41")]
+[assembly: AssemblyFileVersion("4.9.0.41")]

File java/build.xml

View file
       <arg value="-jar" />
       <arg value="${build.tools.jar}"/>
       <arg value="BuildMetadataProtoFromXml"/>
-      <arg value="${resources.dir}/PhoneNumberMetaData.xml"/>
-      <arg value="libphonenumber/src"/>
-      <arg value="false"/> <!-- Not for testing. -->
-      <arg value="false"/> <!-- Not for alternate formats. -->
-      <arg value="false"/> <!-- No lite metadata. -->
+      <arg value="--input-file=${resources.dir}/PhoneNumberMetaData.xml"/>
+      <arg value="--output-dir=${libphonenumber.src.dir}/com/google/i18n/phonenumbers"/>
+      <arg value="--data-prefix=data/PhoneNumberMetadataProto"/>
+      <arg value="--mapping-class=CountryCodeToRegionCodeMap"/>
+      <arg value="--copyright=2010"/>
+      <arg value="--lite-build=false"/>
     </exec>
   </target>
 
       <arg value="-jar" />
       <arg value="${build.tools.jar}"/>
       <arg value="BuildMetadataProtoFromXml"/>
-      <arg value="${resources.dir}/PhoneNumberMetaDataForTesting.xml"/>
-      <arg value="libphonenumber/test"/>
-      <arg value="true"/> <!-- For testing. -->
-      <arg value="false"/> <!-- Not for alternate formats. -->
-      <arg value="false"/> <!-- No lite metadata. -->
+      <arg value="--input-file=${resources.dir}/PhoneNumberMetaDataForTesting.xml"/>
+      <arg value="--output-dir=${libphonenumber.test.dir}/com/google/i18n/phonenumbers"/>
+      <arg value="--data-prefix=data/PhoneNumberMetadataProtoForTesting"/>
+      <arg value="--mapping-class=CountryCodeToRegionCodeMapForTesting"/>
+      <arg value="--copyright=2010"/>
+      <arg value="--lite-build=false"/>
     </exec>
   </target>
 
 
   <target name="junit" depends="test-jar">
     <mkdir dir="${report.dir}"/>
-    <junit printsummary="yes">
+    <junit printsummary="yes"
+        failureProperty="test.failed" errorProperty="test.failed">
       <classpath refid="test.classpath"/>
       <formatter type="xml"/>
       <batchtest fork="no" todir="${report.dir}">
         <fileset dir="${geocoder.test.dir}" includes="**/*Test.java"/>
       </batchtest>
     </junit>
+    <fail message="Tests failed. Run 'ant junitreport' for more info."
+        if="test.failed"/>
   </target>
 
   <target name="junitreport">

File tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java

View file
       } else {
         // For most countries, there will be only one region code for the country calling code.
         List<String> listWithRegionCode = new ArrayList<String>(1);
-        listWithRegionCode.add(regionCode);
+        if (!regionCode.isEmpty()) {  // For alternate formats, there are no region codes at all.
+          listWithRegionCode.add(regionCode);
+        }
         countryCodeToRegionCodeMap.put(countryCode, listWithRegionCode);
       }
     }

File tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java

View file
 import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection;
 
 import java.io.BufferedWriter;
+import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.ObjectOutputStream;
+import java.io.Writer;
 import java.util.Formatter;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Tool to convert phone number metadata from the XML format to protocol buffer format.
  * @author Shaopeng Jia
  */
 public class BuildMetadataProtoFromXml extends Command {
-  private static final String PACKAGE_NAME = "com/google/i18n/phonenumbers";
+  private static final String CLASS_NAME = BuildMetadataProtoFromXml.class.getSimpleName();
+  private static final String PACKAGE_NAME = BuildMetadataProtoFromXml.class.getPackage().getName();
 
-  private static final String META_DATA_FILE_PREFIX =
-      "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto";
-  private static final String TEST_META_DATA_FILE_PREFIX =
-      "/com/google/i18n/phonenumbers/data/PhoneNumberMetadataProtoForTesting";
-  private static final String ALTERNATE_FORMATS_FILE_PREFIX =
-      "/com/google/i18n/phonenumbers/data/PhoneNumberAlternateFormatsProto";
-
-  private static final String COUNTRY_CODE_TO_REGION_CODE_MAP_CLASS_NAME =
-      "CountryCodeToRegionCodeMap";
-  private static final String TEST_COUNTRY_CODE_TO_REGION_CODE_MAP_CLASS_NAME =
-      "CountryCodeToRegionCodeMapForTesting";
-  private static final String ALTERNATE_COUNTRY_CODE_TO_REGION_CODE_MAP_CLASS_NAME =
-      "CountryCodeToRegionCodeMapForAlternate";
+  // Command line parameter names.
+  private static final String INPUT_FILE = "input-file";
+  private static final String OUTPUT_DIR = "output-dir";
+  private static final String DATA_PREFIX = "data-prefix";
+  private static final String MAPPING_CLASS = "mapping-class";
+  private static final String COPYRIGHT = "copyright";
+  private static final String LITE_BUILD = "lite-build";
 
   private static final String HELP_MESSAGE =
-      "Usage:\n" +
-      "BuildMetadataProtoFromXml <inputFile> <outputDir>" +
-      "                          <forTesting> <forAlternate> [<liteBuild>]\n" +
+      "Usage: " + CLASS_NAME + " [OPTION]...\n" +
       "\n" +
-      "where:\n" +
-      "  inputFile    The input file containing phone number metadata in XML format.\n" +
-      "  outputDir    The output source directory to store phone number metadata in proto\n" +
-      "               format (one file per region) and the country code to region code\n" +
-      "               mapping file.\n" +
-      "  forTesting   Flag whether to generate metadata for testing purposes or not.\n" +
-      "  forAlternate Flag whether to generate metadata for alternate formats or not.\n" +
-      "  liteBuild    Whether to generate the lite-version of the metadata (default:\n" +
-      "               false). When set to true certain metadata will be omitted.\n" +
-      "               At this moment, example numbers information is omitted.\n" +
+      "  --" + INPUT_FILE + "=PATH     Read phone number metadata in XML format from PATH.\n" +
+      "  --" + OUTPUT_DIR + "=PATH     Use PATH as the root directory for output files.\n" +
+      "  --" + DATA_PREFIX +
+          "=PATH    Use PATH (relative to " + OUTPUT_DIR + ") as the basename when\n" +
+      "                        writing phone number metadata (one file per region) in\n" +
+      "                        proto format.\n" +
+      "  --" + MAPPING_CLASS + "=NAME  Store country code mappings in the class NAME, which\n" +
+      "                        will be written to a file in " + OUTPUT_DIR + ".\n" +
+      "  --" + COPYRIGHT + "=YEAR      Use YEAR in generated copyright headers.\n" +
       "\n" +
-      "Metadata will be stored in:\n" +
-      "  <outputDir>" + META_DATA_FILE_PREFIX + "_*\n" +
-      "Mapping file will be stored in:\n" +
-      "  <outputDir>/" + PACKAGE_NAME + "/" +
-          COUNTRY_CODE_TO_REGION_CODE_MAP_CLASS_NAME + ".java\n" +
+      "  [--" + LITE_BUILD + "=<true|false>]  Optional (default: false). In a lite build,\n" +
+      "                               certain metadata will be omitted. At this\n" +
+      "                               moment, example numbers information is omitted.\n" +
       "\n" +
       "Example command line invocation:\n" +
-      "BuildMetadataProtoFromXml PhoneNumberMetadata.xml src false false false\n";
+      CLASS_NAME + " \\\n" +
+      "  --" + INPUT_FILE + "=resources/PhoneNumberMetaData.xml \\\n" +
+      "  --" + OUTPUT_DIR + "=java/libphonenumber/src/com/google/i18n/phonenumbers \\\n" +
+      "  --" + DATA_PREFIX + "=data/PhoneNumberMetadataProto \\\n" +
+      "  --" + MAPPING_CLASS + "=CountryCodeToRegionCodeMap \\\n" +
+      "  --" + COPYRIGHT + "=2010 \\\n" +
+      "  --" + LITE_BUILD + "=false\n";
 
   private static final String GENERATION_COMMENT =
-      "/* This file is automatically generated by {@link BuildMetadataProtoFromXml}.\n" +
+      "/* This file is automatically generated by {@link " + CLASS_NAME + "}.\n" +
       " * Please don't modify it directly.\n" +
       " */\n\n";
 
   @Override
   public String getCommandName() {
-    return "BuildMetadataProtoFromXml";
+    return CLASS_NAME;
   }
 
   @Override
   public boolean start() {
-    String[] args = getArgs();
-    if (args.length != 5 && args.length != 6) {
+    // The format of a well-formed command line parameter.
+    Pattern pattern = Pattern.compile("--(.+?)=(.*)");
+
+    String inputFile = null;
+    String outputDir = null;
+    String dataPrefix = null;
+    String mappingClass = null;
+    String copyright = null;
+    boolean liteBuild = false;
+
+    for (int i = 1; i < getArgs().length; i++) {
+      String key = null;
+      String value = null;
+      Matcher matcher = pattern.matcher(getArgs()[i]);
+      if (matcher.matches()) {
+        key = matcher.group(1);
+        value = matcher.group(2);
+      }
+
+      if (INPUT_FILE.equals(key)) {
+        inputFile = value;
+      } else if (OUTPUT_DIR.equals(key)) {
+        outputDir = value;
+      } else if (DATA_PREFIX.equals(key)) {
+        dataPrefix = value;
+      } else if (MAPPING_CLASS.equals(key)) {
+        mappingClass = value;
+      } else if (COPYRIGHT.equals(key)) {
+        copyright = value;
+      } else if (LITE_BUILD.equals(key) &&
+                 ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value))) {
+        liteBuild = "true".equalsIgnoreCase(value);
+      } else {
+        System.err.println(HELP_MESSAGE);
+        System.err.println("Illegal command line parameter: " + getArgs()[i]);
+        return false;
+      }
+    }
+
+    if (inputFile == null ||
+        outputDir == null ||
+        dataPrefix == null ||
+        mappingClass == null ||
+        copyright == null) {
       System.err.println(HELP_MESSAGE);
       return false;
     }
-    String inputFile = args[1];
-    String outputDir = args[2];
-    boolean forTesting = args[3].equals("true");
-    boolean forAlternate = args[4].equals("true");
-    boolean liteBuild = args.length > 5 && args[5].equals("true");
 
-    String filePrefix;
-    if (forAlternate) {
-      filePrefix = outputDir + ALTERNATE_FORMATS_FILE_PREFIX;
-    } else if (forTesting) {
-      filePrefix = outputDir + TEST_META_DATA_FILE_PREFIX;
-    } else {
-      filePrefix = outputDir + META_DATA_FILE_PREFIX;
-    }
+    String filePrefix = new File(outputDir, dataPrefix).getPath();
 
     try {
       PhoneMetadataCollection metadataCollection =
           BuildMetadataFromXml.buildCountryCodeToRegionCodeMap(metadataCollection);
 
       writeCountryCallingCodeMappingToJavaFile(
-          countryCodeToRegionCodeMap, outputDir, forTesting, forAlternate);
+          countryCodeToRegionCodeMap, outputDir, mappingClass, copyright);
     } catch (Exception e) {
       e.printStackTrace();
       return false;
     return true;
   }
 
-  private static final String MAPPING_IMPORTS =
-      "import java.util.ArrayList;\n" +
-      "import java.util.HashMap;\n" +
-      "import java.util.List;\n" +
-      "import java.util.Map;\n";
-  private static final String MAPPING_COMMENT =
+  private static final String MAP_COMMENT =
       "  // A mapping from a country code to the region codes which denote the\n" +
       "  // country/region represented by that country code. In the case of multiple\n" +
       "  // countries sharing a calling code, such as the NANPA countries, the one\n" +
       "  // indicated with \"isMainCountryForCode\" in the metadata should be first.\n";
-  private static final double MAPPING_LOAD_FACTOR = 0.75;
-  private static final String MAPPING_COMMENT_2 =
+  private static final String SET_COMMENT =
+      "  // A set of all country codes for which data is available.\n";
+  private static final double CAPACITY_FACTOR = 0.75;
+  private static final String CAPACITY_COMMENT =
       "    // The capacity is set to %d as there are %d different country codes,\n" +
-      "    // and this offers a load factor of roughly " + MAPPING_LOAD_FACTOR + ".\n";
-  private static final int COPYRIGHT_YEAR = 2010;
+      "    // and this offers a load factor of roughly " + CAPACITY_FACTOR + ".\n";
 
   private static void writeCountryCallingCodeMappingToJavaFile(
       Map<Integer, List<String>> countryCodeToRegionCodeMap,
-      String outputDir, boolean forTesting, boolean forAlternate) throws IOException {
-    String mappingClassName;
-    if (forAlternate) {
-      // For alternate formats there will be no region codes in the map (and a set would have been
-      // more appropriate), but we are lazy and re-use existing infrastructure.
-      mappingClassName = ALTERNATE_COUNTRY_CODE_TO_REGION_CODE_MAP_CLASS_NAME;
-    } else if (forTesting) {
-      mappingClassName = TEST_COUNTRY_CODE_TO_REGION_CODE_MAP_CLASS_NAME;
+      String outputDir, String mappingClass, String copyright) throws IOException {
+    int capacity = (int) (countryCodeToRegionCodeMap.size() / CAPACITY_FACTOR);
+
+    // Find out whether the countryCodeToRegionCodeMap has any region codes listed in it.
+    boolean hasRegionCodes = false;
+    for (List<String> listWithRegionCode : countryCodeToRegionCodeMap.values()) {
+      if (!listWithRegionCode.isEmpty()) {
+        hasRegionCodes = true;
+        break;
+      }
+    }
+
+    ClassWriter writer = new ClassWriter(outputDir, mappingClass, copyright);
+
+    if (hasRegionCodes) {
+      writeMap(writer, capacity, countryCodeToRegionCodeMap);
     } else {
-      mappingClassName = COUNTRY_CODE_TO_REGION_CODE_MAP_CLASS_NAME;
+      writeSet(writer, capacity, countryCodeToRegionCodeMap.keySet());
     }
-    String mappingFile = outputDir + "/" + PACKAGE_NAME + "/" + mappingClassName + ".java";
-    int capacity = (int) (countryCodeToRegionCodeMap.size() / MAPPING_LOAD_FACTOR);
 
-    BufferedWriter writer = new BufferedWriter(new FileWriter(mappingFile));
+    writer.writeToFile();
+  }
 
-    CopyrightNotice.writeTo(writer, COPYRIGHT_YEAR);
-    writer.write(GENERATION_COMMENT);
-    if (PACKAGE_NAME.length() > 0) {
-      writer.write("package " + PACKAGE_NAME.replaceAll("/", ".") + ";\n\n");
-    }
-    writer.write(MAPPING_IMPORTS);
-    writer.write("\n");
-    writer.write("public class " + mappingClassName + " {\n");
-    writer.write(MAPPING_COMMENT);
-    writer.write("  static Map<Integer, List<String>> getCountryCodeToRegionCodeMap() {\n");
-    Formatter formatter = new Formatter(writer);
-    formatter.format(MAPPING_COMMENT_2, capacity, countryCodeToRegionCodeMap.size());
-    writer.write("    Map<Integer, List<String>> countryCodeToRegionCodeMap =\n");
-    writer.write("        new HashMap<Integer, List<String>>(" + capacity + ");\n");
-    writer.write("\n");
-    writer.write("    ArrayList<String> listWithRegionCode;\n");
-    writer.write("\n");
+  private static void writeMap(ClassWriter writer, int capacity,
+                               Map<Integer, List<String>> countryCodeToRegionCodeMap) {
+    writer.addToBody(MAP_COMMENT);
+
+    writer.addToImports("java.util.ArrayList");
+    writer.addToImports("java.util.HashMap");
+    writer.addToImports("java.util.List");
+    writer.addToImports("java.util.Map");
+
+    writer.addToBody("  static Map<Integer, List<String>> getCountryCodeToRegionCodeMap() {\n");
+    writer.formatToBody(CAPACITY_COMMENT, capacity, countryCodeToRegionCodeMap.size());
+    writer.addToBody("    Map<Integer, List<String>> countryCodeToRegionCodeMap =\n");
+    writer.addToBody("        new HashMap<Integer, List<String>>(" + capacity + ");\n");
+    writer.addToBody("\n");
+    writer.addToBody("    ArrayList<String> listWithRegionCode;\n");
+    writer.addToBody("\n");
 
     for (Map.Entry<Integer, List<String>> entry : countryCodeToRegionCodeMap.entrySet()) {
       int countryCallingCode = entry.getKey();
       List<String> regionCodes = entry.getValue();
-      writer.write("    listWithRegionCode = new ArrayList<String>(" + regionCodes.size() + ");\n");
+      writer.addToBody("    listWithRegionCode = new ArrayList<String>(" +
+                       regionCodes.size() + ");\n");
       for (String regionCode : regionCodes) {
-        writer.write("    listWithRegionCode.add(\"" + regionCode + "\");\n");
+        writer.addToBody("    listWithRegionCode.add(\"" + regionCode + "\");\n");
       }
-      writer.write("    countryCodeToRegionCodeMap.put(" + countryCallingCode +
-                   ", listWithRegionCode);\n");
-      writer.write("\n");
+      writer.addToBody("    countryCodeToRegionCodeMap.put(" + countryCallingCode +
+                       ", listWithRegionCode);\n");
+      writer.addToBody("\n");
     }
 
-    writer.write("    return countryCodeToRegionCodeMap;\n");
-    writer.write("  }\n");
-    writer.write("}\n");
+    writer.addToBody("    return countryCodeToRegionCodeMap;\n");
+    writer.addToBody("  }\n");
+  }
 
-    writer.flush();
-    writer.close();
+  private static void writeSet(ClassWriter writer, int capacity,
+                               Set<Integer> countryCodeSet) {
+    writer.addToBody(SET_COMMENT);
+
+    writer.addToImports("java.util.HashSet");
+    writer.addToImports("java.util.Set");
+
+    writer.addToBody("  static Set<Integer> getCountryCodeSet() {\n");
+    writer.formatToBody(CAPACITY_COMMENT, capacity, countryCodeSet.size());
+    writer.addToBody("    Set<Integer> countryCodeSet = new HashSet<Integer>(" + capacity + ");\n");
+    writer.addToBody("\n");
+
+    for (int countryCallingCode : countryCodeSet) {
+      writer.addToBody("    countryCodeSet.add(" + countryCallingCode + ");\n");
+    }
+
+    writer.addToBody("\n");
+    writer.addToBody("    return countryCodeSet;\n");
+    writer.addToBody("  }\n");
+  }
+
+  private static final class ClassWriter {
+    private final String name;
+    private final String copyright;
+
+    private final SortedSet<String> imports;
+    private final StringBuffer body;
+    private final Formatter formatter;
+    private final Writer writer;
+
+    ClassWriter(String outputDir, String name, String copyright) throws IOException {
+      this.name = name;
+      this.copyright = copyright;
+
+      imports = new TreeSet<String>();
+      body = new StringBuffer();
+      formatter = new Formatter(body);
+      writer = new BufferedWriter(new FileWriter(new File(outputDir, name + ".java")));
+    }
+
+    void addToImports(String name) {
+      imports.add(name);
+    }
+
+    void addToBody(CharSequence text) {
+      body.append(text);
+    }
+
+    void formatToBody(String format, Object... args) {
+      formatter.format(format, args);
+    }
+
+    void writeToFile() throws IOException {
+      CopyrightNotice.writeTo(writer, Integer.valueOf(copyright));
+      writer.write(GENERATION_COMMENT);
+      writer.write("package " + PACKAGE_NAME + ";\n\n");
+
+      if (!imports.isEmpty()) {
+        for (String item : imports) {
+          writer.write("import " + item + ";\n");
+        }
+        writer.write("\n");
+      }
+
+      writer.write("public class " + name + " {\n");
+      writer.write(body.toString());
+      writer.write("}\n");
+
+      writer.flush();
+      writer.close();
+    }
   }
 }

File tools/java/java-build/target/java-build-1.0-SNAPSHOT-jar-with-dependencies.jar

Binary file modified.