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.IFlagContainerSupport;
30 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
31 import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag;
32 import gov.nist.secauto.metaschema.databind.model.annotations.Ignore;
33
34 import java.lang.reflect.Field;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.LinkedList;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.function.Consumer;
41 import java.util.function.Function;
42 import java.util.stream.Collectors;
43 import java.util.stream.Stream;
44
45 import edu.umd.cs.findbugs.annotations.NonNull;
46 import edu.umd.cs.findbugs.annotations.Nullable;
47
48 class ClassBindingFlagContainerSupport implements IFlagContainerSupport<IBoundFlagInstance> {
49 @NonNull
50 private final Map<String, IBoundFlagInstance> flagInstances;
51 @Nullable
52 private IBoundFlagInstance jsonKeyFlag;
53
54 @SuppressWarnings("PMD.ConstructorCallsOverridableMethod")
55 public ClassBindingFlagContainerSupport(
56 @NonNull IClassBinding classBinding,
57 @Nullable Consumer<IBoundFlagInstance> peeker) {
58 Class<?> clazz = classBinding.getBoundClass();
59
60 Stream<IBoundFlagInstance> instances = getFlagInstanceFields(clazz).stream()
61 .flatMap(field -> {
62 Stream<IBoundFlagInstance> stream;
63 if (field.isAnnotationPresent(BoundFlag.class)) {
64 stream = Stream.of(new DefaultFlagProperty(field, classBinding));
65 } else {
66 stream = Stream.empty();
67 }
68 return stream;
69 });
70
71 Consumer<IBoundFlagInstance> intermediate = this::handle;
72
73 if (peeker != null) {
74 intermediate = intermediate.andThen(peeker);
75 }
76
77 this.flagInstances = ObjectUtils.notNull(instances
78 .peek(intermediate)
79 .collect(Collectors.toUnmodifiableMap(
80 IBoundFlagInstance::getEffectiveName,
81 Function.identity())));
82 }
83
84 private void handle(IBoundFlagInstance instance) {
85 if (instance.isJsonKey()) {
86 this.jsonKeyFlag = instance;
87 }
88 }
89
90
91
92
93
94
95
96
97 @SuppressWarnings("PMD.UseArraysAsList")
98 @NonNull
99 protected static Collection<Field> getFlagInstanceFields(Class<?> clazz) {
100 Field[] fields = clazz.getDeclaredFields();
101
102 List<Field> retval = new LinkedList<>();
103
104 Class<?> superClass = clazz.getSuperclass();
105 if (superClass != null) {
106
107 retval.addAll(getFlagInstanceFields(superClass));
108 }
109
110 for (Field field : fields) {
111 if (!field.isAnnotationPresent(BoundFlag.class)) {
112
113 continue;
114 }
115
116 if (field.isAnnotationPresent(Ignore.class)) {
117
118 continue;
119 }
120
121 retval.add(field);
122 }
123 return ObjectUtils.notNull(Collections.unmodifiableCollection(retval));
124 }
125
126
127
128
129
130
131
132 protected void handleFlagInstance(IBoundFlagInstance instance) {
133 if (instance.isJsonKey()) {
134 this.jsonKeyFlag = instance;
135 }
136 }
137
138 @Override
139 @NonNull
140 public Map<String, IBoundFlagInstance> getFlagInstanceMap() {
141 return flagInstances;
142 }
143
144 @Override
145 public IBoundFlagInstance getJsonKeyFlagInstance() {
146 return jsonKeyFlag;
147 }
148 }