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