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.binding.metaschema.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 IBoundInstanceModelGroupedAssembly objInstance
103 = (IBoundInstanceModelGroupedAssembly) instance.getItemInstance(obj);
104
105 if (obj instanceof AssemblyModel.ChoiceGroup.Assembly) {
106 IAssemblyInstanceGrouped assembly = newInstance(
107 (AssemblyModel.ChoiceGroup.Assembly) obj,
108 objInstance,
109 assemblyReferencePosition++,
110 parent);
111 addInstance(assembly, namedModelInstances, assemblyInstances);
112 } else if (obj instanceof AssemblyModel.ChoiceGroup.DefineAssembly) {
113 IAssemblyInstanceGrouped assembly = new InstanceModelGroupedAssemblyInline(
114 (AssemblyModel.ChoiceGroup.DefineAssembly) obj,
115 objInstance,
116 assemblyInlineDefinitionPosition++,
117 parent,
118 nodeItemFactory);
119 addInstance(assembly, namedModelInstances, assemblyInstances);
120 } else if (obj instanceof AssemblyModel.ChoiceGroup.Field) {
121 IFieldInstanceGrouped field = newInstance(
122 (AssemblyModel.ChoiceGroup.Field) obj,
123 objInstance,
124 fieldReferencePosition++,
125 parent);
126 addInstance(field, namedModelInstances, fieldInstances);
127 } else if (obj instanceof AssemblyModel.ChoiceGroup.DefineField) {
128 IFieldInstanceGrouped field = new InstanceModelGroupedFieldInline(
129 (AssemblyModel.ChoiceGroup.DefineField) obj,
130 objInstance,
131 fieldInlineDefinitionPosition++,
132 parent);
133 addInstance(field, namedModelInstances, fieldInstances);
134 } else {
135 throw new UnsupportedOperationException(
136 String.format("Unknown choice group model instance class: %s", obj.getClass()));
137 }
138 }
139
140 this.namedModelInstances = namedModelInstances.isEmpty()
141 ? CollectionUtil.emptyMap()
142 : CollectionUtil.unmodifiableMap(namedModelInstances);
143 this.fieldInstances = fieldInstances.isEmpty()
144 ? CollectionUtil.emptyMap()
145 : CollectionUtil.unmodifiableMap(fieldInstances);
146 this.assemblyInstances = assemblyInstances.isEmpty()
147 ? CollectionUtil.emptyMap()
148 : CollectionUtil.unmodifiableMap(assemblyInstances);
149 }
150
151 protected static void addInstance(
152 @NonNull IAssemblyInstanceGrouped assembly,
153 @NonNull Map<QName, INamedModelInstanceGrouped> namedModelInstances,
154 @NonNull Map<QName, IAssemblyInstanceGrouped> assemblyInstances) {
155 QName effectiveName = assembly.getXmlQName();
156 namedModelInstances.put(effectiveName, assembly);
157 assemblyInstances.put(effectiveName, assembly);
158 }
159
160 protected static void addInstance(
161 @NonNull IFieldInstanceGrouped field,
162 @NonNull Map<QName, INamedModelInstanceGrouped> namedModelInstances,
163 @NonNull Map<QName, IFieldInstanceGrouped> fieldInstances) {
164 QName effectiveName = field.getXmlQName();
165 namedModelInstances.put(effectiveName, field);
166 fieldInstances.put(effectiveName, field);
167 }
168
169 @NonNull
170 protected static IAssemblyInstanceGrouped newInstance(
171 @NonNull AssemblyModel.ChoiceGroup.Assembly obj,
172 @NonNull IBoundInstanceModelGroupedAssembly objInstance,
173 int position,
174 @NonNull IChoiceGroupInstance parent) {
175 IAssemblyDefinition owningDefinition = parent.getOwningDefinition();
176 IModule module = owningDefinition.getContainingModule();
177
178 QName name = parent.getContainingModule().toModelQName(ObjectUtils.requireNonNull(obj.getRef()));
179 IAssemblyDefinition definition = module.getScopedAssemblyDefinitionByName(name);
180
181 if (definition == null) {
182 throw new IllegalStateException(
183 String.format("Unable to resolve assembly reference '%s' in definition '%s' in module '%s'",
184 name,
185 owningDefinition.getName(),
186 module.getShortName()));
187 }
188 return new InstanceModelGroupedAssemblyReference(obj, objInstance, position, definition, parent);
189 }
190
191 @NonNull
192 protected static IFieldInstanceGrouped newInstance(
193 @NonNull AssemblyModel.ChoiceGroup.Field obj,
194 @NonNull IBoundInstanceModelGroupedAssembly objInstance,
195 int position,
196 @NonNull IChoiceGroupInstance parent) {
197 IAssemblyDefinition owningDefinition = parent.getOwningDefinition();
198 IModule module = owningDefinition.getContainingModule();
199
200 QName name = parent.getContainingModule().toModelQName(ObjectUtils.requireNonNull(obj.getRef()));
201 IFieldDefinition definition = module.getScopedFieldDefinitionByName(name);
202 if (definition == null) {
203 throw new IllegalStateException(
204 String.format("Unable to resolve field reference '%s' in definition '%s' in module '%s'",
205 name,
206 owningDefinition.getName(),
207 module.getShortName()));
208 }
209 return new InstanceModelGroupedFieldReference(obj, objInstance, position, definition, parent);
210 }
211
212 @SuppressWarnings("null")
213 @Override
214 public Collection<INamedModelInstanceGrouped> getModelInstances() {
215 return namedModelInstances.values();
216 }
217
218 @Override
219 public Map<QName, INamedModelInstanceGrouped> getNamedModelInstanceMap() {
220 return namedModelInstances;
221 }
222
223 @Override
224 public Map<QName, IFieldInstanceGrouped> getFieldInstanceMap() {
225 return fieldInstances;
226 }
227
228 @Override
229 public Map<QName, IAssemblyInstanceGrouped> getAssemblyInstanceMap() {
230 return assemblyInstances;
231 }
232 }