简体   繁体   English

自定义资源密钥生成,以促进向后兼容

[英]Custom resource key generation to facilitate backwards compatibility

I just recently discovered that you can change the key of a resource from the default "method name" method to a customly specified key. 我最近才发现,您可以将资源的密钥从默认的“方法名称”方法更改为自定义的密钥。

I'm now thinking of switching the format to a "dot separated" format (which is usually used in Java projects). 我现在正在考虑将格式切换为“点分隔”格式(通常在Java项目中使用)。

I know, this can be achieved by either using the @Key("my.new.key") annotation or by providing a custom KeyGenerator using the @GenerateKeys annotation. 我知道,这可以通过使用@Key("my.new.key")注释或使用@GenerateKeys注释提供自定义KeyGenerator来实现。

The problem is, that I'm searching for a solution that supports my new format as well as the old format. 问题是,我正在寻找一种支持我的新格式和旧格式的解决方案。 This is needed for backwards compatibility. 这是向后兼容所必需的。 I release my tool to the public and they can provide their own properties files (with their custom content). 我向公众发布了我的工具,他们可以提供自己的属性文件(及其自定义内容)。 This means that I'm not able to change their keys to match my new format. 这意味着我无法更改其键以匹配我的新格式。

I'm now looking for a solution that uses the new key (if available) and falls back to the old key if necessary. 我现在正在寻找一种使用新密钥(如果有)并在必要时使用旧密钥的解决方案。

I thought I was being clever and came up with this KeyGenerator : 我以为我很聪明,因此想出了这个KeyGenerator

public class MyKeyGenerator implements KeyGenerator
{
    private PropertyResourceBundle bundle;

    @Override
    public String generateKey(Message msg)
    {
        if(bundle == null)
        {
            try
            {
                File file = urlToResourceFile(Text.class.getName()); /* Finds the properties file */
                bundle = new PropertyResourceBundle(new FileInputStream(file));
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }

        String key = msg.getKey();

        if(key != null)
        {
            if(bundle.containsKey(key))
                return key;
        }

        return msg.getMethodName();
    }
}

Which will check if the new key exists in the properties file. 它将检查属性文件中是否存在新密钥。 If so, return it, if not return the old key. 如果是这样,则返回它,如果不返回旧密钥。

What I receive however, is this error: 但是,我收到的是以下错误:

Computing all possible rebind results for 'my.package.here.i18n.Text'
        Rebinding my.package.here.i18n.Text
        Invoking generator com.google.gwt.i18n.rebind.LocalizableGenerator
            Processing interface my.package.here.i18n.Text
                Generating method body for generalSuccess()
                    [ERROR] No resource found for key 'general.success'
com.google.gwt.i18n.rebind.AbstractResource$MissingResourceException: No resource found for key 'general.success'
    at com.google.gwt.i18n.rebind.MessagesMethodCreator.createMethodFor(MessagesMethodCreator.java:1086)
    at com.google.gwt.i18n.rebind.AbstractLocalizableImplCreator.delegateToCreator(AbstractLocalizableImplCreator.java:501)
    at com.google.gwt.i18n.rebind.MessagesImplCreator.emitMethodBody(MessagesImplCreator.java:92)
    at com.google.gwt.user.rebind.AbstractGeneratorClassCreator.genMethod(AbstractGeneratorClassCreator.java:277)
    at com.google.gwt.user.rebind.AbstractGeneratorClassCreator.emitMethods(AbstractGeneratorClassCreator.java:239)
    at com.google.gwt.user.rebind.AbstractGeneratorClassCreator.emitClass(AbstractGeneratorClassCreator.java:118)
    at com.google.gwt.i18n.rebind.AbstractLocalizableImplCreator.generateConstantOrMessageClass(AbstractLocalizableImplCreator.java:225)
    at com.google.gwt.i18n.rebind.LocalizableGenerator.generate(LocalizableGenerator.java:151)
    at com.google.gwt.i18n.rebind.LocalizableGenerator.generate(LocalizableGenerator.java:124)
    at com.google.gwt.core.ext.IncrementalGenerator.generateNonIncrementally(IncrementalGenerator.java:40)
    at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:676)
    at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:41)
    at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:79)
    at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:276)
    at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:265)
    at com.google.gwt.dev.DistillerRebindPermutationOracle.getAllPossibleRebindAnswers(DistillerRebindPermutationOracle.java:91)
    at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.handleGwtCreate(UnifyAst.java:387)
    at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.handleMagicMethodCall(UnifyAst.java:465)
    at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.endVisit(UnifyAst.java:255)
    at com.google.gwt.dev.jjs.ast.JMethodCall.traverse(JMethodCall.java:244)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
    at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:117)
    at com.google.gwt.dev.jjs.ast.JCastOperation.traverse(JCastOperation.java:65)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
    at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:117)
    at com.google.gwt.dev.jjs.ast.JDeclarationStatement.traverse(JDeclarationStatement.java:48)
    at com.google.gwt.dev.jjs.ast.JModVisitor$ListContextImmutable.traverse(JModVisitor.java:170)
    at com.google.gwt.dev.jjs.ast.JModVisitor.acceptWithInsertRemoveImmutable(JModVisitor.java:336)
    at com.google.gwt.dev.jjs.ast.JBlock.traverse(JBlock.java:83)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:138)
    at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:134)
    at com.google.gwt.dev.jjs.ast.JMethodBody.traverse(JMethodBody.java:82)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
    at com.google.gwt.dev.jjs.ast.JMethod.visitChildren(JMethod.java:449)
    at com.google.gwt.dev.jjs.ast.JMethod.traverse(JMethod.java:418)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
    at com.google.gwt.dev.jjs.impl.UnifyAst.mainLoop(UnifyAst.java:940)
    at com.google.gwt.dev.jjs.impl.UnifyAst.exec(UnifyAst.java:665)
    at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.precompile(JavaToJavaScriptCompiler.java:672)
    at com.google.gwt.dev.jjs.JavaScriptCompiler.precompile(JavaScriptCompiler.java:34)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:271)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:223)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:139)
    at com.google.gwt.dev.Compiler.run(Compiler.java:167)
    at com.google.gwt.dev.Compiler.run(Compiler.java:132)
    at com.google.gwt.dev.Compiler$1.run(Compiler.java:99)
    at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:55)
    at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:50)
    at com.google.gwt.dev.Compiler.main(Compiler.java:106)

