001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package gov.nist.secauto.oscal.lib.profile.resolver.selection;
007
008import gov.nist.secauto.metaschema.core.util.ObjectUtils;
009import gov.nist.secauto.oscal.lib.model.Catalog;
010import gov.nist.secauto.oscal.lib.model.CatalogGroup;
011import gov.nist.secauto.oscal.lib.model.Control;
012import gov.nist.secauto.oscal.lib.model.Parameter;
013
014import org.apache.logging.log4j.LogManager;
015import org.apache.logging.log4j.Logger;
016
017import java.util.Collection;
018import java.util.Collections;
019import java.util.HashSet;
020import java.util.LinkedHashSet;
021import java.util.List;
022import java.util.Set;
023
024import edu.umd.cs.findbugs.annotations.NonNull;
025import nl.talsmasoftware.lazy4j.Lazy;
026
027public class DefaultResult implements IResult {
028  private static final Logger LOGGER = LogManager.getLogger(DefaultResult.class);
029
030  @NonNull
031  private final Lazy<Set<Control>> promotedControls = ObjectUtils.notNull(Lazy.lazy(LinkedHashSet::new));
032  @NonNull
033  private final Lazy<Set<Parameter>> promotedParameters = ObjectUtils.notNull(Lazy.lazy(LinkedHashSet::new));
034  @NonNull
035  private final Lazy<Set<CatalogGroup>> removedGroups = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
036  @NonNull
037  private final Lazy<Set<Control>> removedControls = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
038  @NonNull
039  private final Lazy<Set<Parameter>> removedParameters = ObjectUtils.notNull(Lazy.lazy(HashSet::new));
040
041  @SuppressWarnings("null")
042  @NonNull
043  protected Collection<Parameter> getPromotedParameters() {
044    return promotedParameters.getIfAvailable().orElse(Collections.emptySet());
045  }
046
047  @SuppressWarnings("null")
048  @NonNull
049  protected Collection<Control> getPromotedControls() {
050    return promotedControls.getIfAvailable().orElse(Collections.emptySet());
051  }
052
053  @SuppressWarnings("null")
054  @NonNull
055  protected Collection<CatalogGroup> getRemovedGroups() {
056    return removedGroups.getIfAvailable().orElse(Collections.emptySet());
057  }
058
059  @SuppressWarnings("null")
060  @NonNull
061  protected Collection<Control> getRemovedControls() {
062    return removedControls.getIfAvailable().orElse(Collections.emptySet());
063  }
064
065  @SuppressWarnings("null")
066  @NonNull
067  protected Collection<Parameter> getRemovedParameters() {
068    return removedParameters.getIfAvailable().orElse(Collections.emptySet());
069  }
070
071  @Override
072  public void promoteParameter(@NonNull Parameter param) {
073    if (LOGGER.isDebugEnabled()) {
074      LOGGER.atDebug().log("promoting parameter '{}'", param.getId());
075    }
076    promotedParameters.get().add(param);
077  }
078
079  @Override
080  public void promoteControl(@NonNull Control control) {
081    if (LOGGER.isDebugEnabled()) {
082      LOGGER.atDebug().log("promoting control '{}'", control.getId());
083    }
084    // promote
085    promotedControls.get().add(control);
086  }
087
088  @Override
089  public void applyTo(@NonNull Catalog parent) {
090    applyRemovesTo(parent);
091    getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
092    getPromotedControls().forEach(control -> {
093      assert control != null;
094      // add promoted control
095      parent.addControl(control);
096      control.setParentControl(null);
097    });
098  }
099
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}