@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix gs1: <https://ref.gs1.org/voc/> .
@prefix schema: <https://schema.org/> .
@prefix oec: <https://ref.openepcis.io/extensions/common/core/> .
@prefix dpp-sh: <https://ref.openepcis.io/extensions/common/core/shapes/> .
@prefix dcterms: <http://purl.org/dc/terms/> .

# =============================================================================
# SHACL Shapes for OpenEPCIS DPP Core Vocabulary
# Version: 0.9.6
# =============================================================================

<https://ref.openepcis.io/extensions/common/core/shapes/>
    a sh:ShapesGraph ;
    dcterms:title "OpenEPCIS DPP Core SHACL Shapes"@en ;
    dcterms:description "SHACL validation shapes for OpenEPCIS DPP Core vocabulary. Validates value ranges, required properties, and cardinality constraints."@en ;
    dcterms:created "2025-02-02"^^xsd:date ;
    dcterms:modified "2026-06-07"^^xsd:date ;
    sh:declare [ sh:prefix "dpp" ; sh:namespace "https://ref.openepcis.io/extensions/common/core/"^^xsd:anyURI ] ;
    sh:declare [ sh:prefix "oec" ; sh:namespace "https://ref.openepcis.io/extensions/common/core/"^^xsd:anyURI ] ;
    sh:declare [ sh:prefix "gs1" ; sh:namespace "https://ref.gs1.org/voc/"^^xsd:anyURI ] .

# =============================================================================
# CircularityPerformance Shape
# =============================================================================

dpp-sh:CircularityPerformanceShape
    a sh:NodeShape ;
    sh:targetClass oec:CircularityPerformance ;
    sh:name "Circularity Performance Shape"@en ;
    sh:description "Validates CircularityPerformance instances"@en ;

    sh:property [
        sh:path oec:recyclableContent ;
        sh:name "recyclableContent"@en ;
        sh:description "Fraction of product that can be recycled (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "recyclableContent must be a decimal between 0 and 1"@en
    ] ;

    sh:property [
        sh:path oec:utilityFactor ;
        sh:name "utilityFactor"@en ;
        sh:description "Durability relative to industry average (typically 0.5-2.0)"@en ;
        sh:datatype xsd:decimal ;
        sh:minExclusive 0 ;
        sh:maxCount 1 ;
        sh:message "utilityFactor must be a positive decimal"@en
    ] ;

    sh:property [
        sh:path oec:materialCircularityIndicator ;
        sh:name "materialCircularityIndicator"@en ;
        sh:description "Overall MCI score (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "materialCircularityIndicator must be a decimal between 0 and 1"@en
    ] ;

    sh:property [
        sh:path oec:endOfLifeInstructions ;
        sh:name "endOfLifeInstructions"@en ;
        sh:nodeKind sh:IRI ;
        sh:maxCount 1
    ] ;

    sh:property [
        sh:path oec:wastePreventionInfo ;
        sh:name "wastePreventionInfo"@en ;
        sh:nodeKind sh:IRI ;
        sh:maxCount 1
    ] ;

    sh:property [
        sh:path oec:separateCollectionInfo ;
        sh:name "separateCollectionInfo"@en ;
        sh:nodeKind sh:IRI ;
        sh:maxCount 1
    ] .

# =============================================================================
# RecycledContent Shape
# =============================================================================

dpp-sh:RecycledContentShape
    a sh:NodeShape ;
    sh:targetClass oec:RecycledContent ;
    sh:name "Recycled Content Shape"@en ;
    sh:description "Validates RecycledContent instances"@en ;

    sh:property [
        sh:path oec:recycledContent ;
        sh:name "recycledContent"@en ;
        sh:description "Total fraction of recycled content (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "recycledContent must be a decimal between 0 and 1"@en
    ] ;

    sh:property [
        sh:path oec:preConsumerRecycledContent ;
        sh:name "preConsumerRecycledContent"@en ;
        sh:description "Fraction of pre-consumer recycled content (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "preConsumerRecycledContent must be a decimal between 0 and 1"@en
    ] ;

    sh:property [
        sh:path oec:postConsumerRecycledContent ;
        sh:name "postConsumerRecycledContent"@en ;
        sh:description "Fraction of post-consumer recycled content (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "postConsumerRecycledContent must be a decimal between 0 and 1"@en
    ] .

# =============================================================================
# MaterialComposition Shape
# =============================================================================

