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.oscal.lib.profile.resolver.support;
28
29 import gov.nist.secauto.metaschema.model.common.metapath.MetapathExpression;
30 import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem;
31 import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem;
32 import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem;
33 import gov.nist.secauto.metaschema.model.common.util.CollectionUtil;
34 import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
35
36 import java.util.Collections;
37 import java.util.EnumSet;
38 import java.util.Set;
39
40 import edu.umd.cs.findbugs.annotations.NonNull;
41
42
43
44
45
46
47
48
49
50
51
52
53 public abstract class AbstractCatalogEntityVisitor<T, R>
54 extends AbstractCatalogVisitor<T, R> {
55 @NonNull
56 public static final MetapathExpression CHILD_PART_METAPATH
57 = MetapathExpression.compile("part|part//part");
58 @NonNull
59 private static final MetapathExpression BACK_MATTER_RESOURCES_METAPATH
60 = MetapathExpression.compile("back-matter/resource");
61 @NonNull
62 private static final Set<IEntityItem.ItemType> GROUP_CONTAINER_TYPES
63 = ObjectUtils.notNull(EnumSet.of(
64 IEntityItem.ItemType.GROUP,
65 IEntityItem.ItemType.CONTROL,
66 IEntityItem.ItemType.PARAMETER,
67 IEntityItem.ItemType.PART));
68 @NonNull
69 private static final Set<IEntityItem.ItemType> CONTROL_CONTAINER_TYPES
70 = ObjectUtils.notNull(EnumSet.of(
71 IEntityItem.ItemType.CONTROL,
72 IEntityItem.ItemType.PARAMETER,
73 IEntityItem.ItemType.PART));
74 @NonNull
75 private final Set<IEntityItem.ItemType> itemTypesToVisit;
76
77
78
79
80
81
82
83
84 public AbstractCatalogEntityVisitor(@NonNull Set<IEntityItem.ItemType> itemTypesToVisit) {
85 this.itemTypesToVisit = CollectionUtil.unmodifiableSet(itemTypesToVisit);
86 }
87
88 public Set<IEntityItem.ItemType> getItemTypesToVisit() {
89 return CollectionUtil.unmodifiableSet(itemTypesToVisit);
90 }
91
92 protected boolean isVisitedItemType(@NonNull IEntityItem.ItemType type) {
93 return itemTypesToVisit.contains(type);
94 }
95
96 @Override
97 public R visitCatalog(IDocumentNodeItem catalogDocument, T state) {
98 R result = super.visitCatalog(catalogDocument, state);
99
100 IRootAssemblyNodeItem root = catalogDocument.getRootAssemblyNodeItem();
101 visitMetadata(root, state);
102 visitBackMatter(root, state);
103 return result;
104 }
105
106 @Override
107 protected R visitGroupContainer(IRequiredValueModelNodeItem catalogOrGroup, R initialResult, T state) {
108 R retval;
109 if (Collections.disjoint(getItemTypesToVisit(), GROUP_CONTAINER_TYPES)) {
110 retval = initialResult;
111 } else {
112 retval = super.visitGroupContainer(catalogOrGroup, initialResult, state);
113 }
114 return retval;
115 }
116
117 @Override
118 protected R visitControlContainer(IRequiredValueModelNodeItem catalogOrGroupOrControl, R initialResult, T state) {
119 R retval;
120 if (Collections.disjoint(getItemTypesToVisit(), CONTROL_CONTAINER_TYPES)) {
121 retval = initialResult;
122 } else {
123
124 retval = super.visitControlContainer(catalogOrGroupOrControl, initialResult, state);
125
126
127 if (isVisitedItemType(IEntityItem.ItemType.PARAMETER)) {
128 retval = catalogOrGroupOrControl.getModelItemsByName("param").stream()
129 .map(paramItem -> {
130 return visitParameter(ObjectUtils.requireNonNull(paramItem), catalogOrGroupOrControl, state);
131 })
132 .reduce(retval, (first, second) -> aggregateResults(first, second, state));
133 }
134 }
135 return retval;
136 }
137
138 protected void visitParts(@NonNull IRequiredValueModelNodeItem groupOrControlItem, T state) {
139
140 if (isVisitedItemType(IEntityItem.ItemType.PART)) {
141 CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream()
142 .map(item -> (IRequiredValueModelNodeItem) item)
143 .forEachOrdered(partItem -> {
144 visitPart(ObjectUtils.requireNonNull(partItem), groupOrControlItem, state);
145 });
146 }
147 }
148
149 @Override
150 protected R visitGroupInternal(@NonNull IRequiredValueModelNodeItem item, R childResult, T state) {
151 if (isVisitedItemType(IEntityItem.ItemType.PART)) {
152 visitParts(item, state);
153 }
154
155 R retval = childResult;
156 if (isVisitedItemType(IEntityItem.ItemType.GROUP)) {
157 retval = visitGroup(item, retval, state);
158 }
159 return retval;
160 }
161
162 @Override
163 protected R visitControlInternal(IRequiredValueModelNodeItem item, R childResult, T state) {
164 if (isVisitedItemType(IEntityItem.ItemType.PART)) {
165 visitParts(item, state);
166 }
167
168 R retval = childResult;
169 if (isVisitedItemType(IEntityItem.ItemType.CONTROL)) {
170 retval = visitControl(item, retval, state);
171 }
172 return retval;
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189 protected R visitParameter(
190 @NonNull IRequiredValueModelNodeItem item,
191 @NonNull IRequiredValueModelNodeItem catalogOrGroupOrControl,
192 T state) {
193
194 return newDefaultResult(state);
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 protected void visitPart(
211 @NonNull IRequiredValueModelNodeItem item,
212 @NonNull IRequiredValueModelNodeItem groupOrControl,
213 T state) {
214
215 }
216
217
218
219
220
221
222
223
224
225
226
227 protected void visitMetadata(@NonNull IRootAssemblyNodeItem rootItem, T state) {
228 rootItem.getModelItemsByName("metadata").forEach(metadataItem -> {
229 if (isVisitedItemType(IEntityItem.ItemType.ROLE)) {
230 metadataItem.getModelItemsByName("role").forEach(roleItem -> {
231 visitRole(ObjectUtils.requireNonNull(roleItem), metadataItem, state);
232 });
233 }
234
235 if (isVisitedItemType(IEntityItem.ItemType.LOCATION)) {
236 metadataItem.getModelItemsByName("location").forEach(locationItem -> {
237 visitLocation(ObjectUtils.requireNonNull(locationItem), metadataItem, state);
238 });
239 }
240
241 if (isVisitedItemType(IEntityItem.ItemType.PARTY)) {
242 metadataItem.getModelItemsByName("party").forEach(partyItem -> {
243 visitParty(ObjectUtils.requireNonNull(partyItem), metadataItem, state);
244 });
245 }
246 });
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263 protected void visitRole(
264 @NonNull IRequiredValueModelNodeItem item,
265 @NonNull IRequiredValueModelNodeItem metadataItem,
266 T state) {
267
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285 protected void visitLocation(
286 @NonNull IRequiredValueModelNodeItem item,
287 @NonNull IRequiredValueModelNodeItem metadataItem,
288 T state) {
289
290 }
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306 protected void visitParty(
307 @NonNull IRequiredValueModelNodeItem item,
308 @NonNull IRequiredValueModelNodeItem metadataItem,
309 T state) {
310
311 }
312
313
314
315
316
317
318
319
320
321
322
323 protected void visitBackMatter(@NonNull IRootAssemblyNodeItem rootItem, T state) {
324 if (isVisitedItemType(IEntityItem.ItemType.RESOURCE)) {
325 BACK_MATTER_RESOURCES_METAPATH.evaluate(rootItem).asStream()
326 .map(item -> (IRequiredValueModelNodeItem) item)
327 .forEachOrdered(resourceItem -> {
328 visitResource(ObjectUtils.requireNonNull(resourceItem), rootItem, state);
329 });
330 }
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348 protected void visitResource(
349 @NonNull IRequiredValueModelNodeItem item,
350 @NonNull IRootAssemblyNodeItem backMatterItem,
351 T state) {
352
353 }
354 }