BackMatter.java

package gov.nist.secauto.oscal.lib.model;

import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValue;
import gov.nist.secauto.metaschema.binding.model.annotations.AllowedValues;
import gov.nist.secauto.metaschema.binding.model.annotations.AssemblyConstraints;
import gov.nist.secauto.metaschema.binding.model.annotations.BoundAssembly;
import gov.nist.secauto.metaschema.binding.model.annotations.BoundField;
import gov.nist.secauto.metaschema.binding.model.annotations.BoundFieldValue;
import gov.nist.secauto.metaschema.binding.model.annotations.BoundFlag;
import gov.nist.secauto.metaschema.binding.model.annotations.Expect;
import gov.nist.secauto.metaschema.binding.model.annotations.GroupAs;
import gov.nist.secauto.metaschema.binding.model.annotations.HasCardinality;
import gov.nist.secauto.metaschema.binding.model.annotations.Index;
import gov.nist.secauto.metaschema.binding.model.annotations.IsUnique;
import gov.nist.secauto.metaschema.binding.model.annotations.KeyField;
import gov.nist.secauto.metaschema.binding.model.annotations.Matches;
import gov.nist.secauto.metaschema.binding.model.annotations.MetaschemaAssembly;
import gov.nist.secauto.metaschema.binding.model.annotations.MetaschemaField;
import gov.nist.secauto.metaschema.binding.model.annotations.MetaschemaFieldValue;
import gov.nist.secauto.metaschema.binding.model.annotations.ValueConstraints;
import gov.nist.secauto.metaschema.model.common.JsonGroupAsBehavior;
import gov.nist.secauto.metaschema.model.common.constraint.IConstraint;
import gov.nist.secauto.metaschema.model.common.datatype.adapter.Base64Adapter;
import gov.nist.secauto.metaschema.model.common.datatype.adapter.DateTimeWithTZAdapter;
import gov.nist.secauto.metaschema.model.common.datatype.adapter.StringAdapter;
import gov.nist.secauto.metaschema.model.common.datatype.adapter.TokenAdapter;
import gov.nist.secauto.metaschema.model.common.datatype.adapter.UriReferenceAdapter;
import gov.nist.secauto.metaschema.model.common.datatype.adapter.UuidAdapter;
import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLine;
import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupLineAdapter;
import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultiline;
import gov.nist.secauto.metaschema.model.common.datatype.markup.MarkupMultilineAdapter;
import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
import gov.nist.secauto.oscal.lib.model.metadata.AbstractBackMatter;
import java.lang.Override;
import java.lang.String;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import org.apache.commons.lang3.builder.MultilineRecursiveToStringStyle;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

/**
 * A collection of resources that may be referenced from within the OSCAL document instance.
 */
@MetaschemaAssembly(
    formalName = "Back matter",
    description = "A collection of resources that may be referenced from within the OSCAL document instance.",
    name = "back-matter",
    metaschema = OscalMetadataMetaschema.class,
    remarks = "Provides a collection of identified `resource` objects that can be referenced by a `link` with a `rel` value of \"reference\" and an `href` value that is a fragment \"#\" followed by a reference to a reference's `uuid`. Other specialized link \"rel\" values also use this pattern when indicated in that context of use."
)
@AssemblyConstraints(
    index = @Index(level = IConstraint.Level.ERROR, target = "resource", name = "index-back-matter-resource", keyFields = @KeyField(target = "@uuid"))
)
public class BackMatter extends AbstractBackMatter {
  /**
   * "A resource associated with content in the containing document instance. A resource may be directly included in the document using base64 encoding or may point to one or more equivalent internet resources."
   */
  @BoundAssembly(
      formalName = "Resource",
      description = "A resource associated with content in the containing document instance. A resource may be directly included in the document using base64 encoding or may point to one or more equivalent internet resources.",
      useName = "resource",
      maxOccurs = -1,
      remarks = "A resource can be used in two ways. 1) it may point to an specific retrievable network resource using a `rlink`, or 2) it may be included as an attachment using a `base64`. A resource may contain multiple `rlink` and `base64` entries that represent alternative download locations (rlink) and attachments (base64) for the same resource.\n"
              + "\n"
              + "Both rlink and base64 allow for a `media-type` to be specified, which is used to distinguish between different representations of the same resource (e.g., Microsoft Word, PDF). When multiple `rlink` and `base64` items are included for a given resource, all items must contain equivalent information. This allows the document consumer to choose a preferred item to process based on a the selected item's `media-type`. This is extremely important when the items represent OSCAL content that is represented in alternate formats (i.e., XML, JSON, YAML), allowing the same OSCAL data to be processed from any of the available formats indicated by the items.\n"
              + "\n"
              + "When a resource includes a citation, then the `title` and `citation` properties must both be included."
  )
  @GroupAs(
      name = "resources",
      inJson = JsonGroupAsBehavior.LIST
  )
  private List<Resource> _resources;

  public BackMatter() {
  }

  public List<Resource> getResources() {
    return _resources;
  }

  public void setResources(List<Resource> value) {
    _resources = value;
  }

  /**
   * Add a new {@link Resource} item to the underlying collection.
   * @param item the item to add
   * @return {@code true}
   */
  public boolean addResource(Resource item) {
    Resource value = ObjectUtils.requireNonNull(item,"item cannot be null");
    if (_resources == null) {
      _resources = new LinkedList<>();
    }
    return _resources.add(value);
  }

  /**
   * Remove the first matching {@link Resource} item from the underlying collection.
   * @param item the item to remove
   * @return {@code true} if the item was removed or {@code false} otherwise
   */
  public boolean removeResource(Resource item) {
    Resource value = ObjectUtils.requireNonNull(item,"item cannot be null");
    return _resources == null ? false : _resources.remove(value);
  }

  @Override
  public String toString() {
    return new ReflectionToStringBuilder(this, MultilineRecursiveToStringStyle.MULTI_LINE_STYLE).toString();
  }

  /**
   * A resource associated with content in the containing document instance. A resource may be directly included in the document using base64 encoding or may point to one or more equivalent internet resources.
   */
  @MetaschemaAssembly(
      formalName = "Resource",
      description = "A resource associated with content in the containing document instance. A resource may be directly included in the document using base64 encoding or may point to one or more equivalent internet resources.",
      name = "resource",
      metaschema = OscalMetadataMetaschema.class,
      remarks = "A resource can be used in two ways. 1) it may point to an specific retrievable network resource using a `rlink`, or 2) it may be included as an attachment using a `base64`. A resource may contain multiple `rlink` and `base64` entries that represent alternative download locations (rlink) and attachments (base64) for the same resource.\n"
              + "\n"
              + "Both rlink and base64 allow for a `media-type` to be specified, which is used to distinguish between different representations of the same resource (e.g., Microsoft Word, PDF). When multiple `rlink` and `base64` items are included for a given resource, all items must contain equivalent information. This allows the document consumer to choose a preferred item to process based on a the selected item's `media-type`. This is extremely important when the items represent OSCAL content that is represented in alternate formats (i.e., XML, JSON, YAML), allowing the same OSCAL data to be processed from any of the available formats indicated by the items.\n"
              + "\n"
              + "When a resource includes a citation, then the `title` and `citation` properties must both be included."
  )
  @ValueConstraints(
      allowedValues = {
          @AllowedValues(level = IConstraint.Level.ERROR, target = "prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal')]/@name", values = {@AllowedValue(value = "type", description = "Identifies the type of resource represented. The most specific appropriate type value SHOULD be used."), @AllowedValue(value = "version", description = "For resources representing a published document, this represents the version number of that document."), @AllowedValue(value = "published", description = "For resources representing a published document, this represents the publication date of that document.")}),
          @AllowedValues(level = IConstraint.Level.ERROR, target = "prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name='type']/@value", values = {@AllowedValue(value = "logo", description = "Indicates the resource is an organization's logo."), @AllowedValue(value = "image", description = "Indicates the resource represents an image."), @AllowedValue(value = "screen-shot", description = "Indicates the resource represents an image of screen content."), @AllowedValue(value = "law", description = "Indicates the resource represents an applicable law."), @AllowedValue(value = "regulation", description = "Indicates the resource represents an applicable regulation."), @AllowedValue(value = "standard", description = "Indicates the resource represents an applicable standard."), @AllowedValue(value = "external-guidance", description = "Indicates the resource represents applicable guidance."), @AllowedValue(value = "acronyms", description = "Indicates the resource provides a list of relevant acronyms."), @AllowedValue(value = "citation", description = "Indicates the resource cites relevant information."), @AllowedValue(value = "policy", description = "Indicates the resource is a policy."), @AllowedValue(value = "procedure", description = "Indicates the resource is a procedure."), @AllowedValue(value = "system-guide", description = "Indicates the resource is guidance document related to the subject system of an SSP."), @AllowedValue(value = "users-guide", description = "Indicates the resource is guidance document a user's guide or administrator's guide."), @AllowedValue(value = "administrators-guide", description = "Indicates the resource is guidance document a administrator's guide."), @AllowedValue(value = "rules-of-behavior", description = "Indicates the resource represents rules of behavior content."), @AllowedValue(value = "plan", description = "Indicates the resource represents a plan."), @AllowedValue(value = "artifact", description = "Indicates the resource represents an artifact, such as may be reviewed by an assessor."), @AllowedValue(value = "evidence", description = "Indicates the resource represents evidence, such as to support an assessment finding."), @AllowedValue(value = "tool-output", description = "Indicates the resource represents output from a tool."), @AllowedValue(value = "raw-data", description = "Indicates the resource represents machine data, which may require a tool or analysis for interpretation or presentation."), @AllowedValue(value = "interview-notes", description = "Indicates the resource represents notes from an interview, such as may be collected during an assessment."), @AllowedValue(value = "questionnaire", description = "Indicates the resource is a set of questions, possibly with responses."), @AllowedValue(value = "report", description = "Indicates the resource is a report."), @AllowedValue(value = "agreement", description = "Indicates the resource is a formal agreement between two or more parties.")})
      },
      matches = @Matches(level = IConstraint.Level.ERROR, target = "prop[has-oscal-namespace('http://csrc.nist.gov/ns/oscal') and @name='published']/@value", typeAdapter = DateTimeWithTZAdapter.class),
      expect = @Expect(level = IConstraint.Level.ERROR, target = ".[citation]", test = "title")
  )
  @AssemblyConstraints(
      isUnique = {
          @IsUnique(id = "unique-resource-rlink-href", level = IConstraint.Level.ERROR, target = "rlink", keyFields = {@KeyField(target = "@href"), @KeyField(target = "@media-type")}),
          @IsUnique(id = "unique-resource-base64-filename", level = IConstraint.Level.ERROR, target = "base64", keyFields = @KeyField(target = "@filename"))
      },
      hasCardinality = @HasCardinality(level = IConstraint.Level.WARNING, target = "rlink|base64", minOccurs = 1)
  )
  public static class Resource {
    @BoundFlag(
        formalName = "Resource Universally Unique Identifier",
        description = "A unique identifier for a resource.",
        useName = "uuid",
        required = true,
        typeAdapter = UuidAdapter.class
    )
    private UUID _uuid;

