001package gov.nist.secauto.oscal.lib.model;
002
003import gov.nist.secauto.metaschema.core.datatype.adapter.TokenAdapter;
004import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine;
005import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLineAdapter;
006import gov.nist.secauto.metaschema.core.model.IBoundObject;
007import gov.nist.secauto.metaschema.core.model.IMetaschemaData;
008import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior;
009import gov.nist.secauto.metaschema.core.model.constraint.IConstraint;
010import gov.nist.secauto.metaschema.core.util.ObjectUtils;
011import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValue;
012import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValues;
013import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly;
014import gov.nist.secauto.metaschema.databind.model.annotations.BoundField;
015import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag;
016import gov.nist.secauto.metaschema.databind.model.annotations.Expect;
017import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs;
018import gov.nist.secauto.metaschema.databind.model.annotations.IndexHasKey;
019import gov.nist.secauto.metaschema.databind.model.annotations.KeyField;
020import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly;
021import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints;
022import gov.nist.secauto.oscal.lib.model.control.catalog.AbstractControl;
023import java.lang.Override;
024import java.lang.String;
025import java.util.LinkedList;
026import java.util.List;
027import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
028import org.apache.commons.lang3.builder.ToStringStyle;
029
030/**
031 * 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.
032 */
033@MetaschemaAssembly(
034    formalName = "Control",
035    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.",
036    name = "control",
037    moduleClass = OscalCatalogModule.class,
038    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"
039            + "\n"
040            + "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.",
041    valueConstraints = @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']")})
042)
043public class Control extends AbstractControl implements IBoundObject {
044  private final IMetaschemaData __metaschemaData;
045
046  /**
047   * "Identifies a control such that it can be referenced in the defining catalog and other OSCAL instances (e.g., profiles)."
048   */
049  @BoundFlag(
050      formalName = "Control Identifier",
051      description = "Identifies a control such that it can be referenced in the defining catalog and other OSCAL instances (e.g., profiles).",
052      name = "id",
053      required = true,
054      typeAdapter = TokenAdapter.class
055  )
056  private String _id;
057
058  /**
059   * "A textual label that provides a sub-type or characterization of the control."
060   */
061  @BoundFlag(
062      formalName = "Control Class",
063      description = "A textual label that provides a sub-type or characterization of the control.",
064      name = "class",
065      typeAdapter = TokenAdapter.class,
066      remarks = "A `class` can be used in validation rules to express extra constraints over named items of a specific `class` value.\n"
067              + "\n"
068              + "A `class` can also be used in an OSCAL profile as a means to target an alteration to control content."
069  )
070  private String _clazz;
071
072  @BoundField(
073      formalName = "Control Title",
074      description = "A name given to the control, which may be used by a tool for display and navigation.",
075      useName = "title",
076      minOccurs = 1,
077      typeAdapter = MarkupLineAdapter.class
078  )
079  private MarkupLine _title;
080
081  @BoundAssembly(
082      formalName = "Parameter",
083      description = "Parameters provide a mechanism for the dynamic assignment of value(s) in a control.",
084      useName = "param",
085      maxOccurs = -1,
086      groupAs = @GroupAs(name = "params", inJson = JsonGroupAsBehavior.LIST)
087  )
088  private List<Parameter> _params;
089
090  @BoundAssembly(
091      formalName = "Property",
092      description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.",
093      useName = "prop",
094      maxOccurs = -1,
095      groupAs = @GroupAs(name = "props", inJson = JsonGroupAsBehavior.LIST)
096  )
097  private List<Property> _props;
098
099  @BoundAssembly(
100      formalName = "Link",
101      description = "A reference to a local or remote resource, that has a specific relation to the containing object.",
102      useName = "link",
103      maxOccurs = -1,
104      groupAs = @GroupAs(name = "links", inJson = JsonGroupAsBehavior.LIST)
105  )
106  private List<Link> _links;
107
108  @BoundAssembly(
109      formalName = "Part",
110      description = "An annotated, markup-based textual element of a control's or catalog group's definition, or a child of another part.",
111      useName = "part",
112      maxOccurs = -1,
113      groupAs = @GroupAs(name = "parts", inJson = JsonGroupAsBehavior.LIST)
114  )
115  private List<ControlPart> _parts;
116
117  @BoundAssembly(
118      formalName = "Control",
119      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.",
120      useName = "control",
121      maxOccurs = -1,
122      groupAs = @GroupAs(name = "controls", inJson = JsonGroupAsBehavior.LIST)
123  )
124  private List<Control> _controls;
125
126  public Control() {
127    this(null);
128  }
129
130  public Control(IMetaschemaData data) {
131    this.__metaschemaData = data;
132  }
133
134  @Override
135  public IMetaschemaData getMetaschemaData() {
136    return __metaschemaData;
137  }
138
139  public String getId() {
140    return _id;
141  }
142
143  public void setId(String value) {
144    _id = value;
145  }
146
147  public String getClazz() {
148    return _clazz;
149  }
150
151  public void setClazz(String value) {
152    _clazz = value;
153  }
154
155  public MarkupLine getTitle() {
156    return _title;
157  }
158
159  public void setTitle(MarkupLine value) {
160    _title = value;
161  }
162
163  public List<Parameter> getParams() {
164    return _params;
165  }
166
167  public void setParams(List<Parameter> value) {
168    _params = value;
169  }
170
171  /**
172   * Add a new {@link Parameter} item to the underlying collection.
173   * @param item the item to add
174   * @return {@code true}
175   */
176  public boolean addParam(Parameter item) {
177    Parameter value = ObjectUtils.requireNonNull(item,"item cannot be null");
178    if (_params == null) {
179      _params = new LinkedList<>();
180    }
181    return _params.add(value);
182  }
183
184  /**
185   * Remove the first matching {@link Parameter} item from the underlying collection.
186   * @param item the item to remove
187   * @return {@code true} if the item was removed or {@code false} otherwise
188   */
189  public boolean removeParam(Parameter item) {
190    Parameter value = ObjectUtils.requireNonNull(item,"item cannot be null");
191    return _params != null && _params.remove(value);
192  }
193
194  public List<Property> getProps() {
195    return _props;
196  }
197
198  public void setProps(List<Property> value) {
199    _props = value;
200  }
201
202  /**
203   * Add a new {@link Property} item to the underlying collection.
204   * @param item the item to add
205   * @return {@code true}
206   */
207  public boolean addProp(Property item) {
208    Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
209    if (_props == null) {
210      _props = new LinkedList<>();
211    }
212    return _props.add(value);
213  }
214
215  /**
216   * Remove the first matching {@link Property} item from the underlying collection.
217   * @param item the item to remove
218   * @return {@code true} if the item was removed or {@code false} otherwise
219   */
220  public boolean removeProp(Property item) {
221    Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
222    return _props != null && _props.remove(value);
223  }
224
225  public List<Link> getLinks() {
226    return _links;
227  }
228
229  public void setLinks(List<Link> value) {
230    _links = value;
231  }
232
233  /**
234   * Add a new {@link Link} item to the underlying collection.
235   * @param item the item to add
236   * @return {@code true}
237   */
238  public boolean addLink(Link item) {
239    Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
240    if (_links == null) {
241      _links = new LinkedList<>();
242    }
243    return _links.add(value);
244  }
245
246  /**
247   * Remove the first matching {@link Link} item from the underlying collection.
248   * @param item the item to remove
249   * @return {@code true} if the item was removed or {@code false} otherwise
250   */
251  public boolean removeLink(Link item) {
252    Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
253    return _links != null && _links.remove(value);
254  }
255
256  public List<ControlPart> getParts() {
257    return _parts;
258  }
259
260  public void setParts(List<ControlPart> value) {
261    _parts = value;
262  }
263
264  /**
265   * Add a new {@link ControlPart} item to the underlying collection.
266   * @param item the item to add
267   * @return {@code true}
268   */
269  public boolean addPart(ControlPart item) {
270    ControlPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
271    if (_parts == null) {
272      _parts = new LinkedList<>();
273    }
274    return _parts.add(value);
275  }
276
277  /**
278   * Remove the first matching {@link ControlPart} item from the underlying collection.
279   * @param item the item to remove
280   * @return {@code true} if the item was removed or {@code false} otherwise
281   */
282  public boolean removePart(ControlPart item) {
283    ControlPart value = ObjectUtils.requireNonNull(item,"item cannot be null");
284    return _parts != null && _parts.remove(value);
285  }
286
287  public List<Control> getControls() {
288    return _controls;
289  }
290
291  public void setControls(List<Control> value) {
292    _controls = value;
293  }
294
295  /**
296   * Add a new {@link Control} item to the underlying collection.
297   * @param item the item to add
298   * @return {@code true}
299   */
300  public boolean addControl(Control item) {
301    Control value = ObjectUtils.requireNonNull(item,"item cannot be null");
302    if (_controls == null) {
303      _controls = new LinkedList<>();
304    }
305    return _controls.add(value);
306  }
307
308  /**
309   * Remove the first matching {@link Control} item from the underlying collection.
310   * @param item the item to remove
311   * @return {@code true} if the item was removed or {@code false} otherwise
312   */
313  public boolean removeControl(Control item) {
314    Control value = ObjectUtils.requireNonNull(item,"item cannot be null");
315    return _controls != null && _controls.remove(value);
316  }
317
318  @Override
319  public String toString() {
320    return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString();
321  }
322}