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