    /**
     * "An optional name given to the resource, which may be used by a tool for display and navigation."
     */
    @BoundField(
        formalName = "Resource Title",
        description = "An optional name given to the resource, which may be used by a tool for display and navigation.",
        useName = "title"
    )
    @BoundFieldValue(
        typeAdapter = MarkupLineAdapter.class
    )
    private MarkupLine _title;

    /**
     * "An optional short summary of the resource used to indicate the purpose of the resource."
     */
    @BoundField(
        formalName = "Resource Description",
        description = "An optional short summary of the resource used to indicate the purpose of the resource.",
        useName = "description"
    )
    @BoundFieldValue(
        typeAdapter = MarkupMultilineAdapter.class
    )
    private MarkupMultiline _description;

    @BoundAssembly(
        formalName = "Property",
        description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.",
        useName = "prop",
        maxOccurs = -1
    )
    @GroupAs(
        name = "props",
        inJson = JsonGroupAsBehavior.LIST
    )
    private List<Property> _props;

    @BoundField(
        formalName = "Document Identifier",
        description = "A document identifier qualified by an identifier `scheme`.",
        useName = "document-id",
        maxOccurs = -1
    )
    @GroupAs(
        name = "document-ids",
        inJson = JsonGroupAsBehavior.LIST
    )
    private List<DocumentId> _documentIds;

    /**
     * "An optional citation consisting of end note text using structured markup."
     */
    @BoundAssembly(
        formalName = "Citation",
        description = "An optional citation consisting of end note text using structured markup.",
        useName = "citation"
    )
    private Citation _citation;

