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