Skip to content

Commit

Permalink
Rewrite ClassWriter with Builder pattern and add javadoc support.
Browse files Browse the repository at this point in the history
  • Loading branch information
silvio2402 committed Sep 13, 2024
1 parent debee26 commit 21c08b0
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@

package com.google.i18n.phonenumbers;

/**
* Class containing string constants of region codes for easier testing.
*/
final class RegionCode {
// Class containing string constants of region codes for easier testing.
// Region code for global networks (e.g. +800 numbers).
static final String UN001 = "001";
static final String AD = "AD";
Expand Down
25 changes: 25 additions & 0 deletions tools/java/java-build/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,31 @@
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.auto.value/auto-value -->
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value</artifactId>
<version>1.11.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.auto.value/auto-value-annotations -->
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value-annotations</artifactId>
<version>1.11.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.findbugs/jsr305 -->
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.3.0-jre</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.google.i18n.phonenumbers;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSortedSet;
import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
import com.google.i18n.phonenumbers.Phonemetadata.PhoneMetadataCollection;

Expand All @@ -35,6 +37,7 @@
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;

/**
* Tool to convert phone number metadata from the XML format to protocol buffer format.
Expand Down Expand Up @@ -101,9 +104,25 @@ public class BuildMetadataProtoFromXml extends Command {
"/* This file is automatically generated by {@link " + CLASS_NAME + "}.\n" +
" * Please don't modify it directly.\n" +
" */\n\n";

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 String COUNTRY_CODE_SET_COMMENT =
" // A set of all country codes for which data is available.\n";
private static final String REGION_CODE_SET_COMMENT =
" // A set of all region 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 entries,\n" +
" // and this offers a load factor of roughly " + CAPACITY_FACTOR + ".\n";

private static final String REGION_CODE_CONSTS_COMMENT =
" // Class containing string constants of region codes for easier testing.\n";
private static final String REGION_CODE_CONSTS_JAVADOC =
"/**\n" +
" * Class containing string constants of region codes for easier testing.\n" +
" */\n";

@Override
public String getCommandName() {
Expand Down Expand Up @@ -241,20 +260,6 @@ private void deleteAllFilesForPrefix(String filePrefix) {
System.out.println("Deleted " + counter + " old files");
}

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 String COUNTRY_CODE_SET_COMMENT =
" // A set of all country codes for which data is available.\n";
private static final String REGION_CODE_SET_COMMENT =
" // A set of all region 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 entries,\n" +
" // and this offers a load factor of roughly " + CAPACITY_FACTOR + ".\n";

private static void writeCountryCallingCodeMappingToJavaFile(
Map<Integer, List<String>> countryCodeToRegionCodeMap,
String outputDir, String mappingClass, String copyright) throws IOException {
Expand All @@ -269,7 +274,11 @@ private static void writeCountryCallingCodeMappingToJavaFile(
}
boolean hasCountryCodes = countryCodeToRegionCodeMap.size() > 1;

ClassWriter writer = new ClassWriter(outputDir, mappingClass, copyright);
ClassWriter.Builder writer = ClassWriter.builder()
.setOutputDir(outputDir)
.setCopyright(Integer.parseInt(copyright))
.setModifiers("public")
.setName(mappingClass);

int capacity = (int) (countryCodeToRegionCodeMap.size() / CAPACITY_FACTOR);
if (hasRegionCodes && hasCountryCodes) {
Expand All @@ -282,10 +291,10 @@ private static void writeCountryCallingCodeMappingToJavaFile(
writeRegionCodeSet(writer, capacity, regionCodeList);
}

writer.writeToFile();
writer.build().writeToFile();
}

private static void writeMap(ClassWriter writer, int capacity,
private static void writeMap(ClassWriter.Builder writer, int capacity,
Map<Integer, List<String>> countryCodeToRegionCodeMap) {
writer.addToBody(MAP_COMMENT);

Expand Down Expand Up @@ -319,7 +328,7 @@ private static void writeMap(ClassWriter writer, int capacity,
writer.addToBody(" }\n");
}

private static void writeRegionCodeSet(ClassWriter writer, int capacity,
private static void writeRegionCodeSet(ClassWriter.Builder writer, int capacity,
List<String> regionCodeList) {
writer.addToBody(REGION_CODE_SET_COMMENT);

Expand All @@ -340,7 +349,7 @@ private static void writeRegionCodeSet(ClassWriter writer, int capacity,
writer.addToBody(" }\n");
}

private static void writeCountryCodeSet(ClassWriter writer, int capacity,
private static void writeCountryCodeSet(ClassWriter.Builder writer, int capacity,
Set<Integer> countryCodeSet) {
writer.addToBody(COUNTRY_CODE_SET_COMMENT);

Expand All @@ -361,9 +370,15 @@ private static void writeCountryCodeSet(ClassWriter writer, int capacity,
writer.addToBody(" }\n");
}

private static void writeRegionCodeConstantsToJavaFile(Collection<String> regionCodeList, String outputDir, String copyright) throws IOException {
ClassWriter writer = new ClassWriter(outputDir, "RegionCode", copyright, "final");
writer.addToBody(REGION_CODE_CONSTS_COMMENT);
private static void writeRegionCodeConstantsToJavaFile(Collection<String> regionCodeList,
String outputDir, String copyright) throws IOException {
ClassWriter.Builder writer = ClassWriter.builder()
.setOutputDir(outputDir)
.setName("RegionCode")
.setModifiers("final")
.setCopyright(Integer.parseInt(copyright));

writer.addToJavadoc(REGION_CODE_CONSTS_JAVADOC);

for (String regionCode : regionCodeList) {
String variableName = regionCode.toUpperCase();
Expand All @@ -376,60 +391,89 @@ private static void writeRegionCodeConstantsToJavaFile(Collection<String> region
writer.addToBody(" static final String " + variableName + " = \"" + regionCode + "\";\n");
}

writer.writeToFile();
writer.build().writeToFile();
}

private static final class ClassWriter {
private final String name;
private final String copyright;
private final String modifiers;

private final SortedSet<String> imports;
private final StringBuffer body;
private final Formatter formatter;
private final Writer writer;

ClassWriter(String outputDir, String name, String copyright, String modifiers) throws IOException {
this.name = name;
this.copyright = copyright;
this.modifiers = modifiers;

imports = new TreeSet<String>();
body = new StringBuffer();
formatter = new Formatter(body);
writer = new BufferedWriter(new FileWriter(new File(outputDir, name + ".java")));
}

ClassWriter(String outputDir, String name, String copyright) throws IOException {
this(outputDir, name, copyright, "public");
@AutoValue
abstract static class ClassWriter {
abstract String outputDir();

abstract Integer copyright();
abstract ImmutableSortedSet<String> imports();
abstract String javadoc();
abstract String modifiers();
abstract String name();
abstract String body();

static Builder builder() {
return new AutoValue_BuildMetadataProtoFromXml_ClassWriter.Builder()
.setModifiers("");
}

void addToImports(String name) {
imports.add(name);
}
@AutoValue.Builder
abstract static class Builder {
abstract Builder setOutputDir(String outputDir);

abstract Builder setCopyright(Integer copyright);

abstract ImmutableSortedSet.Builder<String> importsBuilder();
final Builder addToImports(String name) {
importsBuilder().add(name);
return this;
}

void addToBody(CharSequence text) {
body.append(text);
}
abstract Builder setJavadoc(String javadoc);
private final StringBuilder javadocBuilder = new StringBuilder();
final Builder addToJavadoc(String text) {
javadocBuilder.append(text);
return this;
}

abstract Builder setName(String name);
abstract Builder setModifiers(String modifiers);

abstract Builder setBody(String body);
private final StringBuilder bodyBuilder = new StringBuilder();
final Builder addToBody(String text) {
bodyBuilder.append(text);
return this;
}
final Builder formatToBody(String format, Object... args) {
Formatter formatter = new Formatter(bodyBuilder);
formatter.format(format, args);
return this;
}

void formatToBody(String format, Object... args) {
formatter.format(format, args);
abstract ClassWriter autoBuild();

final ClassWriter build() {
setJavadoc(javadocBuilder.toString());
setBody(bodyBuilder.toString());
return autoBuild();
}
}

void writeToFile() throws IOException {
CopyrightNotice.writeTo(writer, Integer.valueOf(copyright));
Writer writer = new BufferedWriter(new FileWriter(new File(outputDir(), name() + ".java")));

CopyrightNotice.writeTo(writer, copyright());
writer.write(GENERATION_COMMENT);
writer.write("package " + PACKAGE_NAME + ";\n\n");

if (!imports.isEmpty()) {
for (String item : imports) {
if (!imports().isEmpty()) {
for (String item : imports()) {
writer.write("import " + item + ";\n");
}
writer.write("\n");
}

writer.write((modifiers.isEmpty() ? "" : modifiers + " ") + "class " + name + " {\n");
writer.write(body.toString());
writer.write(javadoc());
if (!modifiers().isEmpty()) {
writer.write(modifiers() + " ");
}
writer.write("class " + name() + " {\n");
writer.write(body());
writer.write("}\n");

writer.flush();
Expand Down

0 comments on commit 21c08b0

Please sign in to comment.