001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package gov.nist.secauto.oscal.lib.model.control.catalog;
007
008import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
009import gov.nist.secauto.metaschema.core.util.CollectionUtil;
010import gov.nist.secauto.metaschema.core.util.ObjectUtils;
011import gov.nist.secauto.oscal.lib.model.CatalogGroup;
012import gov.nist.secauto.oscal.lib.model.Control;
013import gov.nist.secauto.oscal.lib.model.ControlPart;
014import gov.nist.secauto.oscal.lib.model.Link;
015import gov.nist.secauto.oscal.lib.model.Parameter;
016import gov.nist.secauto.oscal.lib.model.Property;
017import gov.nist.secauto.oscal.lib.model.control.AbstractParameter;
018
019import java.util.LinkedList;
020import java.util.List;
021import java.util.Objects;
022import java.util.stream.Stream;
023
024import edu.umd.cs.findbugs.annotations.NonNull;
025
026public abstract class AbstractCatalogGroup
027    implements ICatalogGroup {
028
029  @NonNull
030  @Override
031  public Stream<String> getReferencedParameterIds() {
032
033    // get parameters referenced by the group's parts
034    Stream<String> insertIds = CollectionUtil.listOrEmpty(getParts()).stream()
035        // Get the full part hierarchy
036        .flatMap(part -> Stream.concat(Stream.of(part), part.getPartsRecursively()))
037        // Get the inserts for each part
038        .flatMap(part -> part.getInserts(insert -> "param".equals(insert.getType().toString())))
039        // Get the param ids for each insert
040        .map(insert -> insert.getIdReference().toString())
041        .flatMap(ObjectUtils::filterNull);
042
043    // get parameters referenced by the control's parameters
044    Stream<String> parameterIds = CollectionUtil.listOrEmpty(getParams()).stream()
045        .flatMap(ObjectUtils::filterNull)
046        .flatMap(AbstractParameter::getParameterReferences);
047
048    return ObjectUtils.notNull(
049        Stream.concat(insertIds, parameterIds).distinct());
050  }
051
052  @NonNull
053  public static Builder builder(@NonNull String id) {
054    return new Builder(id);
055  }
056
057  public static class Builder {
058    @NonNull
059    private final String id;
060
061    private String clazz;
062    private MarkupLine title;
063    private final List<Parameter> params = new LinkedList<>();
064    private final List<Property> props = new LinkedList<>();
065    private final List<Link> links = new LinkedList<>();
066    private final List<ControlPart> parts = new LinkedList<>();
067    private final List<CatalogGroup> groups = new LinkedList<>();
068    private final List<Control> controls = new LinkedList<>();
069
070    public Builder(@NonNull String id) {
071      this.id = ObjectUtils.requireNonNull(id, "id");
072    }
073
074    @NonNull
075    public Builder clazz(@NonNull String value) {
076      this.clazz = ObjectUtils.requireNonNull(value, "value");
077      return this;
078    }
079
080    @NonNull
081    public Builder title(@NonNull String markdown) {
082      this.title = MarkupLine.fromMarkdown(Objects.requireNonNull(markdown, "markdown"));
083      return this;
084    }
085
086    @NonNull
087    public Builder title(@NonNull MarkupLine value) {
088      this.title = ObjectUtils.requireNonNull(value, "value");
089      return this;
090    }
091
092    @NonNull
093    public Builder param(@NonNull Parameter value) {
094      this.params.add(Objects.requireNonNull(value, "value"));
095      return this;
096    }
097
098    @NonNull
099    public Builder prop(@NonNull Property value) {
100      this.props.add(Objects.requireNonNull(value, "value"));
101      return this;
102    }
103
104    @NonNull
105    public Builder link(@NonNull Link value) {
106      this.links.add(Objects.requireNonNull(value, "value"));
107      return this;
108    }
109
110    @NonNull
111    public Builder part(@NonNull ControlPart value) {
112      this.parts.add(Objects.requireNonNull(value, "value"));
113      return this;
114    }
115
116    @NonNull
117    public Builder group(@NonNull CatalogGroup value) {
118      this.groups.add(Objects.requireNonNull(value, "value"));
119      return this;
120    }
121
122    @NonNull
123    public Builder control(@NonNull Control value) {
124      this.controls.add(Objects.requireNonNull(value, "value"));
125      return this;
126    }
127
128    @NonNull
129    public CatalogGroup build() {
130      CatalogGroup retval = new CatalogGroup();
131      retval.setId(id);
132
133      if (title == null) {
134        throw new IllegalStateException("a title must be provided");
135      }
136      retval.setTitle(title);
137
138      if (clazz != null) {
139        retval.setClazz(clazz);
140      }
141      if (!params.isEmpty()) {
142        retval.setParams(params);
143      }
144      if (!props.isEmpty()) {
145        retval.setProps(props);
146      }
147      if (!links.isEmpty()) {
148        retval.setLinks(links);
149      }
150      if (!parts.isEmpty()) {
151        retval.setParts(parts);
152      }
153      if (!controls.isEmpty()) {
154        retval.setControls(controls);
155      }
156      if (!groups.isEmpty()) {
157        retval.setGroups(groups);
158      }
159
160      return retval;
161    }
162  }
163}