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