Skip to content

Commit db8bb0e

Browse files
Merge pull request #33 from OP-TED/feature/TEDEFO-3230-differentiate-components
Add qualifier for SDK component, to allow differentiating components the same SDK version and component type
2 parents f7003bc + c74e01f commit db8bb0e

11 files changed

Lines changed: 203 additions & 24 deletions

File tree

pom.xml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
<version.jaxb-impl>4.0.4</version.jaxb-impl>
6464
<version.jool>0.9.15</version.jool>
6565
<version.junit>5.7.2</version.junit>
66+
<version.logback>1.5.3</version.logback>
6667
<version.maven>3.8.6</version.maven>
6768
<version.ph-jaxb>11.1.3</version.ph-jaxb>
6869
<version.ph-genericode>7.1.1</version.ph-genericode>
@@ -205,6 +206,16 @@
205206
</dependency>
206207

207208
<!-- Other -->
209+
<dependency>
210+
<groupId>ch.qos.logback</groupId>
211+
<artifactId>logback-classic</artifactId>
212+
<version>${version.logback}</version>
213+
</dependency>
214+
<dependency>
215+
<groupId>ch.qos.logback</groupId>
216+
<artifactId>logback-core</artifactId>
217+
<version>${version.logback}</version>
218+
</dependency>
208219
<dependency>
209220
<groupId>org.antlr</groupId>
210221
<artifactId>antlr4-runtime</artifactId>
@@ -326,6 +337,16 @@
326337
</dependency>
327338

328339
<!-- Other -->
340+
<dependency>
341+
<groupId>ch.qos.logback</groupId>
342+
<artifactId>logback-classic</artifactId>
343+
<scope>test</scope>
344+
</dependency>
345+
<dependency>
346+
<groupId>ch.qos.logback</groupId>
347+
<artifactId>logback-core</artifactId>
348+
<scope>test</scope>
349+
</dependency>
329350
<dependency>
330351
<groupId>org.antlr</groupId>
331352
<artifactId>antlr4-runtime</artifactId>

src/main/java/eu/europa/ted/eforms/sdk/component/SdkComponent.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@
1313
public String[] versions();
1414

1515
public SdkComponentType componentType();
16+
17+
public String qualifier() default "";
1618
}

