1
2
3
4
5
6 package gov.nist.secauto.metaschema.databind.model.info;
7
8 import gov.nist.secauto.metaschema.core.model.IBoundObject;
9 import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior;
10 import gov.nist.secauto.metaschema.databind.io.BindingException;
11 import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModel;
12
13 import java.io.IOException;
14 import java.lang.reflect.Field;
15 import java.lang.reflect.ParameterizedType;
16 import java.lang.reflect.Type;
17 import java.util.Collection;
18 import java.util.List;
19 import java.util.Map;
20
21 import edu.umd.cs.findbugs.annotations.NonNull;
22 import edu.umd.cs.findbugs.annotations.Nullable;
23
24
25 public interface IModelInstanceCollectionInfo<ITEM> {
26
27 @SuppressWarnings("PMD.ShortMethodName")
28 @NonNull
29 static <T> IModelInstanceCollectionInfo<T> of(
30 @NonNull IBoundInstanceModel<T> instance) {
31
32
33 Type type = instance.getType();
34 Field field = instance.getField();
35
36 IModelInstanceCollectionInfo<T> retval;
37 if (instance.getMaxOccurs() == -1 || instance.getMaxOccurs() > 1) {
38
39 JsonGroupAsBehavior jsonGroupAs = instance.getJsonGroupAsBehavior();
40
41
42 if (!(type instanceof ParameterizedType)) {
43 switch (jsonGroupAs) {
44 case KEYED:
45 throw new IllegalStateException(
46 String.format("The field '%s' on class '%s' has data type of '%s'," + " but should have a type of '%s'.",
47 field.getName(),
48 field.getDeclaringClass().getName(),
49 field.getType().getName(), Map.class.getName()));
50 case LIST:
51 case SINGLETON_OR_LIST:
52 throw new IllegalStateException(
53 String.format("The field '%s' on class '%s' has data type of '%s'," + " but should have a type of '%s'.",
54 field.getName(),
55 field.getDeclaringClass().getName(),
56 field.getType().getName(), List.class.getName()));
57 default:
58
59 throw new IllegalStateException(jsonGroupAs.name());
60 }
61 }
62
63 Class<?> rawType = (Class<?>) ((ParameterizedType) type).getRawType();
64 if (JsonGroupAsBehavior.KEYED.equals(jsonGroupAs)) {
65 if (!Map.class.isAssignableFrom(rawType)) {
66 throw new IllegalArgumentException(String.format(
67 "The field '%s' on class '%s' has data type '%s', which is not the expected '%s' derived data type.",
68 field.getName(),
69 field.getDeclaringClass().getName(),
70 field.getType().getName(),
71 Map.class.getName()));
72 }
73 retval = new MapCollectionInfo<>(instance);
74 } else {
75 if (!List.class.isAssignableFrom(rawType)) {
76 throw new IllegalArgumentException(String.format(
77 "The field '%s' on class '%s' has data type '%s', which is not the expected '%s' derived data type.",
78 field.getName(),
79 field.getDeclaringClass().getName(),
80 field.getType().getName(),
81 List.class.getName()));
82 }
83 retval = new ListCollectionInfo<>(instance);
84 }
85 } else {
86
87 if (type instanceof ParameterizedType) {
88 throw new IllegalStateException(String.format(
89 "The field '%s' on class '%s' has a data parmeterized type of '%s',"
90 + " but the occurance is not multi-valued.",
91 field.getName(),
92 field.getDeclaringClass().getName(),
93 field.getType().getName()));
94 }
95 retval = new SingletonCollectionInfo<>(instance);
96 }
97 return retval;
98 }
99
100
101
102
103
104
105 @NonNull
106 IBoundInstanceModel<ITEM> getInstance();
107
108
109
110
111
112
113
114
115 int size(@Nullable Object value);
116
117
118
119
120
121
122
123
124
125 boolean isEmpty(@Nullable Object value);
126
127
128
129
130
131
132 @NonNull
133 Class<? extends ITEM> getItemType();
134
135 @NonNull
136 default Collection<? extends ITEM> getItemsFromParentInstance(@NonNull Object parentInstance) {
137 Object value = getInstance().getValue(parentInstance);
138 return getItemsFromValue(value);
139 }
140
141 @NonNull
142 Collection<? extends ITEM> getItemsFromValue(Object value);
143
144 Object emptyValue();
145
146 Object deepCopyItems(@NonNull IBoundObject fromObject, @NonNull IBoundObject toObject) throws BindingException;
147
148
149
150
151
152
153
154
155
156
157
158
159
160 @Nullable
161 Object readItems(@NonNull IModelInstanceReadHandler<ITEM> handler) throws IOException;
162
163 void writeItems(
164 @NonNull IModelInstanceWriteHandler<ITEM> handler,
165 @NonNull Object value) throws IOException;
166 }