1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.oscal.lib.model.control.catalog;
7   
8   import java.util.LinkedList;
9   import java.util.List;
10  import java.util.Objects;
11  import java.util.stream.Stream;
12  
13  import dev.metaschema.core.datatype.markup.MarkupLine;
14  import dev.metaschema.core.util.CollectionUtil;
15  import dev.metaschema.core.util.ObjectUtils;
16  import dev.metaschema.oscal.lib.model.CatalogGroup;
17  import dev.metaschema.oscal.lib.model.Control;
18  import dev.metaschema.oscal.lib.model.ControlPart;
19  import dev.metaschema.oscal.lib.model.Link;
20  import dev.metaschema.oscal.lib.model.Parameter;
21  import dev.metaschema.oscal.lib.model.Property;
22  import dev.metaschema.oscal.lib.model.control.AbstractParameter;
23  import edu.umd.cs.findbugs.annotations.NonNull;
24  
25  public abstract class AbstractCatalogGroup
26      implements ICatalogGroup {
27  
28    @NonNull
29    @Override
30    public Stream<String> getReferencedParameterIds() {
31  
32      // get parameters referenced by the group's parts
33      Stream<String> insertIds = CollectionUtil.listOrEmpty(getParts()).stream()
34          // Get the full part hierarchy
35          .flatMap(part -> Stream.concat(Stream.of(part), part.getPartsRecursively()))
36          // Get the inserts for each part
37          .flatMap(part -> part.getInserts(insert -> "param".equals(insert.getType().toString())))
38          // Get the param ids for each insert
39          .map(insert -> insert.getIdReference().toString())
40          .flatMap(ObjectUtils::filterNull);
41  
42      // get parameters referenced by the control's parameters
43      Stream<String> parameterIds = CollectionUtil.listOrEmpty(getParams()).stream()
44          .flatMap(ObjectUtils::filterNull)
45          .flatMap(AbstractParameter::getParameterReferences);
46  
47      return ObjectUtils.notNull(
48          Stream.concat(insertIds, parameterIds).distinct());
49    }
50  
51    @NonNull
52    public static Builder builder(@NonNull String id) {
53      return new Builder(id);
54    }
55  
56    public static class Builder {
57      @NonNull
58      private final String id;
59  
60      private String clazz;
61      private MarkupLine title;
62      private final List<Parameter> params = new LinkedList<>();
63      private final List<Property> props = new LinkedList<>();
64      private final List<Link> links = new LinkedList<>();
65      private final List<ControlPart> parts = new LinkedList<>();
66      private final List<CatalogGroup> groups = new LinkedList<>();
67      private final List<Control> controls = new LinkedList<>();
68  
69      public Builder(@NonNull String id) {
70        this.id = ObjectUtils.requireNonNull(id, "id");
71      }
72  
73      @NonNull
74      public Builder clazz(@NonNull String value) {
75        this.clazz = ObjectUtils.requireNonNull(value, "value");
76        return this;
77      }
78  
79      @NonNull
80      public Builder title(@NonNull String markdown) {
81        this.title = MarkupLine.fromMarkdown(Objects.requireNonNull(markdown, "markdown"));
82        return this;
83      }
84  
85      @NonNull
86      public Builder title(@NonNull MarkupLine value) {
87        this.title = ObjectUtils.requireNonNull(value, "value");
88        return this;
89      }
90  
91      @NonNull
92      public Builder param(@NonNull Parameter value) {
93        this.params.add(Objects.requireNonNull(value, "value"));
94        return this;
95      }
96  
97      @NonNull
98      public Builder prop(@NonNull Property value) {
99        this.props.add(Objects.requireNonNull(value, "value"));
100       return this;
101     }
102 
103     @NonNull
104     public Builder link(@NonNull Link value) {
105       this.links.add(Objects.requireNonNull(value, "value"));
106       return this;
107     }
108 
109     @NonNull
110     public Builder part(@NonNull ControlPart value) {
111       this.parts.add(Objects.requireNonNull(value, "value"));
112       return this;
113     }
114 
115     @NonNull
116     public Builder group(@NonNull CatalogGroup value) {
117       this.groups.add(Objects.requireNonNull(value, "value"));
118       return this;
119     }
120 
121     @NonNull
122     public Builder control(@NonNull Control value) {
123       this.controls.add(Objects.requireNonNull(value, "value"));
124       return this;
125     }
126 
127     @NonNull
128     public CatalogGroup build() {
129       CatalogGroup retval = new CatalogGroup();
130       retval.setId(id);
131 
132       if (title == null) {
133         throw new IllegalStateException("a title must be provided");
134       }
135       retval.setTitle(title);
136 
137       if (clazz != null) {
138         retval.setClazz(clazz);
139       }
140       if (!params.isEmpty()) {
141         retval.setParams(params);
142       }
143       if (!props.isEmpty()) {
144         retval.setProps(props);
145       }
146       if (!links.isEmpty()) {
147         retval.setLinks(links);
148       }
149       if (!parts.isEmpty()) {
150         retval.setParts(parts);
151       }
152       if (!controls.isEmpty()) {
153         retval.setControls(controls);
154       }
155       if (!groups.isEmpty()) {
156         retval.setGroups(groups);
157       }
158 
159       return retval;
160     }
161   }
162 }