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.AssemblyConstraints;
6   import gov.nist.secauto.metaschema.binding.model.annotations.BoundAssembly;
7   import gov.nist.secauto.metaschema.binding.model.annotations.BoundField;
8   import gov.nist.secauto.metaschema.binding.model.annotations.BoundFieldValue;
9   import gov.nist.secauto.metaschema.binding.model.annotations.BoundFlag;
10  import gov.nist.secauto.metaschema.binding.model.annotations.GroupAs;
11  import gov.nist.secauto.metaschema.binding.model.annotations.HasCardinality;
12  import gov.nist.secauto.metaschema.binding.model.annotations.MetaschemaAssembly;
13  import gov.nist.secauto.metaschema.binding.model.annotations.ValueConstraints;
14  import gov.nist.secauto.metaschema.model.common.JsonGroupAsBehavior;
15  import gov.nist.secauto.metaschema.model.common.constraint.IConstraint;
16  import gov.nist.secauto.metaschema.model.common.datatype.adapter.TokenAdapter;
17  import gov.nist.secauto.metaschema.model.common.datatype.adapter.UriAdapter;
18  import gov.nist.secauto.metaschema.model.common.datatype.adapter.UuidAdapter;
19  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine;
20  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLineAdapter;
21  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultiline;
22  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultilineAdapter;
23  import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
24  import java.lang.Override;
25  import java.lang.String;
26  import java.net.URI;
27  import java.util.LinkedList;
28  import java.util.List;
29  import java.util.UUID;
30  import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle;
31  import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
32  
33  /**
34   * A partition of an assessment plan or results or a child of another part.
35   */
36  @MetaschemaAssembly(
37      formalName = "Assessment Part",
38      description = "A partition of an assessment plan or results or a child of another part.",
39      name = "assessment-part",
40      metaschema = OscalAssessmentCommonMetaschema.class,
41      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"
42              + "\n"
43              + "A `part` can be assigned an optional `id`, which allows for internal and external references to the textual concept contained within a `part`. A `id` provides a means for an OSCAL profile, or a higher layer OSCAL model to reference a specific part within a `catalog`. For example, an `id` can be used to reference or to make modifications to a control statement in a profile.\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 = {
53          @AllowedValues(level = IConstraint.Level.ERROR, target = ".[@name='objective']/prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = @AllowedValue(value = "method", description = "The assessment method to use. This typically appears on parts with the name \"objective\".")),
54          @AllowedValues(level = IConstraint.Level.ERROR, target = ".[@name='objective']/prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name='method']/@value", values = {@AllowedValue(value = "INTERVIEW", description = "The process of holding discussions with individuals or groups of individuals within an organization to once again, facilitate assessor understanding, achieve clarification, or obtain evidence."), @AllowedValue(value = "EXAMINE", description = "The process of reviewing, inspecting, observing, studying, or analyzing one or more assessment objects (i.e., specifications, mechanisms, or activities)."), @AllowedValue(value = "TEST", description = "The process of exercising one or more assessment objects (i.e., activities or mechanisms) under specified conditions to compare actual with expected behavior.")})
55      }
56  )
57  @AssemblyConstraints(
58      hasCardinality = @HasCardinality(level = IConstraint.Level.ERROR, target = ".[@name='objective']/prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name='method']", minOccurs = 1)
59  )
60  public class AssessmentPart {
61    @BoundFlag(
62        formalName = "Part Identifier",
63        description = "A [machine-oriented](https://pages.nist.gov/OSCAL/concepts/identifier-use/#machine-oriented), [globally unique](https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique) identifier with [cross-instance](https://pages.nist.gov/OSCAL/concepts/identifier-use/#cross-instance) scope that can be used to reference this part elsewhere in [this or other OSCAL instances](https://pages.nist.gov/OSCAL/concepts/identifier-use/#scope). The locally defined *UUID* of the `part` can be used to reference the data item locally or globally (e.g., in an ported OSCAL instance). This UUID should be assigned [per-subject](https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency), which means it should be consistently used to identify the same subject across revisions of the document.",
64        useName = "uuid",
65        typeAdapter = UuidAdapter.class
66    )
67    private UUID _uuid;
68  
69    @BoundFlag(
70        formalName = "Part Name",
71        description = "A textual label that uniquely identifies the part's semantic type.",
72        useName = "name",
73        required = true,
74        typeAdapter = TokenAdapter.class
75    )
76    @ValueConstraints(
77        allowedValues = @AllowedValues(level = IConstraint.Level.ERROR, allowOthers = true, values = {@AllowedValue(value = "asset", description = "An assessment asset."), @AllowedValue(value = "method", description = "An assessment method."), @AllowedValue(value = "objective", description = "Describes a set of control objectives.")})
78    )
79    private String _name;
80  
81    @BoundFlag(
82        formalName = "Part Namespace",
83        description = "A namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.",
84        useName = "ns",
85        typeAdapter = UriAdapter.class,
86        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"
87                + "\n"
88                + "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."
89    )
90    private URI _ns;
91  
92    @BoundFlag(
93        formalName = "Part Class",
94        description = "A textual label that provides a sub-type or characterization of the part's `name`. This can be used to further distinguish or discriminate between the semantics of multiple parts of the same control with the same `name` and `ns`.",
95        useName = "class",
96        typeAdapter = TokenAdapter.class,
97        remarks = "A `class` can be used in validation rules to express extra constraints over named items of a specific `class` value.\n"
98                + "\n"
99                + "A `class` can also be used in an OSCAL profile as a means to target an alteration to control content."
100   )
101   private String _clazz;
102 
103   /**
104    * "A name given to the part, which may be used by a tool for display and navigation."
105    */
106   @BoundField(
107       formalName = "Part Title",
108       description = "A name given to the part, which may be used by a tool for display and navigation.",
109       useName = "title"
110   )
111   @BoundFieldValue(
112       typeAdapter = MarkupLineAdapter.class
113   )
114   private MarkupLine _title;
115 
116   @BoundAssembly(
117       formalName = "Property",
118       description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.",
119       useName = "prop",
120       maxOccurs = -1
121   )
122   @GroupAs(
123       name = "props",
124       inJson = JsonGroupAsBehavior.LIST
125   )
126   private List<Property> _props;
127 
128   /**
129    * "Permits multiple paragraphs, lists, tables etc."
130    */
131   @BoundField(
132       formalName = "Part Text",
133       description = "Permits multiple paragraphs, lists, tables etc.",
134       useName = "prose",
135       namespace = "##none",
136       inXmlWrapped = false
137   )
138   @BoundFieldValue(
139       typeAdapter = MarkupMultilineAdapter.class
140   )
141   private MarkupMultiline _prose;
142 
143   @BoundAssembly(
144       formalName = "Assessment Part",
145       description = "A partition of an assessment plan or results or a child of another part.",
146       useName = "part",
147       maxOccurs = -1
148   )
149   @GroupAs(
150       name = "parts",
151       inJson = JsonGroupAsBehavior.LIST
152   )
153   private List<AssessmentPart> _parts;
154 
155   @BoundAssembly(
156       formalName = "Link",
157       description = "A reference to a local or remote resource, that has a specific relation to the containing object.",
158       useName = "link",
159       maxOccurs = -1
160   )
161   @GroupAs(
162       name = "links",
163       inJson = JsonGroupAsBehavior.LIST
164   )
165   private List<Link> _links;
166 
167   public AssessmentPart() {
168   }
169 
170   public UUID getUuid() {
171     return _uuid;
172   }
173 
174   public void setUuid(UUID value) {
175     _uuid = value;
176   }
177 
178   public String getName() {
179     return _name;
180   }
181 
182   public void setName(String value) {
183     _name = value;
184   }
185 
186   public URI getNs() {
187     return _ns;
188   }
189 
190   public void setNs(URI value) {
191     _ns = value;
192   }
193 
194   public String getClazz() {
195     return _clazz;
196   }
197 
198   public void setClazz(String value) {
199     _clazz = value;
200   }
201 
202   public MarkupLine getTitle() {
203     return _title;
204   }
205 
206   public void setTitle(MarkupLine value) {
207     _title = value;
208   }
209 
210   public List<Property> getProps() {
211     return _props;
212   }
213 
214   public void setProps(List<Property> value) {
215     _props = value;
216   }
217 
218   /**
219    * Add a new {@link Property} item to the underlying collection.
220    * @param item the item to add
221    * @return {@code true}
222    */
223   public boolean addProp(Property item) {
224     Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
225     if (_props == null) {
226       _props = new LinkedList<>();
227     }
228     return _props.add(value);
229   }
230 
231   /**
232    * Remove the first matching {@link Property} item from the underlying collection.
233    * @param item the item to remove
234    * @return {@code true} if the item was removed or {@code false} otherwise
235    */
236   public boolean removeProp(Property item) {
237     Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
238     return _props == null ? false : _props.remove(value);
239   }
240 
241   public MarkupMultiline getProse() {
242     return _prose;
243   }
244 
245   public void setProse(MarkupMultiline value) {
246     _prose = value;
247   }
248 
249   public List<AssessmentPart> getParts() {
250     return _parts;
251   }
252 
253   public void setParts(List<AssessmentPart> value) {
254     _parts = value;
255   }
256 
257   /**
258    * Add a new {@link AssessmentPart} item to the underlying collection.
259    * @param item the item to add
260    * @return {@code true}
261    */
262   public boolean addPart(AssessmentPart item) {
263     AssessmentPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
264     if (_parts == null) {
265       _parts = new LinkedList<>();
266     }
267     return _parts.add(value);
268   }
269 
270   /**
271    * Remove the first matching {@link AssessmentPart} item from the underlying collection.
272    * @param item the item to remove
273    * @return {@code true} if the item was removed or {@code false} otherwise
274    */
275   public boolean removePart(AssessmentPart item) {
276     AssessmentPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
277     return _parts == null ? false : _parts.remove(value);
278   }
279 
280   public List<Link> getLinks() {
281     return _links;
282   }
283 
284   public void setLinks(List<Link> value) {
285     _links = value;
286   }
287 
288   /**
289    * Add a new {@link Link} item to the underlying collection.
290    * @param item the item to add
291    * @return {@code true}
292    */
293   public boolean addLink(Link item) {
294     Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
295     if (_links == null) {
296       _links = new LinkedList<>();
297     }
298     return _links.add(value);
299   }
300 
301   /**
302    * Remove the first matching {@link Link} item from the underlying collection.
303    * @param item the item to remove
304    * @return {@code true} if the item was removed or {@code false} otherwise
305    */
306   public boolean removeLink(Link item) {
307     Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
308     return _links == null ? false : _links.remove(value);
309   }
310 
311   @Override
312   public String toString() {
313     return new ReflectionToStringBuilder(this, MultilineRecursiveToStringStyle.MULTI_LINE_STYLE).toString();
314   }
315 }