Control.java

package gov.nist.secauto.oscal.lib.model;

import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValue;
import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValues;
import gov.nist.secauto.metaschema.binding.model.annotations.BoundAssembly;
import gov.nist.secauto.metaschema.binding.model.annotations.BoundField;
import gov.nist.secauto.metaschema.binding.model.annotations.BoundFieldValue;
import gov.nist.secauto.metaschema.binding.model.annotations.BoundFlag;
import gov.nist.secauto.metaschema.binding.model.annotations.Expect;
import gov.nist.secauto.metaschema.binding.model.annotations.GroupAs;
import gov.nist.secauto.metaschema.binding.model.annotations.IndexHasKey;
import gov.nist.secauto.metaschema.binding.model.annotations.KeyField;
import gov.nist.secauto.metaschema.binding.model.annotations.MetaschemaAssembly;
import gov.nist.secauto.metaschema.binding.model.annotations.ValueConstraints;
import gov.nist.secauto.metaschema.model.common.JsonGroupAsBehavior;
import gov.nist.secauto.metaschema.model.common.constraint.IConstraint;
import gov.nist.secauto.metaschema.model.common.datatype.adapter.TokenAdapter;
import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLineAdapter;
import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
import gov.nist.secauto.oscal.lib.model.control.catalog.AbstractControl;
import java.lang.Override;
import java.lang.String;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

/**
 * A <a href="https://pages.nist.gov/OSCAL/concepts/terminology/#control">structured object</a> representing a requirement or guideline, which when implemented will reduce an aspect of risk related to an information system and its information.
 */
@MetaschemaAssembly(
    formalName = "Control",
    description = "A [structured object](https://pages.nist.gov/OSCAL/concepts/terminology/#control) representing a requirement or guideline, which when implemented will reduce an aspect of risk related to an information system and its information.",
    name = "control",
    metaschema = OscalCatalogMetaschema.class,
    remarks = "Each security or privacy control within the catalog is defined by a distinct control instance. Controls may be as complex or as simple as a catalog defines them. They may be decomposed or further specified into child `control` objects, for example to represent control enhancements or specific breakouts of control functionality, to be maintained as discrete requirements. Controls may also contain structured parts (using `part`) and they may be grouped together in families or classes with `group`.\n"
            + "\n"
            + "Control structures in OSCAL will also exhibit regularities and rules that are not codified in OSCAL but in its applications or domains of application. For example, for catalogs describing controls as defined by NIST SP 800-53, a control must have a part with the name \"statement\", which represents the textual narrative of the control. This \"statement\" part must occur only once, but may have nested parts to allow for multiple paragraphs or sections of text. This organization supports addressability of this data content as long as, and only insofar as, it is consistently implemented across the control set. As given with these model definitions, constraints defined and assigned here can aid in ensuring this regularity; but other such constraints and other useful patterns of use remain to be discovered and described."
)
@ValueConstraints(
    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."), @AllowedValue(value = "status", description = "The status of a `control`. For example, a value of 'withdrawn' can indicate that the `control` has been withdrawn and should no longer be used.")}),
        @AllowedValues(level = IConstraint.Level.ERROR, target = "prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name='status']/@value", values = {@AllowedValue(value = "withdrawn", description = "The control is no longer used."), @AllowedValue(value = "Withdrawn", description = "\\*\\*(deprecated)\\*\\*\\* Use 'withdrawn' instead.")}),
        @AllowedValues(level = IConstraint.Level.ERROR, target = "link/@rel", allowOthers = true, values = {@AllowedValue(value = "reference", description = "The link cites an external resource related to this control."), @AllowedValue(value = "related", description = "The link identifies another control with bearing to this control."), @AllowedValue(value = "required", description = "The link identifies another control that must be present if this control is present."), @AllowedValue(value = "incorporated-into", description = "The link identifies other control content where this control content is now addressed."), @AllowedValue(value = "moved-to", description = "The containing control definition was moved to the referenced control.")}),
        @AllowedValues(level = IConstraint.Level.ERROR, target = "part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = {@AllowedValue(value = "overview", description = "An introduction to a control or a group of controls."), @AllowedValue(value = "statement", description = "A set of implementation requirements or recommendations."), @AllowedValue(value = "guidance", description = "Additional information to consider when selecting, implementing, assessing, and monitoring a control."), @AllowedValue(value = "example", description = "An example of an implemented requirement or control statement."), @AllowedValue(value = "assessment", description = "\\*\\*(deprecated)\\*\\* Use 'assessment-method' instead."), @AllowedValue(value = "assessment-method", description = "The part describes a method-based assessment over a set of assessment objects.")}),
        @AllowedValues(level = IConstraint.Level.ERROR, target = "part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name='statement']//part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = @AllowedValue(value = "item", description = "An individual item within a control statement."), remarks = "Nested statement parts are \"item\" parts."),
        @AllowedValues(level = IConstraint.Level.ERROR, target = ".//part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = {@AllowedValue(value = "objective", description = "\\*\\*(deprecated)\\*\\* Use 'assessment-objective' instead."), @AllowedValue(value = "assessment-objective", description = "The part describes a set of assessment objectives.")}, remarks = "Objectives can be nested."),
        @AllowedValues(level = IConstraint.Level.ERROR, target = "part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name=('assessment','assessment-method')]/part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = {@AllowedValue(value = "objects", description = "\\*\\*(deprecated)\\*\\* Use 'assessment-objects' instead."), @AllowedValue(value = "assessment-objects", description = "Provides a listing of assessment objects.")}, remarks = "Assessment objects appear on assessment methods."),
        @AllowedValues(level = IConstraint.Level.ERROR, target = "part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name=('assessment','assessment-method')]/prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = @AllowedValue(value = "method", description = "\\*\\*(deprecated)\\*\\* Use 'method' in the 'http://csrc.nist.gov/ns/rmf' namespace. The assessment method to use. This typically appears on parts with the name \"assessment-method\".")),
        @AllowedValues(level = IConstraint.Level.ERROR, target = "part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name=('assessment','assessment-method')]/prop[has-oscal-namespace('http://csrc.nist.gov/ns/rmf')]/@name", values = @AllowedValue(value = "method", description = "The assessment method to use. This typically appears on parts with the name \"assessment-method\".")),
        @AllowedValues(level = IConstraint.Level.ERROR, target = "part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name=('assessment','assessment-method')]/prop[has-oscal-namespace(('http://csrc.nist.gov/ns/oscal','http://csrc.nist.gov/ns/rmf')) 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.")})
    },
    indexHasKey = @IndexHasKey(level = IConstraint.Level.ERROR, target = "link[@rel=('related','required','incorporated-into','moved-to') and starts-with(@href,'#')]", indexName = "catalog-groups-controls-parts", keyFields = @KeyField(target = "@href", pattern = "#(.*)")),
    expect = {
        @Expect(id = "catalog-control-require-statement-when-not-withdrawn", level = IConstraint.Level.ERROR, test = "prop[@name='status']/@value=('withdrawn','Withdrawn') or part[@name='statement']"),
        @Expect(level = IConstraint.Level.WARNING, target = "part[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name=('assessment','assessment-method')]", test = "prop[has-oscal-namespace(('http://csrc.nist.gov/ns/oscal','http://csrc.nist.gov/ns/rmf')) and @name='method']")
    }
)
public class Control extends AbstractControl {
  @BoundFlag(
      formalName = "Control Identifier",
      description = "Identifies a control such that it can be referenced in the defining catalog and other OSCAL instances (e.g., profiles).",
      useName = "id",
      required = true,
      typeAdapter = TokenAdapter.class
  )
  private String _id;