Which seems to suggest, that my KeyGenerator is either only used if @Key isn't present or that this GWT check is performed before my KeyGenerator is executed. 这似乎表明,我的KeyGenerator仅在不存在@Key使用,或者在执行KeyGenerator之前执行了GWT检查。

Does anyone know how to solve this? 有谁知道如何解决这个问题? Or maybe someone knows another solution? 也许有人知道另一种解决方案?

UPDATE UPDATE

Just found this here : 刚刚在这里找到这个:

@Key(String key)

Specifies the key to use in the external format for this particular method. 指定用于此特定方法的外部格式的键。 If not supplied , it will be generated based on the @GenerateKeys annotation, discussed above. 如果未提供 ,它将根据上面讨论的@GenerateKeys注释生成。

Which seems to make my goal unreachable... Any other suggestions? 哪个似乎无法实现我的目标?还有其他建议吗?

Your goal may not be unreachable, but it is certainly not a easy one. 您的目标可能并非遥不可及,但绝对不是一件容易的事。 While GWT-compile the com.google.gwt.i18n.rebind.LocalizableGenerator is invoked and performs its I18N-magic. 在GWT编译时, com.google.gwt.i18n.rebind.LocalizableGenerator会被调用并执行其I18N魔术。 This involves checking the keys which is causing the stated exception. 这涉及检查导致所述异常的密钥。 The good news is that generator are very powerful and you can roll your custom implementation. 好消息是生成器非常强大,您可以滚动自定义实现。 The bad news is that generators are somewhat complicate to write and not very well documented. 坏消息是,生成器编写起来有些复杂,而且没有很好的文档记录。 The official documentation mentions generators just briefly. 官方文档仅简要提到了生成器。

So in a first attempt I would suggest to replace the default LocalizableGenerator with your own version. 因此,在第一次尝试中,我建议用您自己的版本替换默认的LocalizableGenerator In your own version of the generator you can then suppress the exception and add your own resource loading logic (you may end up overriding some more classes...). 然后,在您自己的生成器版本中,您可以抑制该异常并添加您自己的资源加载逻辑(您可能最终会覆盖更多的类...)。 I'm quite sure you can override what generator is called in your local module configuration (the XML file). 我非常确定您可以覆盖在本地模块配置(XML文件)中调用的生成器。 Although I have not tried it. 虽然我还没有尝试过。

If that fails, the only option I see is to run your own I18N implementation. 如果失败,我看到的唯一选择是运行您自己的I18N实现。 I mean a complete one, your own annotations with custom generators and linkers to create the necessary output... 我的意思是说完整的,带有定制生成器和链接器的您自己的注释,以创建必要的输出...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM