001// Generated from: ../../../../../../../../oscal/src/metaschema/oscal_mapping-common_metaschema.xml 002// Do not edit - changes will be lost when regenerated. 003package dev.metaschema.oscal.lib.model; 004 005import dev.metaschema.core.datatype.adapter.StringAdapter; 006import dev.metaschema.core.datatype.adapter.TokenAdapter; 007import dev.metaschema.core.datatype.adapter.UriAdapter; 008import dev.metaschema.core.datatype.adapter.UuidAdapter; 009import dev.metaschema.core.datatype.markup.MarkupMultiline; 010import dev.metaschema.core.datatype.markup.MarkupMultilineAdapter; 011import dev.metaschema.core.model.IBoundObject; 012import dev.metaschema.core.model.IMetaschemaData; 013import dev.metaschema.core.model.JsonGroupAsBehavior; 014import dev.metaschema.core.model.constraint.IConstraint; 015import dev.metaschema.core.util.ObjectUtils; 016import dev.metaschema.databind.model.annotations.AllowedValue; 017import dev.metaschema.databind.model.annotations.AllowedValues; 018import dev.metaschema.databind.model.annotations.BoundAssembly; 019import dev.metaschema.databind.model.annotations.BoundField; 020import dev.metaschema.databind.model.annotations.BoundFlag; 021import dev.metaschema.databind.model.annotations.GroupAs; 022import dev.metaschema.databind.model.annotations.MetaschemaAssembly; 023import dev.metaschema.databind.model.annotations.ValueConstraints; 024import edu.umd.cs.findbugs.annotations.NonNull; 025import edu.umd.cs.findbugs.annotations.Nullable; 026import java.net.URI; 027import java.util.LinkedList; 028import java.util.List; 029import java.util.UUID; 030import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 031import org.apache.commons.lang3.builder.ToStringStyle; 032 033/** 034 * A relationship-based mapping between a source and target set consisting of members (i.e., controls, control statements) from the respective source and target. 035 */ 036@MetaschemaAssembly( 037 formalName = "Mapping Entry", 038 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.", 039 name = "map", 040 moduleClass = OscalMappingCommonModule.class 041) 042public class MappingEntry implements IBoundObject { 043 private final IMetaschemaData __metaschemaData; 044 045 /** 046 * The unique identifier for the mapping entry. 047 */ 048 @BoundFlag( 049 formalName = "Mapping Entry Identifier", 050 description = "The unique identifier for the mapping entry.", 051 name = "uuid", 052 required = true, 053 typeAdapter = UuidAdapter.class 054 ) 055 private UUID _uuid; 056 057 /** 058 * A namespace qualifying the relationship's value. This allows different organizations to associate distinct semantics for relationships with the same name. 059 */ 060 @BoundFlag( 061 formalName = "Relationship Value Namespace", 062 description = "A namespace qualifying the relationship's value. This allows different organizations to associate distinct semantics for relationships with the same name.", 063 name = "ns", 064 defaultValue = "http://csrc.nist.gov/ns/oscal", 065 typeAdapter = UriAdapter.class, 066 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" 067 + "\n" 068 + "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." 069 ) 070 private URI _ns; 071 072 /** 073 * 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. 074 */ 075 @BoundFlag( 076 formalName = "Matching", 077 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.", 078 name = "matching-rationale", 079 typeAdapter = StringAdapter.class, 080 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.")})) 081 ) 082 private String _matchingRationale; 083 084 /** 085 * 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 <code>matching-rationale</code> method globaly defined in the <code>provenance</code> unless overwritten locally in the <code> map</code>. The <code>relationship</code> type and the <code>matching-rationale</code> must be used together. However, more than one <code>matching-rationale</code> method may apply to a <code>source</code> and <code>target</code> pair. 086 */ 087 @BoundField( 088 formalName = "Mapping Entry Relationship", 089 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.", 090 useName = "relationship", 091 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" 092 + "\n" 093 + "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" 094 + "\n" 095 + "When establishing relationships, mapping SHOULD be done at the control statement level where possible. This approach allows for a more accurate relationship.", 096 minOccurs = 1, 097 typeAdapter = TokenAdapter.class, 098 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).")})) 099 ) 100 private String _relationship; 101 102 /** 103 * A specific edge within a source or target that is the subject of a mapping. 104 */ 105 @BoundAssembly( 106 formalName = "Mapping Entry Item (source or target)", 107 description = "A specific edge within a source or target that is the subject of a mapping.", 108 useName = "source", 109 minOccurs = 1, 110 maxOccurs = -1, 111 groupAs = @GroupAs(name = "sources", inJson = JsonGroupAsBehavior.LIST) 112 ) 113 private List<MappingItem> _sources; 114 115 /** 116 * A specific edge within a source or target that is the subject of a mapping. 117 */ 118 @BoundAssembly( 119 formalName = "Mapping Entry Item (source or target)", 120 description = "A specific edge within a source or target that is the subject of a mapping.", 121 useName = "target", 122 minOccurs = 1, 123 maxOccurs = -1, 124 groupAs = @GroupAs(name = "targets", inJson = JsonGroupAsBehavior.LIST) 125 ) 126 private List<MappingItem> _targets; 127 128 /** 129 * Describes requirements, incompatibilities and gaps that are identified between a target and source in a mapping item. 130 */ 131 @BoundAssembly( 132 formalName = "Relationship Qualifier", 133 description = "Describes requirements, incompatibilities and gaps that are identified between a target and source in a mapping item.", 134 useName = "qualifier", 135 maxOccurs = -1, 136 groupAs = @GroupAs(name = "qualifiers", inJson = JsonGroupAsBehavior.LIST) 137 ) 138 private List<QualifierItem> _qualifiers; 139 140 /** 141 * 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. 142 */ 143 @BoundField( 144 formalName = "Confidence Score", 145 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.", 146 useName = "confidence-score" 147 ) 148 private ConfidenceScore _confidenceScore; 149 150 /** 151 * A decimal value from 0-1, representing the percentage coverage of the targets by the sources. 152 */ 153 @BoundField( 154 formalName = "Coverage", 155 description = "A decimal value from 0-1, representing the percentage coverage of the targets by the sources.", 156 useName = "coverage" 157 ) 158 private Coverage _coverage; 159 160 /** 161 * An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair. 162 */ 163 @BoundAssembly( 164 formalName = "Property", 165 description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.", 166 useName = "prop", 167 maxOccurs = -1, 168 groupAs = @GroupAs(name = "props", inJson = JsonGroupAsBehavior.LIST) 169 ) 170 private List<Property> _props; 171 172 /** 173 * A reference to a local or remote resource, that has a specific relation to the containing object. 174 */ 175 @BoundAssembly( 176 formalName = "Link", 177 description = "A reference to a local or remote resource, that has a specific relation to the containing object.", 178 useName = "link", 179 maxOccurs = -1, 180 groupAs = @GroupAs(name = "links", inJson = JsonGroupAsBehavior.LIST) 181 ) 182 private List<Link> _links; 183 184 /** 185 * Additional commentary about the containing object. 186 */ 187 @BoundField( 188 formalName = "Remarks", 189 description = "Additional commentary about the containing object.", 190 useName = "remarks", 191 typeAdapter = MarkupMultilineAdapter.class 192 ) 193 private MarkupMultiline _remarks; 194 195 /** 196 * Constructs a new {@code dev.metaschema.oscal.lib.model.MappingEntry} instance with no metadata. 197 */ 198 public MappingEntry() { 199 this(null); 200 } 201 202 /** 203 * Constructs a new {@code dev.metaschema.oscal.lib.model.MappingEntry} instance with the specified metadata. 204 * 205 * @param data 206 * the metaschema data, or {@code null} if none 207 */ 208 public MappingEntry(IMetaschemaData data) { 209 this.__metaschemaData = data; 210 } 211 212 @Override 213 public IMetaschemaData getMetaschemaData() { 214 return __metaschemaData; 215 } 216 217 /** 218 * Get the "{@literal Mapping Entry Identifier}". 219 * 220 * <p> 221 * The unique identifier for the mapping entry. 222 * 223 * @return the uuid value 224 */ 225 @NonNull 226 public UUID getUuid() { 227 return _uuid; 228 } 229 230 /** 231 * Set the "{@literal Mapping Entry Identifier}". 232 * 233 * <p> 234 * The unique identifier for the mapping entry. 235 * 236 * @param value 237 * the uuid value to set 238 */ 239 public void setUuid(@NonNull UUID value) { 240 _uuid = value; 241 } 242 243 /** 244 * Get the "{@literal Relationship Value Namespace}". 245 * 246 * <p> 247 * A namespace qualifying the relationship's value. This allows different organizations to associate distinct semantics for relationships with the same name. 248 * 249 * @return the ns value, or {@code null} if not set 250 */ 251 @Nullable 252 public URI getNs() { 253 return _ns; 254 } 255 256 /** 257 * Set the "{@literal Relationship Value Namespace}". 258 * 259 * <p> 260 * A namespace qualifying the relationship's value. This allows different organizations to associate distinct semantics for relationships with the same name. 261 * 262 * @param value 263 * the ns value to set, or {@code null} to clear 264 */ 265 public void setNs(@Nullable URI value) { 266 _ns = value; 267 } 268 269 /** 270 * Get the "{@literal Matching}". 271 * 272 * <p> 273 * 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. 274 * 275 * @return the matching-rationale value, or {@code null} if not set 276 */ 277 @Nullable 278 public String getMatchingRationale() { 279 return _matchingRationale; 280 } 281 282 /** 283 * Set the "{@literal Matching}". 284 * 285 * <p> 286 * 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. 287 * 288 * @param value 289 * the matching-rationale value to set, or {@code null} to clear 290 */ 291 public void setMatchingRationale(@Nullable String value) { 292 _matchingRationale = value; 293 } 294 295 /** 296 * Get the "{@literal Mapping Entry Relationship}". 297 * 298 * <p> 299 * 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 <code>matching-rationale</code> method globaly defined in the <code>provenance</code> unless overwritten locally in the <code> map</code>. The <code>relationship</code> type and the <code>matching-rationale</code> must be used together. However, more than one <code>matching-rationale</code> method may apply to a <code>source</code> and <code>target</code> pair. 300 * 301 * @return the relationship value 302 */ 303 @NonNull 304 public String getRelationship() { 305 return _relationship; 306 } 307 308 /** 309 * Set the "{@literal Mapping Entry Relationship}". 310 * 311 * <p> 312 * 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 <code>matching-rationale</code> method globaly defined in the <code>provenance</code> unless overwritten locally in the <code> map</code>. The <code>relationship</code> type and the <code>matching-rationale</code> must be used together. However, more than one <code>matching-rationale</code> method may apply to a <code>source</code> and <code>target</code> pair. 313 * 314 * @param value 315 * the relationship value to set 316 */ 317 public void setRelationship(@NonNull String value) { 318 _relationship = value; 319 } 320 321 /** 322 * Get the "{@literal Mapping Entry Item (source or target)}". 323 * 324 * <p> 325 * A specific edge within a source or target that is the subject of a mapping. 326 * 327 * @return the source value 328 */ 329 @NonNull 330 public List<MappingItem> getSources() { 331 if (_sources == null) { 332 _sources = new LinkedList<>(); 333 } 334 return ObjectUtils.notNull(_sources); 335 } 336 337 /** 338 * Set the "{@literal Mapping Entry Item (source or target)}". 339 * 340 * <p> 341 * A specific edge within a source or target that is the subject of a mapping. 342 * 343 * @param value 344 * the source value to set 345 */ 346 public void setSources(@NonNull List<MappingItem> value) { 347 _sources = value; 348 } 349 350 /** 351 * Add a new {@link MappingItem} item to the underlying collection. 352 * @param item the item to add 353 * @return {@code true} 354 */ 355 public boolean addSource(MappingItem item) { 356 MappingItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 357 if (_sources == null) { 358 _sources = new LinkedList<>(); 359 } 360 return _sources.add(value); 361 } 362 363 /** 364 * Remove the first matching {@link MappingItem} item from the underlying collection. 365 * @param item the item to remove 366 * @return {@code true} if the item was removed or {@code false} otherwise 367 */ 368 public boolean removeSource(MappingItem item) { 369 MappingItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 370 return _sources != null && _sources.remove(value); 371 } 372 373 /** 374 * Get the "{@literal Mapping Entry Item (source or target)}". 375 * 376 * <p> 377 * A specific edge within a source or target that is the subject of a mapping. 378 * 379 * @return the target value 380 */ 381 @NonNull 382 public List<MappingItem> getTargets() { 383 if (_targets == null) { 384 _targets = new LinkedList<>(); 385 } 386 return ObjectUtils.notNull(_targets); 387 } 388 389 /** 390 * Set the "{@literal Mapping Entry Item (source or target)}". 391 * 392 * <p> 393 * A specific edge within a source or target that is the subject of a mapping. 394 * 395 * @param value 396 * the target value to set 397 */ 398 public void setTargets(@NonNull List<MappingItem> value) { 399 _targets = value; 400 } 401 402 /** 403 * Add a new {@link MappingItem} item to the underlying collection. 404 * @param item the item to add 405 * @return {@code true} 406 */ 407 public boolean addTarget(MappingItem item) { 408 MappingItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 409 if (_targets == null) { 410 _targets = new LinkedList<>(); 411 } 412 return _targets.add(value); 413 } 414 415 /** 416 * Remove the first matching {@link MappingItem} item from the underlying collection. 417 * @param item the item to remove 418 * @return {@code true} if the item was removed or {@code false} otherwise 419 */ 420 public boolean removeTarget(MappingItem item) { 421 MappingItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 422 return _targets != null && _targets.remove(value); 423 } 424 425 /** 426 * Get the "{@literal Relationship Qualifier}". 427 * 428 * <p> 429 * Describes requirements, incompatibilities and gaps that are identified between a target and source in a mapping item. 430 * 431 * @return the qualifier value 432 */ 433 @NonNull 434 public List<QualifierItem> getQualifiers() { 435 if (_qualifiers == null) { 436 _qualifiers = new LinkedList<>(); 437 } 438 return ObjectUtils.notNull(_qualifiers); 439 } 440 441 /** 442 * Set the "{@literal Relationship Qualifier}". 443 * 444 * <p> 445 * Describes requirements, incompatibilities and gaps that are identified between a target and source in a mapping item. 446 * 447 * @param value 448 * the qualifier value to set 449 */ 450 public void setQualifiers(@NonNull List<QualifierItem> value) { 451 _qualifiers = value; 452 } 453 454 /** 455 * Add a new {@link QualifierItem} item to the underlying collection. 456 * @param item the item to add 457 * @return {@code true} 458 */ 459 public boolean addQualifier(QualifierItem item) { 460 QualifierItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 461 if (_qualifiers == null) { 462 _qualifiers = new LinkedList<>(); 463 } 464 return _qualifiers.add(value); 465 } 466 467 /** 468 * Remove the first matching {@link QualifierItem} item from the underlying collection. 469 * @param item the item to remove 470 * @return {@code true} if the item was removed or {@code false} otherwise 471 */ 472 public boolean removeQualifier(QualifierItem item) { 473 QualifierItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 474 return _qualifiers != null && _qualifiers.remove(value); 475 } 476 477 /** 478 * Get the "{@literal Confidence Score}". 479 * 480 * <p> 481 * 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. 482 * 483 * @return the confidence-score value, or {@code null} if not set 484 */ 485 @Nullable 486 public ConfidenceScore getConfidenceScore() { 487 return _confidenceScore; 488 } 489 490 /** 491 * Set the "{@literal Confidence Score}". 492 * 493 * <p> 494 * 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. 495 * 496 * @param value 497 * the confidence-score value to set, or {@code null} to clear 498 */ 499 public void setConfidenceScore(@Nullable ConfidenceScore value) { 500 _confidenceScore = value; 501 } 502 503 /** 504 * Get the "{@literal Coverage}". 505 * 506 * <p> 507 * A decimal value from 0-1, representing the percentage coverage of the targets by the sources. 508 * 509 * @return the coverage value, or {@code null} if not set 510 */ 511 @Nullable 512 public Coverage getCoverage() { 513 return _coverage; 514 } 515 516 /** 517 * Set the "{@literal Coverage}". 518 * 519 * <p> 520 * A decimal value from 0-1, representing the percentage coverage of the targets by the sources. 521 * 522 * @param value 523 * the coverage value to set, or {@code null} to clear 524 */ 525 public void setCoverage(@Nullable Coverage value) { 526 _coverage = value; 527 } 528 529 /** 530 * Get the "{@literal Property}". 531 * 532 * <p> 533 * An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair. 534 * 535 * @return the prop value 536 */ 537 @NonNull 538 public List<Property> getProps() { 539 if (_props == null) { 540 _props = new LinkedList<>(); 541 } 542 return ObjectUtils.notNull(_props); 543 } 544 545 /** 546 * Set the "{@literal Property}". 547 * 548 * <p> 549 * An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair. 550 * 551 * @param value 552 * the prop value to set 553 */ 554 public void setProps(@NonNull List<Property> value) { 555 _props = value; 556 } 557 558 /** 559 * Add a new {@link Property} item to the underlying collection. 560 * @param item the item to add 561 * @return {@code true} 562 */ 563 public boolean addProp(Property item) { 564 Property value = ObjectUtils.requireNonNull(item,"item cannot be null"); 565 if (_props == null) { 566 _props = new LinkedList<>(); 567 } 568 return _props.add(value); 569 } 570 571 /** 572 * Remove the first matching {@link Property} item from the underlying collection. 573 * @param item the item to remove 574 * @return {@code true} if the item was removed or {@code false} otherwise 575 */ 576 public boolean removeProp(Property item) { 577 Property value = ObjectUtils.requireNonNull(item,"item cannot be null"); 578 return _props != null && _props.remove(value); 579 } 580 581 /** 582 * Get the "{@literal Link}". 583 * 584 * <p> 585 * A reference to a local or remote resource, that has a specific relation to the containing object. 586 * 587 * @return the link value 588 */ 589 @NonNull 590 public List<Link> getLinks() { 591 if (_links == null) { 592 _links = new LinkedList<>(); 593 } 594 return ObjectUtils.notNull(_links); 595 } 596 597 /** 598 * Set the "{@literal Link}". 599 * 600 * <p> 601 * A reference to a local or remote resource, that has a specific relation to the containing object. 602 * 603 * @param value 604 * the link value to set 605 */ 606 public void setLinks(@NonNull List<Link> value) { 607 _links = value; 608 } 609 610 /** 611 * Add a new {@link Link} item to the underlying collection. 612 * @param item the item to add 613 * @return {@code true} 614 */ 615 public boolean addLink(Link item) { 616 Link value = ObjectUtils.requireNonNull(item,"item cannot be null"); 617 if (_links == null) { 618 _links = new LinkedList<>(); 619 } 620 return _links.add(value); 621 } 622 623 /** 624 * Remove the first matching {@link Link} item from the underlying collection. 625 * @param item the item to remove 626 * @return {@code true} if the item was removed or {@code false} otherwise 627 */ 628 public boolean removeLink(Link item) { 629 Link value = ObjectUtils.requireNonNull(item,"item cannot be null"); 630 return _links != null && _links.remove(value); 631 } 632 633 /** 634 * Get the "{@literal Remarks}". 635 * 636 * <p> 637 * Additional commentary about the containing object. 638 * 639 * @return the remarks value, or {@code null} if not set 640 */ 641 @Nullable 642 public MarkupMultiline getRemarks() { 643 return _remarks; 644 } 645 646 /** 647 * Set the "{@literal Remarks}". 648 * 649 * <p> 650 * Additional commentary about the containing object. 651 * 652 * @param value 653 * the remarks value to set, or {@code null} to clear 654 */ 655 public void setRemarks(@Nullable MarkupMultiline value) { 656 _remarks = value; 657 } 658 659 @Override 660 public String toString() { 661 return ObjectUtils.notNull(new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString()); 662 } 663}