1
2
3
4
5
6 package gov.nist.secauto.metaschema.databind.model.metaschema.impl;
7
8 import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItemFactory;
9 import gov.nist.secauto.metaschema.core.model.IAssemblyDefinition;
10 import gov.nist.secauto.metaschema.core.model.IAssemblyInstanceGrouped;
11 import gov.nist.secauto.metaschema.core.model.IChoiceGroupInstance;
12 import gov.nist.secauto.metaschema.core.model.IContainerModelSupport;
13 import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
14 import gov.nist.secauto.metaschema.core.model.IFieldInstanceGrouped;
15 import gov.nist.secauto.metaschema.core.model.IModule;
16 import gov.nist.secauto.metaschema.core.model.INamedModelInstanceGrouped;
17 import gov.nist.secauto.metaschema.core.util.CollectionUtil;
18 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
19 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup;
20 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedAssembly;
21 import gov.nist.secauto.metaschema.databind.model.metaschema.binding.AssemblyModel;
22
23 import java.util.Collection;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.xml.namespace.QName;
29
30 import edu.umd.cs.findbugs.annotations.NonNull;
31 import edu.umd.cs.findbugs.annotations.Nullable;
32 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
33
34 class ChoiceGroupModelContainerSupport
35 implements IContainerModelSupport<
36 INamedModelInstanceGrouped,
37 INamedModelInstanceGrouped,
38 IFieldInstanceGrouped,
39 IAssemblyInstanceGrouped> {
40 @NonNull
41 private final Map<QName, INamedModelInstanceGrouped> namedModelInstances;
42 @NonNull
43 private final Map<QName, IFieldInstanceGrouped> fieldInstances;
44 @NonNull
45 private final Map<QName, IAssemblyInstanceGrouped> assemblyInstances;
46
47 @SuppressWarnings("PMD.ShortMethodName")
48 public static IContainerModelSupport<
49 INamedModelInstanceGrouped,
50 INamedModelInstanceGrouped,
51 IFieldInstanceGrouped,
52 IAssemblyInstanceGrouped> of(
53 @Nullable AssemblyModel.ChoiceGroup binding,
54 @NonNull IBoundInstanceModelGroupedAssembly bindingInstance,
55 @NonNull IChoiceGroupInstance parent,
56 @NonNull INodeItemFactory nodeItemFactory) {
57 List<Object> instances;
58 return binding == null || (instances = binding.getChoices()) == null || instances.isEmpty()
59 ? IContainerModelSupport.empty()
60 : new ChoiceGroupModelContainerSupport(
61 binding,
62 bindingInstance,
63 parent,
64 nodeItemFactory);
65 }
66
67
68
69
70
71
72
73
74
75
76
77
78
79 @SuppressWarnings({ "PMD.AvoidInstantiatingObjectsInLoops", "PMD.UseConcurrentHashMap", "PMD.PrematureDeclaration" })
80 @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields")
81 public ChoiceGroupModelContainerSupport(
82 @NonNull AssemblyModel.ChoiceGroup binding,
83 @NonNull IBoundInstanceModelGroupedAssembly bindingInstance,
84 @NonNull IChoiceGroupInstance parent,
85 @NonNull INodeItemFactory nodeItemFactory) {
86
87
88 final Map<QName, INamedModelInstanceGrouped> namedModelInstances = new LinkedHashMap<>();
89 final Map<QName, IFieldInstanceGrouped> fieldInstances = new LinkedHashMap<>();
90 final Map<QName, IAssemblyInstanceGrouped> assemblyInstances = new LinkedHashMap<>();
91
92
93 int assemblyReferencePosition = 0;
94 int assemblyInlineDefinitionPosition = 0;
95 int fieldReferencePosition = 0;
96 int fieldInlineDefinitionPosition = 0;
97
98
99 IBoundInstanceModelChoiceGroup instance = ObjectUtils.requireNonNull(
100 bindingInstance.getDefinition().getChoiceGroupInstanceByName("choices"));
101 for (Object obj : ObjectUtils.notNull(binding.getChoices())) {
102 assert obj != null;
103
104 IBoundInstanceModelGroupedAssembly objInstance
105 = (IBoundInstanceModelGroupedAssembly) instance.getItemInstance(obj);
106
107 if (obj instanceof AssemblyModel.ChoiceGroup.Assembly) {
108 IAssemblyInstanceGrouped assembly = newInstance(
109 (AssemblyModel.ChoiceGroup.Assembly) obj,
110 objInstance,
111 assemblyReferencePosition++,
112 parent);
113 addInstance(assembly, namedModelInstances, assemblyInstances);
114 } else if (obj instanceof AssemblyModel.ChoiceGroup.DefineAssembly) {
115 IAssemblyInstanceGrouped assembly = new InstanceModelGroupedAssemblyInline(
116 (AssemblyModel.ChoiceGroup.DefineAssembly) obj,
117 objInstance,
118 assemblyInlineDefinitionPosition++,
119 parent,
120 nodeItemFactory);
121 addInstance(assembly, namedModelInstances, assemblyInstances);
122 } else if (obj instanceof AssemblyModel.ChoiceGroup.Field) {
123 IFieldInstanceGrouped field = newInstance(
124 (AssemblyModel.ChoiceGroup.Field) obj,
125 objInstance,
126 fieldReferencePosition++,
127 parent);
128 addInstance(field, namedModelInstances, fieldInstances);
129 } else if (obj instanceof AssemblyModel.ChoiceGroup.DefineField) {
130 IFieldInstanceGrouped field = new InstanceModelGroupedFieldInline(
131 (AssemblyModel.ChoiceGroup.DefineField) obj,
132 objInstance,
133 fieldInlineDefinitionPosition++,
134 parent);
135 addInstance(field, namedModelInstances, fieldInstances);
136 } else {
137 throw new UnsupportedOperationException(
138 String.format("Unknown choice group model instance class: %s", obj.getClass()));
139 }
140 }
141
142 this.namedModelInstances = namedModelInstances.isEmpty()
143 ? CollectionUtil.emptyMap()
144 : CollectionUtil.unmodifiableMap(namedModelInstances);
145 this.fieldInstances = fieldInstances.isEmpty()
146 ? CollectionUtil.emptyMap()
147 : CollectionUtil.unmodifiableMap(fieldInstances);
148 this.assemblyInstances = assemblyInstances.isEmpty()
149 ? CollectionUtil.emptyMap()
150 : CollectionUtil.unmodifiableMap(assemblyInstances);
151 }
152
153 protected static void addInstance(
154 @NonNull IAssemblyInstanceGrouped assembly,
155 @NonNull Map<QName, INamedModelInstanceGrouped> namedModelInstances,
156 @NonNull Map<QName, IAssemblyInstanceGrouped> assemblyInstances) {
157 QName effectiveName = assembly.getXmlQName();
158 namedModelInstances.put(effectiveName, assembly);
159 assemblyInstances.put(effectiveName, assembly);
160 }
161
162 protected static void addInstance(
163 @NonNull IFieldInstanceGrouped field,
164 @NonNull Map<QName, INamedModelInstanceGrouped> namedModelInstances,
165 @NonNull Map<QName, IFieldInstanceGrouped> fieldInstances) {
166 QName effectiveName = field.getXmlQName();
167 namedModelInstances.put(effectiveName, field);
168 fieldInstances.put(effectiveName, field);
169 }
170
171 @NonNull
172 protected static IAssemblyInstanceGrouped newInstance(
173 @NonNull AssemblyModel.ChoiceGroup.Assembly obj,
174 @NonNull IBoundInstanceModelGroupedAssembly objInstance,
175 int position,
176 @NonNull IChoiceGroupInstance parent) {
177 IAssemblyDefinition owningDefinition = parent.getOwningDefinition();
178 IModule module = owningDefinition.getContainingModule();
179
180 QName name = parent.getContainingModule().toModelQName(ObjectUtils.requireNonNull(obj.getRef()));
181 IAssemblyDefinition definition = module.getScopedAssemblyDefinitionByName(name);
182
183 if (definition == null) {
184 throw new IllegalStateException(
185 String.format("Unable to resolve assembly reference '%s' in definition '%s' in module '%s'",
186 name,
187 owningDefinition.getName(),
188 module.getShortName()));
189 }
190 return new InstanceModelGroupedAssemblyReference(obj, objInstance, position, definition, parent);
191 }
192
193 @NonNull
194 protected static IFieldInstanceGrouped newInstance(
195 @NonNull AssemblyModel.ChoiceGroup.Field obj,
196 @NonNull IBoundInstanceModelGroupedAssembly objInstance,
197 int position,
198 @NonNull IChoiceGroupInstance parent) {
199 IAssemblyDefinition owningDefinition = parent.getOwningDefinition();
200 IModule module = owningDefinition.getContainingModule();
201
202 QName name = parent.getContainingModule().toModelQName(ObjectUtils.requireNonNull(obj.getRef()));
203 IFieldDefinition definition = module.getScopedFieldDefinitionByName(name);
204 if (definition == null) {
205 throw new IllegalStateException(
206 String.format("Unable to resolve field reference '%s' in definition '%s' in module '%s'",
207 name,
208 owningDefinition.getName(),
209 module.getShortName()));
210 }
211 return new InstanceModelGroupedFieldReference(obj, objInstance, position, definition, parent);
212 }
213
214 @SuppressWarnings("null")
215 @Override
216 public Collection<INamedModelInstanceGrouped> getModelInstances() {
217 return namedModelInstances.values();
218 }
219
220 @Override
221 public Map<QName, INamedModelInstanceGrouped> getNamedModelInstanceMap() {
222 return namedModelInstances;
223 }
224
225 @Override
226 public Map<QName, IFieldInstanceGrouped> getFieldInstanceMap() {
227 return fieldInstances;
228 }
229
230 @Override
231 public Map<QName, IAssemblyInstanceGrouped> getAssemblyInstanceMap() {
232 return assemblyInstances;
233 }
234 }