Skip to content

Commit

Permalink
Restoring deprecated datatypes per usnistgov#195
Browse files Browse the repository at this point in the history
  • Loading branch information
wendellpiez authored and david-waltermire committed Jul 14, 2022
1 parent dbe71cd commit 81cc41e
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 85 deletions.
12 changes: 6 additions & 6 deletions toolchains/xslt-M4/schema-gen/make-metaschema-xsd.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@

<!-- these old names are permitted for now, while only deprecated -->
<!--../../../schema/xml/metaschema.xsd line 1052 inside /*/xs:simpleType[@name='SimpleDatatypesType']> -->
<type as-type="base64Binary">Base64Datatype</type>
<type as-type="dateTime">DateTimeDatatype</type>
<type as-type="dateTime-with-timezone">DateTimeWithTimezoneDatatype</type>
<type as-type="email">EmailAddressDatatype</type>
<type as-type="nonNegativeInteger">NonNegativeIntegerDatatype</type>
<type as-type="positiveInteger">PositiveIntegerDatatype</type>
<type prefer="base64" as-type="base64Binary">Base64Datatype</type>
<type prefer="date-time" as-type="dateTime">DateTimeDatatype</type>
<type prefer="date-time-with-timezone" as-type="dateTime-with-timezone">DateTimeWithTimezoneDatatype</type>
<type prefer="email-address" as-type="email">EmailAddressDatatype</type>
<type prefer="non-negative-integer" as-type="nonNegativeInteger">NonNegativeIntegerDatatype</type>
<type prefer="positive-integer" as-type="positiveInteger">PositiveIntegerDatatype</type>
</xsl:variable>
<xsl:variable name="prose-xsd-definitions" select="$prose-modules/document(string(.))/*/*"/>

Expand Down
27 changes: 24 additions & 3 deletions toolchains/xslt-M4/validate/metaschema-composition-check.sch
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

<xsl:import href="metaschema-validation-support.xsl"/>

<xsl:import href="oscal-datatypes-check.xsl"/>
<!--<xsl:import href="oscal-datatypes-check.xsl"/>-->


<!--<xsl:import href="oscal-datatypes-check.xsl"/>-->
<xsl:import href="oscal-datatypes-check.xsl"/>

<xsl:param name="global-context" select="/"/>

Expand Down Expand Up @@ -133,8 +133,27 @@
</sch:pattern>


<sch:pattern id="atomic_datatypes">
<sch:let name="more-types" value="'markup-line','markup-multiline'"/>
<sch:rule context="m:field | m:define-field | m:flag | m:define-flag">
<sch:let name="given-type" value="(@as-type,'string')[1]"/>
<sch:let name="bound-type" value="$type-map[@as-type = $given-type]"/>
<sch:assert test="($given-type = $more-types) or exists($bound-type)">type <sch:value-of select="@as-type"/> is unknown.</sch:assert>
<sch:report sqf:fix="updateDatatype" id="warn-if-datatype-name-is-deprecated" role="warning"
test="matches($bound-type/@prefer,'\S')">Type name '<sch:value-of select="$given-type" />' is deprecated: '<sch:value-of select="$bound-type/@prefer"/>' is preferred</sch:report>

<sqf:fix id="updateDatatype">
<sqf:description>
<sqf:title>Update the datatype to '<sch:value-of select="$bound-type/@prefer"/>'</sqf:title>
</sqf:description>
<sqf:replace match="@as-type" node-type="attribute" target="as-type">
<sch:value-of select="$bound-type/@prefer"/>
</sqf:replace>
</sqf:fix>
</sch:rule>
</sch:pattern>

<sch:pattern id="flags_and_fields_and_datatypes">

<!-- flag references and inline definitions -->
<sch:rule context="m:flag | m:define-field/m:define-flag | m:define-assembly/m:define-flag">
<sch:assert id="json-value-key-flag-is-required"
Expand All @@ -151,6 +170,8 @@
<sch:assert id="permit-a-single-unwrapped-markupmultiline" test="empty($as-composed) or not($as-composed/@in-xml='UNWRAPPED') or not($as-composed/@as-type='markup-multiline') or not(preceding-sibling::*[$as-composed/@in-xml='UNWRAPPED']/@as-type='markup-multiline')">Only one field may be marked as 'markup-multiline' (without xml wrapping) within a model.</sch:assert>
<sch:report id="forbid-multiple-unwrapped-fields" test="($as-composed/@in-xml='UNWRAPPED') and (@max-occurs!='1')">An 'unwrapped' field must have a max occurrence of 1</sch:report>
<sch:assert id="forbid-unwrapped-xml-except-markupmultiline" test="$as-composed/key('composed-definition-by-key-name',nm:composed-definition-identifier(.),$composed-metaschema)/@as-type='markup-multiline' or not(@in-xml='UNWRAPPED')">Only 'markup-multiline' fields may be unwrapped in XML. SEEING '<sch:value-of select="nm:composed-definition-identifier(.)"/>'</sch:assert>


