1
2
3
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.metaschema.databind.io.IDeserializationHandler;
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 AbstractControl
27 implements IDeserializationHandler, IControl {
28 private Control parent;
29
30 @Override
31 public Control getParentControl() {
32 return parent;
33 }
34
35 @Override
36 public void setParentControl(Control parent) {
37 this.parent = parent;
38 }
39
40 @Override
41 public void beforeDeserialize(Object parent) {
42
43 }
44
45 @Override
46 public void afterDeserialize(Object parent) {
47 if (parent instanceof Control) {
48 setParentControl((Control) parent);
49 }
50 }
51
52 @NonNull
53 @Override
54 public Stream<String> getReferencedParameterIds() {
55
56
57 Stream<String> insertIds = CollectionUtil.listOrEmpty(getParts()).stream()
58
59 .flatMap(part -> Stream.concat(Stream.of(part), part.getPartsRecursively()))
60
61 .flatMap(part -> part.getInserts(insert -> "param".equals(insert.getType().toString())))
62
63 .map(insert -> insert.getIdReference().toString())
64 .flatMap(ObjectUtils::filterNull);
65
66
67 Stream<String> parameterIds = CollectionUtil.listOrEmpty(getParams()).stream()
68 .flatMap(ObjectUtils::filterNull)
69 .flatMap(AbstractParameter::getParameterReferences);
70
71 return ObjectUtils.notNull(
72 Stream.concat(insertIds, parameterIds).distinct());
73 }
74
75 @NonNull
76 public static Builder builder(@NonNull String id) {
77 return new Builder(id);
78 }
79
80 public static class Builder {
81 @NonNull
82 private final String id;
83
84 private String clazz;
85 private MarkupLine title;
86 private final List<Parameter> params = new LinkedList<>();
87 private final List<Property> props = new LinkedList<>();
88 private final List<Link> links = new LinkedList<>();
89 private final List<ControlPart> parts = new LinkedList<>();
90 private final List<Control> controls = new LinkedList<>();
91
92 public Builder(@NonNull String id) {
93 this.id = Objects.requireNonNull(id, "id");
94 }
95
96 @NonNull
97 public Builder clazz(@NonNull String value) {
98 this.clazz = Objects.requireNonNull(value);
99 return this;
100 }
101
102 @NonNull
103 public Builder title(@NonNull String markdown) {
104 this.title = MarkupLine.fromMarkdown(Objects.requireNonNull(markdown));
105 return this;
106 }
107
108 @NonNull
109 public Builder title(@NonNull MarkupLine value) {
110 this.title = Objects.requireNonNull(value);
111 return this;
112 }
113
114 @NonNull
115 public Builder param(@NonNull Parameter value) {
116 this.params.add(Objects.requireNonNull(value));
117 return this;
118 }
119
120 @NonNull
121 public Builder prop(@NonNull Property value) {
122 this.props.add(Objects.requireNonNull(value));
123 return this;
124 }
125
126 @NonNull
127 public Builder link(@NonNull Link value) {
128 this.links.add(Objects.requireNonNull(value));
129 return this;
130 }
131
132 @NonNull
133 public Builder part(@NonNull ControlPart value) {
134 this.parts.add(Objects.requireNonNull(value));
135 return this;
136 }
137
138 @NonNull
139 public Builder control(@NonNull Control value) {
140 this.controls.add(Objects.requireNonNull(value));
141 return this;
142 }
143
144 @NonNull
145 public Control build() {
146 Control retval = new Control();
147 retval.setId(id);
148
149 if (title == null) {
150 throw new IllegalStateException("a title must be provided");
151 }
152 retval.setTitle(title);
153
154 if (clazz != null) {
155 retval.setClazz(clazz);
156 }
157 if (!params.isEmpty()) {
158 retval.setParams(params);
159 }
160 if (!props.isEmpty()) {
161 retval.setProps(props);
162 }
163 if (!links.isEmpty()) {
164 retval.setLinks(links);
165 }
166 if (!parts.isEmpty()) {
167 retval.setParts(parts);
168 }
169 if (!controls.isEmpty()) {
170 controls.forEach(control -> control.setParentControl(retval));
171 retval.setControls(controls);
172 }
173
174 return retval;
175 }
176 }
177 }