    /**
     * "A URL-based pointer to an external resource with an optional hash for verification and change detection."
     */
    @BoundAssembly(
        formalName = "Resource link",
        description = "A URL-based pointer to an external resource with an optional hash for verification and change detection.",
        useName = "rlink",
        maxOccurs = -1,
        remarks = "Multiple `rlink` objects can be included for a resource. In such a case, all provided `rlink` items are intended to be equivalent in content, but may differ in structure or format.\n"
                + "\n"
                + "A `media-type` is used to identify the format of a given rlink, and can be used to differentiate items in a collection of rlinks. The `media-type` provides a hint to the OSCAL document consumer about the structure of the resource referenced by the `rlink`."
    )
    @GroupAs(
        name = "rlinks",
        inJson = JsonGroupAsBehavior.LIST
    )
    private List<Rlink> _rlinks;

    /**
     * "A resource encoded using the Base64 alphabet defined by <a href=\"https://www.rfc-editor.org/rfc/rfc2045.html\">RFC 2045</a>."
     */
    @BoundField(
        formalName = "Base64",
        description = "A resource encoded using the Base64 alphabet defined by [RFC 2045](https://www.rfc-editor.org/rfc/rfc2045.html).",
        useName = "base64"
    )
    private Base64 _base64;

    @BoundField(
        formalName = "Remarks",
        description = "Additional commentary about the containing object.",
        useName = "remarks"
    )
    @BoundFieldValue(
        typeAdapter = MarkupMultilineAdapter.class
    )
    private MarkupMultiline _remarks;

    public Resource() {
    }

    public UUID getUuid() {
      return _uuid;
    }

    public void setUuid(UUID value) {
      _uuid = value;
    }

    public MarkupLine getTitle() {
      return _title;
    }

    public void setTitle(MarkupLine value) {
      _title = value;
    }

    public MarkupMultiline getDescription() {
      return _description;
    }

    public void setDescription(MarkupMultiline value) {
      _description = value;
    }

    public List<Property> getProps() {
      return _props;
    }

    public void setProps(List<Property> value) {
      _props = value;
    }

    /**
     * Add a new {@link Property} item to the underlying collection.
     * @param item the item to add
     * @return {@code true}
     */
    public boolean addProp(Property item) {
      Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
      if (_props == null) {
        _props = new LinkedList<>();
      }
      return _props.add(value);
    }

    /**
     * Remove the first matching {@link Property} item from the underlying collection.
     * @param item the item to remove
     * @return {@code true} if the item was removed or {@code false} otherwise
     */
    public boolean removeProp(Property item) {
      Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
      return _props == null ? false : _props.remove(value);
    }

    public List<DocumentId> getDocumentIds() {
      return _documentIds;
    }

    public void setDocumentIds(List<DocumentId> value) {
      _documentIds = value;
    }

    /**
     * Add a new {@link DocumentId} item to the underlying collection.
     * @param item the item to add
     * @return {@code true}
     */
    public boolean addDocumentId(DocumentId item) {
      DocumentId value = ObjectUtils.requireNonNull(item,"item cannot be null");
      if (_documentIds == null) {
        _documentIds = new LinkedList<>();
      }
      return _documentIds.add(value);
    }

    /**
     * Remove the first matching {@link DocumentId} item from the underlying collection.
     * @param item the item to remove
     * @return {@code true} if the item was removed or {@code false} otherwise
     */
    public boolean removeDocumentId(DocumentId item) {
      DocumentId value = ObjectUtils.requireNonNull(item,"item cannot be null");
      return _documentIds == null ? false : _documentIds.remove(value);
    }

    public Citation getCitation() {
      return _citation;
    }

    public void setCitation(Citation value) {
      _citation = value;
    }

    public List<Rlink> getRlinks() {
      return _rlinks;
    }

    public void setRlinks(List<Rlink> value) {
      _rlinks = value;
    }

    /**
     * Add a new {@link Rlink} item to the underlying collection.
     * @param item the item to add
     * @return {@code true}
     */
    public boolean addRlink(Rlink item) {
      Rlink value = ObjectUtils.requireNonNull(item,"item cannot be null");
      if (_rlinks == null) {
        _rlinks = new LinkedList<>();
      }
      return _rlinks.add(value);
    }

    /**
     * Remove the first matching {@link Rlink} item from the underlying collection.
     * @param item the item to remove
     * @return {@code true} if the item was removed or {@code false} otherwise
     */
    public boolean removeRlink(Rlink item) {
      Rlink value = ObjectUtils.requireNonNull(item,"item cannot be null");
      return _rlinks == null ? false : _rlinks.remove(value);
    }