</sch:rule>

<sch:rule context="m:define-field">
Expand Down
188 changes: 126 additions & 62 deletions toolchains/xslt-M4/validate/oscal-datatypes-check.xsl
Original file line number Diff line number Diff line change
@@ -1,121 +1,185 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:stylesheet xmlns:m="http://csrc.nist.gov/ns/oscal/metaschema/1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:m="http://csrc.nist.gov/ns/oscal/metaschema/1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://csrc.nist.gov/ns/oscal/metaschema/1.0"
version="3.0">
<xsl:variable name="type-map" as="element()*">
<type as-type="base64">Base64Datatype</type>
<type as-type="boolean">BooleanDatatype</type>
<type as-type="date">DateDatatype</type>
<type as-type="date-time">DateTimeDatatype</type>
<type as-type="date-time-with-timezone">DateTimeWithTimezoneDatatype</type>
<type as-type="date-with-timezone">DateWithTimezoneDatatype</type>
<type as-type="day-time-duration">DayTimeDurationDatatype</type>
<type as-type="decimal">DecimalDatatype</type>
<type as-type="email-address">EmailAddressDatatype</type>
<type as-type="hostname">HostnameDatatype</type>
<type as-type="integer">IntegerDatatype</type>
<type as-type="ip-v4-address">IPV4AddressDatatype</type>
<type as-type="ip-v6-address">IPV6AddressDatatype</type>
<type as-type="non-negative-integer">NonNegativeIntegerDatatype</type>
<type as-type="positive-integer">PositiveIntegerDatatype</type>
<type as-type="string">StringDatatype</type>
<type as-type="token">TokenDatatype</type>
<type as-type="uri">URIDatatype</type>
<type as-type="uri-reference">URIReferenceDatatype</type>
<type as-type="uuid">UUIDDatatype</type>
<type prefer="base64" as-type="base64Binary">Base64Datatype</type>
<type prefer="date-time" as-type="dateTime">DateTimeDatatype</type>
<type prefer="date-time-with-timezone" as-type="dateTime-with-timezone">DateTimeWithTimezoneDatatype</type>
<type prefer="email-address" as-type="email">EmailAddressDatatype</type>
<type prefer="non-negative-integer" as-type="nonNegativeInteger">NonNegativeIntegerDatatype</type>
<type prefer="positive-integer" as-type="positiveInteger">PositiveIntegerDatatype</type>
</xsl:variable>
<xsl:function name="m:datatype-validate" as="xs:boolean">
<xsl:param name="value" as="item()"/>
<xsl:param name="nominal-type" as="item()?"/>
<xsl:variable name="test-type" as="xs:string">
<xsl:choose>
<xsl:when test="empty($nominal-type)">string</xsl:when>
<xsl:when test="$nominal-type = ('IDREFS', 'NMTOKENS')">string</xsl:when>
<xsl:when test="$nominal-type = ('ID', 'IDREF')">NCName</xsl:when>
<xsl:otherwise expand-text="yes">{ $nominal-type }</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="assigned-type" select="$type-map[@as-type=$nominal-type]"/>
<xsl:variable name="proxy" as="element()">
<xsl:element namespace="http://csrc.nist.gov/ns/oscal/metaschema/1.0"
name="{$test-type}"
name="{($assigned-type,'StringDatatype')[1]}"
expand-text="true">{$value}</xsl:element>
</xsl:variable>
<xsl:apply-templates select="$proxy" mode="m:validate-type"/>
</xsl:function>
<xsl:template match="m:boolean" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:boolean"/>
</xsl:template>
<xsl:template match="m:base64Binary" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:base64Binary"/>
</xsl:template>
<xsl:template match="m:string" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:string"/>
<xsl:template match="*" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select="true()"/>
</xsl:template>
<xsl:template match="m:NCName" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:NCName"/>
<xsl:template match="m:Base64Datatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^\S(.*\S)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:base64Binary) and $extra"/>
</xsl:template>
<xsl:template match="m:NMTOKENS" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:NMTOKENS"/>
<xsl:template match="m:BooleanDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^\S(.*\S)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:boolean) and $extra"/>
</xsl:template>
<xsl:template match="m:decimal" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:decimal"/>
<xsl:template match="m:DateDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^(((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30)))(Z|[+-][0-9]{2}:[0-9]{2})?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:date) and $extra"/>
</xsl:template>
<xsl:template match="m:integer" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:integer"/>
<xsl:template match="m:DateWithTimezoneDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^(((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30)))(Z|[+-][0-9]{2}:[0-9]{2})$')"/>
</xsl:variable>
<xsl:sequence select="m:datatype-validate(.,'DateDatatype') and $extra"/>
</xsl:template>
<xsl:template match="m:nonNegativeInteger" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:nonNegativeInteger"/>
<xsl:template match="m:DateTimeDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^(((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30)))T((2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?)(Z|[+-][0-9]{2}:[0-9]{2})?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:dateTime) and $extra"/>
</xsl:template>
<xsl:template match="m:positiveInteger" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:positiveInteger"/>
<xsl:template match="m:DateTimeWithTimezoneDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^(((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)|(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))|(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))|(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30)))T((2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?)(Z|[+-][0-9]{2}:[0-9]{2})$')"/>
</xsl:variable>
<xsl:sequence select="m:datatype-validate(.,'DateTimeDatatype') and $extra"/>
</xsl:template>
<xsl:template match="m:ID" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:ID"/>
<xsl:template match="m:DayTimeDurationDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^[-+]?P([-+]?[0-9]+D)?(T([-+]?[0-9]+H)?([-+]?[0-9]+M)?([-+]?[0-9]+([.,][0-9]{0,9})?S)?)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:duration) and $extra"/>
</xsl:template>
<xsl:template match="m:IDREF" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:IDREF"/>
<xsl:template match="m:DecimalDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^\S(.*\S)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:decimal) and $extra"/>
</xsl:template>
<xsl:template match="m:IDREFS" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:IDREFS"/>
<xsl:template match="m:EmailAddressDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^\S.*@.*\S$')"/>
</xsl:variable>
<xsl:sequence select="m:datatype-validate(.,'StringDatatype') and $extra"/>
</xsl:template>
<xsl:template match="m:date" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:date"/>
<xsl:template match="m:HostnameDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra" select="true()"/>
<xsl:sequence select="m:datatype-validate(.,'StringDatatype') and $extra"/>
</xsl:template>
<xsl:template match="m:dateTime" mode="m:validate-type" as="xs:boolean">
<xsl:sequence select=". castable as xs:dateTime"/>
<xsl:template match="m:IntegerDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^\S(.*\S)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:integer) and $extra"/>
</xsl:template>
<xsl:template match="m:ip-v4-address" mode="m:validate-type" as="xs:boolean">
<xsl:template match="m:IPV4AddressDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]).){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:string) and $extra"/>
<xsl:sequence select="m:datatype-validate(.,'StringDatatype') and $extra"/>
</xsl:template>
<xsl:template match="m:ip-v6-address" mode="m:validate-type" as="xs:boolean">
<xsl:template match="m:IPV6AddressDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|[fF][eE]80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::([fF]{4}(:0{1,4}){0,1}:){0,1}((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]).){3,3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]).){3,3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9]))$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:string) and $extra"/>
</xsl:template>
<xsl:template match="m:dateTime-with-timezone"
<xsl:template match="m:NonNegativeIntegerDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^.+T.+(Z|[+-].+)$')"/>
<xsl:sequence select="matches(.,'^\S(.*\S)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:dateTime) and $extra"/>
<xsl:sequence select="(. castable as xs:nonNegativeInteger) and $extra"/>
</xsl:template>
<xsl:template match="m:date-with-timezone" mode="m:validate-type" as="xs:boolean">
<xsl:template match="m:PositiveIntegerDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^.+[:Z].*$')"/>
<xsl:sequence select="matches(.,'^\S(.*\S)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:date) and $extra"/>
<xsl:sequence select="(. castable as xs:positiveInteger) and $extra"/>
</xsl:template>
<xsl:template match="m:email" mode="m:validate-type" as="xs:boolean">
<xsl:template match="m:StringDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^.+@.+$')"/>
<xsl:sequence select="matches(.,'^\S(.*\S)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:string) and $extra"/>
</xsl:template>
<xsl:template match="m:hostname" mode="m:validate-type" as="xs:boolean">
<xsl:template match="m:TokenDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^.+$')"/>
<xsl:sequence select="matches(.,'^(\p{L}|_)(\p{L}|\p{N}|[.\-_])*$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:string) and $extra"/>
<xsl:sequence select="m:datatype-validate(.,'StringDatatype') and $extra"/>
</xsl:template>
<xsl:template match="m:uri" mode="m:validate-type" as="xs:boolean">
<xsl:template match="m:URIDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^\p{L}[\p{L}\d+\-\.]*:.+$')"/>
<xsl:sequence select="matches(.,'^[a-zA-Z][a-zA-Z0-9+\-.]+:.*\S$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:anyURI) and $extra"/>
</xsl:template>
<xsl:template match="m:uri-reference" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra"/>
<xsl:template match="m:URIReferenceDatatype"
mode="m:validate-type"
as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^\S(.*\S)?$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:anyURI) and $extra"/>
</xsl:template>
<xsl:template match="m:uuid" mode="m:validate-type" as="xs:boolean">
<xsl:template match="m:UUIDDatatype" mode="m:validate-type" as="xs:boolean">
<xsl:variable name="extra">
<xsl:sequence select="matches(.,'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$')"/>
<xsl:sequence select="matches(.,'^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[45][0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$')"/>
</xsl:variable>
<xsl:sequence select="(. castable as xs:string) and $extra"/>
<xsl:sequence select="m:datatype-validate(.,'StringDatatype') and $extra"/>
</xsl:template>
</xsl:stylesheet>
Loading

0 comments on commit 81cc41e

Please sign in to comment.