GWT Maven插件:在Messages类中生成非String参数

时间:2011-10-21 19:35:04

标签: java gwt maven

我的“Messages.properties”文件中有一个属性,它有一个使用数字格式的参数:

my.message=File exceeds {0,number,0.0}MB.

当我运行gwt:i18n Maven目标时,它会根据我的“Messages.properties”文件中的属性生成Messages接口(正常情况下):

public interface Messages extends com.google.gwt.i18n.client.Messages {
  //...

  @DefaultMessage("File exceeds {0,number,0.0}MB.")
  @Key("my.message")
  String my_message(String arg0);

  //...
}

问题是方法参数是String。当我运行应用程序时,它给了我一个错误,因为message参数需要一个数字,但提供了一个String(错误消息是,“只有数字子类可以被格式化为数字”)。

如何配置Maven将此参数更改为数字(如floatNumber)?感谢。

2 个答案:

答案 0 :(得分:2)

鉴于上述讨论,我决定补充我以前的答案。 首先,据我所知,你无法使用现有的i18n Maven目标(和GWT的I18NCreator)来做所谓的事情。 其次,在对我建议的Generator解决方案进行了更多研究之后,我发现:

  • 迈克尔是对的,你不会在编译时使用接口方法来查找错误,如上所述查找属性(GWT中的一个罪)。但是,这仍然是最简单/最快捷的方式。
  • 您可以通过编写自己的接口来确保编译时检查 与属性文件保持同步,为每个属性提供一种方法,然后获取您的属性 生成器来编写实现该接口的类。注意 当您更改属性文件上的属性时,您只需要 改变你写的界面。如果你写过发电机 没问题,它永远不会再被改变!最好的方式去 关于方法名称可能遵循GWT:如果调用属性 the.prop.one,然后方法名称为the_prop_one(..)。
  • 如果你真的不想手动维护界面,那就是唯一的 我能看到的方法是你自己编写的I18NCreator版本。 这是因为maven目标i18n不是GWT编译器 参数,但是要求maven插件写入 消息/常量接口基于在中找到的属性文件 阶级路径。因此,如果您编写自己的I18NCreator,您将会 还必须编写一个Maven插件,您可以使用它来调用它 编译GWT应用程序。或者,为了简单起见,你可以简单地说 手动运行你的I18NCreator(使用古老的java命令运行) 它)每次更改属性文件键(当然,
    只更改实际消息时无需运行它。

就个人而言,我只会编写和维护我的属性文件以及手动镜像它的界面。生成器将始终查看属性文件并生成与属性对应的方法(根据实际消息需要任何参数),因此如果您编写的接口反映了属性文件,则生成器生成的类将始终正确实施。

答案 1 :(得分:1)

在我看来,GWT I18NCreator不支持此功能(这是maven i18n目标所称的)。你必须编写自己的Generator才能做到这一点。 我写了几个发电机,并没有你想象的那么难。 在您的情况下,您可能希望编写一个生成器,该生成器创建类似于GWT的消息的接口实例(但您可以使用自己的消息)但在解码消息时具有所需的附加功能。 以下如何使用小指南可能会对您有所帮助,因为它似乎也是我所做的,它也起作用:

http://groups.google.com/group/Google-Web-Toolkit/msg/ae249ea67c2c3435?pli=1

我发现编写GWT生成器的最简单方法是实际编写一个测试类,其中包含您希望在IDE中生成的代码(并借助自动完成,语法检查等),然后再过去/适应这样的作家调用:

writer.println("public void doSomething() { /* implement */ }");

并且不要忘记告诉你的模块(module.gwt.xml文件)需要生成哪个接口,以及使用哪个类:

<generate-with  class="mycompany.utils.generators.MyGenerator">
    <when-type-assignable class="mycompany.messages.MyCoolPropertiesReader" />
</generate-with>

在Generator代码中,您可以使用Java及其所有强大功能(不限于GWT可翻译代码),因此实现您想要的并不困难。在客户端代码中,您可以执行以下操作:

public interface MyCoolPropertiesReader {
  public String getMessage(String propKey, Object... parameters);
}

public class MyClientSideClass {
  MyCoolPropertiesReader reader = GWT.create(MyCoolPropertiesReader.class);
  String msg = reader.getMessage("my.message", 10);
  // do more work
}

我写的一个测试生成器(一个GWT“反射”的getter和setter,就像这样)看起来像这样:

public class TestGenerator extends Generator {

@Override
public String generate(TreeLogger logger, GeneratorContext context,
  String typeName) throws UnableToCompleteException {
  try {
    TypeOracle oracle = context.getTypeOracle();
    JClassType requestedClass = oracle.getType(typeName);
    String packageName = requestedClass.getPackage().getName();
    String simpleClassName = requestedClass.getSimpleSourceName();
    String proxyClassName = simpleClassName + "GetterAndSetter";
    String qualifiedProxyClassName = packageName + "." + proxyClassName;
    System.out.println("Created a class called: " + qualifiedProxyClassName);

    PrintWriter printWriter = context.tryCreate(logger, packageName, className);
    if (printWriter == null) return null;
      ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(packageName, className);
      composerFactory.addImport("test.project.shared.GetterAndSetter");
      composerFactory.addImplementedInterface("GetterAndSetter<" + underlyingTypeName + ">");
      SourceWriter writer = composerFactory.createSourceWriter(context, printWriter);
      if (writer != null) {
        JField[] fields = requestedClass.getFields();
        for (JField field : fields) {
          createSetterMethodForField(typeName, writer, field);
        }
        writer.indent();
        writer.println("public void set(" + typeName + " target, String path, Object value) {");
        writer.indent();
        createIfBlockForFields(writer, fields, true);
        writer.outdent();
        writer.println("}");
        writer.println();
        writer.println("public <K> K get(" + typeName + " target, String path) {");
        writer.indent();
        createIfBlockForFields(writer, fields, false);
        writer.outdent();
        writer.println("}");
        writer.println();
        writer.outdent();
        writer.commit(logger);
      }
      return packageName + "." + proxyClassName;
    } catch(NotFoundException nfe) {
      throw new UnableToCompleteException();
    }
  }
}

我希望这会对你有所帮助。