    public Base64 getBase64() {
      return _base64;
    }

    public void setBase64(Base64 value) {
      _base64 = value;
    }

    public MarkupMultiline getRemarks() {
      return _remarks;
    }

    public void setRemarks(MarkupMultiline value) {
      _remarks = value;
    }

    @Override
    public String toString() {
      return new ReflectionToStringBuilder(this, MultilineRecursiveToStringStyle.MULTI_LINE_STYLE).toString();
    }

    /**
     * An optional citation consisting of end note text using structured markup.
     */
    @MetaschemaAssembly(
        formalName = "Citation",
        description = "An optional citation consisting of end note text using structured markup.",
        name = "citation",
        metaschema = OscalMetadataMetaschema.class
    )
    public static class Citation {
      /**
       * "A line of citation text."
       */
      @BoundField(
          formalName = "Citation Text",
          description = "A line of citation text.",
          useName = "text",
          minOccurs = 1
      )
      @BoundFieldValue(
          typeAdapter = MarkupLineAdapter.class
      )
      private MarkupLine _text;

      @BoundAssembly(
          formalName = "Property",
          description = "An attribute, characteristic, or quality of the containing object expressed as a namespace qualified name/value pair.",
          useName = "prop",
          maxOccurs = -1
      )
      @GroupAs(
          name = "props",
          inJson = JsonGroupAsBehavior.LIST
      )
      private List<Property> _props;

      @BoundAssembly(
          formalName = "Link",
          description = "A reference to a local or remote resource, that has a specific relation to the containing object.",
          useName = "link",
          maxOccurs = -1
      )
      @GroupAs(
          name = "links",
          inJson = JsonGroupAsBehavior.LIST
      )
      private List<Link> _links;

      public Citation() {
      }

      public MarkupLine getText() {
        return _text;
      }

      public void setText(MarkupLine value) {
        _text = value;
      }

      public List<Property> getProps() {
        return _props;
      }

      public void setProps(List<Property> value) {
        _props = value;
      }

      /**
       * Add a new {@link Property} item to the underlying collection.
       * @param item the item to add
       * @return {@code true}
       */
      public boolean addProp(Property item) {
        Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
        if (_props == null) {
          _props = new LinkedList<>();
        }
        return _props.add(value);
      }

      /**
       * Remove the first matching {@link Property} item from the underlying collection.
       * @param item the item to remove
       * @return {@code true} if the item was removed or {@code false} otherwise
       */
      public boolean removeProp(Property item) {
        Property value = ObjectUtils.requireNonNull(item,"item cannot be null");
        return _props == null ? false : _props.remove(value);
      }

      public List<Link> getLinks() {
        return _links;
      }

      public void setLinks(List<Link> value) {
        _links = value;
      }

      /**
       * Add a new {@link Link} item to the underlying collection.
       * @param item the item to add
       * @return {@code true}
       */
      public boolean addLink(Link item) {
        Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
        if (_links == null) {
          _links = new LinkedList<>();
        }
        return _links.add(value);
      }

      /**
       * Remove the first matching {@link Link} item from the underlying collection.
       * @param item the item to remove
       * @return {@code true} if the item was removed or {@code false} otherwise
       */
      public boolean removeLink(Link item) {
        Link value = ObjectUtils.requireNonNull(item,"item cannot be null");
        return _links == null ? false : _links.remove(value);
      }

      @Override
      public String toString() {
        return new ReflectionToStringBuilder(this, MultilineRecursiveToStringStyle.MULTI_LINE_STYLE).toString();
      }
    }

    /**
     * A resource encoded using the Base64 alphabet defined by <a href="https://www.rfc-editor.org/rfc/rfc2045.html">RFC 2045</a>.
     */
    @MetaschemaField(
        formalName = "Base64",
        description = "A resource encoded using the Base64 alphabet defined by [RFC 2045](https://www.rfc-editor.org/rfc/rfc2045.html).",
        name = "base64",
        metaschema = OscalMetadataMetaschema.class,
        isCollapsible = false
    )
    public static class Base64 {
      @MetaschemaFieldValue(
          valueKeyName = "value",
          typeAdapter = Base64Adapter.class
      )
      private ByteBuffer _value;

