001package gov.nist.secauto.oscal.lib.model; 002 003import gov.nist.secauto.metaschema.core.datatype.adapter.StringAdapter; 004import gov.nist.secauto.metaschema.core.datatype.adapter.TokenAdapter; 005import gov.nist.secauto.metaschema.core.datatype.adapter.UriAdapter; 006import gov.nist.secauto.metaschema.core.datatype.adapter.UriReferenceAdapter; 007import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; 008import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLineAdapter; 009import gov.nist.secauto.metaschema.core.model.IBoundObject; 010import gov.nist.secauto.metaschema.core.model.IMetaschemaData; 011import gov.nist.secauto.metaschema.core.model.constraint.IConstraint; 012import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValue; 013import gov.nist.secauto.metaschema.databind.model.annotations.AllowedValues; 014import gov.nist.secauto.metaschema.databind.model.annotations.BoundField; 015import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag; 016import gov.nist.secauto.metaschema.databind.model.annotations.Expect; 017import gov.nist.secauto.metaschema.databind.model.annotations.IndexHasKey; 018import gov.nist.secauto.metaschema.databind.model.annotations.KeyField; 019import gov.nist.secauto.metaschema.databind.model.annotations.Matches; 020import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly; 021import gov.nist.secauto.metaschema.databind.model.annotations.ValueConstraints; 022import gov.nist.secauto.oscal.lib.model.metadata.AbstractLink; 023import java.lang.Override; 024import java.lang.String; 025import java.net.URI; 026import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 027import org.apache.commons.lang3.builder.ToStringStyle; 028 029/** 030 * A reference to a local or remote resource, that has a specific relation to the containing object. 031 */ 032@MetaschemaAssembly( 033 formalName = "Link", 034 description = "A reference to a local or remote resource, that has a specific relation to the containing object.", 035 name = "link", 036 moduleClass = OscalMetadataModule.class, 037 remarks = "To provide a cryptographic hash for a remote target resource, a local reference to a back matter `resource` is needed. The resource allows one or more hash values to be provided using the `rlink/hash` object.\n" 038 + "\n" 039 + "The OSCAL `link` is a roughly based on the HTML [link element](https://www.w3.org/TR/html401/struct/links.html#edef-LINK).", 040 valueConstraints = @ValueConstraints(indexHasKey = @IndexHasKey(level = IConstraint.Level.ERROR, target = ".[@rel=('reference') and starts-with(@href,'#')]", indexName = "index-back-matter-resource", keyFields = @KeyField(target = "@href", pattern = "#(.*)")), matches = {@Matches(level = IConstraint.Level.ERROR, target = ".[@rel=('reference') and starts-with(@href,'#')]/@href", typeAdapter = UriReferenceAdapter.class), @Matches(level = IConstraint.Level.ERROR, target = ".[@rel=('reference') and not(starts-with(@href,'#'))]/@href", typeAdapter = UriAdapter.class), @Matches(level = IConstraint.Level.ERROR, target = "@resource-fragment", pattern = "(?:[0-9a-zA-Z-._~/?!$&'()*+,;=:@]|%[0-9A-F][0-9A-F])+", remarks = "This pattern is based on the fragment Augmented Backus-Naur form (ABNF) syntax provided in \\[RFC3986 section 3.5\\](https://www.rfc-editor.org/rfc/rfc3986#section-3.5). Uppercase alpha hex digits are required, which is the preferred normalized form defined in RFC3986.")}, expect = @Expect(description = "A local reference SHOULD NOT have a media-type.", level = IConstraint.Level.ERROR, target = ".[starts-with(@href,'#')]", test = "not(exists(@media-type))", remarks = "Since both `link` and `back-matter/resource` both allow specification of a `media-type`, the `media-type` on `link` may conflict with the any `media-type` entries on a resource's `rlink` or `base64` objects. This constraint prevents this from occurring.")) 041) 042public class Link extends AbstractLink implements IBoundObject { 043 private final IMetaschemaData __metaschemaData; 044 045 /** 046 * "A resolvable URL reference to a resource." 047 */ 048 @BoundFlag( 049 formalName = "Hypertext Reference", 050 description = "A resolvable URL reference to a resource.", 051 name = "href", 052 required = true, 053 typeAdapter = UriReferenceAdapter.class, 054 remarks = "This value may be one of:\n" 055 + "\n" 056 + "1. an [absolute URI](https://pages.nist.gov/OSCAL/concepts/uri-use/#absolute-uri) that points to a network resolvable resource,\n" 057 + "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" 058 + "3. a bare URI fragment (i.e., \\`#uuid\\`) pointing to an OSCAL object by the objects identifier (e.g., id, uuid) 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)). The specific object type will differ based on the link relationship type." 059 ) 060 private URI _href; 061 062 /** 063 * "Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose." 064 */ 065 @BoundFlag( 066 formalName = "Link Relation Type", 067 description = "Describes the type of relationship provided by the link's hypertext reference. This can be an indicator of the link's purpose.", 068 name = "rel", 069 typeAdapter = TokenAdapter.class, 070 valueConstraints = @ValueConstraints(allowedValues = @AllowedValues(level = IConstraint.Level.ERROR, allowOthers = true, values = @AllowedValue(value = "reference", description = "A generalized reference to a network resource (relative or absolute) or to a `back-matter` resource by UUID expressed as a bare URI fragment."))) 071 ) 072 private String _rel; 073 074 /** 075 * "A label that indicates the nature of a resource, as a data serialization or format." 076 */ 077 @BoundFlag( 078 formalName = "Link Media Type", 079 description = "A label that indicates the nature of a resource, as a data serialization or format.", 080 name = "media-type", 081 typeAdapter = StringAdapter.class, 082 remarks = "The `media-type` provides a hint about the content model of the referenced resource. A valid entry from the [IANA Media Types registry](https://www.iana.org/assignments/media-types/media-types.xhtml) SHOULD be used." 083 ) 084 private String _mediaType; 085 086 /** 087 * "In case where the <code>href</code> points to a <code>back-matter/resource</code>, this value will indicate the URI <a href=\"https://www.rfc-editor.org/rfc/rfc3986#section-3.5\">fragment</a> to append to any <code>rlink</code> associated with the resource. This value MUST be <a href=\"https://www.rfc-editor.org/rfc/rfc3986#section-2.1\">URI encoded</a>." 088 */ 089 @BoundFlag( 090 formalName = "Resource Fragment", 091 description = "In case where the `href` points to a `back-matter/resource`, this value will indicate the URI [fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) to append to any `rlink` associated with the resource. This value MUST be [URI encoded](https://www.rfc-editor.org/rfc/rfc3986#section-2.1).", 092 name = "resource-fragment", 093 typeAdapter = StringAdapter.class 094 ) 095 private String _resourceFragment; 096 097 @BoundField( 098 formalName = "Link Text", 099 description = "A textual label to associate with the link, which may be used for presentation in a tool.", 100 useName = "text", 101 typeAdapter = MarkupLineAdapter.class 102 ) 103 private MarkupLine _text; 104 105 public Link() { 106 this(null); 107 } 108 109 public Link(IMetaschemaData data) { 110 this.__metaschemaData = data; 111 } 112 113 @Override 114 public IMetaschemaData getMetaschemaData() { 115 return __metaschemaData; 116 } 117 118 public URI getHref() { 119 return _href; 120 } 121 122 public void setHref(URI value) { 123 _href = value; 124 } 125 126 public String getRel() { 127 return _rel; 128 } 129 130 public void setRel(String value) { 131 _rel = value; 132 } 133 134 public String getMediaType() { 135 return _mediaType; 136 } 137 138 public void setMediaType(String value) { 139 _mediaType = value; 140 } 141 142 public String getResourceFragment() { 143 return _resourceFragment; 144 } 145 146 public void setResourceFragment(String value) { 147 _resourceFragment = value; 148 } 149 150 public MarkupLine getText() { 151 return _text; 152 } 153 154 public void setText(MarkupLine value) { 155 _text = value; 156 } 157 158 @Override 159 public String toString() { 160 return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString(); 161 } 162}