From 76d66b4adac23f3e3eb5d367ca5b61e36f6509e7 Mon Sep 17 00:00:00 2001 From: Stephen Richard Date: Wed, 7 Oct 2026 11:49:19 -0700 Subject: [PATCH] cdifTabularData: give the row and column counts a propertyID countRows and countColumns were the only two properties on this class with no namespace and no description -- bare `type: integer` among twenty-one prefixed siblings (cdi:headerRowCount, cdi:skipRows, cdi:tableDirection, cdif:hasPhysicalMapping and the rest). Nothing said what they meant or tied them to a vocabulary, and because the class is open, nothing would ever complain. They become schema:additionalProperty PropertyValue entries carrying a schema:propertyID that names the concept each one quantifies: countRows http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity countColumns http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity DDI DISCOVERY, not Codebook -- confirmed with the originator. The terms are read from the vocabulary rather than from a documentation link: DISCO declares "The namespace for all terms in this ontology is: http://rdf-vocabulary.ddialliance.org/discovery#", so the IRIs are `discovery#caseQuantity` / `#variableQuantity` and NOT the `discovery.html#dfn-disco-casequantity` anchors that were first proposed -- those are doc-page fragments, with a different path and https where DISCO declares http. Either form is a string that validates, so a doc anchor would have sat in schema:propertyID identifying a web page instead of a property, and nothing downstream would have surfaced it. The semantics line up: both DISCO properties are datatype properties with domain DataFile and LogicalDataSet, and this class describes a tabular data file. variableQuantity is the count of variables (columns), caseQuantity the number of cases (rows). The array follows the house pattern from cdifProvActivity -- items $ref a $defs entry that in turn $refs schemaorgProperties/additionalProperty -- rather than restating the PropertyValue shape here. 30 occurrences across 12 example and negative-test files are converted, in cdifTabularData, cdifComplete and DiscoveryDataDescription. Note this was NOT a breaking change: the class has no additionalProperties:false, so the old bare form still validated and the examples were updated to demonstrate the convention rather than to repair a failure. The large cdifManifest/resolvedSchema.json diff is this change, not unrelated drift -- swapping two scalars for a $ref inlines the whole additionalProperty definition (PropertyValue, DefinedTerm, propertyID_item) into the resolved output. Verified by regenerating against a clean HEAD: "0 updated, 68 already current", so nothing was stale beforehand. validate_examples 130 passed, 0 failed test_fail_cases 103 of 103 still fail for the reason they name Co-Authored-By: Claude Opus 5 --- .../cdifTabularDataSchema.json | 18 +- .../exampleCdifTabularData.json | 24 +- .../exampleCdifTabularDataComplete.json | 24 +- .../cdifTabularData/examples.yaml | 3 +- .../cdifTabularData/resolvedSchema.json | 373 ++++++---- .../cdifDataType/cdifTabularData/schema.yaml | 20 +- .../tests/commentPrefix-fail.json | 24 +- .../cdifTabularData/tests/delimiter-fail.json | 24 +- .../exampleCDIFDataDescription.json | 24 +- .../exampleCDIFDataDescription_long.json | 24 +- .../exampleCDIFDataDescription_wide.json | 24 +- .../tests/description-fail.json | 24 +- .../tests/name-fail.json | 24 +- .../cdifComplete/exampleCDIFcomplete.json | 48 +- .../cdifComplete/resolvedSchema.json | 11 +- .../cdifComplete/tests/description-fail.json | 48 +- .../cdifComplete/tests/name-fail.json | 48 +- .../cdifManifest/resolvedSchema.json | 657 ++++++------------ 18 files changed, 821 insertions(+), 621 deletions(-) diff --git a/_sources/cdifDataType/cdifTabularData/cdifTabularDataSchema.json b/_sources/cdifDataType/cdifTabularData/cdifTabularDataSchema.json index 65cb6c77d7..427b55da79 100644 --- a/_sources/cdifDataType/cdifTabularData/cdifTabularDataSchema.json +++ b/_sources/cdifDataType/cdifTabularData/cdifTabularDataSchema.json @@ -122,11 +122,12 @@ "$ref": "../../cdifDataType/cdifPhysicalMapping/cdifPhysicalMappingSchema.json" } }, - "countRows": { - "type": "integer" - }, - "countColumns": { - "type": "integer" + "schema:additionalProperty": { + "description": "Soft-typed extension properties. The row and column counts live here rather than as bare properties, so that each carries a schema:propertyID identifying the concept it quantifies - DDI Discovery caseQuantity for the row count and variableQuantity for the column count. As bare unprefixed `countRows`/`countColumns` they were the only two properties on this class with no namespace and no definition, so nothing said what they meant or tied them to a vocabulary.", + "type": "array", + "items": { + "$ref": "#/$defs/AdditionalProperty" + } } }, "oneOf": [ @@ -160,5 +161,10 @@ "required": [ "@type", "cdif:hasPhysicalMapping" - ] + ], + "$defs": { + "AdditionalProperty": { + "$ref": "../../schemaorgProperties/additionalProperty/additionalPropertySchema.json" + } + } } diff --git a/_sources/cdifDataType/cdifTabularData/exampleCdifTabularData.json b/_sources/cdifDataType/cdifTabularData/exampleCdifTabularData.json index 96fc284427..297850defa 100644 --- a/_sources/cdifDataType/cdifTabularData/exampleCdifTabularData.json +++ b/_sources/cdifDataType/cdifTabularData/exampleCdifTabularData.json @@ -16,8 +16,28 @@ "cdi:commentPrefix": "#", "cdi:skipBlankRows": false, "cdi:skipInitialSpace": true, - "countRows": 1500, - "countColumns": 5, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 1500 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 5 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/cdifDataType/cdifTabularData/exampleCdifTabularDataComplete.json b/_sources/cdifDataType/cdifTabularData/exampleCdifTabularDataComplete.json index f18b895f28..3d2d620b67 100644 --- a/_sources/cdifDataType/cdifTabularData/exampleCdifTabularDataComplete.json +++ b/_sources/cdifDataType/cdifTabularData/exampleCdifTabularDataComplete.json @@ -30,8 +30,28 @@ "cdi:tableDirection": "Ltr", "cdi:textDirection": "Inherit", "cdi:trim": "Both", - "countRows": 1500, - "countColumns": 3, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 1500 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 3 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/cdifDataType/cdifTabularData/examples.yaml b/_sources/cdifDataType/cdifTabularData/examples.yaml index fde1c71a30..374e685d81 100644 --- a/_sources/cdifDataType/cdifTabularData/examples.yaml +++ b/_sources/cdifDataType/cdifTabularData/examples.yaml @@ -13,7 +13,8 @@ Delimited tabular dataset exercising every CSVW dialect property (delimiter, quote/escape, header, lineTerminators, skipBlankRows/ skipColumns/skipRows, table/text direction, trim), plus arrayBase, - headerIsCaseSensitive, treatConsecutiveDelimitersAsOne, countRows/Cols, + headerIsCaseSensitive, treatConsecutiveDelimitersAsOne, the row and column + counts as DDI Discovery-identified schema:additionalProperty entries, and three physical-mapping entries. prefixes: cdi: http://ddialliance.org/Specification/DDI-CDI/1.0/RDF/ diff --git a/_sources/cdifDataType/cdifTabularData/resolvedSchema.json b/_sources/cdifDataType/cdifTabularData/resolvedSchema.json index a60175eb92..63f403d53d 100644 --- a/_sources/cdifDataType/cdifTabularData/resolvedSchema.json +++ b/_sources/cdifDataType/cdifTabularData/resolvedSchema.json @@ -171,147 +171,7 @@ } }, { - "description": "schema.org Defined Term schema.\n\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:DefinedTerm is represented by a single attribute of that class type.\nThe JSON Schema implementation permits the property value to be EITHER a\nplain string (interpreted as schema:name or schema:termCode in the default\nvocabulary) OR a full schema:DefinedTerm object (with explicit @type, name,\nidentifier, termCode, inDefinedTermSet). Consumers should accept either form.\n\nNote that this differs from the cdif Concept policy: a Concept (skos:Concept)\nin CDIF profiles MUST be a controlled-vocabulary entry (object form or\n@id-reference) — plain strings are not permitted for Concept-typed values\nbecause vocabulary identity cannot be recovered from an unscoped label.\n", - "type": "object", - "properties": { - "@type": { - "type": "array", - "items": { - "type": "string" - }, - "contains": { - "const": "schema:DefinedTerm" - }, - "minItems": 1 - }, - "schema:name": { - "type": "string", - "description": "text label for the term that is useful to human user" - }, - "schema:identifier": { - "anyOf": [ - { - "type": "string" - }, - { - "description": "Properties for a schema.org identifier (schema:PropertyValue pattern).\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:Identifier / schema:PropertyValue is represented by a single attribute\nof that class type. The JSON Schema implementation permits the property value\nto be EITHER a plain string (interpreted as the bare identifier value) OR a\nfull schema:PropertyValue object (with explicit @type, propertyID, value).\nConsumers should accept either form.\n", - "type": "object", - "properties": { - "@type": { - "type": "array", - "items": { - "type": "string" - }, - "contains": { - "const": "schema:PropertyValue" - }, - "minItems": 1 - }, - "schema:propertyID": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "@id" - ], - "properties": { - "@id": { - "type": "string" - } - } - } - ], - "description": "In this context for the schema:PropertyValue, this field is an identifier for the identifier schema, e.g. DOI, ARK. Get values from https://registry.identifiers.org/registry/ for interoperability. URI-shape values MUST be serialized as JSON-LD IRI references ({\"@id\":\"...\"}) so they participate in RDF entailment; free-label strings remain valid as strings." - }, - "schema:value": { - "type": "string", - "description": "the identifier string. E.g. 10.5066/F7VX0DMQ" - }, - "schema:url": { - "type": "string", - "format": "uri", - "description": "web-resolveable string for the identifier; host name part is location of a resolver that will return some representation for the given identifier value. E.g. https://doi.org/10.5066/F7VX0DMQ " - } - }, - "allOf": [ - { - "required": [ - "@type" - ] - }, - { - "anyOf": [ - { - "required": [ - "schema:value" - ] - }, - { - "required": [ - "schema:url" - ] - } - ] - } - ] - } - ] - }, - "schema:inDefinedTermSet": { - "description": "The controlled vocabulary responsible for this keyword, as EITHER a plain URI string identifying the vocabulary, OR an object reference ({\"@id\": \"\"}) to a vocabulary defined elsewhere in the document. Both forms are already in use across CDIF profiles and downstream ADA building blocks; permitting only the string form made the object form - the natural JSON-LD spelling of a reference - invalid, while this class's own union-type policy above explicitly anticipates both.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "required": [ - "@id" - ], - "additionalProperties": false, - "properties": { - "@id": { - "type": "string" - } - } - } - ] - }, - "schema:termCode": { - "type": "string", - "description": "A representative code for this keyword in the controlled vocabulary. Analogous to skos:Notation" - } - }, - "allOf": [ - { - "required": [ - "@type" - ] - }, - { - "anyOf": [ - { - "required": [ - "schema:name" - ] - }, - { - "required": [ - "schema:identifier" - ] - }, - { - "required": [ - "schema:termCode" - ] - } - ] - } - ] + "$ref": "#/$defs/DefinedTerm" }, { "$ref": "#/$defs/Concept" @@ -405,11 +265,89 @@ ] } }, - "countRows": { - "type": "integer" - }, - "countColumns": { - "type": "integer" + "schema:additionalProperty": { + "description": "Soft-typed extension properties. The row and column counts live here rather than as bare properties, so that each carries a schema:propertyID identifying the concept it quantifies - DDI Discovery caseQuantity for the row count and variableQuantity for the column count. As bare unprefixed `countRows`/`countColumns` they were the only two properties on this class with no namespace and no definition, so nothing said what they meant or tied them to a vocabulary.", + "type": "array", + "items": { + "type": "object", + "title": "additionalProperty PropertyValue", + "description": "PropertyValue values required to define a soft-typed property with a value. ", + "properties": { + "@type": { + "type": "array", + "items": { + "type": "string" + }, + "contains": { + "const": "schema:PropertyValue" + }, + "minItems": 1 + }, + "schema:propertyID": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "required": [ + "@id" + ], + "additionalProperties": false, + "properties": { + "@id": { + "type": "string" + } + } + }, + { + "$ref": "#/$defs/DefinedTerm" + } + ] + }, + "minItems": 1, + "description": "identifier or name for the property concept quantified by the values in this variable slot. Multiple values can specify the property at different levels of granularity." + }, + "schema:name": { + "type": "string" + }, + "schema:value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "object" + } + ] + }, + "schema:unitCode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/DefinedTerm" + } + ] + }, + "schema:unitText": { + "type": "string" + } + }, + "required": [ + "schema:name", + "schema:value" + ] + } } }, "oneOf": [ @@ -445,6 +383,149 @@ "cdif:hasPhysicalMapping" ], "$defs": { + "DefinedTerm": { + "description": "schema.org Defined Term schema.\n\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:DefinedTerm is represented by a single attribute of that class type.\nThe JSON Schema implementation permits the property value to be EITHER a\nplain string (interpreted as schema:name or schema:termCode in the default\nvocabulary) OR a full schema:DefinedTerm object (with explicit @type, name,\nidentifier, termCode, inDefinedTermSet). Consumers should accept either form.\n\nNote that this differs from the cdif Concept policy: a Concept (skos:Concept)\nin CDIF profiles MUST be a controlled-vocabulary entry (object form or\n@id-reference) — plain strings are not permitted for Concept-typed values\nbecause vocabulary identity cannot be recovered from an unscoped label.\n", + "type": "object", + "properties": { + "@type": { + "type": "array", + "items": { + "type": "string" + }, + "contains": { + "const": "schema:DefinedTerm" + }, + "minItems": 1 + }, + "schema:name": { + "type": "string", + "description": "text label for the term that is useful to human user" + }, + "schema:identifier": { + "anyOf": [ + { + "type": "string" + }, + { + "description": "Properties for a schema.org identifier (schema:PropertyValue pattern).\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:Identifier / schema:PropertyValue is represented by a single attribute\nof that class type. The JSON Schema implementation permits the property value\nto be EITHER a plain string (interpreted as the bare identifier value) OR a\nfull schema:PropertyValue object (with explicit @type, propertyID, value).\nConsumers should accept either form.\n", + "type": "object", + "properties": { + "@type": { + "type": "array", + "items": { + "type": "string" + }, + "contains": { + "const": "schema:PropertyValue" + }, + "minItems": 1 + }, + "schema:propertyID": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "@id" + ], + "properties": { + "@id": { + "type": "string" + } + } + } + ], + "description": "In this context for the schema:PropertyValue, this field is an identifier for the identifier schema, e.g. DOI, ARK. Get values from https://registry.identifiers.org/registry/ for interoperability. URI-shape values MUST be serialized as JSON-LD IRI references ({\"@id\":\"...\"}) so they participate in RDF entailment; free-label strings remain valid as strings." + }, + "schema:value": { + "type": "string", + "description": "the identifier string. E.g. 10.5066/F7VX0DMQ" + }, + "schema:url": { + "type": "string", + "format": "uri", + "description": "web-resolveable string for the identifier; host name part is location of a resolver that will return some representation for the given identifier value. E.g. https://doi.org/10.5066/F7VX0DMQ " + } + }, + "allOf": [ + { + "required": [ + "@type" + ] + }, + { + "anyOf": [ + { + "required": [ + "schema:value" + ] + }, + { + "required": [ + "schema:url" + ] + } + ] + } + ] + } + ] + }, + "schema:inDefinedTermSet": { + "description": "The controlled vocabulary responsible for this keyword, as EITHER a plain URI string identifying the vocabulary, OR an object reference ({\"@id\": \"\"}) to a vocabulary defined elsewhere in the document. Both forms are already in use across CDIF profiles and downstream ADA building blocks; permitting only the string form made the object form - the natural JSON-LD spelling of a reference - invalid, while this class's own union-type policy above explicitly anticipates both.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "required": [ + "@id" + ], + "additionalProperties": false, + "properties": { + "@id": { + "type": "string" + } + } + } + ] + }, + "schema:termCode": { + "type": "string", + "description": "A representative code for this keyword in the controlled vocabulary. Analogous to skos:Notation" + } + }, + "allOf": [ + { + "required": [ + "@type" + ] + }, + { + "anyOf": [ + { + "required": [ + "schema:name" + ] + }, + { + "required": [ + "schema:identifier" + ] + }, + { + "required": [ + "schema:termCode" + ] + } + ] + } + ] + }, "Concept": { "type": "object", "properties": { diff --git a/_sources/cdifDataType/cdifTabularData/schema.yaml b/_sources/cdifDataType/cdifTabularData/schema.yaml index 44256f4fd7..f5cf4d0814 100644 --- a/_sources/cdifDataType/cdifTabularData/schema.yaml +++ b/_sources/cdifDataType/cdifTabularData/schema.yaml @@ -100,10 +100,16 @@ properties: description: Links variables to their physical representation in this dataset. items: $ref: ../../cdifDataType/cdifPhysicalMapping/schema.yaml - countRows: - type: integer - countColumns: - type: integer + 'schema:additionalProperty': + description: Soft-typed extension properties. The row and column counts live here rather than + as bare properties, so that each carries a schema:propertyID identifying the concept it + quantifies - DDI Discovery caseQuantity for the row count and variableQuantity for the + column count. As bare unprefixed `countRows`/`countColumns` they were the only two + properties on this class with no namespace and no definition, so nothing said what they + meant or tied them to a vocabulary. + type: array + items: + $ref: '#/$defs/AdditionalProperty' oneOf: - properties: cdi:isDelimited: @@ -121,4 +127,8 @@ oneOf: - cdi:isFixedWidth required: - '@type' -- 'cdif:hasPhysicalMapping' \ No newline at end of file +- 'cdif:hasPhysicalMapping' + +$defs: + AdditionalProperty: + $ref: ../../schemaorgProperties/additionalProperty/schema.yaml diff --git a/_sources/cdifDataType/cdifTabularData/tests/commentPrefix-fail.json b/_sources/cdifDataType/cdifTabularData/tests/commentPrefix-fail.json index 53b51c77e8..17ef77a0b0 100644 --- a/_sources/cdifDataType/cdifTabularData/tests/commentPrefix-fail.json +++ b/_sources/cdifDataType/cdifTabularData/tests/commentPrefix-fail.json @@ -16,8 +16,28 @@ "cdi:commentPrefix": 42, "cdi:skipBlankRows": false, "cdi:skipInitialSpace": true, - "countRows": 1500, - "countColumns": 5, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 1500 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 5 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/cdifDataType/cdifTabularData/tests/delimiter-fail.json b/_sources/cdifDataType/cdifTabularData/tests/delimiter-fail.json index b6d85decad..7009112aed 100644 --- a/_sources/cdifDataType/cdifTabularData/tests/delimiter-fail.json +++ b/_sources/cdifDataType/cdifTabularData/tests/delimiter-fail.json @@ -16,8 +16,28 @@ "cdi:commentPrefix": "#", "cdi:skipBlankRows": false, "cdi:skipInitialSpace": true, - "countRows": 1500, - "countColumns": 5, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 1500 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 5 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription.json b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription.json index 54a5a88d01..11c01321e0 100644 --- a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription.json +++ b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription.json @@ -520,8 +520,28 @@ "cdi:skipRows": 0, "cdi:skipBlankRows": true, "cdi:quoteCharacter": "\"", - "countRows": 461, - "countColumns": 2, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 461 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 2 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription_long.json b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription_long.json index edeff463a6..b67daf73dd 100644 --- a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription_long.json +++ b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription_long.json @@ -88,8 +88,28 @@ "cdi:headerRowCount": 1, "cdi:quoteCharacter": "\"", "cdi:skipBlankRows": true, - "countRows": 576, - "countColumns": 5, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 576 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 5 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription_wide.json b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription_wide.json index 685a954f3c..1b03c1dcd2 100644 --- a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription_wide.json +++ b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/exampleCDIFDataDescription_wide.json @@ -83,8 +83,28 @@ "cdi:headerRowCount": 1, "cdi:quoteCharacter": "\"", "cdi:skipBlankRows": true, - "countRows": 144, - "countColumns": 6, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 144 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 6 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/tests/description-fail.json b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/tests/description-fail.json index a7d6a49c1f..b35fed80e4 100644 --- a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/tests/description-fail.json +++ b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/tests/description-fail.json @@ -520,8 +520,28 @@ "cdi:skipRows": 0, "cdi:skipBlankRows": true, "cdi:quoteCharacter": "\"", - "countRows": 461, - "countColumns": 2, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 461 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 2 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/tests/name-fail.json b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/tests/name-fail.json index f682e9e6f7..6d518a4c07 100644 --- a/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/tests/name-fail.json +++ b/_sources/profiles/cdifCompositeProfile/DiscoveryDataDescription/tests/name-fail.json @@ -520,8 +520,28 @@ "cdi:skipRows": 0, "cdi:skipBlankRows": true, "cdi:quoteCharacter": "\"", - "countRows": 461, - "countColumns": 2, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 461 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 2 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifCompositeProfile/cdifComplete/exampleCDIFcomplete.json b/_sources/profiles/cdifCompositeProfile/cdifComplete/exampleCDIFcomplete.json index 1d67f73110..4bb4acea93 100644 --- a/_sources/profiles/cdifCompositeProfile/cdifComplete/exampleCDIFcomplete.json +++ b/_sources/profiles/cdifCompositeProfile/cdifComplete/exampleCDIFcomplete.json @@ -404,8 +404,28 @@ "cdi:tableDirection": "Ltr", "cdi:textDirection": "Auto", "cdi:trim": "Both", - "countRows": 461, - "countColumns": 3, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 461 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 3 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, @@ -592,8 +612,28 @@ "cdi:delimiter": ",", "cdi:hasHeader": true, "cdi:headerRowCount": 1, - "countRows": 144, - "countColumns": 3, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 144 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 3 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifCompositeProfile/cdifComplete/resolvedSchema.json b/_sources/profiles/cdifCompositeProfile/cdifComplete/resolvedSchema.json index b27f4aacf2..11b373c0b3 100644 --- a/_sources/profiles/cdifCompositeProfile/cdifComplete/resolvedSchema.json +++ b/_sources/profiles/cdifCompositeProfile/cdifComplete/resolvedSchema.json @@ -1401,11 +1401,12 @@ "$ref": "#/$defs/CdifPhysicalMapping" } }, - "countRows": { - "type": "integer" - }, - "countColumns": { - "type": "integer" + "schema:additionalProperty": { + "description": "Soft-typed extension properties. The row and column counts live here rather than as bare properties, so that each carries a schema:propertyID identifying the concept it quantifies - DDI Discovery caseQuantity for the row count and variableQuantity for the column count. As bare unprefixed `countRows`/`countColumns` they were the only two properties on this class with no namespace and no definition, so nothing said what they meant or tied them to a vocabulary.", + "type": "array", + "items": { + "$ref": "#/$defs/AdditionalProperty" + } } }, "oneOf": [ diff --git a/_sources/profiles/cdifCompositeProfile/cdifComplete/tests/description-fail.json b/_sources/profiles/cdifCompositeProfile/cdifComplete/tests/description-fail.json index cd8de363d6..c2c742c90d 100644 --- a/_sources/profiles/cdifCompositeProfile/cdifComplete/tests/description-fail.json +++ b/_sources/profiles/cdifCompositeProfile/cdifComplete/tests/description-fail.json @@ -404,8 +404,28 @@ "cdi:tableDirection": "Ltr", "cdi:textDirection": "Auto", "cdi:trim": "Both", - "countRows": 461, - "countColumns": 3, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 461 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 3 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, @@ -560,8 +580,28 @@ "cdi:delimiter": ",", "cdi:hasHeader": true, "cdi:headerRowCount": 1, - "countRows": 144, - "countColumns": 3, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 144 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 3 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifCompositeProfile/cdifComplete/tests/name-fail.json b/_sources/profiles/cdifCompositeProfile/cdifComplete/tests/name-fail.json index f400e9957f..09243016de 100644 --- a/_sources/profiles/cdifCompositeProfile/cdifComplete/tests/name-fail.json +++ b/_sources/profiles/cdifCompositeProfile/cdifComplete/tests/name-fail.json @@ -404,8 +404,28 @@ "cdi:tableDirection": "Ltr", "cdi:textDirection": "Auto", "cdi:trim": "Both", - "countRows": 461, - "countColumns": 3, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 461 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 3 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, @@ -560,8 +580,28 @@ "cdi:delimiter": ",", "cdi:hasHeader": true, "cdi:headerRowCount": 1, - "countRows": 144, - "countColumns": 3, + "schema:additionalProperty": [ + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#caseQuantity" + ], + "schema:name": "countRows", + "schema:value": 144 + }, + { + "@type": [ + "schema:PropertyValue" + ], + "schema:propertyID": [ + "http://rdf-vocabulary.ddialliance.org/discovery#variableQuantity" + ], + "schema:name": "countColumns", + "schema:value": 3 + } + ], "cdif:hasPhysicalMapping": [ { "cdif:index": 0, diff --git a/_sources/profiles/cdifProfile/cdifManifest/resolvedSchema.json b/_sources/profiles/cdifProfile/cdifManifest/resolvedSchema.json index b45eee48b1..28d2193102 100644 --- a/_sources/profiles/cdifProfile/cdifManifest/resolvedSchema.json +++ b/_sources/profiles/cdifProfile/cdifManifest/resolvedSchema.json @@ -171,147 +171,7 @@ } }, { - "description": "schema.org Defined Term schema.\n\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:DefinedTerm is represented by a single attribute of that class type.\nThe JSON Schema implementation permits the property value to be EITHER a\nplain string (interpreted as schema:name or schema:termCode in the default\nvocabulary) OR a full schema:DefinedTerm object (with explicit @type, name,\nidentifier, termCode, inDefinedTermSet). Consumers should accept either form.\n\nNote that this differs from the cdif Concept policy: a Concept (skos:Concept)\nin CDIF profiles MUST be a controlled-vocabulary entry (object form or\n@id-reference) — plain strings are not permitted for Concept-typed values\nbecause vocabulary identity cannot be recovered from an unscoped label.\n", - "type": "object", - "properties": { - "@type": { - "type": "array", - "items": { - "type": "string" - }, - "contains": { - "const": "schema:DefinedTerm" - }, - "minItems": 1 - }, - "schema:name": { - "type": "string", - "description": "text label for the term that is useful to human user" - }, - "schema:identifier": { - "anyOf": [ - { - "type": "string" - }, - { - "description": "Properties for a schema.org identifier (schema:PropertyValue pattern).\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:Identifier / schema:PropertyValue is represented by a single attribute\nof that class type. The JSON Schema implementation permits the property value\nto be EITHER a plain string (interpreted as the bare identifier value) OR a\nfull schema:PropertyValue object (with explicit @type, propertyID, value).\nConsumers should accept either form.\n", - "type": "object", - "properties": { - "@type": { - "type": "array", - "items": { - "type": "string" - }, - "contains": { - "const": "schema:PropertyValue" - }, - "minItems": 1 - }, - "schema:propertyID": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "@id" - ], - "properties": { - "@id": { - "type": "string" - } - } - } - ], - "description": "In this context for the schema:PropertyValue, this field is an identifier for the identifier schema, e.g. DOI, ARK. Get values from https://registry.identifiers.org/registry/ for interoperability. URI-shape values MUST be serialized as JSON-LD IRI references ({\"@id\":\"...\"}) so they participate in RDF entailment; free-label strings remain valid as strings." - }, - "schema:value": { - "type": "string", - "description": "the identifier string. E.g. 10.5066/F7VX0DMQ" - }, - "schema:url": { - "type": "string", - "format": "uri", - "description": "web-resolveable string for the identifier; host name part is location of a resolver that will return some representation for the given identifier value. E.g. https://doi.org/10.5066/F7VX0DMQ " - } - }, - "allOf": [ - { - "required": [ - "@type" - ] - }, - { - "anyOf": [ - { - "required": [ - "schema:value" - ] - }, - { - "required": [ - "schema:url" - ] - } - ] - } - ] - } - ] - }, - "schema:inDefinedTermSet": { - "description": "The controlled vocabulary responsible for this keyword, as EITHER a plain URI string identifying the vocabulary, OR an object reference ({\"@id\": \"\"}) to a vocabulary defined elsewhere in the document. Both forms are already in use across CDIF profiles and downstream ADA building blocks; permitting only the string form made the object form - the natural JSON-LD spelling of a reference - invalid, while this class's own union-type policy above explicitly anticipates both.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "required": [ - "@id" - ], - "additionalProperties": false, - "properties": { - "@id": { - "type": "string" - } - } - } - ] - }, - "schema:termCode": { - "type": "string", - "description": "A representative code for this keyword in the controlled vocabulary. Analogous to skos:Notation" - } - }, - "allOf": [ - { - "required": [ - "@type" - ] - }, - { - "anyOf": [ - { - "required": [ - "schema:name" - ] - }, - { - "required": [ - "schema:identifier" - ] - }, - { - "required": [ - "schema:termCode" - ] - } - ] - } - ] + "$ref": "#/$defs/DefinedTerm" }, { "$ref": "#/$defs/Concept" @@ -522,147 +382,7 @@ } }, { - "description": "schema.org Defined Term schema.\n\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:DefinedTerm is represented by a single attribute of that class type.\nThe JSON Schema implementation permits the property value to be EITHER a\nplain string (interpreted as schema:name or schema:termCode in the default\nvocabulary) OR a full schema:DefinedTerm object (with explicit @type, name,\nidentifier, termCode, inDefinedTermSet). Consumers should accept either form.\n\nNote that this differs from the cdif Concept policy: a Concept (skos:Concept)\nin CDIF profiles MUST be a controlled-vocabulary entry (object form or\n@id-reference) — plain strings are not permitted for Concept-typed values\nbecause vocabulary identity cannot be recovered from an unscoped label.\n", - "type": "object", - "properties": { - "@type": { - "type": "array", - "items": { - "type": "string" - }, - "contains": { - "const": "schema:DefinedTerm" - }, - "minItems": 1 - }, - "schema:name": { - "type": "string", - "description": "text label for the term that is useful to human user" - }, - "schema:identifier": { - "anyOf": [ - { - "type": "string" - }, - { - "description": "Properties for a schema.org identifier (schema:PropertyValue pattern).\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:Identifier / schema:PropertyValue is represented by a single attribute\nof that class type. The JSON Schema implementation permits the property value\nto be EITHER a plain string (interpreted as the bare identifier value) OR a\nfull schema:PropertyValue object (with explicit @type, propertyID, value).\nConsumers should accept either form.\n", - "type": "object", - "properties": { - "@type": { - "type": "array", - "items": { - "type": "string" - }, - "contains": { - "const": "schema:PropertyValue" - }, - "minItems": 1 - }, - "schema:propertyID": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "@id" - ], - "properties": { - "@id": { - "type": "string" - } - } - } - ], - "description": "In this context for the schema:PropertyValue, this field is an identifier for the identifier schema, e.g. DOI, ARK. Get values from https://registry.identifiers.org/registry/ for interoperability. URI-shape values MUST be serialized as JSON-LD IRI references ({\"@id\":\"...\"}) so they participate in RDF entailment; free-label strings remain valid as strings." - }, - "schema:value": { - "type": "string", - "description": "the identifier string. E.g. 10.5066/F7VX0DMQ" - }, - "schema:url": { - "type": "string", - "format": "uri", - "description": "web-resolveable string for the identifier; host name part is location of a resolver that will return some representation for the given identifier value. E.g. https://doi.org/10.5066/F7VX0DMQ " - } - }, - "allOf": [ - { - "required": [ - "@type" - ] - }, - { - "anyOf": [ - { - "required": [ - "schema:value" - ] - }, - { - "required": [ - "schema:url" - ] - } - ] - } - ] - } - ] - }, - "schema:inDefinedTermSet": { - "description": "The controlled vocabulary responsible for this keyword, as EITHER a plain URI string identifying the vocabulary, OR an object reference ({\"@id\": \"\"}) to a vocabulary defined elsewhere in the document. Both forms are already in use across CDIF profiles and downstream ADA building blocks; permitting only the string form made the object form - the natural JSON-LD spelling of a reference - invalid, while this class's own union-type policy above explicitly anticipates both.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "required": [ - "@id" - ], - "additionalProperties": false, - "properties": { - "@id": { - "type": "string" - } - } - } - ] - }, - "schema:termCode": { - "type": "string", - "description": "A representative code for this keyword in the controlled vocabulary. Analogous to skos:Notation" - } - }, - "allOf": [ - { - "required": [ - "@type" - ] - }, - { - "anyOf": [ - { - "required": [ - "schema:name" - ] - }, - { - "required": [ - "schema:identifier" - ] - }, - { - "required": [ - "schema:termCode" - ] - } - ] - } - ] + "$ref": "#/$defs/DefinedTerm" }, { "$ref": "#/$defs/Concept" @@ -941,147 +661,7 @@ } }, { - "description": "schema.org Defined Term schema.\n\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:DefinedTerm is represented by a single attribute of that class type.\nThe JSON Schema implementation permits the property value to be EITHER a\nplain string (interpreted as schema:name or schema:termCode in the default\nvocabulary) OR a full schema:DefinedTerm object (with explicit @type, name,\nidentifier, termCode, inDefinedTermSet). Consumers should accept either form.\n\nNote that this differs from the cdif Concept policy: a Concept (skos:Concept)\nin CDIF profiles MUST be a controlled-vocabulary entry (object form or\n@id-reference) — plain strings are not permitted for Concept-typed values\nbecause vocabulary identity cannot be recovered from an unscoped label.\n", - "type": "object", - "properties": { - "@type": { - "type": "array", - "items": { - "type": "string" - }, - "contains": { - "const": "schema:DefinedTerm" - }, - "minItems": 1 - }, - "schema:name": { - "type": "string", - "description": "text label for the term that is useful to human user" - }, - "schema:identifier": { - "anyOf": [ - { - "type": "string" - }, - { - "description": "Properties for a schema.org identifier (schema:PropertyValue pattern).\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:Identifier / schema:PropertyValue is represented by a single attribute\nof that class type. The JSON Schema implementation permits the property value\nto be EITHER a plain string (interpreted as the bare identifier value) OR a\nfull schema:PropertyValue object (with explicit @type, propertyID, value).\nConsumers should accept either form.\n", - "type": "object", - "properties": { - "@type": { - "type": "array", - "items": { - "type": "string" - }, - "contains": { - "const": "schema:PropertyValue" - }, - "minItems": 1 - }, - "schema:propertyID": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "@id" - ], - "properties": { - "@id": { - "type": "string" - } - } - } - ], - "description": "In this context for the schema:PropertyValue, this field is an identifier for the identifier schema, e.g. DOI, ARK. Get values from https://registry.identifiers.org/registry/ for interoperability. URI-shape values MUST be serialized as JSON-LD IRI references ({\"@id\":\"...\"}) so they participate in RDF entailment; free-label strings remain valid as strings." - }, - "schema:value": { - "type": "string", - "description": "the identifier string. E.g. 10.5066/F7VX0DMQ" - }, - "schema:url": { - "type": "string", - "format": "uri", - "description": "web-resolveable string for the identifier; host name part is location of a resolver that will return some representation for the given identifier value. E.g. https://doi.org/10.5066/F7VX0DMQ " - } - }, - "allOf": [ - { - "required": [ - "@type" - ] - }, - { - "anyOf": [ - { - "required": [ - "schema:value" - ] - }, - { - "required": [ - "schema:url" - ] - } - ] - } - ] - } - ] - }, - "schema:inDefinedTermSet": { - "description": "The controlled vocabulary responsible for this keyword, as EITHER a plain URI string identifying the vocabulary, OR an object reference ({\"@id\": \"\"}) to a vocabulary defined elsewhere in the document. Both forms are already in use across CDIF profiles and downstream ADA building blocks; permitting only the string form made the object form - the natural JSON-LD spelling of a reference - invalid, while this class's own union-type policy above explicitly anticipates both.", - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "required": [ - "@id" - ], - "additionalProperties": false, - "properties": { - "@id": { - "type": "string" - } - } - } - ] - }, - "schema:termCode": { - "type": "string", - "description": "A representative code for this keyword in the controlled vocabulary. Analogous to skos:Notation" - } - }, - "allOf": [ - { - "required": [ - "@type" - ] - }, - { - "anyOf": [ - { - "required": [ - "schema:name" - ] - }, - { - "required": [ - "schema:identifier" - ] - }, - { - "required": [ - "schema:termCode" - ] - } - ] - } - ] + "$ref": "#/$defs/DefinedTerm" }, { "$ref": "#/$defs/Concept" @@ -1175,11 +755,89 @@ ] } }, - "countRows": { - "type": "integer" - }, - "countColumns": { - "type": "integer" + "schema:additionalProperty": { + "description": "Soft-typed extension properties. The row and column counts live here rather than as bare properties, so that each carries a schema:propertyID identifying the concept it quantifies - DDI Discovery caseQuantity for the row count and variableQuantity for the column count. As bare unprefixed `countRows`/`countColumns` they were the only two properties on this class with no namespace and no definition, so nothing said what they meant or tied them to a vocabulary.", + "type": "array", + "items": { + "type": "object", + "title": "additionalProperty PropertyValue", + "description": "PropertyValue values required to define a soft-typed property with a value. ", + "properties": { + "@type": { + "type": "array", + "items": { + "type": "string" + }, + "contains": { + "const": "schema:PropertyValue" + }, + "minItems": 1 + }, + "schema:propertyID": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "required": [ + "@id" + ], + "additionalProperties": false, + "properties": { + "@id": { + "type": "string" + } + } + }, + { + "$ref": "#/$defs/DefinedTerm" + } + ] + }, + "minItems": 1, + "description": "identifier or name for the property concept quantified by the values in this variable slot. Multiple values can specify the property at different levels of granularity." + }, + "schema:name": { + "type": "string" + }, + "schema:value": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "object" + } + ] + }, + "schema:unitCode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/DefinedTerm" + } + ] + }, + "schema:unitText": { + "type": "string" + } + }, + "required": [ + "schema:name", + "schema:value" + ] + } } }, "oneOf": [ @@ -1248,6 +906,149 @@ } }, "$defs": { + "DefinedTerm": { + "description": "schema.org Defined Term schema.\n\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:DefinedTerm is represented by a single attribute of that class type.\nThe JSON Schema implementation permits the property value to be EITHER a\nplain string (interpreted as schema:name or schema:termCode in the default\nvocabulary) OR a full schema:DefinedTerm object (with explicit @type, name,\nidentifier, termCode, inDefinedTermSet). Consumers should accept either form.\n\nNote that this differs from the cdif Concept policy: a Concept (skos:Concept)\nin CDIF profiles MUST be a controlled-vocabulary entry (object form or\n@id-reference) — plain strings are not permitted for Concept-typed values\nbecause vocabulary identity cannot be recovered from an unscoped label.\n", + "type": "object", + "properties": { + "@type": { + "type": "array", + "items": { + "type": "string" + }, + "contains": { + "const": "schema:DefinedTerm" + }, + "minItems": 1 + }, + "schema:name": { + "type": "string", + "description": "text label for the term that is useful to human user" + }, + "schema:identifier": { + "anyOf": [ + { + "type": "string" + }, + { + "description": "Properties for a schema.org identifier (schema:PropertyValue pattern).\n**Union-type policy:** In CDIF profile UML models an attribute typed as\nschema:Identifier / schema:PropertyValue is represented by a single attribute\nof that class type. The JSON Schema implementation permits the property value\nto be EITHER a plain string (interpreted as the bare identifier value) OR a\nfull schema:PropertyValue object (with explicit @type, propertyID, value).\nConsumers should accept either form.\n", + "type": "object", + "properties": { + "@type": { + "type": "array", + "items": { + "type": "string" + }, + "contains": { + "const": "schema:PropertyValue" + }, + "minItems": 1 + }, + "schema:propertyID": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "@id" + ], + "properties": { + "@id": { + "type": "string" + } + } + } + ], + "description": "In this context for the schema:PropertyValue, this field is an identifier for the identifier schema, e.g. DOI, ARK. Get values from https://registry.identifiers.org/registry/ for interoperability. URI-shape values MUST be serialized as JSON-LD IRI references ({\"@id\":\"...\"}) so they participate in RDF entailment; free-label strings remain valid as strings." + }, + "schema:value": { + "type": "string", + "description": "the identifier string. E.g. 10.5066/F7VX0DMQ" + }, + "schema:url": { + "type": "string", + "format": "uri", + "description": "web-resolveable string for the identifier; host name part is location of a resolver that will return some representation for the given identifier value. E.g. https://doi.org/10.5066/F7VX0DMQ " + } + }, + "allOf": [ + { + "required": [ + "@type" + ] + }, + { + "anyOf": [ + { + "required": [ + "schema:value" + ] + }, + { + "required": [ + "schema:url" + ] + } + ] + } + ] + } + ] + }, + "schema:inDefinedTermSet": { + "description": "The controlled vocabulary responsible for this keyword, as EITHER a plain URI string identifying the vocabulary, OR an object reference ({\"@id\": \"\"}) to a vocabulary defined elsewhere in the document. Both forms are already in use across CDIF profiles and downstream ADA building blocks; permitting only the string form made the object form - the natural JSON-LD spelling of a reference - invalid, while this class's own union-type policy above explicitly anticipates both.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "required": [ + "@id" + ], + "additionalProperties": false, + "properties": { + "@id": { + "type": "string" + } + } + } + ] + }, + "schema:termCode": { + "type": "string", + "description": "A representative code for this keyword in the controlled vocabulary. Analogous to skos:Notation" + } + }, + "allOf": [ + { + "required": [ + "@type" + ] + }, + { + "anyOf": [ + { + "required": [ + "schema:name" + ] + }, + { + "required": [ + "schema:identifier" + ] + }, + { + "required": [ + "schema:termCode" + ] + } + ] + } + ] + }, "Concept": { "type": "object", "properties": {