@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix eutex: <https://ref.openepcis.io/extensions/eu/textile/> .
@prefix gs1: <https://ref.gs1.org/voc/> .
@prefix schema: <https://schema.org/> .
@prefix oec: <https://ref.openepcis.io/extensions/common/core/> .
# Reusable value shapes from the core shapes graph (dpp-sh:TranslatableText).
# Every validation type bundles dpp-core-shapes.ttl alongside this file, so the
# reference always resolves; see docs/GITB_CONFORMANCE.md.
@prefix dpp-sh: <https://ref.openepcis.io/extensions/common/core/shapes/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .

<https://ref.openepcis.io/extensions/eu/textile/shapes/>
    a sh:ShapesGraph ;
    dcterms:title "OpenEPCIS Textile SHACL Shapes"@en ;
    dcterms:description "SHACL validation shapes for Textile Digital Product Passport vocabulary."@en ;
    owl:versionInfo "0.9.9" ;
    dcterms:created "2025-02-02"^^xsd:date ;
    dcterms:modified "2026-08-10"^^xsd:date .

# =============================================================================
# OpenEPCIS Textile Vocabulary SHACL Shapes
# Validation shapes for Textile Digital Product Passport data
# Aligned with EU Sustainable Textiles Strategy, ESPR 2024/1781,
# and EU Preparatory Study on Textiles 3rd Milestone
# =============================================================================

