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