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