Skip to content

Commit 4ba76bd

Browse files
authored
Fixed issue with the dimension context not properly handling multiple instances of plugin datas or builders. (#320)
1 parent 666a67c commit 4ba76bd

3 files changed

Lines changed: 366 additions & 51 deletions

File tree

simulation/src/main/java/gov/hhs/aspr/ms/gcm/simulation/nucleus/DimensionContext.java

Lines changed: 148 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
*/
1414
public final class DimensionContext implements PluginDataBuilderContainer {
1515

16-
private Map<Class<?>, PluginDataBuilder> pluginDataBuilderBaseMap = new LinkedHashMap<>();
17-
private Map<Class<?>, PluginDataBuilder> pluginDataBuilderWorkingMap = new LinkedHashMap<>();
18-
private Map<Class<?>, PluginData> pluginDataBaseMap = new LinkedHashMap<>();
19-
private Map<Class<?>, PluginData> pluginDataWorkingMap = new LinkedHashMap<>();
16+
private Map<Class<?>, List<PluginDataBuilder>> pluginDataBuilderBaseMap = new LinkedHashMap<>();
17+
private Map<Class<?>, List<PluginDataBuilder>> pluginDataBuilderWorkingMap = new LinkedHashMap<>();
18+
private Map<Class<?>, List<PluginData>> pluginDataBaseMap = new LinkedHashMap<>();
19+
private Map<Class<?>, List<PluginData>> pluginDataWorkingMap = new LinkedHashMap<>();
2020

2121
private DimensionContext() {
2222
}
@@ -28,8 +28,8 @@ public static class Builder {
2828
private Builder() {
2929
}
3030

31-
private Map<Class<?>, PluginDataBuilder> pluginDataBuilderMap = new LinkedHashMap<>();
32-
private Map<Class<?>, PluginData> pluginDataMap = new LinkedHashMap<>();
31+
private Map<Class<?>, List<PluginDataBuilder>> pluginDataBuilderMap = new LinkedHashMap<>();
32+
private Map<Class<?>, List<PluginData>> pluginDataMap = new LinkedHashMap<>();
3333

3434
/**
3535
* Returns the DimensionContext instance composed from the inputs to this
@@ -43,8 +43,8 @@ public DimensionContext build() {
4343
}
4444

4545
/**
46-
* Given a plugin Data, will add it and its clone builder to the internal map in
47-
* this class
46+
* Adds the plugin data to the context and returns the plugin data builder
47+
* generated from the plugin data.
4848
*
4949
* @throws ContractException {@linkplain NucleusError#NULL_PLUGIN_DATA} if the
5050
* plugin data builder is null
@@ -53,10 +53,20 @@ public <T extends PluginData> PluginDataBuilder add(T t) {
5353
if (t == null) {
5454
throw new ContractException(NucleusError.NULL_PLUGIN_DATA);
5555
}
56-
pluginDataMap.put(t.getClass(), t);
57-
PluginDataBuilder builder = t.toBuilder();
56+
List<PluginData> pluginDatas = pluginDataMap.get(t.getClass());
57+
if (pluginDatas == null) {
58+
pluginDatas = new ArrayList<>();
59+
pluginDataMap.put(t.getClass(), pluginDatas);
60+
}
61+
pluginDatas.add(t);
5862

59-
pluginDataBuilderMap.put(builder.getClass(), builder);
63+
PluginDataBuilder builder = t.toBuilder();
64+
List<PluginDataBuilder> pluginDataBuilders = pluginDataBuilderMap.get(builder.getClass());
65+
if (pluginDataBuilders == null) {
66+
pluginDataBuilders = new ArrayList<>();
67+
pluginDataBuilderMap.put(builder.getClass(), pluginDataBuilders);
68+
}
69+
pluginDataBuilders.add(builder);
6070
return builder;
6171
}
6272
}
@@ -68,36 +78,93 @@ public static Builder builder() {
6878
return new Builder();
6979
}
7080

81+
/**
82+
* Returns the stored plugin data builder matching the given class reference.
83+
*
84+
* @throws ContractException
85+
* <ul>
86+
* <li>{@linkplain NucleusError#NULL_PLUGIN_DATA_BUILDER_CLASS}
87+
* if the class reference is null</li>
88+
* <li>{@linkplain NucleusError#AMBIGUOUS_PLUGIN_DATA_BUILDER_CLASS}
89+
* if more than one plugin data builder matches the
90+
* given class reference</li>
91+
* <li>{@linkplain NucleusError#UNKNOWN_PLUGIN_DATA_BUILDER_CLASS}
92+
* if no plugin data builder matches the given class
93+
* reference</li>
94+
* </ul>
95+
*/
7196
@Override
7297
public <T extends PluginDataBuilder> T getPluginDataBuilder(Class<T> classRef) {
98+
if (classRef == null) {
99+
throw new ContractException(NucleusError.NULL_PLUGIN_DATA_BUILDER_CLASS);
100+
}
101+
List<PluginDataBuilder> pluginDataBuilders = pluginDataBuilderWorkingMap.get(classRef);
73102

74-
PluginDataBuilder pluginDataBuilder = pluginDataBuilderWorkingMap.get(classRef);
75-
if (pluginDataBuilder == null) {
76-
List<Class<?>> candidates = new ArrayList<>();
103+
if (pluginDataBuilders == null) {
104+
pluginDataBuilders = new ArrayList<>();
77105
for (Class<?> c : pluginDataBuilderBaseMap.keySet()) {
78106
if (classRef.isAssignableFrom(c)) {
79-
candidates.add(c);
107+
List<PluginDataBuilder> list = pluginDataBuilderBaseMap.get(c);
108+
pluginDataBuilders.addAll(list);
80109
}
81110
}
82-
if (candidates.isEmpty()) {
83-
throw new ContractException(NucleusError.UNKNOWN_PLUGIN_DATA_BUILDER_CLASS);
84-
}
85-
if (candidates.size() > 1) {
86-
throw new ContractException(NucleusError.AMBIGUOUS_PLUGIN_DATA_BUILDER_CLASS);
87-
}
88-
89-
pluginDataBuilder = pluginDataBuilderBaseMap.get(candidates.get(0));
90-
pluginDataBuilderWorkingMap.put(classRef, pluginDataBuilder);
111+
pluginDataBuilderWorkingMap.put(classRef, pluginDataBuilders);
91112
}
113+
if (pluginDataBuilders.isEmpty()) {
114+
throw new ContractException(NucleusError.UNKNOWN_PLUGIN_DATA_BUILDER_CLASS);
115+
}
116+
if (pluginDataBuilders.size() > 1) {
117+
throw new ContractException(NucleusError.AMBIGUOUS_PLUGIN_DATA_BUILDER_CLASS);
118+
}
119+
PluginDataBuilder pluginDataBuilder = pluginDataBuilders.get(0);
92120

93121
return classRef.cast(pluginDataBuilder);
94122
}
123+
124+
/**
125+
* Returns the stored plugin data builders matching the given class reference.
126+
*
127+
* @throws ContractException
128+
* <ul>
129+
* <li>{@linkplain NucleusError#NULL_PLUGIN_DATA_BUILDER_CLASS}
130+
* if the class reference is null</li> *
131+
* </ul>
132+
*/
133+
@SuppressWarnings("unchecked")
134+
public <T extends PluginDataBuilder> List<T> getPluginDataBuilders(Class<T> classRef) {
135+
if (classRef == null) {
136+
throw new ContractException(NucleusError.NULL_PLUGIN_DATA_BUILDER_CLASS);
137+
}
138+
139+
List<T> result = new ArrayList<>();
140+
141+
List<PluginDataBuilder> pluginDataBuilders = pluginDataBuilderWorkingMap.get(classRef);
142+
143+
if (pluginDataBuilders == null) {
144+
pluginDataBuilders = new ArrayList<>();
145+
for (Class<?> c : pluginDataBuilderBaseMap.keySet()) {
146+
if (classRef.isAssignableFrom(c)) {
147+
List<PluginDataBuilder> list = pluginDataBuilderBaseMap.get(c);
148+
pluginDataBuilders.addAll(list);
149+
}
150+
}
151+
pluginDataBuilderWorkingMap.put(classRef, pluginDataBuilders);
152+
}
153+
154+
for(PluginDataBuilder pluginDataBuilder : pluginDataBuilders) {
155+
result.add((T)pluginDataBuilder);
156+
}
157+
158+
return result;
159+
}
95160

96161
/**
97-
* Returns the stored item matching the given class reference.
162+
* Returns the stored plugin data matching the given class reference.
98163
*
99164
* @throws ContractException
100165
* <ul>
166+
* <li>{@linkplain NucleusError#NULL_PLUGIN_DATA_CLASS}
167+
* if the class reference is null</li>
101168
* <li>{@linkplain NucleusError#AMBIGUOUS_PLUGIN_DATA_CLASS}
102169
* if more than one plugin data matches the given
103170
* class reference</li>
@@ -108,25 +175,69 @@ public <T extends PluginDataBuilder> T getPluginDataBuilder(Class<T> classRef) {
108175
*/
109176
public <T extends PluginData> T getPluginData(Class<T> classRef) {
110177

111-
PluginData pluginData = pluginDataWorkingMap.get(classRef);
112-
if (pluginData == null) {
113-
List<Class<?>> candidates = new ArrayList<>();
178+
if (classRef == null) {
179+
throw new ContractException(NucleusError.NULL_PLUGIN_DATA_CLASS);
180+
}
181+
182+
List<PluginData> pluginDatas = pluginDataWorkingMap.get(classRef);
183+
if (pluginDatas == null) {
184+
pluginDatas = new ArrayList<>();
114185
for (Class<?> c : pluginDataBaseMap.keySet()) {
115186
if (classRef.isAssignableFrom(c)) {
116-
candidates.add(c);
187+
List<PluginData> list = pluginDataBaseMap.get(c);
188+
pluginDatas.addAll(list);
117189
}
118190
}
119-
if (candidates.isEmpty()) {
120-
throw new ContractException(NucleusError.UNKNOWN_PLUGIN_DATA_CLASS);
121-
}
122-
if (candidates.size() > 1) {
123-
throw new ContractException(NucleusError.AMBIGUOUS_PLUGIN_DATA_CLASS);
124-
}
191+
pluginDataWorkingMap.put(classRef, pluginDatas);
192+
}
125193

126-
pluginData = pluginDataBaseMap.get(candidates.get(0));
127-
pluginDataWorkingMap.put(classRef, pluginData);
194+
if (pluginDatas.isEmpty()) {
195+
throw new ContractException(NucleusError.UNKNOWN_PLUGIN_DATA_CLASS);
196+
}
197+
if (pluginDatas.size() > 1) {
198+
throw new ContractException(NucleusError.AMBIGUOUS_PLUGIN_DATA_CLASS);
128199
}
129200

201+
PluginData pluginData = pluginDatas.get(0);
202+
130203
return classRef.cast(pluginData);
131204
}
205+
206+
/**
207+
* Returns the stored plugin datas matching the given class reference.
208+
*
209+
* @throws ContractException
210+
* <ul>
211+
* <li>{@linkplain NucleusError#NULL_PLUGIN_DATA_CLASS}
212+
* if the class reference is null</li>
213+
* </ul>
214+
*/
215+
@SuppressWarnings("unchecked")
216+
public <T extends PluginData> List<T> getPluginDatas(Class<T> classRef) {
217+
218+
219+
if (classRef == null) {
220+
throw new ContractException(NucleusError.NULL_PLUGIN_DATA_CLASS);
221+
}
222+
223+
List<T> result = new ArrayList<>();
224+
225+
List<PluginData> pluginDatas = pluginDataWorkingMap.get(classRef);
226+
if (pluginDatas == null) {
227+
pluginDatas = new ArrayList<>();
228+
for (Class<?> c : pluginDataBaseMap.keySet()) {
229+
if (classRef.isAssignableFrom(c)) {
230+
List<PluginData> list = pluginDataBaseMap.get(c);
231+
pluginDatas.addAll(list);
232+
}
233+
}
234+
pluginDataWorkingMap.put(classRef, pluginDatas);
235+
}
236+
237+
for(PluginData pluginData : pluginDatas) {
238+
result.add((T)pluginData);
239+
}
240+
241+
return result;
242+
}
132243
}

simulation/src/main/java/gov/hhs/aspr/ms/gcm/simulation/nucleus/NucleusError.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public enum NucleusError implements ContractError {
5757
NULL_PLUGIN_CONTEXT("Null plugin context"),//
5858
NULL_PLUGIN_DATA("Null plugin data"),//
5959
NULL_PLUGIN_DATA_CLASS("Null plugin data class"),//
60+
NULL_PLUGIN_DATA_BUILDER_CLASS("Null plugin data builder class"),//
6061
NULL_PLUGIN_ID("Null plugin id"),//
6162
NULL_PLUGIN_INITIALIZER("Null plugin initializer"),//
6263
NULL_PLUGINS("Null collection of plugins"),//

0 commit comments

Comments
 (0)