  @BoundFlag(
      formalName = "Control Class",
      description = "A textual label that provides a sub-type or characterization of the control.",
      useName = "class",
      typeAdapter = TokenAdapter.class,
      remarks = "A `class` can be used in validation rules to express extra constraints over named items of a specific `class` value.\n"
              + "\n"
              + "A `class` can also be used in an OSCAL profile as a means to target an alteration to control content."
  )
  private String _clazz;

  /**
   * "A name given to the control, which may be used by a tool for display and navigation."
   */
  @BoundField(
      formalName = "Control Title",
      description = "A name given to the control, which may be used by a tool for display and navigation.",
      useName = "title",
      minOccurs = 1
  )
  @BoundFieldValue(
      typeAdapter = MarkupLineAdapter.class
  )
  private MarkupLine _title;

  @BoundAssembly(
      formalName = "Parameter",
      description = "Parameters provide a mechanism for the dynamic assignment of value(s) in a control.",
      useName = "param",
      maxOccurs = -1
  )
  @GroupAs(
      name = "params",
      inJson = JsonGroupAsBehavior.LIST
  )
  private List<Parameter> _params;

  @BoundAssembly(
      formalName = "Property",
      description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.",
      useName = "prop",
      maxOccurs = -1
  )
  @GroupAs(
      name = "props",
      inJson = JsonGroupAsBehavior.LIST
  )
  private List<Property> _props;

  @BoundAssembly(
      formalName = "Link",
      description = "A reference to a local or remote resource, that has a specific relation to the containing object.",
      useName = "link",
      maxOccurs = -1
  )
  @GroupAs(
      name = "links",
      inJson = JsonGroupAsBehavior.LIST
  )
  private List<Link> _links;

  @BoundAssembly(
      formalName = "Part",
      description = "An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.",
      useName = "part",
      maxOccurs = -1
  )
  @GroupAs(
      name = "parts",
      inJson = JsonGroupAsBehavior.LIST
  )
  private List<ControlPart> _parts;

