1
2
3
4
5
6 package dev.metaschema.databind.model;
7
8 import java.lang.reflect.Field;
9 import java.lang.reflect.ParameterizedType;
10 import java.lang.reflect.Type;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.Map;
14
15 import dev.metaschema.core.model.IBoundObject;
16 import dev.metaschema.core.model.IModelInstanceAbsolute;
17 import dev.metaschema.core.util.ObjectUtils;
18 import dev.metaschema.databind.io.BindingException;
19 import dev.metaschema.databind.model.info.IModelInstanceCollectionInfo;
20 import edu.umd.cs.findbugs.annotations.NonNull;
21 import edu.umd.cs.findbugs.annotations.Nullable;
22
23
24
25
26
27
28
29 public interface IBoundInstanceModel<ITEM>
30 extends IBoundInstance<ITEM>, IModelInstanceAbsolute {
31
32
33
34
35
36
37
38
39 @NonNull
40 static Class<?> getItemType(@NonNull Field field) {
41 Type fieldType = field.getGenericType();
42 Class<?> rawType = ObjectUtils.notNull(
43 (Class<?>) (fieldType instanceof ParameterizedType ? ((ParameterizedType) fieldType).getRawType() : fieldType));
44
45 Class<?> itemType;
46 if (Map.class.isAssignableFrom(rawType)) {
47
48 itemType = ObjectUtils.notNull((Class<?>) ((ParameterizedType) fieldType).getActualTypeArguments()[1]);
49 } else if (List.class.isAssignableFrom(rawType)) {
50
51 itemType = ObjectUtils.notNull((Class<?>) ((ParameterizedType) fieldType).getActualTypeArguments()[0]);
52 } else {
53
54 itemType = rawType;
55 }
56 return itemType;
57 }
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 @NonNull
73 static <TYPE> Class<? extends TYPE> getItemType(@NonNull Field field, @NonNull Class<TYPE> expectedItemType) {
74 Type fieldType = field.getGenericType();
75 Class<?> rawType = ObjectUtils.notNull(
76 (Class<?>) (fieldType instanceof ParameterizedType ? ((ParameterizedType) fieldType).getRawType() : fieldType));
77
78 Class<?> itemType;
79 if (Map.class.isAssignableFrom(rawType)) {
80
81 itemType = ObjectUtils.notNull((Class<?>) ((ParameterizedType) fieldType).getActualTypeArguments()[1]);
82 } else if (List.class.isAssignableFrom(rawType)) {
83
84 itemType = ObjectUtils.notNull((Class<?>) ((ParameterizedType) fieldType).getActualTypeArguments()[0]);
85 } else {
86
87 itemType = rawType;
88 }
89 return ObjectUtils.notNull(itemType.asSubclass(expectedItemType));
90 }
91
92 @Override
93 @NonNull
94 IBoundDefinitionModelAssembly getContainingDefinition();
95
96 @Override
97 default Object getResolvedDefaultValue() {
98 return getMaxOccurs() == 1 ? getEffectiveDefaultValue() : getCollectionInfo().emptyValue();
99 }
100
101
102
103
104
105
106
107
108 @Override
109 @NonNull
110 default Collection<? extends Object> getItemValues(Object value) {
111 return getCollectionInfo().getItemsFromValue(value);
112 }
113
114
115
116
117
118
119
120 @NonNull
121 IModelInstanceCollectionInfo<ITEM> getCollectionInfo();
122
123
124
125
126
127
128
129
130 @Nullable
131 IBoundInstanceFlag getItemJsonKey(@NonNull Object item);
132
133 @Override
134 default void deepCopy(@NonNull IBoundObject fromInstance, @NonNull IBoundObject toInstance) throws BindingException {
135 Object value = getValue(fromInstance);
136 if (value != null) {
137 value = getCollectionInfo().deepCopyItems(fromInstance, toInstance);
138 }
139 setValue(toInstance, value);
140 }
141 }