View Javadoc
1   /*
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.oscal.lib.profile.resolver.selection;
28  
29  import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
30  import gov.nist.secauto.oscal.lib.model.Catalog;
31  import gov.nist.secauto.oscal.lib.model.CatalogGroup;
32  import gov.nist.secauto.oscal.lib.model.Control;
33  import gov.nist.secauto.oscal.lib.model.Parameter;
34  
35  import org.apache.logging.log4j.LogManager;
36  import org.apache.logging.log4j.Logger;
37  
38  import java.util.Collection;
39  import java.util.Collections;
40  import java.util.HashSet;
41  import java.util.LinkedHashSet;
42  import java.util.List;
43  import java.util.Set;
44  
45  import edu.umd.cs.findbugs.annotations.NonNull;
46  import nl.talsmasoftware.lazy4j.Lazy;
47  
48  public class DefaultResult implements IResult {
49    private static final Logger LOGGER = LogManager.getLogger(DefaultResult.class);
50  
51    @NonNull
52    private final Lazy<Set<Control>> promotedControls = ObjectUtils.notNull(Lazy.lazy(LinkedHashSet::new));
53    @NonNull
54    private final Lazy<Set<Parameter>> promotedParameters = ObjectUtils.notNull(Lazy.lazy(LinkedHashSet::new));
55    @NonNull
56    private final Lazy<Set<CatalogGroup>> removedGroups = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
57    @NonNull
58    private final Lazy<Set<Control>> removedControls = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
59    @NonNull
60    private final Lazy<Set<Parameter>> removedParameters = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
61  
62    @SuppressWarnings("null")
63    @NonNull
64    protected Collection<Parameter> getPromotedParameters() {
65      return promotedParameters.getIfAvailable().orElse(Collections.emptySet());
66    }
67  
68    @SuppressWarnings("null")
69    @NonNull
70    protected Collection<Control> getPromotedControls() {
71      return promotedControls.getIfAvailable().orElse(Collections.emptySet());
72    }
73  
74    @SuppressWarnings("null")
75    @NonNull
76    protected Collection<CatalogGroup> getRemovedGroups() {
77      return removedGroups.getIfAvailable().orElse(Collections.emptySet());
78    }
79  
80    @SuppressWarnings("null")
81    @NonNull
82    protected Collection<Control> getRemovedControls() {
83      return removedControls.getIfAvailable().orElse(Collections.emptySet());
84    }
85  
86    @SuppressWarnings("null")
87    @NonNull
88    protected Collection<Parameter> getRemovedParameters() {
89      return removedParameters.getIfAvailable().orElse(Collections.emptySet());
90    }
91  
92    @Override
93    public void promoteParameter(@NonNull Parameter param) {
94      if (LOGGER.isDebugEnabled()) {
95        LOGGER.atDebug().log("promoting parameter '{}'", param.getId());
96      }
97      promotedParameters.get().add(param);
98    }
99  
100   @Override
101   public void promoteControl(@NonNull Control control) {
102     if (LOGGER.isDebugEnabled()) {
103       LOGGER.atDebug().log("promoting control '{}'", control.getId());
104     }
105     promotedControls.get().add(control);
106   }
107 
108   @Override
109   public void applyTo(@NonNull Catalog parent) {
110     applyRemovesTo(parent);
111     getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
112     getPromotedControls().forEach(control -> {
113       assert control != null;
114       parent.addControl(control);
115       control.setParentControl(null);
116     });
117   }
118 
119   @Override
120   public void applyTo(@NonNull CatalogGroup parent) {
121     applyRemovesTo(parent);
122     getPromotedControls().forEach(control -> {
123       assert control != null;
124       parent.addControl(control);
125       control.setParentControl(null);
126     });
127     getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
128   }
129 
130   @Override
131   public void applyTo(@NonNull Control parent) {
132     applyRemovesTo(parent);
133     getPromotedControls().forEach(control -> {
134       assert control != null;
135       parent.addControl(control);
136       control.setParentControl(null);
137     });
138     getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
139   }
140 
141   public void applyRemovesTo(Catalog parent) {
142     removeItems(parent.getGroups(), getRemovedGroups());
143     removeItems(parent.getControls(), getRemovedControls());
144     removeItems(parent.getParams(), getRemovedParameters());
145   }
146 
147   public void applyRemovesTo(CatalogGroup parent) {
148     removeItems(parent.getGroups(), getRemovedGroups());
149     removeItems(parent.getControls(), getRemovedControls());
150     removeItems(parent.getParams(), getRemovedParameters());
151   }
152 
153   public void applyRemovesTo(Control parent) {
154     removeItems(parent.getControls(), getRemovedControls());
155     removeItems(parent.getParams(), getRemovedParameters());
156   }
157 
158   public DefaultResult append(@NonNull DefaultResult that) {
159     lazyAppend(promotedControls, that.promotedControls);
160     lazyAppend(promotedParameters, that.promotedParameters);
161     lazyAppend(removedGroups, that.removedGroups);
162     lazyAppend(removedControls, that.removedControls);
163     lazyAppend(removedParameters, that.removedParameters);
164     return this;
165   }
166 
167   public DefaultResult appendPromoted(@NonNull DefaultResult that) {
168     lazyAppend(promotedControls, that.promotedControls);
169     lazyAppend(promotedParameters, that.promotedParameters);
170     return this;
171   }
172 
173   protected static <T> void lazyAppend(@NonNull Lazy<Set<T>> self, @NonNull Lazy<Set<T>> other) {
174     if (other.isAvailable()) {
175       Set<T> otherSet = other.get();
176       if (!otherSet.isEmpty()) {
177         self.get().addAll(otherSet);
178       }
179     }
180   }
181 
182   protected static <T> void removeItems(List<T> list, @NonNull Collection<T> itemsToDelete) {
183     itemsToDelete.forEach(item -> {
184       if (!list.remove(item)) {
185         LOGGER.atError().log("item didn't exist in list");
186       }
187     });
188   }
189 
190   public void removeGroup(CatalogGroup group) {
191     if (LOGGER.isDebugEnabled()) {
192       LOGGER.atDebug().log("Requesting removal of group '{}'.", group.getId());
193     }
194     removedGroups.get().add(group);
195   }
196 
197   public void removeControl(Control control) {
198     if (LOGGER.isDebugEnabled()) {
199       LOGGER.atDebug().log("Requesting removal of control '{}'.", control.getId());
200     }
201     removedControls.get().add(control);
202   }
203 
204   public void removeParameter(Parameter parameter) {
205     if (LOGGER.isDebugEnabled()) {
206       LOGGER.atDebug().log("Requesting removal of parameter '{}'.", parameter.getId());
207     }
208     removedParameters.get().add(parameter);
209   }
210 }