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