1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.oscal.lib.model.control;
7   
8   import java.util.ArrayList;
9   import java.util.Arrays;
10  import java.util.Collection;
11  import java.util.LinkedList;
12  import java.util.List;
13  import java.util.Objects;
14  import java.util.stream.Stream;
15  
16  import dev.metaschema.core.datatype.markup.MarkupLine;
17  import dev.metaschema.core.datatype.markup.MarkupMultiline;
18  import dev.metaschema.core.util.CollectionUtil;
19  import dev.metaschema.core.util.ObjectUtils;
20  import dev.metaschema.oscal.lib.model.Link;
21  import dev.metaschema.oscal.lib.model.Parameter;
22  import dev.metaschema.oscal.lib.model.ParameterConstraint;
23  import dev.metaschema.oscal.lib.model.ParameterGuideline;
24  import dev.metaschema.oscal.lib.model.ParameterSelection;
25  import dev.metaschema.oscal.lib.model.Property;
26  import dev.metaschema.oscal.lib.model.metadata.IProperty;
27  import edu.umd.cs.findbugs.annotations.NonNull;
28  
29  public abstract class AbstractParameter implements IParameter {
30  
31    @Override
32    public Stream<String> getParameterReferences() {
33  
34      // handle prop name="aggregates"
35      Stream<String> aggregatesIds = CollectionUtil.listOrEmpty(getProps()).stream()
36          .filter(Objects::nonNull)
37          .filter(prop -> prop.isNamespaceEqual(IProperty.OSCAL_NAMESPACE) && "aggregates".equals(prop.getName()))
38          .map(Property::getValue);
39  
40      // handle select/choice/insert
41      ParameterSelection selection = getSelect();
42  
43      Stream<String> selectInsertIds;
44      if (selection == null) {
45        selectInsertIds = Stream.empty();
46      } else {
47        selectInsertIds = CollectionUtil.listOrEmpty(selection.getChoice()).stream()
48            .filter(Objects::nonNull)
49            .flatMap(choice -> choice.getInserts(insert -> "param".equals(insert.getType().toString())).stream()
50                .map(insert -> insert.getIdReference().toString()));
51      }
52      Stream<String> retval = Stream.concat(aggregatesIds, selectInsertIds)
53          .filter(Objects::nonNull)
54          .distinct();
55      assert retval != null;
56      return retval;
57    }
58  
59    @NonNull
60    public static Builder builder(@NonNull String id) {
61      return new Builder(id);
62    }
63  
64    public static class Builder {
65      @NonNull
66      private final String id;
67  
68      private String clazz;
69      private final List<Property> props = new LinkedList<>();
70      private final List<Link> links = new LinkedList<>();
71      private MarkupLine label;
72      private MarkupMultiline usage;
73      private final List<ParameterConstraint> constraints = new LinkedList<>();
74      private final List<ParameterGuideline> guidelines = new LinkedList<>();
75      private List<String> values = new LinkedList<>();
76      private ParameterSelection selection;
77      private MarkupMultiline remarks;
78  
79      public Builder(@NonNull String id) {
80        this.id = ObjectUtils.requireNonNull(id);
81      }
82  
83      @NonNull
84      public Builder clazz(@NonNull String value) {
85        this.clazz = ObjectUtils.requireNonNull(value);
86        return this;
87      }
88  
89      @NonNull
90      public Builder prop(@NonNull Property value) {
91        this.props.add(ObjectUtils.requireNonNull(value));
92        return this;
93      }
94  
95      @NonNull
96      public Builder link(@NonNull Link value) {
97        this.links.add(ObjectUtils.requireNonNull(value));
98        return this;
99      }
100 
101     @NonNull
102     public Builder label(@NonNull String markdown) {
103       return label(MarkupLine.fromMarkdown(Objects.requireNonNull(markdown)));
104     }
105 
106     @NonNull
107     public Builder label(@NonNull MarkupLine value) {
108       this.label = ObjectUtils.requireNonNull(value);
109       return this;
110     }
111 
112     @NonNull
113     public Builder usage(@NonNull String markdown) {
114       return usage(MarkupMultiline.fromMarkdown(ObjectUtils.requireNonNull(markdown)));
115     }
116 
117     @NonNull
118     public Builder usage(@NonNull MarkupMultiline value) {
119       this.usage = ObjectUtils.requireNonNull(value);
120       return this;
121     }
122 
123     @NonNull
124     public Builder constraint(@NonNull ParameterConstraint value) {
125       this.constraints.add(ObjectUtils.requireNonNull(value));
126       return this;
127     }
128 
129     @NonNull
130     public Builder guideline(@NonNull ParameterGuideline value) {
131       this.guidelines.add(ObjectUtils.requireNonNull(value));
132       return this;
133     }
134 
135     @SuppressWarnings("null")
136     @NonNull
137     public Builder values(@NonNull String... values) {
138       return values(Arrays.asList(values));
139     }
140 
141     @NonNull
142     public Builder values(@NonNull Collection<String> values) {
143       this.values = new ArrayList<>(values);
144       return this;
145     }
146 
147     @NonNull
148     public Builder select(@NonNull ParameterSelection value) {
149       this.selection = Objects.requireNonNull(value);
150       return this;
151     }
152 
153     @NonNull
154     public Builder remarks(@NonNull MarkupMultiline value) {
155       this.remarks = Objects.requireNonNull(value);
156       return this;
157     }
158 
159     @NonNull
160     public Parameter build() {
161       Parameter retval = new Parameter();
162       retval.setId(id);
163 
164       if (clazz != null) {
165         retval.setClazz(clazz);
166       }
167       if (!props.isEmpty()) {
168         retval.setProps(props);
169       }
170       if (!links.isEmpty()) {
171         retval.setLinks(links);
172       }
173       if (label != null) {
174         retval.setLabel(label);
175       }
176       if (usage != null) {
177         retval.setUsage(usage);
178       }
179       if (!constraints.isEmpty()) {
180         retval.setConstraints(constraints);
181       }
182       if (!guidelines.isEmpty()) {
183         retval.setGuidelines(guidelines);
184       }
185       if (!values.isEmpty()) {
186         retval.setValues(values);
187       }
188       if (selection != null) {
189         retval.setSelect(selection);
190       }
191       if (remarks != null) {
192         retval.setRemarks(remarks);
193       }
194       return retval;
195     }
196   }
197 }