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