  @BoundAssembly(
      formalName = "Control",
      description = "A [structured object](https://pages.nist.gov/OSCAL/concepts/terminology/#control) representing a requirement or guideline, which when implemented will reduce an aspect of risk related to an information system and its information.",
      useName = "control",
      maxOccurs = -1
  )
  @GroupAs(
      name = "controls",
      inJson = JsonGroupAsBehavior.LIST
  )
  private List<Control> _controls;

  public Control() {
  }

  public String getId() {
    return _id;
  }

  public void setId(String value) {
    _id = value;
  }

  public String getClazz() {
    return _clazz;
  }

  public void setClazz(String value) {
    _clazz = value;
  }

  public MarkupLine getTitle() {
    return _title;
  }

  public void setTitle(MarkupLine value) {
    _title = value;
  }

  public List<Parameter> getParams() {
    return _params;
  }

  public void setParams(List<Parameter> value) {
    _params = value;
  }

  /**
   * Add a new {@link Parameter} item to the underlying collection.
   * @param item the item to add
   * @return {@code true}
   */
  public boolean addParam(Parameter item) {
    Parameter value = ObjectUtils.requireNonNull(item,"item cannot be null");
    if (_params == null) {
      _params = new LinkedList<>();
    }
    return _params.add(value);
  }

  /**
   * Remove the first matching {@link Parameter} item from the underlying collection.
   * @param item the item to remove
   * @return {@code true} if the item was removed or {@code false} otherwise
   */
  public boolean removeParam(Parameter item) {
    Parameter value = ObjectUtils.requireNonNull(item,"item cannot be null");
    return _params == null ? false : _params.remove(value);
  }

  public List<Property> getProps() {
    return _props;
  }

  public void setProps(List<Property> value) {
    _props = value;
  }

  /**
   * Add a new {@link Property} item to the underlying collection.
   * @param item the item to add
   * @return {@code true}
   */
  public boolean addProp(Property item) {
    Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
    if (_props == null) {
      _props = new LinkedList<>();
    }
    return _props.add(value);
  }

  /**
   * Remove the first matching {@link Property} item from the underlying collection.
   * @param item the item to remove
   * @return {@code true} if the item was removed or {@code false} otherwise
   */
  public boolean removeProp(Property item) {
    Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
    return _props == null ? false : _props.remove(value);
  }

  public List<Link> getLinks() {
    return _links;
  }

  public void setLinks(List<Link> value) {
    _links = value;
  }

  /**
   * Add a new {@link Link} item to the underlying collection.
   * @param item the item to add
   * @return {@code true}
   */
  public boolean addLink(Link item) {
    Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
    if (_links == null) {
      _links = new LinkedList<>();
    }
    return _links.add(value);
  }

  /**
   * Remove the first matching {@link Link} item from the underlying collection.
   * @param item the item to remove
   * @return {@code true} if the item was removed or {@code false} otherwise
   */
  public boolean removeLink(Link item) {
    Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
    return _links == null ? false : _links.remove(value);
  }

  public List<ControlPart> getParts() {
    return _parts;
  }

  public void setParts(List<ControlPart> value) {
    _parts = value;
  }

  /**
   * Add a new {@link ControlPart} item to the underlying collection.
   * @param item the item to add
   * @return {@code true}
   */
  public boolean addPart(ControlPart item) {
    ControlPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
    if (_parts == null) {
      _parts = new LinkedList<>();
    }
    return _parts.add(value);
  }

  /**
   * Remove the first matching {@link ControlPart} item from the underlying collection.
   * @param item the item to remove
   * @return {@code true} if the item was removed or {@code false} otherwise
   */
  public boolean removePart(ControlPart item) {
    ControlPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
    return _parts == null ? false : _parts.remove(value);
  }

  public List<Control> getControls() {
    return _controls;
  }

  public void setControls(List<Control> value) {
    _controls = value;
  }

  /**
   * Add a new {@link Control} item to the underlying collection.
   * @param item the item to add
   * @return {@code true}
   */
  public boolean addControl(Control item) {
    Control value = ObjectUtils.requireNonNull(item,"item cannot be null");
    if (_controls == null) {
      _controls = new LinkedList<>();
    }
    return _controls.add(value);
  }

  /**
   * Remove the first matching {@link Control} item from the underlying collection.
   * @param item the item to remove
   * @return {@code true} if the item was removed or {@code false} otherwise
   */
  public boolean removeControl(Control item) {
    Control value = ObjectUtils.requireNonNull(item,"item cannot be null");
    return _controls == null ? false : _controls.remove(value);
  }

  @Override
  public String toString() {
    return new ReflectionToStringBuilder(this, MultilineRecursiveToStringStyle.MULTI_LINE_STYLE).toString();
  }
}