1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.oscal.lib.model.control;
7   
8   import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
9   import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
10  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
11  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
12  import gov.nist.secauto.oscal.lib.model.Link;
13  import gov.nist.secauto.oscal.lib.model.Parameter;
14  import gov.nist.secauto.oscal.lib.model.ParameterConstraint;
15  import gov.nist.secauto.oscal.lib.model.ParameterGuideline;
16  import gov.nist.secauto.oscal.lib.model.ParameterSelection;
17  import gov.nist.secauto.oscal.lib.model.Property;
18  import gov.nist.secauto.oscal.lib.model.metadata.IProperty;
19  
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.Collection;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Objects;
26  import java.util.stream.Stream;
27  
28  import edu.umd.cs.findbugs.annotations.NonNull;
29  
30  public abstract class AbstractParameter implements IParameter {
31  
32    @Override
33    public Stream<String> getParameterReferences() {
34  
35      // handle prop name="aggregates"
36      Stream<String> aggregatesIds = CollectionUtil.listOrEmpty(getProps()).stream()
37          .filter(Objects::nonNull)
38          .filter(prop -> prop.isNamespaceEqual(IProperty.OSCAL_NAMESPACE) && "aggregates".equals(prop.getName()))
39          .map(Property::getValue);
40  
41      // handle select/choice/insert
42      ParameterSelection selection = getSelect();
43  
44      Stream<String> selectInsertIds;
45      if (selection == null) {
46        selectInsertIds = Stream.empty();
47      } else {
48        selectInsertIds = CollectionUtil.listOrEmpty(selection.getChoice()).stream()
49            .filter(Objects::nonNull)
50            .flatMap(choice -> choice.getInserts(insert -> "param".equals(insert.getType().toString())).stream()
51                .map(insert -> insert.getIdReference().toString()));
52      }
53      Stream<String> retval = Stream.concat(aggregatesIds, selectInsertIds)
54          .filter(Objects::nonNull)
55          .distinct();
56      assert retval != null;
57      return retval;
58    }
59  
60    @NonNull
61    public static Builder builder(@NonNull String id) {
62      return new Builder(id);
63    }
64  
65    public static class Builder {
66      @NonNull
67      private final String id;
68  
69      private String clazz;
70      private final List<Property> props = new LinkedList<>();
71      private final List<Link> links = new LinkedList<>();
72      private MarkupLine label;
73      private MarkupMultiline usage;
74      private final List<ParameterConstraint> constraints = new LinkedList<>();
75      private final List<ParameterGuideline> guidelines = new LinkedList<>();
76      private List<String> values = new LinkedList<>();
77      private ParameterSelection selection;
78      private MarkupMultiline remarks;
79  
80      public Builder(@NonNull String id) {
81        this.id = ObjectUtils.requireNonNull(id);
82      }
83  
84      @NonNull
85      public Builder clazz(@NonNull String value) {
86        this.clazz = ObjectUtils.requireNonNull(value);
87        return this;
88      }
89  
90      @NonNull
91      public Builder prop(@NonNull Property value) {
92        this.props.add(ObjectUtils.requireNonNull(value));
93        return this;
94      }
95  
96      @NonNull
97      public Builder link(@NonNull Link value) {
98        this.links.add(ObjectUtils.requireNonNull(value));
99        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 }