001package gov.nist.secauto.oscal.lib.model;
002
003import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValue;
004import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValues;
005import gov.nist.secauto.metaschema.binding.model.annotations.AssemblyConstraints;
006import gov.nist.secauto.metaschema.binding.model.annotations.BoundAssembly;
007import gov.nist.secauto.metaschema.binding.model.annotations.BoundField;
008import gov.nist.secauto.metaschema.binding.model.annotations.BoundFieldValue;
009import gov.nist.secauto.metaschema.binding.model.annotations.BoundFlag;
010import gov.nist.secauto.metaschema.binding.model.annotations.GroupAs;
011import gov.nist.secauto.metaschema.binding.model.annotations.HasCardinality;
012import gov.nist.secauto.metaschema.binding.model.annotations.MetaschemaAssembly;
013import gov.nist.secauto.metaschema.binding.model.annotations.ValueConstraints;
014import gov.nist.secauto.metaschema.model.common.JsonGroupAsBehavior;
015import gov.nist.secauto.metaschema.model.common.constraint.IConstraint;
016import gov.nist.secauto.metaschema.model.common.datatype.adapter.TokenAdapter;
017import gov.nist.secauto.metaschema.model.common.datatype.adapter.UriAdapter;
018import gov.nist.secauto.metaschema.model.common.datatype.adapter.UuidAdapter;
019import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine;
020import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLineAdapter;
021import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultiline;
022import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultilineAdapter;
023import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
024import java.lang.Override;
025import java.lang.String;
026import java.net.URI;
027import java.util.LinkedList;
028import java.util.List;
029import java.util.UUID;
030import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle;
031import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
032
033/**
034 * A partition of an assessment plan or results or a child of another part.
035 */
036@MetaschemaAssembly(
037    formalName = "Assessment Part",
038    description = "A partition of an assessment plan or results or a child of another part.",
039    name = "assessment-part",
040    metaschema = OscalAssessmentCommonMetaschema.class,
041    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"
042            + "\n"
043            + "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"
044            + "\n"
045            + "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"
046            + "\n"
047            + "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"
048            + "\n"
049            + "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."
050)
051@ValueConstraints(
052    allowedValues = {
053        @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\".")),
054        @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.")})
055    }
056)
057@AssemblyConstraints(
058    hasCardinality = @HasCardinality(level = IConstraint.Level.ERROR, target = ".[@name='objective']/prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name='method']", minOccurs = 1)
059)
060public class AssessmentPart {
061  @BoundFlag(
062      formalName = "Part Identifier",
063      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.",
064      useName = "uuid",
065      typeAdapter = UuidAdapter.class
066  )
067  private UUID _uuid;
068
069  @BoundFlag(
070      formalName = "Part Name",
071      description = "A textual label that uniquely identifies the part's semantic type.",
072      useName = "name",
073      required = true,
074      typeAdapter = TokenAdapter.class
075  )
076  @ValueConstraints(
077      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  @BoundFlag(
082      formalName = "Part Namespace",
083      description = "A namespace qualifying the part's name. This allows different organizations to associate distinct semantics with the same name.",
084      useName = "ns",
085      typeAdapter = UriAdapter.class,
086      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"
087              + "\n"
088              + "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."
089  )
090  private URI _ns;
091
092  @BoundFlag(
093      formalName = "Part Class",
094      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`.",
095      useName = "class",
096      typeAdapter = TokenAdapter.class,
097      remarks = "A `class` can be used in validation rules to express extra constraints over named items of a specific `class` value.\n"
098              + "\n"
099              + "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}