001package gov.nist.secauto.oscal.lib.model; 002 003import gov.nist.secauto.metaschema.core.datatype.adapter.DateTimeWithTZAdapter; 004import gov.nist.secauto.metaschema.core.datatype.adapter.TokenAdapter; 005import gov.nist.secauto.metaschema.core.datatype.adapter.UriReferenceAdapter; 006import gov.nist.secauto.metaschema.core.datatype.adapter.UuidAdapter; 007import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; 008import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLineAdapter; 009import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; 010import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultilineAdapter; 011import gov.nist.secauto.metaschema.core.model.IBoundObject; 012import gov.nist.secauto.metaschema.core.model.IMetaschemaData; 013import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior; 014import gov.nist.secauto.metaschema.core.model.constraint.IConstraint; 015import gov.nist.secauto.metaschema.core.util.ObjectUtils; 016import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValue; 017import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValues; 018import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly; 019import gov.nist.secauto.metaschema.databind.model.annotations.BoundField; 020import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag; 021import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs; 022import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly; 023import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints; 024import java.lang.Override; 025import java.lang.String; 026import java.net.URI; 027import java.time.ZonedDateTime; 028import java.util.LinkedList; 029import java.util.List; 030import java.util.UUID; 031import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 032import org.apache.commons.lang3.builder.ToStringStyle; 033 034/** 035 * Describes an individual observation. 036 */ 037@MetaschemaAssembly( 038 formalName = "Observation", 039 description = "Describes an individual observation.", 040 name = "observation", 041 moduleClass = OscalAssessmentCommonModule.class 042) 043public class Observation implements IBoundObject { 044 private final IMetaschemaData __metaschemaData; 045 046 /** 047 * "A <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#machine-oriented\">machine-oriented</a>, <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique\">globally unique</a> identifier with <em>cross-instance</em> scope that can be used to reference this observation elsewhere in <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#scope\">this or other OSCAL instances</a>. The locally defined <em>UUID</em> of the <code>observation</code> can be used to reference the data item locally or globally (e.g., in an imorted OSCAL instance). This UUID should be assigned <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency\">per-subject</a>, which means it should be consistently used to identify the same subject across revisions of the document." 048 */ 049 @BoundFlag( 050 formalName = "Observation Universally Unique Identifier", 051 description = "A [machine-oriented](https://pages.nist.gov/OSCAL/concepts/identifier-use/#machine-oriented), [globally unique](https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique) identifier with *cross-instance* scope that can be used to reference this observation elsewhere in [this or other OSCAL instances](https://pages.nist.gov/OSCAL/concepts/identifier-use/#scope). The locally defined *UUID* of the `observation` can be used to reference the data item locally or globally (e.g., in an imorted OSCAL instance). This UUID should be assigned [per-subject](https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency), which means it should be consistently used to identify the same subject across revisions of the document.", 052 name = "uuid", 053 required = true, 054 typeAdapter = UuidAdapter.class 055 ) 056 private UUID _uuid; 057 058 @BoundField( 059 formalName = "Observation Title", 060 description = "The title for this observation.", 061 useName = "title", 062 typeAdapter = MarkupLineAdapter.class 063 ) 064 private MarkupLine _title; 065 066 @BoundField( 067 formalName = "Observation Description", 068 description = "A human-readable description of this assessment observation.", 069 useName = "description", 070 minOccurs = 1, 071 typeAdapter = MarkupMultilineAdapter.class 072 ) 073 private MarkupMultiline _description; 074 075 @BoundAssembly( 076 formalName = "Property", 077 description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.", 078 useName = "prop", 079 maxOccurs = -1, 080 groupAs = @GroupAs(name = "props", inJson = JsonGroupAsBehavior.LIST) 081 ) 082 private List<Property> _props; 083 084 @BoundAssembly( 085 formalName = "Link", 086 description = "A reference to a local or remote resource, that has a specific relation to the containing object.", 087 useName = "link", 088 maxOccurs = -1, 089 groupAs = @GroupAs(name = "links", inJson = JsonGroupAsBehavior.LIST) 090 ) 091 private List<Link> _links; 092 093 @BoundField( 094 formalName = "Observation Method", 095 description = "Identifies how the observation was made.", 096 useName = "method", 097 minOccurs = 1, 098 maxOccurs = -1, 099 groupAs = @GroupAs(name = "methods", inJson = JsonGroupAsBehavior.LIST), 100 valueConstraints = @ValueConstraints(allowedValues = @AllowedValues(level = IConstraint.Level.ERROR, allowOthers = true, values = {@AllowedValue(value = "EXAMINE", description = "An inspection was performed."), @AllowedValue(value = "INTERVIEW", description = "An interview was performed."), @AllowedValue(value = "TEST", description = "A manual or automated test was performed."), @AllowedValue(value = "UNKNOWN", description = "This is only for use when converting historic content to OSCAL, where the conversion process cannot initially identify the appropriate method(s).")})) 101 ) 102 private List<String> _methods; 103 104 @BoundField( 105 formalName = "Observation Type", 106 description = "Identifies the nature of the observation. More than one may be used to further qualify and enable filtering.", 107 useName = "type", 108 maxOccurs = -1, 109 groupAs = @GroupAs(name = "types", inJson = JsonGroupAsBehavior.LIST), 110 typeAdapter = TokenAdapter.class, 111 valueConstraints = @ValueConstraints(allowedValues = @AllowedValues(level = IConstraint.Level.ERROR, allowOthers = true, values = {@AllowedValue(value = "ssp-statement-issue", description = "A difference between the SSP implementation statement, and actual implementation."), @AllowedValue(value = "control-objective", description = "An observation about the status of a the associated control objective."), @AllowedValue(value = "mitigation", description = "A mitigating factor was identified."), @AllowedValue(value = "finding", description = "An assessment finding. Used for observations made by tools, penetration testing, and other means."), @AllowedValue(value = "historic", description = "An observation from a past assessment, which was converted to OSCAL at a later date.")})) 112 ) 113 private List<String> _types; 114 115 @BoundAssembly( 116 formalName = "Origin", 117 description = "Identifies the source of the finding, such as a tool, interviewed person, or activity.", 118 useName = "origin", 119 remarks = "Used to identify the individual and/or tool that gathered the evidence resulting in the observation identification.", 120 maxOccurs = -1, 121 groupAs = @GroupAs(name = "origins", inJson = JsonGroupAsBehavior.LIST) 122 ) 123 private List<Origin> _origins; 124 125 @BoundAssembly( 126 formalName = "Identifies the Subject", 127 description = "A [human-oriented](https://pages.nist.gov/OSCAL/concepts/identifier-use/#human-oriented) identifier reference to a resource. Use type to indicate whether the identified resource is a component, inventory item, location, user, or something else.", 128 useName = "subject", 129 remarks = "Identifies who was interviewed, or what was tested or inspected.", 130 maxOccurs = -1, 131 groupAs = @GroupAs(name = "subjects", inJson = JsonGroupAsBehavior.LIST) 132 ) 133 private List<SubjectReference> _subjects; 134 135 @BoundAssembly( 136 formalName = "Relevant Evidence", 137 description = "Links this observation to relevant evidence.", 138 useName = "relevant-evidence", 139 maxOccurs = -1, 140 groupAs = @GroupAs(name = "relevant-evidence", inJson = JsonGroupAsBehavior.LIST) 141 ) 142 private List<RelevantEvidence> _relevantEvidence; 143 144 @BoundField( 145 formalName = "Collected Field", 146 description = "Date/time stamp identifying when the finding information was collected.", 147 useName = "collected", 148 minOccurs = 1, 149 typeAdapter = DateTimeWithTZAdapter.class 150 ) 151 private ZonedDateTime _collected; 152 153 @BoundField( 154 formalName = "Expires Field", 155 description = "Date/time identifying when the finding information is out-of-date and no longer valid. Typically used with continuous assessment scenarios.", 156 useName = "expires", 157 typeAdapter = DateTimeWithTZAdapter.class 158 ) 159 private ZonedDateTime _expires; 160 161 @BoundField( 162 formalName = "Remarks", 163 description = "Additional commentary about the containing object.", 164 useName = "remarks", 165 typeAdapter = MarkupMultilineAdapter.class 166 ) 167 private MarkupMultiline _remarks; 168 169 public Observation() { 170 this(null); 171 } 172 173 public Observation(IMetaschemaData data) { 174 this.__metaschemaData = data; 175 } 176 177 @Override 178 public IMetaschemaData getMetaschemaData() { 179 return __metaschemaData; 180 } 181 182 public UUID getUuid() { 183 return _uuid; 184 } 185 186 public void setUuid(UUID value) { 187 _uuid = value; 188 } 189 190 public MarkupLine getTitle() { 191 return _title; 192 } 193 194 public void setTitle(MarkupLine value) { 195 _title = value; 196 } 197 198 public MarkupMultiline getDescription() { 199 return _description; 200 } 201 202 public void setDescription(MarkupMultiline value) { 203 _description = value; 204 } 205 206 public List<Property> getProps() { 207 return _props; 208 } 209 210 public void setProps(List<Property> value) { 211 _props = value; 212 } 213 214 /** 215 * Add a new {@link Property} item to the underlying collection. 216 * @param item the item to add 217 * @return {@code true} 218 */ 219 public boolean addProp(Property item) { 220 Property value = ObjectUtils.requireNonNull(item,"item cannot be null"); 221 if (_props == null) { 222 _props = new LinkedList<>(); 223 } 224 return _props.add(value); 225 } 226 227 /** 228 * Remove the first matching {@link Property} item from the underlying collection. 229 * @param item the item to remove 230 * @return {@code true} if the item was removed or {@code false} otherwise 231 */ 232 public boolean removeProp(Property item) { 233 Property value = ObjectUtils.requireNonNull(item,"item cannot be null"); 234 return _props != null && _props.remove(value); 235 } 236 237 public List<Link> getLinks() { 238 return _links; 239 } 240 241 public void setLinks(List<Link> value) { 242 _links = value; 243 } 244 245 /** 246 * Add a new {@link Link} item to the underlying collection. 247 * @param item the item to add 248 * @return {@code true} 249 */ 250 public boolean addLink(Link item) { 251 Link value = ObjectUtils.requireNonNull(item,"item cannot be null"); 252 if (_links == null) { 253 _links = new LinkedList<>(); 254 } 255 return _links.add(value); 256 } 257 258 /** 259 * Remove the first matching {@link Link} item from the underlying collection. 260 * @param item the item to remove 261 * @return {@code true} if the item was removed or {@code false} otherwise 262 */ 263 public boolean removeLink(Link item) { 264 Link value = ObjectUtils.requireNonNull(item,"item cannot be null"); 265 return _links != null && _links.remove(value); 266 } 267 268 public List<String> getMethods() { 269 return _methods; 270 } 271 272 public void setMethods(List<String> value) { 273 _methods = value; 274 } 275 276 /** 277 * Add a new {@link String} item to the underlying collection. 278 * @param item the item to add 279 * @return {@code true} 280 */ 281 public boolean addMethod(String item) { 282 String value = ObjectUtils.requireNonNull(item,"item cannot be null"); 283 if (_methods == null) { 284 _methods = new LinkedList<>(); 285 } 286 return _methods.add(value); 287 } 288 289 /** 290 * Remove the first matching {@link String} item from the underlying collection. 291 * @param item the item to remove 292 * @return {@code true} if the item was removed or {@code false} otherwise 293 */ 294 public boolean removeMethod(String item) { 295 String value = ObjectUtils.requireNonNull(item,"item cannot be null"); 296 return _methods != null && _methods.remove(value); 297 } 298 299 public List<String> getTypes() { 300 return _types; 301 } 302 303 public void setTypes(List<String> value) { 304 _types = value; 305 } 306 307 /** 308 * Add a new {@link String} item to the underlying collection. 309 * @param item the item to add 310 * @return {@code true} 311 */ 312 public boolean addType(String item) { 313 String value = ObjectUtils.requireNonNull(item,"item cannot be null"); 314 if (_types == null) { 315 _types = new LinkedList<>(); 316 } 317 return _types.add(value); 318 } 319 320 /** 321 * Remove the first matching {@link String} item from the underlying collection. 322 * @param item the item to remove 323 * @return {@code true} if the item was removed or {@code false} otherwise 324 */ 325 public boolean removeType(String item) { 326 String value = ObjectUtils.requireNonNull(item,"item cannot be null"); 327 return _types != null && _types.remove(value); 328 } 329 330 public List<Origin> getOrigins() { 331 return _origins; 332 } 333 334 public void setOrigins(List<Origin> value) { 335 _origins = value; 336 } 337 338 /** 339 * Add a new {@link Origin} item to the underlying collection. 340 * @param item the item to add 341 * @return {@code true} 342 */ 343 public boolean addOrigin(Origin item) { 344 Origin value = ObjectUtils.requireNonNull(item,"item cannot be null"); 345 if (_origins == null) { 346 _origins = new LinkedList<>(); 347 } 348 return _origins.add(value); 349 } 350 351 /** 352 * Remove the first matching {@link Origin} item from the underlying collection. 353 * @param item the item to remove 354 * @return {@code true} if the item was removed or {@code false} otherwise 355 */ 356 public boolean removeOrigin(Origin item) { 357 Origin value = ObjectUtils.requireNonNull(item,"item cannot be null"); 358 return _origins != null && _origins.remove(value); 359 } 360 361 public List<SubjectReference> getSubjects() { 362 return _subjects; 363 } 364 365 public void setSubjects(List<SubjectReference> value) { 366 _subjects = value; 367 } 368 369 /** 370 * Add a new {@link SubjectReference} item to the underlying collection. 371 * @param item the item to add 372 * @return {@code true} 373 */ 374 public boolean addSubject(SubjectReference item) { 375 SubjectReference value = ObjectUtils.requireNonNull(item,"item cannot be null"); 376 if (_subjects == null) { 377 _subjects = new LinkedList<>(); 378 } 379 return _subjects.add(value); 380 } 381 382 /** 383 * Remove the first matching {@link SubjectReference} item from the underlying collection. 384 * @param item the item to remove 385 * @return {@code true} if the item was removed or {@code false} otherwise 386 */ 387 public boolean removeSubject(SubjectReference item) { 388 SubjectReference value = ObjectUtils.requireNonNull(item,"item cannot be null"); 389 return _subjects != null && _subjects.remove(value); 390 } 391 392 public List<RelevantEvidence> getRelevantEvidence() { 393 return _relevantEvidence; 394 } 395 396 public void setRelevantEvidence(List<RelevantEvidence> value) { 397 _relevantEvidence = value; 398 } 399 400 /** 401 * Add a new {@link RelevantEvidence} item to the underlying collection. 402 * @param item the item to add 403 * @return {@code true} 404 */ 405 public boolean addRelevantEvidence(RelevantEvidence item) { 406 RelevantEvidence value = ObjectUtils.requireNonNull(item,"item cannot be null"); 407 if (_relevantEvidence == null) { 408 _relevantEvidence = new LinkedList<>(); 409 } 410 return _relevantEvidence.add(value); 411 } 412 413 /** 414 * Remove the first matching {@link RelevantEvidence} item from the underlying collection. 415 * @param item the item to remove 416 * @return {@code true} if the item was removed or {@code false} otherwise 417 */ 418 public boolean removeRelevantEvidence(RelevantEvidence item) { 419 RelevantEvidence value = ObjectUtils.requireNonNull(item,"item cannot be null"); 420 return _relevantEvidence != null && _relevantEvidence.remove(value); 421 } 422 423 public ZonedDateTime getCollected() { 424 return _collected; 425 } 426 427 public void setCollected(ZonedDateTime value) { 428 _collected = value; 429 } 430 431 public ZonedDateTime getExpires() { 432 return _expires; 433 } 434 435 public void setExpires(ZonedDateTime value) { 436 _expires = value; 437 } 438 439 public MarkupMultiline getRemarks() { 440 return _remarks; 441 } 442 443 public void setRemarks(MarkupMultiline value) { 444 _remarks = value; 445 } 446 447 @Override 448 public String toString() { 449 return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString(); 450 } 451 452 /** 453 * Links this observation to relevant evidence. 454 */ 455 @MetaschemaAssembly( 456 formalName = "Relevant Evidence", 457 description = "Links this observation to relevant evidence.", 458 name = "relevant-evidence", 459 moduleClass = OscalAssessmentCommonModule.class 460 ) 461 public static class RelevantEvidence implements IBoundObject { 462 private final IMetaschemaData __metaschemaData; 463 464 /** 465 * "A resolvable URL reference to relevant evidence." 466 */ 467 @BoundFlag( 468 formalName = "Relevant Evidence Reference", 469 description = "A resolvable URL reference to relevant evidence.", 470 name = "href", 471 typeAdapter = UriReferenceAdapter.class, 472 remarks = "This value may be one of:\n" 473 + "\n" 474 + "1. an [absolute URI](https://pages.nist.gov/OSCAL/concepts/uri-use/#absolute-uri) that points to a network resolvable resource,\n" 475 + "2. a [relative reference](https://pages.nist.gov/OSCAL/concepts/uri-use/#relative-reference) pointing to a network resolvable resource whose base URI is the URI of the containing document, or\n" 476 + "3. a bare URI fragment (i.e., \\`#uuid\\`) pointing to a `back-matter` resource in this or an imported document (see [linking to another OSCAL object](https://pages.nist.gov/OSCAL/concepts/uri-use/#linking-to-another-oscal-object))." 477 ) 478 private URI _href; 479 480 @BoundField( 481 formalName = "Relevant Evidence Description", 482 description = "A human-readable description of this evidence.", 483 useName = "description", 484 minOccurs = 1, 485 typeAdapter = MarkupMultilineAdapter.class 486 ) 487 private MarkupMultiline _description; 488 489 @BoundAssembly( 490 formalName = "Property", 491 description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.", 492 useName = "prop", 493 maxOccurs = -1, 494 groupAs = @GroupAs(name = "props", inJson = JsonGroupAsBehavior.LIST) 495 ) 496 private List<Property> _props; 497 498 @BoundAssembly( 499 formalName = "Link", 500 description = "A reference to a local or remote resource, that has a specific relation to the containing object.", 501 useName = "link", 502 maxOccurs = -1, 503 groupAs = @GroupAs(name = "links", inJson = JsonGroupAsBehavior.LIST) 504 ) 505 private List<Link> _links; 506 507 @BoundField( 508 formalName = "Remarks", 509 description = "Additional commentary about the containing object.", 510 useName = "remarks", 511 typeAdapter = MarkupMultilineAdapter.class 512 ) 513 private MarkupMultiline _remarks; 514 515 public RelevantEvidence() { 516 this(null); 517 } 518 519 public RelevantEvidence(IMetaschemaData data) { 520 this.__metaschemaData = data; 521 } 522 523 @Override 524 public IMetaschemaData getMetaschemaData() { 525 return __metaschemaData; 526 } 527 528 public URI getHref() { 529 return _href; 530 } 531 532 public void setHref(URI value) { 533 _href = value; 534 } 535 536 public MarkupMultiline getDescription() { 537 return _description; 538 } 539 540 public void setDescription(MarkupMultiline value) { 541 _description = value; 542 } 543 544 public List<Property> getProps() { 545 return _props; 546 } 547 548 public void setProps(List<Property> value) { 549 _props = value; 550 } 551 552 /** 553 * Add a new {@link Property} item to the underlying collection. 554 * @param item the item to add 555 * @return {@code true} 556 */ 557 public boolean addProp(Property item) { 558 Property value = ObjectUtils.requireNonNull(item,"item cannot be null"); 559 if (_props == null) { 560 _props = new LinkedList<>(); 561 } 562 return _props.add(value); 563 } 564 565 /** 566 * Remove the first matching {@link Property} item from the underlying collection. 567 * @param item the item to remove 568 * @return {@code true} if the item was removed or {@code false} otherwise 569 */ 570 public boolean removeProp(Property item) { 571 Property value = ObjectUtils.requireNonNull(item,"item cannot be null"); 572 return _props != null && _props.remove(value); 573 } 574 575 public List<Link> getLinks() { 576 return _links; 577 } 578 579 public void setLinks(List<Link> value) { 580 _links = value; 581 } 582 583 /** 584 * Add a new {@link Link} item to the underlying collection. 585 * @param item the item to add 586 * @return {@code true} 587 */ 588 public boolean addLink(Link item) { 589 Link value = ObjectUtils.requireNonNull(item,"item cannot be null"); 590 if (_links == null) { 591 _links = new LinkedList<>(); 592 } 593 return _links.add(value); 594 } 595 596 /** 597 * Remove the first matching {@link Link} item from the underlying collection. 598 * @param item the item to remove 599 * @return {@code true} if the item was removed or {@code false} otherwise 600 */ 601 public boolean removeLink(Link item) { 602 Link value = ObjectUtils.requireNonNull(item,"item cannot be null"); 603 return _links != null && _links.remove(value); 604 } 605 606 public MarkupMultiline getRemarks() { 607 return _remarks; 608 } 609 610 public void setRemarks(MarkupMultiline value) { 611 _remarks = value; 612 } 613 614 @Override 615 public String toString() { 616 return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString(); 617 } 618 } 619}