001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package gov.nist.secauto.oscal.lib.model.control;
007
008import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
009import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
010import gov.nist.secauto.metaschema.core.util.CollectionUtil;
011import gov.nist.secauto.metaschema.core.util.ObjectUtils;
012import gov.nist.secauto.oscal.lib.model.Link;
013import gov.nist.secauto.oscal.lib.model.Parameter;
014import gov.nist.secauto.oscal.lib.model.ParameterConstraint;
015import gov.nist.secauto.oscal.lib.model.ParameterGuideline;
016import gov.nist.secauto.oscal.lib.model.ParameterSelection;
017import gov.nist.secauto.oscal.lib.model.Property;
018import gov.nist.secauto.oscal.lib.model.metadata.IProperty;
019
020import java.util.ArrayList;
021import java.util.Arrays;
022import java.util.Collection;
023import java.util.LinkedList;
024import java.util.List;
025import java.util.Objects;
026import java.util.stream.Stream;
027
028import edu.umd.cs.findbugs.annotations.NonNull;
029
030public abstract class AbstractParameter implements IParameter {
031
032  @Override
033  public Stream<String> getParameterReferences() {
034
035    // handle prop name="aggregates"
036    Stream<String> aggregatesIds = CollectionUtil.listOrEmpty(getProps()).stream()
037        .filter(Objects::nonNull)
038        .filter(prop -> prop.isNamespaceEqual(IProperty.OSCAL_NAMESPACE) && "aggregates".equals(prop.getName()))
039        .map(Property::getValue);
040
041    // handle select/choice/insert
042    ParameterSelection selection = getSelect();
043
044    Stream<String> selectInsertIds;
045    if (selection == null) {
046      selectInsertIds = Stream.empty();
047    } else {
048      selectInsertIds = CollectionUtil.listOrEmpty(selection.getChoice()).stream()
049          .filter(Objects::nonNull)
050          .flatMap(choice -> choice.getInserts(insert -> "param".equals(insert.getType().toString())).stream()
051              .map(insert -> insert.getIdReference().toString()));
052    }
053    Stream<String> retval = Stream.concat(aggregatesIds, selectInsertIds)
054        .filter(Objects::nonNull)
055        .distinct();
056    assert retval != null;
057    return retval;
058  }
059
060  @NonNull
061  public static Builder builder(@NonNull String id) {
062    return new Builder(id);
063  }
064
065  public static class Builder {
066    @NonNull
067    private final String id;
068
069    private String clazz;
070    private final List<Property> props = new LinkedList<>();
071    private final List<Link> links = new LinkedList<>();
072    private MarkupLine label;
073    private MarkupMultiline usage;
074    private final List<ParameterConstraint> constraints = new LinkedList<>();
075    private final List<ParameterGuideline> guidelines = new LinkedList<>();
076    private List<String> values = new LinkedList<>();
077    private ParameterSelection selection;
078    private MarkupMultiline remarks;
079
080    public Builder(@NonNull String id) {
081      this.id = ObjectUtils.requireNonNull(id);
082    }
083
084    @NonNull
085    public Builder clazz(@NonNull String value) {
086      this.clazz = ObjectUtils.requireNonNull(value);
087      return this;
088    }
089
090    @NonNull
091    public Builder prop(@NonNull Property value) {
092      this.props.add(ObjectUtils.requireNonNull(value));
093      return this;
094    }
095
096    @NonNull
097    public Builder link(@NonNull Link value) {
098      this.links.add(ObjectUtils.requireNonNull(value));
099      return this;
100    }
101
102    @NonNull
103    public Builder label(@NonNull String markdown) {
104      return label(MarkupLine.fromMarkdown(Objects.requireNonNull(markdown)));
105    }
106
107    @NonNull
108    public Builder label(@NonNull MarkupLine value) {
109      this.label = ObjectUtils.requireNonNull(value);
110      return this;
111    }
112
113    @NonNull
114    public Builder usage(@NonNull String markdown) {
115      return usage(MarkupMultiline.fromMarkdown(ObjectUtils.requireNonNull(markdown)));
116    }
117
118    @NonNull
119    public Builder usage(@NonNull MarkupMultiline value) {
120      this.usage = ObjectUtils.requireNonNull(value);
121      return this;
122    }
123
124    @NonNull
125    public Builder constraint(@NonNull ParameterConstraint value) {
126      this.constraints.add(ObjectUtils.requireNonNull(value));
127      return this;
128    }
129
130    @NonNull
131    public Builder guideline(@NonNull ParameterGuideline value) {
132      this.guidelines.add(ObjectUtils.requireNonNull(value));
133      return this;
134    }
135
136    @SuppressWarnings("null")
137    @NonNull
138    public Builder values(@NonNull String... values) {
139      return values(Arrays.asList(values));
140    }
141
142    @NonNull
143    public Builder values(@NonNull Collection<String> values) {
144      this.values = new ArrayList<>(values);
145      return this;
146    }
147
148    @NonNull
149    public Builder select(@NonNull ParameterSelection value) {
150      this.selection = Objects.requireNonNull(value);
151      return this;
152    }
153
154    @NonNull
155    public Builder remarks(@NonNull MarkupMultiline value) {
156      this.remarks = Objects.requireNonNull(value);
157      return this;
158    }
159
160    @NonNull
161    public Parameter build() {
162      Parameter retval = new Parameter();
163      retval.setId(id);
164
165      if (clazz != null) {
166        retval.setClazz(clazz);
167      }
168      if (!props.isEmpty()) {
169        retval.setProps(props);
170      }
171      if (!links.isEmpty()) {
172        retval.setLinks(links);
173      }
174      if (label != null) {
175        retval.setLabel(label);
176      }
177      if (usage != null) {
178        retval.setUsage(usage);
179      }
180      if (!constraints.isEmpty()) {
181        retval.setConstraints(constraints);
182      }
183      if (!guidelines.isEmpty()) {
184        retval.setGuidelines(guidelines);
185      }
186      if (!values.isEmpty()) {
187        retval.setValues(values);
188      }
189      if (selection != null) {
190        retval.setSelect(selection);
191      }
192      if (remarks != null) {
193        retval.setRemarks(remarks);
194      }
195      return retval;
196    }
197  }
198}