View Javadoc
1   package gov.nist.secauto.oscal.lib.model;
2   
3   import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValue;
4   import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValues;
5   import gov.nist.secauto.metaschema.binding.model.annotations.BoundAssembly;
6   import gov.nist.secauto.metaschema.binding.model.annotations.BoundField;
7   import gov.nist.secauto.metaschema.binding.model.annotations.BoundFieldValue;
8   import gov.nist.secauto.metaschema.binding.model.annotations.BoundFlag;
9   import gov.nist.secauto.metaschema.binding.model.annotations.Expect;
10  import gov.nist.secauto.metaschema.binding.model.annotations.GroupAs;
11  import gov.nist.secauto.metaschema.binding.model.annotations.IndexHasKey;
12  import gov.nist.secauto.metaschema.binding.model.annotations.KeyField;
13  import gov.nist.secauto.metaschema.binding.model.annotations.MetaschemaAssembly;
14  import gov.nist.secauto.metaschema.binding.model.annotations.ValueConstraints;
15  import gov.nist.secauto.metaschema.model.common.JsonGroupAsBehavior;
16  import gov.nist.secauto.metaschema.model.common.constraint.IConstraint;
17  import gov.nist.secauto.metaschema.model.common.datatype.adapter.TokenAdapter;
18  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine;
19  import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLineAdapter;
20  import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
21  import gov.nist.secauto.oscal.lib.model.control.catalog.AbstractControl;
22  import java.lang.Override;
23  import java.lang.String;
24  import java.util.LinkedList;
25  import java.util.List;
26  import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle;
27  import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
28  
29  /**
30   * 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.
31   */
32  @MetaschemaAssembly(
33      formalName = "Control",
34      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.",
35      name = "control",
36      metaschema = OscalCatalogMetaschema.class,
37      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"
38              + "\n"
39              + "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."
40  )
41  @ValueConstraints(
42      allowedValues = {
43          @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.")}),
44          @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.")}),
45          @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.")}),
46          @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.")}),
47          @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."),
48          @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."),
49          @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."),
50          @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\".")),
51          @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\".")),
52          @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.")})
53      },
54      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 = "#(.*)")),
55      expect = {
56          @Expect(id = "catalog-control-require-statement-when-not-withdrawn", level = IConstraint.Level.ERROR, test = "prop[@name='status']/@value=('withdrawn','Withdrawn') or part[@name='statement']"),
57          @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']")
58      }
59  )
60  public class Control extends AbstractControl {
61    @BoundFlag(
62        formalName = "Control Identifier",
63        description = "Identifies a control such that it can be referenced in the defining catalog and other OSCAL instances (e.g., profiles).",
64        useName = "id",
65        required = true,
66        typeAdapter = TokenAdapter.class
67    )
68    private String _id;
69  
70    @BoundFlag(
71        formalName = "Control Class",
72        description = "A textual label that provides a sub-type or characterization of the control.",
73        useName = "class",
74        typeAdapter = TokenAdapter.class,
75        remarks = "A `class` can be used in validation rules to express extra constraints over named items of a specific `class` value.\n"
76                + "\n"
77                + "A `class` can also be used in an OSCAL profile as a means to target an alteration to control content."
78    )
79    private String _clazz;
80  
81    /**
82     * "A name given to the control, which may be used by a tool for display and navigation."
83     */
84    @BoundField(
85        formalName = "Control Title",
86        description = "A name given to the control, which may be used by a tool for display and navigation.",
87        useName = "title",
88        minOccurs = 1
89    )
90    @BoundFieldValue(
91        typeAdapter = MarkupLineAdapter.class
92    )
93    private MarkupLine _title;
94  
95    @BoundAssembly(
96        formalName = "Parameter",
97        description = "Parameters provide a mechanism for the dynamic assignment of value(s) in a control.",
98        useName = "param",
99        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 }