Skip to content

Commit

Permalink
Merge pull request #104 from OP-TED/feature/add-component-qualifiers
Browse files Browse the repository at this point in the history
Add method overloads to support using qualifiers for SDK components
  • Loading branch information
bertrand-lorentz authored Apr 5, 2024
2 parents 513815c + 38af615 commit 718e8c8
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 25 deletions.
75 changes: 68 additions & 7 deletions src/main/java/eu/europa/ted/eforms/sdk/ComponentFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<String, SymbolResolver> instances = new HashMap<>();
private static final Map<VersionQualifier, SymbolResolver> instances = new HashMap<>();

/**
* Gets the single instance containing the symbols defined in the given version of the eForms SDK.
Expand All @@ -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(
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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.
Expand Down
17 changes: 8 additions & 9 deletions src/test/java/eu/europa/ted/efx/mock/DependencyFactoryMock.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,19 @@ private DependencyFactoryMock() {}
Map<String, MarkupGenerator> 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);
}
Expand All @@ -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
Expand Down

0 comments on commit 718e8c8

Please sign in to comment.