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.merge;
28
29 import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem;
30 import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem;
31 import gov.nist.secauto.metaschema.model.common.metapath.item.IRootAssemblyNodeItem;
32 import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
33 import gov.nist.secauto.oscal.lib.model.BackMatter.Resource;
34 import gov.nist.secauto.oscal.lib.model.CatalogGroup;
35 import gov.nist.secauto.oscal.lib.model.Control;
36 import gov.nist.secauto.oscal.lib.model.ControlPart;
37 import gov.nist.secauto.oscal.lib.model.Metadata.Location;
38 import gov.nist.secauto.oscal.lib.model.Metadata.Party;
39 import gov.nist.secauto.oscal.lib.model.Metadata.Role;
40 import gov.nist.secauto.oscal.lib.model.Parameter;
41 import gov.nist.secauto.oscal.lib.profile.resolver.policy.ReferenceCountingVisitor;
42 import gov.nist.secauto.oscal.lib.profile.resolver.selection.DefaultResult;
43 import gov.nist.secauto.oscal.lib.profile.resolver.selection.FilterNonSelectedVisitor;
44 import gov.nist.secauto.oscal.lib.profile.resolver.support.AbstractCatalogEntityVisitor;
45 import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem;
46 import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem.ItemType;
47 import gov.nist.secauto.oscal.lib.profile.resolver.support.IIndexer;
48 import gov.nist.secauto.oscal.lib.profile.resolver.support.IIndexer.SelectionStatus;
49
50 import java.util.EnumSet;
51 import java.util.UUID;
52
53 import edu.umd.cs.findbugs.annotations.NonNull;
54
55 public class FlatteningStructuringVisitor
56 extends AbstractCatalogEntityVisitor<IIndexer, Void> {
57 private static final FlatteningStructuringVisitor SINGLETON = new FlatteningStructuringVisitor();
58
59 public static FlatteningStructuringVisitor instance() {
60 return SINGLETON;
61 }
62
63 public FlatteningStructuringVisitor() {
64 super(ObjectUtils.notNull(EnumSet.of(ItemType.GROUP, ItemType.CONTROL)));
65 }
66
67 @Override
68 protected Void newDefaultResult(IIndexer state) {
69
70 return null;
71 }
72
73 @Override
74 protected Void aggregateResults(Void first, Void second, IIndexer state) {
75
76 return null;
77 }
78
79 @Override
80 public Void visitCatalog(@NonNull IDocumentNodeItem catalogItem, IIndexer index) {
81 index.resetSelectionStatus();
82
83 index.setSelectionStatus(catalogItem, SelectionStatus.SELECTED);
84 super.visitCatalog(catalogItem, index);
85
86 for (ItemType itemType : ItemType.values()) {
87 assert itemType != null;
88 for (IEntityItem item : index.getEntitiesByItemType(itemType)) {
89 item.resetReferenceCount();
90 }
91 }
92
93
94 ReferenceCountingVisitor.instance().visitCatalog(catalogItem, index, catalogItem.getDocumentUri());
95
96 FlatteningFilterNonSelectedVisitor.instance().visitCatalog(catalogItem, index);
97 return null;
98 }
99
100 @Override
101 public Void visitGroup(IRequiredValueModelNodeItem item, Void childResult, IIndexer index) {
102 CatalogGroup group = (CatalogGroup) item.getValue();
103 String id = group.getId();
104 if (id != null) {
105 IEntityItem entity = index.getEntity(ItemType.GROUP, id);
106 assert entity != null;
107
108 entity.setInstance(item);
109 }
110
111 index.setSelectionStatus(item, SelectionStatus.UNSELECTED);
112 handlePartSelection(item, index, SelectionStatus.UNSELECTED);
113 return super.visitGroup(item, childResult, index);
114 }
115
116 @Override
117 public Void visitControl(IRequiredValueModelNodeItem item, Void childResult, IIndexer index) {
118 Control control = (Control) item.getValue();
119 String id = ObjectUtils.requireNonNull(control.getId());
120 IEntityItem entity = index.getEntity(ItemType.CONTROL, id);
121 assert entity != null;
122
123 entity.setInstance(item);
124
125 index.setSelectionStatus(item, SelectionStatus.SELECTED);
126 handlePartSelection(item, index, SelectionStatus.SELECTED);
127 return null;
128 }
129
130 @Override
131 protected Void visitParameter(IRequiredValueModelNodeItem item,
132 IRequiredValueModelNodeItem catalogOrGroupOrControl, IIndexer index) {
133 Parameter parameter = (Parameter) item.getValue();
134 String id = ObjectUtils.requireNonNull(parameter.getId());
135 IEntityItem entity = index.getEntity(ItemType.PARAMETER, id);
136 assert entity != null;
137
138 entity.setInstance(item);
139
140 return null;
141 }
142
143 @Override
144 protected void visitRole(IRequiredValueModelNodeItem item, IRequiredValueModelNodeItem metadataItem,
145 IIndexer index) {
146 Role role = (Role) item.getValue();
147 String id = ObjectUtils.requireNonNull(role.getId());
148 IEntityItem entity = index.getEntity(ItemType.ROLE, id);
149 assert entity != null;
150
151 entity.setInstance(item);
152 }
153
154 @Override
155 protected void visitLocation(IRequiredValueModelNodeItem item, IRequiredValueModelNodeItem metadataItem,
156 IIndexer index) {
157 Location location = (Location) item.getValue();
158 UUID uuid = ObjectUtils.requireNonNull(location.getUuid());
159 IEntityItem entity = index.getEntity(ItemType.LOCATION, uuid);
160 assert entity != null;
161
162 entity.setInstance(item);
163 }
164
165 @Override
166 protected void visitParty(IRequiredValueModelNodeItem item, IRequiredValueModelNodeItem metadataItem,
167 IIndexer index) {
168 Party location = (Party) item.getValue();
169 UUID uuid = ObjectUtils.requireNonNull(location.getUuid());
170 IEntityItem entity = index.getEntity(ItemType.PARTY, uuid);
171 assert entity != null;
172
173 entity.setInstance(item);
174 }
175
176 @Override
177 protected void visitResource(IRequiredValueModelNodeItem item, IRootAssemblyNodeItem rootItem,
178 IIndexer index) {
179 Resource location = (Resource) item.getValue();
180 UUID uuid = ObjectUtils.requireNonNull(location.getUuid());
181 IEntityItem entity = index.getEntity(ItemType.RESOURCE, uuid);
182 assert entity != null;
183
184 entity.setInstance(item);
185 }
186
187 private static void handlePartSelection(
188 @NonNull IRequiredValueModelNodeItem groupOrControlItem,
189 @NonNull IIndexer index,
190 @NonNull SelectionStatus selectionStatus) {
191 CHILD_PART_METAPATH.evaluate(groupOrControlItem).asStream()
192 .map(item -> (IRequiredValueModelNodeItem) item)
193 .forEachOrdered(partItem -> {
194 index.setSelectionStatus(ObjectUtils.requireNonNull(partItem), selectionStatus);
195
196 ControlPart part = (ControlPart) partItem.getValue();
197 String id = part.getId();
198 if (id != null) {
199 IEntityItem entity = index.getEntity(ItemType.PART, id);
200 assert entity != null;
201
202 entity.setInstance(partItem);
203 }
204 });
205 }
206
207 private static final class FlatteningFilterNonSelectedVisitor
208 extends FilterNonSelectedVisitor {
209 private static final FlatteningFilterNonSelectedVisitor SINGLETON = new FlatteningFilterNonSelectedVisitor();
210
211 public static FlatteningFilterNonSelectedVisitor instance() {
212 return SINGLETON;
213 }
214
215 @Override
216 public DefaultResult visitControl(IRequiredValueModelNodeItem item, DefaultResult childResult,
217 Context context) {
218 assert childResult != null;
219
220 Control control = (Control) item.getValue();
221 IIndexer index = context.getIndexer();
222
223 IEntityItem entity = ObjectUtils.requireNonNull(
224 index.getEntity(ItemType.CONTROL, ObjectUtils.requireNonNull(control.getId()), false));
225
226 IRequiredValueModelNodeItem parent = ObjectUtils.notNull(item.getParentContentNodeItem());
227 DefaultResult retval = new DefaultResult();
228 if (SelectionStatus.SELECTED.equals(index.getSelectionStatus(item))) {
229
230
231
232 retval.promoteControl(control);
233
234 retval.appendPromoted(childResult);
235 childResult.applyRemovesTo(control);
236
237 if (parent.getValue() instanceof Control && SelectionStatus.SELECTED.equals(index.getSelectionStatus(parent))) {
238 retval.removeControl(control);
239 }
240 } else {
241
242
243 if (SelectionStatus.SELECTED.equals(index.getSelectionStatus(parent))) {
244 retval.removeControl(control);
245 }
246 retval.appendPromoted(ObjectUtils.notNull(childResult));
247 index.removeItem(entity);
248
249
250 removePartsFromIndex(item, index);
251 }
252 return retval;
253 }
254 }
255 }