1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.oscal.lib.model.control.catalog;
7   
8   import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
9   import gov.nist.secauto.metaschema.core.util.CollectionUtil;
10  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
11  import gov.nist.secauto.oscal.lib.model.CatalogGroup;
12  import gov.nist.secauto.oscal.lib.model.Control;
13  import gov.nist.secauto.oscal.lib.model.ControlPart;
14  import gov.nist.secauto.oscal.lib.model.Link;
15  import gov.nist.secauto.oscal.lib.model.Parameter;
16  import gov.nist.secauto.oscal.lib.model.Property;
17  import gov.nist.secauto.oscal.lib.model.control.AbstractParameter;
18  
19  import java.util.LinkedList;
20  import java.util.List;
21  import java.util.Objects;
22  import java.util.stream.Stream;
23  
24  import edu.umd.cs.findbugs.annotations.NonNull;
25  
26  public abstract class AbstractCatalogGroup
27      implements ICatalogGroup {
28  
29    @NonNull
30    @Override
31    public Stream<String> getReferencedParameterIds() {
32  
33      // get parameters referenced by the group's parts
34      Stream<String> insertIds = CollectionUtil.listOrEmpty(getParts()).stream()
35          // Get the full part hierarchy
36          .flatMap(part -> Stream.concat(Stream.of(part), part.getPartsRecursively()))
37          // Get the inserts for each part
38          .flatMap(part -> part.getInserts(insert -> "param".equals(insert.getType().toString())))
39          // Get the param ids for each insert
40          .map(insert -> insert.getIdReference().toString())
41          .flatMap(ObjectUtils::filterNull);
42  
43      // get parameters referenced by the control's parameters
44      Stream<String> parameterIds = CollectionUtil.listOrEmpty(getParams()).stream()
45          .flatMap(ObjectUtils::filterNull)
46          .flatMap(AbstractParameter::getParameterReferences);
47  
48      return ObjectUtils.notNull(
49          Stream.concat(insertIds, parameterIds).distinct());
50    }
51  
52    @NonNull
53    public static Builder builder(@NonNull String id) {
54      return new Builder(id);
55    }
56  
57    public static class Builder {
58      @NonNull
59      private final String id;
60  
61      private String clazz;
62      private MarkupLine title;
63      private final List<Parameter> params = new LinkedList<>();
64      private final List<Property> props = new LinkedList<>();
65      private final List<Link> links = new LinkedList<>();
66      private final List<ControlPart> parts = new LinkedList<>();
67      private final List<CatalogGroup> groups = new LinkedList<>();
68      private final List<Control> controls = new LinkedList<>();
69  
70      public Builder(@NonNull String id) {
71        this.id = ObjectUtils.requireNonNull(id, "id");
72      }
73  
74      @NonNull
75      public Builder clazz(@NonNull String value) {
76        this.clazz = ObjectUtils.requireNonNull(value, "value");
77        return this;
78      }
79  
80      @NonNull
81      public Builder title(@NonNull String markdown) {
82        this.title = MarkupLine.fromMarkdown(Objects.requireNonNull(markdown, "markdown"));
83        return this;
84      }
85  
86      @NonNull
87      public Builder title(@NonNull MarkupLine value) {
88        this.title = ObjectUtils.requireNonNull(value, "value");
89        return this;
90      }
91  
92      @NonNull
93      public Builder param(@NonNull Parameter value) {
94        this.params.add(Objects.requireNonNull(value, "value"));
95        return this;
96      }
97  
98      @NonNull
99      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 }