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.model.JsonGroupAsBehavior;
30 import gov.nist.secauto.metaschema.core.model.XmlGroupAsBehavior;
31 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
32 import gov.nist.secauto.metaschema.databind.io.BindingException;
33 import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs;
34 import gov.nist.secauto.metaschema.databind.model.info.IDataTypeHandler;
35 import gov.nist.secauto.metaschema.databind.model.info.IModelPropertyInfo;
36 import gov.nist.secauto.metaschema.databind.model.info.IPropertyCollector;
37
38 import java.lang.reflect.Field;
39 import java.util.Collection;
40
41 import edu.umd.cs.findbugs.annotations.NonNull;
42 import edu.umd.cs.findbugs.annotations.Nullable;
43 import nl.talsmasoftware.lazy4j.Lazy;
44
45 abstract class AbstractNamedModelProperty
46 extends AbstractProperty<IAssemblyClassBinding>
47 implements IBoundNamedModelInstance {
48
49
50
51 @NonNull
52 private static final IGroupAs SINGLETON_GROUP_AS = new IGroupAs() {
53 @Override
54 public String getGroupAsName() {
55 throw new UnsupportedOperationException();
56 }
57
58 @Override
59 public String getGroupAsXmlNamespace() {
60 throw new UnsupportedOperationException();
61 }
62
63 @Override
64 public JsonGroupAsBehavior getJsonGroupAsBehavior() {
65 return JsonGroupAsBehavior.NONE;
66 }
67
68 @Override
69 public XmlGroupAsBehavior getXmlGroupAsBehavior() {
70 return XmlGroupAsBehavior.UNGROUPED;
71 }
72 };
73
74 @NonNull
75 private final Field field;
76 @NonNull
77 private final IGroupAs groupAs;
78 @NonNull
79 private final Lazy<IModelPropertyInfo> propertyInfo;
80 @NonNull
81 private final Lazy<IDataTypeHandler> dataTypeHandler;
82
83
84
85
86
87
88
89
90
91
92
93 protected AbstractNamedModelProperty(
94 @NonNull Field field,
95 @NonNull IAssemblyClassBinding parentClassBinding) {
96 super(parentClassBinding);
97 this.field = ObjectUtils.requireNonNull(field, "field");
98
99 GroupAs annotation = field.getAnnotation(GroupAs.class);
100
101
102
103
104
105
106
107 this.groupAs = annotation == null ? SINGLETON_GROUP_AS : new SimpleGroupAs(annotation, parentClassBinding);
108 this.propertyInfo = ObjectUtils.notNull(Lazy.lazy(() -> IModelPropertyInfo.newPropertyInfo(this)));
109 this.dataTypeHandler = ObjectUtils.notNull(Lazy.lazy(this::newDataTypeHandler));
110
111 }
112
113
114 protected abstract IDataTypeHandler newDataTypeHandler();
115
116 @Override
117 public IDataTypeHandler getDataTypeHandler() {
118 return ObjectUtils.notNull(dataTypeHandler.get());
119 }
120
121 @Override
122 public Field getField() {
123 return field;
124 }
125
126 @Override
127 public abstract int getMinOccurs();
128
129 @Override
130 public abstract int getMaxOccurs();
131
132 @Override
133 public String getGroupAsName() {
134 return groupAs.getGroupAsName();
135 }
136
137 @Override
138 public String getGroupAsXmlNamespace() {
139 return groupAs.getGroupAsXmlNamespace();
140 }
141
142 @Override
143 public JsonGroupAsBehavior getJsonGroupAsBehavior() {
144 return groupAs.getJsonGroupAsBehavior();
145 }
146
147 @Override
148 public XmlGroupAsBehavior getXmlGroupAsBehavior() {
149 return groupAs.getXmlGroupAsBehavior();
150 }
151
152
153
154
155
156
157 @SuppressWarnings("null")
158 @Override
159 @NonNull
160 public IModelPropertyInfo getPropertyInfo() {
161 return propertyInfo.get();
162 }
163
164 @Override
165 public Collection<? extends Object> getItemValues(Object value) {
166 return getPropertyInfo().getItemsFromValue(value);
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 @Override
183 public void copyBoundObject(@NonNull Object fromInstance, @NonNull Object toInstance) throws BindingException {
184 Object value = getValue(fromInstance);
185 if (value != null) {
186 IModelPropertyInfo propertyInfo = getPropertyInfo();
187 IPropertyCollector collector = propertyInfo.newPropertyCollector();
188
189 propertyInfo.copy(fromInstance, toInstance, collector);
190
191 value = collector.getValue();
192 }
193 setValue(toInstance, value);
194 }
195
196 @Override
197 public Object copyItem(Object fromItem, Object toInstance) throws BindingException {
198 return getDataTypeHandler().copyItem(fromItem, toInstance);
199 }
200
201
202
203
204 private interface IGroupAs {
205 @NonNull
206 String getGroupAsName();
207
208 @Nullable
209 String getGroupAsXmlNamespace();
210
211 @NonNull
212 JsonGroupAsBehavior getJsonGroupAsBehavior();
213
214 @NonNull
215 XmlGroupAsBehavior getXmlGroupAsBehavior();
216 }
217
218 private static final class SimpleGroupAs implements IGroupAs {
219 @NonNull
220 private final String name;
221 @NonNull
222 private final Lazy<String> namespace;
223 @NonNull
224 private final GroupAs annotation;
225
226 private SimpleGroupAs(@NonNull GroupAs annotation, @NonNull IClassBinding parentDefinition) {
227 this.annotation = annotation;
228 {
229 String value = ModelUtil.resolveLocalName(annotation.name(), null);
230 if (value == null) {
231 throw new IllegalStateException(
232 String.format("The %s#groupName value '%s' resulted in an invalid null value",
233 GroupAs.class.getName(),
234 annotation.name()));
235 }
236 this.name = value;
237 }
238 this.namespace = ObjectUtils.notNull(
239 Lazy.lazy(() -> ModelUtil.resolveNamespace(annotation.namespace(), parentDefinition)));
240 }
241
242 @Override
243 public String getGroupAsName() {
244 return name;
245 }
246
247 @Override
248 public String getGroupAsXmlNamespace() {
249 return namespace.get();
250 }
251
252 @Override
253 public JsonGroupAsBehavior getJsonGroupAsBehavior() {
254 return annotation.inJson();
255 }
256
257 @Override
258 public XmlGroupAsBehavior getXmlGroupAsBehavior() {
259 return annotation.inXml();
260 }
261 }
262
263 }