View Javadoc
1   package gov.nist.secauto.oscal.lib.model;
2   
3   import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValue;
4   import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValues;
5   import gov.nist.secauto.metaschema.binding.model.annotations.BoundAssembly;
6   import gov.nist.secauto.metaschema.binding.model.annotations.BoundField;
7   import gov.nist.secauto.metaschema.binding.model.annotations.BoundFieldValue;
8   import gov.nist.secauto.metaschema.binding.model.annotations.BoundFlag;
9   import gov.nist.secauto.metaschema.binding.model.annotations.GroupAs;
10  import gov.nist.secauto.metaschema.binding.model.annotations.MetaschemaAssembly;
11  import gov.nist.secauto.metaschema.binding.model.annotations.ValueConstraints;
12  import gov.nist.secauto.metaschema.model.common.JsonGroupAsBehavior;
13  import gov.nist.secauto.metaschema.model.common.constraint.IConstraint;
14  import gov.nist.secauto.metaschema.model.common.datatype.adapter.TokenAdapter;
15  import gov.nist.secauto.metaschema.model.common.datatype.adapter.UriAdapter;
16  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine;
17  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLineAdapter;
18  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultiline;
19  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultilineAdapter;
20  import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
21  import gov.nist.secauto.oscal.lib.model.control.AbstractPart;
22  import java.lang.Override;
23  import java.lang.String;
24  import java.net.URI;
25  import java.util.LinkedList;
26  import java.util.List;
27  import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle;
28  import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
29  
30  /**
31   * An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.
32   */
33  @MetaschemaAssembly(
34      formalName = "Part",
35      description = "An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.",
36      name = "part",
37      metaschema = OscalControlCommonMetaschema.class,
38      remarks = "A `part` provides for logical partitioning of prose, and can be thought of as a grouping structure (e.g., section). A `part` can have child parts allowing for arbitrary nesting of prose content (e.g., statement hierarchy). A `part` can contain `prop` objects that allow for enriching prose text with structured name/value information.\n"
39              + "\n"
40              + "A `part` can be assigned an optional `id`, which allows references to this part from within a catalog, or within an instance of another OSCAL model that has a need to reference the part. Examples of where part referencing is used in OSCAL include:\n"
41              + "\n"
42              + "- Referencing a part by id to tailor (make modifications to) a control statement in a profile.\n"
43              + "- Referencing a control statement represented by a part in a system security plan implemented-requirement where a statement-level response is desired.\n"
44              + "\n"
45              + "Use of `part` and `prop` provides for a wide degree of extensibility within the OSCAL catalog model. The optional `ns` provides a means to qualify a part's `name`, allowing for organization-specific vocabularies to be defined with clear semantics. Any organization that extends OSCAL in this way should consistently assign a `ns` value that represents the organization, making a given namespace qualified `name` unique to that organization. This allows the combination of `ns` and `name` to always be unique and unambiguous, even when mixed with extensions from other organizations. Each organization is responsible for governance of their own extensions, and is strongly encouraged to publish their extensions as standards to their user community. If no `ns` is provided, the name is expected to be in the \"OSCAL\" namespace.\n"
46              + "\n"
47              + "To ensure a `ns` is unique to an organization and naming conflicts are avoided, a URI containing a DNS or other globally defined organization name should be used. For example, if FedRAMP and DoD both extend OSCAL, FedRAMP will use the `ns` `http://fedramp.gov/ns/oscal`, while DoD might use the `ns` `https://defense.gov` for any organization specific `name`.\n"
48              + "\n"
49              + "Tools that process OSCAL content are not required to interpret unrecognized OSCAL extensions; however, OSCAL compliant tools should not modify or remove unrecognized extensions, unless there is a compelling reason to do so, such as data sensitivity."
50  )
51  @ValueConstraints(
52      allowedValues = @AllowedValues(level = IConstraint.Level.ERROR, target = "prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = {@AllowedValue(value = "label", description = "A human-readable label for the parent context, which may be rendered in place of the actual identifier for some use cases."), @AllowedValue(value = "sort-id", description = "An alternative identifier, whose value is easily sortable among other such values in the document."), @AllowedValue(value = "alt-identifier", description = "An alternate or aliased identifier for the parent context.")})
53  )
54  public class ControlPart extends AbstractPart {
55    @BoundFlag(
56        formalName = "Part Identifier",
57        description = "A unique identifier for the part.",
58        useName = "id",
59        typeAdapter = TokenAdapter.class,
60        remarks = "While a part is not required to have an id, it is often desirable for an identifier to be provided, which allows the part to be referenced elsewhere in OSCAL document instances. For this reason, it is RECOMMENDED to provide a part identifier."
61    )
62    private String _id;
63  
64    @BoundFlag(
65        formalName = "Part Name",
66        description = "A textual label that uniquely identifies the part's semantic type, which exists in a value space qualified by the `ns`.",
67        useName = "name",
68        required = true,
69        typeAdapter = TokenAdapter.class
70    )
71    private String _name;
72  
73    @BoundFlag(
74        formalName = "Part Namespace",
75        description = "An optional namespace qualifying the part's `name`. This allows different organizations to associate distinct semantics with the same name.",
76        useName = "ns",
77        typeAdapter = UriAdapter.class,
78        remarks = "This value must be an [absolute URI](https://pages.nist.gov/OSCAL/concepts/uri-use/#absolute-uri) that serves as a [naming system identifier](https://pages.nist.gov/OSCAL/concepts/uri-use/#use-as-a-naming-system-identifier).\n"
79                + "\n"
80                + "When a `ns` is not provided, its value should be assumed to be `http://csrc.nist.gov/ns/oscal` and the name should be a name defined by the associated OSCAL model."
81    )
82    private URI _ns;
83  
84    @BoundFlag(
85        formalName = "Part Class",
86        description = "An optional textual providing a sub-type or characterization of the part's `name`, or a category to which the part belongs.",
87        useName = "class",
88        typeAdapter = TokenAdapter.class,
89        remarks = "One use of this flag is to distinguish or discriminate between the semantics of multiple parts of the same control with the same `name` and `ns` (since even within a given namespace it can be useful to overload a name).\n"
90                + "\n"
91                + "A `class` can be used in validation rules to express extra constraints over named items of a specific `class` value.\n"
92                + "\n"
93                + "A `class` can also be used in an OSCAL profile as a means to target an alteration to control content."
94    )
95    private String _clazz;
96  
97    /**
98     * "An optional name given to the part, which may be used by a tool for display and navigation."
99     */
100   @BoundField(
101       formalName = "Part Title",
102       description = "An optional name given to the part, which may be used by a tool for display and navigation.",
103       useName = "title"
104   )
105   @BoundFieldValue(
106       typeAdapter = MarkupLineAdapter.class
107   )
108   private MarkupLine _title;
109 
110   @BoundAssembly(
111       formalName = "Property",
112       description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.",
113       useName = "prop",
114       maxOccurs = -1
115   )
116   @GroupAs(
117       name = "props",
118       inJson = JsonGroupAsBehavior.LIST
119   )
120   private List<Property> _props;
121 
122   /**
123    * "Permits multiple paragraphs, lists, tables etc."
124    */
125   @BoundField(
126       formalName = "Part Text",
127       description = "Permits multiple paragraphs, lists, tables etc.",
128       useName = "prose",
129       namespace = "##none",
130       inXmlWrapped = false
131   )
132   @BoundFieldValue(
133       typeAdapter = MarkupMultilineAdapter.class
134   )
135   private MarkupMultiline _prose;
136 
137   @BoundAssembly(
138       formalName = "Part",
139       description = "An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.",
140       useName = "part",
141       maxOccurs = -1
142   )
143   @GroupAs(
144       name = "parts",
145       inJson = JsonGroupAsBehavior.LIST
146   )
147   private List<ControlPart> _parts;
148 
149   @BoundAssembly(
150       formalName = "Link",
151       description = "A reference to a local or remote resource, that has a specific relation to the containing object.",
152       useName = "link",
153       maxOccurs = -1
154   )
155   @GroupAs(
156       name = "links",
157       inJson = JsonGroupAsBehavior.LIST
158   )
159   private List<Link> _links;
160 
161   public ControlPart() {
162   }
163 
164   public String getId() {
165     return _id;
166   }
167 
168   public void setId(String value) {
169     _id = value;
170   }
171 
172   public String getName() {
173     return _name;
174   }
175 
176   public void setName(String value) {
177     _name = value;
178   }
179 
180   public URI getNs() {
181     return _ns;
182   }
183 
184   public void setNs(URI value) {
185     _ns = value;
186   }
187 
188   public String getClazz() {
189     return _clazz;
190   }
191 
192   public void setClazz(String value) {
193     _clazz = value;
194   }
195 
196   public MarkupLine getTitle() {
197     return _title;
198   }
199 
200   public void setTitle(MarkupLine value) {
201     _title = value;
202   }
203 
204   public List<Property> getProps() {
205     return _props;
206   }
207 
208   public void setProps(List<Property> value) {
209     _props = value;
210   }
211 
212   /**
213    * Add a new {@link Property} item to the underlying collection.
214    * @param item the item to add
215    * @return {@code true}
216    */
217   public boolean addProp(Property item) {
218     Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
219     if (_props == null) {
220       _props = new LinkedList<>();
221     }
222     return _props.add(value);
223   }
224 
225   /**
226    * Remove the first matching {@link Property} item from the underlying collection.
227    * @param item the item to remove
228    * @return {@code true} if the item was removed or {@code false} otherwise
229    */
230   public boolean removeProp(Property item) {
231     Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
232     return _props == null ? false : _props.remove(value);
233   }
234 
235   public MarkupMultiline getProse() {
236     return _prose;
237   }
238 
239   public void setProse(MarkupMultiline value) {
240     _prose = value;
241   }
242 
243   public List<ControlPart> getParts() {
244     return _parts;
245   }
246 
247   public void setParts(List<ControlPart> value) {
248     _parts = value;
249   }
250 
251   /**
252    * Add a new {@link ControlPart} item to the underlying collection.
253    * @param item the item to add
254    * @return {@code true}
255    */
256   public boolean addPart(ControlPart item) {
257     ControlPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
258     if (_parts == null) {
259       _parts = new LinkedList<>();
260     }
261     return _parts.add(value);
262   }
263 
264   /**
265    * Remove the first matching {@link ControlPart} item from the underlying collection.
266    * @param item the item to remove
267    * @return {@code true} if the item was removed or {@code false} otherwise
268    */
269   public boolean removePart(ControlPart item) {
270     ControlPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
271     return _parts == null ? false : _parts.remove(value);
272   }
273 
274   public List<Link> getLinks() {
275     return _links;
276   }
277 
278   public void setLinks(List<Link> value) {
279     _links = value;
280   }
281 
282   /**
283    * Add a new {@link Link} item to the underlying collection.
284    * @param item the item to add
285    * @return {@code true}
286    */
287   public boolean addLink(Link item) {
288     Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
289     if (_links == null) {
290       _links = new LinkedList<>();
291     }
292     return _links.add(value);
293   }
294 
295   /**
296    * Remove the first matching {@link Link} item from the underlying collection.
297    * @param item the item to remove
298    * @return {@code true} if the item was removed or {@code false} otherwise
299    */
300   public boolean removeLink(Link item) {
301     Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
302     return _links == null ? false : _links.remove(value);
303   }
304 
305   @Override
306   public String toString() {
307     return new ReflectionToStringBuilder(this, MultilineRecursiveToStringStyle.MULTI_LINE_STYLE).toString();
308   }
309 }