1
2
3
4
5
6 package gov.nist.secauto.metaschema.databind.model.impl;
7
8 import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
9 import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
10 import gov.nist.secauto.metaschema.core.model.IAttributable;
11 import gov.nist.secauto.metaschema.core.model.IBoundObject;
12 import gov.nist.secauto.metaschema.core.model.IChoiceInstance;
13 import gov.nist.secauto.metaschema.core.model.IContainerModelAssemblySupport;
14 import gov.nist.secauto.metaschema.core.model.ISource;
15 import gov.nist.secauto.metaschema.core.model.constraint.AssemblyConstraintSet;
16 import gov.nist.secauto.metaschema.core.model.constraint.IModelConstrained;
17 import gov.nist.secauto.metaschema.core.model.util.ModuleUtils;
18 import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
19 import gov.nist.secauto.metaschema.core.util.CollectionUtil;
20 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
21 import gov.nist.secauto.metaschema.databind.IBindingContext;
22 import gov.nist.secauto.metaschema.databind.io.BindingException;
23 import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly;
24 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModel;
25 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelAssembly;
26 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup;
27 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelField;
28 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelNamed;
29 import gov.nist.secauto.metaschema.databind.model.IBoundModule;
30 import gov.nist.secauto.metaschema.databind.model.IBoundProperty;
31 import gov.nist.secauto.metaschema.databind.model.annotations.AssemblyConstraints;
32 import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly;
33 import gov.nist.secauto.metaschema.databind.model.annotations.ModelUtil;
34 import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints;
35
36 import java.util.Arrays;
37 import java.util.LinkedHashMap;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.stream.Collectors;
41
42 import edu.umd.cs.findbugs.annotations.NonNull;
43 import edu.umd.cs.findbugs.annotations.Nullable;
44 import nl.talsmasoftware.lazy4j.Lazy;
45
46
47
48
49
50 @SuppressWarnings("PMD.CouplingBetweenObjects")
51 public final class DefinitionAssembly
52 extends AbstractBoundDefinitionModelComplex<MetaschemaAssembly>
53 implements IBoundDefinitionModelAssembly {
54
55 @NonNull
56 private final Lazy<FlagContainerSupport> flagContainer;
57 @NonNull
58 private final Lazy<IContainerModelAssemblySupport<
59 IBoundInstanceModel<?>,
60 IBoundInstanceModelNamed<?>,
61 IBoundInstanceModelField<?>,
62 IBoundInstanceModelAssembly,
63 IChoiceInstance,
64 IBoundInstanceModelChoiceGroup>> modelContainer;
65 @NonNull
66 private final Lazy<IModelConstrained> constraints;
67 @NonNull
68 private final Lazy<IEnhancedQName> xmlRootQName;
69 @NonNull
70 private final Lazy<Map<String, IBoundProperty<?>>> jsonProperties;
71 @NonNull
72 private final Lazy<Map<IAttributable.Key, Set<String>>> properties;
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 @NonNull
89 public static DefinitionAssembly newInstance(
90 @NonNull Class<? extends IBoundObject> clazz,
91 @NonNull MetaschemaAssembly annotation,
92 @NonNull IBoundModule module,
93 @NonNull IBindingContext bindingContext) {
94 return new DefinitionAssembly(clazz, annotation, module, bindingContext);
95 }
96
97 private DefinitionAssembly(
98 @NonNull Class<? extends IBoundObject> clazz,
99 @NonNull MetaschemaAssembly annotation,
100 @NonNull IBoundModule module,
101 @NonNull IBindingContext bindingContext) {
102 super(clazz, annotation, module, bindingContext);
103
104 String rootLocalName = ModelUtil.resolveNoneOrDefault(getAnnotation().rootName(), null);
105 this.xmlRootQName = ObjectUtils.notNull(Lazy.lazy(() -> rootLocalName == null
106 ? null
107 : ModuleUtils.parseModelName(getContainingModule(), rootLocalName)));
108 this.flagContainer = ObjectUtils.notNull(Lazy.lazy(() -> new FlagContainerSupport(this, null)));
109 this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> AssemblyModelGenerator.of(this)));
110
111 ISource source = module.getSource();
112 this.constraints = ObjectUtils.notNull(Lazy.lazy(() -> {
113 IModelConstrained retval = new AssemblyConstraintSet(source);
114 ValueConstraints valueAnnotation = getAnnotation().valueConstraints();
115 ConstraintSupport.parse(valueAnnotation, source, retval);
116
117 AssemblyConstraints assemblyAnnotation = getAnnotation().modelConstraints();
118 ConstraintSupport.parse(assemblyAnnotation, source, retval);
119 return retval;
120 }));
121 this.jsonProperties = ObjectUtils.notNull(Lazy.lazy(() -> getJsonProperties(null)));
122 this.properties = ObjectUtils.notNull(
123 Lazy.lazy(() -> CollectionUtil.unmodifiableMap(ObjectUtils.notNull(
124 Arrays.stream(annotation.properties())
125 .map(ModelUtil::toPropertyEntry)
126 .collect(
127 Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2, LinkedHashMap::new))))));
128 }
129
130 @Override
131 protected void deepCopyItemInternal(IBoundObject fromObject, IBoundObject toObject) throws BindingException {
132
133 super.deepCopyItemInternal(fromObject, toObject);
134
135 for (IBoundInstanceModel<?> instance : getModelInstances()) {
136 assert instance != null;
137
138 instance.deepCopy(fromObject, toObject);
139 }
140 }
141
142 @Override
143 public Map<String, IBoundProperty<?>> getJsonProperties() {
144 return ObjectUtils.notNull(jsonProperties.get());
145 }
146
147
148
149
150
151 @Override
152 @SuppressWarnings("null")
153 @NonNull
154 public FlagContainerSupport getFlagContainer() {
155 return flagContainer.get();
156 }
157
158 @Override
159 @SuppressWarnings("null")
160 @NonNull
161 public IContainerModelAssemblySupport<
162 IBoundInstanceModel<?>,
163 IBoundInstanceModelNamed<?>,
164 IBoundInstanceModelField<?>,
165 IBoundInstanceModelAssembly,
166 IChoiceInstance,
167 IBoundInstanceModelChoiceGroup> getModelContainer() {
168 return modelContainer.get();
169 }
170
171 @Override
172 @NonNull
173 public IModelConstrained getConstraintSupport() {
174 return ObjectUtils.notNull(constraints.get());
175 }
176
177 @Override
178 @Nullable
179 public String getFormalName() {
180 return ModelUtil.resolveNoneOrValue(getAnnotation().formalName());
181 }
182
183 @Override
184 @Nullable
185 public MarkupLine getDescription() {
186 return ModelUtil.resolveToMarkupLine(getAnnotation().description());
187 }
188
189 @Override
190 @NonNull
191 public String getName() {
192 return getAnnotation().name();
193 }
194
195 @Override
196 @Nullable
197 public Integer getIndex() {
198 return ModelUtil.resolveDefaultInteger(getAnnotation().index());
199 }
200
201 @Override
202 public Map<Key, Set<String>> getProperties() {
203 return ObjectUtils.notNull(properties.get());
204 }
205
206 @Override
207 @Nullable
208 public MarkupMultiline getRemarks() {
209 return ModelUtil.resolveToMarkupMultiline(getAnnotation().description());
210 }
211
212 @Override
213 @Nullable
214 public IEnhancedQName getRootQName() {
215
216 return xmlRootQName.get();
217 }
218
219 @Override
220 public boolean isRoot() {
221
222
223 return getRootQName() != null;
224 }
225
226 @Override
227 @Nullable
228 public String getRootName() {
229
230 IEnhancedQName qname = getRootQName();
231 return qname == null ? null : qname.getLocalName();
232 }
233
234 @Override
235 @Nullable
236 public Integer getRootIndex() {
237 return ModelUtil.resolveDefaultInteger(getAnnotation().rootIndex());
238 }
239
240
241
242
243 }