src/main/java/eu/europa/ted/eforms/sdk/component/SdkComponentDescriptor.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,20 @@ public class SdkComponentDescriptor<T> implements Serializable {
2323

2424
private SdkComponentType componentType;
2525

26+
private String qualifier;
27+
2628
private Class<T> implType;
2729

2830
public SdkComponentDescriptor(String sdkVersion, SdkComponentType componentType,
2931
Class<T> implType) {
32+
this(sdkVersion, componentType, "", implType);
33+
}
34+
35+
public SdkComponentDescriptor(String sdkVersion, SdkComponentType componentType, String qualifier,
36+
Class<T> implType) {
3037
this.sdkVersion = Validate.notBlank(sdkVersion, "Undefined SDK version");
3138
this.componentType = Validate.notNull(componentType, "Undefined component type");
39+
this.qualifier = Validate.notNull(qualifier, "Undefined qualifier");
3240
this.implType = Validate.notNull(implType, "Undefined implementation type");
3341
}
3442

@@ -94,7 +102,7 @@ private boolean constructorHasExpectedParameters(Constructor<?> constructor,
94102

95103
@Override
96104
public int hashCode() {
97-
return Objects.hash(componentType, sdkVersion);
105+
return Objects.hash(componentType, sdkVersion, qualifier, implType);
98106
}
99107

100108
@Override
@@ -106,7 +114,10 @@ public boolean equals(Object obj) {
106114
if (getClass() != obj.getClass())
107115
return false;
108116
SdkComponentDescriptor<?> other = (SdkComponentDescriptor<?>) obj;
109-
return componentType == other.componentType && Objects.equals(sdkVersion, other.sdkVersion);
117+
return componentType == other.componentType
118+
&& Objects.equals(sdkVersion, other.sdkVersion)
119+
&& Objects.equals(qualifier, other.qualifier)
120+
&& Objects.equals(implType, other.implType);
110121
}
111122

112123
public Class<T> getImplType() {

src/main/java/eu/europa/ted/eforms/sdk/component/SdkComponentFactory.java

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import java.text.MessageFormat;
44
import java.util.Arrays;
55
import java.util.Collections;
6-
import java.util.EnumMap;
76
import java.util.HashMap;
87
import java.util.Map;
8+
import java.util.Objects;
99
import java.util.Optional;
1010
import java.util.stream.Stream;
1111
import org.reflections.Reflections;
@@ -20,7 +20,40 @@
2020
public abstract class SdkComponentFactory {
2121
private static final Logger logger = LoggerFactory.getLogger(SdkComponentFactory.class);
2222

23-
private Map<String, Map<SdkComponentType, SdkComponentDescriptor<?>>> componentsMap;
23+
private Map<String, Map<ComponentSelector, SdkComponentDescriptor<?>>> componentsMap;
24+
25+
class ComponentSelector {
26+
private final SdkComponentType componentType;
27+
private final String qualifier;
28+
29+
public ComponentSelector(SdkComponentType componentType, String qualifier) {
30+
this.componentType = componentType;
31+
this.qualifier = qualifier;
32+
}
33+
34+
@Override
35+
public int hashCode() {
36+
return Objects.hash(componentType, qualifier);
37+
}
38+
39+
@Override
40+
public boolean equals(Object obj) {
41+
if (this == obj)
42+
return true;
43+
if (obj == null)
44+
return false;
45+
if (getClass() != obj.getClass())
46+
return false;
47+
ComponentSelector other = (ComponentSelector) obj;
48+
if (!getEnclosingInstance().equals(other.getEnclosingInstance()))
49+
return false;
50+
return componentType == other.componentType && Objects.equals(qualifier, other.qualifier);
51+
}
52+
53+
private SdkComponentFactory getEnclosingInstance() {
54+
return SdkComponentFactory.this;
55+
}
56+
}
2457

2558
protected SdkComponentFactory() {
2659
populateComponents();
@@ -54,6 +87,8 @@ private void populateComponents() {
5487

5588
String[] supportedSdkVersions = annotation.versions();
5689
SdkComponentType componentType = annotation.componentType();
90+
String qualifier = annotation.qualifier();
91+
ComponentSelector selector = new ComponentSelector(componentType, qualifier);
5792

5893
logger.trace("Class [{}] has a component type of [{}] and supports SDK versions [{}]",
5994
clazz, componentType, supportedSdkVersions);
@@ -62,11 +97,11 @@ private void populateComponents() {
6297
SdkComponentDescriptor<?> component =
6398
new SdkComponentDescriptor<>(sdkVersion, componentType, clazz);
6499

65-
Map<SdkComponentType, SdkComponentDescriptor<?>> components =
100+
Map<ComponentSelector, SdkComponentDescriptor<?>> components =
66101
componentsMap.get(sdkVersion);
67102

68103
if (components != null) {
69-
SdkComponentDescriptor<?> existingComponent = components.get(componentType);
104+
SdkComponentDescriptor<?> existingComponent = components.get(selector);
70105

71106
if (existingComponent != null && !existingComponent.equals(component)) {
72107
throw new IllegalArgumentException(MessageFormat.format(
@@ -75,30 +110,39 @@ private void populateComponents() {
75110
clazz.getName()));
76111
}
77112
} else {
78-
components = new EnumMap<>(SdkComponentType.class);
113+
components = new HashMap<>();
79114
componentsMap.put(sdkVersion, components);
80115
}
81116

82-
components.put(componentType, component);
117+
components.put(selector, component);
83118
});
84119
});
85120
}
86121

87122
protected <T> T getComponentImpl(String sdkVersion, final SdkComponentType componentType,
88123
final Class<T> intf, Object... initArgs) throws InstantiationException {
89124

125+
return getComponentImpl(sdkVersion, componentType, "", intf, initArgs);
126+
}
127+
128+
protected <T> T getComponentImpl(String sdkVersion, final SdkComponentType componentType,
129+
final String qualifier, final Class<T> intf, Object... initArgs) throws InstantiationException {
130+
90131
String normalizedVersion = normalizeVersion(sdkVersion);
91132

133+
ComponentSelector selector = new ComponentSelector(componentType, qualifier);
134+
92135
@SuppressWarnings("unchecked")
93136
SdkComponentDescriptor<T> descriptor =
94137
(SdkComponentDescriptor<T>) Optional.ofNullable(componentsMap.get(normalizedVersion))
95-
.orElseGet(Collections::emptyMap).get(componentType);
138+
.orElseGet(Collections::emptyMap).get(selector);
96139

97140
if (descriptor == null) {
98141
logger.error("Failed to load required components of SDK [{}]", sdkVersion);
99142
throw new IllegalArgumentException(
100-
MessageFormat.format("No implementation found for component type [{0}] of SDK [{1}].",
101-
componentType, sdkVersion));
143+
MessageFormat.format(
144+
"No implementation found for SDK [{0}], component type [{1}] and qualifier '{2}'.",
145+
sdkVersion, componentType, qualifier));
102146
}
103147

104148
return descriptor.createInstance(initArgs);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package eu.europa.ted.eforms.sdk.component;
2+
3+
@SdkComponent(versions = "0.5", componentType = SdkComponentType.EFX_EXPRESSION_TRANSLATOR)
4+
class MyComponent implements TestComponent {
5+
6+
@Override
7+
public String testMethod() {
8+
return null;
9+
}
10+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package eu.europa.ted.eforms.sdk.component;
2+
3+
class MyComponentFactory extends SdkComponentFactory {
4+
5+
@Override
6+
protected <T> T getComponentImpl(String sdkVersion, SdkComponentType componentType, Class<T> intf,
7+
Object... initArgs) throws InstantiationException {
8+
return super.getComponentImpl(sdkVersion, componentType, intf, initArgs);
9+
}
10+
11+
@Override
12+
protected <T> T getComponentImpl(String sdkVersion, SdkComponentType componentType,
13+
String qualifier, Class<T> intf, Object... initArgs) throws InstantiationException {
14+
return super.getComponentImpl(sdkVersion, componentType, qualifier, intf, initArgs);
15+
}
16+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package eu.europa.ted.eforms.sdk.component;
2+
3+
@SdkComponent(versions = "1", componentType = SdkComponentType.NODE, qualifier = "qualifier")
4+
public class NodeComponentWithQualifier implements TestComponent {
5+
6+
@Override
7+
public String testMethod() {
8+
return "Node";
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package eu.europa.ted.eforms.sdk.component;
2+
3+
@SdkComponent(versions = "1", componentType = SdkComponentType.SCRIPT_GENERATOR)
4+
class ScriptGeneratorA implements TestComponent {
5+
6+
@Override
7+
public String testMethod() {
8+
return "A";
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package eu.europa.ted.eforms.sdk.component;
2+
3+
@SdkComponent(versions = "1", componentType = SdkComponentType.SCRIPT_GENERATOR, qualifier = "B")
4+
class ScriptGeneratorB implements TestComponent {
5+
6+
@Override
7+
public String testMethod() {
8+
return "B";
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package eu.europa.ted.eforms.sdk.component;
2+
3+
@SdkComponent(versions = "1", componentType = SdkComponentType.SCRIPT_GENERATOR, qualifier = "other")
4+
class ScriptGeneratorSubclass extends ScriptGeneratorA {
5+
6+
@Override
7+
public String testMethod() {
8+
return "Subclass";
9+
}
10+
}

0 commit comments

Comments
 (0)