001package gov.nist.secauto.oscal.lib.model; 002 003import gov.nist.secauto.metaschema.core.datatype.adapter.StringAdapter; 004import gov.nist.secauto.metaschema.core.datatype.adapter.TokenAdapter; 005import gov.nist.secauto.metaschema.core.datatype.adapter.UriAdapter; 006import gov.nist.secauto.metaschema.core.datatype.adapter.UuidAdapter; 007import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; 008import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultilineAdapter; 009import gov.nist.secauto.metaschema.core.model.IBoundObject; 010import gov.nist.secauto.metaschema.core.model.IMetaschemaData; 011import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior; 012import gov.nist.secauto.metaschema.core.model.constraint.IConstraint; 013import gov.nist.secauto.metaschema.core.util.ObjectUtils; 014import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValue; 015import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValues; 016import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly; 017import gov.nist.secauto.metaschema.databind.model.annotations.BoundField; 018import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag; 019import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs; 020import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly; 021import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints; 022import java.lang.Override; 023import java.lang.String; 024import java.net.URI; 025import java.util.LinkedList; 026import java.util.List; 027import java.util.UUID; 028import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 029import org.apache.commons.lang3.builder.ToStringStyle; 030 031/** 032 * A relationship-based mapping between a source and target set consisting of members (i.e., controls, control statements) from the respective source and target. 033 */ 034@MetaschemaAssembly( 035 formalName = "Mapping Entry", 036 description = "A relationship-based mapping between a source and target set consisting of members (i.e., controls, control statements) from the respective source and target.", 037 name = "map", 038 moduleClass = OscalMappingCommonModule.class 039) 040public class MappingEntry implements IBoundObject { 041 private final IMetaschemaData __metaschemaData; 042 043 /** 044 * "The unique identifier for the mapping entry." 045 */ 046 @BoundFlag( 047 formalName = "Mapping Entry Identifier", 048 description = "The unique identifier for the mapping entry.", 049 name = "uuid", 050 required = true, 051 typeAdapter = UuidAdapter.class 052 ) 053 private UUID _uuid; 054 055 /** 056 * "A namespace qualifying the relationship's value. This allows different organizations to associate distinct semantics for relationships with the same name." 057 */ 058 @BoundFlag( 059 formalName = "Relationship Value Namespace", 060 description = "A namespace qualifying the relationship's value. This allows different organizations to associate distinct semantics for relationships with the same name.", 061 name = "ns", 062 defaultValue = "http://csrc.nist.gov/ns/oscal", 063 typeAdapter = UriAdapter.class, 064 remarks = "This value must be an [absolute URI](https://pages.nist.gov/OSCAL/concepts/uri-use/#absolute-uri) that serves as a [naming system identifier](https://pages.nist.gov/OSCAL/concepts/uri-use/#use-as-a-naming-system-identifier).\n" 065 + "\n" 066 + "When a `ns` is not provided, its value should be assumed to be ` http://csrc.nist.gov/ns/oscal` and the name should be a name defined by the associated OSCAL model." 067 ) 068 private URI _ns; 069 070 /** 071 * "The method used for relating controls within the mapping. The supported methods are aligned with the <a href=\"https://doi.org/10.6028/NIST.IR.8477\">NIST Interagency Report (IR) 8477</a>, Section 4.3 Set Theory Relationship Mapping." 072 */ 073 @BoundFlag( 074 formalName = "Matching", 075 description = "The method used for relating controls within the mapping. The supported methods are aligned with the [NIST Interagency Report (IR) 8477](https://doi.org/10.6028/NIST.IR.8477), Section 4.3 Set Theory Relationship Mapping.", 076 name = "matching-rationale", 077 typeAdapter = StringAdapter.class, 078 valueConstraints = @ValueConstraints(allowedValues = @AllowedValues(level = IConstraint.Level.ERROR, values = {@AllowedValue(value = "syntactic", description = "Syntactic: How similar is the *wording* that expresses the two concepts. This is a word-for-word analysis of the relationship, not an interpretation of the language."), @AllowedValue(value = "semantic", description = "Semantic: How similar are the *meanings* of the two concepts? This involves some interpretation of each concept’s language."), @AllowedValue(value = "functional", description = "Functional: How similar are the *results* of executing the two concepts? This involves understanding what will happen if the two concepts are implemented, performed, or otherwise executed.")})) 079 ) 080 private String _matchingRationale; 081 082 @BoundField( 083 formalName = "Mapping Entry Relationship", 084 description = "The relationship type for the mapping entry, which describes the relationship between the effective requirements of the specified source and target sets in the context of the `matching-rationale` method globaly defined in the `provenance` unless overwritten locally in the ` map`. The `relationship` type and the `matching-rationale` must be used together. However, more than one `matching-rationale` method may apply to a `source` and `target` pair.", 085 useName = "relationship", 086 remarks = "For example, consider the CSF 1.1's PR.AC-1, \"Identities and credentials are issued, managed, verified, revoked, and audited for authorized devices, users and processes\", and the Privacy Framework's PR.AC-P1, \"Identities and credentials are issued, managed, verified, and devices.\"\n" 087 + "\n" 088 + "These two requirements have identical wording except for \"users\" versus \"individuals\" and the order of the last few words. With a \\`matching-rationale\\` of syntactic, the relationship type would beintersects with because the two overlap, but each includes content that the other does not. However, with a rationale of semantic, the relationship type would be equal if \"users\" and \"individuals\" have the same meaning in their respective sources, subset if \"users\" was a subset of \"individuals,\" and so on.\n" 089 + "\n" 090 + "When establishing relationships, mapping SHOULD be done at the control statement level where possible. This approach allows for a more accurate relationship.", 091 minOccurs = 1, 092 typeAdapter = TokenAdapter.class, 093 valueConstraints = @ValueConstraints(allowedValues = @AllowedValues(level = IConstraint.Level.ERROR, target = ".[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]", values = {@AllowedValue(value = "equivalent-to", description = "The `source` and `target` requirements are similar, although not necessarily identical. The words may differ, but both mapped sets convey similar information with the same effective meaning. This relationship may be reversed, since \\`A equivalent-to B\\` also means that \\`B equivalent-to A\\`. This relationship is less suitable for a *syntactic* `matching-rationale` ."), @AllowedValue(value = "equal-to", description = "The `source` and `target` requirements are the same. Differences in capitalization, spelling, and grammar can be ignored, if these differences do not change the meaning. This relationship may be reversed, since \\`A equal-to B\\` also means that \\`B equal-to A\\`."), @AllowedValue(value = "subset-of", description = "The `source` requirements are a subset of ` target` requirements. In other words, `target` contains all `source`requirements and aditional others. This relationship may be reversed as a \\`superset-of\\`, since \\`A subset-of B\\` also means that \\`B superset-of A\\`."), @AllowedValue(value = "superset-of", description = "The `source` requirements are a superset of `target` requirements. In other words, ` source` contains all `target`requirements and aditional others. This relationship may be reversed as a \\`subset-of\\`, since \\`A superset-of B\\` also means that \\`B subset-of A\\`."), @AllowedValue(value = "intersects-with", description = "The `source` and `target` requirements have some overlap, but each includes content that the other does not. This relationship may be reversed, since \\`A intersects-with B\\` also means that \\`B intersects-with A\\`. A mapping at statement level could result on `relationships` mapping that allows for more inference than using this relationship type."), @AllowedValue(value = "no-relationship", description = "The `source` and `target` requirements are not related; their content does not overlap. This relation is introduced not with the intention to support exhaustiv mapping of all requirements and statements that have no overlap, but rather to support edge cases such is the need to tailor a ` relationship` in the context of a component or system to better align with the implementation and configuration of the respective component or system. Also, this `relationship` is provided in support of the [NIST IR 8477](https://doi.org/10.6028/NIST.IR.8477).")})) 094 ) 095 private String _relationship; 096 097 @BoundAssembly( 098 formalName = "Mapping Entry Item (source or target)", 099 description = "A specific edge within a source or target that is the subject of a mapping.", 100 useName = "source", 101 minOccurs = 1, 102 maxOccurs = -1, 103 groupAs = @GroupAs(name = "sources", inJson = JsonGroupAsBehavior.LIST) 104 ) 105 private List<MappingItem> _sources; 106 107 @BoundAssembly( 108 formalName = "Mapping Entry Item (source or target)", 109 description = "A specific edge within a source or target that is the subject of a mapping.", 110 useName = "target", 111 minOccurs = 1, 112 maxOccurs = -1, 113 groupAs = @GroupAs(name = "targets", inJson = JsonGroupAsBehavior.LIST) 114 ) 115 private List<MappingItem> _targets; 116 117 @BoundAssembly( 118 formalName = "Relationship Qualifier", 119 description = "Describes requirements, incompatibilities and gaps that are identified between a target and source in a mapping item.", 120 useName = "qualifier", 121 maxOccurs = -1, 122 groupAs = @GroupAs(name = "qualifiers", inJson = JsonGroupAsBehavior.LIST) 123 ) 124 private List<QualifierItem> _qualifiers; 125 126 @BoundField( 127 formalName = "Confidence Score", 128 description = "This records either a string category or a decimal value from 0-1 representing a percentage. Both of these values describe an estimation of the author's confidence that this mapping is correct and accurate.", 129 useName = "confidence-score" 130 ) 131 private ConfidenceScore _confidenceScore; 132 133 @BoundField( 134 formalName = "Coverage", 135 description = "A decimal value from 0-1, representing the percentage coverage of the targets by the sources.", 136 useName = "coverage" 137 ) 138 private Coverage _coverage; 139 140 @BoundAssembly( 141 formalName = "Property", 142 description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.", 143 useName = "prop", 144 maxOccurs = -1, 145 groupAs = @GroupAs(name = "props", inJson = JsonGroupAsBehavior.LIST) 146 ) 147 private List<Property> _props; 148 149 @BoundAssembly( 150 formalName = "Link", 151 description = "A reference to a local or remote resource, that has a specific relation to the containing object.", 152 useName = "link", 153 maxOccurs = -1, 154 groupAs = @GroupAs(name = "links", inJson = JsonGroupAsBehavior.LIST) 155 ) 156 private List<Link> _links; 157 158 @BoundField( 159 formalName = "Remarks", 160 description = "Additional commentary about the containing object.", 161 useName = "remarks", 162 typeAdapter = MarkupMultilineAdapter.class 163 ) 164 private MarkupMultiline _remarks; 165 166 public MappingEntry() { 167 this(null); 168 } 169 170 public MappingEntry(IMetaschemaData data) { 171 this.__metaschemaData = data; 172 } 173 174 @Override 175 public IMetaschemaData getMetaschemaData() { 176 return __metaschemaData; 177 } 178 179 public UUID getUuid() { 180 return _uuid; 181 } 182 183 public void setUuid(UUID value) { 184 _uuid = value; 185 } 186 187 public URI getNs() { 188 return _ns; 189 } 190 191 public void setNs(URI value) { 192 _ns = value; 193 } 194 195 public String getMatchingRationale() { 196 return _matchingRationale; 197 } 198 199 public void setMatchingRationale(String value) { 200 _matchingRationale = value; 201 } 202 203 public String getRelationship() { 204 return _relationship; 205 } 206 207 public void setRelationship(String value) { 208 _relationship = value; 209 } 210 211 public List<MappingItem> getSources() { 212 return _sources; 213 } 214 215 public void setSources(List<MappingItem> value) { 216 _sources = value; 217 } 218 219 /** 220 * Add a new {@link MappingItem} item to the underlying collection. 221 * @param item the item to add 222 * @return {@code true} 223 */ 224 public boolean addSource(MappingItem item) { 225 MappingItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 226 if (_sources == null) { 227 _sources = new LinkedList<>(); 228 } 229 return _sources.add(value); 230 } 231 232 /** 233 * Remove the first matching {@link MappingItem} item from the underlying collection. 234 * @param item the item to remove 235 * @return {@code true} if the item was removed or {@code false} otherwise 236 */ 237 public boolean removeSource(MappingItem item) { 238 MappingItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 239 return _sources != null && _sources.remove(value); 240 } 241 242 public List<MappingItem> getTargets() { 243 return _targets; 244 } 245 246 public void setTargets(List<MappingItem> value) { 247 _targets = value; 248 } 249 250 /** 251 * Add a new {@link MappingItem} item to the underlying collection. 252 * @param item the item to add 253 * @return {@code true} 254 */ 255 public boolean addTarget(MappingItem item) { 256 MappingItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 257 if (_targets == null) { 258 _targets = new LinkedList<>(); 259 } 260 return _targets.add(value); 261 } 262 263 /** 264 * Remove the first matching {@link MappingItem} item from the underlying collection. 265 * @param item the item to remove 266 * @return {@code true} if the item was removed or {@code false} otherwise 267 */ 268 public boolean removeTarget(MappingItem item) { 269 MappingItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 270 return _targets != null && _targets.remove(value); 271 } 272 273 public List<QualifierItem> getQualifiers() { 274 return _qualifiers; 275 } 276 277 public void setQualifiers(List<QualifierItem> value) { 278 _qualifiers = value; 279 } 280 281 /** 282 * Add a new {@link QualifierItem} item to the underlying collection. 283 * @param item the item to add 284 * @return {@code true} 285 */ 286 public boolean addQualifier(QualifierItem item) { 287 QualifierItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 288 if (_qualifiers == null) { 289 _qualifiers = new LinkedList<>(); 290 } 291 return _qualifiers.add(value); 292 } 293 294 /** 295 * Remove the first matching {@link QualifierItem} item from the underlying collection. 296 * @param item the item to remove 297 * @return {@code true} if the item was removed or {@code false} otherwise 298 */ 299 public boolean removeQualifier(QualifierItem item) { 300 QualifierItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 301 return _qualifiers != null && _qualifiers.remove(value); 302 } 303 304 public ConfidenceScore getConfidenceScore() { 305 return _confidenceScore; 306 } 307 308 public void setConfidenceScore(ConfidenceScore value) { 309 _confidenceScore = value; 310 } 311 312 public Coverage getCoverage() { 313 return _coverage; 314 } 315 316 public void setCoverage(Coverage value) { 317 _coverage = value; 318 } 319 320 public List<Property> getProps() { 321 return _props; 322 } 323 324 public void setProps(List<Property> value) { 325 _props = value; 326 } 327 328 /** 329 * Add a new {@link Property} item to the underlying collection. 330 * @param item the item to add 331 * @return {@code true} 332 */ 333 public boolean addProp(Property item) { 334 Property value = ObjectUtils.requireNonNull(item,"item cannot be null"); 335 if (_props == null) { 336 _props = new LinkedList<>(); 337 } 338 return _props.add(value); 339 } 340 341 /** 342 * Remove the first matching {@link Property} item from the underlying collection. 343 * @param item the item to remove 344 * @return {@code true} if the item was removed or {@code false} otherwise 345 */ 346 public boolean removeProp(Property item) { 347 Property value = ObjectUtils.requireNonNull(item,"item cannot be null"); 348 return _props != null && _props.remove(value); 349 } 350 351 public List<Link> getLinks() { 352 return _links; 353 } 354 355 public void setLinks(List<Link> value) { 356 _links = value; 357 } 358 359 /** 360 * Add a new {@link Link} item to the underlying collection. 361 * @param item the item to add 362 * @return {@code true} 363 */ 364 public boolean addLink(Link item) { 365 Link value = ObjectUtils.requireNonNull(item,"item cannot be null"); 366 if (_links == null) { 367 _links = new LinkedList<>(); 368 } 369 return _links.add(value); 370 } 371 372 /** 373 * Remove the first matching {@link Link} item from the underlying collection. 374 * @param item the item to remove 375 * @return {@code true} if the item was removed or {@code false} otherwise 376 */ 377 public boolean removeLink(Link item) { 378 Link value = ObjectUtils.requireNonNull(item,"item cannot be null"); 379 return _links != null && _links.remove(value); 380 } 381 382 public MarkupMultiline getRemarks() { 383 return _remarks; 384 } 385 386 public void setRemarks(MarkupMultiline value) { 387 _remarks = value; 388 } 389 390 @Override 391 public String toString() { 392 return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString(); 393 } 394}