      @BoundFlag(
          formalName = "File Name",
          description = "Name of the file before it was encoded as Base64 to be embedded in a `resource`. This is the name that will be assigned to the file when the file is decoded.",
          useName = "filename",
          typeAdapter = TokenAdapter.class
      )
      private String _filename;

      @BoundFlag(
          formalName = "Media Type",
          description = "A label that indicates the nature of a resource, as a data serialization or format.",
          useName = "media-type",
          typeAdapter = StringAdapter.class
      )
      private String _mediaType;

      public Base64() {
      }

      public ByteBuffer getValue() {
        return _value;
      }

      public void setValue(ByteBuffer value) {
        _value = value;
      }

      public String getFilename() {
        return _filename;
      }

      public void setFilename(String value) {
        _filename = value;
      }

      public String getMediaType() {
        return _mediaType;
      }

      public void setMediaType(String value) {
        _mediaType = value;
      }

      @Override
      public String toString() {
        return new ReflectionToStringBuilder(this, MultilineRecursiveToStringStyle.MULTI_LINE_STYLE).toString();
      }
    }

    /**
     * A URL-based pointer to an external resource with an optional hash for verification and change detection.
     */
    @MetaschemaAssembly(
        formalName = "Resource link",
        description = "A URL-based pointer to an external resource with an optional hash for verification and change detection.",
        name = "rlink",
        metaschema = OscalMetadataMetaschema.class,
        remarks = "Multiple `rlink` objects can be included for a resource. In such a case, all provided `rlink` items are intended to be equivalent in content, but may differ in structure or format.\n"
                + "\n"
                + "A `media-type` is used to identify the format of a given rlink, and can be used to differentiate items in a collection of rlinks. The `media-type` provides a hint to the OSCAL document consumer about the structure of the resource referenced by the `rlink`."
    )
    public static class Rlink {
      @BoundFlag(
          formalName = "Hypertext Reference",
          description = "A resolvable URL pointing to the referenced resource.",
          useName = "href",
          required = true,
          typeAdapter = UriReferenceAdapter.class,
          remarks = "This value may be either:\n"
                  + "\n"
                  + "1. an [absolute URI](https://pages.nist.gov/OSCAL/concepts/uri-use/#absolute-uri) that points to a network resolvable resource,\n"
                  + "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"
      )
      private URI _href;

      @BoundFlag(
          formalName = "Media Type",
          description = "A label that indicates the nature of a resource, as a data serialization or format.",
          useName = "media-type",
          typeAdapter = StringAdapter.class
      )
      private String _mediaType;

      /**
       * "A hash of the resource identified by <code>href</code>, which can be used to verify the resource was not changed since it was hashed."
       */
      @BoundField(
          formalName = "Hash",
          description = "A hash of the resource identified by `href`, which can be used to verify the resource was not changed since it was hashed.",
          useName = "hash",
          maxOccurs = -1,
          remarks = "The `hash` value can be used to confirm that the resource referenced by the `href` is the same resources that was hashed by retrieving the resource, calculating a hash, and comparing the result to this value."
      )
      @GroupAs(
          name = "hashes",
          inJson = JsonGroupAsBehavior.LIST
      )
      private List<Hash> _hashes;

      public Rlink() {
      }

      public URI getHref() {
        return _href;
      }

      public void setHref(URI value) {
        _href = value;
      }

      public String getMediaType() {
        return _mediaType;
      }

      public void setMediaType(String value) {
        _mediaType = value;
      }

      public List<Hash> getHashes() {
        return _hashes;
      }

      public void setHashes(List<Hash> value) {
        _hashes = value;
      }

      /**
       * Add a new {@link Hash} item to the underlying collection.
       * @param item the item to add
       * @return {@code true}
       */
      public boolean addHash(Hash item) {
        Hash value = ObjectUtils.requireNonNull(item,"item cannot be null");
        if (_hashes == null) {
          _hashes = new LinkedList<>();
        }
        return _hashes.add(value);
      }

      /**
       * Remove the first matching {@link Hash} item from the underlying collection.
       * @param item the item to remove
       * @return {@code true} if the item was removed or {@code false} otherwise
       */
      public boolean removeHash(Hash item) {
        Hash value = ObjectUtils.requireNonNull(item,"item cannot be null");
        return _hashes == null ? false : _hashes.remove(value);
      }

      @Override
      public String toString() {
        return new ReflectionToStringBuilder(this, MultilineRecursiveToStringStyle.MULTI_LINE_STYLE).toString();
      }
    }
  }
}