1
2
3
4
5
6 package dev.metaschema.databind.model.impl;
7
8 import java.lang.reflect.Field;
9 import java.util.Arrays;
10 import java.util.LinkedHashMap;
11 import java.util.Map;
12 import java.util.Optional;
13 import java.util.Set;
14 import java.util.stream.Collectors;
15
16 import dev.metaschema.core.datatype.IDataTypeAdapter;
17 import dev.metaschema.core.datatype.markup.MarkupLine;
18 import dev.metaschema.core.datatype.markup.MarkupMultiline;
19 import dev.metaschema.core.model.AbstractInlineFlagDefinition;
20 import dev.metaschema.core.model.IAttributable;
21 import dev.metaschema.core.model.IBoundObject;
22 import dev.metaschema.core.model.IModule;
23 import dev.metaschema.core.model.ISource;
24 import dev.metaschema.core.model.constraint.IValueConstrained;
25 import dev.metaschema.core.model.constraint.ValueConstraintSet;
26 import dev.metaschema.core.util.CollectionUtil;
27 import dev.metaschema.core.util.ObjectUtils;
28 import dev.metaschema.databind.model.IBoundDefinitionFlag;
29 import dev.metaschema.databind.model.IBoundDefinitionModel;
30 import dev.metaschema.databind.model.IBoundInstanceFlag;
31 import dev.metaschema.databind.model.IBoundModule;
32 import dev.metaschema.databind.model.annotations.BoundFlag;
33 import dev.metaschema.databind.model.annotations.JsonFieldValueKeyFlag;
34 import dev.metaschema.databind.model.annotations.JsonKey;
35 import dev.metaschema.databind.model.annotations.ModelUtil;
36 import dev.metaschema.databind.model.annotations.ValueConstraints;
37 import edu.umd.cs.findbugs.annotations.NonNull;
38 import edu.umd.cs.findbugs.annotations.Nullable;
39 import nl.talsmasoftware.lazy4j.Lazy;
40
41
42
43
44
45 public class InstanceFlagInline
46 extends AbstractInlineFlagDefinition<IBoundDefinitionModel<IBoundObject>, IBoundDefinitionFlag, IBoundInstanceFlag>
47 implements IBoundInstanceFlag {
48 @NonNull
49 private final Field javaField;
50 @NonNull
51 private final BoundFlag annotation;
52 @NonNull
53 private final IDataTypeAdapter<?> javaTypeAdapter;
54 @Nullable
55 private final Object defaultValue;
56 @NonNull
57 private final Lazy<IValueConstrained> constraints;
58 @NonNull
59 private final Lazy<Map<IAttributable.Key, Set<String>>> properties;
60
61
62
63
64
65
66
67
68
69 public InstanceFlagInline(
70 @NonNull Field javaField,
71 @NonNull IBoundDefinitionModel<IBoundObject> parent) {
72 super(parent);
73 FieldSupport.bindField(javaField);
74 this.javaField = javaField;
75 this.annotation = ModelUtil.getAnnotation(javaField, BoundFlag.class);
76 Class<? extends IDataTypeAdapter<?>> adapterClass = ObjectUtils.notNull(getAnnotation().typeAdapter());
77 this.javaTypeAdapter = ModelUtil.getDataTypeAdapter(
78 adapterClass,
79 parent.getBindingContext());
80 this.defaultValue = ModelUtil.resolveDefaultValue(getAnnotation().defaultValue(), this.javaTypeAdapter);
81
82 IModule module = parent.getContainingModule();
83 ISource source = module.getSource();
84
85 this.constraints = ObjectUtils.notNull(Lazy.of(() -> {
86 IValueConstrained retval = new ValueConstraintSet(source);
87 ValueConstraints valueAnnotation = getAnnotation().valueConstraints();
88 ConstraintSupport.parse(valueAnnotation, source, retval);
89 return retval;
90 }));
91 this.properties = ObjectUtils.notNull(
92 Lazy.of(() -> CollectionUtil.unmodifiableMap(ObjectUtils.notNull(
93 Arrays.stream(annotation.properties())
94 .map(ModelUtil::toPropertyEntry)
95 .collect(
96 Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2, LinkedHashMap::new))))));
97 }
98
99
100
101
102
103
104 @Override
105 @NonNull
106 public Field getField() {
107 return javaField;
108 }
109
110
111
112
113
114
115 @NonNull
116 private BoundFlag getAnnotation() {
117 return annotation;
118 }
119
120 @Override
121 public IBoundModule getContainingModule() {
122 return getContainingDefinition().getContainingModule();
123 }
124
125
126
127
128
129 @SuppressWarnings("null")
130 @Override
131 @NonNull
132 public IValueConstrained getConstraintSupport() {
133 return constraints.get();
134 }
135
136 @Override
137 public boolean isRequired() {
138 return getAnnotation().required();
139 }
140
141 @Override
142 public Object getDefaultValue() {
143 return defaultValue;
144 }
145
146 @Override
147 public boolean isJsonKey() {
148 return getField().isAnnotationPresent(JsonKey.class);
149 }
150
151 @Override
152 public boolean isJsonValueKey() {
153 return getField().isAnnotationPresent(JsonFieldValueKeyFlag.class);
154 }
155
156 @Override
157 public IDataTypeAdapter<?> getJavaTypeAdapter() {
158 return javaTypeAdapter;
159 }
160
161 @Override
162 @Nullable
163 public String getFormalName() {
164 return ModelUtil.resolveNoneOrValue(getAnnotation().formalName());
165 }
166
167 @Override
168 @Nullable
169 public MarkupLine getDescription() {
170 return ModelUtil.resolveToMarkupLine(getAnnotation().description());
171 }
172
173 @Override
174 public String getName() {
175 return ObjectUtils.notNull(
176 Optional.ofNullable(ModelUtil.resolveNoneOrValue(getAnnotation().name())).orElse(getField().getName()));
177 }
178
179 @Override
180 public Integer getUseIndex() {
181 return getAnnotation().useIndex();
182 }
183
184 @Override
185 public Map<Key, Set<String>> getProperties() {
186 return ObjectUtils.notNull(properties.get());
187 }
188
189 @Override
190 @Nullable
191 public MarkupMultiline getRemarks() {
192 return ModelUtil.resolveToMarkupMultiline(getAnnotation().remarks());
193 }
194
195
196
197
198 }