dpp-sh:MaterialCompositionShape
    a sh:NodeShape ;
    sh:targetClass oec:MaterialComposition ;
    sh:name "Material Composition Shape"@en ;
    sh:description "Validates MaterialComposition instances"@en ;

    sh:property [
        sh:path schema:name ;
        sh:name "materialName"@en ;
        sh:description "Name of the material"@en ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "materialName is required and must be a string"@en
    ] ;

    sh:property [
        sh:path oec:massFraction ;
        sh:name "massFraction"@en ;
        sh:description "Mass fraction of this material (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "massFraction must be a decimal between 0 and 1"@en
    ] ;

    sh:property [
        sh:path gs1:countryOfOrigin ;
        sh:name "sourceCountry"@en ;
        sh:description "Country of origin (ISO 3166-1 alpha-2)"@en ;
        sh:datatype xsd:string ;
        sh:pattern "^[A-Z]{2}$" ;
        sh:message "sourceCountry must be a 2-letter ISO country code (e.g., DE, FR, US)"@en
    ] ;

    sh:property [
        sh:path oec:isCriticalRawMaterial ;
        sh:name "isCriticalRawMaterial"@en ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;

    sh:property [
        sh:path oec:casNumber ;
        sh:name "casNumber"@en ;
        sh:description "CAS Registry Number"@en ;
        sh:datatype xsd:string ;
        sh:pattern "^[0-9]{2,7}-[0-9]{2}-[0-9]$" ;
        sh:message "casNumber must be in CAS format (e.g., 7440-50-8)"@en
    ] .

# =============================================================================
# EmissionsPerformance Shape
# =============================================================================

dpp-sh:EmissionsPerformanceShape
    a sh:NodeShape ;
    sh:targetClass oec:EmissionsPerformance ;
    sh:name "Emissions Performance Shape"@en ;
    sh:description "Validates EmissionsPerformance instances"@en ;

    sh:property [
        sh:path oec:carbonFootprintTotal ;
        sh:name "carbonFootprintTotal"@en ;
        sh:description "Total carbon footprint in kg CO2e"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxCount 1 ;
        sh:message "carbonFootprintTotal must be a non-negative decimal"@en
    ] ;

    sh:property [
        sh:path oec:declaredUnit ;
        sh:name "declaredUnit"@en ;
        sh:description "Functional unit for the measurement"@en ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;

    sh:property [
        sh:path oec:operationalScope ;
        sh:name "operationalScope"@en ;
        sh:description "Lifecycle boundary"@en ;
        sh:in ( oec:CradleToGate oec:CradleToGrave ) ;
        sh:maxCount 1 ;
        sh:message "operationalScope must be CradleToGate or CradleToGrave"@en
    ] ;

    sh:property [
        sh:path oec:primarySourcedRatio ;
        sh:name "primarySourcedRatio"@en ;
        sh:description "Fraction from direct measurement (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "primarySourcedRatio must be a decimal between 0 and 1"@en
    ] .

# =============================================================================
# TraceabilityPerformance Shape
# =============================================================================

dpp-sh:TraceabilityPerformanceShape
    a sh:NodeShape ;
    sh:targetClass oec:TraceabilityPerformance ;
    sh:name "Traceability Performance Shape"@en ;
    sh:description "Validates TraceabilityPerformance instances"@en ;

    sh:property [
        sh:path oec:verifiedRatio ;
        sh:name "verifiedRatio"@en ;
        sh:description "Fraction of materials verifiably traced (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "verifiedRatio must be a decimal between 0 and 1"@en
    ] .

# =============================================================================
# OperatorInformation Shape
# =============================================================================

dpp-sh:OperatorInformationShape
    a sh:NodeShape ;
    sh:targetClass oec:OperatorInformation ;
    sh:name "Operator Information Shape"@en ;
    sh:description "Validates OperatorInformation instances"@en ;

    sh:property [
        sh:path oec:operatorRole ;
        sh:name "operatorRole"@en ;
        sh:description "Role of the economic operator"@en ;
        sh:in (
            oec:Manufacturer
            oec:Importer
            oec:Distributor
            oec:Processor
            oec:Trader
            oec:AuthorisedRepresentative
            oec:FulfilmentServiceProvider
        ) ;
        sh:minCount 1 ;
        sh:message "operatorRole is required and must be a valid OperatorRole"@en
    ] ;

    sh:property [
        sh:path gs1:globalLocationNumber ;
        sh:name "gln"@en ;
        sh:description "Operator GLN (Global Location Number)"@en ;
        sh:datatype xsd:string ;
        sh:pattern "^[0-9]{13}$" ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "gln must be a 13-digit GLN"@en
    ] ;

    sh:property [
        sh:path oec:economicOperatorId ;
        sh:name "economicOperatorId"@en ;
        sh:description "EU EOID per ESPR Article 77"@en ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;

    sh:property [
        sh:path oec:eoriNumber ;
        sh:name "eoriNumber"@en ;
        sh:description "EORI number for customs"@en ;
        sh:datatype xsd:string ;
        sh:pattern "^[A-Z]{2}[A-Z0-9]{1,15}$" ;
        sh:message "eoriNumber must be in EORI format (e.g., DE123456789012345)"@en
    ] ;

    sh:property [
        sh:path schema:vatID ;
        sh:name "vatIdentificationNumber"@en ;
        sh:description "VAT identification number"@en ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] .

# =============================================================================
# FacilityInformation Shape
# =============================================================================

dpp-sh:FacilityInformationShape
    a sh:NodeShape ;
    sh:targetClass oec:FacilityInformation ;
    sh:name "Facility Information Shape"@en ;
    sh:description "Validates FacilityInformation instances"@en ;

    sh:property [
        sh:path gs1:globalLocationNumber ;
        sh:name "gln"@en ;
        sh:description "Facility GLN (Global Location Number)"@en ;
        sh:datatype xsd:string ;
        sh:pattern "^[0-9]{13}$" ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "gln must be a 13-digit GLN"@en
    ] ;

    sh:property [
        sh:path schema:name ;
        sh:name "name"@en ;
        sh:description "Official facility name (inherited from gs1:Place)"@en ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "name is required"@en
    ] ;

    sh:property [
        sh:path oec:facilityType ;
        sh:name "facilityType"@en ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] .

# =============================================================================
# SubstanceOfConcern Shape
# =============================================================================

dpp-sh:SubstanceOfConcernShape
    a sh:NodeShape ;
    sh:targetClass oec:SubstanceOfConcern ;
    sh:name "Substance of Concern Shape"@en ;
    sh:description "Validates SubstanceOfConcern instances"@en ;

    sh:property [
        sh:path schema:name ;
        sh:name "substanceName"@en ;
        sh:description "Name of the hazardous substance"@en ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "substanceName is required"@en
    ] ;

    sh:property [
        sh:path oec:casNumber ;
        sh:name "casNumber"@en ;
        sh:description "CAS Registry Number"@en ;
        sh:datatype xsd:string ;
        sh:pattern "^[0-9]{2,7}-[0-9]{2}-[0-9]$" ;
        sh:message "casNumber must be in CAS format (e.g., 7440-50-8)"@en
    ] ;

    sh:property [
        sh:path oec:ecNumber ;
        sh:name "ecNumber"@en ;
        sh:description "EC Number (EINECS/ELINCS)"@en ;
        sh:datatype xsd:string ;
        sh:pattern "^[0-9]{3}-[0-9]{3}-[0-9]$" ;
        sh:message "ecNumber must be in EC format (e.g., 231-111-4)"@en
    ] ;

    sh:property [
        sh:path oec:concentration ;
        sh:name "concentration"@en ;
        sh:description "Concentration as fraction (0-1)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 1 ;
        sh:maxCount 1 ;
        sh:message "concentration must be a decimal between 0 and 1"@en
    ] ;

    sh:property [
        sh:path oec:scipId ;
        sh:name "scipId"@en ;
        sh:description "ECHA SCIP database identifier"@en ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;

    sh:property [
        sh:path oec:hazardClass ;
        sh:name "hazardClass"@en ;
        sh:in (
            oec:AcuteToxicity
            oec:SkinCorrosionOrIrritation
            oec:EyeDamageOrIrritation
            oec:RespiratoryOrSkinSensitization
            oec:GermCellMutagenicity
            oec:Carcinogenicity
            oec:ReproductiveToxicity
            oec:SpecificTargetOrganToxicity
            oec:AspirationHazard
            oec:HazardousToAquaticEnvironment
        ) ;
        sh:message "hazardClass must be a valid HazardClass"@en
    ] .

# =============================================================================
# AccessRights Shape
# =============================================================================

dpp-sh:AccessRightsShape
    a sh:NodeShape ;
    sh:targetClass oec:AccessRights ;
    sh:name "Access Rights Shape"@en ;
    sh:description "Validates AccessRights instances"@en ;

    sh:property [
        sh:path oec:accessLevel ;
        sh:name "accessLevel"@en ;
        sh:description "ESPR Article 9 access level"@en ;
        sh:in ( oec:Public oec:AuthorizedOnly oec:Restricted ) ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "accessLevel is required and must be Public, AuthorizedOnly, or Restricted"@en
    ] .

# =============================================================================
# RepairabilityInfo Shape
# =============================================================================

dpp-sh:RepairabilityInfoShape
    a sh:NodeShape ;
    sh:targetClass oec:RepairabilityInfo ;
    sh:name "Repairability Information Shape"@en ;
    sh:description "Validates RepairabilityInfo instances"@en ;

    sh:property [
        sh:path oec:repairabilityScore ;
        sh:name "repairabilityScore"@en ;
        sh:description "Repairability score (typically 0-10)"@en ;
        sh:datatype xsd:decimal ;
        sh:minInclusive 0 ;
        sh:maxInclusive 10 ;
        sh:maxCount 1 ;
        sh:message "repairabilityScore must be between 0 and 10"@en
    ] ;

    sh:property [
        sh:path oec:repairabilityClass ;
        sh:name "repairabilityClass"@en ;
        sh:description "Repairability class (A-E)"@en ;
        sh:datatype xsd:string ;
        sh:pattern "^[A-E]$" ;
        sh:maxCount 1 ;
        sh:message "repairabilityClass must be A, B, C, D, or E"@en
    ] ;

    sh:property [
        sh:path oec:diyRepairPossible ;
        sh:name "diyRepairPossible"@en ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;

    sh:property [
        sh:path oec:professionalRepairNetwork ;
        sh:name "professionalRepairNetwork"@en ;
        sh:nodeKind sh:IRI ;
        sh:maxCount 1
    ] .

# =============================================================================
# PerformanceInfo Shape
# =============================================================================

dpp-sh:PerformanceInfoShape
    a sh:NodeShape ;
    sh:targetClass oec:PerformanceInfo ;
    sh:name "Performance Information Shape"@en ;
    sh:description "Validates PerformanceInfo instances"@en ;

    sh:property [
        sh:path oec:usageCycles ;
        sh:name "usageCycles"@en ;
        sh:description "Expected number of usage cycles"@en ;
        sh:datatype xsd:integer ;
        sh:minInclusive 0 ;
        sh:maxCount 1 ;
        sh:message "usageCycles must be a non-negative integer"@en
    ] ;

    sh:property [
        sh:path oec:performanceClass ;
        sh:name "performanceClass"@en ;
        sh:description "Performance/efficiency class (e.g., A+++ to G)"@en ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] .

# =============================================================================
# GranularityLevel Constraint
# =============================================================================

dpp-sh:GranularityLevelConstraint
    a sh:NodeShape ;
    sh:name "Granularity Level Constraint"@en ;
    sh:property [
        sh:path oec:granularityLevel ;
        sh:datatype xsd:string ;
        sh:in ( "model" "batch" "item" ) ;
        sh:maxCount 1 ;
        sh:message "granularity must be model, batch, or item (EN 18223)"@en
    ] .

# =============================================================================
# DigitalProductPassport: granularity must match the GS1 Digital Link AIs
# (EN 18219 4.4 consistency; EN 18223 granularity). 01 -> model,
# 01+10 -> batch, 01+21 -> item. Applies when uniqueProductIdentifier
# (gs1:productID) is a GS1 Digital Link URI.
# =============================================================================

dpp-sh:GranularityDigitalLinkConstraint
    a sh:NodeShape ;
    sh:targetClass oec:DigitalProductPassport ;
    sh:sparql [
        a sh:SPARQLConstraint ;
        sh:message "granularity must match the GS1 Digital Link Application Identifiers in uniqueProductIdentifier (01 -> model, 01+10 -> batch, 01+21 -> item) per EN 18219 4.4 / EN 18223."@en ;
        sh:prefixes <https://ref.openepcis.io/extensions/common/core/shapes/> ;
        sh:select """
            SELECT $this ?value WHERE {
                $this oec:granularityLevel ?value .
                $this gs1:productID ?dl .
                BIND( IF(REGEX(STR(?dl), "/21/"), "item",
                       IF(REGEX(STR(?dl), "/10/"), "batch", "model")) AS ?expected )
                FILTER( STR(?value) != ?expected )
            }
        """ ;
    ] .

# =============================================================================
# QuantitativeValue Shapes (GS1-idiomatic value + unitCode pattern)
# =============================================================================
# Every QuantitativeValue node must have a numeric `gs1:value` and a
# `gs1:unitCode` (UN/CEFACT Rec 20). Per-property NodeShapes pin the code.

dpp-sh:QuantitativeValueShape
    a sh:NodeShape ;
    sh:targetClass gs1:QuantitativeValue ;
    sh:name "QuantitativeValue Shape"@en ;
    sh:description "Every QuantitativeValue must have gs1:value and gs1:unitCode (UN/CEFACT Rec 20)."@en ;
    sh:property [
        sh:path gs1:value ;
        sh:datatype xsd:decimal ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "QuantitativeValue must have exactly one xsd:decimal gs1:value"@en
    ] ;
    sh:property [
        sh:path gs1:unitCode ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "QuantitativeValue must have exactly one gs1:unitCode (UN/CEFACT Rec 20 string)"@en
    ] .

# Per-property unitCode shapes (representative; extend as new properties land).
# Pattern: target subjects of a property; require its value's unitCode = canonical code.

dpp-sh:ExpectedLifespanShape
    a sh:NodeShape ;
    sh:targetSubjectsOf oec:expectedLifespan ;
    sh:property [
        sh:path ( oec:expectedLifespan gs1:unitCode ) ;
        sh:hasValue "ANN" ;
        sh:message "oec:expectedLifespan must use unitCode 'ANN' (years)"@en
    ] .

dpp-sh:GuaranteedLifespanShape
    a sh:NodeShape ;
    sh:targetSubjectsOf oec:guaranteedLifespan ;
    sh:property [
        sh:path ( oec:guaranteedLifespan gs1:unitCode ) ;
        sh:hasValue "ANN" ;
        sh:message "oec:guaranteedLifespan must use unitCode 'ANN' (years)"@en
    ] .

dpp-sh:TechnicalLifetimeShape
    a sh:NodeShape ;
    sh:targetSubjectsOf oec:technicalLifetime ;
    sh:property [
        sh:path ( oec:technicalLifetime gs1:unitCode ) ;
        sh:hasValue "ANN" ;
        sh:message "oec:technicalLifetime must use unitCode 'ANN' (years)"@en
    ] .

# =============================================================================
# Cross-Cutting EU Concept Shapes (lifted)
# =============================================================================

dpp-sh:ExtendedProducerResponsibilityShape
    a sh:NodeShape ;
    sh:targetClass oec:ExtendedProducerResponsibility ;
    sh:name "Extended Producer Responsibility Shape"@en ;
    sh:property [
        sh:path oec:eprRegistrationNumber ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "ExtendedProducerResponsibility must have exactly one eprRegistrationNumber"@en
    ] ;
    sh:property [
        sh:path oec:eprJurisdiction ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "ExtendedProducerResponsibility must declare exactly one eprJurisdiction"@en
    ] ;
    sh:property [
        sh:path oec:eprComplianceUrl ;
        sh:datatype xsd:anyURI ;
        sh:maxCount 1
    ] .

dpp-sh:CompostabilityShape
    a sh:NodeShape ;
    sh:targetClass oec:Compostability ;
    sh:name "Compostability Shape"@en ;
    sh:property [
        sh:path oec:compostabilityType ;
        sh:in ( oec:IndustrialCompostable oec:HomeCompostable oec:NotCompostable ) ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "compostabilityType must be IndustrialCompostable, HomeCompostable, or NotCompostable"@en
    ] ;
    sh:property [
        sh:path oec:compostabilityStandard ;
        sh:datatype xsd:anyURI ;
        sh:maxCount 1
    ] .

dpp-sh:BiodegradabilityShape
    a sh:NodeShape ;
    sh:targetClass oec:Biodegradability ;
    sh:name "Biodegradability Shape"@en ;
    sh:property [
        sh:path oec:biodegradationPercentage ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "Biodegradability must have exactly one biodegradationPercentage"@en
    ] ;
    sh:property [
        sh:path oec:biodegradabilityTestMethod ;
        sh:in ( oec:ISO14593 oec:OECD301B oec:OECD301D oec:OECD301F oec:OECD310 ) ;
        sh:maxCount 1
    ] .

dpp-sh:DepositReturnSchemeShape
    a sh:NodeShape ;
    sh:targetClass oec:DepositReturnScheme ;
    sh:name "DepositReturnScheme Shape"@en ;
    sh:property [
        sh:path oec:depositAmount ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:message "DepositReturnScheme must declare exactly one depositAmount"@en
    ] ;
    sh:property [
        sh:path oec:depositRedemptionChannelUrl ;
        sh:datatype xsd:anyURI ;
        sh:maxCount 1
    ] .

# Pin biodegradationPercentage to unitCode 'P1' (percent fraction).
dpp-sh:BiodegradationPercentageUnitShape
    a sh:NodeShape ;
    sh:targetSubjectsOf oec:biodegradationPercentage ;
    sh:property [
        sh:path ( oec:biodegradationPercentage gs1:unitCode ) ;
        sh:hasValue "P1" ;
        sh:message "oec:biodegradationPercentage must use unitCode 'P1' (percent)"@en
    ] .
