From b5eaccfc71ad16ef26ec73e3b92fe5c38d079907 Mon Sep 17 00:00:00 2001 From: Marco Volpini Date: Tue, 7 Apr 2026 16:42:44 +0200 Subject: [PATCH] improved schema extraction --- .../dpp/validation/api/rest/PayloadType.java | 11 +- .../json/JsonSchemaMetadataExtractor.java | 244 ++- .../json/JsonSchemaMetadataExtractorTest.java | 9 + .../json-schemas/test-aas-schema.json | 1540 +++++++++++++++++ 4 files changed, 1750 insertions(+), 54 deletions(-) create mode 100644 core/src/test/resources/json-schemas/test-aas-schema.json diff --git a/api/rest/src/main/java/it/extrared/dpp/validation/api/rest/PayloadType.java b/api/rest/src/main/java/it/extrared/dpp/validation/api/rest/PayloadType.java index 728aaf1..938642d 100644 --- a/api/rest/src/main/java/it/extrared/dpp/validation/api/rest/PayloadType.java +++ b/api/rest/src/main/java/it/extrared/dpp/validation/api/rest/PayloadType.java @@ -50,7 +50,8 @@ public enum PayloadType { private final Lang lang; private final List supportedMimeTypes; - private static final Logger LOGGER=Logger.getLogger(PayloadType.class); + private static final Logger LOGGER = Logger.getLogger(PayloadType.class); + PayloadType(Lang lang, List supportedMimeTypes) { this.lang = lang; this.supportedMimeTypes = supportedMimeTypes; @@ -68,10 +69,10 @@ public InputStream convert(InputStream input) { } } - public byte[] convertToJsonLdIfNeeded(byte[] input){ - if (input==null) throw new InvalidOpException("Empty DPP input"); - if (Objects.equals(json,this) || Objects.equals(json_ld,this)) return input; - debug(LOGGER,()->"converting %s to json-ld".formatted(new String(input))); + public byte[] convertToJsonLdIfNeeded(byte[] input) { + if (input == null) throw new InvalidOpException("Empty DPP input"); + if (Objects.equals(json, this) || Objects.equals(json_ld, this)) return input; + debug(LOGGER, () -> "converting %s to json-ld".formatted(new String(input))); Model model = ModelFactory.createDefaultModel(); RDFDataMgr.read(model, new ByteArrayInputStream(input), this.lang); ByteArrayOutputStream baos = new ByteArrayOutputStream(); diff --git a/core/src/main/java/it/extared/dpp/validator/json/JsonSchemaMetadataExtractor.java b/core/src/main/java/it/extared/dpp/validator/json/JsonSchemaMetadataExtractor.java index f0dc269..c9e14c0 100644 --- a/core/src/main/java/it/extared/dpp/validator/json/JsonSchemaMetadataExtractor.java +++ b/core/src/main/java/it/extared/dpp/validator/json/JsonSchemaMetadataExtractor.java @@ -19,12 +19,16 @@ import static it.extared.dpp.validator.utils.JsonUtils.*; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import io.quarkus.runtime.util.StringUtil; import it.extared.dpp.validator.json.dto.DiscriminatorInfo; import it.extared.dpp.validator.json.dto.PatternProperty; import it.extared.dpp.validator.json.dto.SchemaMetadata; import it.extared.dpp.validator.json.dto.SchemaVariant; import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import java.util.*; import org.jboss.logging.Logger; @@ -33,34 +37,108 @@ public class JsonSchemaMetadataExtractor { private static final Logger LOGGER = Logger.getLogger(JsonSchemaMetadataExtractor.class); + private static final String REF_KEY = "$ref"; + + @Inject ObjectMapper objectMapper; + public SchemaMetadata extractMetadata(JsonNode schema) { SchemaMetadata metadata = new SchemaMetadata(); debug(LOGGER, () -> "extracting metadata from schema \n %s".formatted(schema)); - handleSchema(schema, metadata); + // Use an identity-based set to track visited nodes and break circular ref chains + Set visited = Collections.newSetFromMap(new IdentityHashMap<>()); + handleSchema(schema, schema, metadata, visited); return metadata; } - private void handleSchema(JsonNode schema, SchemaMetadata metadata) { - Set paths = extractRequiredPaths(schema, ""); + private void handleSchema( + JsonNode schema, JsonNode root, SchemaMetadata metadata, Set visited) { + JsonNode resolved = resolveRef(schema, root, visited); + if (resolved == null) return; + + JsonNode flat = flattenAllOf(resolved, root, visited); + + Set paths = extractRequiredPaths(flat, root, "", visited); metadata.getRequiredPaths().addAll(paths); - List patternProps = extractPatternProperties(schema, ""); + List patternProps = extractPatternProperties(flat, root, "", visited); metadata.getPatternProperties().addAll(patternProps); - if (schema.has(ALL_OF_KEY)) { - handleAllOf(schema.get(ALL_OF_KEY), metadata); + + // Use resolved (not flat) because flattenAllOf removes the allOf key + if (resolved.has(ALL_OF_KEY)) { + handleAllOf(resolved.get(ALL_OF_KEY), root, metadata, visited); } - if (schema.has(ONE_OF_KEY)) { + if (flat.has(ONE_OF_KEY)) { metadata.getVariants() - .addAll(extractVariants(schema.get(ONE_OF_KEY), ONE_OF_KEY, schema)); + .addAll(extractVariants(flat.get(ONE_OF_KEY), ONE_OF_KEY, flat, root, visited)); metadata.setHasVariants(true); } - if (schema.has(ANY_OF_KEY)) { + if (flat.has(ANY_OF_KEY)) { metadata.getVariants() - .addAll(extractVariants(schema.get(ANY_OF_KEY), ANY_OF_KEY, schema)); + .addAll(extractVariants(flat.get(ANY_OF_KEY), ANY_OF_KEY, flat, root, visited)); metadata.setHasVariants(true); } } - private Set extractRequiredPaths(JsonNode schema, String currentPath) { + private JsonNode resolveRef(JsonNode schema, JsonNode root, Set visited) { + if (schema == null) return null; + if (!schema.has(REF_KEY)) return schema; + + String ref = schema.get(REF_KEY).asText(); + if (!ref.startsWith("#/")) return schema; + + String[] parts = ref.substring(2).split("/"); + JsonNode resolved = root; + for (String part : parts) { + resolved = resolved.get(part); + if (resolved == null) return null; + } + + // Guard: if we've already visited this exact node instance, stop + if (!visited.add(resolved)) return null; + + return resolveRef(resolved, root, visited); + } + + private JsonNode flattenAllOf(JsonNode schema, JsonNode root, Set visited) { + if (!schema.has(ALL_OF_KEY)) return schema; + + ObjectNode merged = objectMapper.createObjectNode(); + ObjectNode mergedProperties = objectMapper.createObjectNode(); + ArrayNode mergedRequired = objectMapper.createArrayNode(); + + schema.properties().stream() + .filter(e -> !e.getKey().equals(ALL_OF_KEY)) + .forEach(e -> merged.set(e.getKey(), e.getValue())); + + for (JsonNode entry : schema.get(ALL_OF_KEY)) { + JsonNode resolved = resolveRef(entry, root, visited); + if (resolved == null) continue; + JsonNode flattened = flattenAllOf(resolved, root, visited); + + if (flattened.has(PROPERTIES_KEY)) { + flattened + .get(PROPERTIES_KEY) + .properties() + .forEach(e -> mergedProperties.set(e.getKey(), e.getValue())); + } + if (flattened.has(REQUIRED_KEY)) { + flattened.get(REQUIRED_KEY).forEach(mergedRequired::add); + } + flattened.properties().stream() + .filter( + e -> + !e.getKey().equals(PROPERTIES_KEY) + && !e.getKey().equals(REQUIRED_KEY) + && !e.getKey().equals(ALL_OF_KEY)) + .forEach(e -> merged.set(e.getKey(), e.getValue())); + } + + if (!mergedProperties.isEmpty()) merged.set(PROPERTIES_KEY, mergedProperties); + if (!mergedRequired.isEmpty()) merged.set(REQUIRED_KEY, mergedRequired); + return merged; + } + + private Set extractRequiredPaths( + JsonNode schema, JsonNode root, String currentPath, Set visited) { debug( LOGGER, () -> @@ -72,79 +150,142 @@ private Set extractRequiredPaths(JsonNode schema, String currentPath) { Set paths = new HashSet<>(); if (schema == null || !schema.isObject()) return paths; - JsonNode requiredNode = schema.get(REQUIRED_KEY); - JsonNode propertiesNode = schema.get(PROPERTIES_KEY); + JsonNode resolved = flattenAllOf(resolveRefSafe(schema, root, visited), root, visited); + if (resolved == null) return paths; + + JsonNode requiredNode = resolved.get(REQUIRED_KEY); + JsonNode propertiesNode = resolved.get(PROPERTIES_KEY); + Set requiredFields = new HashSet<>(); if (requiredNode != null && requiredNode.isArray()) { debug(LOGGER, () -> "extracting required properties %s".formatted(requiredNode)); requiredNode.forEach( - req -> addPathsFromRequiredNode(req, paths, propertiesNode, currentPath)); + req -> { + requiredFields.add(req.asText()); + addPathsFromRequiredNode( + req, paths, propertiesNode, root, currentPath, visited); + }); + } + + // Traverse non-required properties too to find nested required paths. + // Needed for schemas like AAS where the root has no required fields + // but nested definitions do. + if (propertiesNode != null) { + for (Map.Entry entry : propertiesNode.properties()) { + String propName = entry.getKey(); + if (requiredFields.contains(propName)) continue; + String fullPath = currentPath.isEmpty() ? propName : currentPath + "." + propName; + paths.addAll(recurseIntoProperty(entry.getValue(), root, fullPath, visited)); + } } return paths; } private void addPathsFromRequiredNode( - JsonNode reqNode, Set paths, JsonNode propertiesNode, String currentPath) { + JsonNode reqNode, + Set paths, + JsonNode propertiesNode, + JsonNode root, + String currentPath, + Set visited) { String propName = reqNode.asText(); String fullPath = currentPath.isEmpty() ? propName : currentPath + "." + propName; - debug(LOGGER, () -> "adding full froom required node, %s".formatted(fullPath)); + debug(LOGGER, () -> "adding full from required node, %s".formatted(fullPath)); paths.add(fullPath); if (propertiesNode != null && propertiesNode.has(propName)) { - JsonNode propSchema = propertiesNode.get(propName); - paths.addAll(recurseIntoProperty(propSchema, fullPath)); + paths.addAll( + recurseIntoProperty(propertiesNode.get(propName), root, fullPath, visited)); } } - private Set recurseIntoProperty(JsonNode propSchema, String fullPath) { + private Set recurseIntoProperty( + JsonNode propSchema, JsonNode root, String fullPath, Set visited) { Set paths = new HashSet<>(); - JsonNode propType = propSchema.get(TYPE_KEY); + if (propSchema == null) return paths; + + JsonNode resolved = resolveRefSafe(propSchema, root, visited); + if (resolved == null) return paths; + + JsonNode flat = flattenAllOf(resolved, root, visited); + JsonNode propType = flat.get(TYPE_KEY); if (propType != null) { if (propType.asText().equals(OBJECT_KEY)) { - paths.addAll(extractRequiredPaths(propSchema, fullPath)); - - if (propSchema.has(PATTER_PROPERTIES_KEY)) { + paths.addAll(extractRequiredPaths(flat, root, fullPath, visited)); + if (flat.has(PATTER_PROPERTIES_KEY)) { paths.add(fullPath + "."); } } else if (propType.asText().equals(ARRAY_KEY)) { - JsonNode itemsNode = propSchema.get(ITEMS_KEY); + JsonNode itemsNode = flat.get(ITEMS_KEY); if (itemsNode != null && itemsNode.isObject()) { - JsonNode itemType = itemsNode.get(TYPE_KEY); - if (itemType != null && itemType.asText().equals(OBJECT_KEY)) { - paths.addAll(extractRequiredPaths(itemsNode, fullPath + "[]")); + JsonNode itemResolved = resolveRefSafe(itemsNode, root, visited); + if (itemResolved != null) { + JsonNode itemFlat = flattenAllOf(itemResolved, root, visited); + JsonNode itemType = itemFlat.get(TYPE_KEY); + if (itemType != null && itemType.asText().equals(OBJECT_KEY)) { + paths.addAll( + extractRequiredPaths(itemFlat, root, fullPath + "[]", visited)); + } } } } + } else if (flat.has(PROPERTIES_KEY) || flat.has(REQUIRED_KEY)) { + paths.addAll(extractRequiredPaths(flat, root, fullPath, visited)); } return paths; } - private void handleAllOf(JsonNode allOfNode, SchemaMetadata metadata) { + /** + * Resolves a $ref without adding the target node to visited — used when we only want to read + * the node content without committing to a traversal path. Returns null if the ref has already + * been visited (cycle detected). + */ + private JsonNode resolveRefSafe(JsonNode schema, JsonNode root, Set visited) { + if (schema == null) return null; + if (!schema.has(REF_KEY)) return schema; + return resolveRef(schema, root, visited); + } + + private void handleAllOf( + JsonNode allOfNode, JsonNode root, SchemaMetadata metadata, Set visited) { if (!allOfNode.isArray()) return; debug(LOGGER, () -> "adding all of schemas %s".formatted(allOfNode)); - allOfNode.forEach(n -> handleSchema(n, metadata)); + allOfNode.forEach(n -> handleSchema(n, root, metadata, visited)); } private List extractVariants( - JsonNode variantsNode, String variantType, JsonNode parentSchema) { + JsonNode variantsNode, + String variantType, + JsonNode parentSchema, + JsonNode root, + Set visited) { List variants = new ArrayList<>(); if (!variantsNode.isArray()) return variants; - DiscriminatorInfo discriminator = detectDiscriminator(variantsNode, parentSchema); + DiscriminatorInfo discriminator = + detectDiscriminator(variantsNode, parentSchema, root, visited); int index = 0; for (JsonNode variantSchema : variantsNode) { + JsonNode resolved = resolveRefSafe(variantSchema, root, visited); + if (resolved == null) { + index++; + continue; + } + JsonNode resolvedVariant = flattenAllOf(resolved, root, visited); SchemaVariant variant = new SchemaVariant(); variant.setVariantType(variantType); variant.setVariantIndex(index); - variant.setRequiredPaths(extractRequiredPaths(variantSchema, "")); + Set variantVisited = Collections.newSetFromMap(new IdentityHashMap<>()); + variant.setRequiredPaths( + extractRequiredPaths(resolvedVariant, root, "", variantVisited)); if (discriminator != null) { variant.setDiscriminatorPath(discriminator.getPath()); variant.setDiscriminatorValue( - extractDiscriminatorValue(variantSchema, discriminator)); + extractDiscriminatorValue(resolvedVariant, discriminator)); } variants.add(variant); @@ -154,7 +295,8 @@ private List extractVariants( return variants; } - private DiscriminatorInfo detectDiscriminator(JsonNode variantsNode, JsonNode parentSchema) { + private DiscriminatorInfo detectDiscriminator( + JsonNode variantsNode, JsonNode parentSchema, JsonNode root, Set visited) { debug(LOGGER, () -> "retrieving discriminator for polymorphic json"); if (parentSchema.has(DISCRIMINATOR_KEY)) { JsonNode disc = parentSchema.get(DISCRIMINATOR_KEY); @@ -165,14 +307,14 @@ private DiscriminatorInfo detectDiscriminator(JsonNode variantsNode, JsonNode pa } } - // ok we don't have a discriminator explicitly defined. - // let's search in all the variants for a common property that has a different value in each - // variant Map> candidateFields = new HashMap<>(); for (JsonNode variant : variantsNode) { - if (variant.has(PROPERTIES_KEY)) - variant.get(PROPERTIES_KEY) + JsonNode resolved = resolveRefSafe(variant, root, visited); + if (resolved == null) continue; + JsonNode flat = flattenAllOf(resolved, root, visited); + if (flat.has(PROPERTIES_KEY)) + flat.get(PROPERTIES_KEY) .properties() .forEach(entry -> addCandidateField(candidateFields, entry)); } @@ -190,7 +332,6 @@ private DiscriminatorInfo detectDiscriminator(JsonNode variantsNode, JsonNode pa return null; } - // add the candidate if we have enum or const keys that might it likely being a discriminator private void addCandidateField( Map> candidateFields, Map.Entry variantProperty) { String fieldName = variantProperty.getKey(); @@ -223,7 +364,8 @@ private String extractDiscriminatorValue( return null; } - private List extractPatternProperties(JsonNode schema, String currentPath) { + private List extractPatternProperties( + JsonNode schema, JsonNode root, String currentPath, Set visited) { List patterns = new ArrayList<>(); if (!schema.has(PATTER_PROPERTIES_KEY)) return patterns; @@ -231,16 +373,15 @@ private List extractPatternProperties(JsonNode schema, String c JsonNode patternPropsNode = schema.get(PATTER_PROPERTIES_KEY); patternPropsNode .properties() - .forEach(entry -> addPatternProperty(patterns, currentPath, entry)); + .forEach(entry -> addPatternProperty(patterns, currentPath, entry, root, visited)); if (schema.has(PROPERTIES_KEY)) { for (Map.Entry entry : schema.get(PROPERTIES_KEY).properties()) { - String propName = entry.getKey(); - JsonNode propSchema = entry.getValue(); + JsonNode propSchema = resolveRefSafe(entry.getValue(), root, visited); + if (propSchema == null) continue; String fullPath = currentPath.isEmpty() ? propName : currentPath + "." + propName; - - patterns.addAll(extractPatternProperties(propSchema, fullPath)); + patterns.addAll(extractPatternProperties(propSchema, root, fullPath, visited)); } } @@ -250,9 +391,12 @@ private List extractPatternProperties(JsonNode schema, String c private void addPatternProperty( List patterns, String currentPath, - Map.Entry patternProp) { + Map.Entry patternProp, + JsonNode root, + Set visited) { String pattern = patternProp.getKey(); - JsonNode patternSchema = patternProp.getValue(); + JsonNode patternSchema = resolveRefSafe(patternProp.getValue(), root, visited); + if (patternSchema == null) return; debug(LOGGER, () -> "adding pattern property %s".formatted(pattern)); PatternProperty pp = new PatternProperty(); pp.setPatternRegex(pattern); @@ -264,7 +408,9 @@ private void addPatternProperty( JsonNode patternType = patternSchema.get(TYPE_KEY); if (patternType != null && patternType.asText().equals(OBJECT_KEY)) { debug(LOGGER, () -> "pattern property is an object. extracting subpaths"); - pp.setRequiredSubPaths(new ArrayList<>(extractRequiredPaths(patternSchema, ""))); + Set patternVisited = Collections.newSetFromMap(new IdentityHashMap<>()); + pp.setRequiredSubPaths( + new ArrayList<>(extractRequiredPaths(patternSchema, root, "", patternVisited))); } patterns.add(pp); diff --git a/core/src/test/java/it/extrared/dpp/validator/json/JsonSchemaMetadataExtractorTest.java b/core/src/test/java/it/extrared/dpp/validator/json/JsonSchemaMetadataExtractorTest.java index c2a54b2..d75f209 100644 --- a/core/src/test/java/it/extrared/dpp/validator/json/JsonSchemaMetadataExtractorTest.java +++ b/core/src/test/java/it/extrared/dpp/validator/json/JsonSchemaMetadataExtractorTest.java @@ -58,4 +58,13 @@ public void testExtraction3() { assertFalse(schema.isHasVariants()); assertEquals(4, schema.getPatternProperties().size()); } + + @Test + public void testExtraction4() { + SchemaMetadata schema = + extractor.extractMetadata(CommonUtils.readJsonSchemaNode("test-aas-schema.json")); + assertEquals(16, schema.getRequiredPaths().size()); + assertFalse(schema.isHasVariants()); + assertEquals(0, schema.getPatternProperties().size()); + } } diff --git a/core/src/test/resources/json-schemas/test-aas-schema.json b/core/src/test/resources/json-schemas/test-aas-schema.json new file mode 100644 index 0000000..4178c9e --- /dev/null +++ b/core/src/test/resources/json-schemas/test-aas-schema.json @@ -0,0 +1,1540 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "AssetAdministrationShellEnvironment", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/Environment" + } + ], + "$id": "https://admin-shell.io/aas/3/0", + "definitions": { + "AasSubmodelElements": { + "type": "string", + "enum": [ + "AnnotatedRelationshipElement", + "BasicEventElement", + "Blob", + "Capability", + "DataElement", + "Entity", + "EventElement", + "File", + "MultiLanguageProperty", + "Operation", + "Property", + "Range", + "ReferenceElement", + "RelationshipElement", + "SubmodelElement", + "SubmodelElementCollection", + "SubmodelElementList" + ] + }, + "AbstractLangString": { + "type": "object", + "properties": { + "language": { + "type": "string", + "pattern": "^(([a-zA-Z]{2,3}(-[a-zA-Z]{3}(-[a-zA-Z]{3}){2})?|[a-zA-Z]{4}|[a-zA-Z]{5,8})(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|[0-9]{3}))?(-(([a-zA-Z0-9]){5,8}|[0-9]([a-zA-Z0-9]){3}))*(-[0-9A-WY-Za-wy-z](-([a-zA-Z0-9]){2,8})+)*(-[xX](-([a-zA-Z0-9]){1,8})+)?|[xX](-([a-zA-Z0-9]){1,8})+|((en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)))$" + }, + "text": { + "type": "string", + "minLength": 1, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + } + }, + "required": [ + "language", + "text" + ] + }, + "AdministrativeInformation": { + "allOf": [ + { + "$ref": "#/definitions/HasDataSpecification" + }, + { + "properties": { + "version": { + "type": "string", + "allOf": [ + { + "minLength": 1, + "maxLength": 4 + }, + { + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + { + "pattern": "^(0|[1-9][0-9]*)$" + } + ] + }, + "revision": { + "type": "string", + "allOf": [ + { + "minLength": 1, + "maxLength": 4 + }, + { + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + { + "pattern": "^(0|[1-9][0-9]*)$" + } + ] + }, + "creator": { + "$ref": "#/definitions/Reference" + }, + "templateId": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + } + } + } + ] + }, + "AnnotatedRelationshipElement": { + "allOf": [ + { + "$ref": "#/definitions/RelationshipElement_abstract" + }, + { + "properties": { + "annotations": { + "type": "array", + "items": { + "$ref": "#/definitions/DataElement_choice" + }, + "minItems": 1 + }, + "modelType": { + "const": "AnnotatedRelationshipElement" + } + } + } + ] + }, + "AssetAdministrationShell": { + "allOf": [ + { + "$ref": "#/definitions/Identifiable" + }, + { + "$ref": "#/definitions/HasDataSpecification" + }, + { + "properties": { + "derivedFrom": { + "$ref": "#/definitions/Reference" + }, + "assetInformation": { + "$ref": "#/definitions/AssetInformation" + }, + "submodels": { + "type": "array", + "items": { + "$ref": "#/definitions/Reference" + }, + "minItems": 1 + }, + "modelType": { + "const": "AssetAdministrationShell" + } + }, + "required": [ + "assetInformation" + ] + } + ] + }, + "AssetInformation": { + "type": "object", + "properties": { + "assetKind": { + "$ref": "#/definitions/AssetKind" + }, + "globalAssetId": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "specificAssetIds": { + "type": "array", + "items": { + "$ref": "#/definitions/SpecificAssetId" + }, + "minItems": 1 + }, + "assetType": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "defaultThumbnail": { + "$ref": "#/definitions/Resource" + } + }, + "required": [ + "assetKind" + ] + }, + "AssetKind": { + "type": "string", + "enum": [ + "Instance", + "NotApplicable", + "Type" + ] + }, + "BasicEventElement": { + "allOf": [ + { + "$ref": "#/definitions/EventElement" + }, + { + "properties": { + "observed": { + "$ref": "#/definitions/Reference" + }, + "direction": { + "$ref": "#/definitions/Direction" + }, + "state": { + "$ref": "#/definitions/StateOfEvent" + }, + "messageTopic": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "messageBroker": { + "$ref": "#/definitions/Reference" + }, + "lastUpdate": { + "type": "string", + "pattern": "^-?(([1-9][0-9][0-9][0-9]+)|(0[0-9][0-9][0-9]))-((0[1-9])|(1[0-2]))-((0[1-9])|([12][0-9])|(3[01]))T(((([01][0-9])|(2[0-3])):[0-5][0-9]:([0-5][0-9])(\\.[0-9]+)?)|24:00:00(\\.0+)?)(Z|\\+00:00|-00:00)$" + }, + "minInterval": { + "type": "string", + "pattern": "^-?P((([0-9]+Y([0-9]+M)?([0-9]+D)?|([0-9]+M)([0-9]+D)?|([0-9]+D))(T(([0-9]+H)([0-9]+M)?([0-9]+(\\.[0-9]+)?S)?|([0-9]+M)([0-9]+(\\.[0-9]+)?S)?|([0-9]+(\\.[0-9]+)?S)))?)|(T(([0-9]+H)([0-9]+M)?([0-9]+(\\.[0-9]+)?S)?|([0-9]+M)([0-9]+(\\.[0-9]+)?S)?|([0-9]+(\\.[0-9]+)?S))))$" + }, + "maxInterval": { + "type": "string", + "pattern": "^-?P((([0-9]+Y([0-9]+M)?([0-9]+D)?|([0-9]+M)([0-9]+D)?|([0-9]+D))(T(([0-9]+H)([0-9]+M)?([0-9]+(\\.[0-9]+)?S)?|([0-9]+M)([0-9]+(\\.[0-9]+)?S)?|([0-9]+(\\.[0-9]+)?S)))?)|(T(([0-9]+H)([0-9]+M)?([0-9]+(\\.[0-9]+)?S)?|([0-9]+M)([0-9]+(\\.[0-9]+)?S)?|([0-9]+(\\.[0-9]+)?S))))$" + }, + "modelType": { + "const": "BasicEventElement" + } + }, + "required": [ + "observed", + "direction", + "state" + ] + } + ] + }, + "Blob": { + "allOf": [ + { + "$ref": "#/definitions/DataElement" + }, + { + "properties": { + "value": { + "type": "string", + "contentEncoding": "base64" + }, + "contentType": { + "type": "string", + "allOf": [ + { + "minLength": 1, + "maxLength": 100 + }, + { + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + { + "pattern": "^([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+/([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+([ \\t]*;[ \\t]*([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+=(([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+|\"(([\\t !#-\\[\\]-~]|[\u0080-\u00ff])|\\\\([\\t !-~]|[\u0080-\u00ff]))*\"))*$" + } + ] + }, + "modelType": { + "const": "Blob" + } + }, + "required": [ + "contentType" + ] + } + ] + }, + "Capability": { + "allOf": [ + { + "$ref": "#/definitions/SubmodelElement" + }, + { + "properties": { + "modelType": { + "const": "Capability" + } + } + } + ] + }, + "ConceptDescription": { + "allOf": [ + { + "$ref": "#/definitions/Identifiable" + }, + { + "$ref": "#/definitions/HasDataSpecification" + }, + { + "properties": { + "isCaseOf": { + "type": "array", + "items": { + "$ref": "#/definitions/Reference" + }, + "minItems": 1 + }, + "modelType": { + "const": "ConceptDescription" + } + } + } + ] + }, + "DataElement": { + "$ref": "#/definitions/SubmodelElement" + }, + "DataElement_choice": { + "oneOf": [ + { + "$ref": "#/definitions/Blob" + }, + { + "$ref": "#/definitions/File" + }, + { + "$ref": "#/definitions/MultiLanguageProperty" + }, + { + "$ref": "#/definitions/Property" + }, + { + "$ref": "#/definitions/Range" + }, + { + "$ref": "#/definitions/ReferenceElement" + } + ] + }, + "DataSpecificationContent": { + "type": "object", + "properties": { + "modelType": { + "$ref": "#/definitions/ModelType" + } + }, + "required": [ + "modelType" + ] + }, + "DataSpecificationContent_choice": { + "oneOf": [ + { + "$ref": "#/definitions/DataSpecificationIec61360" + } + ] + }, + "DataSpecificationIec61360": { + "allOf": [ + { + "$ref": "#/definitions/DataSpecificationContent" + }, + { + "properties": { + "preferredName": { + "type": "array", + "items": { + "$ref": "#/definitions/LangStringPreferredNameTypeIec61360" + }, + "minItems": 1 + }, + "shortName": { + "type": "array", + "items": { + "$ref": "#/definitions/LangStringShortNameTypeIec61360" + }, + "minItems": 1 + }, + "unit": { + "type": "string", + "minLength": 1, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "unitId": { + "$ref": "#/definitions/Reference" + }, + "sourceOfDefinition": { + "type": "string", + "minLength": 1, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "symbol": { + "type": "string", + "minLength": 1, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "dataType": { + "$ref": "#/definitions/DataTypeIec61360" + }, + "definition": { + "type": "array", + "items": { + "$ref": "#/definitions/LangStringDefinitionTypeIec61360" + }, + "minItems": 1 + }, + "valueFormat": { + "type": "string", + "minLength": 1, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "valueList": { + "$ref": "#/definitions/ValueList" + }, + "value": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "levelType": { + "$ref": "#/definitions/LevelType" + }, + "modelType": { + "const": "DataSpecificationIec61360" + } + }, + "required": [ + "preferredName" + ] + } + ] + }, + "DataTypeDefXsd": { + "type": "string", + "enum": [ + "xs:anyURI", + "xs:base64Binary", + "xs:boolean", + "xs:byte", + "xs:date", + "xs:dateTime", + "xs:decimal", + "xs:double", + "xs:duration", + "xs:float", + "xs:gDay", + "xs:gMonth", + "xs:gMonthDay", + "xs:gYear", + "xs:gYearMonth", + "xs:hexBinary", + "xs:int", + "xs:integer", + "xs:long", + "xs:negativeInteger", + "xs:nonNegativeInteger", + "xs:nonPositiveInteger", + "xs:positiveInteger", + "xs:short", + "xs:string", + "xs:time", + "xs:unsignedByte", + "xs:unsignedInt", + "xs:unsignedLong", + "xs:unsignedShort" + ] + }, + "DataTypeIec61360": { + "type": "string", + "enum": [ + "BLOB", + "BOOLEAN", + "DATE", + "FILE", + "HTML", + "INTEGER_COUNT", + "INTEGER_CURRENCY", + "INTEGER_MEASURE", + "IRDI", + "IRI", + "RATIONAL", + "RATIONAL_MEASURE", + "REAL_COUNT", + "REAL_CURRENCY", + "REAL_MEASURE", + "STRING", + "STRING_TRANSLATABLE", + "TIME", + "TIMESTAMP" + ] + }, + "Direction": { + "type": "string", + "enum": [ + "input", + "output" + ] + }, + "EmbeddedDataSpecification": { + "type": "object", + "properties": { + "dataSpecification": { + "$ref": "#/definitions/Reference" + }, + "dataSpecificationContent": { + "$ref": "#/definitions/DataSpecificationContent_choice" + } + }, + "required": [ + "dataSpecification", + "dataSpecificationContent" + ] + }, + "Entity": { + "allOf": [ + { + "$ref": "#/definitions/SubmodelElement" + }, + { + "properties": { + "statements": { + "type": "array", + "items": { + "$ref": "#/definitions/SubmodelElement_choice" + }, + "minItems": 1 + }, + "entityType": { + "$ref": "#/definitions/EntityType" + }, + "globalAssetId": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "specificAssetIds": { + "type": "array", + "items": { + "$ref": "#/definitions/SpecificAssetId" + }, + "minItems": 1 + }, + "modelType": { + "const": "Entity" + } + }, + "required": [ + "entityType" + ] + } + ] + }, + "EntityType": { + "type": "string", + "enum": [ + "CoManagedEntity", + "SelfManagedEntity" + ] + }, + "Environment": { + "type": "object", + "properties": { + "assetAdministrationShells": { + "type": "array", + "items": { + "$ref": "#/definitions/AssetAdministrationShell" + }, + "minItems": 1 + }, + "submodels": { + "type": "array", + "items": { + "$ref": "#/definitions/Submodel" + }, + "minItems": 1 + }, + "conceptDescriptions": { + "type": "array", + "items": { + "$ref": "#/definitions/ConceptDescription" + }, + "minItems": 1 + } + } + }, + "EventElement": { + "$ref": "#/definitions/SubmodelElement" + }, + "EventPayload": { + "type": "object", + "properties": { + "source": { + "$ref": "#/definitions/Reference" + }, + "sourceSemanticId": { + "$ref": "#/definitions/Reference" + }, + "observableReference": { + "$ref": "#/definitions/Reference" + }, + "observableSemanticId": { + "$ref": "#/definitions/Reference" + }, + "topic": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "subjectId": { + "$ref": "#/definitions/Reference" + }, + "timeStamp": { + "type": "string", + "pattern": "^-?(([1-9][0-9][0-9][0-9]+)|(0[0-9][0-9][0-9]))-((0[1-9])|(1[0-2]))-((0[1-9])|([12][0-9])|(3[01]))T(((([01][0-9])|(2[0-3])):[0-5][0-9]:([0-5][0-9])(\\.[0-9]+)?)|24:00:00(\\.0+)?)(Z|\\+00:00|-00:00)$" + }, + "payload": { + "type": "string", + "contentEncoding": "base64" + } + }, + "required": [ + "source", + "observableReference", + "timeStamp" + ] + }, + "Extension": { + "allOf": [ + { + "$ref": "#/definitions/HasSemantics" + }, + { + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "valueType": { + "$ref": "#/definitions/DataTypeDefXsd" + }, + "value": { + "type": "string" + }, + "refersTo": { + "type": "array", + "items": { + "$ref": "#/definitions/Reference" + }, + "minItems": 1 + } + }, + "required": [ + "name" + ] + } + ] + }, + "File": { + "allOf": [ + { + "$ref": "#/definitions/DataElement" + }, + { + "properties": { + "value": { + "type": "string", + "allOf": [ + { + "minLength": 1, + "maxLength": 2000 + }, + { + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + { + "pattern": "^file:(//((localhost|(\\[((([0-9A-Fa-f]{1,4}:){6}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|::([0-9A-Fa-f]{1,4}:){5}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|([0-9A-Fa-f]{1,4})?::([0-9A-Fa-f]{1,4}:){4}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})?::([0-9A-Fa-f]{1,4}:){3}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:){2}[0-9A-Fa-f]{1,4})?::([0-9A-Fa-f]{1,4}:){2}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:){3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:){4}[0-9A-Fa-f]{1,4})?::([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:){5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(([0-9A-Fa-f]{1,4}:){6}[0-9A-Fa-f]{1,4})?::)|[vV][0-9A-Fa-f]+\\.([a-zA-Z0-9\\-._~]|[!$&'()*+,;=]|:)+)\\]|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=])*)))?/((([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=]|[:@]))+(/(([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=]|[:@]))*)*)?|/((([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=]|[:@]))+(/(([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=]|[:@]))*)*)?)$" + } + ] + }, + "contentType": { + "type": "string", + "allOf": [ + { + "minLength": 1, + "maxLength": 100 + }, + { + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + { + "pattern": "^([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+/([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+([ \\t]*;[ \\t]*([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+=(([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+|\"(([\\t !#-\\[\\]-~]|[\u0080-\u00ff])|\\\\([\\t !-~]|[\u0080-\u00ff]))*\"))*$" + } + ] + }, + "modelType": { + "const": "File" + } + }, + "required": [ + "contentType" + ] + } + ] + }, + "HasDataSpecification": { + "type": "object", + "properties": { + "embeddedDataSpecifications": { + "type": "array", + "items": { + "$ref": "#/definitions/EmbeddedDataSpecification" + }, + "minItems": 1 + } + } + }, + "HasExtensions": { + "type": "object", + "properties": { + "extensions": { + "type": "array", + "items": { + "$ref": "#/definitions/Extension" + }, + "minItems": 1 + } + } + }, + "HasKind": { + "type": "object", + "properties": { + "kind": { + "$ref": "#/definitions/ModellingKind" + } + } + }, + "HasSemantics": { + "type": "object", + "properties": { + "semanticId": { + "$ref": "#/definitions/Reference" + }, + "supplementalSemanticIds": { + "type": "array", + "items": { + "$ref": "#/definitions/Reference" + }, + "minItems": 1 + } + } + }, + "Identifiable": { + "allOf": [ + { + "$ref": "#/definitions/Referable" + }, + { + "properties": { + "administration": { + "$ref": "#/definitions/AdministrativeInformation" + }, + "id": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + } + }, + "required": [ + "id" + ] + } + ] + }, + "Key": { + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/KeyTypes" + }, + "value": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + } + }, + "required": [ + "type", + "value" + ] + }, + "KeyTypes": { + "type": "string", + "enum": [ + "AnnotatedRelationshipElement", + "AssetAdministrationShell", + "BasicEventElement", + "Blob", + "Capability", + "ConceptDescription", + "DataElement", + "Entity", + "EventElement", + "File", + "FragmentReference", + "GlobalReference", + "Identifiable", + "MultiLanguageProperty", + "Operation", + "Property", + "Range", + "Referable", + "ReferenceElement", + "RelationshipElement", + "Submodel", + "SubmodelElement", + "SubmodelElementCollection", + "SubmodelElementList" + ] + }, + "LangStringDefinitionTypeIec61360": { + "allOf": [ + { + "$ref": "#/definitions/AbstractLangString" + }, + { + "properties": { + "text": { + "maxLength": 1023 + } + } + } + ] + }, + "LangStringNameType": { + "allOf": [ + { + "$ref": "#/definitions/AbstractLangString" + }, + { + "properties": { + "text": { + "maxLength": 128 + } + } + } + ] + }, + "LangStringPreferredNameTypeIec61360": { + "allOf": [ + { + "$ref": "#/definitions/AbstractLangString" + }, + { + "properties": { + "text": { + "maxLength": 255 + } + } + } + ] + }, + "LangStringShortNameTypeIec61360": { + "allOf": [ + { + "$ref": "#/definitions/AbstractLangString" + }, + { + "properties": { + "text": { + "maxLength": 18 + } + } + } + ] + }, + "LangStringTextType": { + "allOf": [ + { + "$ref": "#/definitions/AbstractLangString" + }, + { + "properties": { + "text": { + "maxLength": 1023 + } + } + } + ] + }, + "LevelType": { + "type": "object", + "properties": { + "min": { + "type": "boolean" + }, + "nom": { + "type": "boolean" + }, + "typ": { + "type": "boolean" + }, + "max": { + "type": "boolean" + } + }, + "required": [ + "min", + "nom", + "typ", + "max" + ] + }, + "ModelType": { + "type": "string", + "enum": [ + "AnnotatedRelationshipElement", + "AssetAdministrationShell", + "BasicEventElement", + "Blob", + "Capability", + "ConceptDescription", + "DataSpecificationIec61360", + "Entity", + "File", + "MultiLanguageProperty", + "Operation", + "Property", + "Range", + "ReferenceElement", + "RelationshipElement", + "Submodel", + "SubmodelElementCollection", + "SubmodelElementList" + ] + }, + "ModellingKind": { + "type": "string", + "enum": [ + "Instance", + "Template" + ] + }, + "MultiLanguageProperty": { + "allOf": [ + { + "$ref": "#/definitions/DataElement" + }, + { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/LangStringTextType" + }, + "minItems": 1 + }, + "valueId": { + "$ref": "#/definitions/Reference" + }, + "modelType": { + "const": "MultiLanguageProperty" + } + } + } + ] + }, + "Operation": { + "allOf": [ + { + "$ref": "#/definitions/SubmodelElement" + }, + { + "properties": { + "inputVariables": { + "type": "array", + "items": { + "$ref": "#/definitions/OperationVariable" + }, + "minItems": 1 + }, + "outputVariables": { + "type": "array", + "items": { + "$ref": "#/definitions/OperationVariable" + }, + "minItems": 1 + }, + "inoutputVariables": { + "type": "array", + "items": { + "$ref": "#/definitions/OperationVariable" + }, + "minItems": 1 + }, + "modelType": { + "const": "Operation" + } + } + } + ] + }, + "OperationVariable": { + "type": "object", + "properties": { + "value": { + "$ref": "#/definitions/SubmodelElement_choice" + } + }, + "required": [ + "value" + ] + }, + "Property": { + "allOf": [ + { + "$ref": "#/definitions/DataElement" + }, + { + "properties": { + "valueType": { + "$ref": "#/definitions/DataTypeDefXsd" + }, + "value": { + "type": "string" + }, + "valueId": { + "$ref": "#/definitions/Reference" + }, + "modelType": { + "const": "Property" + } + }, + "required": [ + "valueType" + ] + } + ] + }, + "Qualifiable": { + "type": "object", + "properties": { + "qualifiers": { + "type": "array", + "items": { + "$ref": "#/definitions/Qualifier" + }, + "minItems": 1 + }, + "modelType": { + "$ref": "#/definitions/ModelType" + } + }, + "required": [ + "modelType" + ] + }, + "Qualifier": { + "allOf": [ + { + "$ref": "#/definitions/HasSemantics" + }, + { + "properties": { + "kind": { + "$ref": "#/definitions/QualifierKind" + }, + "type": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "valueType": { + "$ref": "#/definitions/DataTypeDefXsd" + }, + "value": { + "type": "string" + }, + "valueId": { + "$ref": "#/definitions/Reference" + } + }, + "required": [ + "type", + "valueType" + ] + } + ] + }, + "QualifierKind": { + "type": "string", + "enum": [ + "ConceptQualifier", + "TemplateQualifier", + "ValueQualifier" + ] + }, + "Range": { + "allOf": [ + { + "$ref": "#/definitions/DataElement" + }, + { + "properties": { + "valueType": { + "$ref": "#/definitions/DataTypeDefXsd" + }, + "min": { + "type": "string" + }, + "max": { + "type": "string" + }, + "modelType": { + "const": "Range" + } + }, + "required": [ + "valueType" + ] + } + ] + }, + "Referable": { + "allOf": [ + { + "$ref": "#/definitions/HasExtensions" + }, + { + "properties": { + "category": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "idShort": { + "type": "string", + "allOf": [ + { + "minLength": 1, + "maxLength": 128 + }, + { + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + { + "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$" + } + ] + }, + "displayName": { + "type": "array", + "items": { + "$ref": "#/definitions/LangStringNameType" + }, + "minItems": 1 + }, + "description": { + "type": "array", + "items": { + "$ref": "#/definitions/LangStringTextType" + }, + "minItems": 1 + }, + "modelType": { + "$ref": "#/definitions/ModelType" + } + }, + "required": [ + "modelType" + ] + } + ] + }, + "Reference": { + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/ReferenceTypes" + }, + "referredSemanticId": { + "$ref": "#/definitions/Reference" + }, + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/Key" + }, + "minItems": 1 + } + }, + "required": [ + "type", + "keys" + ] + }, + "ReferenceElement": { + "allOf": [ + { + "$ref": "#/definitions/DataElement" + }, + { + "properties": { + "value": { + "$ref": "#/definitions/Reference" + }, + "modelType": { + "const": "ReferenceElement" + } + } + } + ] + }, + "ReferenceTypes": { + "type": "string", + "enum": [ + "ExternalReference", + "ModelReference" + ] + }, + "RelationshipElement": { + "allOf": [ + { + "$ref": "#/definitions/RelationshipElement_abstract" + }, + { + "properties": { + "modelType": { + "const": "RelationshipElement" + } + } + } + ] + }, + "RelationshipElement_abstract": { + "allOf": [ + { + "$ref": "#/definitions/SubmodelElement" + }, + { + "properties": { + "first": { + "$ref": "#/definitions/Reference" + }, + "second": { + "$ref": "#/definitions/Reference" + } + }, + "required": [ + "first", + "second" + ] + } + ] + }, + "RelationshipElement_choice": { + "oneOf": [ + { + "$ref": "#/definitions/RelationshipElement" + }, + { + "$ref": "#/definitions/AnnotatedRelationshipElement" + } + ] + }, + "Resource": { + "type": "object", + "properties": { + "path": { + "type": "string", + "allOf": [ + { + "minLength": 1, + "maxLength": 2000 + }, + { + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + { + "pattern": "^file:(//((localhost|(\\[((([0-9A-Fa-f]{1,4}:){6}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|::([0-9A-Fa-f]{1,4}:){5}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|([0-9A-Fa-f]{1,4})?::([0-9A-Fa-f]{1,4}:){4}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})?::([0-9A-Fa-f]{1,4}:){3}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:){2}[0-9A-Fa-f]{1,4})?::([0-9A-Fa-f]{1,4}:){2}([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:){3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:){4}[0-9A-Fa-f]{1,4})?::([0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(([0-9A-Fa-f]{1,4}:){5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(([0-9A-Fa-f]{1,4}:){6}[0-9A-Fa-f]{1,4})?::)|[vV][0-9A-Fa-f]+\\.([a-zA-Z0-9\\-._~]|[!$&'()*+,;=]|:)+)\\]|([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])|([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=])*)))?/((([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=]|[:@]))+(/(([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=]|[:@]))*)*)?|/((([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=]|[:@]))+(/(([a-zA-Z0-9\\-._~]|%[0-9A-Fa-f][0-9A-Fa-f]|[!$&'()*+,;=]|[:@]))*)*)?)$" + } + ] + }, + "contentType": { + "type": "string", + "allOf": [ + { + "minLength": 1, + "maxLength": 100 + }, + { + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + { + "pattern": "^([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+/([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+([ \\t]*;[ \\t]*([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+=(([!#$%&'*+\\-.^_`|~0-9a-zA-Z])+|\"(([\\t !#-\\[\\]-~]|[\u0080-\u00ff])|\\\\([\\t !-~]|[\u0080-\u00ff]))*\"))*$" + } + ] + } + }, + "required": [ + "path" + ] + }, + "SpecificAssetId": { + "allOf": [ + { + "$ref": "#/definitions/HasSemantics" + }, + { + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 64, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "value": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "externalSubjectId": { + "$ref": "#/definitions/Reference" + } + }, + "required": [ + "name", + "value" + ] + } + ] + }, + "StateOfEvent": { + "type": "string", + "enum": [ + "off", + "on" + ] + }, + "Submodel": { + "allOf": [ + { + "$ref": "#/definitions/Identifiable" + }, + { + "$ref": "#/definitions/HasKind" + }, + { + "$ref": "#/definitions/HasSemantics" + }, + { + "$ref": "#/definitions/Qualifiable" + }, + { + "$ref": "#/definitions/HasDataSpecification" + }, + { + "properties": { + "submodelElements": { + "type": "array", + "items": { + "$ref": "#/definitions/SubmodelElement_choice" + }, + "minItems": 1 + }, + "modelType": { + "const": "Submodel" + } + } + } + ] + }, + "SubmodelElement": { + "allOf": [ + { + "$ref": "#/definitions/Referable" + }, + { + "$ref": "#/definitions/HasSemantics" + }, + { + "$ref": "#/definitions/Qualifiable" + }, + { + "$ref": "#/definitions/HasDataSpecification" + } + ] + }, + "SubmodelElementCollection": { + "allOf": [ + { + "$ref": "#/definitions/SubmodelElement" + }, + { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/SubmodelElement_choice" + }, + "minItems": 1 + }, + "modelType": { + "const": "SubmodelElementCollection" + } + } + } + ] + }, + "SubmodelElementList": { + "allOf": [ + { + "$ref": "#/definitions/SubmodelElement" + }, + { + "properties": { + "orderRelevant": { + "type": "boolean" + }, + "semanticIdListElement": { + "$ref": "#/definitions/Reference" + }, + "typeValueListElement": { + "$ref": "#/definitions/AasSubmodelElements" + }, + "valueTypeListElement": { + "$ref": "#/definitions/DataTypeDefXsd" + }, + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/SubmodelElement_choice" + }, + "minItems": 1 + }, + "modelType": { + "const": "SubmodelElementList" + } + }, + "required": [ + "typeValueListElement" + ] + } + ] + }, + "SubmodelElement_choice": { + "oneOf": [ + { + "$ref": "#/definitions/RelationshipElement" + }, + { + "$ref": "#/definitions/AnnotatedRelationshipElement" + }, + { + "$ref": "#/definitions/BasicEventElement" + }, + { + "$ref": "#/definitions/Blob" + }, + { + "$ref": "#/definitions/Capability" + }, + { + "$ref": "#/definitions/Entity" + }, + { + "$ref": "#/definitions/File" + }, + { + "$ref": "#/definitions/MultiLanguageProperty" + }, + { + "$ref": "#/definitions/Operation" + }, + { + "$ref": "#/definitions/Property" + }, + { + "$ref": "#/definitions/Range" + }, + { + "$ref": "#/definitions/ReferenceElement" + }, + { + "$ref": "#/definitions/SubmodelElementCollection" + }, + { + "$ref": "#/definitions/SubmodelElementList" + } + ] + }, + "ValueList": { + "type": "object", + "properties": { + "valueReferencePairs": { + "type": "array", + "items": { + "$ref": "#/definitions/ValueReferencePair" + }, + "minItems": 1 + } + }, + "required": [ + "valueReferencePairs" + ] + }, + "ValueReferencePair": { + "type": "object", + "properties": { + "value": { + "type": "string", + "minLength": 1, + "maxLength": 2000, + "pattern": "^([\\t\\n\\r -\ud7ff\ue000-\ufffd]|\\ud800[\\udc00-\\udfff]|[\\ud801-\\udbfe][\\udc00-\\udfff]|\\udbff[\\udc00-\\udfff])*$" + }, + "valueId": { + "$ref": "#/definitions/Reference" + } + }, + "required": [ + "value", + "valueId" + ] + } + } +} \ No newline at end of file