# -----------------------------------------------------------------------------
# Textile Product Shape
# -----------------------------------------------------------------------------
eutex:TextileProductShape a sh:NodeShape ;
    sh:targetClass eutex:TextileProduct ;
    rdfs:label "Textile Product Shape" ;
    rdfs:comment "Validation shape for TextileProduct instances per EU Textile Labelling Regulation 1007/2011." ;
    # schema:category ranges over Text OR Thing in schema.org, and the corpus uses
    # both: a eutex:TextileCategory code where one fits, localized free text where
    # the marketed category has no code. Accept either, and no maxCount — three
    # translations of one category are three values.
    sh:property [
        sh:path schema:category ;
        sh:name "Textile Category" ;
        sh:description "Category of textile product (apparel, footwear, home textiles, etc.)." ;
        sh:or (
            [ sh:class eutex:TextileCategory ]
            [ sh:node dpp-sh:TranslatableText ]
        )
    ] ;
    sh:property [
        sh:path eutex:hasFabricType ;
        sh:name "Fabric Type" ;
        sh:description "Fabric construction type (knitted, denim, woven non-denim)." ;
        sh:maxCount 1 ;
        sh:class eutex:FabricType
    ] ;
    sh:property [
        sh:path eutex:hasApparelSubcategory ;
        sh:name "Apparel Subcategory" ;
        sh:maxCount 1 ;
        sh:class eutex:ApparelSubcategory
    ] ;
    sh:property [
        sh:path eutex:garmentType ;
        sh:name "Garment Type" ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    # A GS1 code-list value, i.e. a gs1:TargetConsumerGenderCode IRI, not a string.
    sh:property [
        sh:path gs1:targetConsumerGender ;
        sh:nodeKind sh:IRI ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:sizeRange ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:seasonCollection ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path gs1:textileMaterial ;
        sh:name "Fiber Composition" ;
        sh:description "GS1-native fibre composition: one gs1:TextileMaterialDetails entry per fibre." ;
        sh:class gs1:TextileMaterialDetails
    ] ;
    sh:property [
        sh:path eutex:hasCareInstructions ;
        sh:name "Care Instructions" ;
        sh:class eutex:CareInstruction
    ] ;
    sh:property [
        sh:path eutex:hasDurabilityInfo ;
        sh:name "Durability Information" ;
        sh:class eutex:DurabilityInfo
    ] ;
    sh:property [
        sh:path eutex:hasRobustnessAssessment ;
        sh:name "Robustness Assessment" ;
        sh:class eutex:RobustnessAssessment ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasRecyclabilityAssessment ;
        sh:name "Recyclability Assessment" ;
        sh:class eutex:RecyclabilityAssessment ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasRecycledContentDeclaration ;
        sh:name "Recycled Content Declaration" ;
        sh:class eutex:RecycledContentDeclaration
    ] ;
    sh:property [
        sh:path eutex:hasEnvironmentalFootprint ;
        sh:name "Environmental Footprint" ;
        sh:class eutex:EnvironmentalFootprint ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasSubstancesOfConcern ;
        sh:name "Substances of Concern" ;
        sh:class eutex:SubstanceOfConcern
    ] ;
    sh:property [
        sh:path eutex:hasMicroplasticInfo ;
        sh:name "Microplastic Information" ;
        sh:class eutex:MicroplasticInfo
    ] ;
    sh:property [
        sh:path eutex:hasTakeBackProgram ;
        sh:name "Take-Back Program" ;
        sh:class eutex:TakeBackProgram
    ] ;
    # Was a second eutex:hasTakeBackProgram block constraining the same object
    # property to xsd:boolean — a leftover of the has* rename. The boolean flag is
    # eutex:takeBackProgramAvailable.
    sh:property [
        sh:path eutex:takeBackProgramAvailable ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasRepairServices ;
        sh:name "Repair Services" ;
        sh:class gs1:Organization
    ] ;
    sh:property [
        sh:path eutex:isRepairable ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:repairGuideUrl ;
        sh:datatype xsd:anyURI ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:sparePartsAvailable ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:sparePartsUrl ;
        sh:datatype xsd:anyURI ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasTextileChemicals ;
        sh:name "Textile Chemicals" ;
        sh:class oec:HazardousSubstance
    ] ;
    sh:property [
        sh:path eutex:pfasFree ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path gs1:consumerRecyclingInstructions ;
        sh:node dpp-sh:TranslatableText
    ] ;
    sh:property [
        sh:path eutex:hasWaterUsage ;
        sh:class gs1:QuantitativeValue
    ] ;
    sh:property [
        sh:path eutex:hasEnergyUsage ;
        sh:class gs1:QuantitativeValue
    ] ;
    sh:property [
        sh:path eutex:productionWastePercentage ;
        sh:datatype xsd:decimal
    ] ;
    sh:property [
        sh:path eutex:biodegradable ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasSpinningFacility ;
        sh:class oec:FacilityInformation ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasWeavingFacility ;
        sh:class oec:FacilityInformation ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasDyeingFacility ;
        sh:class oec:FacilityInformation ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasCutAndSewFacility ;
        sh:class oec:FacilityInformation ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasFinishingFacility ;
        sh:class oec:FacilityInformation ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Fiber Composition Shape
# -----------------------------------------------------------------------------
# Fibre composition is GS1-native: gs1:textileMaterial -> gs1:TextileMaterialDetails
# carrying gs1:textileMaterialDescription + gs1:textileMaterialPercentage, with the
# textile-specific traceability fields attached inline on each entry. Targeted via
# sh:targetObjectsOf so the shape applies to textile fibre entries only, not to every
# gs1:TextileMaterialDetails node in a graph.
eutex:FiberCompositionShape a sh:NodeShape ;
    sh:targetObjectsOf gs1:textileMaterial ;
    rdfs:label "Fiber Composition Shape" ;
    sh:property [
        sh:path gs1:textileMaterialDescription ;
        sh:name "Fiber Type" ;
        sh:description "Name of the fibre (EU Textile Labelling Regulation 1007/2011 Annex I designation)." ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path gs1:textileMaterialPercentage ;
        sh:name "Fiber Percentage" ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 100
    ] ;
    sh:property [
        sh:path eutex:fiberOrigin ;
        sh:name "Fiber Origin" ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:isRecycledFiber ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:recycledContentSource ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasFiberCertification ;
        sh:class gs1:CertificationDetails
    ] .

# -----------------------------------------------------------------------------
# Care Instruction Shape
# -----------------------------------------------------------------------------
eutex:CareInstructionShape a sh:NodeShape ;
    sh:targetClass eutex:CareInstruction ;
    rdfs:label "Care Instruction Shape" ;
    sh:property [
        sh:path eutex:hasWashingSymbol ;
        sh:name "Washing Symbol" ;
        sh:class eutex:CareSymbolCode ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasBleachingSymbol ;
        sh:name "Bleaching Symbol" ;
        sh:class eutex:CareSymbolCode ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasDryingSymbol ;
        sh:name "Drying Symbol" ;
        sh:class eutex:CareSymbolCode ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasIroningSymbol ;
        sh:name "Ironing Symbol" ;
        sh:class eutex:CareSymbolCode ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasDryCleaningSymbol ;
        sh:name "Dry Cleaning Symbol" ;
        sh:class eutex:CareSymbolCode ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:additionalCareInstructions ;
        sh:node dpp-sh:TranslatableText
    ] .

# -----------------------------------------------------------------------------
# Durability Info Shape
# -----------------------------------------------------------------------------
eutex:DurabilityInfoShape a sh:NodeShape ;
    sh:targetClass eutex:DurabilityInfo ;
    rdfs:label "Durability Information Shape" ;
    sh:property [
        sh:path eutex:expectedWashCycles ;
        sh:name "Expected Wash Cycles" ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 0
    ] ;
    sh:property [
        sh:path eutex:hasDurabilityClass ;
        sh:name "Durability Class" ;
        sh:class eutex:DurabilityClass ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:pillingResistance ;
        sh:name "Pilling Resistance" ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 1 ;
        sh:maxInclusive 5
    ] ;
    sh:property [
        sh:path eutex:colorFastness ;
        sh:name "Color Fastness" ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 1 ;
        sh:maxInclusive 5
    ] ;
    sh:property [
        sh:path eutex:dimensionalStability ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:abrasionResistance ;
        sh:name "Abrasion Resistance" ;
        sh:datatype xsd:integer ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasTensileStrength ;
        sh:class gs1:QuantitativeValue
    ] ;
    sh:property [
        sh:path eutex:hasTearStrength ;
        sh:class gs1:QuantitativeValue
    ] ;
    sh:property [
        sh:path eutex:expectedLifetimeYears ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 0
    ] .

# -----------------------------------------------------------------------------
# Robustness Assessment Shape
# -----------------------------------------------------------------------------
eutex:RobustnessAssessmentShape a sh:NodeShape ;
    sh:targetClass eutex:RobustnessAssessment ;
    rdfs:label "Robustness Assessment Shape" ;
    rdfs:comment "Validation shape for the 0-10 robustness scoring system." ;
    sh:property [
        sh:path eutex:robustnessScore ;
        sh:name "Robustness Score" ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 10
    ] ;
    sh:property [
        sh:path eutex:cleaningCyclesBeforeTest ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 0
    ] ;
    sh:property [
        sh:path eutex:hasRobustnessTestFabricType ;
        sh:class eutex:FabricType ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasSpiralityTest ;
        sh:class eutex:SpiralityTestResult ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasDimensionalChangeTest ;
        sh:class eutex:DimensionalChangeTestResult ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasVisualInspection ;
        sh:class eutex:VisualInspectionResult ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Spirality Test Result Shape
# -----------------------------------------------------------------------------
eutex:SpiralityTestResultShape a sh:NodeShape ;
    sh:targetClass eutex:SpiralityTestResult ;
    rdfs:label "Spirality Test Result Shape" ;
    sh:property [
        sh:path eutex:spiralityScore ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 3
    ] ;
    sh:property [
        sh:path eutex:spiralityPercentage ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0
    ] ;
    sh:property [
        sh:path eutex:spiralityTestMethod ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasTestStandard ;
        sh:class eutex:TestStandard ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Dimensional Change Test Result Shape
# -----------------------------------------------------------------------------
eutex:DimensionalChangeTestResultShape a sh:NodeShape ;
    sh:targetClass eutex:DimensionalChangeTestResult ;
    rdfs:label "Dimensional Change Test Result Shape" ;
    sh:property [
        sh:path eutex:dimensionalChangeScore ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 3
    ] ;
    sh:property [
        sh:path eutex:dimensionalChangePercentage ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0
    ] ;
    sh:property [
        sh:path eutex:dimensionalChangeTestMethod ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasTestStandard ;
        sh:class eutex:TestStandard ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Visual Inspection Result Shape
# -----------------------------------------------------------------------------
eutex:VisualInspectionResultShape a sh:NodeShape ;
    sh:targetClass eutex:VisualInspectionResult ;
    rdfs:label "Visual Inspection Result Shape" ;
    sh:property [
        sh:path eutex:visualInspectionScore ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 4
    ] ;
    sh:property [
        sh:path eutex:colourChangeRating ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 1 ;
        sh:maxInclusive 5
    ] ;
    sh:property [
        sh:path eutex:fabricAppearanceRating ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 1 ;
        sh:maxInclusive 5
    ] ;
    sh:property [
        sh:path eutex:seamAppearanceRating ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 1 ;
        sh:maxInclusive 5
    ] ;
    sh:property [
        sh:path eutex:nonTextilePartsRating ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minInclusive 1 ;
        sh:maxInclusive 5
    ] ;
    sh:property [
        sh:path eutex:visualInspectionTestMethod ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasTestStandard ;
        sh:class eutex:TestStandard ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Recyclability Assessment Shape
# -----------------------------------------------------------------------------
eutex:RecyclabilityAssessmentShape a sh:NodeShape ;
    sh:targetClass eutex:RecyclabilityAssessment ;
    rdfs:label "Recyclability Assessment Shape" ;
    rdfs:comment "Validation shape for the 0-10 recyclability scoring system." ;
    sh:property [
        sh:path eutex:recyclabilityScore ;
        sh:name "Recyclability Score" ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 10
    ] ;
    sh:property [
        sh:path eutex:isRecyclable ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:elastaneContentPercent ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 100
    ] ;
    sh:property [
        sh:path eutex:hasSortingFactors ;
        sh:class eutex:SortingFactors ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasTechnicalRecyclability ;
        sh:class eutex:TechnicalRecyclability ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Sorting Factors Shape
# -----------------------------------------------------------------------------
eutex:SortingFactorsShape a sh:NodeShape ;
    sh:targetClass eutex:SortingFactors ;
    rdfs:label "Sorting Factors Shape" ;
    sh:property [
        sh:path eutex:sameInnerOuterComposition ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:freeFromPrintings ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:freeFromCoatings ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:freeFromSequins ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:freeFromDyes ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:isMonoMaterial ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Recycled Content Declaration Shape
# -----------------------------------------------------------------------------
eutex:RecycledContentDeclarationShape a sh:NodeShape ;
    sh:targetClass eutex:RecycledContentDeclaration ;
    rdfs:label "Recycled Content Declaration Shape" ;
    sh:property [
        sh:path eutex:secondaryMaterialFraction ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 100
    ] ;
    sh:property [
        sh:path eutex:hasWasteOriginType ;
        sh:class eutex:WasteOriginType ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasRecycledSourceType ;
        sh:class eutex:RecycledSourceType ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasChainOfCustodyMethod ;
        sh:class eutex:ChainOfCustodyMethod ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:meetsTargetThreshold ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasVerificationCertification ;
        sh:class gs1:CertificationDetails ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Environmental Footprint Shape
# -----------------------------------------------------------------------------
eutex:EnvironmentalFootprintShape a sh:NodeShape ;
    sh:targetClass eutex:EnvironmentalFootprint ;
    rdfs:label "Environmental Footprint Shape" ;
    sh:property [
        sh:path eutex:carbonFootprintManufacturing ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:pefSingleScore ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:benchmarkPerformance ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasDataTypeIndicator ;
        sh:class eutex:FootprintDataType ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:pefcrReference ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasLciaCategories ;
        sh:class eutex:LCIACategory
    ] .

# -----------------------------------------------------------------------------
# LCIA Category Shape
# -----------------------------------------------------------------------------
eutex:LCIACategoryShape a sh:NodeShape ;
    sh:targetClass eutex:LCIACategory ;
    rdfs:label "LCIA Category Shape" ;
    sh:property [
        sh:path eutex:hasLciaCategoryCode ;
        sh:class eutex:LCIACategoryCode ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:lciaValue ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:lciaUnit ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Substance of Concern Shape
# -----------------------------------------------------------------------------
eutex:SubstanceOfConcernShape a sh:NodeShape ;
    sh:targetClass eutex:SubstanceOfConcern ;
    rdfs:label "Substance of Concern Shape" ;
    sh:property [
        sh:path eutex:hasSocType ;
        sh:name "SoC Type" ;
        sh:class eutex:SubstanceOfConcernType ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path schema:name ;
        sh:node dpp-sh:TranslatableText ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path schema:iupacName ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path oec:casNumber ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:ecNumber ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:substanceConcentration ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0
    ] ;
    sh:property [
        sh:path eutex:maxConcentration ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0
    ] ;
    sh:property [
        sh:path eutex:hasClpHazardCategory ;
        sh:class eutex:CLPHazardCategory ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:concentrationRange ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path oec:substanceLocation ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:safeUseInstructions ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:endOfLifeHandling ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Microplastic Info Shape
# -----------------------------------------------------------------------------
eutex:MicroplasticInfoShape a sh:NodeShape ;
    sh:targetClass eutex:MicroplasticInfo ;
    rdfs:label "Microplastic Information Shape" ;
    sh:property [
        sh:path eutex:hasMicroplasticRiskLevel ;
        sh:name "Microplastic Risk Level" ;
        sh:class eutex:MicroplasticRiskLevel ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:hasSheddingRate ;
        sh:name "Shedding Rate" ;
        sh:class gs1:QuantitativeValue
    ] ;
    sh:property [
        sh:path eutex:syntheticFiberContent ;
        sh:datatype xsd:decimal ;
        sh:maxCount 1 ;
        sh:minInclusive 0 ;
        sh:maxInclusive 100
    ] ;
    sh:property [
        sh:path eutex:microplasticMitigationMeasures ;
        sh:node dpp-sh:TranslatableText
    ] .

# -----------------------------------------------------------------------------
# Take-Back Program Shape
# -----------------------------------------------------------------------------
eutex:TakeBackProgramShape a sh:NodeShape ;
    sh:targetClass eutex:TakeBackProgram ;
    rdfs:label "Take-Back Program Shape" ;
    sh:property [
        sh:path eutex:takeBackUrl ;
        sh:datatype xsd:anyURI ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:takeBackIncentive ;
        sh:node dpp-sh:TranslatableText
    ] ;
    sh:property [
        sh:path eutex:endOfLifeDestination ;
        sh:node dpp-sh:TranslatableText
    ] .

# -----------------------------------------------------------------------------
# Repair Service Shape
# -----------------------------------------------------------------------------
# Repair services are gs1:Organization records (see eutex:hasRepairServices range).
# Targeted via sh:targetObjectsOf so manufacturers and other organizations in the
# same graph are not caught by the repair-provider expectations.
eutex:RepairServiceShape a sh:NodeShape ;
    sh:targetObjectsOf eutex:hasRepairServices ;
    rdfs:label "Repair Service Shape" ;
    sh:property [
        sh:path gs1:organizationName ;
        sh:name "Repair Service Name" ;
        sh:minCount 1
    ] .

# -----------------------------------------------------------------------------
# Textile Chemical Shape
# -----------------------------------------------------------------------------
# Textile chemical inputs are oec:HazardousSubstance records (see the
# eutex:hasTextileChemicals range). Targeted via sh:targetObjectsOf so the
# textile-specific MRSL expectations apply to textile chemical inputs only.
eutex:TextileChemicalShape a sh:NodeShape ;
    sh:targetObjectsOf eutex:hasTextileChemicals ;
    rdfs:label "Textile Chemical Shape" ;
    sh:property [
        sh:path schema:name ;
        sh:name "Chemical Name" ;
        sh:node dpp-sh:TranslatableText ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path eutex:chemicalPurpose ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eutex:isMRSLCompliant ;
        sh:datatype xsd:boolean ;
        sh:maxCount 1
    ] .

# =============================================================================
# QuantitativeValue unitCode Shapes (GS1-idiomatic)
# =============================================================================

eutex:WaterUsageShape a sh:NodeShape ;
    sh:targetSubjectsOf eutex:hasWaterUsage ;
    sh:property [
        sh:path ( eutex:hasWaterUsage gs1:unitCode ) ;
        sh:hasValue "LTR" ;
        sh:message "eutex:hasWaterUsage must use unitCode 'LTR' (liters)"@en
    ] .

eutex:EnergyUsageShape a sh:NodeShape ;
    sh:targetSubjectsOf eutex:hasEnergyUsage ;
    sh:property [
        sh:path ( eutex:hasEnergyUsage gs1:unitCode ) ;
        sh:hasValue "KWH" ;
        sh:message "eutex:hasEnergyUsage must use unitCode 'KWH' (kilowatt-hours)"@en
    ] .

eutex:SheddingRateShape a sh:NodeShape ;
    sh:targetSubjectsOf eutex:hasSheddingRate ;
    sh:property [
        sh:path ( eutex:hasSheddingRate gs1:unitCode ) ;
        sh:hasValue "MGM" ;
        sh:message "eutex:hasSheddingRate must use unitCode 'MGM' (mg/kg)"@en
    ] .
