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