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.AbstractAssemblyInstance;
11 import gov.nist.secauto.metaschema.core.model.IBoundObject;
12 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
13 import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly;
14 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceFlag;
15 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelAssembly;
16 import gov.nist.secauto.metaschema.databind.model.IBoundModule;
17 import gov.nist.secauto.metaschema.databind.model.IBoundProperty;
18 import gov.nist.secauto.metaschema.databind.model.IGroupAs;
19 import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly;
20 import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs;
21 import gov.nist.secauto.metaschema.databind.model.annotations.ModelUtil;
22 import gov.nist.secauto.metaschema.databind.model.info.IModelInstanceCollectionInfo;
23
24 import java.lang.reflect.Field;
25 import java.util.Map;
26 import java.util.function.Predicate;
27
28 import edu.umd.cs.findbugs.annotations.NonNull;
29 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
30 import nl.talsmasoftware.lazy4j.Lazy;
31
32
33
34
35
36
37 public final class InstanceModelAssemblyComplex
38 extends AbstractAssemblyInstance<
39 IBoundDefinitionModelAssembly,
40 IBoundDefinitionModelAssembly,
41 IBoundInstanceModelAssembly,
42 IBoundDefinitionModelAssembly>
43 implements IBoundInstanceModelAssembly, IFeatureInstanceModelGroupAs<IBoundObject> {
44 @NonNull
45 private final Field javaField;
46 @NonNull
47 private final BoundAssembly annotation;
48 @NonNull
49 private final Lazy<IModelInstanceCollectionInfo<IBoundObject>> collectionInfo;
50 @NonNull
51 private final IBoundDefinitionModelAssembly definition;
52 @NonNull
53 private final IGroupAs groupAs;
54 @NonNull
55 private final Lazy<Map<String, IBoundProperty<?>>> jsonProperties;
56
57
58
59
60
61
62
63
64
65
66
67
68
69 @NonNull
70 public static InstanceModelAssemblyComplex newInstance(
71 @NonNull Field javaField,
72 @NonNull IBoundDefinitionModelAssembly definition,
73 @NonNull IBoundDefinitionModelAssembly containingDefinition) {
74 BoundAssembly annotation = ModelUtil.getAnnotation(javaField, BoundAssembly.class);
75 IGroupAs groupAs = ModelUtil.resolveDefaultGroupAs(
76 annotation.groupAs(),
77 containingDefinition.getContainingModule());
78 if (annotation.maxOccurs() == -1 || annotation.maxOccurs() > 1) {
79 if (IGroupAs.SINGLETON_GROUP_AS.equals(groupAs)) {
80 throw new IllegalStateException(String.format("Field '%s' on class '%s' is missing the '%s' annotation.",
81 javaField.getName(),
82 containingDefinition.getBoundClass().getName(),
83 GroupAs.class.getName()));
84 }
85 } else if (!IGroupAs.SINGLETON_GROUP_AS.equals(groupAs)) {
86
87 throw new IllegalStateException(
88 String.format(
89 "Field '%s' on class '%s' has the '%s' annotation, but maxOccurs=1. A groupAs must not be specfied.",
90 javaField.getName(),
91 containingDefinition.getBoundClass().getName(),
92 GroupAs.class.getName()));
93 }
94 return new InstanceModelAssemblyComplex(javaField, annotation, groupAs, definition, containingDefinition);
95 }
96
97 @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Use of final fields")
98 private InstanceModelAssemblyComplex(
99 @NonNull Field javaField,
100 @NonNull BoundAssembly annotation,
101 @NonNull IGroupAs groupAs,
102 @NonNull IBoundDefinitionModelAssembly definition,
103 @NonNull IBoundDefinitionModelAssembly containingDefinition) {
104 super(containingDefinition);
105 this.javaField = javaField;
106 this.annotation = annotation;
107 this.groupAs = groupAs;
108 this.collectionInfo = ObjectUtils.notNull(Lazy.lazy(() -> IModelInstanceCollectionInfo.of(this)));
109 this.definition = definition;
110 this.jsonProperties = ObjectUtils.notNull(Lazy.lazy(() -> {
111 IBoundInstanceFlag jsonKey = getEffectiveJsonKey();
112 Predicate<IBoundInstanceFlag> flagFilter = jsonKey == null ? null : flag -> !jsonKey.equals(flag);
113 return getDefinition().getJsonProperties(flagFilter);
114 }));
115 }
116
117
118
119
120
121 @Override
122 public Field getField() {
123 return javaField;
124 }
125
126
127
128
129
130
131 @NonNull
132 public BoundAssembly getAnnotation() {
133 return annotation;
134 }
135
136 @SuppressWarnings("null")
137 @Override
138 public IModelInstanceCollectionInfo<IBoundObject> getCollectionInfo() {
139 return collectionInfo.get();
140 }
141
142 @Override
143 public Map<String, IBoundProperty<?>> getJsonProperties() {
144 return ObjectUtils.notNull(jsonProperties.get());
145 }
146
147 @Override
148 public IBoundDefinitionModelAssembly getDefinition() {
149 return definition;
150 }
151
152 @Override
153 public IBoundModule getContainingModule() {
154 return getContainingDefinition().getContainingModule();
155 }
156
157 @Override
158 public IGroupAs getGroupAs() {
159 return groupAs;
160 }
161
162 @Override
163 public String getFormalName() {
164 return ModelUtil.resolveNoneOrValue(getAnnotation().formalName());
165 }
166
167 @Override
168 public MarkupLine getDescription() {
169 return ModelUtil.resolveToMarkupLine(getAnnotation().description());
170 }
171
172 @Override
173 public String getUseName() {
174 return ModelUtil.resolveNoneOrValue(getAnnotation().useName());
175 }
176
177 @Override
178 public Integer getUseIndex() {
179 int value = getAnnotation().useIndex();
180 return value == Integer.MIN_VALUE ? null : value;
181 }
182
183 @Override
184 public int getMinOccurs() {
185 return getAnnotation().minOccurs();
186 }
187
188 @Override
189 public int getMaxOccurs() {
190 return getAnnotation().maxOccurs();
191 }
192
193 @Override
194 public MarkupMultiline getRemarks() {
195 return ModelUtil.resolveToMarkupMultiline(getAnnotation().remarks());
196 }
197 }