diff --git a/java/build.xml b/java/build.xml index f010e7cf5f..cd68238213 100644 --- a/java/build.xml +++ b/java/build.xml @@ -77,8 +77,9 @@ - + + diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java index a68d45fea5..3a8c65c029 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/CountryCodeToRegionCodeMapForTesting.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Libphonenumber Authors + * Copyright (C) 2011 The Libphonenumber Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java index a8bfec34cf..6bdef41a7c 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/PhoneNumberUtilTest.java @@ -415,7 +415,7 @@ public void testGetExampleNumber() { // We have data for the US, but no data for VOICEMAIL, so return null. assertNull(phoneUtil.getExampleNumberForType(RegionCode.US, PhoneNumberType.VOICEMAIL)); // CS is an invalid region, so we have no data for it. - assertNull(phoneUtil.getExampleNumberForType(RegionCode.CS, PhoneNumberType.MOBILE)); + assertNull(phoneUtil.getExampleNumberForType("CS", PhoneNumberType.MOBILE)); // RegionCode 001 is reserved for supporting non-geographical country calling code. We don't // support getting an example number for it with this method. assertNull(phoneUtil.getExampleNumber(RegionCode.UN001)); @@ -425,7 +425,7 @@ public void testGetInvalidExampleNumber() { // RegionCode 001 is reserved for supporting non-geographical country calling codes. We don't // support getting an invalid example number for it with getInvalidExampleNumber. assertNull(phoneUtil.getInvalidExampleNumber(RegionCode.UN001)); - assertNull(phoneUtil.getInvalidExampleNumber(RegionCode.CS)); + assertNull(phoneUtil.getInvalidExampleNumber("CS")); PhoneNumber usInvalidNumber = phoneUtil.getInvalidExampleNumber(RegionCode.US); assertEquals(1, usInvalidNumber.getCountryCode()); assertFalse(usInvalidNumber.getNationalNumber() == 0); @@ -658,7 +658,7 @@ public void testFormatOutOfCountryWithInvalidRegion() { // AQ/Antarctica isn't a valid region code for phone number formatting, // so this falls back to intl formatting. assertEquals("+1 650 253 0000", - phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.AQ)); + phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, "AQ")); // For region code 001, the out-of-country format always turns into the international format. assertEquals("+1 650 253 0000", phoneUtil.formatOutOfCountryCallingNumber(US_NUMBER, RegionCode.UN001)); @@ -735,7 +735,7 @@ public void testFormatOutOfCountryKeepingAlphaChars() { phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.SG)); // Testing the case of calling from a non-supported region. assertEquals("+61 1-800-SIX-FLAG", - phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AQ)); + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, "AQ")); // Testing the case with an invalid country calling code. alphaNumericNumber.setCountryCode(0).setNationalNumber(18007493524L) @@ -754,7 +754,7 @@ public void testFormatOutOfCountryKeepingAlphaChars() { alphaNumericNumber.setCountryCode(1).setNationalNumber(80749L).setRawInput("180-SIX"); // No country-code stripping can be done since the number is invalid. assertEquals("+1 180-SIX", - phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, RegionCode.AQ)); + phoneUtil.formatOutOfCountryKeepingAlphaChars(alphaNumericNumber, "AQ")); } public void testFormatWithCarrierCode() { @@ -820,12 +820,12 @@ public void testFormatNumberForMobileDialing() { assertEquals("030123456", phoneUtil.formatNumberForMobileDialing(DE_NUMBER, RegionCode.DE, false)); assertEquals("+4930123456", - phoneUtil.formatNumberForMobileDialing(DE_NUMBER, RegionCode.CH, false)); + phoneUtil.formatNumberForMobileDialing(DE_NUMBER, "CH", false)); PhoneNumber deNumberWithExtn = new PhoneNumber().mergeFrom(DE_NUMBER).setExtension("1234"); assertEquals("030123456", phoneUtil.formatNumberForMobileDialing(deNumberWithExtn, RegionCode.DE, false)); assertEquals("+4930123456", - phoneUtil.formatNumberForMobileDialing(deNumberWithExtn, RegionCode.CH, false)); + phoneUtil.formatNumberForMobileDialing(deNumberWithExtn, "CH", false)); // US toll free numbers are marked as noInternationalDialling in the test metadata for testing // purposes. For such numbers, we expect nothing to be returned when the region code is not the @@ -1336,7 +1336,7 @@ public void testGetCountryCodeForRegion() { assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.ZZ)); assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.UN001)); // CS is already deprecated so the library doesn't support it. - assertEquals(0, phoneUtil.getCountryCodeForRegion(RegionCode.CS)); + assertEquals(0, phoneUtil.getCountryCodeForRegion("CS")); } public void testGetNationalDiallingPrefixForRegion() { @@ -1353,7 +1353,7 @@ public void testGetNationalDiallingPrefixForRegion() { assertEquals(null, phoneUtil.getNddPrefixForRegion(RegionCode.ZZ, false)); assertEquals(null, phoneUtil.getNddPrefixForRegion(RegionCode.UN001, false)); // CS is already deprecated so the library doesn't support it. - assertEquals(null, phoneUtil.getNddPrefixForRegion(RegionCode.CS, false)); + assertEquals(null, phoneUtil.getNddPrefixForRegion("CS", false)); } public void testIsNANPACountry() { @@ -2430,7 +2430,7 @@ public void testFailedParseOnInvalidNumbers() { } try { String someNumber = "123 456 7890"; - phoneUtil.parse(someNumber, RegionCode.CS); + phoneUtil.parse(someNumber, "CS"); fail("Deprecated region code not allowed: should fail."); } catch (NumberParseException e) { // Expected this exception. @@ -2854,7 +2854,7 @@ public void testParseAndKeepRaw() throws Exception { // Invalid region code supplied. try { - phoneUtil.parseAndKeepRawInput("123 456 7890", RegionCode.CS); + phoneUtil.parseAndKeepRawInput("123 456 7890", "CS"); fail("Deprecated region code not allowed: should fail."); } catch (NumberParseException e) { // Expected this exception. diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java index 20fc1212cd..acd55ba0d0 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/RegionCode.java @@ -14,6 +14,10 @@ * limitations under the License. */ +/* This file is automatically generated by {@link BuildMetadataProtoFromXml}. + * Please don't modify it directly. + */ + package com.google.i18n.phonenumbers; /** @@ -26,7 +30,6 @@ final class RegionCode { static final String AE = "AE"; static final String AM = "AM"; static final String AO = "AO"; - static final String AQ = "AQ"; static final String AR = "AR"; static final String AU = "AU"; static final String BB = "BB"; @@ -34,31 +37,28 @@ final class RegionCode { static final String BS = "BS"; static final String BY = "BY"; static final String CA = "CA"; - static final String CH = "CH"; - static final String CL = "CL"; + static final String CC = "CC"; static final String CN = "CN"; static final String CO = "CO"; - static final String CS = "CS"; static final String CX = "CX"; static final String DE = "DE"; static final String FR = "FR"; static final String GB = "GB"; - static final String HU = "HU"; + static final String GG = "GG"; static final String IT = "IT"; static final String JP = "JP"; static final String KR = "KR"; static final String MX = "MX"; static final String NZ = "NZ"; - static final String PG = "PG"; static final String PL = "PL"; static final String RE = "RE"; static final String RU = "RU"; static final String SE = "SE"; static final String SG = "SG"; + static final String TA = "TA"; static final String US = "US"; static final String UZ = "UZ"; static final String YT = "YT"; - static final String ZW = "ZW"; // Official code for the unknown region. static final String ZZ = "ZZ"; } diff --git a/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java b/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java index b83a680cf8..b08f82e189 100644 --- a/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java +++ b/java/libphonenumber/test/com/google/i18n/phonenumbers/ShortNumberInfoTest.java @@ -241,14 +241,14 @@ public void testConnectsToEmergencyNumberLongNumber_BR() { } public void testConnectsToEmergencyNumber_CL() { - assertTrue(shortInfo.connectsToEmergencyNumber("131", RegionCode.CL)); - assertTrue(shortInfo.connectsToEmergencyNumber("133", RegionCode.CL)); + assertTrue(shortInfo.connectsToEmergencyNumber("131", "CL")); + assertTrue(shortInfo.connectsToEmergencyNumber("133", "CL")); } public void testConnectsToEmergencyNumberLongNumber_CL() { // Chilean emergency numbers don't work when additional digits are appended. - assertFalse(shortInfo.connectsToEmergencyNumber("1313", RegionCode.CL)); - assertFalse(shortInfo.connectsToEmergencyNumber("1330", RegionCode.CL)); + assertFalse(shortInfo.connectsToEmergencyNumber("1313", "CL")); + assertFalse(shortInfo.connectsToEmergencyNumber("1330", "CL")); } public void testConnectsToEmergencyNumber_AO() { @@ -260,9 +260,9 @@ public void testConnectsToEmergencyNumber_AO() { public void testConnectsToEmergencyNumber_ZW() { // Zimbabwe doesn't have any metadata in the test metadata. - assertFalse(shortInfo.connectsToEmergencyNumber("911", RegionCode.ZW)); - assertFalse(shortInfo.connectsToEmergencyNumber("01312345", RegionCode.ZW)); - assertFalse(shortInfo.connectsToEmergencyNumber("0711234567", RegionCode.ZW)); + assertFalse(shortInfo.connectsToEmergencyNumber("911", "ZW")); + assertFalse(shortInfo.connectsToEmergencyNumber("01312345", "ZW")); + assertFalse(shortInfo.connectsToEmergencyNumber("0711234567", "ZW")); } public void testIsEmergencyNumber_US() { @@ -315,9 +315,9 @@ public void testIsEmergencyNumber_AO() { public void testIsEmergencyNumber_ZW() { // Zimbabwe doesn't have any metadata in the test metadata. - assertFalse(shortInfo.isEmergencyNumber("911", RegionCode.ZW)); - assertFalse(shortInfo.isEmergencyNumber("01312345", RegionCode.ZW)); - assertFalse(shortInfo.isEmergencyNumber("0711234567", RegionCode.ZW)); + assertFalse(shortInfo.isEmergencyNumber("911", "ZW")); + assertFalse(shortInfo.isEmergencyNumber("01312345", "ZW")); + assertFalse(shortInfo.isEmergencyNumber("0711234567", "ZW")); } public void testEmergencyNumberForSharedCountryCallingCode() { diff --git a/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java b/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java index d38927390f..c6ce40b700 100644 --- a/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java +++ b/tools/java/common/src/com/google/i18n/phonenumbers/BuildMetadataFromXml.java @@ -162,6 +162,17 @@ public static Map> buildCountryCodeToRegionCodeMap( return countryCodeToRegionCodeMap; } + // Build a list of region codes from the metadata + public static List buildRegionCodeList( + PhoneMetadataCollection metadataCollection) { + List regionCodeList = new ArrayList(); + for (PhoneMetadata metadata : metadataCollection.getMetadataList()) { + String regionCode = metadata.getId(); + regionCodeList.add(regionCode); + } + return regionCodeList; + } + private static String validateRE(String regex) { return validateRE(regex, false); } diff --git a/tools/java/java-build/pom.xml b/tools/java/java-build/pom.xml index 120043dc1f..2548ac58c1 100644 --- a/tools/java/java-build/pom.xml +++ b/tools/java/java-build/pom.xml @@ -115,6 +115,31 @@ 4.13.2 test + + + com.google.auto.value + auto-value + 1.11.0 + provided + + + + com.google.auto.value + auto-value-annotations + 1.11.0 + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + com.google.guava + guava + 33.3.0-jre + diff --git a/tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java b/tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java index 2828271062..9041497c1f 100644 --- a/tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java +++ b/tools/java/java-build/src/com/google/i18n/phonenumbers/BuildMetadataProtoFromXml.java @@ -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; @@ -26,6 +28,7 @@ import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Writer; +import java.util.Collection; import java.util.Formatter; import java.util.List; import java.util.Map; @@ -34,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. @@ -56,6 +60,7 @@ public class BuildMetadataProtoFromXml extends Command { private static final String COPYRIGHT = "copyright"; private static final String SINGLE_FILE = "single-file"; private static final String LITE_BUILD = "lite-build"; + private static final String BUILD_REGIONCODE = "build-regioncode"; // Only supported for clients who have consulted with the libphonenumber team, and the behavior is // subject to change without notice. private static final String SPECIAL_BUILD = "special-build"; @@ -81,6 +86,8 @@ public class BuildMetadataProtoFromXml extends Command { " [--" + LITE_BUILD + "=] Optional (default: false). In a lite build,\n" + " certain metadata will be omitted. At this\n" + " moment, example numbers information is omitted.\n" + + " [--" + BUILD_REGIONCODE + "=] Optional (default: false). Generate\n" + + " RegionCode class with constants for all region codes.\n" + "\n" + "Example command line invocation:\n" + CLASS_NAME + " \\\n" + @@ -90,12 +97,32 @@ public class BuildMetadataProtoFromXml extends Command { " --" + MAPPING_CLASS + "=CountryCodeToRegionCodeMap \\\n" + " --" + COPYRIGHT + "=2010 \\\n" + " --" + SINGLE_FILE + "=false \\\n" + - " --" + LITE_BUILD + "=false\n"; + " --" + LITE_BUILD + "=false\n" + + " --" + BUILD_REGIONCODE + "=true\n"; private static final String GENERATION_COMMENT = "/* 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_JAVADOC = + "/**\n" + + " * Class containing string constants of region codes for easier testing.\n" + + " */\n"; @Override public String getCommandName() { @@ -115,6 +142,7 @@ public boolean start() { boolean singleFile = false; boolean liteBuild = false; boolean specialBuild = false; + boolean buildRegioncode = false; for (int i = 1; i < getArgs().length; i++) { String key = null; @@ -144,6 +172,9 @@ public boolean start() { } else if (SPECIAL_BUILD.equals(key) && ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value))) { specialBuild = "true".equalsIgnoreCase(value); + } else if (BUILD_REGIONCODE.equals(key) && + ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value))) { + buildRegioncode = "true".equalsIgnoreCase(value); } else { System.err.println(HELP_MESSAGE); System.err.println("Illegal command line parameter: " + getArgs()[i]); @@ -195,6 +226,16 @@ public boolean start() { writeCountryCallingCodeMappingToJavaFile( countryCodeToRegionCodeMap, outputDir, mappingClass, copyright); + + if (buildRegioncode) { + SortedSet regionCodeSet = new TreeSet(); + // Official code for the unknown region. + regionCodeSet.add("ZZ"); + regionCodeSet.addAll(BuildMetadataFromXml.buildRegionCodeList(metadataCollection)); + System.out.println("Found " + regionCodeSet.size() + " region codes"); + + writeRegionCodeConstantsToJavaFile(regionCodeSet, outputDir, copyright); + } } catch (Exception e) { e.printStackTrace(); return false; @@ -219,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> countryCodeToRegionCodeMap, String outputDir, String mappingClass, String copyright) throws IOException { @@ -247,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) { @@ -260,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> countryCodeToRegionCodeMap) { writer.addToBody(MAP_COMMENT); @@ -297,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 regionCodeList) { writer.addToBody(REGION_CODE_SET_COMMENT); @@ -318,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 countryCodeSet) { writer.addToBody(COUNTRY_CODE_SET_COMMENT); @@ -339,51 +370,103 @@ private static void writeCountryCodeSet(ClassWriter writer, int capacity, writer.addToBody(" }\n"); } - private static final class ClassWriter { - private final String name; - private final String copyright; + private static void writeRegionCodeConstantsToJavaFile(Collection regionCodeList, + String outputDir, String copyright) throws IOException { + ClassWriter.Builder writer = ClassWriter.builder() + .setOutputDir(outputDir) + .setName("RegionCode") + .setModifiers("final") + .setCopyright(Integer.parseInt(copyright)); - private final SortedSet imports; - private final StringBuffer body; - private final Formatter formatter; - private final Writer writer; + writer.setJavadoc(REGION_CODE_CONSTS_JAVADOC); + + for (String regionCode : regionCodeList) { + String variableName = regionCode.toUpperCase(); + if (variableName.equals("001")) { + writer.addToBody(" // Region code for global networks (e.g. +800 numbers).\n"); + variableName = "UN001"; + } else if (variableName.equals("ZZ")) { + writer.addToBody(" // Official code for the unknown region.\n"); + } + writer.addToBody(" static final String " + variableName + " = \"" + regionCode + "\";\n"); + } + + writer.build().writeToFile(); + } - ClassWriter(String outputDir, String name, String copyright) throws IOException { - this.name = name; - this.copyright = copyright; - imports = new TreeSet(); - body = new StringBuffer(); - formatter = new Formatter(body); - writer = new BufferedWriter(new FileWriter(new File(outputDir, name + ".java"))); + @AutoValue + abstract static class ClassWriter { + abstract String outputDir(); + + abstract Integer copyright(); + abstract ImmutableSortedSet 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 importsBuilder(); + final Builder addToImports(String name) { + importsBuilder().add(name); + return this; + } - void addToBody(CharSequence text) { - body.append(text); - } + abstract Builder setJavadoc(String javadoc); + 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() { + 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("public 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();