1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.oscal.lib.model.control;
7   
8   import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
9   import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
10  import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode;
11  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
12  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
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.Property;
16  
17  import java.net.URI;
18  import java.util.LinkedList;
19  import java.util.List;
20  import java.util.Objects;
21  import java.util.function.Predicate;
22  import java.util.stream.Stream;
23  
24  import edu.umd.cs.findbugs.annotations.NonNull;
25  
26  public abstract class AbstractPart implements IPart {
27  
28    @Override
29    @NonNull
30    public Stream<InsertAnchorNode> getInserts(@NonNull Predicate<InsertAnchorNode> filter) {
31      MarkupMultiline prose = getProse();
32  
33      @NonNull Stream<InsertAnchorNode> retval;
34      if (prose == null) {
35        retval = ObjectUtils.notNull(Stream.empty());
36      } else {
37        List<InsertAnchorNode> result = prose.getInserts(filter);
38        retval = ObjectUtils.notNull(result.stream());
39      }
40      return retval;
41    }
42  
43    public Stream<IPart> getPartsRecursively() {
44      return Stream.concat(
45          Stream.of(this),
46          CollectionUtil.listOrEmpty(getParts()).stream()
47              .flatMap(AbstractPart::getPartsRecursively));
48    }
49  
50    @NonNull
51    public static Builder builder(@NonNull String name) {
52      return new Builder(name);
53    }
54  
55    public static class Builder {
56      private String id;
57      @NonNull
58      private final String name;
59      private URI namespace;
60      private String clazz;
61      private MarkupMultiline prose;
62      private MarkupLine title;
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  
67      public Builder(@NonNull String name) {
68        this.name = Objects.requireNonNull(name);
69      }
70  
71      @SuppressWarnings("PMD.ShortMethodName")
72      @NonNull
73      public Builder id(@NonNull String value) {
74        this.id = Objects.requireNonNull(value);
75        return this;
76      }
77  
78      @NonNull
79      public Builder namespace(@NonNull URI value) {
80        this.namespace = Objects.requireNonNull(value);
81        return this;
82      }
83  
84      @NonNull
85      public Builder clazz(@NonNull String value) {
86        this.clazz = Objects.requireNonNull(value);
87        return this;
88      }
89  
90      @NonNull
91      public Builder title(@NonNull String markdown) {
92        return title(MarkupLine.fromMarkdown(Objects.requireNonNull(markdown)));
93      }
94  
95      @NonNull
96      public Builder title(@NonNull MarkupLine value) {
97        this.title = Objects.requireNonNull(value);
98        return this;
99      }
100 
101     @NonNull
102     public Builder prose(@NonNull String markdown) {
103       return prose(MarkupMultiline.fromMarkdown(Objects.requireNonNull(markdown)));
104     }
105 
106     @NonNull
107     public Builder prose(@NonNull MarkupMultiline value) {
108       this.prose = Objects.requireNonNull(value);
109       return this;
110     }
111 
112     @NonNull
113     public Builder prop(@NonNull Property value) {
114       this.props.add(Objects.requireNonNull(value));
115       return this;
116     }
117 
118     @NonNull
119     public Builder link(@NonNull Link value) {
120       this.links.add(Objects.requireNonNull(value));
121       return this;
122     }
123 
124     @NonNull
125     public Builder part(@NonNull ControlPart value) {
126       this.parts.add(Objects.requireNonNull(value));
127       return this;
128     }
129 
130     @NonNull
131     public ControlPart build() {
132       ControlPart retval = new ControlPart();
133 
134       retval.setName(name);
135 
136       if (id != null) {
137         retval.setId(id);
138       }
139       if (namespace != null) {
140         retval.setNs(namespace);
141       }
142       if (clazz != null) {
143         retval.setClazz(clazz);
144       }
145       if (prose != null) {
146         retval.setProse(prose);
147       }
148       if (title != null) {
149         retval.setTitle(title);
150       }
151       if (!props.isEmpty()) {
152         retval.setProps(props);
153       }
154       if (!links.isEmpty()) {
155         retval.setLinks(links);
156       }
157       if (!parts.isEmpty()) {
158         retval.setParts(parts);
159       }
160       return retval;
161     }
162   }
163 }