From 38af61593702cd0fd5634667a51170cc3ae8cd5b Mon Sep 17 00:00:00 2001 From: Bertrand Lorentz Date: Tue, 2 Apr 2024 15:40:16 +0200 Subject: [PATCH] Add method overloads to support using qualifiers for SDK components This adds a "qualifier" parameter in several methods in the TranslatorDependencyFactory interface, so implementers must be updated. Update DependencyFactoryMock in the unit tests accordingly. --- .../ted/eforms/sdk/ComponentFactory.java | 75 +++++++++++++++++-- .../efx/component/EfxTranslatorFactory.java | 34 +++++++-- .../TranslatorDependencyFactory.java | 9 ++- .../ted/efx/mock/DependencyFactoryMock.java | 17 ++--- 4 files changed, 110 insertions(+), 25 deletions(-) diff --git a/src/main/java/eu/europa/ted/eforms/sdk/ComponentFactory.java b/src/main/java/eu/europa/ted/eforms/sdk/ComponentFactory.java index 65134e81..8f4c4da9 100644 --- a/src/main/java/eu/europa/ted/eforms/sdk/ComponentFactory.java +++ b/src/main/java/eu/europa/ted/eforms/sdk/ComponentFactory.java @@ -4,6 +4,7 @@ import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import eu.europa.ted.eforms.sdk.component.SdkComponentFactory; import eu.europa.ted.eforms.sdk.component.SdkComponentType; @@ -19,12 +20,45 @@ private ComponentFactory() { super(); } + class VersionQualifier { + private final String sdkVersion; + private final String qualifier; + + VersionQualifier(String sdkVersion, String qualifier) { + this.sdkVersion = sdkVersion; + this.qualifier = qualifier; + } + + @Override + public int hashCode() { + return Objects.hash(sdkVersion, qualifier); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + VersionQualifier other = (VersionQualifier) obj; + if (!getEnclosingInstance().equals(other.getEnclosingInstance())) + return false; + return Objects.equals(sdkVersion, other.sdkVersion) + && Objects.equals(qualifier, other.qualifier); + } + + private ComponentFactory getEnclosingInstance() { + return ComponentFactory.this; + } + } /** - * EfxToXpathSymbols is implemented as a "kind-of" singleton. One instance per version of the - * eForms SDK. + * Symbol resolver is a "kind-of" singleton. One instance per version of the + * eForms SDK and per qualifier. */ - private static final Map instances = new HashMap<>(); + private static final Map instances = new HashMap<>(); /** * Gets the single instance containing the symbols defined in the given version of the eForms SDK. @@ -37,10 +71,27 @@ private ComponentFactory() { */ public static SymbolResolver getSymbolResolver(final String sdkVersion, final Path sdkRootPath) throws InstantiationException { - return instances.computeIfAbsent(sdkVersion, k -> { + return getSymbolResolver(sdkVersion, "", sdkRootPath); + } + + /** + * Gets the single instance containing the symbols defined in the given version of the eForms SDK. + * + * @param sdkVersion Version of the SDK + * @param qualifier Qualifier to choose between several implementations + * @param sdkRootPath Path to the root of the SDK + * @return The single instance containing the symbols defined in the given version of the eForms + * SDK. + * @throws InstantiationException If the SDK version is not supported. + */ + public static SymbolResolver getSymbolResolver(final String sdkVersion, final String qualifier, + final Path sdkRootPath) throws InstantiationException { + VersionQualifier key = ComponentFactory.INSTANCE.new VersionQualifier(sdkVersion, qualifier); + + return instances.computeIfAbsent(key, k -> { try { return ComponentFactory.INSTANCE.getComponentImpl(sdkVersion, - SdkComponentType.SYMBOL_RESOLVER, SymbolResolver.class, sdkVersion, + SdkComponentType.SYMBOL_RESOLVER, qualifier, SymbolResolver.class, sdkVersion, sdkRootPath); } catch (InstantiationException e) { throw new RuntimeException(MessageFormat.format( @@ -51,13 +102,23 @@ public static SymbolResolver getSymbolResolver(final String sdkVersion, final Pa public static MarkupGenerator getMarkupGenerator(final String sdkVersion, TranslatorOptions options) throws InstantiationException { + return getMarkupGenerator(sdkVersion, "", options); + } + + public static MarkupGenerator getMarkupGenerator(final String sdkVersion, final String qualifier, + TranslatorOptions options) throws InstantiationException { return ComponentFactory.INSTANCE.getComponentImpl(sdkVersion, - SdkComponentType.MARKUP_GENERATOR, MarkupGenerator.class, options); + SdkComponentType.MARKUP_GENERATOR, qualifier, MarkupGenerator.class, options); } public static ScriptGenerator getScriptGenerator(final String sdkVersion, TranslatorOptions options) throws InstantiationException { + return getScriptGenerator(sdkVersion, "", options); + } + + public static ScriptGenerator getScriptGenerator(final String sdkVersion, final String qualifier, + TranslatorOptions options) throws InstantiationException { return ComponentFactory.INSTANCE.getComponentImpl(sdkVersion, - SdkComponentType.SCRIPT_GENERATOR, ScriptGenerator.class, options); + SdkComponentType.SCRIPT_GENERATOR, qualifier, ScriptGenerator.class, options); } } diff --git a/src/main/java/eu/europa/ted/efx/component/EfxTranslatorFactory.java b/src/main/java/eu/europa/ted/efx/component/EfxTranslatorFactory.java index e40ae6bb..9bc54785 100644 --- a/src/main/java/eu/europa/ted/efx/component/EfxTranslatorFactory.java +++ b/src/main/java/eu/europa/ted/efx/component/EfxTranslatorFactory.java @@ -4,6 +4,9 @@ import eu.europa.ted.eforms.sdk.component.SdkComponentType; import eu.europa.ted.efx.interfaces.EfxExpressionTranslator; import eu.europa.ted.efx.interfaces.EfxTemplateTranslator; +import eu.europa.ted.efx.interfaces.MarkupGenerator; +import eu.europa.ted.efx.interfaces.ScriptGenerator; +import eu.europa.ted.efx.interfaces.SymbolResolver; import eu.europa.ted.efx.interfaces.TranslatorDependencyFactory; import eu.europa.ted.efx.interfaces.TranslatorOptions; @@ -16,17 +19,36 @@ private EfxTranslatorFactory() { public static EfxExpressionTranslator getEfxExpressionTranslator(final String sdkVersion, final TranslatorDependencyFactory factory, TranslatorOptions options) throws InstantiationException { + return getEfxExpressionTranslator(sdkVersion, "", factory, options); + } + + public static EfxExpressionTranslator getEfxExpressionTranslator(final String sdkVersion, + final String qualifier, final TranslatorDependencyFactory factory, TranslatorOptions options) + throws InstantiationException { + + SymbolResolver symbolResolver = factory.createSymbolResolver(sdkVersion, qualifier); + ScriptGenerator scriptGenerator = factory.createScriptGenerator(sdkVersion, qualifier, options); + return EfxTranslatorFactory.INSTANCE.getComponentImpl(sdkVersion, - SdkComponentType.EFX_EXPRESSION_TRANSLATOR, EfxExpressionTranslator.class, - factory.createSymbolResolver(sdkVersion), factory.createScriptGenerator(sdkVersion, options), - factory.createErrorListener()); + SdkComponentType.EFX_EXPRESSION_TRANSLATOR, qualifier, EfxExpressionTranslator.class, + symbolResolver, scriptGenerator, factory.createErrorListener()); } public static EfxTemplateTranslator getEfxTemplateTranslator(final String sdkVersion, final TranslatorDependencyFactory factory, TranslatorOptions options) throws InstantiationException { + return getEfxTemplateTranslator(sdkVersion, "", factory, options); + } + + public static EfxTemplateTranslator getEfxTemplateTranslator(final String sdkVersion, + final String qualifier, final TranslatorDependencyFactory factory, TranslatorOptions options) + throws InstantiationException { + + MarkupGenerator markupGenerator = factory.createMarkupGenerator(sdkVersion, qualifier, options); + SymbolResolver symbolResolver = factory.createSymbolResolver(sdkVersion, qualifier); + ScriptGenerator scriptGenerator = factory.createScriptGenerator(sdkVersion, qualifier, options); + return EfxTranslatorFactory.INSTANCE.getComponentImpl(sdkVersion, - SdkComponentType.EFX_TEMPLATE_TRANSLATOR, EfxTemplateTranslator.class, - factory.createMarkupGenerator(sdkVersion, options), factory.createSymbolResolver(sdkVersion), - factory.createScriptGenerator(sdkVersion, options), factory.createErrorListener()); + SdkComponentType.EFX_TEMPLATE_TRANSLATOR, qualifier, EfxTemplateTranslator.class, + markupGenerator, symbolResolver, scriptGenerator, factory.createErrorListener()); } } diff --git a/src/main/java/eu/europa/ted/efx/interfaces/TranslatorDependencyFactory.java b/src/main/java/eu/europa/ted/efx/interfaces/TranslatorDependencyFactory.java index 69320ab2..59ad652d 100644 --- a/src/main/java/eu/europa/ted/efx/interfaces/TranslatorDependencyFactory.java +++ b/src/main/java/eu/europa/ted/efx/interfaces/TranslatorDependencyFactory.java @@ -37,9 +37,10 @@ public interface TranslatorDependencyFactory { * @param sdkVersion The version of the SDK that contains the version of the EFX grammar that the * EFX translator will attempt to translate. This is important as the symbols used in the * EFX expression are defined in the specific version of the SDK. + * @param qualifier Qualifier to choose between several implementations. * @return An instance of ScriptGenerator to be used by the EFX translator. */ - public SymbolResolver createSymbolResolver(String sdkVersion); + public SymbolResolver createSymbolResolver(String sdkVersion, String qualifier); /** * Creates a ScriptGenerator instance. @@ -50,10 +51,11 @@ public interface TranslatorDependencyFactory { * @param sdkVersion The version of the SDK that contains the version of the EFX grammar that the * EFX translator will attempt to translate. This is important as it defines the EFX * language features that ScriptGenerator instance should be able to handle. + * @param qualifier Qualifier to choose between several implementations. * @param options The options to be used by the ScriptGenerator. * @return An instance of ScriptGenerator to be used by the EFX translator. */ - public ScriptGenerator createScriptGenerator(String sdkVersion, TranslatorOptions options); + public ScriptGenerator createScriptGenerator(String sdkVersion, String qualifier, TranslatorOptions options); /** * Creates a MarkupGenerator instance. @@ -64,10 +66,11 @@ public interface TranslatorDependencyFactory { * @param sdkVersion The version of the SDK that contains the version of the EFX grammar that the * EFX translator will attempt to translate. This is important as it defines the EFX * language features that MarkupGenerator instance should be able to handle. + * @param qualifier Qualifier to choose between several implementations. * @param options The options to be used by the MarkupGenerator. * @return The instance of MarkupGenerator to be used by the EFX translator. */ - public MarkupGenerator createMarkupGenerator(String sdkVersion, TranslatorOptions options); + public MarkupGenerator createMarkupGenerator(String sdkVersion, String qualifier, TranslatorOptions options); /** * Creates an error listener instance. diff --git a/src/test/java/eu/europa/ted/efx/mock/DependencyFactoryMock.java b/src/test/java/eu/europa/ted/efx/mock/DependencyFactoryMock.java index e05c038f..65070d76 100644 --- a/src/test/java/eu/europa/ted/efx/mock/DependencyFactoryMock.java +++ b/src/test/java/eu/europa/ted/efx/mock/DependencyFactoryMock.java @@ -26,18 +26,19 @@ private DependencyFactoryMock() {} Map markupGenerators = new HashMap<>(); @Override - public SymbolResolver createSymbolResolver(String sdkVersion) { + public SymbolResolver createSymbolResolver(String sdkVersion, String qualifier) { + // Ignore the qualifier for unit tests return SymbolResolverMockFactory.getInstance(sdkVersion); } @Override - public ScriptGenerator createScriptGenerator(String sdkVersion, TranslatorOptions options) { + public ScriptGenerator createScriptGenerator(String sdkVersion, String qualifier, TranslatorOptions options) { // Default hashCode() implementation is OK here // we just need to distinguish TranslatorOptions instances - String key = sdkVersion + options.hashCode(); + String key = sdkVersion + qualifier + options.hashCode(); if (!scriptGenerators.containsKey(key)) { try { - this.scriptGenerators.put(key, ComponentFactory.getScriptGenerator(sdkVersion, options)); + this.scriptGenerators.put(key, ComponentFactory.getScriptGenerator(sdkVersion, qualifier, options)); } catch (InstantiationException e) { throw new RuntimeException(e.getMessage(), e); } @@ -46,11 +47,9 @@ public ScriptGenerator createScriptGenerator(String sdkVersion, TranslatorOption } @Override - public MarkupGenerator createMarkupGenerator(String sdkVersion, TranslatorOptions options) { - if (!this.markupGenerators.containsKey(sdkVersion)) { - this.markupGenerators.put(sdkVersion, new MarkupGeneratorMock()); - } - return this.markupGenerators.get(sdkVersion); + public MarkupGenerator createMarkupGenerator(String sdkVersion, String qualifier, TranslatorOptions options) { + String key = sdkVersion + qualifier; + return this.markupGenerators.computeIfAbsent(key, k -> new MarkupGeneratorMock()); } @Override