001package gov.nist.secauto.oscal.lib.model; 002 003import gov.nist.secauto.metaschema.core.datatype.adapter.UuidAdapter; 004import gov.nist.secauto.metaschema.core.model.IBoundObject; 005import gov.nist.secauto.metaschema.core.model.IMetaschemaData; 006import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior; 007import gov.nist.secauto.metaschema.core.model.constraint.IConstraint; 008import gov.nist.secauto.metaschema.core.util.ObjectUtils; 009import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValue; 010import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValues; 011import gov.nist.secauto.metaschema.databind.model.annotations.AssemblyConstraints; 012import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly; 013import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag; 014import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs; 015import gov.nist.secauto.metaschema.databind.model.annotations.Index; 016import gov.nist.secauto.metaschema.databind.model.annotations.IsUnique; 017import gov.nist.secauto.metaschema.databind.model.annotations.KeyField; 018import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly; 019import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints; 020import gov.nist.secauto.oscal.lib.model.control.catalog.AbstractCatalog; 021import java.lang.Override; 022import java.lang.String; 023import java.util.LinkedList; 024import java.util.List; 025import java.util.UUID; 026import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 027import org.apache.commons.lang3.builder.ToStringStyle; 028 029/** 030 * A structured, <a href="https://pages.nist.gov/OSCAL/concepts/terminology/#catalog">organized collection</a> of control information. 031 */ 032@MetaschemaAssembly( 033 formalName = "Catalog", 034 description = "A structured, [organized collection](https://pages.nist.gov/OSCAL/concepts/terminology/#catalog) of control information.", 035 name = "catalog", 036 moduleClass = OscalCatalogModule.class, 037 rootName = "catalog", 038 remarks = "Catalogs may use one or more `group` objects to subdivide the control contents of a catalog.", 039 valueConstraints = @ValueConstraints(allowedValues = {@AllowedValues(level = IConstraint.Level.ERROR, target = "metadata/prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = {@AllowedValue(value = "resolution-tool", description = "The tool used to produce a resolved profile."), @AllowedValue(value = "source-profile-uuid", description = "The document-level `uuid` of the source profile from which the catalog was produced by [profile resolution](https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/).")}), @AllowedValues(level = IConstraint.Level.ERROR, target = "metadata/link/@rel", allowOthers = true, values = {@AllowedValue(value = "source-profile", description = "The profile from which the catalog was produced by [profile resolution](https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/)."), @AllowedValue(value = "source-profile-uuid", description = "The document-level `uuid` of the profile from which the catalog was produced by [profile resolution](https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/).")})}), 040 modelConstraints = @AssemblyConstraints(index = {@Index(level = IConstraint.Level.ERROR, target = "//part", name = "catalog-parts", keyFields = @KeyField(target = "@id")), @Index(level = IConstraint.Level.ERROR, target = "//prop", name = "catalog-props", keyFields = @KeyField(target = "@uuid")), @Index(level = IConstraint.Level.ERROR, target = "//(control|group|part)", name = "catalog-groups-controls-parts", keyFields = @KeyField(target = "@id")), @Index(level = IConstraint.Level.ERROR, target = "//control", name = "catalog-controls", keyFields = @KeyField(target = "@id")), @Index(level = IConstraint.Level.ERROR, target = "//param", name = "catalog-params", keyFields = @KeyField(target = "@id")), @Index(level = IConstraint.Level.ERROR, target = "//group", name = "catalog-groups", keyFields = @KeyField(target = "@id")), @Index(id = "oscal-catalog-index-metadata-scoped-metadata-role-id", formalName = "In-Scope Role Identifiers", description = "An index of role identifiers that are in-scope for the catalog model.", level = IConstraint.Level.ERROR, target = "metadata/role", name = "index-imports-metadata-role-id", keyFields = @KeyField(target = "@id")), @Index(id = "oscal-catalog-index-metadata-scoped-location-uuid", level = IConstraint.Level.ERROR, target = "metadata/location", name = "index-imports-metadata-location-uuid", keyFields = @KeyField(target = "@uuid")), @Index(id = "oscal-catalog-index-metadata-scoped-party-uuid", level = IConstraint.Level.ERROR, target = "metadata/party", name = "index-imports-metadata-party-uuid", keyFields = @KeyField(target = "@uuid")), @Index(id = "oscal-catalog-index-metadata-scoped-party-organization-uuid", level = IConstraint.Level.ERROR, target = "metadata/party[@type='organization']", name = "index-imports-metadata-party-organization-uuid", keyFields = @KeyField(target = "@uuid")), @Index(id = "oscal-catalog-index-metadata-scoped-property-uuid", level = IConstraint.Level.ERROR, target = ".//prop[@uuid]", name = "index-imports-metadata-property-uuid", keyFields = @KeyField(target = "@uuid"))}, unique = {@IsUnique(id = "oscal-unique-document-id", formalName = "Unique Document Identifier", description = "Ensure all document identifiers have a unique combination of @scheme and value.", level = IConstraint.Level.ERROR, target = "document-id", keyFields = {@KeyField(target = "@scheme"), @KeyField}), @IsUnique(id = "oscal-unique-property-in-context-location", formalName = "Unique Properties", description = "Ensure all properties are unique for a given location using a unique combination of @ns, @name, @class. @group. and @value.", level = IConstraint.Level.ERROR, target = ".//prop", keyFields = {@KeyField(target = "path(..)"), @KeyField(target = "@name"), @KeyField(target = "@ns"), @KeyField(target = "@class"), @KeyField(target = "@group"), @KeyField(target = "@value")}), @IsUnique(id = "oscal-unique-link-in-context-location", formalName = "Unique Links", description = "Ensure all links are unique for a given location using a unique combination of @href, @rel, and @media-type.", level = IConstraint.Level.ERROR, target = ".//link", keyFields = {@KeyField(target = "path(..)"), @KeyField(target = "@href"), @KeyField(target = "@rel"), @KeyField(target = "@media-type")}), @IsUnique(id = "oscal-unique-responsibility-in-context-location", formalName = "Unique Responsibilities", description = "Ensure all responsible-roles and responsible-parties are unique for a given location using a unique combination of @role-id and the combination of @party-uuid values.", level = IConstraint.Level.ERROR, target = ".//(responsible-party|responsible-role)", keyFields = {@KeyField(target = "path(..)"), @KeyField(target = "@role-id"), @KeyField(target = "@party-uuid")}, remarks = "Since `responsible-party` and `responsible-role` associate multiple `party-uuid` entries with a single `role-id`, each role-id must be referenced only once.")}) 041) 042public class Catalog extends AbstractCatalog implements IBoundObject { 043 private final IMetaschemaData __metaschemaData; 044 045 /** 046 * "Provides a globally unique means to identify a given catalog instance." 047 */ 048 @BoundFlag( 049 formalName = "Catalog Universally Unique Identifier", 050 description = "Provides a globally unique means to identify a given catalog instance.", 051 name = "uuid", 052 required = true, 053 typeAdapter = UuidAdapter.class 054 ) 055 private UUID _uuid; 056 057 @BoundAssembly( 058 formalName = "Document Metadata", 059 description = "Provides information about the containing document, and defines concepts that are shared across the document.", 060 useName = "metadata", 061 minOccurs = 1 062 ) 063 private Metadata _metadata; 064 065 @BoundAssembly( 066 formalName = "Parameter", 067 description = "Parameters provide a mechanism for the dynamic assignment of value(s) in a control.", 068 useName = "param", 069 maxOccurs = -1, 070 groupAs = @GroupAs(name = "params", inJson = JsonGroupAsBehavior.LIST) 071 ) 072 private List<Parameter> _params; 073 074 @BoundAssembly( 075 formalName = "Control", 076 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.", 077 useName = "control", 078 maxOccurs = -1, 079 groupAs = @GroupAs(name = "controls", inJson = JsonGroupAsBehavior.LIST) 080 ) 081 private List<Control> _controls; 082 083 @BoundAssembly( 084 formalName = "Control Group", 085 description = "A group of controls, or of groups of controls.", 086 useName = "group", 087 maxOccurs = -1, 088 groupAs = @GroupAs(name = "groups", inJson = JsonGroupAsBehavior.LIST) 089 ) 090 private List<CatalogGroup> _groups; 091 092 @BoundAssembly( 093 formalName = "Back matter", 094 description = "A collection of resources that may be referenced from within the OSCAL document instance.", 095 useName = "back-matter", 096 remarks = "Back matter including references and resources." 097 ) 098 private BackMatter _backMatter; 099 100 public Catalog() { 101 this(null); 102 } 103 104 public Catalog(IMetaschemaData data) { 105 this.__metaschemaData = data; 106 } 107 108 @Override 109 public IMetaschemaData getMetaschemaData() { 110 return __metaschemaData; 111 } 112 113 public UUID getUuid() { 114 return _uuid; 115 } 116 117 public void setUuid(UUID value) { 118 _uuid = value; 119 } 120 121 public Metadata getMetadata() { 122 return _metadata; 123 } 124 125 public void setMetadata(Metadata value) { 126 _metadata = value; 127 } 128 129 public List<Parameter> getParams() { 130 return _params; 131 } 132 133 public void setParams(List<Parameter> value) { 134 _params = value; 135 } 136 137 /** 138 * Add a new {@link Parameter} item to the underlying collection. 139 * @param item the item to add 140 * @return {@code true} 141 */ 142 public boolean addParam(Parameter item) { 143 Parameter value = ObjectUtils.requireNonNull(item,"item cannot be null"); 144 if (_params == null) { 145 _params = new LinkedList<>(); 146 } 147 return _params.add(value); 148 } 149 150 /** 151 * Remove the first matching {@link Parameter} item from the underlying collection. 152 * @param item the item to remove 153 * @return {@code true} if the item was removed or {@code false} otherwise 154 */ 155 public boolean removeParam(Parameter item) { 156 Parameter value = ObjectUtils.requireNonNull(item,"item cannot be null"); 157 return _params != null && _params.remove(value); 158 } 159 160 public List<Control> getControls() { 161 return _controls; 162 } 163 164 public void setControls(List<Control> value) { 165 _controls = value; 166 } 167 168 /** 169 * Add a new {@link Control} item to the underlying collection. 170 * @param item the item to add 171 * @return {@code true} 172 */ 173 public boolean addControl(Control item) { 174 Control value = ObjectUtils.requireNonNull(item,"item cannot be null"); 175 if (_controls == null) { 176 _controls = new LinkedList<>(); 177 } 178 return _controls.add(value); 179 } 180 181 /** 182 * Remove the first matching {@link Control} item from the underlying collection. 183 * @param item the item to remove 184 * @return {@code true} if the item was removed or {@code false} otherwise 185 */ 186 public boolean removeControl(Control item) { 187 Control value = ObjectUtils.requireNonNull(item,"item cannot be null"); 188 return _controls != null && _controls.remove(value); 189 } 190 191 public List<CatalogGroup> getGroups() { 192 return _groups; 193 } 194 195 public void setGroups(List<CatalogGroup> value) { 196 _groups = value; 197 } 198 199 /** 200 * Add a new {@link CatalogGroup} item to the underlying collection. 201 * @param item the item to add 202 * @return {@code true} 203 */ 204 public boolean addGroup(CatalogGroup item) { 205 CatalogGroup value = ObjectUtils.requireNonNull(item,"item cannot be null"); 206 if (_groups == null) { 207 _groups = new LinkedList<>(); 208 } 209 return _groups.add(value); 210 } 211 212 /** 213 * Remove the first matching {@link CatalogGroup} item from the underlying collection. 214 * @param item the item to remove 215 * @return {@code true} if the item was removed or {@code false} otherwise 216 */ 217 public boolean removeGroup(CatalogGroup item) { 218 CatalogGroup value = ObjectUtils.requireNonNull(item,"item cannot be null"); 219 return _groups != null && _groups.remove(value); 220 } 221 222 public BackMatter getBackMatter() { 223 return _backMatter; 224 } 225 226 public void setBackMatter(BackMatter value) { 227 _backMatter = value; 228 } 229 230 @Override 231 public String toString() { 232 return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString(); 233 } 234}