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    promotedControls.get().add(control);
085  }
086
087  @Override
088  public void applyTo(@NonNull Catalog parent) {
089    applyRemovesTo(parent);
090    getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
091    getPromotedControls().forEach(control -> {
092      assert control != null;
093      parent.addControl(control);
094      control.setParentControl(null);
095    });
096  }
097
098  @Override
099  public void applyTo(@NonNull CatalogGroup parent) {
100    applyRemovesTo(parent);
101    getPromotedControls().forEach(control -> {
102      assert control != null;
103      parent.addControl(control);
104      control.setParentControl(null);
105    });
106    getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
107  }
108
109  @Override
110  public void applyTo(@NonNull Control parent) {
111    applyRemovesTo(parent);
112    getPromotedControls().forEach(control -> {
113      assert control != null;
114      parent.addControl(control);
115      control.setParentControl(null);
116    });
117    getPromotedParameters().forEach(param -> parent.addParam(ObjectUtils.notNull(param)));
118  }
119
120  public void applyRemovesTo(Catalog parent) {
121    removeItems(parent.getGroups(), getRemovedGroups());
122    removeItems(parent.getControls(), getRemovedControls());
123    removeItems(parent.getParams(), getRemovedParameters());
124  }
125
126  public void applyRemovesTo(CatalogGroup parent) {
127    removeItems(parent.getGroups(), getRemovedGroups());
128    removeItems(parent.getControls(), getRemovedControls());
129    removeItems(parent.getParams(), getRemovedParameters());
130  }
131
132  public void applyRemovesTo(Control parent) {
133    removeItems(parent.getControls(), getRemovedControls());
134    removeItems(parent.getParams(), getRemovedParameters());
135  }
136
137  public DefaultResult append(@NonNull DefaultResult that) {
138    lazyAppend(promotedControls, that.promotedControls);
139    lazyAppend(promotedParameters, that.promotedParameters);
140    lazyAppend(removedGroups, that.removedGroups);
141    lazyAppend(removedControls, that.removedControls);
142    lazyAppend(removedParameters, that.removedParameters);
143    return this;
144  }
145
146  public DefaultResult appendPromoted(@NonNull DefaultResult that) {
147    lazyAppend(promotedControls, that.promotedControls);
148    lazyAppend(promotedParameters, that.promotedParameters);
149    return this;
150  }
151
152  protected static <T> void lazyAppend(@NonNull Lazy<Set<T>> self, @NonNull Lazy<Set<T>> other) {
153    if (other.isAvailable()) {
154      Set<T> otherSet = other.get();
155      if (!otherSet.isEmpty()) {
156        self.get().addAll(otherSet);
157      }
158    }
159  }
160
161  protected static <T> void removeItems(List<T> list, @NonNull Collection<T> itemsToDelete) {
162    itemsToDelete.forEach(item -> {
163      if (!list.remove(item)) {
164        LOGGER.atError().log("item didn't exist in list");
165      }
166    });
167  }
168
169  public void removeGroup(CatalogGroup group) {
170    if (LOGGER.isDebugEnabled()) {
171      LOGGER.atDebug().log("Requesting removal of group '{}'.", group.getId());
172    }
173    removedGroups.get().add(group);
174  }
175
176  public void removeControl(Control control) {
177    if (LOGGER.isDebugEnabled()) {
178      LOGGER.atDebug().log("Requesting removal of control '{}'.", control.getId());
179    }
180    removedControls.get().add(control);
181  }
182
183  public void removeParameter(Parameter parameter) {
184    if (LOGGER.isDebugEnabled()) {
185      LOGGER.atDebug().log("Requesting removal of parameter '{}'.", parameter.getId());
186    }
187    removedParameters.get().add(parameter);
188  }
189}