001package gov.nist.secauto.oscal.lib.model;
002
003import gov.nist.secauto.metaschema.core.datatype.adapter.TokenAdapter;
004import gov.nist.secauto.metaschema.core.datatype.adapter.UriAdapter;
005import gov.nist.secauto.metaschema.core.datatype.adapter.UuidAdapter;
006import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
007import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLineAdapter;
008import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
009import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultilineAdapter;
010import gov.nist.secauto.metaschema.core.model.IBoundObject;
011import gov.nist.secauto.metaschema.core.model.IMetaschemaData;
012import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior;
013import gov.nist.secauto.metaschema.core.model.constraint.IConstraint;
014import gov.nist.secauto.metaschema.core.util.ObjectUtils;
015import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValue;
016import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValues;
017import gov.nist.secauto.metaschema.databind.model.annotations.AssemblyConstraints;
018import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly;
019import gov.nist.secauto.metaschema.databind.model.annotations.BoundField;
020import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag;
021import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs;
022import gov.nist.secauto.metaschema.databind.model.annotations.HasCardinality;
023import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly;
024import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints;
025import java.lang.Override;
026import java.lang.String;
027import java.net.URI;
028import java.util.LinkedList;
029import java.util.List;
030import java.util.UUID;
031import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
032import org.apache.commons.lang3.builder.ToStringStyle;
033
034/**
035 * A partition of an assessment plan or results or a child of another part.
036 */
037@MetaschemaAssembly(
038    formalName = "Assessment Part",
039    description = "A partition of an assessment plan or results or a child of another part.",
040    name = "assessment-part",
041    moduleClass = OscalAssessmentCommonModule.class,
042    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"
043            + "\n"
044            + "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"
045            + "\n"
046            + "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"
047            + "\n"
048            + "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"
049            + "\n"
050            + "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.",
051    valueConstraints = @ValueConstraints(allowedValues = {@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\".")), @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.")})}),
052    modelConstraints = @AssemblyConstraints(cardinality = @HasCardinality(level = IConstraint.Level.ERROR, target = ".[@name='objective']/prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name='method']", minOccurs = 1))
053)
054public class AssessmentPart implements IBoundObject {
055  private final IMetaschemaData __metaschemaData;
056
057  /**
058   * "A <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#machine-oriented\">machine-oriented</a>, <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique\">globally unique</a> identifier with <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#cross-instance\">cross-instance</a> scope that can be used to reference this part elsewhere in <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#scope\">this or other OSCAL instances</a>. The locally defined <em>UUID</em> of the <code>part</code> can be used to reference the data item locally or globally (e.g., in an ported OSCAL instance). This UUID should be assigned <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency\">per-subject</a>, which means it should be consistently used to identify the same subject across revisions of the document."
059   */
060  @BoundFlag(
061      formalName = "Part Identifier",
062      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.",
063      name = "uuid",
064      typeAdapter = UuidAdapter.class
065  )
066  private UUID _uuid;
067
068  /**
069   * "A textual label that uniquely identifies the part's semantic type."
070   */
071  @BoundFlag(
072      formalName = "Part Name",
073      description = "A textual label that uniquely identifies the part's semantic type.",
074      name = "name",
075      required = true,
076      typeAdapter = TokenAdapter.class,
077      valueConstraints = @ValueConstraints(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.")}))
078  )
079  private String _name;
080
081  /**
082   * "A namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name."
083   */
084  @BoundFlag(
085      formalName = "Part Namespace",
086      description = "A namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.",
087      name = "ns",
088      defaultValue = "http://csrc.nist.gov/ns/oscal",
089      typeAdapter = UriAdapter.class,
090      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"
091              + "\n"
092              + "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."
093  )
094  private URI _ns;
095
096  /**
097   * "A textual label that provides a sub-type or characterization of the part's <code>name</code>. This can be used to further distinguish or discriminate between the semantics of multiple parts of the same control with the same <code>name</code> and <code>ns</code>."
098   */
099  @BoundFlag(
100      formalName = "Part Class",
101      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`.",
102      name = "class",
103      typeAdapter = TokenAdapter.class,
104      remarks = "A `class` can be used in validation rules to express extra constraints over named items of a specific `class` value.\n"
105              + "\n"
106              + "A `class` can also be used in an OSCAL profile as a means to target an alteration to control content."
107  )
108  private String _clazz;
109
110  @BoundField(
111      formalName = "Part Title",
112      description = "A name given to the part, which may be used by a tool for display and navigation.",
113      useName = "title",
114      typeAdapter = MarkupLineAdapter.class
115  )
116  private MarkupLine _title;
117
118  @BoundAssembly(
119      formalName = "Property",
120      description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.",
121      useName = "prop",
122      maxOccurs = -1,
123      groupAs = @GroupAs(name = "props", inJson = JsonGroupAsBehavior.LIST)
124  )
125  private List<Property> _props;
126
127  @BoundField(
128      formalName = "Part Text",
129      description = "Permits multiple paragraphs, lists, tables etc.",
130      useName = "prose",
131      inXmlWrapped = false,
132      typeAdapter = MarkupMultilineAdapter.class
133  )
134  private MarkupMultiline _prose;
135
136  @BoundAssembly(
137      formalName = "Assessment Part",
138      description = "A partition of an assessment plan or results or a child of another part.",
139      useName = "part",
140      maxOccurs = -1,
141      groupAs = @GroupAs(name = "parts", inJson = JsonGroupAsBehavior.LIST)
142  )
143  private List<AssessmentPart> _parts;
144
145  @BoundAssembly(
146      formalName = "Link",
147      description = "A reference to a local or remote resource, that has a specific relation to the containing object.",
148      useName = "link",
149      maxOccurs = -1,
150      groupAs = @GroupAs(name = "links", inJson = JsonGroupAsBehavior.LIST)
151  )
152  private List<Link> _links;
153
154  public AssessmentPart() {
155    this(null);
156  }
157
158  public AssessmentPart(IMetaschemaData data) {
159    this.__metaschemaData = data;
160  }
161
162  @Override
163  public IMetaschemaData getMetaschemaData() {
164    return __metaschemaData;
165  }
166
167  public UUID getUuid() {
168    return _uuid;
169  }
170
171  public void setUuid(UUID value) {
172    _uuid = value;
173  }
174
175  public String getName() {
176    return _name;
177  }
178
179  public void setName(String value) {
180    _name = value;
181  }
182
183  public URI getNs() {
184    return _ns;
185  }
186
187  public void setNs(URI value) {
188    _ns = value;
189  }
190
191  public String getClazz() {
192    return _clazz;
193  }
194
195  public void setClazz(String value) {
196    _clazz = value;
197  }
198
199  public MarkupLine getTitle() {
200    return _title;
201  }
202
203  public void setTitle(MarkupLine value) {
204    _title = value;
205  }
206
207  public List<Property> getProps() {
208    return _props;
209  }
210
211  public void setProps(List<Property> value) {
212    _props = value;
213  }
214
215  /**
216   * Add a new {@link Property} item to the underlying collection.
217   * @param item the item to add
218   * @return {@code true}
219   */
220  public boolean addProp(Property item) {
221    Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
222    if (_props == null) {
223      _props = new LinkedList<>();
224    }
225    return _props.add(value);
226  }
227
228  /**
229   * Remove the first matching {@link Property} item from the underlying collection.
230   * @param item the item to remove
231   * @return {@code true} if the item was removed or {@code false} otherwise
232   */
233  public boolean removeProp(Property item) {
234    Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
235    return _props != null && _props.remove(value);
236  }
237
238  public MarkupMultiline getProse() {
239    return _prose;
240  }
241
242  public void setProse(MarkupMultiline value) {
243    _prose = value;
244  }
245
246  public List<AssessmentPart> getParts() {
247    return _parts;
248  }
249
250  public void setParts(List<AssessmentPart> value) {
251    _parts = value;
252  }
253
254  /**
255   * Add a new {@link AssessmentPart} item to the underlying collection.
256   * @param item the item to add
257   * @return {@code true}
258   */
259  public boolean addPart(AssessmentPart item) {
260    AssessmentPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
261    if (_parts == null) {
262      _parts = new LinkedList<>();
263    }
264    return _parts.add(value);
265  }
266
267  /**
268   * Remove the first matching {@link AssessmentPart} item from the underlying collection.
269   * @param item the item to remove
270   * @return {@code true} if the item was removed or {@code false} otherwise
271   */
272  public boolean removePart(AssessmentPart item) {
273    AssessmentPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
274    return _parts != null && _parts.remove(value);
275  }
276
277  public List<Link> getLinks() {
278    return _links;
279  }
280
281  public void setLinks(List<Link> value) {
282    _links = value;
283  }
284
285  /**
286   * Add a new {@link Link} item to the underlying collection.
287   * @param item the item to add
288   * @return {@code true}
289   */
290  public boolean addLink(Link item) {
291    Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
292    if (_links == null) {
293      _links = new LinkedList<>();
294    }
295    return _links.add(value);
296  }
297
298  /**
299   * Remove the first matching {@link Link} item from the underlying collection.
300   * @param item the item to remove
301   * @return {@code true} if the item was removed or {@code false} otherwise
302   */
303  public boolean removeLink(Link item) {
304    Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
305    return _links != null && _links.remove(value);
306  }
307
308  @Override
309  public String toString() {
310    return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString();
311  }
312}