1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package gov.nist.secauto.metaschema.databind.model;
28
29 import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
30 import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
31 import gov.nist.secauto.metaschema.core.model.IChoiceInstance;
32 import gov.nist.secauto.metaschema.core.model.IFlagContainerSupport;
33 import gov.nist.secauto.metaschema.core.model.IModule;
34 import gov.nist.secauto.metaschema.core.model.IModelContainerSupport;
35 import gov.nist.secauto.metaschema.core.model.constraint.IConstraint.InternalModelSource;
36 import gov.nist.secauto.metaschema.core.model.constraint.IModelConstrained;
37 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
38 import gov.nist.secauto.metaschema.databind.IBindingContext;
39 import gov.nist.secauto.metaschema.databind.io.BindingException;
40 import gov.nist.secauto.metaschema.databind.model.annotations.AssemblyConstraints;
41 import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly;
42 import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly;
43 import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints;
44
45 import java.util.Objects;
46
47 import javax.xml.namespace.QName;
48
49 import edu.umd.cs.findbugs.annotations.NonNull;
50 import edu.umd.cs.findbugs.annotations.Nullable;
51 import nl.talsmasoftware.lazy4j.Lazy;
52
53 public class DefaultAssemblyClassBinding
54 extends AbstractClassBinding
55 implements IAssemblyClassBinding {
56
57 @NonNull
58 private final MetaschemaAssembly metaschemaAssembly;
59 private final QName xmlRootQName;
60 @NonNull
61 private final Lazy<ClassBindingFlagContainerSupport> flagContainer;
62 @NonNull
63 private final Lazy<ClassBindingModelContainerSupport> modelContainer;
64 @NonNull
65 private final Lazy<IModelConstrained> constraints;
66
67
68
69
70
71
72
73
74
75
76
77 @NonNull
78 public static DefaultAssemblyClassBinding createInstance(
79 @NonNull Class<?> clazz,
80 @NonNull IBindingContext bindingContext) {
81 return new DefaultAssemblyClassBinding(clazz, bindingContext);
82 }
83
84
85
86
87
88
89
90
91
92
93 protected DefaultAssemblyClassBinding(@NonNull Class<?> clazz, @NonNull IBindingContext bindingContext) {
94 super(clazz, bindingContext);
95 Objects.requireNonNull(clazz, "clazz");
96 if (!clazz.isAnnotationPresent(MetaschemaAssembly.class)) {
97 throw new IllegalArgumentException(
98 String.format("Class '%s' is missing the '%s' annotation.",
99 clazz.getName(),
100 MetaschemaAssembly.class.getName()));
101 }
102 this.metaschemaAssembly = ObjectUtils.notNull(clazz.getAnnotation(MetaschemaAssembly.class));
103 String namespace = ObjectUtils.notNull(ModelUtil.resolveNamespace(this.metaschemaAssembly.rootNamespace(), this));
104 String localName = ModelUtil.resolveLocalName(this.metaschemaAssembly.rootName(), null);
105
106 this.xmlRootQName = localName == null ? null : new QName(namespace, localName);
107
108 this.flagContainer = ObjectUtils.notNull(Lazy.lazy(() -> new ClassBindingFlagContainerSupport(this, null)));
109 this.modelContainer = ObjectUtils.notNull(Lazy.lazy(() -> new ClassBindingModelContainerSupport(this)));
110 this.constraints = ObjectUtils.notNull(Lazy.lazy(() -> new AssemblyConstraintSupport(
111 clazz.getAnnotation(ValueConstraints.class),
112 clazz.getAnnotation(AssemblyConstraints.class),
113 InternalModelSource.instance())));
114 }
115
116 @SuppressWarnings("null")
117 @Override
118 public IFlagContainerSupport<IBoundFlagInstance> getFlagContainer() {
119 return flagContainer.get();
120 }
121
122 @SuppressWarnings("null")
123 @Override
124 public IModelContainerSupport<
125 IBoundNamedModelInstance,
126 IBoundNamedModelInstance,
127 IBoundFieldInstance,
128 IBoundAssemblyInstance,
129 IChoiceInstance> getModelContainer() {
130 return modelContainer.get();
131 }
132
133
134
135
136
137
138
139
140 @NonNull
141 private MetaschemaAssembly getMetaschemaAssemblyAnnotation() {
142 return metaschemaAssembly;
143 }
144
145 @Override
146 public String getFormalName() {
147 return ModelUtil.resolveToString(getMetaschemaAssemblyAnnotation().formalName());
148 }
149
150 @Override
151 public MarkupLine getDescription() {
152 return ModelUtil.resolveToMarkupLine(getMetaschemaAssemblyAnnotation().description());
153 }
154
155 @Override
156 public @Nullable MarkupMultiline getRemarks() {
157 return ModelUtil.resolveToMarkupMultiline(getMetaschemaAssemblyAnnotation().description());
158 }
159
160 @Override
161 public String getName() {
162 return getMetaschemaAssemblyAnnotation().name();
163 }
164
165 @Override
166 public boolean isInline() {
167 return false;
168 }
169
170 @Override
171 public IBoundAssemblyInstance getInlineInstance() {
172 return null;
173 }
174
175 @Override
176 public boolean isRoot() {
177
178
179 return getRootXmlQName() != null;
180 }
181
182 @Override
183 public String getRootName() {
184
185 QName qname = getRootXmlQName();
186 return qname == null ? null : qname.getLocalPart();
187 }
188
189 @Override
190 public QName getRootXmlQName() {
191
192 return xmlRootQName;
193 }
194
195 @Override
196 public IModelConstrained getConstraintSupport() {
197 return ObjectUtils.notNull(constraints.get());
198 }
199
200 @Override
201 protected void copyBoundObjectInternal(@NonNull Object fromInstance, @NonNull Object toInstance)
202 throws BindingException {
203 super.copyBoundObjectInternal(fromInstance, toInstance);
204
205 for (IBoundNamedModelInstance property : getModelInstances()) {
206 property.copyBoundObject(fromInstance, toInstance);
207 }
208 }
209
210 @Override
211 protected Class<? extends IModule> getModuleClass() {
212 return getMetaschemaAssemblyAnnotation().moduleClass();
213 }
214
215 }