1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.oscal.lib.profile.resolver.selection;
7   
8   import gov.nist.secauto.metaschema.core.util.ObjectUtils;
9   import gov.nist.secauto.oscal.lib.model.Catalog;
10  import gov.nist.secauto.oscal.lib.model.CatalogGroup;
11  import gov.nist.secauto.oscal.lib.model.Control;
12  import gov.nist.secauto.oscal.lib.model.Parameter;
13  
14  import org.apache.logging.log4j.LogManager;
15  import org.apache.logging.log4j.Logger;
16  
17  import java.util.Collection;
18  import java.util.Collections;
19  import java.util.HashSet;
20  import java.util.LinkedHashSet;
21  import java.util.List;
22  import java.util.Set;
23  
24  import edu.umd.cs.findbugs.annotations.NonNull;
25  import nl.talsmasoftware.lazy4j.Lazy;
26  
27  public class DefaultResult implements IResult {
28    private static final Logger LOGGER = LogManager.getLogger(DefaultResult.class);
29  
30    @NonNull
31    private final Lazy<Set<Control>> promotedControls = ObjectUtils.notNull(Lazy.lazy(LinkedHashSet::new));
32    @NonNull
33    private final Lazy<Set<Parameter>> promotedParameters = ObjectUtils.notNull(Lazy.lazy(LinkedHashSet::new));
34    @NonNull
35    private final Lazy<Set<CatalogGroup>> removedGroups = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
36    @NonNull
37    private final Lazy<Set<Control>> removedControls = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
38    @NonNull
39    private final Lazy<Set<Parameter>> removedParameters = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
40  
41    @SuppressWarnings("null")
42    @NonNull
43    protected Collection<Parameter> getPromotedParameters() {
44      return promotedParameters.getIfAvailable().orElse(Collections.emptySet());
45    }
46  
47    @SuppressWarnings("null")
48    @NonNull
49    protected Collection<Control> getPromotedControls() {
50      return promotedControls.getIfAvailable().orElse(Collections.emptySet());
51    }
52  
53    @SuppressWarnings("null")
54    @NonNull
55    protected Collection<CatalogGroup> getRemovedGroups() {
56      return removedGroups.getIfAvailable().orElse(Collections.emptySet());
57    }
58  
59    @SuppressWarnings("null")
60    @NonNull
61    protected Collection<Control> getRemovedControls() {
62      return removedControls.getIfAvailable().orElse(Collections.emptySet());
63    }
64  
65    @SuppressWarnings("null")
66    @NonNull
67    protected Collection<Parameter> getRemovedParameters() {
68      return removedParameters.getIfAvailable().orElse(Collections.emptySet());
69    }
70  
71    @Override
72    public void promoteParameter(@NonNull Parameter param) {
73      if (LOGGER.isDebugEnabled()) {
74        LOGGER.atDebug().log("promoting parameter '{}'", param.getId());
75      }
76      promotedParameters.get().add(param);
77    }
78  
79    @Override
80    public void promoteControl(@NonNull Control control) {
81      if (LOGGER.isDebugEnabled()) {
82        LOGGER.atDebug().log("promoting control '{}'", control.getId());
83      }
84      // promote
85      promotedControls.get().add(control);
86    }
87  
88    @Override
89    public void applyTo(@NonNull Catalog parent) {
90      applyRemovesTo(parent);
91      getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
92      getPromotedControls().forEach(control -> {
93        assert control != null;
94        // add promoted control
95        parent.addControl(control);
96        control.setParentControl(null);
97      });
98    }
99  
100   @Override
101   public void applyTo(@NonNull CatalogGroup parent) {
102     applyRemovesTo(parent);
103     getPromotedControls().forEach(control -> {
104       assert control != null;
105       parent.addControl(control);
106       control.setParentControl(null);
107     });
108     getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
109   }
110 
111   @Override
112   public void applyTo(@NonNull Control parent) {
113     applyRemovesTo(parent);
114     getPromotedControls().forEach(control -> {
115       assert control != null;
116       parent.addControl(control);
117       control.setParentControl(null);
118     });
119     getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
120   }
121 
122   public void applyRemovesTo(Catalog parent) {
123     removeItems(parent.getGroups(), getRemovedGroups());
124     removeItems(parent.getControls(), getRemovedControls());
125     removeItems(parent.getParams(), getRemovedParameters());
126   }
127 
128   public void applyRemovesTo(CatalogGroup parent) {
129     removeItems(parent.getGroups(), getRemovedGroups());
130     removeItems(parent.getControls(), getRemovedControls());
131     removeItems(parent.getParams(), getRemovedParameters());
132   }
133 
134   public void applyRemovesTo(Control parent) {
135     removeItems(parent.getControls(), getRemovedControls());
136     removeItems(parent.getParams(), getRemovedParameters());
137   }
138 
139   public DefaultResult append(@NonNull DefaultResult that) {
140     lazyAppend(promotedControls, that.promotedControls);
141     lazyAppend(promotedParameters, that.promotedParameters);
142     lazyAppend(removedGroups, that.removedGroups);
143     lazyAppend(removedControls, that.removedControls);
144     lazyAppend(removedParameters, that.removedParameters);
145     return this;
146   }
147 
148   public DefaultResult appendPromoted(@NonNull DefaultResult that) {
149     lazyAppend(promotedControls, that.promotedControls);
150     lazyAppend(promotedParameters, that.promotedParameters);
151     return this;
152   }
153 
154   protected static <T> void lazyAppend(@NonNull Lazy<Set<T>> self, @NonNull Lazy<Set<T>> other) {
155     if (other.isAvailable()) {
156       Set<T> otherSet = other.get();
157       if (!otherSet.isEmpty()) {
158         self.get().addAll(otherSet);
159       }
160     }
161   }
162 
163   protected static <T> void removeItems(List<T> list, @NonNull Collection<T> itemsToDelete) {
164     itemsToDelete.forEach(item -> {
165       if (!list.remove(item)) {
166         LOGGER.atError().log("item didn't exist in list");
167       }
168     });
169   }
170 
171   public void removeGroup(CatalogGroup group) {
172     if (LOGGER.isDebugEnabled()) {
173       LOGGER.atDebug().log("Requesting removal of group '{}'.", group.getId());
174     }
175     removedGroups.get().add(group);
176   }
177 
178   public void removeControl(Control control) {
179     if (LOGGER.isDebugEnabled()) {
180       LOGGER.atDebug().log("Requesting removal of control '{}'.", control.getId());
181     }
182     removedControls.get().add(control);
183   }
184 
185   public void removeParameter(Parameter parameter) {
186     if (LOGGER.isDebugEnabled()) {
187       LOGGER.atDebug().log("Requesting removal of parameter '{}'.", parameter.getId());
188     }
189     removedParameters.get().add(parameter);
190   }
191 }