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.IDataTypeAdapter;
30 import gov.nist.secauto.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
31 import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
32 import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
33 import gov.nist.secauto.metaschema.core.model.IFeatureFlagContainer;
34 import gov.nist.secauto.metaschema.core.model.IFlagContainerSupport;
35 import gov.nist.secauto.metaschema.core.model.IFlagInstance;
36 import gov.nist.secauto.metaschema.core.model.IModule;
37 import gov.nist.secauto.metaschema.core.model.ModuleScopeEnum;
38 import gov.nist.secauto.metaschema.core.model.constraint.IConstraint.InternalModelSource;
39 import gov.nist.secauto.metaschema.core.model.constraint.IValueConstrained;
40 import gov.nist.secauto.metaschema.core.util.CollectionUtil;
41 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
42 import gov.nist.secauto.metaschema.databind.model.annotations.BoundFieldValue;
43 import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints;
44 import gov.nist.secauto.metaschema.databind.model.info.IDataTypeHandler;
45
46 import java.lang.reflect.Field;
47 import java.util.Collection;
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 class SimpleFieldProperty
54 extends AbstractFieldProperty {
55 @NonNull
56 private final IDataTypeAdapter<?> javaTypeAdapter;
57 @Nullable
58 private final Object defaultValue;
59 @NonNull
60 private final Lazy<ScalarFieldDefinition> definition;
61
62
63
64
65
66
67
68
69
70
71 public SimpleFieldProperty(
72 @NonNull Field field,
73 @NonNull IAssemblyClassBinding parentClassBinding) {
74 super(field, parentClassBinding);
75
76 BoundFieldValue boundFieldValue = field.getAnnotation(BoundFieldValue.class);
77 if (boundFieldValue == null) {
78 this.javaTypeAdapter = MetaschemaDataTypeProvider.DEFAULT_DATA_TYPE;
79 this.defaultValue = null;
80 } else {
81 this.javaTypeAdapter = ModelUtil.getDataTypeAdapter(
82 boundFieldValue.typeAdapter(),
83 parentClassBinding.getBindingContext());
84 this.defaultValue = ModelUtil.resolveDefaultValue(boundFieldValue.defaultValue(), this.javaTypeAdapter);
85 }
86
87 Class<?> itemType = getItemType();
88 if (!itemType.equals(javaTypeAdapter.getJavaClass())) {
89 throw new IllegalStateException(
90 String.format("Field '%s' on class '%s' has the '%s' type adapter configured," +
91 " but the field's item type '%s' does not match the adapter's type '%s'.",
92 getName(),
93 getContainingDefinition().getBoundClass().getName(),
94 javaTypeAdapter.getClass().getName(),
95 itemType.getName(),
96 javaTypeAdapter.getJavaClass().getName()));
97 }
98 this.definition = ObjectUtils.notNull(Lazy.lazy(() -> new ScalarFieldDefinition()));
99 }
100
101 @Override
102 public IBoundFieldDefinition getDefinition() {
103 return ObjectUtils.notNull(definition.get());
104 }
105
106 public IDataTypeAdapter<?> getJavaTypeAdapter() {
107 return javaTypeAdapter;
108 }
109
110 @Override
111 protected IDataTypeHandler newDataTypeHandler() {
112 return IDataTypeHandler.newDataTypeHandler(this);
113 }
114
115 @Override
116 public boolean isInXmlWrapped() {
117 return getFieldAnnotation().inXmlWrapped();
118 }
119
120 protected Object getDefaultValue() {
121 return defaultValue;
122 }
123
124 @Override
125 public String getUseName() {
126 return ModelUtil.resolveToString(getFieldAnnotation().useName());
127 }
128
129 @Override
130 public Object defaultValue() {
131 return getMaxOccurs() == 1 ? getDefaultValue() : getPropertyInfo().newPropertyCollector().getValue();
132 }
133
134 private final class ScalarFieldDefinition
135 implements IBoundFieldDefinition, IFeatureFlagContainer<IBoundFlagInstance> {
136 private final Lazy<IValueConstrained> constraints;
137
138 private ScalarFieldDefinition() {
139 this.constraints = Lazy.lazy(() -> new ValueConstraintSupport(
140 getField().getAnnotation(ValueConstraints.class),
141 InternalModelSource.instance()));
142 }
143
144 @Override
145 public IFlagContainerSupport<IBoundFlagInstance> getFlagContainer() {
146 return IFlagContainerSupport.empty();
147 }
148
149 @SuppressWarnings("null")
150 @Override
151 public IValueConstrained getConstraintSupport() {
152 return constraints.get();
153 }
154
155 @Override
156 public @NonNull Object getFieldValue(@NonNull Object item) {
157 return item;
158 }
159
160 @Override
161 public IDataTypeAdapter<?> getJavaTypeAdapter() {
162 return ObjectUtils.notNull(SimpleFieldProperty.this.getJavaTypeAdapter());
163 }
164
165 @Override
166 public boolean isInline() {
167 return true;
168 }
169
170 @Override
171 public IBoundFieldInstance getInlineInstance() {
172 return SimpleFieldProperty.this;
173 }
174
175 @Override
176 public String getFormalName() {
177 return SimpleFieldProperty.this.getFormalName();
178 }
179
180 @Override
181 public MarkupLine getDescription() {
182 return SimpleFieldProperty.this.getDescription();
183 }
184
185 @Override
186 public String getName() {
187 return getJavaFieldName();
188 }
189
190 @Override
191 public String getUseName() {
192 return ModelUtil.resolveToString(getFieldAnnotation().useName());
193 }
194
195 @Override
196 public MarkupMultiline getRemarks() {
197 return SimpleFieldProperty.this.getRemarks();
198 }
199
200 @Override
201 public String toCoordinates() {
202 return SimpleFieldProperty.this.toCoordinates();
203 }
204
205 @Override
206 public IBoundFlagInstance getFlagInstanceByName(String name) {
207
208 return null;
209 }
210
211 @Override
212 public Collection<? extends IBoundFlagInstance> getFlagInstances() {
213 return CollectionUtil.emptyList();
214 }
215
216 @Override
217 public boolean hasJsonKey() {
218 return false;
219 }
220
221 @Override
222 public IFlagInstance getJsonValueKeyFlagInstance() {
223 return null;
224 }
225
226 @Override
227 public String getJsonValueKeyName() {
228
229 return getJavaTypeAdapter().getDefaultJsonValueKey();
230 }
231
232 @Override
233 public @NonNull ModuleScopeEnum getModuleScope() {
234
235 return ModuleScopeEnum.INHERITED;
236 }
237
238 @Override
239 public IModule getContainingModule() {
240 return SimpleFieldProperty.this.getContainingModule();
241 }
242
243 @Override
244 public Object getDefaultValue() {
245 return SimpleFieldProperty.this.getDefaultValue();
246 }
247 }
248 }