Add CLDR import code, and external projects for CLDR data/tools.
Patch by: jat
Review by: pdr, fabbott
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9037 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/build.xml b/dev/build.xml
index 00a5c2b..fd43dde 100755
--- a/dev/build.xml
+++ b/dev/build.xml
@@ -59,7 +59,7 @@
<include name="eclipse/jdt-3.4.2.jar" />
<include name="guava/guava-r06/guava-r06-rebased.jar" />
<include name="jetty/jetty-6.1.11.jar" />
- <include name="icu4j/icu4j-4_4_1.jar" />
+ <include name="icu4j/4.4.2/icu4j.jar" />
<include name="protobuf/protobuf-2.2.0/protobuf-java-rebased-2.2.0.jar" />
<include name="tomcat/ant-launcher-1.6.5.jar" />
<include name="tomcat/catalina-1.0.jar" />
@@ -122,7 +122,7 @@
<zipfileset src="${gwt.tools.lib}/eclipse/jdt-3.4.2.jar" />
<zipfileset src="${gwt.tools.lib}/guava/guava-r06/guava-r06-rebased.jar" />
<zipfileset src="${gwt.tools.lib}/jetty/jetty-6.1.11.jar" />
- <zipfileset src="${gwt.tools.lib}/icu4j/icu4j-4_4_1.jar" />
+ <zipfileset src="${gwt.tools.lib}/icu4j/4.4.2/icu4j.jar" />
<zipfileset src="${gwt.tools.lib}/protobuf/protobuf-2.2.0/protobuf-java-rebased-2.2.0.jar" />
<zipfileset src="${gwt.tools.lib}/streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-1.5-rebased.jar" />
<zipfileset src="${gwt.tools.lib}/tomcat/ant-launcher-1.6.5.jar" />
diff --git a/eclipse/README-CLDR.txt b/eclipse/README-CLDR.txt
new file mode 100644
index 0000000..1a99f3d
--- /dev/null
+++ b/eclipse/README-CLDR.txt
@@ -0,0 +1,16 @@
+Steps to process CLDR data using Eclipse:
+
+1) Get the CLDR data available locally on your system, such as by:
+ svn co http://unicode.org/repos/cldr/tags/release-1-8-1 <cldrdir>
+2) Set a linked resource variable pointing to this in Eclipse:
+ Window -> Preferences -> General -> Workspace -> Linked Resources
+ Add a variable CLDR_ROOT pointing to <cldrdir> above
+3) Import the cldr-data, cldr-tools, and cldr-import projects (note that
+ CLDR_ROOT must be defined as above, or you will have to delete and
+ reimport these projects).
+ File -> Import -> General -> Existing Projects in Workspace
+ Browse to $GWT_ROOT/eclipse and select the cldr-data, cldr-tools,
+ and cldr-import projects.
+4) Run the GenerateGwtCldrData launch config -- by default, it will
+ overwrite files in the GWT distribution; edit the --outdir argument
+ if you want it to go somewhere else.
diff --git a/eclipse/external/cldr-data/.project b/eclipse/external/cldr-data/.project
new file mode 100644
index 0000000..17e74af
--- /dev/null
+++ b/eclipse/external/cldr-data/.project
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>cldr-data</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ </buildSpec>
+ <natures>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>common</name>
+ <type>2</type>
+ <locationURI>CLDR_ROOT/common</locationURI>
+ </link>
+ </linkedResources>
+</projectDescription>
diff --git a/eclipse/external/cldr-tools/.classpath b/eclipse/external/cldr-tools/.classpath
new file mode 100644
index 0000000..19e47de
--- /dev/null
+++ b/eclipse/external/cldr-tools/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry excluding="org/unicode/cldr/web/|org/unicode/cldr/tool/templates/" kind="src" path="java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/xalan/xalan-2.7.1.jar"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/apache/ant-1.7.1.jar"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/icu4j/4.4.2/icu4j.jar"/ sourcepath="/GWT_TOOLS/lib/icu4j/4.4.2/icu4jsrc.jar"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/icu4j/4.4.2/utilities.jar" sourcepath="/GWT_TOOLS/lib/icu4j/4.4.2/icu4jsrc.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/eclipse/external/cldr-tools/.project b/eclipse/external/cldr-tools/.project
new file mode 100644
index 0000000..c7109f6
--- /dev/null
+++ b/eclipse/external/cldr-tools/.project
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>cldr-tools</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>java</name>
+ <type>2</type>
+ <locationURI>CLDR_ROOT/tools/java</locationURI>
+ </link>
+ </linkedResources>
+</projectDescription>
diff --git a/eclipse/external/cldr-tools/.settings/org.eclipse.core.resources.prefs b/eclipse/external/cldr-tools/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..7abc8fb
--- /dev/null
+++ b/eclipse/external/cldr-tools/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Feb 02 11:09:17 EST 2010
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/eclipse/external/cldr-tools/.settings/org.eclipse.jdt.core.prefs b/eclipse/external/cldr-tools/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ee81b53
--- /dev/null
+++ b/eclipse/external/cldr-tools/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,332 @@
+#Mon Oct 04 15:17:42 EDT 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=ignore
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=ignore
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=ignore
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=ignore
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=120
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=1
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=1
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=120
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/eclipse/external/cldr-tools/.settings/org.eclipse.jdt.ui.prefs b/eclipse/external/cldr-tools/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..29ae99b
--- /dev/null
+++ b/eclipse/external/cldr-tools/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,8 @@
+#Tue Feb 02 11:38:32 EST 2010
+eclipse.preferences.version=1
+formatter_profile=_cldr
+formatter_settings_version=11
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
diff --git a/eclipse/tools/cldr-import/.checkstyle b/eclipse/tools/cldr-import/.checkstyle
new file mode 100644
index 0000000..0f1cbd9
--- /dev/null
+++ b/eclipse/tools/cldr-import/.checkstyle
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fileset-config file-format-version="1.2.0" simple-config="true">
+ <fileset name="all" enabled="true" check-config-name="GWT Checks" local="false">
+ <file-match-pattern match-pattern="." include-pattern="true"/>
+ </fileset>
+ <filter name="NonSrcDirs" enabled="true"/>
+</fileset-config>
diff --git a/eclipse/tools/cldr-import/.classpath b/eclipse/tools/cldr-import/.classpath
new file mode 100644
index 0000000..a6f8e0c
--- /dev/null
+++ b/eclipse/tools/cldr-import/.classpath
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="core/src"/>
+ <classpathentry kind="src" path="core/test"/>
+ <classpathentry kind="src" path="generated"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+ <classpathentry combineaccessrules="false" exported="true" kind="src" path="/gwt-user"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/cldr-tools"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/gwt-dev"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/icu4j/4.4.2/utilities.jar" sourcepath="/GWT_TOOLS/lib/icu4j/4.4.2/icu4jsrc.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/eclipse/tools/cldr-import/.project b/eclipse/tools/cldr-import/.project
new file mode 100644
index 0000000..2c5d2ce
--- /dev/null
+++ b/eclipse/tools/cldr-import/.project
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>cldr-import</name>
+ <comment>CLDR import tools</comment>
+ <projects>
+ <project>cldr-data</project>
+ <project>cldr-tools</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.atlassw.tools.eclipse.checkstyle.CheckstyleBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>com.atlassw.tools.eclipse.checkstyle.CheckstyleNature</nature>
+ </natures>
+ <linkedResources>
+ <link>
+ <name>core</name>
+ <type>2</type>
+ <locationURI>GWT_ROOT/tools/cldr-import</locationURI>
+ </link>
+ <link>
+ <name>generated</name>
+ <type>2</type>
+ <location>/tmp/cldr-gen/user/src</location>
+ </link>
+ </linkedResources>
+</projectDescription>
diff --git a/eclipse/tools/cldr-import/GenerateGwtCldrData.launch b/eclipse/tools/cldr-import/GenerateGwtCldrData.launch
new file mode 100644
index 0000000..9c6d71c
--- /dev/null
+++ b/eclipse/tools/cldr-import/GenerateGwtCldrData.launch
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+<stringAttribute key="bad_container_name" value="/cldr-import/G"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/cldr-import/core/src/com/google/gwt/tools/cldr/GenerateGwtCldrData.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.tools.cldr.GenerateGwtCldrData"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="--sourcedir ${resource_loc:cldr-data/common}/main --outdir ${resource_loc:gwt-user/core}/.."/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="cldr-import"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx1024m"/>
+</launchConfiguration>
diff --git a/eclipse/user/.classpath b/eclipse/user/.classpath
index 5075ee1..39d4509 100644
--- a/eclipse/user/.classpath
+++ b/eclipse/user/.classpath
@@ -19,7 +19,6 @@
<classpathentry kind="var" path="GWT_TOOLS/lib/tomcat/commons-logging-1.0.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/apache/commons/commons-io-1.4.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/cssparser/cssparser-0.9.5.jar"/>
- <classpathentry kind="var" path="GWT_TOOLS/lib/icu4j/icu4j-4_4_1.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/nekohtml/nekohtml-1.9.13.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/selenium/selenium-java-client-driver.jar" sourcepath="/GWT_TOOLS/lib/selenium/selenium-java-client-driver-sources.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/xalan/xalan-2.7.1.jar"/>
@@ -46,5 +45,6 @@
<classpathentry kind="var" path="GWT_TOOLS/lib/slf4j/slf4j-log4j12/slf4j-log4j12-1.6.1.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/guava/guava-r06/guava-r06-rebased.jar"/>
<classpathentry kind="var" path="GWT_TOOLS/lib/streamhtmlparser/streamhtmlparser-jsilver-r10/streamhtmlparser-jsilver-r10-1.5-rebased.jar"/>
+ <classpathentry kind="var" path="GWT_TOOLS/lib/icu4j/4.4.2/icu4j.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/build.xml b/tools/build.xml
index 104f13b..cc6c10a 100755
--- a/tools/build.xml
+++ b/tools/build.xml
@@ -5,20 +5,27 @@
<!-- "build" is the default when subprojects are directly targeted -->
<property name="target" value="build" />
-
- <target name="benchmark-viewer" depends="" description="Run benchmark-viewer">
+
+ <target name="benchmark-viewer" depends=""
+ description="Run benchmark-viewer">
<gwt.ant dir="benchmark-viewer" />
</target>
- <target name="api-checker" depends="" description="Compile api-checker">
+ <target name="api-checker" depends=""
+ description="Compile api-checker">
<gwt.ant dir="api-checker" />
</target>
<target name="soyc-vis" depends="" description="Compile SOYC dashboard">
<gwt.ant dir="soyc-vis" />
</target>
-
- <target name="-do" depends="benchmark-viewer,api-checker,soyc-vis" description="Run all subfolders" />
+
+ <target name="cldr-import" depends="" description="Compile CLDR import">
+ <gwt.ant dir="cldr-import" />
+ </target>
+
+ <target name="-do" depends="benchmark-viewer,api-checker,soyc-vis,cldr-import"
+ description="Run all subfolders that don't have additional dependencies" />
<target name="build" description="Build each subfolder">
<antcall target="-do">
@@ -26,7 +33,8 @@
</antcall>
</target>
- <target name="checkstyle" description="Static analysis of source for each subfolder">
+ <target name="checkstyle"
+ description="Static analysis of source for each subfolder">
<antcall target="-do">
<param name="target" value="checkstyle" />
</antcall>
diff --git a/tools/cldr-import/build.xml b/tools/cldr-import/build.xml
new file mode 100644
index 0000000..24aa636
--- /dev/null
+++ b/tools/cldr-import/build.xml
@@ -0,0 +1,138 @@
+<project name="cldr-import" default="build" basedir=".">
+
+ <property name="gwt.root" location="../.." />
+ <property name="project.tail" value="tools/cldr-import" />
+ <import file="${gwt.root}/common.ant.xml" />
+
+ <property.ensure name="gwt.dev.jar" location="${gwt.build.lib}/gwt-dev.jar" />
+ <property.ensure name="gwt.user.jar" location="${gwt.build.lib}/gwt-user.jar" />
+ <property.ensure name="gwt.servlet.jar" location="${gwt.build.lib}/gwt-servlet.jar" />
+
+ <property name="ICU" location="${gwt.tools}/lib/icu4j/4.4.2" />
+ <property name="CLDR_TOOLS" location="${gwt.tools}/lib/cldr/1.8.1" />
+
+ <property.ensure name="ICU_CORE_PATH" location="${ICU}/icu4j.jar" />
+
+ <condition property="cldr.root.check" value="${env.CLDR_ROOT}"
+ else="${gwt.root}/../CLDR">
+ <isset property="env.CLDR_ROOT" />
+ </condition>
+ <property name="cldr.root" location="${cldr.root.check}" />
+
+ <condition property="tmpdir" value="${env.CLDR_TEMP}"
+ else="/tmp/cldr-import">
+ <isset property="env.CLDR_TEMP" />
+ </condition>
+
+ <path id="project.class.path">
+ <pathelement location="${gwt.user.jar}"/>
+ <pathelement location="${gwt.dev.jar}"/>
+ <pathelement location="${CLDR_TOOLS}/cldr.jar"/>
+ <pathelement location="${ICU}/icu4j.jar"/>
+ <pathelement location="${ICU}/utilities.jar"/>
+ </path>
+
+ <target name="compile" description="Compile java source">
+ <mkdir dir="${javac.out}" />
+ <javac srcdir="src" destdir="${javac.out}"
+ debug="${javac.debug}" debuglevel="${javac.debuglevel}"
+ source="${javac.source}" target="${javac.target}"
+ nowarn="${javac.nowarn}" encoding="${javac.encoding}">
+ <classpath refid="project.class.path"/>
+ </javac>
+ <copy todir="${javac.out}">
+ <fileset dir="src" excludes="**/*.java"/>
+ </copy>
+ </target>
+
+ <target name="compile.tests" description="Compile java source">
+ <mkdir dir="${javac.junit.out}" />
+ <javac srcdir="test" destdir="${javac.junit.out}"
+ debug="${javac.debug}" debuglevel="${javac.debuglevel}"
+ source="${javac.source}" target="${javac.target}"
+ nowarn="${javac.nowarn}" encoding="${javac.encoding}">
+ <classpath>
+ <pathelement location="${gwt.dev.jar}" />
+ <pathelement location="${gwt.user.jar}" />
+ <pathelement location="${gwt.tools.lib}/junit/junit-3.8.1.jar" />
+ <pathelement location="${javac.out}"/>
+ <pathelement location="${CLDR_TOOLS}/cldr.jar"/>
+ <pathelement location="${ICU}/icu4j.jar"/>
+ <pathelement location="${ICU}/utilities.jar"/>
+ </classpath>
+ </javac>
+ <copy todir="${javac.junit.out}">
+ <fileset dir="src" excludes="**/*.java"/>
+ </copy>
+ </target>
+
+ <target name="build" depends="compile" description="Build this project" />
+
+ <target name="clean" description="Cleans this project">
+ <delete dir="${javac.out}" failonerror="false" />
+ <delete dir="${javac.junit.out}" failonerror="false" />
+ </target>
+
+ <target name="checkstyle" description="Static analysis of source">
+ <gwt.checkstyle>
+ <fileset dir="src"/>
+ </gwt.checkstyle>
+ </target>
+
+ <target name="test" depends="build, compile.tests" description="Run tests">
+ <mkdir dir="${junit.out}/tools-cldr-import" />
+ <fileset id="tests" dir="${javac.junit.out}"
+ includes="**/*Test.class" />
+ <gwt.junit test.name="test"
+ test.args=""
+ test.jvmargs="-ea"
+ test.out="${junit.out}/tools-cldr-import"
+ test.cases="tests">
+ <extraclasspaths>
+ <pathelement location="${gwt.dev.jar}" />
+ <pathelement location="${gwt.user.jar}" />
+ <pathelement location="${CLDR_TOOLS}/cldr.jar"/>
+ <pathelement location="${ICU}/icu4j.jar"/>
+ <pathelement location="${ICU}/utilities.jar"/>
+ </extraclasspaths>
+ </gwt.junit>
+ </target>
+
+ <target name="cldrdata" description="Verifies CLDR data is present">
+ <property.ensure name="cldr.data" location="${cldr.root}/common/main"
+ message="common/main missing under ${cldr.root} (set using CLDR_ROOT)" />
+ </target>
+
+ <target name="gen.temp" depends="build, cldrdata"
+ description="Generate GWT classes/property files in a temporary directory">
+ <mkdir dir="${tmpdir}"/>
+ <java classname="com.google.gwt.tools.cldr.GenerateGwtCldrData"
+ fork="true" maxmemory="2048m" failonerror="true">
+ <arg line="--sourcedir ${cldr.data} --outdir ${tmpdir}"/>
+ <classpath>
+ <pathelement location="${javac.out}"/>
+ <pathelement location="${gwt.user.jar}"/>
+ <pathelement location="${gwt.dev.jar}"/>
+ <pathelement location="${ICU}/icu4j.jar"/>
+ <pathelement location="${ICU}/utilities.jar"/>
+ <pathelement location="${CLDR_TOOLS}/cldr.jar"/>
+ </classpath>
+ </java>
+ </target>
+
+ <target name="gen" depends="build, cldrdata"
+ description="Generate GWT classes/property files">
+ <java classname="com.google.gwt.tools.cldr.GenerateGwtCldrData"
+ fork="true" maxmemory="2048m" failonerror="true">
+ <arg line="--sourcedir ${cldr.data} --outdir ${gwt.root}"/>
+ <classpath>
+ <pathelement location="${javac.out}"/>
+ <pathelement location="${gwt.user.jar}"/>
+ <pathelement location="${gwt.dev.jar}"/>
+ <pathelement location="${ICU}/icu4j.jar"/>
+ <pathelement location="${ICU}/utilities.jar"/>
+ <pathelement location="${CLDR_TOOLS}/cldr.jar"/>
+ </classpath>
+ </java>
+ </target>
+</project>
diff --git a/tools/cldr-import/src/com/google/gwt/tools/cldr/CurrencyDataProcessor.java b/tools/cldr-import/src/com/google/gwt/tools/cldr/CurrencyDataProcessor.java
new file mode 100644
index 0000000..92fb6af
--- /dev/null
+++ b/tools/cldr-import/src/com/google/gwt/tools/cldr/CurrencyDataProcessor.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.tools.cldr;
+
+import com.google.gwt.i18n.shared.GwtLocale;
+
+import org.unicode.cldr.util.CLDRFile;
+import org.unicode.cldr.util.XPathParts;
+import org.unicode.cldr.util.CLDRFile.DraftStatus;
+import org.unicode.cldr.util.CLDRFile.Factory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Loads data needed to produce DateTimeFormatInfo implementations.
+ */
+public class CurrencyDataProcessor extends Processor {
+
+ private Map<String, Integer> currencyFractions = new HashMap<String, Integer>();
+ private int defaultCurrencyFraction;
+
+ private Set<String> stillInUse = new HashSet<String>();
+
+ public CurrencyDataProcessor(File outputDir, Factory cldrFactory,
+ LocaleData localeData) {
+ super(outputDir, cldrFactory, localeData);
+ }
+
+ @Override
+ protected void cleanupData() {
+ localeData.removeDuplicates("currency");
+ }
+
+ @Override
+ protected void loadData() throws IOException {
+ System.out.println("Loading data for currencies");
+ loadLocaleIndependentCurrencyData();
+ localeData.addCurrencyEntries("currency", cldrFactory, currencyFractions,
+ defaultCurrencyFraction, stillInUse);
+ }
+
+ @Override
+ protected void writeOutputFiles() throws IOException {
+ for (GwtLocale locale : localeData.getNonEmptyLocales()) {
+ String path = "client/impl/cldr/CurrencyData";
+ PrintWriter pw = createOutputFile(path + Processor.localeSuffix(locale)
+ + ".properties");
+ printHeader(pw);
+ Map<String, String> map = localeData.getEntries("currency", locale);
+ String[] keys = new String[map.size()];
+ map.keySet().toArray(keys);
+ Arrays.sort(keys);
+
+ for (String key : keys) {
+ pw.print(key);
+ pw.print(" = ");
+ pw.println(map.get(key));
+ }
+ pw.close();
+ }
+ }
+
+ private void loadLocaleIndependentCurrencyData() {
+ CLDRFile supp = cldrFactory.make("supplementalData", true,
+ DraftStatus.approved);
+
+ // load the table of default # of decimal places for each currency
+ currencyFractions = new HashMap<String, Integer>();
+ defaultCurrencyFraction = 0;
+ XPathParts parts = new XPathParts();
+ Iterator<String> iterator = supp.iterator(
+ "//supplementalData/currencyData/fractions/info");
+ while (iterator.hasNext()) {
+ String path = iterator.next();
+ parts.set(supp.getFullXPath(path));
+ Map<String, String> attr = parts.findAttributes("info");
+ if (attr == null) {
+ continue;
+ }
+ String curCode = attr.get("iso4217");
+ int digits = Integer.valueOf(attr.get("digits"));
+ // TODO(jat): make use of the "rounding" attribute, currently only on CHF
+ if ("DEFAULT".equalsIgnoreCase(curCode)) {
+ defaultCurrencyFraction = digits;
+ } else {
+ currencyFractions.put(curCode, digits);
+ }
+ }
+
+ // find which currencies are still in use in some region, everything else
+ // should be marked as deprecated
+ iterator = supp.iterator(
+ "//supplementalData/currencyData/region");
+ while (iterator.hasNext()) {
+ String path = iterator.next();
+ parts.set(supp.getFullXPath(path));
+ Map<String, String> attr = parts.findAttributes("currency");
+ if (attr == null) {
+ continue;
+ }
+ String region = parts.findAttributeValue("region", "iso3166");
+ String curCode = attr.get("iso4217");
+ if ("ZZ".equals(region) || "false".equals(attr.get("tender"))
+ || "XXX".equals(curCode)) {
+ // ZZ is an undefined region, XXX is an unknown currency code (and needs
+ // to be special-cased because it is listed as used in Anartica!)
+ continue;
+ }
+ String to = attr.get("to");
+ if (to == null) {
+ stillInUse.add(curCode);
+ }
+ }
+ }
+
+ private void printHeader(PrintWriter pw) {
+ pw.println("# Do not edit - generated from Unicode CLDR data");
+ pw.println("#");
+ pw.println("# The key is an ISO4217 currency code, and the value is of the "
+ + "form:");
+ pw.println("# display name|symbol|decimal digits|not-used-flag");
+ pw.println("# If a symbol is not supplied, the currency code will be used");
+ pw.println("# If # of decimal digits is omitted, 2 is used");
+ pw.println("# If a currency is not generally used, not-used-flag=1");
+ pw.println("# Trailing empty fields can be omitted");
+ pw.println();
+ }
+}
diff --git a/tools/cldr-import/src/com/google/gwt/tools/cldr/DateTimeFormatInfoProcessor.java b/tools/cldr-import/src/com/google/gwt/tools/cldr/DateTimeFormatInfoProcessor.java
new file mode 100644
index 0000000..42edc54
--- /dev/null
+++ b/tools/cldr-import/src/com/google/gwt/tools/cldr/DateTimeFormatInfoProcessor.java
@@ -0,0 +1,656 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.tools.cldr;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.i18n.client.DateTimeFormatInfo;
+import com.google.gwt.i18n.client.impl.cldr.DateTimeFormatInfoImpl;
+import com.google.gwt.i18n.rebind.DateTimePatternGenerator;
+import com.google.gwt.i18n.rebind.MessageFormatParser;
+import com.google.gwt.i18n.rebind.StringGenerator;
+import com.google.gwt.i18n.rebind.MessageFormatParser.ArgumentChunk;
+import com.google.gwt.i18n.rebind.MessageFormatParser.DefaultTemplateChunkVisitor;
+import com.google.gwt.i18n.rebind.MessageFormatParser.StringChunk;
+import com.google.gwt.i18n.rebind.MessageFormatParser.TemplateChunk;
+import com.google.gwt.i18n.shared.GwtLocale;
+
+import org.unicode.cldr.util.CLDRFile.Factory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.ParseException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * Loads data needed to produce DateTimeFormatInfo implementations.
+ */
+public class DateTimeFormatInfoProcessor extends Processor {
+
+ private static final String[] DAYS = new String[] {
+ "sun", "mon", "tue", "wed", "thu", "fri", "sat"
+ };
+
+ /**
+ * Map of skeleton format patterns and the method name suffix that uses them.
+ */
+ private static final Map<String, String> FORMATS;
+
+
+ /**
+ * Index of the formats, ordered by the method name.
+ */
+ private static final SortedMap<String, String> FORMAT_BY_METHOD;
+
+ static {
+ FORMATS = new HashMap<String, String>();
+ FORMATS.put("d", "Day");
+ FORMATS.put("hmm", "Hour12Minute");
+ FORMATS.put("hmmss", "Hour12MinuteSecond");
+ FORMATS.put("Hmm", "Hour24Minute");
+ FORMATS.put("Hmmss", "Hour24MinuteSecond");
+ FORMATS.put("mss", "MinuteSecond");
+ FORMATS.put("MMM", "MonthAbbrev");
+ FORMATS.put("MMMd", "MonthAbbrevDay");
+ FORMATS.put("MMMM", "MonthFull");
+ FORMATS.put("MMMMd", "MonthFullDay");
+ FORMATS.put("MMMMEEEEd", "MonthFullWeekdayDay");
+ FORMATS.put("Md", "MonthNumDay");
+ FORMATS.put("y", "Year");
+ FORMATS.put("yMMM", "YearMonthAbbrev");
+ FORMATS.put("yMMMd", "YearMonthAbbrevDay");
+ FORMATS.put("yMMMM", "YearMonthFull");
+ FORMATS.put("yMMMMd", "YearMonthFullDay");
+ FORMATS.put("yM", "YearMonthNum");
+ FORMATS.put("yMd", "YearMonthNumDay");
+ FORMATS.put("yMMMEEEd", "YearMonthWeekdayDay");
+ FORMATS.put("yQQQQ", "YearQuarterFull");
+ FORMATS.put("yQ", "YearQuarterShort");
+
+ FORMAT_BY_METHOD = new TreeMap<String, String>();
+ for (Map.Entry<String, String> entry : FORMATS.entrySet()) {
+ FORMAT_BY_METHOD.put(entry.getValue(), entry.getKey());
+ }
+ }
+
+ /**
+ * Convert the unlocalized name of a day ("sun".."sat") into a day number of
+ * the week, ie 0-6.
+ *
+ * @param day abbreviated, unlocalized name of the day ("sun".."sat")
+ * @return the day number, 0-6
+ * @throws IllegalArgumentException if the day name is not found
+ */
+ private static int getDayNumber(String day) {
+ for (int i = 0; i < DAYS.length; ++i) {
+ if (DAYS[i].equals(day)) {
+ return i;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+
+ private final RegionLanguageData regionLanguageData;
+
+ public DateTimeFormatInfoProcessor(File outputDir, Factory cldrFactory,
+ LocaleData localeData) {
+ super(outputDir, cldrFactory, localeData);
+ regionLanguageData = new RegionLanguageData(cldrFactory);
+ }
+
+ @Override
+ protected void cleanupData() {
+ System.out.println("Removing duplicates from date/time formats");
+ localeData.copyLocaleData("en", "default", "era-wide", "era-abbrev",
+ "quarter-wide", "quarter-abbrev", "day-wide", "day-sa-wide",
+ "day-narrow", "day-sa-narrow", "day-abbrev", "day-sa-abbrev",
+ "month-wide", "month-sa-wide", "month-narrow", "month-sa-narrow",
+ "month-abbrev", "month-sa-abbrev");
+ removeUnusedFormats();
+ localeData.removeDuplicates("predef");
+ localeData.removeDuplicates("weekdata");
+ localeData.removeDuplicates("date");
+ localeData.removeDuplicates("time");
+ localeData.removeDuplicates("dateTime");
+ localeData.removeCompleteDuplicates("dayPeriod-abbrev");
+ computePeriodRedirects("day");
+ computePeriodRedirects("month");
+ computePeriodRedirects("day");
+ removePeriodDuplicates("day");
+ removePeriodDuplicates("month");
+ removePeriodDuplicates("quarter");
+ removePeriodDuplicates("era");
+ }
+
+ /**
+ * Generate an override for a method which takes String arguments, which
+ * simply redirect to another method based on a default value.
+ *
+ * @param pw
+ * @param category
+ * @param locale
+ * @param method
+ * @param args
+ */
+ protected void generateArgMethod(PrintWriter pw, String category,
+ GwtLocale locale, String method, String... args) {
+ String value = localeData.getEntry(category, locale, "default");
+ if (value != null && value.length() > 0) {
+ pw.println();
+ if (getOverrides()) {
+ pw.println(" @Override");
+ }
+ pw.print(" public String " + method + "(");
+ String prefix = "";
+ for (String arg : args) {
+ pw.print(prefix + "String " + arg);
+ prefix = ", ";
+ }
+ pw.println(") {");
+ pw.print(" return " + method + Character.toTitleCase(value.charAt(0))
+ + value.substring(1) + "(");
+ prefix = "";
+ for (String arg : args) {
+ pw.print(prefix + arg);
+ prefix = ", ";
+ }
+ pw.println(");");
+ pw.println(" }");
+ }
+ }
+
+ /**
+ * Generate an override for a method which takes String arguments.
+ *
+ * @param pw
+ * @param category
+ * @param locale
+ * @param key
+ * @param method
+ * @param args
+ */
+ protected void generateArgMethodRedirect(PrintWriter pw, String category,
+ GwtLocale locale, String key, String method, final String... args) {
+ String value = localeData.getEntry(category, locale, key);
+ if (value != null) {
+ pw.println();
+ if (getOverrides()) {
+ pw.println(" @Override");
+ }
+ pw.print(" public String " + method + "(");
+ String prefix = "";
+ for (String arg : args) {
+ pw.print(prefix + "String " + arg);
+ prefix = ", ";
+ }
+ pw.println(") {");
+ final StringBuffer buf = new StringBuffer();
+ final StringGenerator gen = new StringGenerator(buf, false);
+ try {
+ List<TemplateChunk> chunks = MessageFormatParser.parse(value);
+ for (TemplateChunk chunk : chunks) {
+ chunk.accept(new DefaultTemplateChunkVisitor() {
+ @Override
+ public void visit(ArgumentChunk argChunk)
+ throws UnableToCompleteException {
+ gen.appendStringValuedExpression(args[argChunk.getArgumentNumber()]);
+ }
+
+ @Override
+ public void visit(StringChunk stringChunk)
+ throws UnableToCompleteException {
+ gen.appendStringLiteral(stringChunk.getString());
+ }
+ });
+ }
+ } catch (ParseException e) {
+ throw new RuntimeException("Unable to parse pattern '" + value
+ + "' for locale " + locale + " key " + category + "/" + key, e);
+ } catch (UnableToCompleteException e) {
+ throw new RuntimeException("Unable to parse pattern '" + value
+ + "' for locale " + locale + " key " + category + "/" + key, e);
+ }
+ gen.completeString();
+ pw.println(" return " + buf.toString() + ";");
+ pw.println(" }");
+ }
+ }
+
+ /**
+ * Generate a method which returns a day number as an integer.
+ *
+ * @param pw
+ * @param locale
+ * @param key
+ * @param method
+ */
+ protected void generateDayNumber(PrintWriter pw, GwtLocale locale,
+ String key, String method) {
+ String day = localeData.getEntry("weekdata", locale, key);
+ if (day != null) {
+ int value = getDayNumber(day);
+ pw.println();
+ if (getOverrides()) {
+ pw.println(" @Override");
+ }
+ pw.println(" public int " + method + "() {");
+ pw.println(" return " + value + ";");
+ pw.println(" }");
+ }
+ }
+
+ /**
+ * Generate a method which returns a format string for a given predefined
+ * skeleton pattern.
+ *
+ * @param locale
+ * @param pw
+ * @param skeleton
+ * @param methodSuffix
+ */
+ protected void generateFormat(GwtLocale locale, PrintWriter pw,
+ String skeleton, String methodSuffix) {
+ String pattern = localeData.getEntry("predef", locale, skeleton);
+ generateStringValue(pw, "format" + methodSuffix, pattern);
+ }
+
+ /**
+ * Generate a series of methods which returns names in wide, narrow, and
+ * abbreviated lengths plus their standalone versions.
+ *
+ * @param pw
+ * @param group
+ * @param locale
+ * @param methodPrefix
+ * @param keys
+ */
+ protected void generateFullStringList(PrintWriter pw, String group,
+ GwtLocale locale, String methodPrefix, String... keys) {
+ generateStringListPair(pw, group, locale, methodPrefix, "Full", "wide",
+ keys);
+ generateStringListPair(pw, group, locale, methodPrefix, "Narrow", "narrow",
+ keys);
+ generateStringListPair(pw, group, locale, methodPrefix, "Short", "abbrev",
+ keys);
+ }
+
+ /**
+ * Generate an override of a standalone names list that simply redirects to
+ * the non-standalone version.
+ *
+ * @param pw
+ * @param methodPrefix
+ */
+ protected void generateStandaloneRedirect(PrintWriter pw,
+ String methodPrefix) {
+ pw.println();
+ if (getOverrides()) {
+ pw.println(" @Override");
+ }
+ pw.println(" public String[] " + methodPrefix
+ + "Standalone" + "() {");
+ pw.println(" return " + methodPrefix + "();");
+ pw.println(" }");
+ }
+
+ /**
+ * Generate a method which returns a list of strings.
+ *
+ * @param pw
+ * @param category
+ * @param fallbackCategory
+ * @param locale
+ * @param method
+ * @param keys
+ * @return true if the method was skipped as identical to its ancestor
+ */
+ protected boolean generateStringList(PrintWriter pw, String category,
+ String fallbackCategory, GwtLocale locale, String method,
+ String... keys) {
+ Map<String, String> map = localeData.getEntries(category, locale);
+ Map<String, String> fallback = fallbackCategory == null ?
+ Collections.<String, String>emptyMap()
+ : localeData.getEntries(fallbackCategory, locale);
+ if (map == null || map.isEmpty() && fallback != null
+ && !fallback.isEmpty()) {
+ return true;
+ }
+ if (map != null && !map.isEmpty()) {
+ if (fallbackCategory != null) {
+ // see if the entry is the same as the fallback
+ boolean different = false;
+ for (String key : keys) {
+ String value = map.get(key);
+ if (value != null && !value.equals(fallback.get(key))) {
+ different = true;
+ break;
+ }
+ }
+ if (!different) {
+ return true;
+ }
+ }
+ pw.println();
+ if (getOverrides()) {
+ pw.println(" @Override");
+ }
+ pw.println(" public String[] " + method + "() {");
+ pw.print(" return new String[] {");
+ boolean first = true;
+ for (String key : keys) {
+ String value = map.get(key);
+ if (value == null) {
+ value = fallback.get(key);
+ }
+ if (value == null) {
+ System.err.println("Missing \"" + key + "\" in " + locale + "/"
+ + category);
+ value = "";
+ }
+ if (first) {
+ first = false;
+ } else {
+ pw.print(",");
+ }
+ pw.print("\n \"" + value.replace("\"", "\\\"") + "\"");
+ }
+ pw.println("\n };");
+ pw.println(" }");
+ }
+ return false;
+ }
+
+ protected void generateStringListPair(PrintWriter pw, String group,
+ GwtLocale locale, String methodPrefix, String width, String categorySuffix,
+ String... keys) {
+ generateStringList(pw, group + "-" + categorySuffix, null, locale,
+ methodPrefix + width, keys);
+ String redirect = localeData.getEntry(group + "-sa-" + categorySuffix
+ + "-redirect", locale, "redirect");
+ if ("yes".equals(redirect)) {
+ generateStandaloneRedirect(pw, methodPrefix + width);
+ } else {
+ generateStringList(pw, group + "-sa-" + categorySuffix, group + "-"
+ + categorySuffix, locale, methodPrefix + width + "Standalone", keys);
+ }
+ }
+
+ @Override
+ protected void loadData() throws IOException {
+ System.out.println("Loading data for date/time formats");
+ localeData.addEntries("predef", cldrFactory,
+ "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/"
+ + "availableFormats", "dateFormatItem", "id");
+ localeData.addNameEntries("month", cldrFactory);
+ localeData.addNameEntries("day", cldrFactory);
+ localeData.addNameEntries("quarter", cldrFactory);
+
+ // only add the entries we will use to avoid overriding a parent for
+ // differences that don't matter.
+ localeData.addEntries("dayPeriod-abbrev", cldrFactory,
+ "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/"
+ + "dayPeriodContext[@type=\"format\"]/"
+ + "dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"am\"]",
+ "dayPeriod", "type");
+ localeData.addEntries("dayPeriod-abbrev", cldrFactory,
+ "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dayPeriods/"
+ + "dayPeriodContext[@type=\"format\"]/"
+ + "dayPeriodWidth[@type=\"abbreviated\"]/dayPeriod[@type=\"pm\"]",
+ "dayPeriod", "type");
+
+ localeData.addEntries("era-abbrev", cldrFactory,
+ "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/eras/eraAbbr",
+ "era", "type");
+ localeData.addEntries("era-wide", cldrFactory,
+ "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/eras/eraNames",
+ "era", "type");
+ localeData.addDateTimeFormatEntries("date", cldrFactory);
+ localeData.addDateTimeFormatEntries("time", cldrFactory);
+ localeData.addDateTimeFormatEntries("dateTime", cldrFactory);
+ loadWeekData();
+ loadFormatPatterns();
+ }
+
+ @Override
+ protected void writeOutputFiles() throws IOException {
+ // TODO(jat): make uz_UZ inherit from uz_Cyrl rather than uz, for example
+ System.out.println("Writing output for date/time formats");
+ for (GwtLocale locale : localeData.getNonEmptyLocales()) {
+ String myClass;
+ String path = "client/";
+ String pathSuffix = "";
+ if (locale.isDefault()) {
+ myClass = "DefaultDateTimeFormatInfo";
+ } else {
+ myClass = "DateTimeFormatInfoImpl" + localeSuffix(locale);
+ pathSuffix = "impl/cldr/";
+ }
+ GwtLocale parent = localeData.inheritsFrom(locale);
+ PrintWriter pw = createOutputFile(path + pathSuffix + myClass + ".java");
+ printHeader(pw);
+ pw.print("package com.google.gwt.i18n.client");
+ if (!locale.isDefault()) {
+ pw.print(".impl.cldr");
+ setOverrides(true);
+ } else {
+ setOverrides(false);
+ }
+ pw.println(";");
+ pw.println();
+ pw.println("// DO NOT EDIT - GENERATED FROM CLDR AND ICU DATA");
+ pw.println();
+ if (locale.isDefault()) {
+ pw.println("/**");
+ pw.println(" * Default implementation of DateTimeFormatInfo interface, "
+ + "using values from");
+ pw.println(" * the CLDR root locale.");
+ pw.println(" * <p>");
+ pw.println(" * Users who need to create their own DateTimeFormatInfo "
+ + "implementation are");
+ pw.println(" * encouraged to extend this class so their implementation "
+ + "won't break when ");
+ pw.println(" * new methods are added.");
+ pw.println(" */");
+ } else {
+ pw.println("/**");
+ pw.println(" * Implementation of DateTimeFormatInfo for the \""
+ + locale + "\" locale.");
+ pw.println(" */");
+ }
+ pw.print("public class " + myClass);
+ if (locale.isDefault()) {
+ pw.print(" implements " + DateTimeFormatInfo.class.getSimpleName());
+ } else {
+ pw.print(" extends ");
+ pw.print(DateTimeFormatInfoImpl.class.getSimpleName());
+ if (!parent.isDefault()) {
+ pw.print('_');
+ pw.print(parent.getAsString());
+ }
+ }
+ pw.println(" {");
+
+ // write AM/PM names
+ generateStringList(pw, "dayPeriod-abbrev", null, locale, "ampms", "am",
+ "pm");
+
+ // write standard date formats
+ generateArgMethod(pw, "date", locale, "dateFormat");
+ generateStringMethod(pw, "date", locale, "full", "dateFormatFull");
+ generateStringMethod(pw, "date", locale, "long", "dateFormatLong");
+ generateStringMethod(pw, "date", locale, "medium", "dateFormatMedium");
+ generateStringMethod(pw, "date", locale, "short", "dateFormatShort");
+
+ // write methods for assembling date/time formats
+ generateArgMethod(pw, "dateTime", locale, "dateTime", "timePattern",
+ "datePattern");
+ generateArgMethodRedirect(pw, "dateTime", locale, "full", "dateTimeFull",
+ "timePattern", "datePattern");
+ generateArgMethodRedirect(pw, "dateTime", locale, "long", "dateTimeLong",
+ "timePattern", "datePattern");
+ generateArgMethodRedirect(pw, "dateTime", locale, "medium",
+ "dateTimeMedium", "timePattern", "datePattern");
+ generateArgMethodRedirect(pw, "dateTime", locale, "short",
+ "dateTimeShort", "timePattern", "datePattern");
+
+ // write era names
+ generateStringList(pw, "era-wide", null, locale, "erasFull", "0", "1");
+ generateStringList(pw, "era-abbrev", null, locale, "erasShort", "0", "1");
+
+ // write firstDayOfTheWeek
+ generateDayNumber(pw, locale, "firstDay", "firstDayOfTheWeek");
+
+ // write predefined date/time formats
+ for (Map.Entry<String, String> entry : FORMAT_BY_METHOD.entrySet()) {
+ generateFormat(locale, pw, entry.getValue(), entry.getKey());
+ }
+
+ // write month names
+ generateFullStringList(pw, "month", locale, "months", "1", "2", "3", "4",
+ "5", "6", "7", "8", "9", "10", "11", "12");
+
+ // write quarter names
+ generateStringList(pw, "quarter-wide", null, locale, "quartersFull", "1",
+ "2", "3", "4");
+ generateStringList(pw, "quarter-abbrev", null, locale, "quartersShort",
+ "1", "2", "3", "4");
+
+ // write standard time formats
+ generateArgMethod(pw, "time", locale, "timeFormat");
+ generateStringMethod(pw, "time", locale, "full", "timeFormatFull");
+ generateStringMethod(pw, "time", locale, "long", "timeFormatLong");
+ generateStringMethod(pw, "time", locale, "medium",
+ "timeFormatMedium");
+ generateStringMethod(pw, "time", locale, "short",
+ "timeFormatShort");
+
+ // write weekday names
+ generateFullStringList(pw, "day", locale, "weekdays", DAYS);
+
+ // write weekend boundaries
+ generateDayNumber(pw, locale, "weekendEnd", "weekendEnd");
+ generateDayNumber(pw, locale, "weekendStart", "weekendStart");
+
+ pw.println("}");
+ pw.close();
+ }
+ }
+
+ /**
+ * @param period
+ */
+ private void computePeriodRedirects(String period) {
+ localeData.computeRedirects(period + "-abbrev", period + "-sa-abbrev");
+ localeData.computeRedirects(period + "-narrow", period + "-sa-narrow");
+ localeData.computeRedirects(period + "-wide", period + "-sa-wide");
+ }
+
+ private void loadFormatPatterns() {
+ localeData.addEntries("predef", cldrFactory,
+ "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/dateTimeFormats/"
+ + "availableFormats", "dateFormatItem", "id");
+ for (GwtLocale locale : localeData.getAllLocales()) {
+ DateTimePatternGenerator dtpg = new DateTimePatternGenerator(locale);
+ for (Map.Entry<String, String> entry : FORMATS.entrySet()) {
+ String skeleton = entry.getKey();
+ String cldrPattern = localeData.getEntry("predef", locale, skeleton);
+ String pattern = dtpg.getBestPattern(skeleton);
+ if (cldrPattern != null && !cldrPattern.equals(pattern)) {
+ System.err.println("Mismatch on skeleton pattern in locale " + locale
+ + " for skeleton '" + skeleton + "': icu='" + pattern
+ + "', cldr='" + cldrPattern + "'");
+ }
+ localeData.addEntry("predef", locale, skeleton, pattern);
+ }
+ }
+ }
+
+ /**
+ * Load the week start and weekend range values from CLDR.
+ */
+ private void loadWeekData() {
+ localeData.addTerritoryEntries("weekdata", cldrFactory,
+ regionLanguageData, "//supplementalData/weekData/firstDay", "firstDay", "day");
+ localeData.addTerritoryEntries("weekdata", cldrFactory,
+ regionLanguageData, "//supplementalData/weekData/weekendStart", "weekendStart", "day");
+ localeData.addTerritoryEntries("weekdata", cldrFactory,
+ regionLanguageData, "//supplementalData/weekData/weekendEnd", "weekendEnd", "day");
+ localeData.addTerritoryEntries("weekdata", cldrFactory,
+ regionLanguageData, "//supplementalData/weekData/minDays", "minDays", "count");
+ }
+
+ private void printHeader(PrintWriter pw) {
+ pw.println("/*");
+ pw.println(" * Copyright 2010 Google Inc.");
+ pw.println(" * ");
+ pw.println(" * Licensed under the Apache License, Version 2.0 (the "
+ + "\"License\"); you may not");
+ pw.println(" * use this file except in compliance with the License. You "
+ + "may obtain a copy of");
+ pw.println(" * the License at");
+ pw.println(" * ");
+ pw.println(" * http://www.apache.org/licenses/LICENSE-2.0");
+ pw.println(" * ");
+ pw.println(" * Unless required by applicable law or agreed to in writing, "
+ + "software");
+ pw.println(" * distributed under the License is distributed on an \"AS "
+ + "IS\" BASIS, WITHOUT");
+ pw.println(" * WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
+ + "implied. See the");
+ pw.println(" * License for the specific language governing permissions and "
+ + "limitations under");
+ pw.println(" * the License.");
+ pw.println(" */");
+ }
+
+ /**
+ * Remove duplicates from period names.
+ *
+ * @param group
+ */
+ private void removePeriodDuplicates(String group) {
+ removePeriodWidthDuplicates(group, "wide");
+ removePeriodWidthDuplicates(group, "abbrev");
+ removePeriodWidthDuplicates(group, "narrow");
+ }
+
+ private void removePeriodWidthDuplicates(String group, String width) {
+ localeData.removeCompleteDuplicates(group + "-" + width);
+ localeData.removeCompleteDuplicates(group + "-sa-" + width);
+ localeData.removeCompleteDuplicates(group + "-sa-" + width + "-redirect");
+ }
+
+ private void removeUnusedFormats() {
+ for (GwtLocale locale : localeData.getAllLocales()) {
+ Set<String> toRemove = new HashSet<String>();
+ Map<String, String> map = localeData.getEntries("predef", locale);
+ for (Entry<String, String> entry : map.entrySet()) {
+ if (!FORMATS.containsKey(entry.getKey())) {
+ toRemove.add(entry.getKey());
+ }
+ }
+ localeData.removeEntries("predef", locale, toRemove);
+ }
+ }
+}
diff --git a/tools/cldr-import/src/com/google/gwt/tools/cldr/GenerateGwtCldrData.java b/tools/cldr-import/src/com/google/gwt/tools/cldr/GenerateGwtCldrData.java
new file mode 100644
index 0000000..cea2fe6
--- /dev/null
+++ b/tools/cldr-import/src/com/google/gwt/tools/cldr/GenerateGwtCldrData.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.tools.cldr;
+
+import com.google.gwt.i18n.server.GwtLocaleFactoryImpl;
+import com.google.gwt.i18n.shared.GwtLocaleFactory;
+
+import com.ibm.icu.dev.tool.UOption;
+
+import org.unicode.cldr.util.CldrUtility;
+import org.unicode.cldr.util.CLDRFile.Factory;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Generate a country list for each locale, taking into account the literate
+ * population of each country speaking the language.
+ */
+@SuppressWarnings("unchecked")
+public class GenerateGwtCldrData {
+
+ private static final GwtLocaleFactory factory = new GwtLocaleFactoryImpl();
+
+ private static boolean DEBUG = false;
+
+ private static final Class<? extends Processor>[] PROCESSORS;
+
+ static {
+ PROCESSORS = new Class[] {
+ CurrencyDataProcessor.class,
+ DateTimeFormatInfoProcessor.class,
+ ListFormattingProcessor.class,
+ };
+ }
+
+ public static void main(String[] args) throws IOException, SecurityException,
+ NoSuchMethodException, IllegalArgumentException, InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ System.out.println("Starting to generate from CLDR data (ignore -D lines "
+ + "produced by cldr-tools)");
+ UOption[] options = {
+ UOption.HELP_H(),
+ UOption.HELP_QUESTION_MARK(),
+ UOption.SOURCEDIR().setDefault(CldrUtility.MAIN_DIRECTORY), // C:\cvsdata/unicode\cldr\diff\summary
+ outputDir().setDefault("./"),
+ restrictLocales(),
+ };
+ UOption.parseArgs(args, options);
+ String sourceDir = options[2].value; // SOURCEDIR
+ String targetDir = options[3].value; // outputDir
+ DEBUG = options[4].doesOccur; // --restrictLocales
+ Factory cldrFactory = Factory.make(sourceDir, ".*");
+ Set<String> locales = cldrFactory.getAvailable();
+ if (DEBUG) {
+ locales = new HashSet<String>(Arrays.asList(new String[] {
+ "root", "en", "en_US", "en_CA", "ar", "ar_IQ"}));
+ }
+ System.out.println("Processing " + locales.size() + " locales");
+ File outputDir = new File(targetDir);
+ LocaleData localeData = new LocaleData(factory, locales);
+ for (Class<? extends Processor> processorClass : PROCESSORS) {
+ Constructor<? extends Processor> ctor = processorClass.getConstructor(
+ File.class, Factory.class, LocaleData.class);
+ Processor processor = ctor.newInstance(outputDir, cldrFactory,
+ localeData);
+ processor.run();
+ }
+ System.out.println("Finished.");
+ }
+
+ private static UOption outputDir() {
+ return UOption.create("outdir", 'o', UOption.REQUIRES_ARG);
+ }
+
+ private static UOption restrictLocales() {
+ return UOption.create("restrictLocales", 'r', UOption.NO_ARG);
+ }
+}
diff --git a/tools/cldr-import/src/com/google/gwt/tools/cldr/ListFormattingProcessor.java b/tools/cldr-import/src/com/google/gwt/tools/cldr/ListFormattingProcessor.java
new file mode 100644
index 0000000..91bea10
--- /dev/null
+++ b/tools/cldr-import/src/com/google/gwt/tools/cldr/ListFormattingProcessor.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.tools.cldr;
+
+import com.google.gwt.i18n.shared.GwtLocale;
+
+import org.unicode.cldr.util.CLDRFile.Factory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+/**
+ * Extract list formatting information from CLDR data.
+ */
+public class ListFormattingProcessor extends Processor {
+
+ public ListFormattingProcessor(File outputDir, Factory cldrFactory,
+ LocaleData localeData) {
+ super(outputDir, cldrFactory, localeData);
+ }
+
+ @Override
+ protected void cleanupData() {
+ localeData.removeCompleteDuplicates();
+ }
+
+ @Override
+ protected void loadData() throws IOException {
+ System.out.println("Loading data for list formatting");
+ localeData.addEntries("list", cldrFactory,
+ "//ldml/listPatterns/listPattern", "listPatternPart", "type");
+ }
+
+ @Override
+ protected void writeOutputFiles() throws IOException {
+ for (GwtLocale locale : localeData.getNonEmptyLocales("list")) {
+ PrintWriter pw = null;
+ for (Map.Entry<String, String> entry : localeData.getEntries("list",
+ locale).entrySet()) {
+ if (pw == null) {
+ pw = createOutputFile("rebind/cldr/ListPatterns_"
+ + locale.getAsString() + ".properties");
+ }
+ pw.println(entry.getKey() + "=" + entry.getValue());
+ }
+ if (pw != null) {
+ pw.close();
+ }
+ }
+ }
+}
diff --git a/tools/cldr-import/src/com/google/gwt/tools/cldr/LocaleData.java b/tools/cldr-import/src/com/google/gwt/tools/cldr/LocaleData.java
new file mode 100644
index 0000000..db3cfba
--- /dev/null
+++ b/tools/cldr-import/src/com/google/gwt/tools/cldr/LocaleData.java
@@ -0,0 +1,1048 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.tools.cldr;
+
+import com.google.gwt.i18n.shared.GwtLocale;
+import com.google.gwt.i18n.shared.GwtLocaleFactory;
+
+import org.unicode.cldr.util.CLDRFile;
+import org.unicode.cldr.util.CLDRFile.Factory;
+import org.unicode.cldr.util.XPathParts;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Collects all the locale data from CLDR, grouping it by how it will be used
+ * and removing equivalent values that could be inherited.
+ */
+public class LocaleData {
+
+ /**
+ * Represents data about a single currency in a particular locale from CLDR.
+ */
+ public static class Currency {
+
+ private static boolean equalsNullCheck(Object a, Object b) {
+ if (a == null) {
+ return b == null;
+ }
+ return a.equals(b);
+ }
+
+ private static int hashCodeNullCheck(Object obj) {
+ return obj == null ? 0 : obj.hashCode();
+ }
+
+ private final String code;
+
+ private String symbol;
+
+ private String displayName;
+
+ private String pattern;
+
+ private String decimalSeparator;
+
+ private String groupingSeparator;
+
+ private int decimalDigits;
+
+ private boolean inUse;
+
+ public Currency(String code) {
+ this.code = code;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof Currency)) {
+ return false;
+ }
+ Currency other = (Currency) obj;
+ return code.equals(other.code)
+ && equalsNullCheck(displayName, other.displayName)
+ && equalsNullCheck(symbol, other.symbol)
+ && equalsNullCheck(pattern, other.pattern)
+ && equalsNullCheck(decimalSeparator, other.decimalSeparator)
+ && equalsNullCheck(groupingSeparator, other.groupingSeparator)
+ && decimalDigits == other.decimalDigits && inUse == other.inUse;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ /**
+ * @return the number of decimal digits this currency is commonly displayed
+ * with.
+ */
+ public int getDecimalDigits() {
+ return decimalDigits;
+ }
+
+ public String getDecimalSeparator() {
+ return decimalSeparator;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public String getGroupingSeparator() {
+ return groupingSeparator;
+ }
+
+ public String getPattern() {
+ return pattern;
+ }
+
+ public String getSymbol() {
+ return symbol;
+ }
+
+ @Override
+ public int hashCode() {
+ return code.hashCode() + 17 * hashCodeNullCheck(displayName) + 19
+ * hashCodeNullCheck(symbol) + 23 * hashCodeNullCheck(pattern) + 29
+ * hashCodeNullCheck(decimalSeparator) + 31
+ * hashCodeNullCheck(groupingSeparator) + 37 * decimalDigits
+ + (inUse ? 41 : 0);
+ }
+
+ /**
+ * @return true if this currency is still in regular use.
+ */
+ public boolean isInUse() {
+ return inUse;
+ }
+
+ public void setDecimalDigits(int decimalDigits) {
+ this.decimalDigits = decimalDigits;
+ }
+
+ public void setDecimalSeparator(String decimalSeparator) {
+ this.decimalSeparator = decimalSeparator;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public void setGroupingSeparator(String groupingSeparator) {
+ this.groupingSeparator = groupingSeparator;
+ }
+
+ public void setInUse(boolean inUse) {
+ this.inUse = inUse;
+ }
+
+ public void setPattern(String pattern) {
+ this.pattern = pattern;
+ }
+
+ public void setSymbol(String symbol) {
+ this.symbol = symbol;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(code);
+ if (displayName != null || symbol != null) {
+ buf.append(" (");
+ }
+ if (displayName != null) {
+ buf.append(displayName);
+ }
+ if (symbol != null) {
+ if (displayName != null) {
+ buf.append("; ");
+ }
+ buf.append(symbol);
+ }
+ if (displayName != null || symbol != null) {
+ buf.append(")");
+ }
+ return buf.toString();
+ }
+ }
+
+ /**
+ * Comparator that orders locales based the inheritance depth.
+ */
+ private class LocaleComparator implements Comparator<GwtLocale> {
+ public int compare(GwtLocale a, GwtLocale b) {
+ int depthA = localeDepth.get(a);
+ int depthB = localeDepth.get(b);
+ int c = depthB - depthA;
+ if (c == 0) {
+ c = a.compareTo(b);
+ }
+ return c;
+ }
+ }
+
+ /**
+ * Encapsulates the key for lookup values, comprising a locale and a category.
+ */
+ private static class MapKey {
+ private final GwtLocale locale;
+ private final String category;
+
+ public MapKey(String category, GwtLocale locale) {
+ this.category = category;
+ this.locale = locale;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ MapKey other = (MapKey) obj;
+ return locale.equals(other.locale) && category.equals(other.category);
+ }
+
+ public String getCategory() {
+ return category;
+ }
+
+ public GwtLocale getLocale() {
+ return locale;
+ }
+
+ @Override
+ public int hashCode() {
+ return category.hashCode() + 31 * locale.hashCode();
+ }
+
+ public MapKey inNewLocale(GwtLocale newLocale) {
+ return new MapKey(category, newLocale);
+ }
+
+ @Override
+ public String toString() {
+ return "[cat=" + category + ", locale=" + locale + "]";
+ }
+ }
+
+ /**
+ * Return the CLDR locale name for a GWT locale.
+ *
+ * @param locale
+ * @return CLDR locale name for GWT locale
+ */
+ public static String getCldrLocale(GwtLocale locale) {
+ return locale.isDefault() ? "root" : locale.toString();
+ }
+
+ /**
+ * @param factory
+ * @param localeName
+ * @return GwtLocale instance for CLDR locale
+ */
+ public static GwtLocale getGwtLocale(GwtLocaleFactory factory,
+ String localeName) {
+ return "root".equals(localeName) ? factory.getDefault()
+ : factory.fromString(localeName).getCanonicalForm();
+ }
+
+ /**
+ * Get the value of a given category of territory data inherited by a locale.
+ *
+ * @param locale the locale to search for
+ * @param map the map containing territory=>value data
+ * @return the requested value from the closest ancestor of the specified
+ * locale, or null if not found
+ */
+ private static String getTerritoryData(GwtLocale locale,
+ Map<String, String> map) {
+ if (map == null) {
+ return null;
+ }
+ for (GwtLocale search : locale.getCompleteSearchList()) {
+ String region = search.getRegion();
+ if (region == null) {
+ region = "001";
+ }
+ String value = map.get(region);
+ if (value != null) {
+ return value;
+ }
+ }
+ return null;
+ }
+
+ private Map<MapKey, Map<String, String>> maps;
+
+ private final HashMap<GwtLocale, GwtLocale> inheritsFrom;
+
+ private final Map<GwtLocale, String> allLocales;
+
+ private final Map<GwtLocale, Integer> localeDepth;
+
+ private final GwtLocale defaultLocale;
+
+ private final GwtLocaleFactory localeFactory;
+
+ /**
+ * Construct a LocaleData object.
+ *
+ * @param localeFactory
+ * @param localeNames
+ */
+ public LocaleData(GwtLocaleFactory localeFactory,
+ Collection<String> localeNames) {
+ this.localeFactory = localeFactory;
+ defaultLocale = localeFactory.getDefault();
+ allLocales = new HashMap<GwtLocale, String>();
+ for (String localeName : localeNames) {
+ allLocales.put(getGwtLocale(localeFactory, localeName), localeName);
+ }
+ inheritsFrom = new HashMap<GwtLocale, GwtLocale>();
+ buildInheritsFrom();
+ localeDepth = new HashMap<GwtLocale, Integer>();
+ maps = new HashMap<MapKey, Map<String, String>>();
+ buildLocaleDepth();
+ }
+
+ /**
+ * Add a single entry from an attribute on a CLDR node.
+ *
+ * @param category
+ * @param locale
+ * @param cldrFactory
+ * @param path
+ * @param tag
+ * @param key
+ * @param attribute
+ */
+ public void addAttributeEntry(String category, GwtLocale locale,
+ Factory cldrFactory, String path, String tag, String key,
+ String attribute) {
+ Map<String, String> map = getMap(category, locale);
+ CLDRFile cldr = cldrFactory.make(allLocales.get(locale), true);
+ XPathParts parts = new XPathParts();
+ parts.set(cldr.getFullXPath(path));
+ Map<String, String> attr = parts.findAttributes(tag);
+ if (attr == null) {
+ return;
+ }
+ String value = attr.get(attribute);
+ map.put(key, value);
+ }
+
+ /**
+ * Add currency entries for all locales.
+ *
+ * @param category
+ * @param cldrFactory
+ * @param currencyFractions map of currency fraction data extracted from
+ * locale-independent data
+ * @param defaultCurrencyFraction
+ * @param stillInUse
+ */
+ public void addCurrencyEntries(String category, Factory cldrFactory,
+ Map<String, Integer> currencyFractions, int defaultCurrencyFraction,
+ Set<String> stillInUse) {
+ for (GwtLocale locale : allLocales.keySet()) {
+ // skip the "default" locale for now
+ if (locale.isDefault()) {
+ continue;
+ }
+ addCurrencyEntries(category, locale, cldrFactory, currencyFractions,
+ defaultCurrencyFraction, stillInUse);
+ }
+ // run the "default" locale last, to override inherited entries
+ GwtLocale locale = localeFactory.getDefault();
+ addCurrencyEntries(category, locale, cldrFactory, currencyFractions,
+ defaultCurrencyFraction, stillInUse);
+ }
+
+ public void addDateTimeFormatEntries(String group, Factory cldrFactory) {
+ addAttributeEntries(group, cldrFactory,
+ "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + group
+ + "Formats/default", "default", "default", "choice");
+ addDateTimeFormatEntries(group, "full", cldrFactory);
+ addDateTimeFormatEntries(group, "long", cldrFactory);
+ addDateTimeFormatEntries(group, "medium", cldrFactory);
+ addDateTimeFormatEntries(group, "short", cldrFactory);
+ }
+
+ public void addEntries(String category, Factory cldrFactory, String prefix,
+ String tag, String keyAttribute) {
+ for (GwtLocale locale : allLocales.keySet()) {
+ addEntries(category, locale, cldrFactory, prefix, tag, keyAttribute);
+ }
+ }
+
+ public void addEntries(String category, GwtLocale locale, Factory cldrFactory,
+ String prefix, String tag, String keyAttribute) {
+ Map<String, String> map = getMap(category, locale);
+ CLDRFile cldr = cldrFactory.make(allLocales.get(locale), true);
+ XPathParts parts = new XPathParts();
+ Iterator<String> iterator = cldr.iterator(prefix);
+ while (iterator.hasNext()) {
+ String path = iterator.next();
+ String fullXPath = cldr.getFullXPath(path);
+ if (fullXPath == null) {
+ fullXPath = path;
+ }
+ parts.set(fullXPath);
+ if (parts.containsAttribute("alt")) {
+ // ignore alternate strings
+ continue;
+ }
+ Map<String, String> attr = parts.findAttributes(tag);
+ if (attr == null) {
+ continue;
+ }
+ String key = attr.get(keyAttribute);
+ String value = cldr.getStringValue(path);
+ boolean draft = parts.containsAttribute("draft");
+ if (!draft || !map.containsKey(key)) {
+ map.put(key, value);
+ }
+ }
+ }
+
+ public void addEntry(String category, GwtLocale locale, String key,
+ String value) {
+ Map<String, String> map = getMap(category, locale);
+ map.put(key, value);
+ }
+
+ /**
+ * @param period "month", "day", "quarter", "dayPeriod",
+ * @param cldrFactory
+ */
+ public void addNameEntries(String period, Factory cldrFactory) {
+ addEntries(period + "-abbrev", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
+ + "s/" + period + "Context[@type=\"format\"]/" + period
+ + "Width[@type=\"abbreviated\"]", period, "type");
+ addEntries(period + "-narrow", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
+ + "s/" + period + "Context[@type=\"format\"]/" + period
+ + "Width[@type=\"narrow\"]", period, "type");
+ addEntries(period + "-wide", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
+ + "s/" + period + "Context[@type=\"format\"]/" + period
+ + "Width[@type=\"wide\"]", period, "type");
+ addEntries(period + "-sa-abbrev", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
+ + "s/" + period + "Context[@type=\"stand-alone\"]/" + period
+ + "Width[@type=\"abbreviated\"]", period, "type");
+ addEntries(period + "-sa-narrow", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
+ + "s/" + period + "Context[@type=\"stand-alone\"]/" + period
+ + "Width[@type=\"narrow\"]", period, "type");
+ addEntries(period + "-sa-wide", cldrFactory, "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + period
+ + "s/" + period + "Context[@type=\"stand-alone\"]/" + period
+ + "Width[@type=\"wide\"]", period, "type");
+ }
+
+ /**
+ * Add entries from territory-oriented CLDR data.
+ *
+ * @param category category to store resulting data under
+ * @param cldrFactory
+ * @param regionLanguageData
+ * @param prefix the XPath prefix to iterate through
+ * @param tag the tag to load
+ * @param keyAttribute the attribute in the tag to use as the key
+ */
+ public void addTerritoryEntries(String category, Factory cldrFactory,
+ RegionLanguageData regionLanguageData, String prefix, String tag,
+ String keyAttribute) {
+ CLDRFile supp = cldrFactory.make("supplementalData", true);
+ Map<String, String> map = new HashMap<String, String>();
+ XPathParts parts = new XPathParts();
+ Iterator<String> iterator = supp.iterator(prefix);
+ while (iterator.hasNext()) {
+ String path = iterator.next();
+ parts.set(supp.getFullXPath(path));
+ Map<String, String> attr = parts.findAttributes(tag);
+ if (attr == null || attr.get("alt") != null) {
+ continue;
+ }
+ String key = attr.get(keyAttribute);
+ String territories = attr.get("territories");
+ String draft = attr.get("draft");
+ for (String territory : territories.split(" ")) {
+ if (draft == null || !map.containsKey(territory)) {
+ map.put(territory, key);
+ }
+ }
+ }
+
+ if (regionLanguageData != null) {
+ // find the choice used by most literate speakers of each language
+ // based on region-based preferences.
+ for (GwtLocale locale : allLocales.keySet()) {
+ if (locale.getRegion() != null || locale.getLanguage() == null) {
+ // skip any that have a region or don't have a language
+ continue;
+ }
+ String language = locale.getAsString();
+ Map<String, Double> langMap = new HashMap<String, Double>();
+ for (RegionLanguageData.RegionPopulation langData
+ : regionLanguageData.getRegions(language)) {
+ String region = langData.getRegion();
+ GwtLocale regionLocale = localeFactory.fromString(language + "_"
+ + region);
+ String day = getTerritoryData(regionLocale, map);
+ if (day != null) {
+ Double pop = langMap.get(day);
+ if (pop == null) {
+ pop = 0.0;
+ }
+ pop += langData.getLiteratePopulation();
+ langMap.put(day, pop);
+ }
+ }
+ double max = 0;
+ String maxDay = null;
+ for (Map.Entry<String, Double> entry : langMap.entrySet()) {
+ if (entry.getValue() > max) {
+ max = entry.getValue();
+ maxDay = entry.getKey();
+ }
+ }
+ if (maxDay != null) {
+ addEntry(category, locale, tag, maxDay);
+ }
+ }
+ }
+
+ // map locales to territory data
+ for (GwtLocale locale : allLocales.keySet()) {
+ if (getEntry(category, locale, tag) != null) {
+ // don't override what we set above
+ continue;
+ }
+ String day = getTerritoryData(locale, map);
+ if (day != null) {
+ addEntry(category, locale, tag, day);
+ }
+ }
+ }
+
+ /**
+ * Add a redirect entry for each locale where all entries in the standalone
+ * category match those in the base category.
+ *
+ * @param baseCategory
+ * @param standaloneCategory
+ */
+ public void computeRedirects(String baseCategory,
+ String standaloneCategory) {
+ for (GwtLocale locale : allLocales.keySet()) {
+ MapKey baseKey = new MapKey(baseCategory, locale);
+ MapKey standaloneKey = new MapKey(standaloneCategory, locale);
+ Map<String, String> baseMap = maps.get(baseKey);
+ Map<String, String> standaloneMap = maps.get(standaloneKey);
+ if (baseMap != null && standaloneMap != null && (standaloneMap.isEmpty()
+ || baseMap.equals(standaloneMap))) {
+ addEntry(standaloneCategory + "-redirect", locale, "redirect", "yes");
+ }
+ }
+ }
+
+ /**
+ * Copy data from one locale to another.
+ *
+ * @param srcLocaleName source locale name
+ * @param destLocaleName destination locale name
+ * @param categories list of categories to copy
+ */
+ public void copyLocaleData(String srcLocaleName, String destLocaleName,
+ String... categories) {
+ GwtLocale src = localeFactory.fromString(srcLocaleName);
+ GwtLocale dest = localeFactory.fromString(destLocaleName);
+ for (String category : categories) {
+ Map<String, String> srcMap = maps.get(new MapKey(category, src));
+ if (srcMap == null || srcMap.isEmpty()) {
+ continue;
+ }
+ Map<String, String> destMap = getMap(category, dest);
+ destMap.putAll(srcMap);
+ }
+ }
+
+ public Map<String, Map<String, String>> getAllEntries(String localeName) {
+ GwtLocale locale = localeFactory.fromString(localeName);
+ Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
+ for (Map.Entry<MapKey, Map<String, String>> entry : maps.entrySet()) {
+ Map<String, String> map = entry.getValue();
+ if (entry.getKey().getLocale().equals(locale) && !map.isEmpty()) {
+ result.put(entry.getKey().getCategory(),
+ Collections.unmodifiableMap(entry.getValue()));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @return all locales present in the CLDR data.
+ */
+ public Set<GwtLocale> getAllLocales() {
+ return Collections.unmodifiableSet(allLocales.keySet());
+ }
+
+ /**
+ * Return all entries in a given category and locale.
+ *
+ * @param category
+ * @param locale
+ * @return map of keys to localized values
+ */
+ public Map<String, String> getEntries(String category, GwtLocale locale) {
+ MapKey mapKey = new MapKey(category, locale);
+ Map<String, String> map = maps.get(mapKey);
+ if (map == null) {
+ return Collections.emptyMap();
+ }
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * Return a single value.
+ *
+ * @param category
+ * @param locale
+ * @param key
+ * @return the requested value, or null if not present
+ */
+ public String getEntry(String category, GwtLocale locale, String key) {
+ MapKey mapKey = new MapKey(category, locale);
+ Map<String, String> map = maps.get(mapKey);
+ if (map == null) {
+ return null;
+ }
+ return map.get(key);
+ }
+
+ /**
+ * @return all locales that have some data associated with them.
+ */
+ public Set<GwtLocale> getNonEmptyLocales() {
+ Set<GwtLocale> result = new HashSet<GwtLocale>();
+ for (Map.Entry<MapKey, Map<String, String>> entry : maps.entrySet()) {
+ Map<String, String> map = entry.getValue();
+ if (map.isEmpty()) {
+ continue;
+ }
+ result.add(entry.getKey().getLocale());
+ }
+ return result;
+ }
+
+ /**
+ * @return all locales that have some data associated with them in the
+ * specified category.
+ */
+ public Set<GwtLocale> getNonEmptyLocales(String category) {
+ Set<GwtLocale> result = new HashSet<GwtLocale>();
+ for (Map.Entry<MapKey, Map<String, String>> entry : maps.entrySet()) {
+ Map<String, String> map = entry.getValue();
+ if (!category.equals(entry.getKey().category) || map.isEmpty()) {
+ continue;
+ }
+ result.add(entry.getKey().getLocale());
+ }
+ return result;
+ }
+
+ /**
+ * Return the nearest ancestor locale of the supplied locale which has any
+ * values present.
+ *
+ * @param locale
+ * @return GwtLocale of nearest ancestor
+ */
+ public GwtLocale inheritsFrom(GwtLocale locale) {
+ GwtLocale parent = inheritsFrom.get(locale);
+ while (parent != null && parent != defaultLocale) {
+ for (Map.Entry<MapKey, Map<String, String>> entry : maps.entrySet()) {
+ if (entry.getKey().getLocale().equals(parent)) {
+ Map<String, String> map = entry.getValue();
+ if (!map.isEmpty()) {
+ return parent;
+ }
+ }
+ }
+ parent = inheritsFrom.get(parent);
+ }
+ return parent;
+ }
+
+ /**
+ * Return the nearest ancestor locale of the supplied locale which has any
+ * values present in the specified category.
+ *
+ * @param category
+ * @param locale
+ * @return GwtLocale of nearest ancestor with the specified category
+ */
+ public GwtLocale inheritsFrom(String category, GwtLocale locale) {
+ GwtLocale parent = inheritsFrom.get(locale);
+ while (parent != null && parent != defaultLocale) {
+ Map<String, String> map = getMap(category, parent);
+ if (!map.isEmpty()) {
+ return parent;
+ }
+ parent = inheritsFrom.get(parent);
+ }
+ return parent;
+ }
+
+ /**
+ * Remove locale entries that completely duplicate their parent.
+ */
+ public void removeCompleteDuplicates() {
+ removeCompleteDuplicates(null);
+ }
+
+ /**
+ * Remove locale entries that completely duplicate their parent.
+ *
+ * @param matchCategory
+ */
+ public void removeCompleteDuplicates(String matchCategory) {
+ MapKey[] keys = getSortedMapKeys();
+ for (MapKey key : keys) {
+ String category = key.getCategory();
+ if (matchCategory != null && !matchCategory.equals(category)) {
+ continue;
+ }
+ GwtLocale locale = key.getLocale();
+ GwtLocale parent = inheritsFrom(category, locale);
+ if (parent == null) {
+ continue;
+ }
+ MapKey parentKey = key.inNewLocale(parent);
+ Map<String, String> parentMap = maps.get(parentKey);
+ if (parentMap == null) {
+ continue;
+ }
+ Map<String, String> map = maps.get(key);
+ boolean allMatch = true;
+ for (Map.Entry<String, String> entry : map.entrySet()) {
+ if (!entry.getValue().equals(parentMap.get(entry.getKey()))) {
+ allMatch = false;
+ break;
+ }
+ }
+ if (allMatch) {
+ maps.remove(key);
+ }
+ }
+ }
+
+ /**
+ * Remove entries that are duplicates of the entries in the parent locale.
+ */
+ public void removeDuplicates() {
+ removeDuplicates(null);
+ }
+
+ /**
+ * Remove entries that are duplicates of the entries in the parent locale.
+ *
+ * @param matchCategory
+ */
+ public void removeDuplicates(String matchCategory) {
+ MapKey[] keys = getSortedMapKeys();
+ for (MapKey key : keys) {
+ String category = key.getCategory();
+ if (matchCategory != null && !matchCategory.equals(category)) {
+ continue;
+ }
+ GwtLocale locale = key.getLocale();
+ GwtLocale parent = inheritsFrom(category, locale);
+ if (parent == null) {
+ continue;
+ }
+ MapKey parentKey = key.inNewLocale(parent);
+ Map<String, String> parentMap = maps.get(parentKey);
+ if (parentMap == null) {
+ continue;
+ }
+ Map<String, String> map = maps.get(key);
+ Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, String> entry = it.next();
+ String value = entry.getValue();
+ if (value == null || value.equals(parentMap.get(entry.getKey()))) {
+ it.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Remove entries in the specified category and locale which match any of
+ * the supplied keys.
+ *
+ * @param category
+ * @param locale
+ * @param keys
+ */
+ public void removeEntries(String category, GwtLocale locale,
+ Collection<String> keys) {
+ Map<String, String> map = getMap(category, locale);
+ map.keySet().removeAll(keys);
+ }
+
+ /**
+ * Remove a single entry, if present.
+ *
+ * @param category
+ * @param locale
+ * @param key
+ */
+ public void removeEntry(String category, GwtLocale locale, String key) {
+ Map<String, String> map = getMap(category, locale);
+ map.remove(key);
+ }
+
+ /**
+ * Reset state, forgetting any cached values.
+ */
+ public void reset() {
+ maps.clear();
+ }
+
+ private void addAttributeEntries(String category, Factory cldrFactory,
+ String prefix, String tag, String key, String attribute) {
+ for (GwtLocale locale : allLocales.keySet()) {
+ addAttributeEntry(category, locale, cldrFactory, prefix, tag, key,
+ attribute);
+ }
+ }
+
+ /**
+ * Add currency entries for the specified locale. If this locale is not the
+ * default locale, also add default entries into the default locale to make
+ * sure it has entries for any currency present in any locale. Note that
+ * this means that the default locale must be processed last.
+ *
+ * @param category
+ * @param locale
+ * @param cldrFactory
+ * @param currencyFractions map of currency fraction data extracted from
+ * locale-independent data
+ * @param defaultCurrencyFraction
+ * @param stillInUse
+ */
+ private void addCurrencyEntries(String category, GwtLocale locale,
+ Factory cldrFactory, Map<String, Integer> currencyFractions,
+ int defaultCurrencyFraction, Set<String> stillInUse) {
+ Map<String, String> outputMap = getMap(category, locale);
+ Map<String, String> defaultMap = null;
+ if (!locale.isDefault()) {
+ defaultMap = getMap(category, localeFactory.getDefault());
+ }
+ Map<String, Currency> tempMap = new HashMap<String, Currency>();
+ CLDRFile cldr = cldrFactory.make(allLocales.get(locale), true);
+ XPathParts parts = new XPathParts();
+ Iterator<String> iterator = cldr.iterator(
+ "//ldml/numbers/currencies");
+ while (iterator.hasNext()) {
+ String path = iterator.next();
+ path = cldr.getFullXPath(path);
+ parts.set(path);
+ Map<String, String> attr = parts.findAttributes("currency");
+ if (attr == null) {
+ continue;
+ }
+ String currencyCode = attr.get("type");
+ Currency currency = tempMap.get(currencyCode);
+ if (currency == null) {
+ currency = new Currency(currencyCode);
+ if (currencyFractions.containsKey(currencyCode)) {
+ currency.setDecimalDigits(currencyFractions.get(currencyCode));
+ } else {
+ currency.setDecimalDigits(defaultCurrencyFraction);
+ }
+ currency.setInUse(stillInUse.contains(currencyCode));
+ tempMap.put(currencyCode, currency);
+ }
+ String field = parts.getElement(4);
+ String value = cldr.getStringValue(path);
+ attr = parts.findAttributes(field);
+ if (attr == null) {
+ attr = Collections.emptyMap();
+ }
+ String draft = attr.get("draft");
+ if ("symbol".equalsIgnoreCase(field)) {
+ currency.setSymbol(value);
+ } else if ("displayName".equalsIgnoreCase(field)) {
+ if (attr.get("count") != null) {
+ // We don't care about currency "count" names
+ continue;
+ }
+ if (draft == null || currency.getDisplayName() == null) {
+ // don't override non-draft name with draft name
+ currency.setDisplayName(value);
+ }
+ } else if ("pattern".equalsIgnoreCase(field)) {
+ currency.setPattern(value);
+ } else if ("decimal".equalsIgnoreCase(field)) {
+ currency.setDecimalSeparator(value);
+ } else if ("group".equalsIgnoreCase(field)) {
+ currency.setGroupingSeparator(value);
+ } else {
+ System.err.println("Ignoring unknown field \"" + field
+ + "\" on currency data for \"" + currencyCode + "\"");
+ }
+ }
+ for (Currency currency : tempMap.values()) {
+ String code = currency.getCode();
+ outputMap.put(code, encodeCurrencyData(currency));
+ if (defaultMap != null) {
+ // Don't copy language-specific things to default
+ currency.setDisplayName(code);
+ currency.setSymbol(null);
+ defaultMap.put(code, encodeCurrencyData(currency));
+ }
+ }
+ }
+
+ private void addDateTimeFormatEntries(String group, String length,
+ Factory cldrFactory) {
+ addEntries(group, cldrFactory,
+ "//ldml/dates/calendars/calendar[@type=\"gregorian\"]/" + group
+ + "Formats/" + group + "FormatLength"
+ + "[@type=\"" + length + "\"]/" + group + "Format[@type=\"standard\"]"
+ + "/pattern[@type=\"standard\"]", group + "FormatLength", "type");
+ }
+
+ private void buildInheritsFrom() {
+ for (GwtLocale locale : allLocales.keySet()) {
+ GwtLocale parent = null;
+ for (GwtLocale search : locale.getInheritanceChain()) {
+ if (!search.equals(locale) && allLocales.containsKey(search)) {
+ parent = search;
+ break;
+ }
+ }
+ inheritsFrom.put(locale, parent);
+ }
+ }
+
+ /**
+ * Build a depth map which is used to sort locales such that more derived
+ * locales are processed before less derived locales.
+ */
+ private void buildLocaleDepth() {
+ Set<GwtLocale> remaining = new HashSet<GwtLocale>(allLocales.keySet());
+ localeDepth.put(defaultLocale, 0);
+ remaining.remove(defaultLocale);
+ while (!remaining.isEmpty()) {
+ Set<GwtLocale> nextPass = new HashSet<GwtLocale>();
+ for (GwtLocale locale : remaining) {
+ GwtLocale parent = inheritsFrom.get(locale);
+ if (localeDepth.containsKey(parent)) {
+ int depth = localeDepth.get(parent);
+ localeDepth.put(locale, depth + 1);
+ } else {
+ nextPass.add(locale);
+ }
+ }
+ remaining = nextPass;
+ }
+ }
+
+ /**
+ * Encode the currency data as needed by CurrencyListGenerator.
+ *
+ * @param currency
+ * @return a string containing the property file entry for the specified
+ * currency
+ */
+ private String encodeCurrencyData(Currency currency) {
+ StringBuilder buf = new StringBuilder();
+ String skipped = "";
+ String displayName = currency.getDisplayName();
+ if (displayName == null) {
+ displayName = currency.getCode();
+ }
+ buf.append(displayName);
+ String symbol = currency.getSymbol();
+ if (symbol != null && !currency.getCode().equals(symbol)) {
+ buf.append('|');
+ buf.append(symbol);
+ skipped = "";
+ } else {
+ skipped = "|";
+ }
+ if (currency.getDecimalDigits() != 2) {
+ buf.append(skipped).append('|');
+ buf.append(currency.getDecimalDigits());
+ skipped = "";
+ } else {
+ skipped += "|";
+ }
+ if (!currency.isInUse()) {
+ buf.append(skipped).append("|1");
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Get a map for a given class/locale combination.
+ * @param category
+ * @param locale
+ *
+ * @return map for the specified class/locale
+ */
+ private Map<String, String> getMap(String category, GwtLocale locale) {
+ MapKey mapKey = new MapKey(category, locale);
+ Map<String, String> map = maps.get(mapKey);
+ if (map == null) {
+ map = new HashMap<String, String>();
+ maps.put(mapKey, map);
+ }
+ return map;
+ }
+
+ /**
+ * @return an array of map keys, ordered from most derived to least derived.
+ */
+ private MapKey[] getSortedMapKeys() {
+ Set<MapKey> keySet = maps.keySet();
+ MapKey[] keys = keySet.toArray(new MapKey[keySet.size()]);
+ Arrays.sort(keys, new Comparator<MapKey>() {
+ private final Comparator<GwtLocale> depthComparator = new LocaleComparator();
+
+ public int compare(MapKey a, MapKey b) {
+ return depthComparator.compare(a.getLocale(), b.getLocale());
+ }
+ });
+ return keys;
+ }
+}
diff --git a/tools/cldr-import/src/com/google/gwt/tools/cldr/Processor.java b/tools/cldr-import/src/com/google/gwt/tools/cldr/Processor.java
new file mode 100644
index 0000000..7ad1b75
--- /dev/null
+++ b/tools/cldr-import/src/com/google/gwt/tools/cldr/Processor.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.tools.cldr;
+
+import com.google.gwt.i18n.shared.GwtLocale;
+
+import org.unicode.cldr.util.CLDRFile.Factory;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+
+/**
+ * Base class for CLDR processors that generate GWT i18n resources.
+ */
+public abstract class Processor {
+
+ protected static final String I18N_PACKAGE_PATH = "user/src/com/google/gwt/i18n/";
+
+ protected static <T> String join(String joiner, Iterable<T> objects) {
+ StringBuilder buf = new StringBuilder();
+ for (Object obj : objects) {
+ if (buf.length() > 0) {
+ buf.append(joiner);
+ }
+ buf.append(obj.toString());
+ }
+ return buf.toString();
+ }
+
+ protected static String localeSuffix(GwtLocale locale) {
+ return (locale.isDefault() ? "" : "_") + locale.getAsString();
+ }
+
+ protected final Factory cldrFactory;
+
+ protected final LocaleData localeData;
+
+ protected final File outputDir;
+
+ private boolean useOverride;
+
+ /**
+ * Initialize the shared portion of a Processor.
+ *
+ * @param outputDir output directory for created files
+ * @param cldrFactory CLDR factory used to create new CLDRFile instances
+ * @param localeData LocaleData instance to collect data from CLDR files
+ */
+ protected Processor(File outputDir, Factory cldrFactory,
+ LocaleData localeData) {
+ this.outputDir = outputDir;
+ this.cldrFactory = cldrFactory;
+ this.localeData = localeData;
+ useOverride = true;
+ }
+
+ /**
+ * Execute this processor.
+ *
+ * It will call loadData, cleanupData, writeOutputFiles, and then reset on
+ * its localeData instance.
+ *
+ * @throws IOException
+ */
+ public final void run() throws IOException {
+ try {
+ loadData();
+ cleanupData();
+ writeOutputFiles();
+ } finally {
+ localeData.reset();
+ }
+ }
+
+ /**
+ * Override hook for subclasses to implement any cleanup needed, such as
+ * removing values which duplicate those from ancestors.
+ */
+ protected void cleanupData() {
+ // do nothing by default
+ }
+
+ /**
+ * Create an output file including any parent directories.
+ *
+ * @param name name of file, which will be prefixed by
+ * user/src/com/google/gwt/i18n/client/impl/cldr
+ * @param ext extension for file
+ * @param locale locale name or null if not localized
+ * @return a PrintWriter instance
+ * @throws IOException
+ */
+ protected PrintWriter createFile(String name, String ext, String locale)
+ throws IOException {
+ if (locale == null || locale.length() == 0) {
+ locale = "";
+ } else {
+ locale = "_" + locale;
+ }
+ return createOutputFile("client/impl/cldr/" + name + locale + "." + ext);
+ }
+
+ protected PrintWriter createOutputFile(String suffix)
+ throws IOException, FileNotFoundException {
+ return createOutputFile(I18N_PACKAGE_PATH, suffix);
+ }
+
+ protected PrintWriter createOutputFile(String prefix, String suffix)
+ throws IOException, FileNotFoundException {
+ PrintWriter pw;
+ File f = new File(outputDir, prefix + suffix);
+ File parent = f.getParentFile();
+ if (parent != null) {
+ parent.mkdirs();
+ }
+ f.createNewFile();
+ pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
+ new FileOutputStream(f), "UTF-8")), false);
+ return pw;
+ }
+
+ protected void generateIntMethod(PrintWriter pw, String category,
+ GwtLocale locale, String key, String method) {
+ String value = localeData.getEntry(category, locale, key);
+ if (value != null) {
+ pw.println();
+ if (useOverride) {
+ pw.println(" @Override");
+ }
+ pw.println(" public int " + method + "() {");
+ pw.println(" return " + value + ";");
+ pw.println(" }");
+ }
+ }
+
+ protected void generateStringMethod(PrintWriter pw, String category,
+ GwtLocale locale, String key, String method) {
+ String value = localeData.getEntry(category, locale, key);
+ generateStringValue(pw, method, value);
+ }
+
+ protected void generateStringValue(PrintWriter pw, String method,
+ String value) {
+ if (value != null) {
+ pw.println();
+ if (useOverride) {
+ pw.println(" @Override");
+ }
+ pw.println(" public String " + method + "() {");
+ pw.println(" return \"" + value.replace("\"", "\\\"") + "\";");
+ pw.println(" }");
+ }
+ }
+
+ /**
+ * @return true if generated methods should use @Override.
+ */
+ protected boolean getOverrides() {
+ return useOverride;
+ }
+
+ /**
+ * Load data needed by this processor.
+ *
+ * @throws IOException
+ */
+ protected abstract void loadData() throws IOException;
+
+ /**
+ * Set whether method definitions should use @Override.
+ *
+ * @param useOverride
+ */
+ protected void setOverrides(boolean useOverride) {
+ this.useOverride = useOverride;
+ }
+
+ /**
+ * Write output files produced by this processor.
+ *
+ * @throws IOException
+ */
+ protected abstract void writeOutputFiles() throws IOException;
+}
diff --git a/tools/cldr-import/src/com/google/gwt/tools/cldr/RegionLanguageData.java b/tools/cldr-import/src/com/google/gwt/tools/cldr/RegionLanguageData.java
new file mode 100644
index 0000000..bdab309
--- /dev/null
+++ b/tools/cldr-import/src/com/google/gwt/tools/cldr/RegionLanguageData.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.tools.cldr;
+
+import org.unicode.cldr.util.CLDRFile;
+import org.unicode.cldr.util.XPathParts;
+import org.unicode.cldr.util.CLDRFile.DraftStatus;
+import org.unicode.cldr.util.CLDRFile.Factory;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Encapsulates region/language literacy data from CLDR.
+ */
+public class RegionLanguageData {
+
+ /**
+ * Stores the populate literate in a given language.
+ */
+ public static class LanguagePopulation implements
+ Comparable<LanguagePopulation> {
+ private final String language;
+ private final double literatePopulation;
+ private final boolean official;
+
+ public LanguagePopulation(String language, double literatePopulation,
+ boolean official) {
+ this.language = language;
+ this.literatePopulation = literatePopulation;
+ this.official = official;
+ }
+
+ public int compareTo(LanguagePopulation other) {
+ int c = -Double.compare(literatePopulation, other.literatePopulation);
+ if (c == 0) {
+ c = language.compareTo(other.language);
+ }
+ return c;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ LanguagePopulation other = (LanguagePopulation) obj;
+ return language.equals(other.language)
+ && (Double.compare(literatePopulation, other.literatePopulation) == 0);
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public double getLiteratePopulation() {
+ return literatePopulation;
+ }
+
+ @Override
+ public int hashCode() {
+ long temp = Double.doubleToLongBits(literatePopulation);
+ return language.hashCode() + 31 * (int) (temp ^ (temp >>> 32));
+ }
+
+ public boolean isOfficial() {
+ return official;
+ }
+
+ @Override
+ public String toString() {
+ return "[lang=" + language + " pop=" + literatePopulation + "]";
+ }
+ }
+
+ /**
+ * Stores the region populations literate in a given language.
+ */
+ public static class RegionPopulation implements Comparable<RegionPopulation> {
+ private final String region;
+ private final double literatePopulation;
+ private final boolean official;
+
+ public RegionPopulation(String region, double literatePopulation,
+ boolean official) {
+ this.region = region;
+ this.literatePopulation = literatePopulation;
+ this.official = official;
+ }
+
+ public int compareTo(RegionPopulation other) {
+ int c = -Double.compare(literatePopulation, other.literatePopulation);
+ if (c == 0) {
+ c = region.compareTo(other.region);
+ }
+ return c;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ RegionPopulation other = (RegionPopulation) obj;
+ return region.equals(other.region)
+ && (Double.compare(literatePopulation, other.literatePopulation) == 0);
+ }
+
+ public double getLiteratePopulation() {
+ return literatePopulation;
+ }
+
+ public String getRegion() {
+ return region;
+ }
+
+ @Override
+ public int hashCode() {
+ long temp = Double.doubleToLongBits(literatePopulation);
+ return region.hashCode() + 31 * (int) (temp ^ (temp >>> 32));
+ }
+
+ public boolean isOfficial() {
+ return official;
+ }
+
+ @Override
+ public String toString() {
+ return "[region=" + region + " pop=" + literatePopulation + "]";
+ }
+ }
+
+ private final Factory cldrFactory;
+
+ private Map<String, SortedSet<LanguagePopulation>> regionMap;
+ private Map<String, SortedSet<RegionPopulation>> languageMap;
+
+ public RegionLanguageData(Factory cldrFactory) {
+ this.cldrFactory = cldrFactory;
+ }
+
+ public Set<LanguagePopulation> getLanguages(String region) {
+ ensureMaps();
+ Set<LanguagePopulation> languageSet = regionMap.get(region);
+ if (languageSet == null) {
+ languageSet = Collections.emptySet();
+ }
+ return languageSet;
+ }
+
+ public Set<RegionPopulation> getRegions(String language) {
+ ensureMaps();
+ Set<RegionPopulation> regionSet = languageMap.get(language);
+ if (regionSet == null) {
+ regionSet = Collections.emptySet();
+ }
+ return regionSet;
+ }
+
+ private void ensureMaps() {
+ if (regionMap != null) {
+ return;
+ }
+ regionMap = new HashMap<String, SortedSet<LanguagePopulation>>();
+ languageMap = new HashMap<String, SortedSet<RegionPopulation>>();
+ CLDRFile supp = cldrFactory.make("supplementalData", true,
+ DraftStatus.approved);
+ XPathParts parts = new XPathParts();
+ Iterator<String> iterator = supp.iterator(
+ "//supplementalData/territoryInfo/territory");
+ while (iterator.hasNext()) {
+ String path = iterator.next();
+ parts.set(supp.getFullXPath(path));
+ String language = parts.findAttributeValue("languagePopulation", "type");
+ if (language == null) {
+ continue;
+ }
+ String territory = parts.findAttributeValue("territory", "type");
+ String literacyPercentStr = parts.findAttributeValue("territory",
+ "literacyPercent");
+ String populationStr = parts.findAttributeValue("territory",
+ "population");
+ String populationPercentStr = parts.findAttributeValue(
+ "languagePopulation", "populationPercent");
+ String statusStr = parts.findAttributeValue("languagePopulation",
+ "officialStatus");
+ double literacyPercent = Double.parseDouble(literacyPercentStr) * .01;
+ double population = Double.parseDouble(populationStr);
+ double populationPercent = Double.parseDouble(populationPercentStr) * .01;
+ double literatePopulation = population * populationPercent
+ * literacyPercent;
+ boolean official = "official".equals(statusStr);
+ SortedSet<RegionPopulation> regPop = languageMap.get(language);
+ if (regPop == null) {
+ regPop = new TreeSet<RegionPopulation>();
+ languageMap.put(language, regPop);
+ }
+ regPop.add(new RegionPopulation(territory, literatePopulation, official));
+ SortedSet<LanguagePopulation> langPop = regionMap.get(territory);
+ if (langPop == null) {
+ langPop = new TreeSet<LanguagePopulation>();
+ regionMap.put(territory, langPop);
+ }
+ langPop.add(new LanguagePopulation(language, literatePopulation,
+ official));
+ }
+ }
+}
diff --git a/tools/cldr-import/test/com/google/gwt/tools/cldr/LocaleDataTest.java b/tools/cldr-import/test/com/google/gwt/tools/cldr/LocaleDataTest.java
new file mode 100644
index 0000000..817139c
--- /dev/null
+++ b/tools/cldr-import/test/com/google/gwt/tools/cldr/LocaleDataTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.tools.cldr;
+
+import com.google.gwt.i18n.server.GwtLocaleFactoryImpl;
+import com.google.gwt.i18n.shared.GwtLocale;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Test the LocaleData class.
+ */
+public class LocaleDataTest extends TestCase {
+
+ private static final GwtLocaleFactoryImpl localeFactory;
+
+ static {
+ localeFactory = new GwtLocaleFactoryImpl();
+ }
+
+ /**
+ * Test method for {@link LocaleData#getAllLocales()}.
+ */
+ public void testGetAllLocales() {
+ LocaleData localeData = new LocaleData(localeFactory, Arrays.asList(
+ "root", "en", "en_US", "ar", "ar_IQ"));
+ Set<GwtLocale> locales = localeData.getAllLocales();
+ assertEquals(5, locales.size());
+ GwtLocale localeEn = localeFactory.fromString("en");
+ localeData.addEntry("foo", localeEn, "k1", "v1");
+ locales = localeData.getAllLocales();
+ assertEquals(5, locales.size());
+ GwtLocale localeAr = localeFactory.fromString("ar");
+ localeData.addEntry("bar", localeAr, "k1", "v1");
+ locales = localeData.getAllLocales();
+ assertEquals(5, locales.size());
+ }
+
+ /**
+ * Test method for {@link LocaleData#getNonEmptyLocales()}.
+ */
+ public void testGetNonEmptyLocales() {
+ LocaleData localeData = new LocaleData(localeFactory, Arrays.asList(
+ "root", "en", "en_US", "ar", "ar_IQ"));
+ Iterator<GwtLocale> it = localeData.getNonEmptyLocales().iterator();
+ assertFalse(it.hasNext());
+ GwtLocale localeEn = localeFactory.fromString("en");
+ localeData.addEntry("foo", localeEn, "k1", "v1");
+ it = localeData.getNonEmptyLocales().iterator();
+ assertTrue(it.hasNext());
+ assertEquals(localeEn, it.next());
+ assertFalse(it.hasNext());
+ GwtLocale localeAr = localeFactory.fromString("ar");
+ localeData.addEntry("bar", localeAr, "k1", "v1");
+ it = localeData.getNonEmptyLocales().iterator();
+ assertTrue(it.hasNext());
+ assertNotNull(it.next());
+ assertTrue(it.hasNext());
+ assertNotNull(it.next());
+ assertFalse(it.hasNext());
+ }
+
+ /**
+ * Test method for {@link LocaleData#getNonEmptyLocales(java.lang.String)}.
+ */
+ public void testGetNonEmptyLocalesString() {
+ LocaleData localeData = new LocaleData(localeFactory, Arrays.asList(
+ "root", "en", "en_US", "ar", "ar_IQ"));
+ Iterator<GwtLocale> it = localeData.getNonEmptyLocales("foo").iterator();
+ assertFalse(it.hasNext());
+ GwtLocale localeEn = localeFactory.fromString("en");
+ localeData.addEntry("foo", localeEn, "k1", "v1");
+ it = localeData.getNonEmptyLocales("foo").iterator();
+ assertTrue(it.hasNext());
+ assertEquals(localeEn, it.next());
+ assertFalse(it.hasNext());
+ it = localeData.getNonEmptyLocales("bar").iterator();
+ assertFalse(it.hasNext());
+ GwtLocale localeAr = localeFactory.fromString("ar");
+ localeData.addEntry("bar", localeAr, "k1", "v1");
+ it = localeData.getNonEmptyLocales("foo").iterator();
+ assertTrue(it.hasNext());
+ assertEquals(localeEn, it.next());
+ assertFalse(it.hasNext());
+ it = localeData.getNonEmptyLocales("bar").iterator();
+ assertTrue(it.hasNext());
+ assertEquals(localeAr, it.next());
+ assertFalse(it.hasNext());
+ it = localeData.getNonEmptyLocales("baz").iterator();
+ assertFalse(it.hasNext());
+ }
+
+ /**
+ * Test method for {@link LocaleData#inheritsFrom(com.google.gwt.i18n.shared.GwtLocale)}.
+ */
+ public void testInheritsFrom() {
+ LocaleData localeData = new LocaleData(localeFactory, Arrays.asList(
+ "root", "en", "en_US", "en_US_VARIANT", "ar", "ar_IQ"));
+ GwtLocale localeEn = localeFactory.fromString("en");
+ localeData.addEntry("foo", localeEn, "k1", "v1");
+ GwtLocale localeEnUs = localeFactory.fromString("en_us");
+ GwtLocale localeEnUsVariant = localeFactory.fromString("en_us_variant");
+ GwtLocale localeDefault = localeFactory.getDefault();
+ assertEquals(null, localeData.inheritsFrom(localeDefault));
+ assertEquals(localeEn, localeData.inheritsFrom(localeEnUs));
+ assertEquals(localeEn, localeData.inheritsFrom(localeEnUsVariant));
+ assertEquals(localeDefault, localeData.inheritsFrom(localeEn));
+ GwtLocale localeAr = localeFactory.fromString("ar");
+ assertEquals(localeDefault, localeData.inheritsFrom(localeAr));
+ }
+
+ /**
+ * Test method for {@link LocaleData#inheritsFrom(java.lang.String, com.google.gwt.i18n.shared.GwtLocale)}.
+ */
+ public void testInheritsFromWithCategory() {
+ LocaleData localeData = new LocaleData(localeFactory, Arrays.asList(
+ "root", "en", "en_US", "en_US_VARIANT", "ar", "ar_IQ"));
+ GwtLocale localeEn = localeFactory.fromString("en");
+ localeData.addEntry("foo", localeEn, "k1", "v1");
+ GwtLocale localeEnUs = localeFactory.fromString("en_us");
+ GwtLocale localeEnUsVariant = localeFactory.fromString("en_us_variant");
+ GwtLocale localeDefault = localeFactory.getDefault();
+ assertEquals(localeEn, localeData.inheritsFrom("foo", localeEnUs));
+ assertEquals(localeEn, localeData.inheritsFrom("foo", localeEnUsVariant));
+ assertEquals(localeDefault, localeData.inheritsFrom("foo", localeEn));
+ assertEquals(localeDefault, localeData.inheritsFrom("bar", localeEnUs));
+ assertEquals(localeDefault, localeData.inheritsFrom("bar", localeEnUsVariant));
+ GwtLocale localeAr = localeFactory.fromString("ar");
+ assertEquals(localeDefault, localeData.inheritsFrom("foo", localeAr));
+ assertEquals(localeDefault, localeData.inheritsFrom("bar", localeAr));
+ }
+
+ /**
+ * Test method for {@link LocaleData#removeCompleteDuplicates()}.
+ */
+ public void testRemoveCompleteDuplicates() {
+ LocaleData localeData = new LocaleData(localeFactory, Arrays.asList(
+ "root", "en", "en_US", "ar", "ar_IQ"));
+ GwtLocale localeEn = localeFactory.fromString("en");
+ GwtLocale localeEnUs = localeFactory.fromString("en_us");
+ localeData.addEntry("foo", localeEn, "k1", "v1");
+ localeData.addEntry("foo", localeEn, "k2", "v2");
+ localeData.addEntry("foo", localeEnUs, "k1", "v1");
+ localeData.addEntry("foo", localeEnUs, "k2", "v2");
+ localeData.removeCompleteDuplicates();
+ Set<GwtLocale> locales = localeData.getNonEmptyLocales();
+ assertEquals(1, locales.size());
+ localeData.addEntry("foo", localeEnUs, "k2", "v2a");
+ locales = localeData.getNonEmptyLocales();
+ assertEquals(2, locales.size());
+ }
+
+ /**
+ * Test method for {@link LocaleData#removeDuplicates()}.
+ */
+ public void testRemoveDuplicates() {
+ LocaleData localeData = new LocaleData(localeFactory, Arrays.asList(
+ "root", "en", "en_US", "ar", "ar_IQ"));
+ GwtLocale localeEn = localeFactory.fromString("en");
+ GwtLocale localeEnUs = localeFactory.fromString("en_us");
+ localeData.addEntry("foo", localeEn, "k1", "v1");
+ localeData.addEntry("foo", localeEn, "k2", "v2");
+ localeData.addEntry("foo", localeEnUs, "k1", "v1");
+ localeData.addEntry("foo", localeEnUs, "k2", "v2a");
+ localeData.removeDuplicates();
+ Set<GwtLocale> locales = localeData.getNonEmptyLocales();
+ assertEquals(2, locales.size());
+ assertEquals("v2a", localeData.getEntry("foo", localeEnUs, "k2"));
+ localeData.addEntry("foo", localeEnUs, "k2", "v2");
+ localeData.removeDuplicates();
+ locales = localeData.getNonEmptyLocales();
+ assertEquals(1, locales.size());
+ assertNull(localeData.getEntry("foo", localeEnUs, "k2"));
+ }
+}
diff --git a/user/src/com/google/gwt/i18n/rebind/DateTimePatternGenerator.java b/user/src/com/google/gwt/i18n/rebind/DateTimePatternGenerator.java
index b84d04a..66269a2 100644
--- a/user/src/com/google/gwt/i18n/rebind/DateTimePatternGenerator.java
+++ b/user/src/com/google/gwt/i18n/rebind/DateTimePatternGenerator.java
@@ -23,7 +23,7 @@
* Helper class to create a localized date/time pattern based on a pattern
* skeleton.
*/
-class DateTimePatternGenerator {
+public class DateTimePatternGenerator {
// TODO(jat): Currently uses ICU4J's DateTimePatternGenerator, but should
// probably be rewritten to avoid that dependency.
diff --git a/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java b/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
index b5e1729..0168f07 100644
--- a/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
+++ b/user/src/com/google/gwt/i18n/rebind/MessagesMethodCreator.java
@@ -403,130 +403,6 @@
}
/**
- * Helper class to produce string expressions consisting of literals and
- * computed values.
- */
- private static class StringGenerator {
-
- /**
- * Output string buffer.
- */
- private StringBuffer buf;
-
- /**
- * True if we are in the middle of a string literal.
- */
- private boolean inString;
-
- /**
- * True if the method's return type is SafeHtml (and SafeHtmlBuilder is to
- * be used to generate the expression); otherwise a String expression is
- * generated.
- */
- private final boolean returnsSafeHtml;
-
- /**
- * Initialize the StringGenerator with an output buffer.
- *
- * @param buf output buffer
- * @param returnsSafeHtml if true, an expression of type {@link SafeHtml} is
- * being generated, otherwise a {@link String}-valued expression is
- * generated
- */
- public StringGenerator(StringBuffer buf, boolean returnsSafeHtml) {
- this.buf = buf;
- inString = false;
- this.returnsSafeHtml = returnsSafeHtml;
- if (returnsSafeHtml) {
- buf.append("new " + SAFE_HTML_BUILDER_FQCN + "()");
- } else {
- buf.append("new java.lang.StringBuffer()");
- }
- }
-
- /**
- * Append an expression to this string expression.
- *
- * @param expression to add
- * @param isSafeHtmlTyped true if the expression is known to be of type
- * {@link SafeHtml}; only relevant if this generator has been
- * initialized to generate a {@link SafeHtml}-valued expression
- * @param isPrimititiveTyped true if the expression is of a primitive type;
- * only relevant if this generator has been initialized to generate
- * a {@link SafeHtml}-valued expression
- * @param needsConversionToString true if the expression is not known to be
- * of type String and needs to be converted
- */
- public void appendExpression(String expression, boolean isSafeHtmlTyped,
- boolean isPrimititiveTyped, boolean needsConversionToString) {
- if (inString) {
- buf.append("\")");
- inString = false;
- }
- /*
- * SafeHtmlBuilder has append() methods for primitive types as well as for
- * SafeHtml-valued expressions. For all other expression types, use
- * appendEscaped(). In addition, if the expression is not known to be of
- * type String, covert to String.
- */
- if (returnsSafeHtml && !isSafeHtmlTyped && !isPrimititiveTyped) {
- buf.append(".appendEscaped(");
- if (needsConversionToString) {
- buf.append("String.valueOf(");
- }
- } else {
- buf.append(".append(");
- }
- buf.append(expression);
- buf.append(")");
- if (returnsSafeHtml && !isSafeHtmlTyped && !isPrimititiveTyped
- && needsConversionToString) {
- buf.append(")");
- }
- }
-
- /**
- * Append part of a string literal.
- *
- * @param str part of string literal
- */
- public void appendStringLiteral(String str) {
- if (!inString) {
- if (returnsSafeHtml) {
- buf.append(".appendHtmlConstant(\"");
- } else {
- buf.append(".append(\"");
- }
- inString = true;
- }
- buf.append(str);
- }
-
- /**
- * Append an expression to this string expression.
- *
- * @param expression to add, which the caller asserts is String-valued
- */
- public void appendStringValuedExpression(String expression) {
- appendExpression(expression, false, false, false);
- }
-
- /**
- * Complete the string, closing an open quote and handling empty strings.
- */
- public void completeString() {
- if (inString) {
- buf.append("\")");
- }
- if (returnsSafeHtml) {
- buf.append(".toSafeHtml()");
- } else {
- buf.append(".toString()");
- }
- }
- }
-
- /**
* Implements {x,time...} references in MessageFormat.
*/
private static class TimeFormatter implements ValueFormatter {
diff --git a/user/src/com/google/gwt/i18n/rebind/StringGenerator.java b/user/src/com/google/gwt/i18n/rebind/StringGenerator.java
new file mode 100644
index 0000000..1200220
--- /dev/null
+++ b/user/src/com/google/gwt/i18n/rebind/StringGenerator.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.i18n.rebind;
+
+/**
+ * Helper class to produce string expressions consisting of literals and
+ * computed values.
+ */
+public class StringGenerator {
+
+ /**
+ * Output string buffer.
+ */
+ private StringBuffer buf;
+
+ /**
+ * True if we are in the middle of a string literal.
+ */
+ private boolean inString;
+
+ /**
+ * True if the method's return type is SafeHtml (and SafeHtmlBuilder is to
+ * be used to generate the expression); otherwise a String expression is
+ * generated.
+ */
+ private final boolean returnsSafeHtml;
+
+ /**
+ * Initialize the StringGenerator with an output buffer.
+ *
+ * @param buf output buffer
+ * @param returnsSafeHtml if true, an expression of type {@link SafeHtml} is
+ * being generated, otherwise a {@link String}-valued expression is
+ * generated
+ */
+ public StringGenerator(StringBuffer buf, boolean returnsSafeHtml) {
+ this.buf = buf;
+ inString = false;
+ this.returnsSafeHtml = returnsSafeHtml;
+ if (returnsSafeHtml) {
+ buf.append("new " + MessagesMethodCreator.SAFE_HTML_BUILDER_FQCN + "()");
+ } else {
+ buf.append("new java.lang.StringBuffer()");
+ }
+ }
+
+ /**
+ * Append an expression to this string expression.
+ *
+ * @param expression to add
+ * @param isSafeHtmlTyped true if the expression is known to be of type
+ * {@link SafeHtml}; only relevant if this generator has been
+ * initialized to generate a {@link SafeHtml}-valued expression
+ * @param isPrimititiveTyped true if the expression is of a primitive type;
+ * only relevant if this generator has been initialized to generate
+ * a {@link SafeHtml}-valued expression
+ * @param needsConversionToString true if the expression is not known to be
+ * of type String and needs to be converted
+ */
+ public void appendExpression(String expression, boolean isSafeHtmlTyped,
+ boolean isPrimititiveTyped, boolean needsConversionToString) {
+ if (inString) {
+ buf.append("\")");
+ inString = false;
+ }
+ /*
+ * SafeHtmlBuilder has append() methods for primitive types as well as for
+ * SafeHtml-valued expressions. For all other expression types, use
+ * appendEscaped(). In addition, if the expression is not known to be of
+ * type String, covert to String.
+ */
+ if (returnsSafeHtml && !isSafeHtmlTyped && !isPrimititiveTyped) {
+ buf.append(".appendEscaped(");
+ if (needsConversionToString) {
+ buf.append("String.valueOf(");
+ }
+ } else {
+ buf.append(".append(");
+ }
+ buf.append(expression);
+ buf.append(")");
+ if (returnsSafeHtml && !isSafeHtmlTyped && !isPrimititiveTyped
+ && needsConversionToString) {
+ buf.append(")");
+ }
+ }
+
+ /**
+ * Append part of a string literal.
+ *
+ * @param str part of string literal
+ */
+ public void appendStringLiteral(String str) {
+ if (!inString) {
+ if (returnsSafeHtml) {
+ buf.append(".appendHtmlConstant(\"");
+ } else {
+ buf.append(".append(\"");
+ }
+ inString = true;
+ }
+ buf.append(str);
+ }
+
+ /**
+ * Append an expression to this string expression.
+ *
+ * @param expression to add, which the caller asserts is String-valued
+ */
+ public void appendStringValuedExpression(String expression) {
+ appendExpression(expression, false, false, false);
+ }
+
+ /**
+ * Complete the string, closing an open quote and handling empty strings.
+ */
+ public void completeString() {
+ if (inString) {
+ buf.append("\")");
+ }
+ if (returnsSafeHtml) {
+ buf.append(".toSafeHtml()");
+ } else {
+ buf.append(".toString()");
+ }
+ }
+}