1616package com .google .gwt .i18n .rebind ;
1717
1818import com .google .gwt .i18n .client .Messages ;
19- import com .google .gwt .i18n .rebind .MessageFormatParser .ArgumentChunk ;
20- import com .google .gwt .i18n .rebind .MessageFormatParser .TemplateChunk ;
19+ import com .google .gwt .i18n .server .MessageFormatUtils ;
20+ import com .google .gwt .i18n .server .MessageFormatUtils .ArgumentChunk ;
21+ import com .google .gwt .i18n .server .MessageFormatUtils .TemplateChunk ;
22+
23+ import org .apache .tapestry .util .text .LocalizedProperties ;
2124
2225import java .io .File ;
2326import java .io .IOException ;
2427import java .text .ParseException ;
25- import java .util .HashSet ;
26- import java .util .Set ;
28+ import java .util .Collections ;
29+ import java .util .HashMap ;
30+ import java .util .Map ;
2731
2832/**
2933 * Creates a MessagesInterface from a Resource file.
@@ -32,22 +36,21 @@ public class MessagesInterfaceCreator extends
3236 AbstractLocalizableInterfaceCreator {
3337
3438 /**
35- * Searches for MessageFormat-style args in the template string and returns
36- * a set of argument indices seen.
39+ * Searches for MessageFormat-style args in the template string and returns a map of of argument
40+ * indices seen.
3741 *
3842 * @param template template to parse
3943 * @return set of argument indices seen
4044 * @throws ParseException if the template is incorrect.
4145 */
42- private static Set <Integer > numberOfMessageArgs (String template )
43- throws ParseException {
44- Set <Integer > seenArgs = new HashSet <Integer >();
45- for (TemplateChunk chunk : MessageFormatParser .parse (template )) {
46+ private static Map <Integer , ArgumentChunk > getMessageArgs (String template ) throws ParseException {
47+ HashMap <Integer , ArgumentChunk > args = new HashMap <>();
48+ for (TemplateChunk chunk : MessageFormatUtils .MessageStyle .MESSAGE_FORMAT .parse (template )) {
4649 if (chunk instanceof ArgumentChunk ) {
47- seenArgs . add (((ArgumentChunk ) chunk ).getArgumentNumber ());
50+ args . put (((ArgumentChunk ) chunk ).getArgumentNumber (), ( ArgumentChunk ) chunk );
4851 }
4952 }
50- return seenArgs ;
53+ return args ;
5154 }
5255
5356 /**
@@ -65,28 +68,61 @@ public MessagesInterfaceCreator(String className, String packageName,
6568 Messages .class );
6669 }
6770
71+ @ Override
72+ void generateMethods (LocalizedProperties properties , String [] keys ) {
73+ for (int i = 0 ; i < keys .length ; i ++) {
74+ String key = keys [i ];
75+ String value = properties .getProperty (key );
76+ Map <String , String > plurals = new HashMap <>();
77+ while (i + 1 < keys .length && isNextPlural (key , keys [i + 1 ])) {
78+ i ++;
79+ plurals .put (keys [i ], properties .getProperty (keys [i ]));
80+ }
81+ genMethodDecl (value , key , plurals );
82+ }
83+ }
84+
6885 @ Override
6986 protected void genMethodArgs (String defaultValue ) {
70- try {
71- Set <Integer > seenArgs = numberOfMessageArgs (defaultValue );
72- int maxArgSeen = -1 ;
73- for (int arg : seenArgs ) {
74- if (arg > maxArgSeen ) {
75- maxArgSeen = arg ;
76- }
87+ }
88+
89+ private boolean isNextPlural (String key , String nextKey ) {
90+ return nextKey .matches (key + "\\ [.*\\ ]" );
91+ }
92+
93+ private void genMethodArgs (Map <Integer , ArgumentChunk > args ) {
94+ for (int i = 0 ; i <= Collections .max (args .keySet ()); i ++) {
95+ if (i > 0 ) {
96+ composer .print (", " );
7797 }
78- for (int i = 0 ; i <= maxArgSeen ; i ++) {
79- if (i > 0 ) {
80- composer .print (", " );
81- }
82- if (!seenArgs .contains (i )) {
83- composer .print ("@Optional " );
84- }
85- composer .print ("String arg" + i );
98+ if (!args .containsKey (i )) {
99+ composer .print ("@Optional String arg" + i );
100+ continue ;
86101 }
87- } catch (ParseException e ) {
88- throw new RuntimeException (defaultValue
89- + " could not be parsed as a MessageFormat string." , e );
102+ String format = (format = args .get (i ).getFormat ()) != null ? format : "string" ;
103+ String subFormat = (subFormat = args .get (i ).getSubFormat ()) != null ? subFormat : "" ;
104+ if (args .get (i ).isList ()) {
105+ composer .print ("java.util.List<" );
106+ }
107+ switch (format ) {
108+ case "number" :
109+ determineNumberType (subFormat );
110+ break ;
111+ case "date" :
112+ case "time" :
113+ case "localdatetime" :
114+ composer .print ("java.util.Date" );
115+ break ;
116+ case "safehtml" :
117+ composer .print ("com.google.gwt.safehtml.shared.SafeHtml" );
118+ break ;
119+ default :
120+ composer .print ("String" );
121+ }
122+ if (args .get (i ).isList ()) {
123+ composer .print (">" );
124+ }
125+ composer .print (" arg" + i );
90126 }
91127 }
92128
@@ -100,4 +136,99 @@ protected String javaDocComment(String path) {
100136 return "Interface to represent the messages contained in resource bundle:\n \t "
101137 + path + "'." ;
102138 }
139+
140+ private void determineNumberType (String subFormat ) {
141+ switch (subFormat ) {
142+ case "integer" :
143+ composer .print ("Integer" );
144+ break ;
145+ case "currency" :
146+ case "percent" :
147+ default :
148+ if (subFormat .contains ("." )) {
149+ composer .print ("Double" );
150+ } else {
151+ composer .print ("Integer" );
152+ }
153+ }
154+ }
155+
156+ private String determineReturnType (Map <Integer , ArgumentChunk > args ) {
157+ for (ArgumentChunk arg : args .values ()) {
158+ if ("safehtml" .equals (arg .getFormat ())) {
159+ return "com.google.gwt.safehtml.shared.SafeHtml" ;
160+ }
161+ }
162+ return "String" ;
163+ }
164+
165+ private void genPluralsAnnotation (Map <String , String > plurals ) {
166+ composer .print ("@AlternateMessage({" );
167+ String [] keys = plurals .keySet ().toArray (new String [] {});
168+ if (keys .length > 1 ) {
169+ composer .println ();
170+ composer .indent ();
171+ }
172+ for (int i = 0 ; i < keys .length ; i ++) {
173+ String key = keys [i ];
174+ if (i > 0 ) {
175+ composer .println ("," );
176+ }
177+ composer .print ("\" " );
178+ composer .print (key .substring (key .indexOf ('[' ) + 1 , key .length () - 1 ));
179+ composer .print ("\" , \" " );
180+ composer .print (makeJavaString (plurals .get (key )));
181+ composer .println ("\" " );
182+ }
183+ if (keys .length > 1 ) {
184+ composer .println ();
185+ composer .outdent ();
186+ }
187+ composer .println ("})" );
188+ }
189+
190+ private void genMethodDecl (String defaultValue , String key , Map <String , String > plurals ) {
191+ try {
192+ Map <Integer , ArgumentChunk > args = getMessageArgs (defaultValue );
193+ genMethodJavaDoc (defaultValue , args );
194+ genValueAnnotation (defaultValue );
195+ if (!plurals .isEmpty ()) {
196+ genPluralsAnnotation (plurals );
197+ }
198+ composer .println ("@Key(" + makeJavaString (key ) + ")" );
199+ String methodName = formatKey (key );
200+ String type = determineReturnType (args );
201+ composer .print (type + " " + methodName );
202+ composer .print ("(" );
203+ if (!plurals .isEmpty ()) {
204+ composer .print ("@PluralCount " );
205+ }
206+ if (!args .isEmpty ()) {
207+ genMethodArgs (args );
208+ }
209+ composer .print (");\n " );
210+ } catch (ParseException e ) {
211+ throw new RuntimeException (defaultValue + " could not be parsed as a MessageFormat string." ,
212+ e );
213+ }
214+ }
215+
216+ private void genMethodJavaDoc (String defaultValue , Map <Integer , ArgumentChunk > args ) {
217+ composer .beginJavaDocComment ();
218+ String escaped = makeJavaString (defaultValue );
219+ composer .println ("Translated " + escaped + ".\n " );
220+ if (!args .isEmpty ()) {
221+ for (int i = 0 ; i <= Collections .max (args .keySet ()); i ++) {
222+ composer .print ("@param arg" + i );
223+ if (args .containsKey (i )) {
224+ composer .println (" " + makeJavaString (args .get (i ).getAsMessageFormatString ()));
225+ } else {
226+ composer .println (" optional" );
227+ }
228+ }
229+ }
230+ composer .println ("@return translated " + escaped );
231+ composer .endJavaDocComment ();
232+ }
233+
103234}
0 commit comments