diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..c29e6ce
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,49 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
+
+version: 2
+updates:
+ - package-ecosystem: "nuget"
+ target-branch: "develop"
+ directory: "/source"
+ groups:
+ major-minor-patch:
+ applies-to: version-updates
+ update-types:
+ - "major"
+ - "minor"
+ - "patch"
+ schedule:
+ interval: "weekly"
+ cooldown:
+ default-days: 3
+
+ - package-ecosystem: "docker"
+ target-branch: "develop"
+ directory: "/source/AAS.TwinEngine.DataEngine"
+ groups:
+ major-minor-patch:
+ applies-to: version-updates
+ update-types:
+ - "major"
+ - "minor"
+ - "patch"
+ schedule:
+ interval: "daily"
+
+ - package-ecosystem: "github-actions"
+ target-branch: "develop"
+ directory: "/"
+ groups:
+ major-minor-patch:
+ applies-to: version-updates
+ update-types:
+ - "major"
+ - "minor"
+ - "patch"
+ schedule:
+ interval: "weekly"
+ cooldown:
+ default-days: 3
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..9c05865
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,100 @@
+name: "CodeQL Advanced"
+
+on:
+ push:
+ branches:
+ - 'main'
+ - 'develop'
+ - 'release/**'
+ - 'hotfix/**'
+ pull_request:
+ branches:
+ - 'main'
+ - 'develop'
+ - 'release/**'
+ - 'hotfix/**'
+ schedule:
+ - cron: '30 19 * * 0'
+
+permissions: read-all
+
+jobs:
+ analyze:
+ name: Analyze (${{ matrix.language }})
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
+ # - https://gh.io/supported-runners-and-hardware-resources
+ # - https://gh.io/using-larger-runners (GitHub.com only)
+ # Consider using larger runners or machines with greater resources for possible analysis time improvements.
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+ permissions:
+ # required for all workflows
+ security-events: write
+
+ # required to fetch internal or private CodeQL packs
+ packages: read
+
+ # only required for workflows in private repositories
+ actions: read
+ contents: read
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: actions
+ build-mode: none
+ - language: csharp
+ build-mode: none
+ # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
+ # Use `c-cpp` to analyze code written in C, C++ or both
+ # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
+ # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+ # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
+ # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
+ # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
+ # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ # Add any setup steps before running the `github/codeql-action/init` action.
+ # This includes steps like installing compilers or runtimes (`actions/setup-node`
+ # or others). This is typically only required for manual builds.
+ # - name: Setup runtime (example)
+ # uses: actions/setup-example@v1
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+
+ # If the analyze step fails for one of the languages you are analyzing with
+ # "We were unable to automatically build your code", modify the matrix above
+ # to set the build mode to "manual" for that language. Then modify this step
+ # to build your code.
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+ - name: Run manual build steps
+ if: matrix.build-mode == 'manual'
+ shell: bash
+ run: |
+ echo 'If you are using a "manual" build mode for one or more of the' \
+ 'languages you are analyzing, replace this with the commands to build' \
+ 'your code, for example:'
+ echo ' make bootstrap'
+ echo ' make release'
+ exit 1
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
new file mode 100644
index 0000000..c57ba33
--- /dev/null
+++ b/.github/workflows/dependency-review.yml
@@ -0,0 +1,99 @@
+# Dependency Review Action
+#
+# This Action will scan dependency manifest files that change as part of a Pull Request,
+# surfacing known-vulnerable versions of the packages declared or updated in the PR.
+# Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable
+# packages will be blocked from merging.
+#
+# Source repository: https://github.com/actions/dependency-review-action
+# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
+name: 'Dependency review'
+on:
+ pull_request:
+ branches:
+ - 'main'
+ - 'develop'
+ - 'release/**'
+ - 'hotfix/**'
+
+# If using a dependency submission action in this workflow this permission will need to be set to:
+#
+# permissions:
+# contents: write
+#
+# https://docs.github.com/en/enterprise-cloud@latest/code-security/supply-chain-security/understanding-your-software-supply-chain/using-the-dependency-submission-api
+permissions:
+ contents: read
+ # Write permissions for pull-requests are required for using the `comment-summary-in-pr` option, comment out if you aren't using this option
+ pull-requests: write
+
+jobs:
+ dependency-review:
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Checkout repository'
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - name: 'Dependency Review'
+ uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2
+ # Commonly enabled options, see https://github.com/actions/dependency-review-action#configuration-options for all available options.
+ with:
+ retry-on-snapshot-warnings: true
+ retry-on-snapshot-warnings-timeout: 60
+ warn-on-openssf-scorecard-level: 5
+ comment-summary-in-pr: always
+ allow-dependencies-licenses: |
+ pkg:nuget/AasCore.Aas3_0,
+ pkg:nuget/AasCore.Aas3.Package
+ allow-licenses: |
+ Apache-1.0,
+ Apache-1.1,
+ Apache-2.0,
+ BSL-1.0,
+ BSD-1-Clause,
+ BSD-2-Clause,
+ BSD-2-Clause-FreeBSD,
+ BSD-2-Clause-NetBSD,
+ BSD-3-Clause,
+ BSD-3-Clause-Clear,
+ BSD-3-Clause-No-Nuclear-License,
+ BSD-3-Clause-No-Nuclear-License-2014,
+ BSD-3-Clause-No-Nuclear-Warranty,
+ BSD-3-Clause-Open-MPI,
+ BSD-4-Clause,
+ BSD-Protection,
+ BSD-Source-Code,
+ BSD-3-Clause-Attribution,
+ 0BSD,
+ BSD-2-Clause-Patent,
+ BSD-4-Clause-UC,
+ MIT-CMU,
+ CC-BY-3.0,
+ CC-BY-SA-1.0,
+ CC-BY-SA-2.0,
+ CC-BY-SA-2.5,
+ CC-BY-SA-3.0,
+ CC-BY-SA-4.0,
+ CC0-1.0,
+ WTFPL,
+ MIT-enna,
+ MIT-feh,
+ ISC,
+ JSON,
+ BSD-3-Clause-LBNL,
+ MITNFA,
+ MIT,
+ MIT-0,
+ UPL-1.0,
+ NCSA,
+ X11,
+ Xerox,
+ BlueOak-1.0.0,
+ CC-BY-4.0,
+ MS-PL,
+ PostgreSQL,
+ Python-2.0,
+ SSPL-1.0,
+ OFL-1.1,
+ Unlicense,
+ Unicode-DFS-2016,
+ Unicode-3.0
diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
new file mode 100644
index 0000000..113c32f
--- /dev/null
+++ b/.github/workflows/docker-publish.yml
@@ -0,0 +1,125 @@
+name: Docker
+
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - 'develop'
+ - 'release/**'
+ - 'hotfix/**'
+ # Publish semver tags as releases.
+ tags: [ 'v**' ]
+ pull_request:
+ branches:
+ - 'main'
+ - 'develop'
+ - 'release/**'
+ - 'hotfix/**'
+
+permissions:
+ contents: read
+
+env:
+ # Use docker.io for Docker Hub if empty
+ REGISTRY: ghcr.io
+ IMAGE_NAME: ${{ github.repository_owner }}/dataengine
+ DOCKERFILE_PATH: source/AAS.TwinEngine.DataEngine/Dockerfile
+ BUILD_CONTEXT: source
+
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ # Set up BuildKit Docker container builder to be able to build
+ # multi-platform images and export cache
+ # https://github.com/docker/setup-buildx-action
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
+
+ # Login against a Docker registry except on PR
+ # https://github.com/docker/login-action
+ - name: Log into registry ${{ env.REGISTRY }}
+ if: github.event_name != 'pull_request'
+ uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ # Extract metadata (tags, labels) for Docker
+ # https://github.com/docker/metadata-action
+ - name: Extract Docker metadata
+ id: meta
+ uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
+ with:
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
+ flavor: |
+ latest=false
+ tags: |
+ type=semver,pattern={{raw}}
+ type=raw,value=develop-{{sha}},enable=${{startsWith(github.ref, 'refs/heads/develop')}}
+ type=raw,value=rc-{{branch}}-{{sha}},enable=${{startsWith(github.ref, 'refs/heads/release/')}}
+ type=raw,value={{branch}}-{{sha}},enable=${{startsWith(github.ref, 'refs/heads/hotfix/')}}
+ type=ref,event=pr
+ type=raw,value=manual-{{branch}}-{{sha}},enable=${{github.event_name == 'workflow_dispatch'}}
+
+ # Build and push Docker image with Buildx (don't push on PR)
+ # https://github.com/docker/build-push-action
+ - name: Build and push Docker image
+ id: build-and-push
+ uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
+ with:
+ sbom: true
+ provenance: mode=max
+ context: ${{ env.BUILD_CONTEXT }}
+ file: ${{ env.DOCKERFILE_PATH }}
+ push: ${{ github.event_name != 'pull_request' }}
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+
+
+ # Extract the pure application SBOM from the artifact stage, we want to handle it separately from the container SBOM
+ # This automaticaly re-uses the previously generated stage from cache, so we get the exact sbom from previous build step
+ - name: Export Application SBOM from artifact stage
+ if: ${{ github.event_name != 'pull_request' }}
+ uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
+ with:
+ context: ${{ env.BUILD_CONTEXT }}
+ file: ${{ env.DOCKERFILE_PATH }}
+ target: app-sbom-artifact
+ push: false
+ outputs: type=local,dest=sbom-output
+
+ # Generate container SBOM.
+ - name: Run Trivy in GitHub SBOM mode to generate CycloneDX SBOM for container
+ if: ${{ github.event_name != 'pull_request' }}
+ uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
+ with:
+ scan-type: 'image'
+ format: 'cyclonedx'
+ output: 'sbom-output/sbom_container.cyclonedx.json'
+ image-ref: ${{ steps.meta.outputs.tags }}
+ skip-dirs: '/App' # Skip the /app directory as we handle the content of the application in a seperate SBOM for easier vulnerability management and because trivy misses important fields
+
+ - name: Upload trivy/container AND application SBOMs as a Github artifact
+ if: ${{ github.event_name != 'pull_request' }}
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+ with:
+ name: sbom
+ path: '${{ github.workspace }}/sbom-output/'
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
new file mode 100644
index 0000000..1af6d85
--- /dev/null
+++ b/.github/workflows/dotnet.yml
@@ -0,0 +1,141 @@
+name: .NET
+
+on:
+ workflow_dispatch:
+ pull_request:
+ branches:
+ - 'main'
+ - 'develop'
+ - 'release/**'
+ - 'hotfix/**'
+ push:
+ branches:
+ - 'main'
+ - 'develop'
+ - 'release/**'
+ - 'hotfix/**'
+
+permissions:
+ contents: read
+
+env:
+ BUILD_CONFIGURATION: "Release"
+ SOLUTION_PATH: source/AAS.TwinEngine.DataEngine.sln
+ TEST_PROJECT: source/AAS.TwinEngine.DataEngine.UnitTests/AAS.TwinEngine.DataEngine.UnitTests.csproj
+ MODULE_TEST_PROJECT: source/AAS.TwinEngine.DataEngine.ModuleTests/AAS.TwinEngine.DataEngine.ModuleTests.csproj
+
+jobs:
+
+ build-test:
+ name: Build & Test
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ checks: write
+ pull-requests: write
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1
+ with:
+ dotnet-version: "8.0.x"
+
+ - name: Restore
+ run: dotnet restore ${{ env.SOLUTION_PATH }} --locked-mode
+
+ - name: Build
+ run: dotnet build ${{ env.SOLUTION_PATH }} --configuration ${{ env.BUILD_CONFIGURATION }} --no-restore
+
+ - name: Run Unit Tests
+ run: dotnet test ${{ env.TEST_PROJECT }} --configuration Release --no-build --logger "trx;LogFileName=unit_test_results.trx" --collect:"XPlat Code Coverage" --settings source/coverlet.runsettings
+
+ - name: Run Module Tests
+ run: dotnet test ${{ env.MODULE_TEST_PROJECT }} --configuration Release --no-build --logger "trx;LogFileName=module_test_results.trx" --collect:"XPlat Code Coverage" --settings source/coverlet.runsettings
+
+ - name: Publish Test Results
+ uses: dorny/test-reporter@fe45e9537387dac839af0d33ba56eed8e24189e8 # v2.3.0
+ id: test-results
+ if: github.event.pull_request.head.repo.fork == false
+ with:
+ name: Test Results (Unit & Module)
+ path: "**/*_test_results.trx"
+ reporter: dotnet-trx
+
+ - name: Combine Reports (Test Results)
+ if: github.event.pull_request.head.repo.fork == false
+ run: |
+ echo "# Test & Coverage Report" > results.md
+ echo "" >> results.md
+ echo "## Test Results Summary" >> results.md
+ echo "" >> results.md
+ echo "| Metric | Count |" >> results.md
+ echo "|--------|-------|" >> results.md
+ echo "| ✅ Passed | ${{ steps.test-results.outputs.passed }} |" >> results.md
+ echo "| ❌ Failed | ${{ steps.test-results.outputs.failed }} |" >> results.md
+ echo "| ⏭️ Skipped | ${{ steps.test-results.outputs.skipped }} |" >> results.md
+ echo "" >> results.md
+ echo "[View Detailed Test Results](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> results.md
+ echo "" >> results.md
+ echo "---" >> results.md
+ echo "" >> results.md
+
+ - name: Code Coverage Report - Unit Tests
+ if: github.event.pull_request.head.repo.fork == false
+ uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # v1.3.0
+ with:
+ filename: "source/AAS.TwinEngine.DataEngine.UnitTests/TestResults/*/coverage.cobertura.xml"
+ badge: false
+ fail_below_min: true
+ format: markdown
+ hide_branch_rate: false
+ hide_complexity: false
+ indicators: true
+ output: both
+ thresholds: "80 80"
+
+ - name: Combine Reports (Unit Test Coverage Results)
+ if: github.event.pull_request.head.repo.fork == false
+ run: |
+ echo "## Code Coverage" >> results.md
+ echo "" >> results.md
+ echo "### Unit Tests Coverage" >> results.md
+ cat code-coverage-results.md >> results.md
+ echo "" >> results.md
+
+ - name: Code Coverage Report - Module Tests
+ if: github.event.pull_request.head.repo.fork == false
+ uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # v1.3.0
+ with:
+ filename: "source/AAS.TwinEngine.DataEngine.ModuleTests/TestResults/*/coverage.cobertura.xml"
+ badge: false
+ fail_below_min: false
+ format: markdown
+ hide_branch_rate: false
+ hide_complexity: false
+ indicators: true
+ output: both
+
+ - name: Combine Reports (Module Test Coverage Results)
+ if: github.event.pull_request.head.repo.fork == false
+ run: |
+ echo "### Module Tests Coverage" >> results.md
+ cat code-coverage-results.md >> results.md
+
+
+ - name: Add PR Comment
+ if: github.event.pull_request.head.repo.fork == false
+ uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0
+ with:
+ recreate: true
+ path: results.md
+
+ - name: Upload TRX as artifact (Fork PR fallback)
+ if: github.event.pull_request.head.repo.fork == true
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
+ with:
+ name: test-results
+ path: "**/*_test_results.trx"
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
new file mode 100644
index 0000000..0d586b6
--- /dev/null
+++ b/.github/workflows/scorecard.yml
@@ -0,0 +1,78 @@
+# This workflow uses actions that are not certified by GitHub. They are provided
+# by a third-party and are governed by separate terms of service, privacy
+# policy, and support documentation.
+
+name: Scorecard supply-chain security
+on:
+ # For Branch-Protection check. Only the default branch is supported. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
+ branch_protection_rule:
+ # To guarantee Maintained check is occasionally updated. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
+ schedule:
+ - cron: '26 2 * * *'
+ push:
+ branches: [ "main" ]
+
+# Declare default permissions as read only.
+permissions: read-all
+
+jobs:
+ analysis:
+ name: Scorecard analysis
+ runs-on: ubuntu-latest
+ # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
+ if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
+ permissions:
+ # Needed to upload the results to code-scanning dashboard.
+ security-events: write
+ # Needed to publish results and get a badge (see publish_results below).
+ id-token: write
+ # Uncomment the permissions below if installing in a private repository.
+ # contents: read
+ # actions: read
+
+ steps:
+ - name: "Checkout code"
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ persist-credentials: false
+
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ # (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
+ # - you want to enable the Branch-Protection check on a *public* repository, or
+ # - you are installing Scorecard on a *private* repository
+ # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
+ # repo_token: ${{ secrets.SCORECARD_TOKEN }}
+
+ # Public repositories:
+ # - Publish results to OpenSSF REST API for easy access by consumers
+ # - Allows the repository to include the Scorecard badge.
+ # - See https://github.com/ossf/scorecard-action#publishing-results.
+ # For private repositories:
+ # - `publish_results` will always be set to `false`, regardless
+ # of the value entered here.
+ publish_results: false
+
+ # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
+ # file_mode: git
+
+ # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
+ # format to the repository Actions tab.
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
+
+ # Upload the results to GitHub's code scanning dashboard (optional).
+ # Commenting out will disable upload of results to your repo's Code Scanning dashboard
+ - name: "Upload to code-scanning"
+ uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6
+ with:
+ sarif_file: results.sarif
diff --git a/README.md b/README.md
index 3dc74ed..ab6f7c3 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,101 @@
# DataEngine
-**DataEngine** is a .NET-based service that dynamically generates complete **Asset Administration Shell (AAS)** submodels by combining standardized templates with real-time data.
-It integrates with **Eclipse BaSyx** and follows **IDTA specifications** to ensure interoperability.
-When a submodel is requested, DataEngine retrieves its template, queries the **Plugin** for semantic ID values, and populates the structure automatically.
-It supports nested and hierarchical data models, providing ready-to-use submodels for visualization or API consumption.
-In short, DataEngine acts as the **core orchestration layer** that transforms static AAS templates into live digital representations.
+[](https://www.mm-software.com/)
+[](https://www.apache.org/licenses/)
+[](https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-10.0&WT.mc_id=dotnet-35129-website)
+
+## Overview
+
+## DataEngine Overview
+
+**DataEngine** is an API service that dynamically generates complete **Asset Administration Shell (AAS) submodels** by combining standardized AAS templates with provided data from database via plugins.
+
+It acts as the **core orchestration layer** in the TwinEngine ecosystem, transforming static AAS templates into **live, ready-to-consume AAS representations** through a **plugin-based value resolution mechanism**.
+
+DataEngine integrates seamlessly with **Eclipse BaSyx** components and is also capable of orchestrating other **open-source AAS-related components**, enabling a **flexible, vendor-neutral AAS infrastructure**.
+
+---
+
+## Features Overview
+
+- **Template-based Dynamic AAS and Submodel Generation**
+ Dynamically builds complete AAS structures using standardized, reusable templates (containing semantic IDs without values).
+ - For more info : [Template-driven submodel generation](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/wiki/Feature-Overview#template-driven-submodel-generation)
+
+- **Schema-driven Plugin Integration**
+ Decouples data access through external Plugin APIs using JSON Schema contracts for type-safe communication.
+ - For more info : [Plugin-based value resolution](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/wiki/Feature-Overview#plugin-based-value-resolution)
+
+- **IDTA-aligned AAS REST Endpoints**
+ Multiple API endpoints that align with official IDTA AAS specifications, supporting shell descriptor, submodel, and submodel element operations for seamless interoperability.
+ - For more info : [Idta-aligned-endpoints](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/wiki/Feature-Overview#idta-aligned-endpoints)
+
+- **Multi-Plugin Orchestration**
+ DataEngine supports orchestration across multiple Plugin APIs to resolve runtime data simultaneously.
+ - For more info : [Multi-plugin orchestration](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/wiki/Feature-Overview#multi-plugin-orchestration)
+
+- **Nested and Hierarchical Submodel Support**
+ Handles complex Submodels with deeply nested and structured SubmodelElements.
+ - For more info : [Hierarchical & nested models](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/wiki/Feature-Overview#hierarchical--nested-models)
+
+- **Comprehensive SubmodelElement Type Support**
+ Supports a broad range of SubmodelElement types with semantic preservation during population.
+ - For more info : [Support for SubmodelElement types](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/wiki/Feature-Overview#support-for-submodelelement-types)
+
+## DataEngine - AAS Generation Flow
+
+```mermaid
+sequenceDiagram
+ actor A as Client
+ participant B as DataEngine
+ participant C as Template Repository
+ participant D as Plugins
+
+ A->>B: GET /submodels/{submodelIdentifier}
+ B->>C: GET / Submodel Templates
+ C-->>B: Submodel Template (Semantic IDs)
+ B->>B: Extract semantic IDs
+ B->>D: POST /data/{submodelId}
+ D-->D: Resolve semantic IDs
+ D-->>B: Semantic Id with Values
+ B->>B: Populate Template
+ B-->>A: Filled submodel
+```
+
+The DataEngine transforms **static AAS templates** into **live digital representations**.
+
+### Step-by-Step Process
+
+When a client requests AAS data (shell descriptor, submodel, or submodel element):
+
+1. **Fetch Template** - DataEngine retrieves the required AAS/Submodel template from the AAS Template Registry
+2. **Extract Semantic IDs** - Identifies all semantic IDs within the template that need values
+3. **Request Data via Schema** - Sends a JSON Schema to the Plugin API describing the structure and semantic IDs needed
+4. **Receive Values** - Plugin queries its database and responds with populated values for the requested semantic IDs
+5. **Populate Template** - DataEngine injects the received values into the template structure
+6. **Return AAS submodel Response** - Responds to the client with a complete, ready-to-use AAS structure
+
+
+## **Quick Start Guide**
+
+### Running the Setup With DPP Plugin
+
+1. **Clone or extract this repository:**
+ ```bash
+ git clone https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine.git
+ cd AAS.TwinEngine.DataEngine/example
+ ```
+
+2. **Start all services:**
+ ```bash
+ docker-compose up -d
+ ```
+
+3. **Access the Web UI:**
+ Open your browser and navigate to:
+ ```
+ http://localhost:8080/aas-ui/
+ ```
+- For more info : [TwinEngine Demonstrator Setup](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/blob/develop/example/README.md)
+---
diff --git a/apiCollection/environments/develop.bru b/apiCollection/environments/develop.bru
deleted file mode 100644
index 2b22af1..0000000
--- a/apiCollection/environments/develop.bru
+++ /dev/null
@@ -1,3 +0,0 @@
-vars {
- DataEngineBaseUrl: https://twinengine-dataengine-dev-euw-ca.icystone-61e99dc5.westeurope.azurecontainerapps.io
-}
diff --git a/example/README.md b/example/README.md
new file mode 100644
index 0000000..6776b04
--- /dev/null
+++ b/example/README.md
@@ -0,0 +1,172 @@
+# TwinEngine Demonstrator Setup
+
+## Overview
+
+This folder provides a complete, containerized setup to demonstrate how **TwinEngine.DataEngine** can be integrated and run locally. It creates a fully functional environment for managing Asset Administration Shells (AAS), submodels, and related digital asset components using Docker Compose.
+
+The setup includes a complete tech stack with services for AAS registry, repository, submodel management, data persistence, UI access, and a plugin system—all orchestrated through Docker containers on a shared network.
+
+## Included Submodel Templates
+
+This example includes 5 standardized submodel templates from the **Digital Product Passport for Industry 4.0**:
+
+- **Nameplate**
+- **ContactInformation**
+- **TechnicalData**
+- **CarbonFootprint**
+- **HandoverDocumentation**
+
+## Quick Start
+
+### Prerequisites
+
+Before running the demonstrator, ensure you have installed:
+
+- **Docker** (v20.10+) — [Install Docker](https://docs.docker.com/get-docker/)
+- **Docker Compose** (v1.29+) — Usually included with Docker Desktop
+- **Available Ports** — The following ports must be available on your machine:
+ - `8080` — Main API Gateway (nginx)
+ - `8081` - PGAdmin
+
+### Running the Setup
+
+1. **Clone or extract this repository:**
+ ```bash
+ git clone https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine.git
+ cd AAS.TwinEngine.DataEngine
+ ```
+2. **Go Inside example Folder**
+
+```bash
+cd AAS.TwinEngine.DataEngine\example
+```
+
+2. **Start all services:**
+ ```bash
+ docker-compose up -d
+ ```
+
+3. **Access the Web UI:**
+ Open your browser and navigate to:
+ ```
+ http://localhost:8080/aas-ui/
+ ```
+
+4. **Stop all services:**
+ ```bash
+ docker-compose down
+ ```
+
+## Architecture & Services
+
+The docker-compose setup includes the following services, all running on a shared `twinengine-network`:
+
+### Core Services
+
+| Service | Port | Image | Purpose |
+|---------|------|-------|----------|
+| **nginx** | 8080 | `nginx:trixie-perl` | API Gateway & Web UI proxy |
+| **twinengine-dataengine** | - | `ghcr.io/aas-twinengine/dataengine:1.0.0` | Main TwinEngine DataEngine service |
+| **template-repository** | - | `eclipsebasyx/aas-environment:2.0.0-SNAPSHOT` | AAS Environment & Submodel repository |
+| **aas-template-registry** | - | `eclipsebasyx/aas-registry-log-mongodb:2.0.0-SNAPSHOT` | AAS Shell Descriptor Registry |
+| **sm-template-registry** | - | `eclipsebasyx/submodel-registry-log-mongodb:2.0.0-SNAPSHOT` | Submodel Descriptor Registry |
+| **dpp-plugin** | - | `ghcr.io/aas-twinengine/plugindpp:1.0.0` | Digital Product Passport Plugin |
+| **aas-web-ui** | — | `eclipsebasyx/aas-gui:SNAPSHOT` | Web User Interface (served via nginx) |
+
+### Infrastructure Services
+
+| Service | Port | Image | Purpose |
+|---------|------|-------|----------|
+| **postgres** | - | `postgres:16-alpine` | Relational database for plugin data |
+| **pgadmin** | 8081 | `dpage/pgadmin4:snapshot` | Web UI for managing PostgreSQL database |
+| **mongo** | - | `mongo:6.0` | NoSQL database for registry metadata |
+
+## Creating/Changing Your AAS-Data
+
+### Using PGAdmin
+
+PGAdmin provides a web-based interface to manage the PostgreSQL database without writing SQL queries.
+
+**Access PGAdmin:**
+1. Navigate to `http://localhost:8081`
+2. Login with:
+ - **Email:** admin@example.com
+ - **Password:** admin
+
+**Connect to PostgreSQL Server:**
+1. In PGAdmin, click **"Add New Server"**
+2. Fill in the connection details:
+ - **Name:** twinengine
+ - **Host name:** postgres
+ - **Port:** 5432
+ - **Username:** postgres
+ - **Password:** admin
+ - **Database:** twinengine
+3. Click **"Save"**
+
+**Browse and Modify Data:**
+- In the left sidebar, navigate to: **Servers → twinengine → Databases → twinengine → Schemas → public → Tables**
+- Right-click any table and select **"View/Edit Data"** to manage records
+- Create new records or modify existing ones directly through the UI
+
+**How changes affect the Plugin:**
+- Updates to application data (e.g., shell records, submodels, submodel element values) are reflected in what the Plugin serves.
+- Submodel and shell templates are managed by BaSyx services and are not modified via PostgreSQL.
+
+--
+
+## Additional Notes
+
+### PostgreSQL Database (Plugin)
+
+If desired, you can edit credentials in `docker-compose.yml`:
+```yaml
+POSTGRES_PASSWORD: admin
+```
+
+Update plugin connection string to match. Edit `example/postgres/init.sql` for custom schema/data.
+
+**Using an External Database:**
+To use your own database instead:
+1. Change `RelationalDatabaseConfiguration__ConnectionString` in the plugin service environment variables
+2. Remove the postgres container from `docker-compose.yml`
+
+**Database Initialization:**
+The initial database script is located in `postgres/init.sql`. Modify this file as needed for your requirements.
+
+**Security and Production Notice**
+
+Change all default passwords before any use beyond local development. Default credentials (postgres: admin) are for **development** only.
+
+In production, hosting and managing the PostgreSQL database is the customer's responsibility, not the DataEngine's. Use a managed or self-hosted, production-grade PostgreSQL instance and configure the plugin connection string accordingly.
+
+
+### Port Changes
+
+Modify port mappings in `docker-compose.yml`. Update corresponding environment variables in affected services.
+
+### Security Note
+
+**Change default passwords before any use beyond local development.** Default credentials (postgres: admin) are for development only.
+
+In production: use a secure API gateway (Azure API Management, AWS API Gateway, Kong), and manage database security (encryption, access control, backups) is a customer responsibility.
+*Do not use this Docker Compose configuration in production.*
+---
+
+## Troubleshooting
+
+**UI not loading:** `docker-compose logs nginx` - Verify ports 8080-8086 are available.
+
+**Port conflicts:** `netstat -ano | findstr :8080` (Windows) to find conflicts. Change ports in `docker-compose.yml`.
+
+**Startup issues:** Run `docker-compose pull` followed by `docker-compose up -d --force-recreate`
+
+**Database errors:** Check `docker-compose ps` for health status. Verify connection strings match credentials.
+
+**PGAdmin not accessible:** Verify the postgres service is healthy with `docker-compose ps`. Check port mappings are correctly configured.
+
+
+
+## Additional Resources
+
+- [TwinEngine Documentation](https://github.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/wiki)
diff --git a/example/aas/CarbonFootprint.xml b/example/aas/CarbonFootprint.xml
new file mode 100644
index 0000000..a99092d
--- /dev/null
+++ b/example/aas/CarbonFootprint.xml
@@ -0,0 +1,2597 @@
+
+
+
+
+ AasTemplate
+ https://admin-shell.io/idta/aas/CarbonFootprintAAS/1/0
+
+ Type
+ https://admin-shell.io/idta/asset/CarbonFootprintAAS/1/0
+
+ /2b6b0bd3.png
+ image/png
+
+ Type
+
+
+
+ ModelReference
+
+
+ Submodel
+ https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0
+
+
+
+
+
+
+
+
+ CarbonFootprint
+
+
+ en
+ The Submodel provides the means to access the Carbon Footprint of the asset.
+
+
+
+ 1
+ 0
+ https://admin-shell.io/IDTA 02023-1-0
+
+ https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0
+ Template
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/CarbonFootprint/1/0
+
+
+
+
+
+ ProductCarbonFootprints
+
+
+ de
+ Produkt CO2-Fußabdruck
+
+
+ en
+ Product carbon footprint
+
+
+
+
+ en
+ Balance of greenhouse gas emissions along the entire life cycle of a product in a defined application and in relation to a defined unit of use.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductCarbonFootprints/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductCarbonFootprint/1/0
+
+
+
+ SubmodelElementCollection
+
+
+ ProductCarbonFootprint
+
+
+ de
+ Produkt CO2-Fußabdruck
+
+
+ en
+ Product carbon footprint
+
+
+
+
+ en
+ Balance of greenhouse gas emissions along the entire life cycle of a product in a defined application and in relation to a defined unit of use.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductCarbonFootprint/1/0
+
+
+
+
+
+ PcfCalculationMethods
+
+
+ de
+ Folgenabschätzungsmethoden
+
+
+ en
+ impact assessment methods
+
+
+
+
+ de
+ Normen, Standards, Verfahren zur Ermittlung der Treibhausgas-Emissionen eines Produkts
+
+
+ en
+ Standards, methods for determining the greenhouse gas emissions of a product.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/PcfCalculationMethods/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG854#003
+
+
+
+ Property
+ xs:string
+
+
+ PARAMETER
+ PcfCalculationMethod
+
+
+ de
+ Folgenabschätzungsmethode / Berechnungsmethode
+
+
+ en
+ impact assessment method / calculation method
+
+
+
+
+ en
+ Standard, method for determining the greenhouse gas emissions of a product.
+
+
+ de
+ Norm, Standard, Verfahren zur Ermittlung der Treibhausgas-Emissionen eines Produkts
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG854#003
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+
+
+
+
+
+ LifeCyclePhases
+
+
+ de
+ Lebenszyklusphasen
+
+
+ en
+ life cycle phases
+
+
+
+
+ en
+ List of life cycle stages of the product according to the quantification requirements of the standard to which the PCF carbon footprint statement refers
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/LifeCyclePhases/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG858#003
+
+
+
+ Property
+ xs:string
+
+
+ PARAMETER
+ LifeCyclePhase
+
+
+ de
+ Lebenszyklusphase
+
+
+ en
+ life cycle phase
+
+
+
+
+ en
+ Life cycle stages of the product according to the quantification requirements of the standard to which the PCF carbon footprint statement refers
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG858#003
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+
+
+
+
+
+ PARAMETER
+ PcfCO2eq
+
+
+ de
+ CO2-Äquivalent
+
+
+ en
+ CO2 equivalent
+
+
+
+
+ en
+ Sum of all greenhouse gas emissions of a product according to the quantification requirements of the standard.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG855#003
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:decimal
+
+
+ PARAMETER
+ ReferenceImpactUnitForCalculation
+
+
+ de
+ Referenzeinheit für die Berechnung
+
+
+ en
+ Reference value for calculation
+
+
+
+
+ en
+ Quantity unit of the product to which the PCF information on the CO2 footprint refers.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG856#003
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+
+
+ PARAMETER
+ QuantityOfMeasureForCalculation
+
+
+ de
+ Mengenangabe für die Berechnung
+
+
+ en
+ quantity of measure for calculation
+
+
+
+
+ en
+ provides the quantity number of pieces or mass or volume to compute the impact of climate change or product carbon footprint.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG857#003
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:double
+
+
+ PARAMETER
+ PublicationDate
+
+
+ de
+ Veröffentlichungsdatum
+
+
+ en
+ Publication date
+
+
+
+
+ en
+ The UTC timestamp on which a Product Carbon Footprint (PCF) - a calculation of a product's total greenhouse gas emissions - was created and published
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/PublicationDate/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:dateTime
+
+
+ PARAMETER
+ ExpirationDate
+
+
+ de
+ Ablaufdatum
+
+
+ en
+ Expiration date
+
+
+
+
+ en
+ End date up to which a study or data collection for calculating an ecological footprint is considered current and valid before an update or new calculation is required.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ExpirationDate/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:dateTime
+
+
+ PARAMETER
+ ExplanatoryStatement
+
+
+ de
+ Erklärung
+
+
+ en
+ Explanatory statement
+
+
+
+
+ en
+ Explanation required or provided to ensure that a footprint communication can be properly understood by a purchaser, potential purchaser, or user of the product.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ExplanatoryStatement/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ application/pdf
+
+
+ GoodsHandoverAddress
+
+
+ de
+ Warenübergabeadresse
+
+
+ en
+ goods address hand-over
+
+
+
+
+ en
+ Indicates the hand-over address of the goods transport
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/AddressInformation
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/smt-dropin/smt-dropin-use/1/0
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61360_7#AAS002#001
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAQ837#008
+
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+
+
+
+
+
+ ProductOrSectorSpecificCarbonFootprints
+
+
+ en
+ Product Or Sector Specific Carbon Footprints
+
+
+
+
+ en
+ Product Carbon Footprints, which is determined in accordance with sector or product group-specific rules or guidelines and covers the life cycle or parts of a product life cycle.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificCarbonFootprints/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificCarbonFootprint/1/0
+
+
+
+ SubmodelElementCollection
+
+
+ ProductOrSectorSpecificCarbonFootprint
+
+
+ de
+ Produkt CO2-Fußabdruck
+
+
+ en
+ Product carbon footprint
+
+
+
+
+ en
+ Product Carbon Footprint, which is determined in accordance with sector or product group-specific rules or guidelines and covers the life cycle or parts of a product life cycle.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificCarbonFootprint/1/0
+
+
+
+
+
+ PcfCalculationMethods
+
+
+ de
+ Folgenabschätzungsmethoden
+
+
+ en
+ impact assessment methods
+
+
+
+
+ de
+ Normen, Standards, Verfahren zur Ermittlung der Treibhausgas-Emissionen eines Produkts
+
+
+ en
+ Standards, methods for determining the greenhouse gas emissions of a product.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/PcfCalculationMethods/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG854#003
+
+
+
+ Property
+ xs:string
+
+
+ PARAMETER
+ PcfCalculationMethod
+
+
+ de
+ Folgenabschätzungsmethode / Berechnungsmethode
+
+
+ en
+ impact assessment method / calculation method
+
+
+
+
+ en
+ Standard, method for determining the greenhouse gas emissions of a product.
+
+
+ de
+ Norm, Standard, Verfahren zur Ermittlung der Treibhausgas-Emissionen eines Produkts
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG854#003
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+
+
+
+
+
+ ProductOrSectorSpecificRule
+
+
+ de
+ Produktspezifische oder sektorspezifische Regel
+
+
+ en
+ Product or Sector Specific Rule
+
+
+
+
+ de
+ Beinhaltet weiterführende Informationen zur produktspezifischen oder sektorspezifischen Regel, welche zur Berechnung des CO2-Fußabdrucks eingesetzt wird.
+
+
+ en
+ Contains further information on the product-specific or sector-specific rule used to calculate the carbon footprint.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+
+ PcfRuleOperator
+
+
+ de
+ Herausgeber der PCF Berechnungsmethode
+
+
+ en
+ Operator of the PCF calculation method
+
+
+
+
+ de
+ Einrichtung, welche spezifische Anweisungen und Methoden zur Berechnung und Überwachung des CO2-Fußabdrucks eines Produkts oder Sektors definiert und umsetzt.
+
+
+ en
+ Organization that defines and implements specific instructions and methods for calculating and monitoring the carbon footprint of a product or sector.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/Operator/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+
+
+ PcfRuleName
+
+
+ de
+ Name der PCF Berechnungsmethode
+
+
+ en
+ Name of the PCF calculation method
+
+
+
+
+ de
+ Folgenabschätzungsmethode / Berechnungsmethode
+
+
+ en
+ Standard, method for determining the greenhouse gas emissions of a product
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/Name/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+
+
+ PcfRuleVersion
+
+
+ de
+ Version der PCF Berechnungsmethode
+
+
+ en
+ Version of the PCF calculation method
+
+
+
+
+ de
+ Spezifische Ausgabe oder Revision der Regel, die zur Berechnung des CO2-Fußabdrucks eines Produkts verwendet wird.
+
+
+ en
+ Specific version or revision of the rule used to calculate the carbon footprint of a product.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/Version/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+
+
+ PcfRuleOnlineReference
+
+
+ de
+ Online Referenz zur PCF Berechnungsmethode
+
+
+ en
+ Online reference to the PCF calculation method
+
+
+
+
+ de
+ Online-Referenz zur PCF-Berechnungsmethodik, die detaillierte Anweisungen und Richtlinien zur Berechnung des CO2-Fußabdrucks eines Produkts bereitstellt.
+
+
+ en
+ Online PCF calculation methodology reference that provides detailed instructions and guidelines for calculating a product's carbon footprint.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/OnlineReference/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ application/pdf
+
+
+
+
+ ExternalPcfApi
+
+
+ de
+ Externe API für PCF Informationen
+
+
+ en
+ External API for PCF information
+
+
+
+
+ de
+ Ein externer Dienst, der über eine Schnittstelle Informationen zum CO2-Fußabdruck bereitstellt und den Abruf dieser Daten auf Abruf ermöglicht.
+
+
+ en
+ An external service that provides carbon footprint information via an interface, allowing on-demand retrieval of this data when required.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ExternalPcfApi/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+
+ PcfApiEndpoint
+
+
+ de
+ Endpunkt
+
+
+ en
+ Endpoint
+
+
+
+
+ de
+ Spezifische URL oder Adresse, über die Daten zur Berechnung des CO2-Fußabdrucks eines Produkts von externen Quellen abgerufen werden können.
+
+
+ en
+ Specific URL or address that can be used to retrieve data from external sources to calculate the carbon footprint of a product.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ExternalPcfApi/Endpoint/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:anyURI
+
+
+ PcfApiQuery
+
+
+ de
+ Abfrage
+
+
+ en
+ Query
+
+
+
+
+ de
+ Spezifische Abfrage, über die Daten zur Berechnung des CO2-Fußabdrucks eines Produkts von externen Quellen abgerufen werden können.
+
+
+ en
+ Specific query that can be used to retrieve data from external sources to calculate the carbon footprint of a product.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/ExternalPcfApi/Query/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+
+
+
+
+ PcfInformation
+
+
+ de
+ Ein Abschnitt, in dem weitere Inhalte entsprechend der Berechnungsmethode zum Product Carbon Footprint aufgeführt werden.
+
+
+ en
+ A section in which further content is listed according to the calculation method for the Product Carbon Footprint.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/CarbonFootprint/PcfInformation/1/0
+
+
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+
+
+
+
+
+
+
+ de
+ C02 Footprint
+
+
+ en
+ Carbon Footprint
+
+
+
+
+
+
+ PcfApiEndpoint
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ExternalPcfApi/Endpoint/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Endpoint
+
+
+ de
+ Endpunkt
+
+
+ STRING
+
+
+ de
+ Spezifische URL oder Adresse, über die Daten zur Berechnung des CO2-Fußabdrucks eines Produkts von externen Quellen abgerufen werden können.
+
+
+ en
+ Specific URL or address that can be used to retrieve data from external sources to calculate the carbon footprint of a product.
+
+
+
+
+
+
+
+
+ PcfRuleVersion
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/Version/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Version of the PCF calculation method
+
+
+ de
+ Version der PCF Berechnungsmethode
+
+
+
+
+ en
+ Version
+
+
+ de
+ Version
+
+
+ STRING
+
+
+ de
+ Spezifische Ausgabe oder Revision der Regel, die zur Berechnung des CO2-Fußabdrucks eines Produkts verwendet wird.
+
+
+ en
+ Specific version or revision of the rule used to calculate the carbon footprint of a product.
+
+
+ 2.0
+
+
+
+
+
+
+ PcfCalculationMethod
+ 0173-1#02-ABG854#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ impact assessment method / calculation method
+
+
+ de
+ Folgenabschätzungsmethode / Berechnungsmethode
+
+
+ STRING
+
+
+ de
+ Norm, Standard, Verfahren zur Ermittlung der Treibhausgas-Emissionen eines Produkts
+
+
+ en
+ standard, method for determining the greenhouse gas emissions of a product
+
+
+
+
+
+ EN 15804
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU223#003
+
+
+
+
+
+ GHG Protocol
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU221#003
+
+
+
+
+
+ IEC TS 63058
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU222#003
+
+
+
+
+
+ IEC 63366
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACA792#002
+
+
+
+
+
+ ISO 14040, ISO 14044
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV505#003
+
+
+
+
+
+ ISO 14067
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU218#003
+
+
+
+
+
+ PEP Ecopassport
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU220#003
+
+
+
+
+
+ PACT v1.0.1
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC004#001
+
+
+
+
+
+ PACT v2.0.0
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC003#001
+
+
+
+
+
+ PACT v3.0.0
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC012#001
+
+
+
+
+
+ TFS v2
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC005#001
+
+
+
+
+
+ TFS v3
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC010#001
+
+
+
+
+
+ Catena-X v1
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC007#001
+
+
+
+
+
+ Catena-X v2
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC006#001
+
+
+
+
+
+ Catena-X v3
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC011#001
+
+
+
+
+
+ BS PAS 2050
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC008#001
+
+
+
+
+
+ IEC 63372
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC019#001
+
+
+
+
+
+
+
+
+
+
+
+
+ PublicationDate
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/PublicationDate/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ de
+ Veröffentlichungsdatum
+
+
+ en
+ Publication date
+
+
+
+
+ en
+ EMPTY
+
+
+ TIMESTAMP
+
+
+ de
+ Der UTC Zeitstempel, an dem ein Product Carbon Footprint (PCF) – eine Berechnung der gesamten Treibhausgasemissionen eines Produkts – erstellt und veröffentlicht wurde
+
+
+ en
+ The UTC timestamp on which a Product Carbon Footprint (PCF) - a calculation of a product's total greenhouse gas emissions - was created and published
+
+
+
+
+
+
+
+
+ ExpirationDate
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ExpirationDate/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ de
+ Ablaufdatum
+
+
+ en
+ Expiration Date
+
+
+ TIMESTAMP
+
+
+ de
+ Enddatum, bis zu dem eine Studie oder Datenerhebung zur Berechnung eines ökologischen Fußabdrucks als aktuell und gültig betrachtet wird, bevor eine Aktualisierung oder neue Berechnung erforderlich ist.
+
+
+ en
+ End date up to which a study or data collection for calculating an ecological footprint is considered current and valid before an update or new calculation is required.
+
+
+
+
+
+
+
+
+ PcfRuleOperator
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/Operator/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Publisher of the PCF calculation method
+
+
+ de
+ Herausgeber der PCF Berechnungsmethode
+
+
+ STRING
+
+
+ de
+ Einrichtung, welche spezifische Anweisungen und Methoden zur Berechnung und Überwachung des CO2-Fußabdrucks eines Produkts oder Sektors definiert und umsetzt.
+
+
+ en
+ Organization that defines and implements specific instructions and methods for calculating and monitoring the carbon footprint of a product or sector.
+
+
+
+
+
+
+
+
+ ProductOrSectorSpecificRule
+
+
+ de
+ Produktspezifische oder sektorspezifische Regel
+
+
+ en
+ Product or Sector Specific Rule
+
+
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Product or Sector Specific Rule
+
+
+ de
+ Produktspezifische oder sektorspezifische Regel
+
+
+
+
+ de
+ Beinhaltet weiterführende Informationen zur produktspezifischen oder sektorspezifischen Regel, welche zur Berechnung des CO2-Fußabdrucks eingesetzt wird.
+
+
+ en
+ Contains further information on the product-specific or sector-specific rule used to calculate the carbon footprint.
+
+
+
+
+
+
+
+
+ ReferenceImpactUnitForCalculation
+ 0173-1#02-ABG856#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Reference value for calculation
+
+
+ de
+ Referenzeinheit für die Berechnung
+
+
+ STRING
+
+
+ en
+ Quantity unit of the product to which the PCF information on the CO2 footprint refers
+
+
+ de
+ Mengeneinheit des Produktes, auf das sich die PCF-Angabe zum CO2-Fußabdruck bezieht
+
+
+
+
+
+ g
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ596#003
+
+
+
+
+
+ kg
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ597#003
+
+
+
+
+
+ t
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ598#003
+
+
+
+
+
+ ml
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ599#003
+
+
+
+
+
+ l
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ600#003
+
+
+
+
+
+ cbm
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ601#003
+
+
+
+
+
+ qm
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ602#003
+
+
+
+
+
+ piece
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ603#003
+
+
+
+
+
+ kWh
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACB997#001
+
+
+
+
+
+
+
+
+
+
+
+
+ PcfApiQuery
+
+
+ en
+ Query
+
+
+ de
+ Abfrage
+
+
+
+
+ de
+ Spezifische Abfrage, über die Daten zur Berechnung des CO2-Fußabdrucks eines Produkts von externen Quellen abgerufen werden können.
+
+
+ en
+ Specific query that can be used to retrieve data from external sources to calculate the carbon footprint of a product.
+
+
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ExternalPcfApi/Query/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Query
+
+
+ de
+ Abfrage
+
+
+ STRING
+
+
+ en
+ Specific query that can be used to retrieve data from external sources to calculate the carbon footprint of a product.
+
+
+ de
+ Spezifische Abfrage, über die Daten zur Berechnung des CO2-Fußabdrucks eines Produkts von externen Quellen abgerufen werden können.
+
+
+
+
+
+
+
+
+ ExternalPcfApi
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ExternalPcfApi/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ An external service that provisions carbon footprint information via an interface, allowing on-demand retrieval of this data.
+
+
+ de
+ Ein externer Dienst, der über eine Schnittstelle Informationen zum CO2-Fußabdruck bereitstellt und den Abruf dieser Daten auf Abruf ermöglicht.
+
+
+
+
+ en
+ An external service that provisions carbon footprint information via an interface, allowing on-demand retrieval of this data.
+
+
+ de
+ Ein externer Dienst, der über eine Schnittstelle Informationen zum CO2-Fußabdruck bereitstellt und den Abruf dieser Daten auf Abruf ermöglicht.
+
+
+
+
+
+
+
+
+ LifeCyclePhase
+ 0173-1#02-ABG858#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ life cycle phase (acc. EN 15804)
+
+
+ de
+ Lebenszyklusphase (nach EN 15804)
+
+
+
+
+ en
+ life cycle phase
+
+
+ de
+ Lebenszyklusphase
+
+
+ STRING
+
+
+ de
+ Lebenszyklusphase des Produktes gemäß den Quantifizierungsvorgaben der Norm, auf den sich die PCF-Angabe zum CO2-Fußabdruck bezieht
+
+
+ en
+ life cycle stages of the product according to the quantification requirements of the standard to which the PCF carbon footprint statement refers
+
+
+
+
+
+ A1 - raw material supply (and upstream production)
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU208#003
+
+
+
+
+
+ A2 - cradle-to-gate transport to factory
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU209#003
+
+
+
+
+
+ A3 - production
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU210#003
+
+
+
+
+
+ A1-A3
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABZ789#003
+
+
+
+
+
+ A4 - transport to final destination
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU211#003
+
+
+
+
+
+ A4-A5
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC013#001
+
+
+
+
+
+ A5 - Installation
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC016#001
+
+
+
+
+
+ B1 - usage phase
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU212#003
+
+
+
+
+
+ B1-B7
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC014#001
+
+
+
+
+
+ B2 - maintenance
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV498#003
+
+
+
+
+
+ B3 - repair
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV497#003
+
+
+
+
+
+ B4 - Replacement
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC017#001
+
+
+
+
+
+ B5 - update/upgrade, refurbishing
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV499#003
+
+
+
+
+
+ B6 - usage energy consumption
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV500#003
+
+
+
+
+
+ B7 - usage water consumption
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV501#003
+
+
+
+
+
+ C1 - reassembly
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV502#003
+
+
+
+
+
+ C1-C4
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC015#001
+
+
+
+
+
+ C2 - transport to recycler
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU213#003
+
+
+
+
+
+ C2-C4
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ACC018#001
+
+
+
+
+
+ C3 - recycling, waste treatment
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV503#003
+
+
+
+
+
+ C4 - landfill
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABV504#003
+
+
+
+
+
+ D - reuse
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-ABU214#003
+
+
+
+
+
+
+
+
+
+
+
+
+ ProductOrSectorSpecificCarbonFootprint
+
+
+ en
+ Product Carbon Footprint, which is determined in accordance with sector or product group-specific rules or guidelines and covers the life cycle or parts of a product life cycle.
+
+
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificCarbonFootprint/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Product Or Sector Specific Carbon Footprint
+
+
+
+
+ en
+ Product Carbon Footprint, which is determined in accordance with sector or product group-specific rules or guidelines and covers the life cycle or parts of a product life cycle.
+
+
+
+
+
+
+
+
+ ProductCarbonFootprint
+
+
+ de
+ Produkt CO2-Fußabdruck
+
+
+ en
+ Product carbon footprint
+
+
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ProductCarbonFootprint/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Product Carbon Footprint
+
+
+ de
+ Produkt CO2-Fußabdruck
+
+
+
+
+ en
+ Balance of greenhouse gas emissions along the entire life cycle of a product in a defined application and in relation to a defined unit of use
+
+
+
+
+
+
+
+
+ PcfInformation
+
+
+ de
+ PCF Informationen
+
+
+ en
+ PCF Informationen
+
+
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/PcfInformation/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ PCF Information
+
+
+ de
+ PCF Informationen
+
+
+
+
+ en
+ A section in which further content is listed according to the calculation method for the Product Carbon Footprint.
+
+
+ de
+ Ein Abschnitt, in dem weitere Inhalte entsprechend der Berechnungsmethode zum Product Carbon Footprint aufgeführt werden.
+
+
+
+
+
+
+
+
+ PcfCO2eq
+ 0173-1#02-ABG855#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ CO2 equivalent - total (for PCF and LCA)
+
+
+ de
+ CO2-Äquivalent - total (für PCF und LCA)
+
+
+ CO2eq
+ REAL_MEASURE
+
+
+ de
+ Summe aller Treibhausgas-Emissionen eines Produkts gemäß der Quantifizierungsvorgaben der Norm
+
+
+ en
+ sum of all greenhouse gas emissions of a product according to the quantification requirements of the standard
+
+
+
+
+
+
+
+
+ PcfRuleName
+
+
+ de
+ Name der PCF Berechnungsmethode
+
+
+ en
+ Name of the PCF calculation method
+
+
+
+ 1
+ 0
+
+ https://admin-shell.io/idta/CarbonFootprint/ProductOrSectorSpecificRule/Name/1/0
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Name of the PCF calculation method
+
+
+ de
+ Name der PCF Berechnungsmethode
+
+
+ STRING
+
+
+ de
+ Folgenabschätzungsmethode / Berechnungsmethode
+
+
+ en
+ Standard, method for determining the greenhouse gas emissions of a product
+
+
+
+
+
+
+
+
+ QuantityOfMeasureForCalculation
+
+
+ de
+ Mengenangabe für die Berechnung
+
+
+ en
+ quantity of measure for calculation
+
+
+ 0173-1#02-ABG857#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ quantity of measure for calculation
+
+
+ de
+ Mengenangabe für die Berechnung
+
+
+ REAL_COUNT
+
+
+ de
+ Angabe der Stückzahl, Masse oder des Volumens zur Berechnung der Auswirkungen des Klimawandels oder des CO2-Fußabdrucks des Produktes
+
+
+ en
+ provides the quantity number of pieces or mass or volume to compute the impact of climate change or product carbon footprint
+
+
+
+
+
+
+
+
+
diff --git a/example/aas/ContactInformationAAS.xml b/example/aas/ContactInformationAAS.xml
new file mode 100644
index 0000000..b0f8973
--- /dev/null
+++ b/example/aas/ContactInformationAAS.xml
@@ -0,0 +1,2139 @@
+
+
+
+ ContactInformationAAS
+ https://admin-shell.io/idta/aas/ContactInformation/1/0
+
+ Type
+ https://admin-shell.io/idta/asset/ContactInformation/1/0
+ Type
+
+
+
+ ModelReference
+
+
+ Submodel
+ https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0
+
+
+
+
+
+
+
+
+ ContactInformations
+ https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0
+ Template
+
+ ModelReference
+
+
+ Submodel
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations
+
+
+
+
+
+ ContactInformation
+
+
+ en
+ The SMC “ContactInformation” contains information on how to contact the manufacturer or an authorised service provider, e.g. when a maintenance service is required
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ OneToMany
+
+
+
+
+ RoleOfContactPerson
+
+
+ en
+ enumeration: 0173-1#07-AAS927#001 (administrativ contact), 0173-1#07-AAS928#001 (commercial contact), 0173-1#07-AAS929#001 (other contact), 0173-1#07-AAS930#001 (hazardous goods contact), 0173-1#07-AAS931#001 (technical contact). Note: the above mentioned ECLASS enumeration should be declared as “open” for further addition. ECLASS enumeration IRDI is preferable. If no IRDI available, custom input as String may also be accepted.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO204#003
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 0173-1#07-AAS931#001
+
+
+ Language
+
+
+ en
+ Note: language codes defined accord. to ISO 639-1. Note: as per ECLASS definition, Expression and representation of thoughts, information, feelings, ideas through characters.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToMany
+
+
+ xs:string
+ de
+
+
+ TimeZone
+
+
+ en
+ Note: notation accord. to ISO 8601 Note: for time in UTC the zone designator “Z” is to be used
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/TimeZone
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ Z
+
+
+ AddressOfAdditionalLink
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAQ326#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+
+
+ NationalCode
+
+
+ en
+ Note: country codes defined accord. to ISO 3166-1. Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO134#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ DE
+
+
+
+
+ CityTown
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO132#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ de
+ Musterstadt
+
+
+
+
+ Company
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAW001#001
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ ABC Company
+
+
+
+
+ Department
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO127#003
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ de
+ Vertrieb
+
+
+
+
+ Street
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO128#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ de
+ Musterstraße 1
+
+
+
+
+ Zipcode
+
+
+ en
+ Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO129#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ de
+ 12345
+
+
+
+
+ POBox
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO130#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ PF 1234
+
+
+
+
+ ZipCodeOfPOBox
+
+
+ en
+ Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO131#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ 12345
+
+
+
+
+ StateCounty
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO133#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ de
+ Muster-Bundesland
+
+
+
+
+ NameOfContact
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO205#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+
+
+
+ de
+
+
+
+
+
+ FirstName
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO206#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+
+
+
+ de
+
+
+
+
+
+ MiddleNames
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO207#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+
+
+
+ de
+
+
+
+
+
+ Title
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO208#003
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ a
+
+
+ de
+ a
+
+
+
+
+ AcademicTitle
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO209#003
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+
+
+
+ de
+
+
+
+
+
+ FurtherDetailsOfContact
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO210#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+
+
+
+ de
+
+
+
+
+
+ Phone
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Phone
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ TelephoneNumber
+
+
+ en
+ Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO136#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ One
+
+
+
+
+ en
+ +491234567890
+
+
+
+
+ AvailableTime
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/AvailableTime/
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ de
+ Montag – Freitag 08:00 bis 16:00
+
+
+
+
+ TypeOfTelephone
+
+
+ en
+ enumeration: 0173-1#07-AAS754#001 (office), 0173-1#07-AAS755#001 (office mobile), 0173-1#07-AAS756#001 (secretary), 0173-1#07-AAS757#001 (substitute), 0173-1#07-AAS758#001 (home), 0173-1#07-AAS759#001 (private mobile)
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO137#003
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 0173-1#07-AAS754#001
+
+
+
+
+ Fax
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAQ834#005
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ FaxNumber
+
+
+ en
+ Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO195#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ One
+
+
+
+
+ en
+ +491234567890
+
+
+
+
+ TypeOfFaxNumber
+
+
+ en
+ enumeration: 0173-1#07-AAS754#001 (office), 0173-1#07-AAS756#001 (secretary), 0173-1#07-AAS758#001 (home)
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO196#003
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 0173-1#07-AAS754#001
+
+
+
+
+ Email
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAQ836#005
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ EmailAddress
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO198#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ One
+
+
+ xs:string
+ email@muster-ag.de
+
+
+ TypeOfEmailAddress
+
+
+ en
+ enumeration: 0173-1#07-AAS754#001 (office), 0173-1#07-AAS756#001 (secretary), 0173-1#07-AAS757#001 (substitute), 0173-1#07-AAS758#001 (home)
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO199#003
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 0173-1#07-AAS754#001
+
+
+ PublicKey
+
+
+ en
+ Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO200#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ o
+
+
+ de
+ a
+
+
+
+
+ TypeOfPublicKey
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO201#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ a
+
+
+ de
+ a
+
+
+
+
+
+
+ IPCommunication__00__
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/IPCommunication/
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToMany
+
+
+
+
+ AddressOfAdditionalLink
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAQ326#002
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ One
+
+
+ xs:string
+
+
+ TypeOfCommunication
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/IPCommunication/TypeOfCommunication
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ Chat
+
+
+ AvailableTime
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/AvailableTime/
+
+
+
+
+
+ ConceptQualifier
+ Multiplicity
+ xs:string
+ ZeroToOne
+
+
+
+
+ de
+ Montag – Freitag 08:00 bis 16:00
+
+
+
+
+
+
+
+
+
+
+
+
+ NationalCode
+ 0173-1#02-AAO134#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ NationalCode
+
+
+
+
+ en
+ code of a country
+
+
+
+
+
+
+
+
+ Company
+ 0173-1#02-AAW001#001
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Company
+
+
+
+
+ en
+ name of the company
+
+
+
+
+
+
+
+
+ Fax
+ 0173-1#02-AAQ834#005
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Fax
+
+
+
+
+ en
+ Fax number including type
+
+
+
+
+
+
+
+
+ TimeZone
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/TimeZone
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ TimeZone
+
+
+
+
+ en
+ offsets from Coordinated Universal Time (UTC)
+
+
+
+
+
+
+
+
+ FurtherDetailsOfContact
+ 0173-1#02-AAO210#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ FurtherDetailsOfContact
+
+
+
+
+ en
+ additional information of the contact person
+
+
+
+
+
+
+
+
+ TypeOfEmailAddress
+ 0173-1#02-AAO199#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ TypeOfEmailAddress
+
+
+
+
+ en
+ characterization of an e-mail address according to its location or usage
+
+
+
+
+
+
+
+
+ MiddleNames
+ 0173-1#02-AAO207#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ MiddleNames
+
+
+
+
+ en
+ middle names of contact person
+
+
+
+
+
+
+
+
+ TypeOfPublicKey
+ 0173-1#02-AAO201#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ TypeOfPublicKey
+
+
+
+
+ en
+ characterization of a public key according to its encryption process
+
+
+
+
+
+
+
+
+ AvailableTime
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/AvailableTime/
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ AvailableTime
+
+
+
+
+ en
+ Specification of the available time window
+
+
+
+
+
+
+
+
+ Department
+ 0173-1#02-AAO127#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Department
+
+
+
+
+ en
+ administrative section within an organisation where a business partner is located
+
+
+
+
+
+
+
+
+ ContactInformation
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ContactInformation
+
+
+
+
+ en
+ The SMC “ContactInformation” contains information on how to contact the manufacturer or an authorised service provider, e.g. when a maintenance service is required
+
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAQ837#005
+
+
+
+
+
+
+ StateCounty
+ 0173-1#02-AAO133#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ StateCounty
+
+
+
+
+ en
+ federal state a part of a state
+
+
+
+
+
+
+
+
+ PublicKey
+ 0173-1#02-AAO200#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ PublicKey
+
+
+
+
+ en
+ public part of an unsymmetrical key pair to sign or encrypt text or messages
+
+
+
+
+
+
+
+
+ EmailAddress
+ 0173-1#02-AAO198#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ EmailAddress
+
+
+
+
+ en
+ electronic mail address of a business partner
+
+
+
+
+
+
+
+
+ Street
+ 0173-1#02-AAO128#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Street
+
+
+
+
+ en
+ street name and house number
+
+
+
+
+
+
+
+
+ TypeOfTelephone
+ 0173-1#02-AAO137#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ TypeOfTelephone
+
+
+
+
+ en
+ characterization of a telephone according to its location or usage
+
+
+
+
+
+
+
+
+ Title
+ 0173-1#02-AAO208#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Title
+
+
+
+
+ en
+ common, formal, religious, or other title preceding a contact person's name
+
+
+
+
+
+
+
+
+ RoleOfContactPerson
+ 0173-1#02-AAO204#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ RoleOfContactPerson
+
+
+
+
+ en
+ function of a contact person in a process
+
+
+
+
+
+
+
+
+ AcademicTitle
+ 0173-1#02-AAO209#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ AcademicTitle
+
+
+
+
+ en
+ academic title preceding a contact person's name
+
+
+
+
+
+
+
+
+ Language
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Language
+
+
+
+
+ en
+ Available language
+
+
+
+
+
+
+
+
+ ModelReference
+
+
+ Submodel
+ 0173-1#02-AAO895#003
+
+
+
+
+
+
+ CityTown
+ 0173-1#02-AAO132#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ CityTown
+
+
+
+
+ en
+ town or city
+
+
+
+
+
+
+
+
+ Email
+ 0173-1#02-AAQ836#005
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Email
+
+
+
+
+ en
+ E-mail address and encryption method
+
+
+
+
+
+
+
+
+ TelephoneNumber
+ 0173-1#02-AAO136#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ TelephoneNumber
+
+
+
+
+ en
+ complete telephone number to be called to reach a business partner
+
+
+
+
+
+
+
+
+ TypeOfFaxNumber
+ 0173-1#02-AAO196#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ TypeOfFaxNumber
+
+
+
+
+ en
+ characterization of the fax according its location or usage
+
+
+
+
+
+
+
+
+ Zipcode
+ 0173-1#02-AAO129#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Zipcode
+
+
+
+
+ en
+ ZIP code of address
+
+
+
+
+
+
+
+
+ NameOfContact
+ 0173-1#02-AAO205#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ NameOfContact
+
+
+
+
+ en
+ surname of a contact person
+
+
+
+
+
+
+
+
+ Phone
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Phone
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Phone
+
+
+
+
+ en
+ Phone number including type
+
+
+
+
+
+
+
+
+ AddressOfAdditionalLink
+ 0173-1#02-AAQ326#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ AddressOfAdditionalLink
+
+
+
+
+ en
+ web site address where information about the product or contact is given
+
+
+
+
+
+
+
+
+ FaxNumber
+ 0173-1#02-AAO195#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ FaxNumber
+
+
+
+
+ en
+ complete telephone number to be called to reach a business partner's fax machine
+
+
+
+
+
+
+
+
+ ZipCodeOfPOBox
+ 0173-1#02-AAO131#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ZipCodeOfPOBox
+
+
+
+
+ en
+ ZIP code of P.O. box address
+
+
+
+
+
+
+
+
+ POBox
+ 0173-1#02-AAO130#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ POBox
+
+
+
+
+ en
+ P.O. box number
+
+
+
+
+
+
+
+
+ ContactInformations
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ContactInformations
+
+
+
+
+ en
+ The Submodel “ContactInformations” is the collection for various contact information.
+
+
+
+
+
+
+
+
+ FirstName
+ 0173-1#02-AAO206#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ FirstName
+
+
+
+
+ en
+ first name of a contact person
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/aas/HandoverDocumentation.xml b/example/aas/HandoverDocumentation.xml
new file mode 100644
index 0000000..e1fdf49
--- /dev/null
+++ b/example/aas/HandoverDocumentation.xml
@@ -0,0 +1,3324 @@
+
+
+
+
+ HandoverDocumentationAAS
+ https://admin-shell.io/idta/aas/HandoverDocumentation/2/0
+
+ Type
+ https://admin-shell.io/idta/asset/HandoverDocumentation/2/0
+ Type
+
+
+
+ ModelReference
+
+
+ Submodel
+ https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0
+
+
+
+
+
+
+
+
+ HandoverDocumentation
+
+
+ en
+ The Submodel defines a set meta data for the handover of documentation from the manufacturer to the operator for industrial equipment
+
+
+
+ 2
+ 0
+ https://admin-shell.io/idta-02004-2-0
+
+ https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0
+ Template
+
+ ModelReference
+
+
+ Submodel
+ 0173-1#01-AHF578#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-01-AHF578-003
+
+
+
+
+
+
+ Documents
+
+
+ en
+ Documents (handover documentation)
+
+
+ de
+ Dokumente (Übergabedokumentation)
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI500#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI500-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI500#003/0173-1#01-AHF579#003
+
+
+
+ SubmodelElementCollection
+
+
+ Document
+
+
+ en
+ This SubmodelElementCollection holds the information for a VDI 2770 Document entity
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI500#003/0173-1#01-AHF579#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI500#003~0/0173-1#01-AHF579#003
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI500-003/0173-1-01-AHF579-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ OneToMany
+
+
+
+
+ DocumentIds
+
+
+ en
+ Document identifyers
+
+
+ de
+ Dokumentidentifikatoren
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI501#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI501-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI501#003/0173-1#01-AHF580#003
+
+
+
+ SubmodelElementCollection
+
+
+ DocumentId
+
+
+ en
+ Document identificator
+
+
+ de
+ Dokumentidentifikator
+
+
+
+
+ en
+ This SubmodelElementCollection holds the information for a VDI 2770 Document entity
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI501#003/0173-1#01-AHF580#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI501#003~0/0173-1#01-AHF580#003
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI501-003/0173-1-01-AHF580-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ OneToMany
+
+
+
+
+ PARAMETER
+ DocumentDomainId
+
+
+ en
+ document domain identificator
+
+
+ de
+ Document Domain Identifikator
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABH994#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABH994-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ https://domain.com/...
+
+
+ xs:string
+
+
+ PARAMETER
+ DocumentIdentifier
+
+
+ en
+ Document Identifyer
+
+
+ de
+ Dokumentennummer
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO099#004
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-AAO099-004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ XF90-884
+
+
+ xs:string
+
+
+ PARAMETER
+ DocumentIsPrimary
+
+
+ en
+ Document is primary
+
+
+ de
+ Dokument ist primär
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABH995#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABH995-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ true
+
+
+ xs:boolean
+
+
+
+
+
+
+ DocumentClassifications
+
+
+ en
+ Document classifications
+
+
+ de
+ Dokumentklassifikationen
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI502#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI502-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI502#003/0173-1#01-AHF581#003
+
+
+
+ SubmodelElementCollection
+
+
+ DocumentClassification
+
+
+ en
+ Document classification
+
+
+ de
+ Dokumentklassifikation
+
+
+
+
+ en
+ Set of information for describing the classification of the Document according to a ClassificationSystem
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI502#003/0173-1#01-AHF581#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI502#003~0/0173-1#01-AHF581#003
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI502-003/0173-1-01-AHF581-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ OneToMany
+
+
+
+
+ PARAMETER
+ ClassId
+
+
+ en
+ Class identificator
+
+
+ de
+ Klassenidentifikator
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABH996#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABH996-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ 03-02
+
+
+ xs:string
+
+
+ PARAMETER
+ ClassificationSystem
+
+
+ en
+ Classification system
+
+
+ de
+ Klassifizierungssystem
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABH997#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABH997-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ VDI2770:2020
+
+
+ xs:string
+
+
+ PARAMETER
+ ClassName
+
+
+ en
+ Class Name
+
+
+ de
+ Klassenname
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABJ219#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABJ219-002
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Operation@en
+
+
+
+
+ en
+
+
+
+ de
+
+
+
+
+
+
+
+
+
+ DocumentVersions
+
+
+ en
+ Document versions
+
+
+ de
+ Dokumentenversionen
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI503#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI503-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI503#003/0173-1#01-AHF582#003
+
+
+
+ SubmodelElementCollection
+
+
+ DocumentVersion
+
+
+ en
+ Document version
+
+
+ de
+ Document version
+
+
+
+
+ en
+ Set of information for describing the classification of the Document according to a ClassificationSystem
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI503#003/0173-1#01-AHF582#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI503#003~0/0173-1#01-AHF582#003
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI503-003/0173-1-01-AHF582-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ OneToMany
+
+
+
+
+ Language
+
+
+ en
+ Language
+
+
+ de
+ Sprache
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAN468#008
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-AAN468-008
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+ Property
+ xs:string
+
+
+ language
+
+
+ en
+ en (English)
+
+
+ de
+ en (Englisch)
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAN468#009
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ OneToMany
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ en
+
+
+ xs:string
+ en
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#07-AAS045#003
+
+
+
+
+
+
+
+ RefersToEntities
+
+
+ en
+ Reference to other documents
+
+
+ de
+ Referenz zu anderen Dokumenten
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABK288#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABK288-002
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ true
+ ReferenceElement
+
+
+ BasedOnReferences
+
+
+ en
+ Based on other documents
+
+
+ de
+ Basiert auf anderen Dokumenten
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABK289#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABK289-002
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ true
+ ReferenceElement
+
+
+ TranslationOfEntities
+
+
+ en
+ Translation of other documents
+
+
+ de
+ Übersetzung von anderen Elementen
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABK290#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABK290-002
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ true
+ ReferenceElement
+
+
+ DigitalFiles
+
+
+ en
+ Digital files
+
+
+ de
+ Digitale Dateien
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABK126#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABK126-002
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ true
+ File
+
+
+ DigitalFile
+
+
+ en
+ Name of the specific digital file@en
+
+
+ de
+ Name der spezifischen digitalen Datei@de
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABK126#003
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ OneToMany
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ docu_cecc_fullmanual_DE.PDF
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0
+
+
+
+ ConceptQualifier
+ AllowedIdShort
+ xs:string
+ DigitalFile[\d{2,3}]
+
+
+ application/pdf
+
+
+
+
+ PARAMETER
+ Version
+
+
+ en
+ Document version
+
+
+ de
+ Dokumentenversion
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAP003#005
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-AAP003-005
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ V1.2
+
+
+ xs:string
+
+
+ PARAMETER
+ StatusSetDate
+
+
+ en
+ Document status set date
+
+
+ de
+ Datum der Einstellung des Dokumentenstatus
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI000#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI000-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ 2020-02-06
+
+
+ xs:date
+
+
+ PARAMETER
+ StatusValue
+
+
+ en
+ Document status
+
+
+ de
+ Dokumentstatus
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI001#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI001-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Released
+
+
+ xs:string
+
+
+ PARAMETER
+ OrganizationShortName
+
+
+ en
+ Organization short name
+
+
+ de
+ Kurzname der Organisation
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI002-003
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Example company
+
+
+ xs:string
+
+
+ PARAMETER
+ OrganizationOfficialName
+
+
+ en
+ Organization official name
+
+
+ de
+ Offizieller Name der Organisation
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI004#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABI004-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Example company Ltd.
+
+
+ xs:string
+
+
+ PARAMETER
+ Title
+
+
+ en
+ Document title
+
+
+ de
+ Dokumententitel
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABG940#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABG940-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Examplary title@en
+
+
+
+
+ en
+
+
+
+ de
+
+
+
+
+
+ PARAMETER
+ Subtitle
+
+
+ en
+ Subtitle
+
+
+ de
+ Untertitel
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABH998#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABH998-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Examplary subtitle@en
+
+
+
+
+ en
+ s
+
+
+ de
+ s
+
+
+
+
+ PARAMETER
+ Description
+
+
+ en
+ Document description
+
+
+ de
+ Dokumentenbeschreibung
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAN466#004
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-AAN466-004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Abstract@en
+
+
+
+
+ en
+ s
+
+
+ de
+ s
+
+
+
+
+ PARAMETER
+ KeyWords
+
+
+ en
+ Keywords
+
+
+ de
+ Stichworte
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABH999#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABH999-003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Examplary keywords@en
+
+
+
+
+ en
+ s
+
+
+ de
+ s
+
+
+
+
+ PARAMETER
+ PreviewFile
+
+
+ en
+ Preview file
+
+
+ de
+ Vorschaudatei
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABK127#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://api.eclass-cdp.com/0173-1-02-ABK127-002
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ docu_cecc_fullmanual_DE.jpg
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0
+
+
+
+ ConceptQualifier
+ AllowedIdShort
+ xs:string
+ PreviewFile[\d{2,3}]
+
+
+ image/jpeg
+
+
+
+
+
+
+ DocumentedEntities
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/vdi/2770/1/0/Document/DocumentedEntities
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ true
+ ReferenceElement
+
+
+
+
+
+
+ Entities
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/vdi/2770/1/0/EntitiesForDocumentation
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ true
+ Entity
+
+
+
+
+
+
+ KeyWords
+
+
+ en
+ Keywords
+
+
+ de
+ Stichworte
+
+
+ 0173-1#02-ABH999#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Keywords
+
+
+ de
+ Stichworte
+
+
+
+
+ en
+ Keywords
+
+
+ en
+ Stichworte
+
+
+ STRING_TRANSLATABLE
+
+
+ en
+ List of language-dependent keywords of the document
+
+
+ de
+ Liste der sprachabhängigen Schlüsselwörter des Dokuments
+
+
+
+
+
+
+
+
+ DocumentDomainId
+
+
+ en
+ document domain identificator
+
+
+ de
+ Document Domain Identifikator
+
+
+ 0173-1#02-ABH994#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document domain id
+
+
+ de
+ Dokument Domain Identifikator
+
+
+
+
+ en
+ DocDomainId
+
+
+ de
+ DokDomainId
+
+
+ STRING
+
+
+ en
+ Identification of the domain in which the given DocumentId is unique. The domain ID can e.g., be the name or acronym of the providing organisation
+
+
+ de
+ Identifikation der Domäne, in der die angegebene DocumentId eindeutig ist. Die Domain-ID kann z. B. der Name oder das Akronym der bereitstellenden Organisation sein
+
+
+
+
+
+
+
+
+ DocumentVersion
+
+
+ en
+ Document version
+
+
+ de
+ Document version
+
+
+ 0173-1#02-ABI503#003/0173-1#01-AHF582#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document version
+
+
+ en
+ Document version
+
+
+
+
+ en
+ DocuVersion
+
+
+ en
+ DokuVersion
+
+
+
+
+ en
+ Information about a document version entity
+
+
+ en
+ Information für eine Dokumentenversdions-Entität
+
+
+
+
+
+
+
+
+ StatusValue
+
+
+ en
+ Document status
+
+
+ de
+ Dokumentstatus
+
+
+ 0173-1#02-ABI001#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document status
+
+
+ de
+ Dokumentstatus
+
+
+
+
+ en
+ DocStatus
+
+
+ de
+ DokStatus
+
+
+
+
+ en
+ Each document version represents a point in time in the document life cycle. This status value refers to the milestones in the document life cycle. The following two values should be used for the application of this guideline: InReview (under review), Released (released)
+
+
+ de
+ Jede Dokumentversion repräsentiert einen Zeitpunkt im Dokumentlebenszyklus. Dieser Statuswert bezieht sich auf die Meilensteine im Dokumentenlebenszyklus. Für die Anwendung dieser Richtlinie sollten die folgenden zwei Werte verwendet werden: InReview (in Überprüfung), Released (freigegeben)
+
+
+
+
+
+
+
+
+ Description
+
+
+ en
+ Document description
+
+
+ de
+ Dokumentenbeschreibung
+
+
+ 0173-1#02-AAN466#004
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document description
+
+
+ de
+ Dokumentenbeschreibung
+
+
+
+
+ en
+ DocDescr
+
+
+ de
+ DokBeschreib
+
+
+ STRING_TRANSLATABLE
+
+
+ en
+ Plain text characterizing the content of the document
+
+
+ de
+ Klartext, der den Inhalt des Dokuments kennzeichnet
+
+
+
+
+
+
+
+
+ ClassificationSystem
+
+
+ en
+ Classification system
+
+
+ en
+ Klassifizierungssystem
+
+
+ 0173-1#02-ABH997#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Classification system
+
+
+ de
+ Klassifizierungssystem
+
+
+
+
+ en
+ ClassSystem
+
+
+ de
+ KlassSystem
+
+
+ STRING
+
+
+ en
+ Identification of the classification system
+
+
+ en
+ Identifikation des Klassifikationssystems
+
+
+
+
+
+
+
+
+ ClassId
+
+
+ en
+ Class identificator
+
+
+ de
+ Klassenidentifikator
+
+
+ 0173-1#02-ABH996#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Class identifyer
+
+
+ de
+ Klassenidentifikator
+
+
+
+
+ en
+ ClassId
+
+
+ de
+ KlassenId
+
+
+ STRING
+
+
+ en
+ Unique ID of the document class within a classficationsystem
+
+
+ de
+ Eindeutige ID der Dokumentenklasse innerhalb eines Klassifikationsystems
+
+
+
+
+
+
+
+
+ Title
+
+
+ en
+ Document title
+
+
+ de
+ Dokumententitel
+
+
+ 0173-1#02-ABG940#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document name
+
+
+ de
+ Dokumentenname
+
+
+
+
+ en
+ DocName
+
+
+ de
+ DokName
+
+
+ STRING_TRANSLATABLE
+
+
+ en
+ Name of the document
+
+
+ de
+ Name des Dokuments
+
+
+
+
+
+
+
+
+ Document
+
+
+ en
+ Document
+
+
+ de
+ Dokument
+
+
+
+
+ en
+ This SubmodelElementCollection holds the information for a VDI 2770 Document entity
+
+
+ 0173-1#02-ABI500#003/0173-1#01-AHF579#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document (handover documentation)
+
+
+ de
+ Dokument (Übergabedokumentation)
+
+
+
+
+ en
+ Document
+
+
+ en
+ Dokument
+
+
+
+
+ en
+ Each SubmodelElementCollection describes a document by standard, which is associated to the particular Asset Administration Shell
+
+
+ de
+ Jede SubmodelElementCollection beschreibt ein Dokument (siehe IEC 82045-1 und IEC 8245-2), das der jeweiligen Asset Administration Shell zugeordnet ist
+
+
+
+
+
+
+
+
+ DocumentIdentifier
+
+
+ en
+ Document identifyer
+
+
+ 0173-1#02-AAO099#004
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ DocumentIdentifier
+
+
+ be
+ Dokumentennummer
+
+
+
+
+ en
+ DocNumber
+
+
+ de
+ DokNummer
+
+
+ STRING
+
+
+ en
+ alphanumeric character sequence uniquely identifying a document
+
+
+ de
+ alphanumerische Zeichenfolge, die ein Dokument eindeutig identifiziert
+
+
+
+
+
+
+
+
+ HandoverDocumentation
+
+
+ en
+ The Submodel defines a set meta data for the handover of documentation from the manufacturer to the operator for industrial equipment
+
+
+ 0173-1#01-AHF578#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ HandoverDocumentation
+
+
+
+
+ en
+ The Submodel defines a set meta data for the handover of documentation from the manufacturer to the operator for industrial equipment
+
+
+
+
+
+
+
+
+ ClassName
+
+
+ en
+ Class Name
+
+
+ de
+ Klassenname
+
+
+ 0173-1#02-ABJ219#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Class name
+
+
+ de
+ Klassenname
+
+
+
+
+ en
+ ClassName
+
+
+ en
+ KlassName
+
+
+ STRING
+
+
+ en
+ Name of the class in the classification system
+
+
+ de
+ Name der Klasse im Klassifikationssystem
+
+
+
+
+
+
+
+
+ OrganizationOfficialName
+
+
+ en
+ Organization official name
+
+
+ de
+ Offizieller Name der Organisation
+
+
+ 0173-1#02-ABI004#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Organization official name
+
+
+ de
+ Offizieller Name der Organisation
+
+
+
+
+ en
+ OfficialName
+
+
+ de
+ OffiziellerName
+
+
+ STRING
+
+
+ en
+ Official name of the organization of the author of the document
+
+
+ de
+ Offizieller Name der Organisation des Autors des Dokuments
+
+
+
+
+
+
+
+
+ DocumentIsPrimary
+
+
+ en
+ Document is primary
+
+
+ de
+ Dokument ist primär
+
+
+ 0173-1#02-ABH995#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ DocumentIsPrimary
+
+
+ de
+ Dokument ist primär
+
+
+
+
+ en
+ DocPrimary
+
+
+ de
+ DokPrimär
+
+
+ BOOLEAN
+
+
+ en
+ Flag indicating that a DocumentId within a collection of at least two DocumentId`s is the ‘primary’ identifier for the document. This is the preferred ID of the document (commonly from the point of view of the owner of the asset)
+
+
+ de
+ Flag, das angibt, dass eine DocumentId innerhalb einer Sammlung von mindestens zwei DocumentIds die „primäre“ Kennung für das Dokument ist. Dies ist die bevorzugte ID des Dokuments (üblicherweise aus Sicht des Eigentümers des Assets)
+
+
+
+
+
+
+
+
+ DocumentId
+
+
+ en
+ Document identificator
+
+
+ de
+ Dokumentidentifikator
+
+
+ 0173-1#02-ABI501#003/0173-1#01-AHF580#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document identificator
+
+
+ de
+ Dokumentidentifikator
+
+
+
+
+ en
+ DocuId
+
+
+ de
+ DokuId
+
+
+
+
+ en
+ Information about a document identification entity
+
+
+ de
+ Information für eine Dokumentenidentifikations-Entität
+
+
+
+
+
+
+
+
+ Subtitle
+
+
+ en
+ Subtitle
+
+
+ de
+ Untertitel
+
+
+ 0173-1#02-ABH998#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Subtitle
+
+
+ de
+ Untertitel
+
+
+
+
+ en
+ Subtitle
+
+
+ de
+ Untertitel
+
+
+ STRING_TRANSLATABLE
+
+
+ en
+ List of language-dependent subtitles of the document
+
+
+ de
+ Liste der sprachabhängigen Untertitel des Dokuments
+
+
+
+
+
+
+
+
+ StatusSetDate
+
+
+ en
+ Document status set date
+
+
+ de
+ Datum der Einstellung des Dokumentenstatus
+
+
+ 0173-1#02-ABI000#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document status set date
+
+
+ de
+ Datum der Einstellung des Dokumentenstatus
+
+
+
+
+ en
+ SetDate
+
+
+ de
+ SetDatum
+
+
+
+
+ en
+ Date when the document status was set
+
+
+ de
+ Datum, an dem der Dokumentenstatus gesetzt wurde
+
+
+
+
+
+
+
+
+ Version
+
+
+ en
+ Document version
+
+
+ de
+ Dokumentenversion
+
+
+ 0173-1#02-AAP003#005
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document version
+
+
+ de
+ Dokumentenversion
+
+
+
+
+ en
+ DocVersion
+
+
+ de
+ DokVersion
+
+
+ STRING
+
+
+ en
+ Design that partly deviates from the previous
+
+
+ de
+ Ausführung, die in einigen Punkten von der vorhergehenden abweicht
+
+
+
+
+
+
+
+
+ DocumentClassification
+
+
+ en
+ Document classification
+
+
+ de
+ Dokumentklassifikation
+
+
+ 0173-1#02-ABI502#003/0173-1#01-AHF581#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Document classification
+
+
+ en
+ Dokumentklassifikation
+
+
+
+
+ en
+ DocuClass
+
+
+ en
+ DokuKlass
+
+
+
+
+ en
+ Information about a document classification entity
+
+
+ de
+ Information für eine Dokumentenklassifikations-Entität
+
+
+
+
+
+
+
+
+ OrganizationShortName
+ https://api.eclass-cdp.com/0173-1-02-ABI002-003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ Organization Short Name
+
+
+
+
+ en
+ Short name of the organization
+
+
+
+
+
+
+
+
+
diff --git a/example/aas/Nameplate.xml b/example/aas/Nameplate.xml
new file mode 100644
index 0000000..f428fd1
--- /dev/null
+++ b/example/aas/Nameplate.xml
@@ -0,0 +1,2071 @@
+
+
+
+
+ DigitalNameplateAAS
+ https://admin-shell.io/idta/aas/DigitalNameplate/3/0
+
+ Type
+ https://admin-shell.io/idta/asset/DigitalNameplate/3/0
+ Type
+
+
+
+ ModelReference
+
+
+ Submodel
+ https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0
+
+
+
+
+
+
+
+
+ Nameplate
+
+
+ en
+ Contains the nameplate information attached to the product
+
+
+
+ 3
+ 0
+ https://admin-shell.io/idta-02006-3-0
+
+ https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0
+ Template
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/nameplate/3/0/Nameplate
+
+
+
+
+
+ URIOfTheProduct
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABN590#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABH173#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:anyURI
+ https://www.domain-abc.com/Model-Nr-1234/Serial-Nr-5678
+
+
+ ManufacturerProductType
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA300#008
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO057#004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ FM-ABC-1234
+
+
+ OrderCodeOfManufacturer
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA950#008
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO227#004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+ FMABC1234
+
+
+ ProductArticleNumberOfManufacturer
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA581#007
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO676#005
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ FM11-ABC22-123456
+
+
+ SerialNumber
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA951#009
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAM556#004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 12345678
+
+
+ YearOfConstruction
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABP000#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAP906#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 2022
+
+
+ DateOfManufacture
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABB757#007
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAR972#004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:date
+ 2022-01-01
+
+
+ HardwareVersion
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA926#008
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAN270#004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 1.0.0
+
+
+ FirmwareVersion
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA302#006
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAM985#004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 1.0.0
+
+
+ SoftwareVersion
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA601#008
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAM737#004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 1.0.0
+
+
+ CountryOfOrigin
+
+
+ en
+ Note: Country codes defined accord. to DIN EN ISO 3166-1 alpha-2 codes
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABP462#001
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO259#007
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ DE
+
+
+ UniqueFacilityIdentifier
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/idta/nameplate/3/0/UniqueFacilityIdentifier
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ 987654321
+
+
+ ManufacturerName
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA565#009
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO677#004
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+
+ de
+ "Muster AG"
+
+
+
+
+ ManufacturerProductDesignation
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA567#009
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAW338#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+
+ en
+ "ABC-123"
+
+
+
+
+ ManufacturerProductRoot
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61360_7#AAS011#001
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAU732#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ "flow meter"
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABP464#002
+
+
+
+
+
+ ManufacturerProductFamily
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABP464#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAU731#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+
+ en
+ "Type ABC"
+
+
+
+
+ AddressInformation
+
+
+ en
+ Note: this set of information is defined by SMT drop-in "Address Information"
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/AddressInformation
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/smt-dropin/smt-dropin-use/1/0
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61360_7#AAS002#001
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAQ837#008/0173-1#01-ADR448#008
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+
+
+ AssetSpecificProperties
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI218#003/0173-1#01-AGZ672#004
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+
+ GuidelineSpecificProperties
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI219#003/0173-1#01-AHD205#004
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ true
+ SubmodelElementCollection
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#01-AHD205#004
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ OneToMany
+
+
+
+
+
+
+
+
+ CompanyLogo
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABP463#001
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI776#002
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ image/png
+
+
+ Markings
+
+
+ en
+ Note: CE marking is declared as mandatory according to EU Blue Guide
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61360_7#AAS006#001
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI563#003/0173-1#01-AHF849#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ true
+ SubmodelElementCollection
+
+
+ Marking
+
+
+ en
+ Note: CE marking is declared as mandatory according to the Blue Guide of the EU-Commission
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61360_7#AAS009#001
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI564#003/0173-1#01-AHF850#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ OneToMany
+
+
+
+
+ MarkingName
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABA231#009
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI190#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ xs:string
+ 0173-1#07-DAA603#004
+
+
+ DesignationOfCertificateOrApproval
+
+
+ en
+ Note: Approval identifier, reference to the certificate number, to be entered without spaces
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABH783#003
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI975#002
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:string
+ KEMA99IECEX1105/128
+
+
+ IssueDate
+
+
+ en
+ Note: format by lexical representation: CCYY-MM-DD Note: to be specified to the day
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABO097#001
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABL774#001
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:date
+ 2022-01-01
+
+
+ ExpiryDate
+
+
+ en
+ Note: format by lexical representation: CCYY-MM-DD Note: to be specified to the day
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABH830#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABL775#001
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToOne
+
+
+ xs:date
+ 2022-01-01
+
+
+ MarkingAdditionalText
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABB146#007
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI192#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ ZeroToMany
+
+
+ xs:string
+ 0044
+
+
+ MarkingFile
+
+ ExternalReference
+
+
+ GlobalReference
+ 0112/2///61987#ABO100#002
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-ABI191#003
+
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ TemplateQualifier
+ SMT/Cardinality
+ xs:string
+ One
+
+
+ image/png
+
+
+
+
+
+
+
+
+
+
+ DateOfManufacture
+ 0112/2///61987#ABB757#007
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ DateOfManufacture
+
+
+ DATE
+
+
+ en
+ date when an item was manufactured
+
+
+
+
+
+
+
+
+ MarkingAdditionalText__00__
+ 0112/2///61987#ABB146#007
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ MarkingAdditionalText__00__
+
+
+ STRING
+
+
+ en
+ where applicable, additional information on the marking in plain text, e.g. the ID-number of the notified body involved in the conformity process
+
+
+
+
+
+
+
+
+ MarkingName
+ 0112/2///61987#ABA231#009
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ MarkingName
+
+
+ STRING
+
+
+ en
+ common name of the marking
+
+
+
+
+
+
+
+
+ IssueDate
+ 0112/2///61987#ABO097#001
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ IssueDate
+
+
+ DATE
+
+
+ en
+ date, at which the specified certificate is issued
+
+
+
+
+
+
+
+
+ FirmwareVersion
+ 0112/2///61987#ABA302#006
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ FirmwareVersion
+
+
+ STRING
+
+
+ en
+ version of the firmware supplied with the device
+
+
+
+
+
+
+
+
+ SerialNumber
+ 0112/2///61987#ABA951#009
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ SerialNumber
+
+
+ STRING
+
+
+ en
+ unique combination of numbers and letters used to identify the device once it has been manufactured
+
+
+
+
+
+
+
+
+ ManufacturerName
+ 0112/2///61987#ABA565#009
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerName
+
+
+ STRING_TRANSLATABLE
+
+
+ en
+ legally valid designation of the natural or judicial person which is directly responsible for the design, production, packaging and labeling of a product in respect to its being brought into circulation
+
+
+
+
+
+
+
+
+ ManufacturerProductRoot
+ 0112/2///61360_7#AAS011#001
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerProductRoot
+
+
+ STRING_TRANSLATABLE
+
+
+ en
+ top level of a 3 level manufacturer specific product hierarchy
+
+
+
+
+
+
+
+
+ YearOfConstruction
+ 0112/2///61987#ABP000#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ YearOfConstruction
+
+
+ STRING
+
+
+ en
+ year in which the manufacturing process is completed
+
+
+
+
+
+
+
+
+ UniqueFacilityIdentifier
+ https://admin-shell.io/idta/nameplate/3/0/UniqueFacilityIdentifier
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ UniqueFacilityIdentifier
+
+
+ STRING
+
+
+ en
+ unique string of characters for the identification of locations or buildings involved in a product’s value chain or used by actors involved in a product’s value chain
+
+
+
+
+
+
+
+
+ OrderCodeOfManufacturer
+ 0112/2///61987#ABA950#008
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ OrderCodeOfManufacturer
+
+
+ STRING
+
+
+ en
+ unique combination of numbers and letters issued by the manufacturer that is used to identify the device for ordering
+
+
+
+
+
+
+
+
+ DesignationOfCertificateOrApproval
+ 0112/2///61987#ABH783#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ DesignationOfCertificateOrApproval
+
+
+ STRING
+
+
+ en
+ alphanumeric character sequence identifying a certificate or approval
+
+
+
+
+
+
+
+
+ ManufacturerProductType
+ 0112/2///61987#ABA300#008
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerProductType
+
+
+ STRING
+
+
+ en
+ characteristic to differentiate between different products of a product family or special variants
+
+
+
+
+
+
+
+
+ ManufacturerProductFamily
+ 0112/2///61987#ABP464#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerProductFamily
+
+
+ STRING_TRANSLATABLE
+
+
+ en
+ second level of a 3 level manufacturer specific product hierarchy
+
+
+
+
+
+
+
+
+ SoftwareVersion
+ 0112/2///61987#ABA601#008
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ SoftwareVersion
+
+
+ STRING
+
+
+ en
+ version of the software used by the device
+
+
+
+
+
+
+
+
+ ProductArticleNumberOfManufacturer
+ 0112/2///61987#ABA581#007
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ProductArticleNumberOfManufacturer
+
+
+ STRING
+
+
+ en
+ unique product identifier of the manufacturer
+
+
+
+
+
+
+
+
+ URIOfTheProduct
+ 0112/2///61987#ABN590#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ URIOfTheProduct
+
+
+
+
+ en
+ URIOfTheProduct
+
+
+ STRING
+
+
+ en
+ unique global identification of the product instance using an universal resource identifier (URI)
+
+
+
+
+
+
+
+
+ Marking
+
+
+ en
+ Note: CE marking is declared as mandatory according to the Blue Guide of the EU-Commission
+
+
+ 0112/2///61360_7#AAS009#001
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ Marking
+
+
+
+
+ en
+ Single marking information
+
+
+
+
+
+
+
+
+ ExpiryDate
+ 0112/2///61987#ABH830#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ExpiryDate
+
+
+ DATE
+
+
+ en
+ date, at which the specified certificate expires
+
+
+
+
+
+
+
+
+ CountryOfOrigin
+ 0112/2///61987#ABP462#001
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ CountryOfOrigin
+
+
+ STRING
+
+
+ en
+ country where the product was manufactured
+
+
+
+
+
+
+
+
+ ManufacturerProductDesignation
+ 0112/2///61987#ABA567#009
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerProductDesignation
+
+
+ STRING_TRANSLATABLE
+
+
+ en
+ short description of the product (short text), third or lowest level of a 3 level manufacturer specific product hierarchy
+
+
+
+
+
+
+
+
+ HardwareVersion
+ 0112/2///61987#ABA926#008
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360/3/0
+
+
+
+
+
+
+
+ en
+ HardwareVersion
+
+
+ STRING
+
+
+ en
+ version of the hardware supplied with the device
+
+
+
+
+
+
+
+
+
diff --git a/example/aas/TechnicalData.xml b/example/aas/TechnicalData.xml
new file mode 100644
index 0000000..0a3239f
--- /dev/null
+++ b/example/aas/TechnicalData.xml
@@ -0,0 +1,1659 @@
+
+
+
+ TechnicalDataAAS
+ https://admin-shell.io/aas/TechnicalData/1/2
+
+ ModelReference
+
+
+ AssetAdministrationShell
+ https://admin-shell.io/aas/TechnicalData/1/2
+
+
+
+
+ Type
+ https://admin-shell.io/asset/TechnicalData/1/2
+ Type
+
+
+
+ ModelReference
+
+
+ Submodel
+ https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2
+
+
+
+
+
+
+
+
+ TechnicalData
+
+
+ en
+ Submodel containing techical data of the asset and associated product classificatons.
+
+
+ de
+ Teilmodell, das die technischen Daten der Anlage und die zugehörigen Produktklassifizierungen enthält.
+
+
+
+ 1
+ 2
+
+ https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2
+ Template
+
+ ModelReference
+
+
+ Submodel
+ https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2
+
+
+
+
+
+ GeneralInformation
+
+
+ en
+ General information, for example ordering and manufacturer information.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/GeneralInformation/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+
+ PARAMETER
+ ManufacturerName
+
+
+ en
+ Legally valid designation of the natural or judicial body which is directly responsible for the design, production, packaging and labeling of a product in respect to its being brought into the market.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO677#002
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Example Company
+
+
+ xs:string
+
+
+ PARAMETER
+ ManufacturerArticleNumber
+
+
+ en
+ unique product identifier of the manufacturer
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO676#003
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ A123-456
+
+
+ xs:string
+
+
+ PARAMETER
+ ManufacturerOrderCode
+
+
+ en
+ By manufactures issued unique combination of numbers and letters used to identify the device for ordering
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAO227#002
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ EEA-EX-200-S/47-Q3
+
+
+ xs:string
+
+
+ ManufacturerLogo
+
+
+ en
+ Imagefile for logo of manufacturer provided in common format (.png, .jpg).
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/ManufacturerLogo/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToOne
+
+
+ image/png
+
+
+ ProductImage
+
+
+ en
+ Image file for associated product provided in common format (.png, .jpg).
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/ProductImage/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToMany
+
+
+ image/png
+
+
+ PARAMETER
+ ManufacturerProductDesignation
+
+
+ en
+ Product designation as given by the mnaufacturer. Short description of the product, product group or function (short text) in common language.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ 0173-1#02-AAW338#001
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Electrical energy accelerator@en
+
+
+
+
+ en
+ a
+
+
+ de
+ a
+
+
+
+
+
+
+ ProductClassifications
+
+
+ en
+ Product classifications by association of product classes with common classification systems.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/ProductClassifications/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+
+ ProductClassificationItem
+
+
+ en
+ Single product classification item by association with product class in a particular classification system or property dictionary.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/ProductClassificationItem/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToMany
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0
+
+
+
+ ConceptQualifier
+ AllowedIdShort
+ xs:string
+ ProductClassificationItem[\d{2,3}]
+
+
+
+
+ PARAMETER
+ ProductClassificationSystem
+
+
+ en
+ Common name of the classification system.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/ProductClassificationSystem/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ ECLASS
+
+
+ xs:string
+
+
+ PARAMETER
+ ClassificationSystemVersion
+
+
+ en
+ Common version identifier of the used classification system, in order to distinguish different version of the property dictionary.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/ClassificationSystemVersion/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ 9.0 (BASIC)
+
+
+ xs:string
+
+
+ PARAMETER
+ ProductClassId
+
+
+ en
+ Class of the associated product or industrial equipment in the classification system. According to the notation of the system.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/ProductClassId/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ 27-01-88-77 | 0112/2///61987#ABA827#003
+
+
+ xs:string
+
+
+
+
+
+
+ TechnicalProperties
+
+
+ en
+ Individual characteristics that describe the product and its technical properties.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/TechnicalProperties/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+
+ MainSection
+
+
+ en
+ Main subdivision possibility for properties.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/MainSection/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToMany
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0
+
+
+
+ ConceptQualifier
+ AllowedIdShort
+ xs:string
+ MainSection[\d{2,3}]
+
+
+
+
+ SubSection
+
+
+ en
+ Subordinate subdivision possibility for properties.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/SubSection/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToMany
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0
+
+
+
+ ConceptQualifier
+ AllowedIdShort
+ xs:string
+ SubSection[\d{2,3}]
+
+
+
+
+
+
+ SubSection
+
+
+ en
+ Subordinate subdivision possibility for properties.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/SubSection/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToMany
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0
+
+
+
+ ConceptQualifier
+ AllowedIdShort
+ xs:string
+ SubSection[\d{2,3}]
+
+
+
+
+
+
+ FurtherInformation
+
+
+ en
+ Further information on the product, the validity of the information provided and this data record.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/FurtherInformation/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToOne
+
+
+
+
+ PARAMETER
+ TextStatement
+
+
+ en
+ Statement by the manufacturer in text form, e.g. scope of validity of the statements, scopes of application, conditions of operation.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/TextStatement/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ ZeroToMany
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ Restricted use@en
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/AllowedIdShort/1/0
+
+
+
+ ConceptQualifier
+ AllowedIdShort
+ xs:string
+ TextStatement[\d{2,3}]
+
+
+
+
+ en
+ a
+
+
+ de
+ a
+
+
+
+
+ PARAMETER
+ ValidDate
+
+
+ en
+ Denotes a date on which the data specified in the Submodel was valid from for the associated asset.
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/ZVEI/TechnicalData/ManufacturerOrderCode/1/1
+
+
+
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/Cardinality/1/0
+
+
+
+ ConceptQualifier
+ Cardinality
+ xs:string
+ One
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/SubmodelTemplates/ExampleValue/1/0
+
+
+
+ ConceptQualifier
+ ExampleValue
+ xs:string
+ 5/28/2021
+
+
+ xs:date
+
+
+
+
+
+
+
+
+ TechnicalData
+
+
+ en
+ Submodel containing techical data of the asset and associated product classificatons.
+
+
+ de
+ Teilmodell, das die technischen Daten der Anlage und die zugehörigen Produktklassifizierungen enthält.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ TechnicalData
+
+
+
+
+ en
+ Submodel containing techical data of the asset and associated product classificatons.
+
+
+
+
+
+
+
+
+ GeneralInformation
+
+
+ en
+ General information, for example ordering and manufacturer information.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/GeneralInformation/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ GeneralInformation
+
+
+
+
+ en
+ General information, for example ordering and manufacturer information.
+
+
+
+
+
+
+
+
+ ProductClassificationSystem
+
+
+ en
+ Common name of the classification system.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/ProductClassificationSystem/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ProductClassificationSystem
+
+
+
+
+ en
+ Common name of the classification system.
+
+
+
+
+
+
+
+
+ ManufacturerName
+
+
+ en
+ Legally valid designation of the natural or judicial body which is directly responsible for the design, production, packaging and labeling of a product in respect to its being brought into the market.
+
+
+ 0173-1#02-AAO677#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerName
+
+
+
+
+ en
+ Legally valid designation of the natural or judicial body which is directly responsible for the design, production, packaging and labeling of a product in respect to its being brought into the market.
+
+
+
+
+
+
+
+
+ TextStatement
+
+
+ en
+ Statement by the manufacturer in text form, e.g. scope of validity of the statements, scopes of application, conditions of operation.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/TextStatement/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ TextStatement
+
+
+
+
+ en
+ Statement by the manufacturer in text form, e.g. scope of validity of the statements, scopes of application, conditions of operation.
+
+
+
+
+
+
+
+
+ FurtherInformation
+
+
+ en
+ Further information on the product, the validity of the information provided and this data record.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/FurtherInformation/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ FurtherInformation
+
+
+
+
+ en
+ Further information on the product, the validity of the information provided and this data record.
+
+
+
+
+
+
+
+
+ ProductClassifications
+
+
+ en
+ Product classifications by association of product classes with common classification systems.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/ProductClassifications/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ProductClassifications
+
+
+
+
+ en
+ Product classifications by association of product classes with common classification systems.
+
+
+
+
+
+
+
+
+ SubSection
+
+
+ en
+ Subordinate subdivision possibility for properties.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/SubSection/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ SubSection
+
+
+
+
+ en
+ Subordinate subdivision possibility for properties.
+
+
+
+
+
+
+
+
+ ManufacturerOrderCode
+
+
+ en
+ By manufactures issued unique combination of numbers and letters used to identify the device for ordering
+
+
+ 0173-1#02-AAO227#002
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerOrderCode
+
+
+
+
+ en
+ By manufactures issued unique combination of numbers and letters used to identify the device for ordering
+
+
+
+
+
+
+
+
+ ProductClassificationItem
+
+
+ en
+ Single product classification item by association with product class in a particular classification system or property dictionary.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/ProductClassificationItem/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ProductClassificationItem
+
+
+
+
+ en
+ Single product classification item by association with product class in a particular classification system or property dictionary.
+
+
+
+
+
+
+
+
+ ProductClassId
+
+
+ en
+ Class of the associated product or industrial equipment in the classification system. According to the notation of the system.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/ProductClassId/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ProductClassId
+
+
+
+
+ en
+ Class of the associated product or industrial equipment in the classification system. According to the notation of the system.
+
+
+
+
+
+
+
+
+ ManufacturerArticleNumber
+
+
+ en
+ unique product identifier of the manufacturer
+
+
+ 0173-1#02-AAO676#003
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerArticleNumber
+
+
+
+
+ en
+ unique product identifier of the manufacturer
+
+
+
+
+
+
+
+
+ ValidDate
+
+
+ en
+ Denotes a date on which the data specified in the Submodel was valid from for the associated asset.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/ManufacturerOrderCode/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ValidDate
+
+
+
+
+ en
+ Denotes a date on which the data specified in the Submodel was valid from for the associated asset.
+
+
+
+
+
+
+
+
+ ClassificationSystemVersion
+
+
+ en
+ Common version identifier of the used classification system, in order to distinguish different version of the property dictionary.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/ClassificationSystemVersion/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ClassificationSystemVersion
+
+
+
+
+ en
+ Common version identifier of the used classification system, in order to distinguish different version of the property dictionary.
+
+
+
+
+
+
+
+
+ MainSection
+
+
+ en
+ Main subdivision possibility for properties.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/MainSection/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ MainSection
+
+
+
+
+ en
+ Main subdivision possibility for properties.
+
+
+
+
+
+
+
+
+ TechnicalProperties
+
+
+ en
+ Individual characteristics that describe the product and its technical properties.
+
+
+ https://admin-shell.io/ZVEI/TechnicalData/TechnicalProperties/1/1
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ TechnicalProperties
+
+
+
+
+ en
+ Individual characteristics that describe the product and its technical properties.
+
+
+
+
+
+
+
+
+ ManufacturerProductDesignation
+
+
+ en
+ Product designation as given by the mnaufacturer. Short description of the product, product group or function (short text) in common language.
+
+
+ 0173-1#02-AAW338#001
+
+
+
+ ExternalReference
+
+
+ GlobalReference
+ https://admin-shell.io/DataSpecificationTemplates/DataSpecificationIec61360/3/0
+
+
+
+
+
+
+
+ en
+ ManufacturerProductDesignation
+
+
+
+
+ en
+ Product designation as given by the mnaufacturer. Short description of the product, product group or function (short text) in common language.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apiCollection/Aas Registry/Get All ShellDescriptors.bru b/example/apiCollection/Aas Registry/Get All ShellDescriptors.bru
similarity index 100%
rename from apiCollection/Aas Registry/Get All ShellDescriptors.bru
rename to example/apiCollection/Aas Registry/Get All ShellDescriptors.bru
diff --git a/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru b/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru
new file mode 100644
index 0000000..549bcf8
--- /dev/null
+++ b/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product1.bru
@@ -0,0 +1,25 @@
+meta {
+ name: Get Shell Descriptor By Id - Product1
+ type: http
+ seq: 2
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shell-descriptors/:aasIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-1}}
+}
+
+script:pre-request {
+
+
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru b/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru
new file mode 100644
index 0000000..f4ece14
--- /dev/null
+++ b/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product2.bru
@@ -0,0 +1,25 @@
+meta {
+ name: Get Shell Descriptor By Id - Product2
+ type: http
+ seq: 3
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shell-descriptors/:aasIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-2}}
+}
+
+script:pre-request {
+
+
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru b/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru
new file mode 100644
index 0000000..69a7745
--- /dev/null
+++ b/example/apiCollection/Aas Registry/Get Shell Descriptor By Id - Product3.bru
@@ -0,0 +1,25 @@
+meta {
+ name: Get Shell Descriptor By Id - Product3
+ type: http
+ seq: 4
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shell-descriptors/:aasIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-3}}
+}
+
+script:pre-request {
+
+
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Registry/folder.bru b/example/apiCollection/Aas Registry/folder.bru
new file mode 100644
index 0000000..4d45dcd
--- /dev/null
+++ b/example/apiCollection/Aas Registry/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: Aas Registry
+ seq: 2
+}
+
+auth {
+ mode: inherit
+}
diff --git a/example/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru b/example/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru
new file mode 100644
index 0000000..eb0df9f
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product1/Get Asset Information By Id.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Asset Information By Id
+ type: http
+ seq: 1
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/asset-information
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product1/Get Shell By Id.bru b/example/apiCollection/Aas Repository/Product1/Get Shell By Id.bru
new file mode 100644
index 0000000..2f49754
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product1/Get Shell By Id.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Shell By Id
+ type: http
+ seq: 1
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru b/example/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru
new file mode 100644
index 0000000..fad3978
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product1/Get Submodel Ref By Id.bru
@@ -0,0 +1,25 @@
+meta {
+ name: Get Submodel Ref By Id
+ type: http
+ seq: 2
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/submodel-refs?limit&cursor
+ body: none
+ auth: inherit
+}
+
+params:query {
+ limit:
+ cursor:
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product1/folder.bru b/example/apiCollection/Aas Repository/Product1/folder.bru
new file mode 100644
index 0000000..a64c644
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product1/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: Product1
+ seq: 1
+}
+
+auth {
+ mode: inherit
+}
diff --git a/example/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru b/example/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru
new file mode 100644
index 0000000..72d5c9b
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product2/Get Asset Information By Id.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Asset Information By Id
+ type: http
+ seq: 1
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/asset-information
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-2}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product2/Get Shell By Id.bru b/example/apiCollection/Aas Repository/Product2/Get Shell By Id.bru
new file mode 100644
index 0000000..e0901d9
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product2/Get Shell By Id.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Shell By Id
+ type: http
+ seq: 2
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-2}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru b/example/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru
new file mode 100644
index 0000000..43cd8ea
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product2/Get Submodel Ref By Id.bru
@@ -0,0 +1,25 @@
+meta {
+ name: Get Submodel Ref By Id
+ type: http
+ seq: 3
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/submodel-refs?limit&cursor
+ body: none
+ auth: inherit
+}
+
+params:query {
+ limit:
+ cursor:
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-2}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product2/folder.bru b/example/apiCollection/Aas Repository/Product2/folder.bru
new file mode 100644
index 0000000..eef6323
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product2/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: Product2
+ seq: 2
+}
+
+auth {
+ mode: inherit
+}
diff --git a/example/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru b/example/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru
new file mode 100644
index 0000000..62e52a2
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product3/Get Asset Information By Id.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Asset Information By Id
+ type: http
+ seq: 1
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/asset-information
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-3}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product3/Get Shell By Id.bru b/example/apiCollection/Aas Repository/Product3/Get Shell By Id.bru
new file mode 100644
index 0000000..1fe6f17
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product3/Get Shell By Id.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Shell By Id
+ type: http
+ seq: 2
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-3}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru b/example/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru
new file mode 100644
index 0000000..cf736ec
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product3/Get Submodel Ref By Id.bru
@@ -0,0 +1,25 @@
+meta {
+ name: Get Submodel Ref By Id
+ type: http
+ seq: 3
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/shells/:aasIdentifier/submodel-refs?limit&cursor
+ body: none
+ auth: inherit
+}
+
+params:query {
+ limit:
+ cursor:
+}
+
+params:path {
+ aasIdentifier: {{aasIdentifier-3}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Aas Repository/Product3/folder.bru b/example/apiCollection/Aas Repository/Product3/folder.bru
new file mode 100644
index 0000000..a102df2
--- /dev/null
+++ b/example/apiCollection/Aas Repository/Product3/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: Product3
+ seq: 3
+}
+
+auth {
+ mode: inherit
+}
diff --git a/example/apiCollection/Aas Repository/folder.bru b/example/apiCollection/Aas Repository/folder.bru
new file mode 100644
index 0000000..3720e72
--- /dev/null
+++ b/example/apiCollection/Aas Repository/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: Aas Repository
+ seq: 3
+}
+
+auth {
+ mode: inherit
+}
diff --git a/example/apiCollection/README.md b/example/apiCollection/README.md
new file mode 100644
index 0000000..d364248
--- /dev/null
+++ b/example/apiCollection/README.md
@@ -0,0 +1,160 @@
+# Bruno API Testing Setup – DataEngine (.NET Backend)
+
+## Overview
+
+This directory contains the Bruno collection and instructions to test the **AAS.TwinEngine.DataEngine** .NET API using Bruno. The collection includes pre-configured requests and environments to exercise the DataEngine API and its plugin-based data sources.
+
+---
+
+## Quick Summary
+
+| Item | Description |
+|--------------------------|-----------------------------------------------------|
+| **API** | `AAS.TwinEngine.DataEngine` (.NET) |
+| **Testing Tool** | [Bruno](https://www.usebruno.com/downloads) |
+| **Default API URL** | `http://localhost:8080` |
+| **SDK Required** | .NET 8 (recommended) |
+| **Run docker compose file** | Run `docker-compose-up` [form AasTwin.DataEngine](../README.md) |
+
+---
+
+## Prerequisites
+
+1. **Install Bruno**
+
+ * Download: [https://www.usebruno.com/downloads](https://www.usebruno.com/downloads)
+ * Platforms: Windows, macOS, Linux
+
+2. **Install .NET SDK**
+
+ * Recommended: **.NET 8** (install from Microsoft docs)
+
+3. **Install docker**
+
+---
+
+## Running the services
+
+
+### 1. Run docker compose file
+
+Before starting , run twinengine environmnet with dpp-plugin.
+[click here for getting starated with docker-compose](../README.md)
+
+
+## Bruno Collection — Quick Start
+
+1. Open Bruno
+2. `Collection -> Open Collection` and choose the Bruno collection folder (`apiCollection`) from the AasTwin.DataEngine repository
+3. From the top-right environment dropdown select an environment: `local`
+4. Expand folders to find requests, select a request and click **Send**
+5. Inspect the request/response in the right panel
+
+---
+
+## Bruno environment & collection variables
+
+The collection includes a set of environment/collection variables you can edit to point the requests at your local or dev instance.
+**Enter these variables in plain text — the collection’s Pre-request script will automatically change value to Base64-encode.**
+
+| Variable name | Purpose | Example value |
+| ------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
+| `DataEngineBaseUrl` | Base URL for DataEngine API | `http://localhost:8080` |
+| `productId-1` | Product ID for first asset | `000-001` |
+| `productId-2` | Product ID for second asset | `000-002` |
+| `productId-3` | Product ID for third asset | `001-001` |
+| `aasIdentifier-1` | AAS identifier (auto-encoded to Base64 by script) | `https://mm-software.com/ids/aas/000-001` |
+| `aasIdentifier-2` | AAS identifier (auto-encoded to Base64 by script) | `https://mm-software.com/ids/aas/000-002` |
+| `aasIdentifier-3` | AAS identifier (auto-encoded to Base64 by script) | `https://mm-software.com/ids/aas/001-001` |
+| `submodelIdentifierContact-1` | Submodel identifier for ContactInformation (auto-encoded) | `https://mm-software.com/submodel/000-001/ContactInformation` |
+| `submodelIdentifierNameplate-1` | Submodel identifier for Nameplate (auto-encoded) | `https://mm-software.com/submodel/000-001/Nameplate` |
+| `submodelIdentifierTechnicalData-1` | Submodel identifier for TechnicalData (auto-encoded) | `https://mm-software.com/submodel/000-001/TechnicalData` |
+| `submodelIdentifierCarbonFootprint-1` | Submodel identifier for CarbonFootprint (auto-encoded) | `https://mm-software.com/submodel/000-001/CarbonFootprint` |
+| `submodelIdentifierHandoverDocumentation-1` | Submodel identifier for HandoverDocumentation (auto-encoded) | `https://mm-software.com/submodel/000-001/HandoverDocumentation` |
+
+**Note:** All identifier variables (aasIdentifier-*, submodelIdentifier-*) are automatically Base64-encoded by the collection's pre-request script. Enter plain URLs as shown above.
+
+---
+
+## Default api-test configuration
+
+* The default configuration includes four shell descriptors with these IDs:
+
+ * `https://mm-software.com/ids/aas/000-001`
+ * `https://mm-software.com/ids/aas/000-002`
+ * `https://mm-software.com/ids/aas/001-001`
+
+* Default submodel templates (under `../aas`):
+
+ * `ContactInformation`
+ * `Nameplate`
+ * `HandoverDocumentation`
+ * `CarbonFootprint`
+ * `TechnicalData`
+
+* Default shell template used by all 5 shells:
+
+```json
+{
+ "id": "https://mm-software.com/aas/aasTemplate",
+ "assetInformation": {
+ "assetKind": "Instance"
+ },
+ "submodels": [
+ {
+ "type": "ModelReference",
+ "keys": [
+ { "type": "Submodel", "value": "Nameplate" }
+ ]
+ },
+ {
+ "type": "ModelReference",
+ "keys": [
+ { "type": "Submodel", "value": "ContactInformation" }
+ ]
+ },
+ {
+ "type": "ModelReference",
+ "keys": [
+ { "type": "Submodel", "value": "HandoverDocumentation" }
+ ]
+ },
+ {
+ "type": "ModelReference",
+ "keys": [
+ { "type": "Submodel", "value": "CarbonFootprint" }
+ ]
+ },
+ {
+ "type": "ModelReference",
+ "keys": [
+ { "type": "Submodel", "value": "TechnicalData" }
+ ]
+ }
+ ],
+ "modelType": "AssetAdministrationShell"
+}
+```
+
+---
+
+## Useful requests & folders
+
+* **Aas Registry** — endpoints to get all ShellDescriptors and ShellDescriptor by id
+* **Aas Repository** — endpoints to get Shell by id, SubmodelRef by id, Asset Information by id
+* **Submodel Registry** — endpoints to get SubmodelDescriptor by id
+* **Submodel Repository** — endpoints to get submodel, submodelElement, and serialization
+
+(Each Bruno request contains example payloads.)
+
+---
+
+## Troubleshooting
+
+#### Bruno shows `SSL/TLS handshake failed`
+
+- Run `dotnet dev-certs https --trust`
+- Ensure plugin and API endpoints match port and schema (`https://`)
+
+
+---
diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru
new file mode 100644
index 0000000..77916ba
--- /dev/null
+++ b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - CarbonFootprint.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel Descriptor By Id - CarbonFootprint
+ type: http
+ seq: 3
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierCarbonFootprint-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Contact.bru b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Contact.bru
new file mode 100644
index 0000000..a9265fc
--- /dev/null
+++ b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Contact.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel Descriptor By Id - Contact
+ type: http
+ seq: 1
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierContact-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru
new file mode 100644
index 0000000..66fb37a
--- /dev/null
+++ b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - HandoverDocumentation.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel Descriptor By Id - HandoverDocumentation
+ type: http
+ seq: 4
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierHandoverDocumentation-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru
new file mode 100644
index 0000000..08b73d4
--- /dev/null
+++ b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - Nameplate.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel Descriptor By Id - Nameplate
+ type: http
+ seq: 2
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierNameplate-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru
new file mode 100644
index 0000000..e2b1dfc
--- /dev/null
+++ b/example/apiCollection/Submodel Registry/Get Submodel Descriptor By Id - TechnicalData.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel Descriptor By Id - TechnicalData
+ type: http
+ seq: 5
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodel-descriptors/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierTechnicalData-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Registry/folder.bru b/example/apiCollection/Submodel Registry/folder.bru
new file mode 100644
index 0000000..bd3aeb4
--- /dev/null
+++ b/example/apiCollection/Submodel Registry/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: Submodel Registry
+ seq: 4
+}
+
+auth {
+ mode: inherit
+}
diff --git a/example/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru b/example/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru
new file mode 100644
index 0000000..da9bd6d
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Serialization/Get appropriate serialization - Product1.bru
@@ -0,0 +1,26 @@
+meta {
+ name: Get appropriate serialization - Product1
+ type: http
+ seq: 1
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/serialization?aasIds={{aasIdentifier-1}}&submodelIds={{submodelIdentifierContact-1}}&submodelIds={{submodelIdentifierNameplate-1}}&submodelIds={{submodelIdentifierCarbonFootprint-1}}&submodelIds={{submodelIdentifierHandoverDocumentation-1}}&submodelIds={{submodelIdentifierTechnicalData-1}}&includeConceptDescriptions=false
+ body: none
+ auth: inherit
+}
+
+params:query {
+ aasIds: {{aasIdentifier-1}}
+ submodelIds: {{submodelIdentifierContact-1}}
+ submodelIds: {{submodelIdentifierNameplate-1}}
+ submodelIds: {{submodelIdentifierCarbonFootprint-1}}
+ submodelIds: {{submodelIdentifierHandoverDocumentation-1}}
+ submodelIds: {{submodelIdentifierTechnicalData-1}}
+ includeConceptDescriptions: false
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/apiCollection/Submodel Repository/Serialization/folder.bru b/example/apiCollection/Submodel Repository/Serialization/folder.bru
similarity index 100%
rename from apiCollection/Submodel Repository/Serialization/folder.bru
rename to example/apiCollection/Submodel Repository/Serialization/folder.bru
diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru
new file mode 100644
index 0000000..9ee3129
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - CarbonFootprint.bru
@@ -0,0 +1,21 @@
+meta {
+ name: Get Submodel Element - CarbonFootprint
+ type: http
+ seq: 3
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierCarbonFootprint-1}}
+ idShortPath: ProductCarbonFootprints[0].LifeCyclePhases[0]
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru
new file mode 100644
index 0000000..9471771
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - ContactInfo.bru
@@ -0,0 +1,21 @@
+meta {
+ name: Get Submodel Element - ContactInfo
+ type: http
+ seq: 1
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierContact-1}}
+ idShortPath: ContactInformation1
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru
new file mode 100644
index 0000000..be59fe6
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - HandoverDocumentation.bru
@@ -0,0 +1,21 @@
+meta {
+ name: Get Submodel Element - HandoverDocumentation
+ type: http
+ seq: 5
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierHandoverDocumentation-1}}
+ idShortPath: Documents[0].DocumentClassifications[1].ClassName
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru
new file mode 100644
index 0000000..5203039
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - Nameplate.bru
@@ -0,0 +1,21 @@
+meta {
+ name: Get Submodel Element - Nameplate
+ type: http
+ seq: 2
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierNameplate-1}}
+ idShortPath: ManufacturerName
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru
new file mode 100644
index 0000000..34ec067
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel Element/Get Submodel Element - TechnicalData.bru
@@ -0,0 +1,21 @@
+meta {
+ name: Get Submodel Element - TechnicalData
+ type: http
+ seq: 4
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/submodel-elements/:idShortPath
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierTechnicalData-1}}
+ idShortPath: GeneralInformation.ProductImage
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel Element/folder.bru b/example/apiCollection/Submodel Repository/Submodel Element/folder.bru
new file mode 100644
index 0000000..04497c4
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel Element/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: Submodel Element
+ seq: 2
+}
+
+auth {
+ mode: inherit
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel - ContactInfo.bru b/example/apiCollection/Submodel Repository/Submodel/Get Submodel - ContactInfo.bru
new file mode 100644
index 0000000..e927e4b
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel/Get Submodel - ContactInfo.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel - ContactInfo
+ type: http
+ seq: 1
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierContact-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru b/example/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru
new file mode 100644
index 0000000..07c7652
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel/Get Submodel - HandoverDocumentation.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel - HandoverDocumentation
+ type: http
+ seq: 5
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierHandoverDocumentation-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru b/example/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru
new file mode 100644
index 0000000..f69644b
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel/Get Submodel - Nameplate.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel - Nameplate
+ type: http
+ seq: 2
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier/
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierNameplate-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru b/example/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru
new file mode 100644
index 0000000..2a645ba
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel/Get Submodel - TechnicalData.bru
@@ -0,0 +1,20 @@
+meta {
+ name: Get Submodel - TechnicalData
+ type: http
+ seq: 3
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierTechnicalData-1}}
+}
+
+settings {
+ encodeUrl: true
+ timeout: 0
+}
diff --git a/example/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru b/example/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru
new file mode 100644
index 0000000..847d0e2
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/Submodel/Get Submodel -CarbonFootprint.bru
@@ -0,0 +1,15 @@
+meta {
+ name: Get Submodel - CarbonFootprint
+ type: http
+ seq: 4
+}
+
+get {
+ url: {{DataEngineBaseUrl}}/submodels/:submodelIdentifier
+ body: none
+ auth: inherit
+}
+
+params:path {
+ submodelIdentifier: {{submodelIdentifierCarbonFootprint-1}}
+}
diff --git a/apiCollection/Submodel Repository/Submodel/folder.bru b/example/apiCollection/Submodel Repository/Submodel/folder.bru
similarity index 100%
rename from apiCollection/Submodel Repository/Submodel/folder.bru
rename to example/apiCollection/Submodel Repository/Submodel/folder.bru
diff --git a/example/apiCollection/Submodel Repository/folder.bru b/example/apiCollection/Submodel Repository/folder.bru
new file mode 100644
index 0000000..a5f1714
--- /dev/null
+++ b/example/apiCollection/Submodel Repository/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: Submodel Repository
+ seq: 5
+}
+
+auth {
+ mode: inherit
+}
diff --git a/example/apiCollection/bruno.json b/example/apiCollection/bruno.json
new file mode 100644
index 0000000..1e3ad27
--- /dev/null
+++ b/example/apiCollection/bruno.json
@@ -0,0 +1,9 @@
+{
+ "version": "1",
+ "name": "DataEngine-DPPPlugin",
+ "type": "collection",
+ "ignore": [
+ "node_modules",
+ ".git"
+ ]
+}
\ No newline at end of file
diff --git a/example/apiCollection/collection.bru b/example/apiCollection/collection.bru
new file mode 100644
index 0000000..00ee856
--- /dev/null
+++ b/example/apiCollection/collection.bru
@@ -0,0 +1,38 @@
+vars:pre-request {
+ aasIdentifier-1: https://mm-software.com/ids/aas/{{productId-1}}
+ submodelIdentifierContact-1: https://mm-software.com/submodel/{{productId-1}}/ContactInformation
+ submodelIdentifierNameplate-1: https://mm-software.com/submodel/{{productId-1}}/Nameplate
+ aasIdentifier-2: https://mm-software.com/ids/aas/{{productId-2}}
+ aasIdentifier-3: https://mm-software.com/ids/aas/{{productId-3}}
+ submodelIdentifierTechnicalData-1: https://mm-software.com/submodel/{{productId-1}}/TechnicalData
+ submodelIdentifierCarbonFootprint-1: https://mm-software.com/submodel/{{productId-1}}/CarbonFootprint
+ submodelIdentifierHandoverDocumentation-1: https://mm-software.com/submodel/{{productId-1}}/HandoverDocumentation
+ productId-1: 000-001
+ productId-2: 000-002
+ productId-3: 001-001
+}
+
+script:pre-request {
+ function b64EncodeUnicode(str){
+ return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (m,p)=>String.fromCharCode('0x'+p)));
+ }
+
+ const varsToEncode = [
+ 'aasIdentifier-1',
+ 'aasIdentifier-2',
+ 'aasIdentifier-3',
+ 'submodelIdentifierContact-1',
+ 'submodelIdentifierNameplate-1',
+ 'submodelIdentifierHandoverDocumentation-1',
+ 'submodelIdentifierTechnicalData-1',
+ 'submodelIdentifierCarbonFootprint-1'
+ ];
+
+ varsToEncode.forEach(name => {
+ const plain = bru.getCollectionVar(name);
+ const encoded = b64EncodeUnicode(plain);
+ bru.setVar(name, encoded);
+ });
+
+
+}
diff --git a/example/apiCollection/environments/local.bru b/example/apiCollection/environments/local.bru
new file mode 100644
index 0000000..5987017
--- /dev/null
+++ b/example/apiCollection/environments/local.bru
@@ -0,0 +1,3 @@
+vars {
+ DataEngineBaseUrl: http://localhost:8080
+}
diff --git a/example/basyx/aas-env.properties b/example/basyx/aas-env.properties
new file mode 100644
index 0000000..70ef7e2
--- /dev/null
+++ b/example/basyx/aas-env.properties
@@ -0,0 +1,16 @@
+server.port=8081
+basyx.environment=file:aas
+basyx.cors.allowed-origins=*
+basyx.cors.allowed-methods=GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD
+basyx.aasrepository.feature.registryintegration=http://aas-template-registry:8080
+basyx.submodelrepository.feature.registryintegration=http://sm-template-registry:8080
+spring.servlet.multipart.max-file-size=128MB
+spring.servlet.multipart.max-request-size=128MB
+basyx.backend=MongoDB
+spring.data.mongodb.host=mongo
+spring.data.mongodb.port=27017
+spring.data.mongodb.database=aasenvironment
+spring.data.mongodb.authentication-database=admin
+spring.data.mongodb.username=mongoAdmin
+spring.data.mongodb.password=mongoPassword
+
diff --git a/example/data/checkmark.png b/example/data/checkmark.png
new file mode 100644
index 0000000..971aaff
Binary files /dev/null and b/example/data/checkmark.png differ
diff --git a/example/data/dummy_document.jpg b/example/data/dummy_document.jpg
new file mode 100644
index 0000000..f6badb5
Binary files /dev/null and b/example/data/dummy_document.jpg differ
diff --git a/example/data/dummy_document.pdf b/example/data/dummy_document.pdf
new file mode 100644
index 0000000..f92a169
Binary files /dev/null and b/example/data/dummy_document.pdf differ
diff --git a/example/data/product1.jpg b/example/data/product1.jpg
new file mode 100644
index 0000000..45ecc8c
Binary files /dev/null and b/example/data/product1.jpg differ
diff --git a/example/data/product2.jpg b/example/data/product2.jpg
new file mode 100644
index 0000000..184bb83
Binary files /dev/null and b/example/data/product2.jpg differ
diff --git a/example/data/product3.jpg b/example/data/product3.jpg
new file mode 100644
index 0000000..9ff957c
Binary files /dev/null and b/example/data/product3.jpg differ
diff --git a/example/docker-compose.yml b/example/docker-compose.yml
new file mode 100644
index 0000000..50f2797
--- /dev/null
+++ b/example/docker-compose.yml
@@ -0,0 +1,222 @@
+networks:
+ twinengine-network:
+ name: twinengine-network
+
+services:
+ nginx:
+ image: nginx:trixie-perl
+ container_name: nginx
+ ports:
+ - "8080:80"
+ volumes:
+ - ./nginx/html:/usr/share/nginx/html
+ - ./nginx/default.conf.template:/etc/nginx/templates/default.conf.template
+ restart: always
+ depends_on:
+ aas-template-registry:
+ condition: service_healthy
+ sm-template-registry:
+ condition: service_healthy
+ template-repository:
+ condition: service_healthy
+ networks:
+ - twinengine-network
+
+ twinengine-dataengine:
+ image: ghcr.io/aas-twinengine/dataengine:v1.0.0
+ container_name: twinengine-dataengine
+ depends_on:
+ dpp-plugin:
+ condition: service_started
+ restart: always
+ environment:
+ - AasEnvironment__DataEngineRepositoryBaseUrl=http://localhost:8080
+ - AasEnvironment__AasEnvironmentRepositoryBaseUrl=http://template-repository:8081
+ - AasEnvironment__SubModelRepositoryPath=submodels
+ - AasEnvironment__AasRegistryBaseUrl=http://aas-template-registry:8080
+ - AasEnvironment__AasRegistryPath=shell-descriptors
+ - AasEnvironment__SubModelRegistryBaseUrl=http://sm-template-registry:8080
+ - AasEnvironment__SubModelRegistryPath=submodel-descriptors
+ - AasEnvironment__AasRepositoryPath=shells
+ - AasEnvironment__SubmodelRefPath=submodel-refs
+ - AasEnvironment__CustomerDomainUrl=https://mm-software.com
+ - TemplateMappingRules__SubmodelTemplateMappings__0__templateId=https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2
+ - TemplateMappingRules__SubmodelTemplateMappings__0__pattern__0=TechnicalData
+ - TemplateMappingRules__SubmodelTemplateMappings__1__templateId=https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0
+ - TemplateMappingRules__SubmodelTemplateMappings__1__pattern__0=Nameplate
+ - TemplateMappingRules__SubmodelTemplateMappings__2__templateId=https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0
+ - TemplateMappingRules__SubmodelTemplateMappings__2__pattern__0=ContactInformation
+ - TemplateMappingRules__SubmodelTemplateMappings__3__templateId=https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0
+ - TemplateMappingRules__SubmodelTemplateMappings__3__pattern__0=CarbonFootprint
+ - TemplateMappingRules__SubmodelTemplateMappings__4__templateId=https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0
+ - TemplateMappingRules__SubmodelTemplateMappings__4__pattern__0=HandoverDocumentation
+ - TemplateMappingRules__ShellTemplateMappings__0__templateId=https://mm-software.com/aas/aasTemplate
+ - TemplateMappingRules__ShellTemplateMappings__0__pattern__0=
+ - TemplateMappingRules__AasIdExtractionRules__0__pattern=Regex
+ - TemplateMappingRules__AasIdExtractionRules__0__index=6
+ - TemplateMappingRules__AasIdExtractionRules__0__separator=/
+ - Semantics__MultiLanguageSemanticPostfixSeparator=_
+ - Semantics__SubmodelElementIndexContextPrefix=_aastwinengineindex_
+ - Semantics__InternalSemanticId=InternalSemanticId
+ - AasxOptions__RootFolder=aasx
+ - AasRegistryPreComputed__ShellDescriptorCron=0 */3 * * * *
+ - AasRegistryPreComputed__IsPreComputed=false
+ - MultiPluginConflictOption__HandlingMode=TakeFirst
+ - PluginConfig__Plugins__0__PluginName=Plugin1
+ - PluginConfig__Plugins__0__PluginUrl=http://dpp-plugin:8080
+ networks:
+ - twinengine-network
+
+ dpp-plugin:
+ image: ghcr.io/aas-twinengine/plugindpp:v1.0.0
+ container_name: dpp-plugin
+ depends_on:
+ postgres:
+ condition: service_healthy
+ restart: always
+ environment:
+ - Semantics__IndexContextPrefix=_aastwinengineindex_
+ - Capabilities__HasShellDescriptor=true
+ - Capabilities__HasAssetInformation=true
+ - RelationalDatabaseConfiguration__ConnectionString=Host=postgres;Port=5432;Database=twinengine;Username=postgres;Password=admin
+ - ExtractionRules__SubmodelNameExtractionRules__0__SubmodelName=NamePlate
+ - ExtractionRules__SubmodelNameExtractionRules__0__pattern__0=Nameplate
+ - ExtractionRules__SubmodelNameExtractionRules__0__pattern__1=NamePlate
+ - ExtractionRules__SubmodelNameExtractionRules__1__SubmodelName=ContactInformation
+ - ExtractionRules__SubmodelNameExtractionRules__1__pattern__0=ContactInformation
+ - ExtractionRules__SubmodelNameExtractionRules__1__pattern__1=ContactInformations
+ - ExtractionRules__SubmodelNameExtractionRules__2__SubmodelName=HandoverDocumentation
+ - ExtractionRules__SubmodelNameExtractionRules__2__pattern__0=HandoverDocumentation
+ - ExtractionRules__SubmodelNameExtractionRules__2__pattern__1=HandoverDocumentations
+ - ExtractionRules__SubmodelNameExtractionRules__3__SubmodelName=TechnicalData
+ - ExtractionRules__SubmodelNameExtractionRules__3__pattern__0=TechnicalData
+ - ExtractionRules__SubmodelNameExtractionRules__4__SubmodelName=CarbonFootprint
+ - ExtractionRules__SubmodelNameExtractionRules__4__pattern__0=CarbonFootprint
+ - ExtractionRules__SubmodelNameExtractionRules__4__pattern__1=Footprint
+ - ExtractionRules__SubmodelNameExtractionRules__4__pattern__2=Carbon
+ - ExtractionRules__ProductIdExtractionRules__0__Pattern=Regex
+ - ExtractionRules__ProductIdExtractionRules__0__Index=5
+ - ExtractionRules__ProductIdExtractionRules__0__Separator=/
+ networks:
+ - twinengine-network
+
+ template-repository:
+ image: eclipsebasyx/aas-environment:2.0.0-SNAPSHOT
+ container_name: template-repository
+ volumes:
+ - ./aas:/application/aas
+ - ./basyx/aas-env.properties:/application/application.properties
+ environment:
+ BASYX_EXTERNALURL : http://localhost:8080
+ restart: always
+ depends_on:
+ aas-template-registry:
+ condition: service_healthy
+ sm-template-registry:
+ condition: service_healthy
+ networks:
+ - twinengine-network
+
+ aas-template-registry:
+ image: eclipsebasyx/aas-registry-log-mongodb:2.0.0-SNAPSHOT
+ container_name: aas-template-registry
+ restart: always
+ depends_on:
+ - mongo
+ environment:
+ - SPRING_DATA_MONGODB_URI=mongodb://mongoAdmin:mongoPassword@mongo:27017
+ networks:
+ - twinengine-network
+
+ sm-template-registry:
+ image: eclipsebasyx/submodel-registry-log-mongodb:2.0.0-SNAPSHOT
+ container_name: sm-template-registry
+ depends_on:
+ - mongo
+ environment:
+ - SPRING_DATA_MONGODB_URI=mongodb://mongoAdmin:mongoPassword@mongo:27017
+ networks:
+ - twinengine-network
+
+ shell-template-creator:
+ image: curlimages/curl:8.18.0
+ container_name: shell-template-creator
+ depends_on:
+ template-repository:
+ condition: service_healthy
+ entrypoint: >
+ sh -c '
+ echo "Waiting for template-repository to be ready...";
+ sleep 10;
+ curl -X POST http://template-repository:8081/shells \
+ -H "accept: application/json" \
+ -H "Content-Type: application/json" \
+ -d "{\"id\":\"https://mm-software.com/aas/aasTemplate\",\"assetInformation\":{\"assetKind\":\"Instance\"},\"submodels\":[{\"type\":\"ModelReference\",\"keys\":[{\"type\":\"Submodel\",\"value\":\"Nameplate\"}]},{\"type\":\"ModelReference\",\"keys\":[{\"type\":\"Submodel\",\"value\":\"ContactInformation\"}]},{\"type\":\"ModelReference\",\"keys\":[{\"type\":\"Submodel\",\"value\":\"TechnicalData\"}]},{\"type\":\"ModelReference\",\"keys\":[{\"type\":\"Submodel\",\"value\":\"CarbonFootprint\"}]},{\"type\":\"ModelReference\",\"keys\":[{\"type\":\"Submodel\",\"value\":\"HandoverDocumentation\"}]}],\"modelType\":\"AssetAdministrationShell\"}";
+ echo "Shell creation request sent.";
+ '
+ networks:
+ - twinengine-network
+
+ aas-web-ui:
+ image: eclipsebasyx/aas-gui:SNAPSHOT
+ container_name: aas-ui
+ volumes:
+ - ./logo:/usr/src/app/dist/Logo
+ environment:
+ AAS_REGISTRY_PATH: http://localhost:8080/shell-descriptors
+ SUBMODEL_REGISTRY_PATH: http://localhost:8080/submodel-descriptors
+ AAS_REPO_PATH: http://localhost:8080/shells
+ SUBMODEL_REPO_PATH: http://localhost:8080/submodels
+ CD_REPO_PATH: http://localhost:8080/concept-descriptions
+ BASE_PATH: "/aas-ui"
+ LOGO_PATH: "MM_Logo.svg"
+ PRIMARY_DARK_COLOR: "#00F2E5"
+ PRIMARY_LIGHT_COLOR: "#041b2b"
+ restart: always
+ depends_on:
+ template-repository:
+ condition: service_healthy
+ networks:
+ - twinengine-network
+
+ mongo:
+ image: mongo:6.0
+ container_name: mongo
+ environment:
+ MONGO_INITDB_ROOT_USERNAME: mongoAdmin
+ MONGO_INITDB_ROOT_PASSWORD: mongoPassword
+ networks:
+ - twinengine-network
+
+ postgres:
+ image: postgres:16-alpine
+ container_name: postgres
+ environment:
+ POSTGRES_DB: twinengine
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: admin
+ volumes:
+ - ./postgres:/docker-entrypoint-initdb.d
+ restart: always
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U postgres -d twinengine"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ networks:
+ - twinengine-network
+
+ pgadmin:
+ image: dpage/pgadmin4:snapshot
+ container_name: pgadmin
+ ports:
+ - "8081:80"
+ environment:
+ PGADMIN_DEFAULT_EMAIL: admin@example.com
+ PGADMIN_DEFAULT_PASSWORD: admin
+ depends_on:
+ postgres:
+ condition: service_healthy
+ restart: always
+ networks:
+ - twinengine-network
diff --git a/example/logo/MM_Logo.svg b/example/logo/MM_Logo.svg
new file mode 100644
index 0000000..35fe73f
--- /dev/null
+++ b/example/logo/MM_Logo.svg
@@ -0,0 +1,51 @@
+
+
+
diff --git a/example/nginx/default.conf.template b/example/nginx/default.conf.template
new file mode 100644
index 0000000..d3fadf5
--- /dev/null
+++ b/example/nginx/default.conf.template
@@ -0,0 +1,133 @@
+server {
+ listen 80;
+ server_name _;
+
+ # Serve static files
+ location /fileprovider/ {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ root /usr/share/nginx/html;
+ }
+
+ location /aas-ui/ {
+ proxy_pass http://aas-web-ui:3000;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header Authorization $http_authorization;
+ proxy_set_header Accept $http_accept;
+ proxy_set_header Content-Type $http_content_type;
+ }
+
+
+ location /shell-descriptors {
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://twinengine-dataengine:8080;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location /shells {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://twinengine-dataengine:8080;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location /submodels {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://twinengine-dataengine:8080;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location /concept-descriptions/ {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://template-repository:8081;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location /concept-descriptions {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://template-repository:8081;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location /submodel-descriptors/ {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://twinengine-dataengine:8080;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ }
+
+ location /submodel-descriptors {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://twinengine-dataengine:8080;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location /serialization {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://twinengine-dataengine:8080;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+
+ location /description {
+ # Allow only GET and OPTIONS requests, deny all other methods
+ limit_except GET OPTIONS {
+ deny all;
+ }
+ proxy_pass http://sm-template-registry:8080;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+}
\ No newline at end of file
diff --git a/example/postgres/01_core_asset_tables.sql.inc b/example/postgres/01_core_asset_tables.sql.inc
new file mode 100644
index 0000000..6b983ca
--- /dev/null
+++ b/example/postgres/01_core_asset_tables.sql.inc
@@ -0,0 +1,118 @@
+-- ============================================================
+-- Core Asset Tables
+-- ============================================================
+
+CREATE TABLE "Asset" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "ProductId" VARCHAR(50),
+ "IdShort" VARCHAR(100),
+ "GlobalAssetId" TEXT,
+ "AasId" TEXT,
+ "ThumbnailContentType" VARCHAR(50),
+ "ThumbnailPath" TEXT,
+ "UriOfTheProduct" TEXT,
+ "ManufacturerProductType" TEXT,
+ "OrderCodeOfManufacturer" TEXT,
+ "ProductArticleNumberOfManufacturer" TEXT,
+ "SerialNumber" TEXT,
+ "YearOfConstruction" INT,
+ "DateOfManufacture" DATE,
+ "HardwareVersion" TEXT,
+ "FirmwareVersion" TEXT,
+ "SoftwareVersion" TEXT,
+ "CountryOfOrigin" TEXT,
+ "UniqueFacilityIdentifier" TEXT,
+ "ManufacturerName" TEXT,
+ "ManufacturerProductDesignation_en" TEXT,
+ "ManufacturerProductDesignation_de" TEXT,
+ "ManufacturerProductRoot_en" TEXT,
+ "ManufacturerProductRoot_de" TEXT,
+ "ManufacturerProductFamily_en" TEXT,
+ "ManufacturerProductFamily_de" TEXT,
+ "CompanyLogo" TEXT,
+ "ManufacturerArticleNumber" TEXT,
+ "ManufacturerOrderCode" TEXT,
+ "ProductImage" TEXT,
+ "ManufacturerLogo" TEXT,
+ "TextStatement_en" TEXT,
+ "TextStatement_de" TEXT,
+ "ValidDate" DATE,
+ "PcfCalculationMethod" TEXT,
+ "LifeCyclePhase" TEXT,
+ "PcfCO2eq" NUMERIC,
+ "ReferenceImpactUnitForCalculation" TEXT,
+ "QuantityOfMeasureForCalculation" NUMERIC,
+ "PublicationDate" TIMESTAMP,
+ "ExpirationDate" TIMESTAMP,
+ "ExplanatoryStatement" TEXT
+);
+
+CREATE TABLE "SpecificAssetIds" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "AssetId" INT NOT NULL REFERENCES "Asset"("Id") ON DELETE CASCADE,
+ "Name" TEXT,
+ "Value" TEXT
+);
+
+INSERT INTO "Asset" (
+ "ProductId","IdShort","GlobalAssetId","AasId","ThumbnailContentType","ThumbnailPath",
+ "UriOfTheProduct","ManufacturerProductType","OrderCodeOfManufacturer","ProductArticleNumberOfManufacturer",
+ "SerialNumber","YearOfConstruction","DateOfManufacture","HardwareVersion","FirmwareVersion","SoftwareVersion",
+ "CountryOfOrigin","UniqueFacilityIdentifier","ManufacturerName","ManufacturerProductDesignation_en",
+ "ManufacturerProductDesignation_de","ManufacturerProductRoot_en","ManufacturerProductRoot_de",
+ "ManufacturerProductFamily_en","ManufacturerProductFamily_de","CompanyLogo","ManufacturerArticleNumber",
+ "ManufacturerOrderCode","ProductImage","ManufacturerLogo","TextStatement_en","TextStatement_de",
+ "ValidDate","PcfCalculationMethod","LifeCyclePhase","PcfCO2eq","ReferenceImpactUnitForCalculation",
+ "QuantityOfMeasureForCalculation","PublicationDate","ExpirationDate","ExplanatoryStatement"
+) VALUES
+('000-001','Product1','https://mm-software.com/ids/assets/000-001','https://mm-software.com/ids/aas/000-001','image/jpeg',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product1.jpg',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product1.jpg',
+ 'FM-ABC-1234','FMABC1234','FM11-ABC22-123456','9804820',2022,'2022-01-01',
+ '1.0.0','1.0.0','1.0.0','DE','987654321','M&M Germany',
+ 'FM-ABC-1234','ABC-123','Camera','Kamera','Electronics','Elektronik',
+ 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853',
+ '123456','EEA-EX-200-S/47-Q3',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product1.jpg',
+ 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853',
+ 'Restricted use','Eingeschränkte Nutzung','2035-05-05',
+ 'ISO 14067','C4 - landfill',17.2,'ml',5,
+ '2025-12-24T14:30:00Z','2035-12-24T14:30:00Z',
+ 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf'),
+('000-002','Product2','https://mm-software.com/ids/assets/000-002','https://mm-software.com/ids/aas/000-002','image/jpeg',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product2.jpg',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product2.jpg',
+ 'FM-ABC-1235','FMABC1238','FM11-ABC22-123458','9804821',2023,'2023-01-01',
+ '1.0.1','1.0.1','1.0.1','IN','123567890','M&M India',
+ 'FM-ABC-123','ABC-123','Camera','Kamera','Electronics','Elektronik',
+ 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853',
+ '123456','EEA-EX-200-S/47-Q4',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product2.jpg',
+ 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853',
+ 'Restricted use','Eingeschränkte Nutzung','2035-06-05',
+ 'EN 15804','A5 - Installation',6.2,'cbm',2.2999999999999998,
+ '2026-01-15T09:15:00+05:30','2036-01-15T09:15:00+05:31',
+ 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf'),
+('001-001','Product3','https://mm-software.com/ids/assets/001-001','https://mm-software.com/ids/aas/001-001','image/jpeg',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product3.jpg',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product3.jpg',
+ 'TM-ABC-1680','TMABC1680','TM11-ABC22-123456','9804760',2024,'2024-01-01',
+ '2.0.0','1.0.0','1.0.2','CN','874512451','M&M China',
+ 'TM-ABC-1234','ABC-1234','perfume','Parfüm','Cosmetics','Kosmetika',
+ 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853',
+ '123456','EEA-EX-200-S/47-Q5',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/product3.jpg',
+ 'https://mmsoftwaregmbh.sharepoint.com/_api/siteiconmanager/getsitelogo?type=%271%27&hash=638518734598723853',
+ 'Restricted use','Eingeschränkte Nutzung','2035-07-05',
+ 'PACT v2.0.0','C3 - recycling, waste treatment',2.2999999999999998,'piece',7.8,
+ '2024-07-01T18:45:00-04:00','2034-07-01T18:45:00-04:01',
+ 'https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf');
+
+-- ============================================================
+-- Specific Asset IDs
+-- ============================================================
+
+INSERT INTO "SpecificAssetIds" ("AssetId","Name","Value") VALUES
+(1,'product1.0','M&M - 001'),
+(1,'product1.1','M&M - 002'),
+(2,'product2','M&M - 003');
diff --git a/example/postgres/02_nameplate_carbonfootprint_technicaldata.sql.inc b/example/postgres/02_nameplate_carbonfootprint_technicaldata.sql.inc
new file mode 100644
index 0000000..a0806d5
--- /dev/null
+++ b/example/postgres/02_nameplate_carbonfootprint_technicaldata.sql.inc
@@ -0,0 +1,116 @@
+-- ============================================================
+-- Core Data Insertion
+-- ============================================================
+-- This file contains CREATE and INSERT statements for core business entities for NamePlate Submodel:
+-- - Markings
+-- - Asset-Marking relationships
+-- - Product Classification Items
+-- - Carbon Footprint data
+-- -Asset-ProductClassificationItem relationships
+-- ============================================================
+
+CREATE TABLE "Marking" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "Index" INT,
+ "MarkingName" TEXT,
+ "DesignationOfCertificateOrApproval" TEXT,
+ "IssueDate" DATE,
+ "ExpiryDate" DATE,
+ "MarkingAdditionalText" TEXT,
+ "MarkingFile" TEXT
+);
+
+CREATE TABLE "AssetMarking" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "AssetId" INT NOT NULL REFERENCES "Asset"("Id") ON DELETE CASCADE,
+ "MarkingId" INT NOT NULL REFERENCES "Marking"("Id") ON DELETE CASCADE
+);
+
+-- ============================================================
+-- Product Classification Tables
+-- ============================================================
+
+CREATE TABLE "ProductClassificationItem" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "Index" INT,
+ "ProductClassificationSystem" TEXT,
+ "ClassificationSystemVersion" TEXT,
+ "ProductClassId" TEXT
+);
+
+CREATE TABLE "AssetProductClassificationItem" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "AssetId" INT REFERENCES "Asset"("Id") ON DELETE CASCADE,
+ "ProductClassificationItemId" INT REFERENCES "ProductClassificationItem"("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "ProductOrSectorSpecificCarbonFootprint" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "AssetId" INT REFERENCES "Asset"("Id") ON DELETE CASCADE,
+ "PcfCalculationMethod" TEXT,
+ "PcfRuleOperator" TEXT,
+ "PcfRuleName" TEXT,
+ "PcfRuleVersion" TEXT,
+ "PcfRuleOnlineReference" TEXT,
+ "PcfApiEndpoint" TEXT,
+ "PcfApiQuery" TEXT
+);
+
+-- ============================================================
+-- Marking Data
+-- ============================================================
+
+INSERT INTO "Marking" ("Index","MarkingName","DesignationOfCertificateOrApproval","IssueDate","ExpiryDate","MarkingAdditionalText","MarkingFile") VALUES
+(0,'0173-1#07-DAA603#004','KEMA99IECEX1105/128','2022-01-01','2030-01-01','additional information on the marking - 00',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/checkmark.png'),
+(0,'0173-1#07-DAA603#005','KEMA99IECEX1105/129','2022-02-01','2030-02-01','additional information on the marking - 01',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/checkmark.png'),
+(1,'0173-1#07-DAA603#006','KEMA99IECEX1105/130','2022-03-01','2030-03-01','additional information on the marking - 02',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/checkmark.png'),
+(0,'0173-1#07-DAA603#007','KEMA99IECEX1105/131','2022-04-01','2030-04-01','additional information on the marking - 03',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/checkmark.png'),
+(1,'0173-1#07-DAA603#008','KEMA99IECEX1105/132','2022-05-01','2030-05-01','additional information on the marking - 04',
+ 'https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/checkmark.png');
+
+-- ============================================================
+-- Asset-Marking Relationships
+-- ============================================================
+
+INSERT INTO "AssetMarking" ("AssetId","MarkingId") VALUES
+(1,1),
+(1,3),
+(2,2),
+(2,3),
+(3,4),
+(3,5);
+
+-- ============================================================
+-- Product Classification
+-- ============================================================
+
+INSERT INTO "ProductClassificationItem" ("Index","ProductClassificationSystem","ClassificationSystemVersion","ProductClassId") VALUES
+(0,'ECLASS','14','19-01-01-01'),
+(1,'IEC CDD','2024-09','IEC-CDD-AAA124'),
+(2,'UNSPSC','23.0301','UNSPSC-43211503'),
+(0,'ISO 13584','2023','ISO13584-XYZ789'),
+(0,'ECLASS','5','27-02-03-05'),
+(1,'IEC CDD','2024-09','IEC-CDD-AAA123');
+
+INSERT INTO "AssetProductClassificationItem" ("AssetId","ProductClassificationItemId") VALUES
+(1,1),
+(1,2),
+(1,3),
+(2,4),
+(3,5),
+(3,6);
+
+-- ============================================================
+-- Carbon Footprint Data
+-- ============================================================
+
+INSERT INTO "ProductOrSectorSpecificCarbonFootprint" (
+ "AssetId","PcfCalculationMethod","PcfRuleOperator","PcfRuleName","PcfRuleVersion","PcfRuleOnlineReference","PcfApiEndpoint","PcfApiQuery"
+) VALUES
+(1,'IEC TS 63058','GHG Protocol','GHG Protocol Product Standard','1.1','https://ghgprotocol.org/standards/product-standard','https://api.carbonfootprint.org/v1/calculate','?productId=12345&unit=kgCO2e&scope=cradle-to-gate'),
+(2,'EN 15804','ISO 14067','ISO 14067','2.1','https://www.iso.org/standard/43278.html','https://api.iso14067.org/v2/emissions','?sector=electronics®ion=EU&year=2025'),
+(3,'PACT v2.0.0','PAS 2050','PAS 2050','0.9','https://www.bsigroup.com/en-GB/PAS-2050-Carbon-Footprint/','https://api.pas2050.com/v1/footprint','?material=steel&quantity=1000kg&method=ISO14067');
diff --git a/example/postgres/03_contactinformations.sql.inc b/example/postgres/03_contactinformations.sql.inc
new file mode 100644
index 0000000..9cb8af6
--- /dev/null
+++ b/example/postgres/03_contactinformations.sql.inc
@@ -0,0 +1,221 @@
+-- ============================================================
+-- Contact Information Data Insertion
+-- ============================================================
+-- This file contains CREATE And INSERT statements for contact-related entities:
+-- - ContactInformation
+-- - Phone numbers
+-- - Fax numbers
+-- - Email addresses
+-- - IP Communication channels
+-- - Asset-ContactInformation relationships
+-- ============================================================
+-- ============================================================
+-- Contact Information Tables
+-- ============================================================
+
+CREATE TABLE "ContactInformation" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "Index" INT,
+ "RoleOfContactPerson" TEXT,
+ "Language" TEXT,
+ "TimeZone" TEXT,
+ "AddressOfAdditionalLink" TEXT,
+ "NationalCode_en" TEXT,
+ "NationalCode_de" TEXT,
+ "CityTown_en" TEXT,
+ "CityTown_de" TEXT,
+ "Company_en" TEXT,
+ "Company_de" TEXT,
+ "Department_en" TEXT,
+ "Department_de" TEXT,
+ "Street_en" TEXT,
+ "Street_de" TEXT,
+ "Zipcode_en" TEXT,
+ "Zipcode_de" TEXT,
+ "POBox_en" TEXT,
+ "POBox_de" TEXT,
+ "ZipCodeOfPOBox_en" TEXT,
+ "ZipCodeOfPOBox_de" TEXT,
+ "StateCounty_en" TEXT,
+ "StateCounty_de" TEXT,
+ "NameOfContact_en" TEXT,
+ "NameOfContact_de" TEXT,
+ "FirstName_en" TEXT,
+ "FirstName_de" TEXT,
+ "MiddleNames_en" TEXT,
+ "MiddleNames_de" TEXT,
+ "Title_en" TEXT,
+ "Title_de" TEXT,
+ "AcademicTitle_en" TEXT,
+ "AcademicTitle_de" TEXT,
+ "FurtherDetailsOfContact_en" TEXT,
+ "FurtherDetailsOfContact_de" TEXT
+);
+
+CREATE TABLE "AssetContactInformation" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "AssetId" INT NOT NULL REFERENCES "Asset"("Id") ON DELETE CASCADE,
+ "ContactInformationId" INT NOT NULL REFERENCES "ContactInformation"("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "Phone" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "ContactInformationId" INT REFERENCES "ContactInformation"("Id") ON DELETE CASCADE,
+ "TelephoneNumber_en" TEXT,
+ "TelephoneNumber_de" TEXT,
+ "AvailableTime_en" TEXT,
+ "AvailableTime_de" TEXT,
+ "TypeOfTelephone" TEXT
+);
+
+CREATE TABLE "Fax" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "ContactInformationId" INT REFERENCES "ContactInformation"("Id") ON DELETE CASCADE,
+ "FaxNumber_en" TEXT,
+ "FaxNumber_de" TEXT,
+ "TypeOfFaxNumber" TEXT
+);
+
+CREATE TABLE "Email" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "ContactInformationId" INT REFERENCES "ContactInformation"("Id") ON DELETE CASCADE,
+ "EmailAddress" TEXT,
+ "TypeOfEmailAddress" TEXT,
+ "PublicKey_en" TEXT,
+ "PublicKey_de" TEXT,
+ "TypeOfPublicKey_en" TEXT,
+ "TypeOfPublicKey_de" TEXT
+);
+
+CREATE TABLE "IPCommunication" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "Index" INT,
+ "AddressOfAdditionalLink" TEXT,
+ "TypeOfCommunication" TEXT,
+ "AvailableTime_en" TEXT,
+ "AvailableTime_de" TEXT
+);
+
+CREATE TABLE "ContactInformationIPCommunication" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "ContactInformationId" INT REFERENCES "ContactInformation"("Id") ON DELETE CASCADE,
+ "IPCommunicationId" INT REFERENCES "IPCommunication"("Id") ON DELETE CASCADE
+);
+
+
+-- ============================================================
+-- Contact Information
+-- ============================================================
+
+INSERT INTO "ContactInformation" (
+ "Index","RoleOfContactPerson","Language","TimeZone","AddressOfAdditionalLink",
+ "NationalCode_en","NationalCode_de","CityTown_en","CityTown_de","Company_en","Company_de",
+ "Department_en","Department_de","Street_en","Street_de","Zipcode_en","Zipcode_de","POBox_en","POBox_de",
+ "ZipCodeOfPOBox_en","ZipCodeOfPOBox_de","StateCounty_en","StateCounty_de","NameOfContact_en","NameOfContact_de",
+ "FirstName_en","FirstName_de","MiddleNames_en","MiddleNames_de","Title_en","Title_de","AcademicTitle_en","AcademicTitle_de",
+ "FurtherDetailsOfContact_en","FurtherDetailsOfContact_de"
+) VALUES
+(0,'0173-1#07-AAS927#001','EN','Z+05:30','https://www.mm-software.com/','IN','IN','Mumbai','München',
+ 'M&M India','M&M India','Human Resources','Human Resources',
+ '221B Baker Street','221B Baker Street','110001','110001','PO Box 123','PO Box 124','110002','110002',
+ 'Delhi','Delhi','Aarav Sharma','Aarav Sharma','Aarav','Aarav','Sharma','Sharma','Mr.','Herr','Dr.','Dr.',
+ 'Responsible for B2B sales in region-1','Responsible for B2B sales in region-1'),
+(1,'0173-1#07-AAS928#001','DE','Z+01:00','https://www.mm-software.com/we/','DE','DE','Berlin','Berlin',
+ 'M&M Germany','M&M Germany','Finance','Finance','Hauptstraße 15','Hauptstraße 16','10115','10115','Postfach 789','Postfach 790',
+ '10116','10116','Berlin','Berlin','Lukas Mueller','Lukas Müller','Lukas','Lukas','Müller','Mueller','Mr.','Herr','Dr.','Dr.',
+ 'Responsible for B2B sales in region-2','Responsible for B2B sales in region-2'),
+(0,'0173-1#07-AAS931#001','EN','Z+05:30','https://www.mm-software.com/more-the-newsroom/detail/mm-software-auf-der-sps-2025/','IN','IN','Mumbai','München',
+ 'M&M India','M&M India','Operations','Operations',
+ '221B Baker Street','221B Baker Street','110001','110001','PO Box 123','PO Box 124','110002','110002','Delhi','Delhi',
+ 'Priya Mehta','Priya Mehta','Priya','Priya','Mehta','Mehta','Ms','Frau','Prof.','Prof.','Responsible for B2B sales in region-3','Responsible for B2B sales in region-3'),
+(1,'0173-1#07-AAS930#001','DE','Z+01:00','https://www.mm-software.com/more-the-newsroom/detail/entscheide-dich-teil-2/','DE','DE','Berlin','Berlin',
+ 'M&M Germany','M&M Germany','Human Resources','Human Resources','Hauptstraße 15','Hauptstraße 16','10115','10115','Postfach 789','Postfach 790',
+ '10116','10116','Berlin','Berlin','Anna Schneider','Anna Schneider','Anna','Anna','Schneider','Schneider','Ms','Frau','Prof.','Prof.','Responsible for B2B sales in region-4','Responsible for B2B sales in region-4'),
+(2,'0173-1#07-AAS929#001','FR','Z+08:00','https://www.mm-software.com/more-the-newsroom/detail/digitaler-produktpass-dpp-in-der-praxis-leitfaden-und-checkliste-fuer-unternehmen/','CN','CN','Beijing','Beijing',
+ 'M&M China','M&M China','Finance','Finance','88 Nanjing Road','89 Nanjing Road','200001','200001','P.O. Box 456','P.O. Box 457',
+ '200002','200002','hanghai Municipality','hanghai Municipality','Anna Müller','Wei Li','Li','Li','Wei','Wei','Mr.','Herr','Dr.','Dr.',
+ 'Responsible for B2B sales in region-5','Responsible for B2B sales in region-5'),
+(3,'0173-1#07-AAS928#001','DE','Z+01:00','https://www.mm-software.com/more-the-newsroom/','DE','DE','Berlin','Berlin',
+ 'M&M Germany','M&M Germany','Operations','Operations','Hauptstraße 15','Hauptstraße 16','10115','10115','Postfach 789','Postfach 790',
+ '10116','10116','Berlin','Berlin','Johann Becker','Johann Becker','Johann','Johann','Becker','Becker','Ms','Frau','Prof.','Prof.',
+ 'Responsible for B2B sales in region-6','Responsible for B2B sales in region-6');
+
+-- ============================================================
+-- Phone Numbers
+-- ============================================================
+
+INSERT INTO "Phone" ("ContactInformationId","TelephoneNumber_en","TelephoneNumber_de","AvailableTime_en","AvailableTime_de","TypeOfTelephone") VALUES
+(1,'+49 151 23456789','+49 151 23456790','Monday – Friday 08:00 to 16:00','Montag – Freitag 08:00 bis 16:00','0173-1#07-AAS754#001'),
+(2,'+91 98765 43210','+91 98765 43211','Monday – Thursday 09:00 to 17:00','Montag – Donnerstag 09:00 bis 17:00','0173-1#07-AAS755#001'),
+(3,'+49 160 98765432','+49 160 98765433','Tuesday – Saturday 07:30 to 15:30','Dienstag – Samstag 07:30 bis 15:30','0173-1#07-AAS756#001'),
+(4,'+91 91234 56789','+91 91234 56790','Monday – Friday 10:00 to 18:00','Montag – Freitag 10:00 bis 18:00','0173-1#07-AAS757#001'),
+(5,'+86 138 1234 5678','+86 138 1234 5679','Wednesday – Sunday 08:00 to 14:00','Mittwoch – Sonntag 08:00 bis 14:00','0173-1#07-AAS758#001'),
+(6,'+49 170 12345678','+49 170 12345679','Monday – Friday 06:00 to 12:00','Montag – Freitag 06:00 bis 12:00','0173-1#07-AAS759#001');
+
+-- ============================================================
+-- Fax Numbers
+-- ============================================================
+
+INSERT INTO "Fax" ("ContactInformationId","FaxNumber_en","FaxNumber_de","TypeOfFaxNumber") VALUES
+(1,'+49 151 23456789','+49 151 23456790','0173-1#07-AAS754#001'),
+(2,'+91 98765 43210','+91 98765 43211','0173-1#07 AAS756#001'),
+(3,'+49 160 98765432','+49 160 98765433','0173-1#07-AAS756#001'),
+(4,'+91 91234 56789','+91 91234 56790','0173-1#07-AAS754#002'),
+(5,'+86 138 1234 5678','+86 138 1234 5679','0173-1#07 AAS756#002'),
+(6,'+49 170 12345678','+49 170 12345679','0173-1#07-AAS756#002');
+
+-- ============================================================
+-- Email Addresses
+-- ============================================================
+
+INSERT INTO "Email" ("ContactInformationId","EmailAddress","TypeOfEmailAddress","PublicKey_en","PublicKey_de","TypeOfPublicKey_en","TypeOfPublicKey_de") VALUES
+(1,'aarav.sharma@example.in','0173-1#07-AAS754#001','A1B2C3D4E5F67890ABCDEF1234567890ABCDEF12','A1B2C3D4E5F67890ABCDEF1234567890ABCDEF13','RSA Encryption','RSA-Verschlüsselung'),
+(2,'lukas.mueller@example.de','0173-1#07-AAS756#001','B2C3D4E5F67890ABCDEF1234567890ABCDEF1234','B2C3D4E5F67890ABCDEF1234567890ABCDEF1235','ECC Encryption','ECC-Verschlüsselung'),
+(3,'priya.mehta@example.in','0173-1#07-AAS757#001','C3D4E5F67890ABCDEF1234567890ABCDEF123456','C3D4E5F67890ABCDEF1234567890ABCDEF123457','DSA Signature','DSA-Signatur'),
+(4,'anna.schneider@example.de','0173-1#07-AAS758#001','E5F67890ABCDEF1234567890ABCDEF1234567890','E5F67890ABCDEF1234567890ABCDEF1234567891','EdDSA Signature','EdDSA-Signatur'),
+(5,'wei.li@example.cn','0173-1#07-AAS754#001','F67890ABCDEF1234567890ABCDEF1234567890AB','F67890ABCDEF1234567890ABCDEF1234567890AB','RSA Encryption','RSA-Verschlüsselung'),
+(6,'johann.becker@example.de','0173-1#07-AAS756#001','D4E5F67890ABCDEF1234567890ABCDEF12345678','D4E5F67890ABCDEF1234567890ABCDEF12345679','ECC Encryption','ECC-Verschlüsselung');
+
+-- ============================================================
+-- IP Communication Channels
+-- ============================================================
+
+INSERT INTO "IPCommunication" ("Index","AddressOfAdditionalLink","TypeOfCommunication","AvailableTime_en","AvailableTime_de") VALUES
+(0,'https://www.mm-software.com/more-the-newsroom/','Chat','Monday – Friday 08:00 to 16:00','Montag – Freitag 08:00 bis 16:00'),
+(1,'https://www.mm-software.com/more-the-newsroom/detail/digitaler-produktpass-dpp-in-der-praxis-leitfaden-und-checkliste-fuer-unternehmen/','Video call','Monday – Thursday 09:00 to 17:00','Montag – Donnerstag 09:00 bis 17:00'),
+(0,'https://www.mm-software.com/more-the-newsroom/','Chat','Tuesday – Saturday 07:30 to 15:30','Dienstag – Samstag 07:30 bis 15:30'),
+(0,'https://www.mm-software.com/we/','Video call','Monday – Friday 10:00 to 18:00','Montag – Freitag 10:00 bis 18:00'),
+(0,'https://www.mm-software.com/we/code-of-conduct/','Chat','Wednesday – Sunday 08:00 to 14:00','Mittwoch – Sonntag 08:00 bis 14:00'),
+(1,'https://www.mm-software.com/more-the-newsroom/anmeldung/','Video call','Monday – Friday 06:00 to 12:00','Montag – Freitag 06:00 bis 12:00'),
+(2,'https://www.mm-software.com/','Chat','Monday – Friday 08:00 to 16:00','Montag – Freitag 08:00 bis 16:00');
+
+-- ============================================================
+-- Contact-IPCommunication Relationships
+-- ============================================================
+
+INSERT INTO "ContactInformationIPCommunication" ("ContactInformationId","IPCommunicationId") VALUES
+(1,1),
+(1,2),
+(2,3),
+(3,4),
+(4,5),
+(5,4),
+(6,5),
+(6,6),
+(6,7);
+
+-- ============================================================
+-- Asset-ContactInformation Relationships
+-- ============================================================
+
+INSERT INTO "AssetContactInformation" (
+ "AssetId",
+ "ContactInformationId"
+)
+VALUES
+ (1, 1),
+ (1, 2),
+ (2, 3),
+ (3, 4),
+ (3, 5),
+ (3, 6);
diff --git a/example/postgres/04_handoverdocumentation.sql.inc b/example/postgres/04_handoverdocumentation.sql.inc
new file mode 100644
index 0000000..14d0e89
--- /dev/null
+++ b/example/postgres/04_handoverdocumentation.sql.inc
@@ -0,0 +1,224 @@
+-- ============================================================
+-- Classification and Document Data Insertion
+-- ============================================================
+-- This file contains CREATE and INSERT statements for:
+-- - Documents and Document metadata
+-- - Document Classifications
+-- - Document Versions
+-- - All related relationships
+-- ============================================================
+
+-- ============================================================
+-- Document Management Tables
+-- ============================================================
+
+CREATE TABLE "Document" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "Index" INT
+);
+
+CREATE TABLE "DocumentId" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "Index" INT,
+ "DocumentDomainId" UUID,
+ "DocumentIdentifier" TEXT,
+ "DocumentIsPrimary" BOOLEAN
+);
+
+CREATE TABLE "AssetDocument" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "AssetId" INT REFERENCES "Asset"("Id") ON DELETE CASCADE,
+ "DocumentId" INT REFERENCES "Document"("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "DocumentDocumentId" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "DocumentId" INT REFERENCES "Document"("Id") ON DELETE CASCADE,
+ "DocumentIdentifierId" INT REFERENCES "DocumentId"("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "DocumentClassification" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "Index" INT,
+ "ClassId" TEXT,
+ "ClassificationSystem" TEXT,
+ "ClassName_en" TEXT,
+ "ClassName_de" TEXT
+);
+
+CREATE TABLE "DocumentDocumentClassification" (
+ "Id" INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
+ "DocumentId" INT REFERENCES "Document"("Id") ON DELETE CASCADE,
+ "DocumentClassificationId" INT REFERENCES "DocumentClassification"("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "DocumentVersion" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "Index" INT,
+ "en" TEXT,
+ "DigitalFile" TEXT,
+ "Version" TEXT,
+ "StatusSetDate" DATE,
+ "StatusValue" TEXT,
+ "OrganizationShortName" TEXT,
+ "OrganizationOfficialName" TEXT,
+ "Title_en" TEXT,
+ "Title_de" TEXT,
+ "Subtitle_en" TEXT,
+ "Subtitle_de" TEXT,
+ "Description_en" TEXT,
+ "Description_de" TEXT,
+ "KeyWords_en" TEXT,
+ "KeyWords_de" TEXT,
+ "PreviewFile" TEXT
+);
+
+CREATE TABLE "DocumentDocumentVersion" (
+ "Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ "DocumentId" INT REFERENCES "Document"("Id") ON DELETE CASCADE,
+ "DocumentVersionId" INT REFERENCES "DocumentVersion"("Id") ON DELETE CASCADE
+);
+
+-- ============================================================
+-- Documents
+-- ============================================================
+
+INSERT INTO "Document" ("Index") VALUES
+(0),(1),(2),(0),(1),(0),(1);
+
+-- ============================================================
+-- Document Identifiers
+-- ============================================================
+
+INSERT INTO "DocumentId" ("Index","DocumentDomainId","DocumentIdentifier","DocumentIsPrimary") VALUES
+(0,'a3f1c2b4-9d81-4e5a-b6f2-01ac9e11d001','DOC2025A001',TRUE),
+(1,'b7e92d10-3c45-4a8f-9f21-02bc9e11d002','CERTX94B21',FALSE),
+(0,'c81a4f22-6d91-43bb-a812-03cd9e11d003','MANUAL8F2Q7',TRUE),
+(0,'a3f1c2b4-9d81-4e5a-b6f2-01ac9e11d002','DOC2025A002',TRUE),
+(0,'b7e92d10-3c45-4a8f-9f21-02bc9e11d003','CERTX94B22',TRUE),
+(0,'c81a4f22-6d91-43bb-a812-03cd9e11d004','MANUAL8F2Q8',TRUE),
+(1,'a3f1c2b4-9d81-4e5a-b6f2-01ac9e11d003','DOC2025A003',TRUE),
+(2,'b7e92d10-3c45-4a8f-9f21-02bc9e11d004','CERTX94B23',FALSE),
+(0,'c81a4f22-6d91-43bb-a812-03cd9e11d005','MANUAL8F2Q9',FALSE);
+
+-- ============================================================
+-- Asset-Document Relationships
+-- ============================================================
+
+INSERT INTO "AssetDocument" ("AssetId","DocumentId") VALUES
+(1,1),
+(1,2),
+(1,3),
+(2,4),
+(2,5),
+(3,6),
+(3,7);
+
+-- ============================================================
+-- Document-DocumentId Relationships
+-- ============================================================
+
+INSERT INTO "DocumentDocumentId" ("DocumentId","DocumentIdentifierId") VALUES
+(1,1),
+(1,2),
+(2,3),
+(3,4),
+(4,5),
+(5,6),
+(6,6),
+(7,9),
+(7,7),
+(7,8);
+
+-- ============================================================
+-- Document Classifications
+-- ============================================================
+
+INSERT INTO "DocumentClassification" ("Index","ClassId","ClassificationSystem","ClassName_en","ClassName_de") VALUES
+(0,'CLS-001','IEC-61360','Electrical Components','Elektrische Bauteile'),
+(1,'CLS-002','ISO-13584','Hydraulic Pumps','Hydraulikpumpen'),
+(0,'CLS-003','ECLASS-13.0','Industrial Sensors','Industrielle Sensoren'),
+(0,'CLS-004','UNSPSC','Fasteners','Befestigungselemente'),
+(0,'CLS-005','ISO-81346','Bearings','Lager'),
+(0,'CLS-006','IEC-61131','PLC Controllers','PLC-Steuerungen'),
+(1,'CLS-007','ECLASS-13.0','Safety Equipment','Sicherheitsausrüstung'),
+(2,'CLS-008','GS1','Packaging Materials','Verpackungsmaterialien'),
+(0,'CLS-009','ISO-13584','Cooling Systems','Kühlsysteme');
+
+-- ============================================================
+-- Document-Classification Relationships
+-- ============================================================
+
+INSERT INTO "DocumentDocumentClassification" ("DocumentId","DocumentClassificationId") VALUES
+(1,1),
+(1,2),
+(2,3),
+(3,4),
+(4,5),
+(5,6),
+(6,6),
+(7,9),
+(7,7),
+(7,8);
+
+-- ============================================================
+-- Document Versions
+-- ============================================================
+
+INSERT INTO "DocumentVersion" (
+ "Index","en","DigitalFile","Version","StatusSetDate","StatusValue","OrganizationShortName",
+ "OrganizationOfficialName","Title_en","Title_de","Subtitle_en","Subtitle_de","Description_en","Description_de",
+ "KeyWords_en","KeyWords_de","PreviewFile"
+) VALUES
+(0,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','1','2023-01-01','Released','M&M','M&M Germany',
+ 'User Guide – DSLR Camera Model X100','Benutzerhandbuch – DSLR-Kamera Modell X100','Complete Instructions for Professional Photography','Vollständige Anleitung für professionelle Fotografie',
+ 'Detailed instructions for operating the X100 DSLR camera, including setup and troubleshooting.','Detaillierte Anweisungen zur Bedienung der DSLR-Kamera X100, einschließlich Einrichtung und Fehlerbehebung',
+ 'DSLR, Camera, Photography, User Guide, Setup','DSLR, Kamera, Fotografie, Benutzerhandbuch, Einrichtung','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg'),
+
+(1,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','1.1','2024-05-05','InReview','M&M','M&M India',
+ 'Technical Specification – Mirrorless Camera Z-Series','Technische Spezifikation – Systemkamera der Z-Serie','Detailed Specs for Advanced Imaging','Detaillierte Spezifikationen für fortschrittliche Bildgebung',
+ 'Comprehensive technical details of the Z-Series mirrorless camera, covering sensor and performance.','Umfassende technische Details der spiegellosen Kamera Z-Serie, einschließlich Sensor und Leistung.','Mirrorless, Camera, Specs, Imaging, Performance','Spiegellos, Kamera, Spezifikationen, Bildgebung, Leistung','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg'),
+
+(0,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','2.1','2026-01-01','Released','M&M','M&M China',
+ 'Maintenance Manual – Professional Camera Lens 50mm','Wartungshandbuch – Professionelles Kameraobjektiv 50 mm','Care and Cleaning Procedures','Pflege und Reinigungsverfahren',
+ 'Guidelines for cleaning and maintaining the 50mm professional lens for optimal performance.','Richtlinien zur Reinigung und Wartung des professionellen 50-mm-Objektivs für optimale Leistung.','Lens, Maintenance, Cleaning, Professional, Care','Objektiv, Wartung, Reinigung, Professionell, Pflege','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg'),
+
+(0,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','2.3','2025-10-10','InReview','M&M','M&M Germany',
+ 'Installation Guide – Wide-Angle Lens Kit','Installationsanleitung – Weitwinkel-Objektiv-Kit','Step-by-Step Setup Instructions','Schritt-für-Schritt-Installationsanleitung',
+ 'Step-by-step instructions for installing and configuring the wide-angle lens kit.','Schritt-für-Schritt-Anleitung zur Installation und Konfiguration des Weitwinkel-Objektivsets.','Wide-Angle, Lens, Installation, Setup, Kit','Weitwinkel, Objektiv, Installation, Einrichtung, Set','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg'),
+
+(0,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','0.9','2024-01-01','Released','M&M','M&M India',
+ 'Product Data Sheet – Telephoto Lens 200mm','Produktdatenblatt – Teleobjektiv 200 mm','Technical Data and Performance Metrics','Technische Daten und Leistungskennzahlen',
+ 'Technical data and compatibility details for the 200mm telephoto lens.','Technische Daten und Kompatibilitätsdetails für das 200-mm-Teleobjektiv.','Telephoto, Lens, Data Sheet, Specifications, Optics','Teleobjektiv, Objektiv, Datenblatt, Spezifikationen, Optik','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg'),
+
+(0,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','1.2','2024-03-03','InReview','M&M','M&M China',
+ 'Safety Instructions – Digital Camera Accessories','Sicherheitsanweisungen – Zubehör für Digitalkameras','Guidelines for Safe Usage','Richtlinien für sichere Verwendung',
+ 'Safety guidelines for handling batteries, chargers, and other camera accessories.','Sicherheitsrichtlinien für den Umgang mit Batterien, Ladegeräten und anderem Kamera-Zubehör.','Safety, Camera, Accessories, Guidelines, Handling','Sicherheit, Kamera, Zubehör, Richtlinien, Handhabung','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg'),
+
+(1,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','1.4','2023-01-01','Released','M&M','M&M Germany',
+ 'Perfume Catalog – Luxury Fragrance Collection 2025','Parfümkatalog – Luxusduftkollektion 2025','Explore Elegant Scents for Every Occasion','Entdecken Sie elegante Düfte für jeden Anlass',
+ 'A curated catalog showcasing premium perfumes with scent profiles and packaging details.','Ein kuratierter Katalog mit Premium-Parfums, Duftprofilen und Verpackungsdetails.','Perfume, Fragrance, Luxury, Catalog, Collection','Parfum, Duft, Luxus, Katalog, Kollektion','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg'),
+
+(2,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','2','2024-03-03','InReview','M&M','M&M India',
+ 'Quality Assurance Report – Eau de Parfum Series A','Qualitätssicherungsbericht – Eau de Parfum Serie A','Verified Standards and Testing Results','Geprüfte Standards und Testergebnisse',
+ 'Report detailing quality checks and compliance standards for Series A perfumes.','Bericht mit Qualitätsprüfungen und Konformitätsstandards für Parfums der Serie A.','Packaging, Perfume, Bottles, Caps, Compliance','Verpackung, Parfum, Flaschen, Verschlüsse, Konformität','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg'),
+
+(0,'en','https://docs.google.com/viewer?url=https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.pdf','1','2022-02-02','Released','M&M','M&M Germany',
+ 'Packaging Standards – Perfume Bottles and Caps','Verpackungsstandards – Parfümflaschen und Verschlüsse','Design and Material Compliance Guidelines','Richtlinien für Design und Materialkonformität',
+ 'Design and material compliance guidelines for perfume packaging.','Richtlinien für Design und Materialkonformität bei Parfumverpackungen.','Perfume, Fragrance, Luxury, Catalog, Collection','Parfum, Duft, Luxus, Katalog, Kollektion','https://raw.githubusercontent.com/AAS-TwinEngine/AAS.TwinEngine.DataEngine/refs/heads/main/example/data/dummy_document.jpg');
+
+-- ============================================================
+-- Document-Version Relationships
+-- ============================================================
+
+INSERT INTO "DocumentDocumentVersion" ("DocumentId","DocumentVersionId") VALUES
+(1,1),
+(1,2),
+(2,3),
+(3,4),
+(4,5),
+(5,6),
+(6,6),
+(7,9),
+(7,7),
+(7,8);
diff --git a/example/postgres/init.sql b/example/postgres/init.sql
new file mode 100644
index 0000000..e82ea3e
--- /dev/null
+++ b/example/postgres/init.sql
@@ -0,0 +1,27 @@
+-- ============================================================
+-- DPP Plugin Database Initialization Script
+-- ============================================================
+-- This is the main orchestration file that executes all database
+-- initialization scripts in the correct hierarchical order.
+--
+-- Execution Order:
+-- 1. 01_core_asset_tables.sql.inc - Create core asset database schema
+-- 2. 02_nameplate_carbonfootprint_technicaldata.sql.inc - Create Nameplate, Carbon Footprint, Technical Data tables and insert data
+-- 3. 03_contactinformations.sql.inc - Create Contact information and relationships table and insert data
+-- 4. 04_handoverdocumentation.sql.inc - Create Handover Documentation table and insert data
+--
+-- ============================================================
+
+\echo 'Executing: 01_core_asset_tables.sql.inc - Creating core asset database schema...'
+\i /docker-entrypoint-initdb.d/01_core_asset_tables.sql.inc
+
+\echo 'Executing: 02_nameplate_carbonfootprint_technicaldata.sql.inc - Inserting data...'
+\i /docker-entrypoint-initdb.d/02_nameplate_carbonfootprint_technicaldata.sql.inc
+
+\echo 'Executing: 03_contactinformations.sql.inc - Inserting contact information...'
+\i /docker-entrypoint-initdb.d/03_contactinformations.sql.inc
+
+\echo 'Executing: 04_handoverdocumentation.sql.inc - Inserting document metadata...'
+\i /docker-entrypoint-initdb.d/04_handoverdocumentation.sql.inc
+
+\echo 'Database initialization completed successfully!'
diff --git a/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/AasRegistry/ShellDescriptorServiceTests.cs b/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/AasRegistry/ShellDescriptorServiceTests.cs
index 9848293..4de2a88 100644
--- a/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/AasRegistry/ShellDescriptorServiceTests.cs
+++ b/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/AasRegistry/ShellDescriptorServiceTests.cs
@@ -254,97 +254,92 @@ public async Task SyncShellDescriptorsAsync_ShouldHandle_EmptyListsGracefully()
}
[Fact]
- public async Task SyncShellDescriptorsAsync_ShouldThrow_InternalDataProcessingException_WhenRegistryDescriptorHasNoId()
+ public async Task SyncShellDescriptorsAsync_WhenRegistryDescriptorHasNoId_ShouldLogAndReturn()
{
var metaData = new ShellDescriptorsMetaData
{
- PagingMetaData = new PagingMetaData { Cursor = "nextCursor" },
+ PagingMetaData = new PagingMetaData(),
ShellDescriptors = [new ShellDescriptorMetaData { Id = "valid" }]
};
- _aasRegistryProvider.GetAllAsync(Arg.Any()).Returns([new ShellDescriptor { Id = "" }]);
- var manifests = new List
- {
- new()
- {
- PluginName = "TestPlugin",
- PluginUrl = new Uri("http://test-plugin"),
- SupportedSemanticIds = new List(),
- Capabilities = new Capabilities { HasShellDescriptor = true }
- }
- };
- _pluginManifestConflictHandler.Manifests.Returns(manifests);
- _pluginDataHandler.GetDataForAllShellDescriptorsAsync(null, null, manifests, Arg.Any()).Returns(metaData);
- await Assert.ThrowsAsync(() => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
+ _aasRegistryProvider
+ .GetAllAsync(Arg.Any())
+ .Returns([new ShellDescriptor { Id = "" }]);
+
+ _pluginDataHandler
+ .GetDataForAllShellDescriptorsAsync(null, null, Arg.Any>(), Arg.Any())
+ .Returns(metaData);
+
+ var exception = await Record.ExceptionAsync(
+ () => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
+
+ Assert.Null(exception);
+
+ await _aasRegistryProvider
+ .DidNotReceive()
+ .CreateAsync(Arg.Any(), Arg.Any());
}
[Fact]
- public async Task SyncShellDescriptorsAsync_WhenRegistryThrowsResourceNotFoundException_ThrowsShellDescriptorNotFoundException()
+ public async Task SyncShellDescriptorsAsync_WhenRegistryThrowsResourceNotFoundException_ShouldNotThrow()
{
- _aasRegistryProvider.GetAllAsync(Arg.Any())
- .Throws(new ResourceNotFoundException());
+ _aasRegistryProvider
+ .GetAllAsync(Arg.Any())
+ .Throws(new ResourceNotFoundException());
- var ex = await Assert.ThrowsAsync(() => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
+ var exception = await Record.ExceptionAsync(
+ () => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
- Assert.NotNull(ex.InnerException);
- Assert.IsType(ex.InnerException);
+ Assert.Null(exception);
}
[Fact]
- public async Task SyncShellDescriptorsAsync_WhenRegistryThrowsResponseParsingException_ThrowsInternalDataProcessingException()
+ public async Task SyncShellDescriptorsAsync_WhenRegistryThrowsResponseParsingException_ShouldNotThrow()
{
- _aasRegistryProvider.GetAllAsync(Arg.Any()).Throws(new ResponseParsingException());
+ _aasRegistryProvider
+ .GetAllAsync(Arg.Any())
+ .Throws(new ResponseParsingException());
- var ex = await Assert.ThrowsAsync(() => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
+ var exception = await Record.ExceptionAsync(
+ () => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
- Assert.NotNull(ex.InnerException);
- Assert.IsType(ex.InnerException);
+ Assert.Null(exception);
}
[Fact]
- public async Task SyncShellDescriptorsAsync_WhenRegistryThrowsRequestTimeoutException_ThrowsRegistryNotAvailableException()
+ public async Task SyncShellDescriptorsAsync_WhenRegistryThrowsRequestTimeoutException_ShouldNotThrow()
{
- _aasRegistryProvider.GetAllAsync(Arg.Any()).Throws(new RequestTimeoutException());
+ _aasRegistryProvider
+ .GetAllAsync(Arg.Any())
+ .Throws(new RequestTimeoutException());
- var ex = await Assert.ThrowsAsync(() => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
+ var exception = await Record.ExceptionAsync(
+ () => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
- Assert.NotNull(ex.InnerException);
- Assert.IsType(ex.InnerException);
+ Assert.Null(exception);
}
[Fact]
- public async Task SyncShellDescriptorsAsync_ShouldThrow_InternalDataProcessingException_WhenPluginMetadataHasNoId()
+ public async Task SyncShellDescriptorsAsync_WhenPluginMetadataHasNoId_ShouldLogAndReturn()
{
var metaData = new ShellDescriptorsMetaData
{
- PagingMetaData = new PagingMetaData { Cursor = "nextCursor" },
+ PagingMetaData = new PagingMetaData(),
ShellDescriptors = [new ShellDescriptorMetaData { Id = "" }]
};
- _aasRegistryProvider.GetAllAsync(Arg.Any()).Returns([new ShellDescriptor { Id = "1" }]);
- var manifests = new List
- {
- new()
- {
- PluginName = "TestPlugin",
- PluginUrl = new Uri("http://test-plugin"),
- SupportedSemanticIds = new List(),
- Capabilities = new Capabilities { HasShellDescriptor = true }
- }
- };
- _pluginManifestConflictHandler.Manifests.Returns(manifests);
- _pluginDataHandler.GetDataForAllShellDescriptorsAsync(null, null, manifests, Arg.Any()).Returns(metaData);
- await Assert.ThrowsAsync(() => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
- }
+ _aasRegistryProvider
+ .GetAllAsync(Arg.Any())
+ .Returns([new ShellDescriptor { Id = "1" }]);
- [Fact]
- public async Task SyncShellDescriptorsAsync_ShouldThrowException_WhenPluginFails()
- {
- _aasRegistryProvider.GetAllAsync(Arg.Any()).Returns([new ShellDescriptor { Id = "1" }]);
+ _pluginDataHandler
+ .GetDataForAllShellDescriptorsAsync(null, null, Arg.Any>(), Arg.Any())
+ .Returns(metaData);
- _pluginDataHandler.GetDataForAllShellDescriptorsAsync(null, null, Arg.Any>(), Arg.Any()).Throws(new InternalDataProcessingException());
+ var exception = await Record.ExceptionAsync(
+ () => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
- await Assert.ThrowsAsync(() => _sut.SyncShellDescriptorsAsync(CancellationToken.None));
+ Assert.Null(exception);
}
[Fact]
diff --git a/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/SemanticIdHandlerTests.cs b/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/SemanticIdHandlerTests.cs
index 457c508..fd96d9c 100644
--- a/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/SemanticIdHandlerTests.cs
+++ b/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/SemanticIdHandlerTests.cs
@@ -557,6 +557,31 @@ public void FillOutTemplate_SubmodelOfComplexData_ReturnsSubmodelWithValues()
AssertContactInfo(complexData1, 2, "Test1 John Doe");
}
+ [Fact]
+ public void FillOutTemplate_SubmodelOfComplexData_ReturnsSubmodelWithValue()
+ {
+ var complexData = TestData.ComplexData;
+ var submodel = TestData.CreateSubmodelWithComplexData();
+ submodel.SubmodelElements?.Add(complexData);
+ var values = TestData.CreateSubmodelWithInValidComplexDataTreeNode();
+
+ var submodelWithValues = (Submodel)_sut.FillOutTemplate(submodel, values);
+
+ Equal(2, submodelWithValues.SubmodelElements!.Count);
+ Equal("ComplexData0", submodelWithValues.SubmodelElements[0].IdShort);
+ Equal("ComplexData1", submodelWithValues.SubmodelElements[1].IdShort);
+ var complexData0 = GetSubmodelElementCollection(submodelWithValues, 0);
+ var complexData1 = GetSubmodelElementCollection(submodelWithValues, 1);
+ Equal(3, complexData1.Value!.Count);
+ AssertMultiLanguageProperty(complexData0, "Test Example Manufacturer", "Test Beispiel Hersteller");
+ AssertMultiLanguageProperty(complexData1, "Test1 Example Manufacturer", "Test1 Beispiel Hersteller");
+ AssertModelType(complexData0, 1, "22.47");
+ AssertModelType(complexData1, 1, "22.47");
+ AssertContactList(complexData0, 2, "Test John Doe", "Test Example Model");
+ AssertContactInfo(complexData0, 3, "Test John Doe");
+ AssertContactInfo(complexData1, 2, "Test1 John Doe");
+ }
+
[Fact]
public void FillOutTemplate_ShouldNotChangeAnyThing_WhenReferenceElementHasNullValue()
{
diff --git a/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/SubmodelTemplateServiceTests.cs b/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/SubmodelTemplateServiceTests.cs
index 3a38608..f41ebbc 100644
--- a/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/SubmodelTemplateServiceTests.cs
+++ b/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/SubmodelTemplateServiceTests.cs
@@ -189,22 +189,64 @@ public async Task GetSubmodelTemplateAsync_WithListIndexPath_ReturnsSubmodelWith
}
[Fact]
- public async Task GetSubmodelTemplateAsync_ThrowsNotFoundException_WhenListIndexIsOutOfRange()
+ public async Task GetSubmodelTemplateAsync_Supports_UrlEncoded_ListIndex()
{
var submodel = TestData.CreateSubmodelWithModel3DList();
- const string Path = "Model3D[5].ModelFile1";
+ const string Path = "Model3D%5B0%5D.ModelDataFile";
+
_mappingProvider.GetTemplateId(SubmodelId).Returns(TemplateId);
_templateProvider.GetSubmodelTemplateAsync(TemplateId, Arg.Any())
.Returns(submodel);
- await Assert.ThrowsAsync(() => _sut.GetSubmodelTemplateAsync(SubmodelId, Path, CancellationToken.None));
+ var result = await _sut.GetSubmodelTemplateAsync(SubmodelId, Path, CancellationToken.None);
+
+ Assert.NotNull(result);
}
[Fact]
- public async Task GetSubmodelTemplateAsync_ThrowsNotFoundException_WhenListElementNotFound()
+ public async Task GetSubmodelTemplateAsync_Throws_When_ListIndex_IsNegative()
{
var submodel = TestData.CreateSubmodelWithModel3DList();
- const string Path = "NonExistentList[0].ModelFile1";
+ const string Path = "Model3D[-1]";
+
+ _mappingProvider.GetTemplateId(SubmodelId).Returns(TemplateId);
+ _templateProvider.GetSubmodelTemplateAsync(TemplateId, Arg.Any())
+ .Returns(submodel);
+
+ await Assert.ThrowsAsync(
+ () => _sut.GetSubmodelTemplateAsync(SubmodelId, Path, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetSubmodelTemplateAsync_ReturnsSubmodel_WhenTypeValueListElementIsSubmodelCollection_AndListIndexExceedsAvailableElements()
+ {
+ var expectedSubmodel = TestData.CreateSubmodelWithModel3DList();
+ var submodel = TestData.CreateSubmodelWithModel3DList();
+ const string Path = "Model3D[5].ModelDataFile";
+ _mappingProvider.GetTemplateId(SubmodelId).Returns(TemplateId);
+ _templateProvider.GetSubmodelTemplateAsync(TemplateId, Arg.Any())
+ .Returns(submodel);
+
+ var result = await _sut.GetSubmodelTemplateAsync(SubmodelId, Path, CancellationToken.None);
+
+ Assert.Equal(GetSemanticId(expectedSubmodel), GetSemanticId(result));
+
+ var list = result.SubmodelElements?.FirstOrDefault() as SubmodelElementList;
+ Assert.NotNull(list);
+ Assert.Single(list.Value!);
+ var collection = list.Value![0] as SubmodelElementCollection;
+ Assert.Single(collection!.Value!);
+ var file = collection!.Value!.FirstOrDefault() as File;
+ Assert.NotNull(file);
+ Assert.Equal("ModelDataFile", file.IdShort);
+ Assert.Equal("https://localhost/ModelDataFile.glb", file.Value);
+ }
+
+ [Fact]
+ public async Task GetSubmodelTemplateAsync_ThrowsInternalDataProcessingException_WhenTypeValueListElementIsSubmodelProperty_AndListIndexExceedsAvailableElements()
+ {
+ var submodel = TestData.CreateSubmodelWithPropertyInsideList();
+ const string Path = "listProperty[2]";
_mappingProvider.GetTemplateId(SubmodelId).Returns(TemplateId);
_templateProvider.GetSubmodelTemplateAsync(TemplateId, Arg.Any())
.Returns(submodel);
@@ -280,5 +322,4 @@ public async Task GetSubmodelTemplateAsync_WithIdShortPath_ThrowsSubmodelElement
await Assert.ThrowsAsync(
() => _sut.GetSubmodelTemplateAsync(SubmodelId, "SomePath", CancellationToken.None));
}
-
}
diff --git a/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/TestData.cs b/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/TestData.cs
index b3732d2..07c7fbf 100644
--- a/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/TestData.cs
+++ b/source/AAS.TwinEngine.DataEngine.UnitTests/ApplicationLogic/Services/SubmodelRepository/TestData.cs
@@ -632,6 +632,41 @@ public static Submodel CreateSubmodelWithoutExtraElementsNested()
);
}
+ public static SubmodelElementList CreateElementListWithProperty()
+ {
+ return new SubmodelElementList(
+ idShort: "listProperty",
+ semanticId: new Reference(
+ ReferenceTypes.ExternalReference,
+ [
+ new Key(KeyTypes.SubmodelElementList,
+ "http://example.com/idta/digital-nameplate/list-property")
+ ]
+ ),
+ typeValueListElement: AasSubmodelElements.Property,
+ value: [
+ CreateContactName()
+ ]
+ );
+ }
+
+ public static Submodel CreateSubmodelWithPropertyInsideList()
+ {
+ return new Submodel(
+ id: "http://example.com/idta/digital-nameplate",
+ idShort: "DigitalNameplate",
+ semanticId: new Reference(
+ ReferenceTypes.ExternalReference,
+ [
+ new Key(KeyTypes.Submodel, "http://example.com/idta/digital-nameplate/semantic-id")
+ ]
+ ),
+ submodelElements: [
+ CreateElementListWithProperty()
+ ]
+ );
+ }
+
public static Submodel CreateSubmodelWithoutExtraElements()
{
return new Submodel(
@@ -720,6 +755,45 @@ public static Submodel CreateSubmodelWithModel3DList()
]
);
+ public static readonly SubmodelElementCollection InValidComplexData = new(
+ idShort: "ComplexData",
+ semanticId: new Reference(
+ ReferenceTypes.ExternalReference,
+ [
+ new Key(KeyTypes.SubmodelElementList, "http://example.com/idta/digital-nameplate/complex-data")
+ ]
+ ),
+ qualifiers:
+ [
+ new Qualifier(
+ type: "ExternalReference",
+ valueType: DataTypeDefXsd.String,
+ value: "OneToMany")
+ ],
+ value: [
+ CreateManufacturerName(),
+ new Property(
+ idShort: "ModelType",
+ valueType: DataTypeDefXsd.String,
+ value: "", // left intentionally empty for FillOut tests
+ semanticId: new Reference(
+ ReferenceTypes.ExternalReference,
+ [
+ new Key(KeyTypes.Property, "http://example.com/idta/digital-nameplate/model-type")
+ ]
+ ),
+ qualifiers:
+ [
+ new Qualifier(
+ type: "ExternalReference",
+ valueType: DataTypeDefXsd.String,
+ value: "ZeroToOne")
+ ]),
+ CreateContactList(),
+ CreateContactInformation(),
+ ]
+);
+
public static readonly SemanticTreeNode SubmodelTreeNode = CreateSubmodelTreeNode();
public static SemanticTreeNode CreateSubmodelTreeNode()
@@ -778,6 +852,41 @@ public static SemanticTreeNode CreateSubmodelWithComplexDataTreeNode()
return semanticTreeNode;
}
+ public static SemanticTreeNode CreateSubmodelWithInValidComplexDataTreeNode()
+ {
+ var semanticTreeNode = new SemanticBranchNode("http://example.com/idta/digital-nameplate/semantic-id", Cardinality.Unknown);
+
+ var complexDataBranchNode1 = new SemanticBranchNode("http://example.com/idta/digital-nameplate/complex-data", Cardinality.ZeroToMany);
+
+ var complexDataBranchNode2 = new SemanticBranchNode("http://example.com/idta/digital-nameplate/complex-data", Cardinality.ZeroToMany);
+
+ semanticTreeNode.AddChild(complexDataBranchNode1);
+
+ semanticTreeNode.AddChild(complexDataBranchNode2);
+
+ complexDataBranchNode1.AddChild(CreateManufacturerNameTreeNode());
+
+ complexDataBranchNode1.AddChild(CreateModelTypeTreeNode());
+
+ complexDataBranchNode1.AddChild(CreateContactListTreeNode());
+
+ complexDataBranchNode1.AddChild(CreateContactInformationTreeNode());
+
+ complexDataBranchNode2.AddChild(CreateManufacturerNameTreeNode("1"));
+
+ complexDataBranchNode2.AddChild(CreateModelTypeTreeNode());
+
+ complexDataBranchNode2.AddChild(CreateContactListTreeNode("1"));
+
+ complexDataBranchNode2.AddChild(CreateContactListTreeNode("2"));
+
+ complexDataBranchNode2.AddChild(new SemanticLeafNode("http://example.com/idta/digital-nameplate/contact-list", $"Test InValid Contact List", DataType.String, Cardinality.One));
+
+ complexDataBranchNode2.AddChild(CreateContactInformationTreeNode("1"));
+
+ return semanticTreeNode;
+ }
+
public static SemanticTreeNode CreateManufacturerNameTreeNode(string testObject = "")
{
var manufacturerName = new SemanticBranchNode("http://example.com/idta/digital-nameplate/manufacturer-name", Cardinality.One);
diff --git a/source/AAS.TwinEngine.DataEngine.UnitTests/Infrastructure/Providers/ProviderTestData.cs b/source/AAS.TwinEngine.DataEngine.UnitTests/Infrastructure/Providers/ProviderTestData.cs
index 67ac836..714ac2b 100644
--- a/source/AAS.TwinEngine.DataEngine.UnitTests/Infrastructure/Providers/ProviderTestData.cs
+++ b/source/AAS.TwinEngine.DataEngine.UnitTests/Infrastructure/Providers/ProviderTestData.cs
@@ -89,7 +89,7 @@ public static class ProviderTestData
"contentType": "image/jpeg",
"path": "http://localhost/fileprovider/k.jpg"
},
- "globalAssetId": "https://sew-eurodrive.de/shell/1"
+ "globalAssetId": "https://mm-software.de/shell/1"
}
""";
@@ -118,9 +118,9 @@ public static class ProviderTestData
"specificAssetIds": []
},
{
- "globalAssetId": "https://wago.com/ids/assets/2206-1631/1000-859",
+ "globalAssetId": "https://mm-software.com/ids/assets/2206-1631/1000-859",
"idShort": "2206-1631/1000-859",
- "id": "https://wago.com/ids/aas/2206-1631/1000-859",
+ "id": "https://mm-software.com/ids/aas/2206-1631/1000-859",
"specificAssetIds": []
}
]
diff --git a/source/AAS.TwinEngine.DataEngine.UnitTests/Infrastructure/Providers/TemplateProvider/Services/TemplateProviderTests.cs b/source/AAS.TwinEngine.DataEngine.UnitTests/Infrastructure/Providers/TemplateProvider/Services/TemplateProviderTests.cs
index 54bdea1..bc8e684 100644
--- a/source/AAS.TwinEngine.DataEngine.UnitTests/Infrastructure/Providers/TemplateProvider/Services/TemplateProviderTests.cs
+++ b/source/AAS.TwinEngine.DataEngine.UnitTests/Infrastructure/Providers/TemplateProvider/Services/TemplateProviderTests.cs
@@ -269,7 +269,7 @@ public async Task GetAssetInformationTemplateAsync_ReturnsAssetInformation_WhenV
var result = await _sut.GetAssetInformationTemplateAsync(TemplateId, CancellationToken.None);
Assert.NotNull(result);
- Assert.Equal("https://sew-eurodrive.de/shell/1", result.GlobalAssetId);
+ Assert.Equal("https://mm-software.de/shell/1", result.GlobalAssetId);
}
[Fact]
diff --git a/source/AAS.TwinEngine.DataEngine.sln b/source/AAS.TwinEngine.DataEngine.sln
index 72313cb..b56b843 100644
--- a/source/AAS.TwinEngine.DataEngine.sln
+++ b/source/AAS.TwinEngine.DataEngine.sln
@@ -9,6 +9,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AAS.TwinEngine.DataEngine.U
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AAS.TwinEngine.DataEngine.ModuleTests", "AAS.TwinEngine.DataEngine.ModuleTests\AAS.TwinEngine.DataEngine.ModuleTests.csproj", "{D16C8CF8-6A29-4A40-971A-9A070A1817A9}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AAS.TwinEngine.Plugin.TestPlugin", "AAS.TwinEngine.Plugin.TestPlugin\AAS.TwinEngine.Plugin.TestPlugin.csproj", "{455B960D-57D0-4D9B-805C-E1DEA05B9311}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AAS.TwinEngine.Plugin.TestPlugin.UnitTests", "AAS.TwinEngine.Plugin.TestPlugin.UnitTests\AAS.TwinEngine.Plugin.TestPlugin.UnitTests.csproj", "{573F3A2B-8CC3-40D8-B543-74BF5DF7D4FF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +31,14 @@ Global
{D16C8CF8-6A29-4A40-971A-9A070A1817A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D16C8CF8-6A29-4A40-971A-9A070A1817A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D16C8CF8-6A29-4A40-971A-9A070A1817A9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {455B960D-57D0-4D9B-805C-E1DEA05B9311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {455B960D-57D0-4D9B-805C-E1DEA05B9311}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {455B960D-57D0-4D9B-805C-E1DEA05B9311}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {455B960D-57D0-4D9B-805C-E1DEA05B9311}.Release|Any CPU.Build.0 = Release|Any CPU
+ {573F3A2B-8CC3-40D8-B543-74BF5DF7D4FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {573F3A2B-8CC3-40D8-B543-74BF5DF7D4FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {573F3A2B-8CC3-40D8-B543-74BF5DF7D4FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {573F3A2B-8CC3-40D8-B543-74BF5DF7D4FF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/AasRegistry/ShellDescriptorService.cs b/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/AasRegistry/ShellDescriptorService.cs
index 63e2529..4a13fec 100644
--- a/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/AasRegistry/ShellDescriptorService.cs
+++ b/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/AasRegistry/ShellDescriptorService.cs
@@ -72,26 +72,37 @@ public class ShellDescriptorService(
throw new InvalidUserInputException(ex);
}
}
+
public async Task SyncShellDescriptorsAsync(CancellationToken cancellationToken)
{
try
{
- var existingDescriptors = await aasRegistryProvider.GetAllAsync(cancellationToken).ConfigureAwait(false) ?? throw new RegistryNotAvailableException();
+ var existingDescriptors = await aasRegistryProvider.GetAllAsync(cancellationToken).ConfigureAwait(false);
+ if (existingDescriptors == null)
+ {
+ logger.LogError("AAS Registry returned null. Sync skipped.");
+ return;
+ }
var pluginManifests = pluginManifestConflictHandler.Manifests;
- var pluginMetadata = await pluginDataHandler.GetDataForAllShellDescriptorsAsync(null, null, pluginManifests, cancellationToken).ConfigureAwait(false) ?? throw new PluginNotAvailableException();
+ var pluginMetadata = await pluginDataHandler.GetDataForAllShellDescriptorsAsync(null, null, pluginManifests, cancellationToken).ConfigureAwait(false);
+ if (pluginMetadata == null)
+ {
+ logger.LogError("Plugin metadata unavailable. Sync skipped.");
+ return;
+ }
if (existingDescriptors.Any(d => string.IsNullOrWhiteSpace(d.Id)))
{
logger.LogError("One or more registry descriptors have missing IDs: {@Descriptors}", existingDescriptors);
- throw new InternalDataProcessingException();
+ return;
}
if (pluginMetadata.ShellDescriptors.Any(m => string.IsNullOrWhiteSpace(m.Id)))
{
logger.LogError("One or more plugin metadata entries have missing IDs: {@Metadata}", pluginMetadata);
- throw new InternalDataProcessingException();
+ return;
}
var existingDescriptorsMap = existingDescriptors.ToDictionary(d => d.Id!);
@@ -100,26 +111,9 @@ public async Task SyncShellDescriptorsAsync(CancellationToken cancellationToken)
await CreateOrUpdateShellDescriptorsAsync(existingDescriptorsMap!, pluginMetadata.ShellDescriptors, cancellationToken).ConfigureAwait(false);
await DeleteMissingShellDescriptorsAsync(existingDescriptors, pluginMetadataMap!, cancellationToken).ConfigureAwait(false);
}
- catch (ResourceNotFoundException ex)
- {
- throw new ShellDescriptorNotFoundException(ex);
- }
- catch (ResponseParsingException ex)
- {
- throw new InternalDataProcessingException(ex);
- }
- catch (RequestTimeoutException ex)
- {
- throw new RegistryNotAvailableException(ex);
- }
- catch (PluginMetaDataInvalidRequestException ex)
- {
- throw new InvalidUserInputException(ex);
- }
catch (Exception ex)
{
logger.LogError(ex, "Unexpected error during ShellDescriptor synchronization.");
- throw new InternalDataProcessingException();
}
}
@@ -144,22 +138,10 @@ private async Task CreateOrUpdateShellDescriptorsAsync(
await aasRegistryProvider.CreateAsync(newDescriptor, cancellationToken).ConfigureAwait(false);
}
}
- catch (ResourceNotFoundException ex)
- {
- throw new ShellDescriptorNotFoundException(ex);
- }
- catch (ResponseParsingException ex)
- {
- throw new InternalDataProcessingException(ex);
- }
- catch (RequestTimeoutException ex)
- {
- throw new RegistryNotAvailableException(ex);
- }
catch (Exception ex)
{
logger.LogError(ex, "Unhandled error while processing descriptor with ID '{Id}'", metadata.Id);
- throw new InternalDataProcessingException(ex);
+ continue;
}
}
}
@@ -184,14 +166,10 @@ private async Task DeleteMissingShellDescriptorsAsync(
{
await aasRegistryProvider.DeleteByIdAsync(descriptorId!, cancellationToken).ConfigureAwait(false);
}
- catch (RequestTimeoutException ex)
- {
- throw new ShellDescriptorNotFoundException(ex);
- }
catch (Exception ex)
{
logger.LogError(ex, "Unexpected error while deleting descriptor with ID '{Id}'", descriptorId);
- throw new InternalDataProcessingException(ex);
+ continue;
}
}
}
diff --git a/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SemanticIdHandler.cs b/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SemanticIdHandler.cs
index 646b923..cca443c 100644
--- a/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SemanticIdHandler.cs
+++ b/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SemanticIdHandler.cs
@@ -526,6 +526,15 @@ private void FillOutSubmodelElementValue(List elements, Semant
continue;
}
+ if (!AreAllNodesOfSameType(semanticTreeNodes, out _))
+ {
+ logger.LogWarning("Mixed node types found for element '{IdShort}' with SemanticId '{SemanticId}'. Expected all nodes to be either SemanticBranchNode or SemanticLeafNode. Removing element.",
+ element.IdShort,
+ ExtractSemanticId(element));
+ _ = elements.Remove(element);
+ continue;
+ }
+
if (semanticTreeNodes.Count > 1 && element is not Property && element is not ReferenceElement)
{
_ = elements.Remove(element);
@@ -548,6 +557,25 @@ private void FillOutSubmodelElementValue(List elements, Semant
}
}
+ private static bool AreAllNodesOfSameType(List nodes, out Type? nodeType)
+ {
+ if (nodes.Count == 0)
+ {
+ nodeType = null;
+ return true;
+ }
+
+ var firstNodeType = nodes[0].GetType();
+ nodeType = firstNodeType;
+
+ if (firstNodeType != typeof(SemanticBranchNode) && firstNodeType != typeof(SemanticLeafNode))
+ {
+ return false;
+ }
+
+ return nodes.All(node => node.GetType() == firstNodeType);
+ }
+
private void HandleSingleSemanticTreeNode(ISubmodelElement element, SemanticTreeNode node) => FillOutTemplate(element, node);
private void FillOutMultiLanguageProperty(MultiLanguageProperty mlp, SemanticTreeNode values)
@@ -800,7 +828,7 @@ private static IEnumerable FindNodeBySemanticId(SemanticTreeNo
/// e.g. "element[3]" -> matches Group1= "element", Group2 = "3"
/// Pattern: ^(.+?)\[(\d+)\]$
///
- [GeneratedRegex(@"^(.+?)\[(\d+)\]$")]
+ [GeneratedRegex(@"^(.+?)(?:\[(\d+)\]|%5B(\d+)%5D)$")]
private static partial Regex SubmodelElementListIndex();
///
@@ -821,19 +849,27 @@ private static IEnumerable FindNodeBySemanticId(SemanticTreeNo
return submodelElements?.FirstOrDefault(e => e.IdShort == idShort);
}
- private static bool TryParseIdShortWithBracketIndex(string segment, out string idShortWithoutIndex, out int index)
+ private static bool TryParseIdShortWithBracketIndex(string idShort, out string idShortWithoutIndex, out int index)
{
- var match = SubmodelElementListIndex().Match(segment);
- if (match.Success)
+ var match = SubmodelElementListIndex().Match(idShort);
+ if (!match.Success)
{
- idShortWithoutIndex = match.Groups[1].Value;
- index = int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
- return true;
+ idShortWithoutIndex = string.Empty;
+ index = -1;
+ return false;
+ }
+
+ idShortWithoutIndex = match.Groups[1].Value;
+ var indexGroup = match.Groups[2].Success ? match.Groups[2] : match.Groups[3];
+ if (!indexGroup.Success)
+ {
+ idShortWithoutIndex = string.Empty;
+ index = -1;
+ return false;
}
- idShortWithoutIndex = string.Empty;
- index = -1;
- return false;
+ index = int.Parse(indexGroup.Value, CultureInfo.InvariantCulture);
+ return true;
}
private ISubmodelElement GetElementFromListByIndex(IEnumerable? elements, string idShortWithoutIndex, int index)
diff --git a/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SubmodelTemplateService.cs b/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SubmodelTemplateService.cs
index ab72948..385d5ca 100644
--- a/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SubmodelTemplateService.cs
+++ b/source/AAS.TwinEngine.DataEngine/ApplicationLogic/Services/SubmodelRepository/SubmodelTemplateService.cs
@@ -5,6 +5,7 @@
using AAS.TwinEngine.DataEngine.ApplicationLogic.Exceptions.Base;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Exceptions.Infrastructure;
using AAS.TwinEngine.DataEngine.ApplicationLogic.Services.AasEnvironment.Providers;
+using AAS.TwinEngine.DataEngine.DomainModel.SubmodelRepository;
using AasCore.Aas3_0;
@@ -131,16 +132,24 @@ private static ISubmodelElement FindMatchingElement(IEnumerable elements, string idShort)
@@ -157,7 +166,20 @@ private static SubmodelElementList GetListElementByIdShort(List= list.Value?.Count)
+ if (index < 0)
+ {
+ throw new InternalDataProcessingException();
+ }
+
+ if (list.TypeValueListElement is AasSubmodelElements.SubmodelElementCollection or AasSubmodelElements.SubmodelElementList && list.Value?.Count > 0)
+ {
+ if (GetCardinality(list.Value.FirstOrDefault()!) is Cardinality.OneToMany or Cardinality.ZeroToMany)
+ {
+ return list.Value.FirstOrDefault()!;
+ }
+ }
+
+ if (index >= list.Value?.Count)
{
throw new InternalDataProcessingException();
}
@@ -183,7 +205,7 @@ private static SubmodelElementList GetListElementByIdShort(List matches Group1= "element", Group2 = "3"
/// Pattern: ^(.+?)\[(\d+)\]$
///
- [GeneratedRegex(@"^(.+?)\[(\d+)\]$")]
+ [GeneratedRegex(@"^(.+?)(?:\[(\d+)\]|%5B(\d+)%5D)$")]
private static partial Regex SubmodelElementListIndex();
///
@@ -201,4 +223,17 @@ private static void ValidateSubmodelId(string submodelId)
throw new InternalDataProcessingException();
}
}
+
+ private static Cardinality GetCardinality(ISubmodelElement element)
+ {
+ var qualifierValue = element.Qualifiers?.FirstOrDefault()?.Value;
+ if (qualifierValue is null)
+ {
+ return Cardinality.Unknown;
+ }
+
+ return Enum.TryParse(qualifierValue, ignoreCase: true, out var result)
+ ? result
+ : Cardinality.Unknown;
+ }
}
diff --git a/source/AAS.TwinEngine.DataEngine/Dockerfile b/source/AAS.TwinEngine.DataEngine/Dockerfile
index 5ff23cd..63b409d 100644
--- a/source/AAS.TwinEngine.DataEngine/Dockerfile
+++ b/source/AAS.TwinEngine.DataEngine/Dockerfile
@@ -1,31 +1,23 @@
-#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
-
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
-USER app
-WORKDIR /app
-EXPOSE 8080
-
-FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:8.0@sha256:aa05b91be697b83229cb000b90120f0783604ad74ed92a0b45cdf3d1a9c873de AS build
+# Install CycloneDX SBOM Generator Package
+RUN dotnet tool install --global CycloneDX --version 5.5.0
+ENV PATH="$PATH:/root/.dotnet/tools"
+# Build application
ARG BUILD_CONFIGURATION=Release
-WORKDIR /src
-COPY ["AAS.TwinEngine.DataEngine/AAS.TwinEngine.DataEngine.csproj", "AAS.TwinEngine.DataEngine/"]
+WORKDIR /App
+COPY ["AAS.TwinEngine.DataEngine/", "AAS.TwinEngine.DataEngine/"]
RUN dotnet restore "AAS.TwinEngine.DataEngine/AAS.TwinEngine.DataEngine.csproj"
-COPY AAS.TwinEngine.DataEngine/ AAS.TwinEngine.DataEngine/
-WORKDIR "/src/AAS.TwinEngine.DataEngine"
-
-RUN dotnet build "AAS.TwinEngine.DataEngine.csproj" -c "$BUILD_CONFIGURATION" -o /app/build
+RUN dotnet publish "AAS.TwinEngine.DataEngine/AAS.TwinEngine.DataEngine.csproj" -c "$BUILD_CONFIGURATION" -o out
+# Generate Application SBOM at sbom/bom.xml (omitting dev/test dependencies as they do not appear in final build)
+RUN dotnet-CycloneDX "AAS.TwinEngine.DataEngine/AAS.TwinEngine.DataEngine.csproj" -o "sbom/" --exclude-dev --exclude-test-projects --set-nuget-purl --spec-version 1.6 --disable-package-restore
-FROM build AS publish
-ARG BUILD_CONFIGURATION=Release
-RUN dotnet publish "AAS.TwinEngine.DataEngine.csproj" -c "$BUILD_CONFIGURATION" -o /app/publish /p:UseAppHost=false
-
-FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
+# Create an "app-sbom-artifact" image which can be use to extract the pure APP SBOM after completing the docker build (we want to keep the SBOM for the application separate from the pure linux image SBOM as this provides more details and simplifies vuln management)
+FROM scratch AS app-sbom-artifact
+COPY --from=build /App/sbom/bom.xml /sbom_application.cyclonedx.xml
-RUN useradd -m appuser \
- && mkdir /app \
- && chown appuser:appuser /app
-
-USER appuser
-WORKDIR /app
-COPY --from=publish /app/publish .
+# Create final image containing application
+FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine@sha256:a0ce42fe86548363a9602c47fc3bd4cf9c35a2705c68cd98d7ce18ae8735b83c
+USER app
+WORKDIR /App
+COPY --from=build /App/out .
ENTRYPOINT ["dotnet", "AAS.TwinEngine.DataEngine.dll"]
diff --git a/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/PluginDataProvider/Services/MultiPluginDataHandler.cs b/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/PluginDataProvider/Services/MultiPluginDataHandler.cs
index 516f5bd..05ce5f5 100644
--- a/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/PluginDataProvider/Services/MultiPluginDataHandler.cs
+++ b/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/PluginDataProvider/Services/MultiPluginDataHandler.cs
@@ -131,7 +131,7 @@ public SemanticTreeNode Merge(SemanticTreeNode globalTree, IList valueTrees)
+ private SemanticTreeNode MergeBranch(SemanticBranchNode branch, IList valueTrees)
{
var mergedBranch = new SemanticBranchNode(branch.SemanticId, branch.Cardinality);
@@ -241,8 +241,14 @@ private static List MergeBranchNodes(SemanticBranchNode templa
}
}
- private static List FindMatchingNodes(IEnumerable valueTrees, string semanticId)
+ private List FindMatchingNodes(IEnumerable valueTrees, string semanticId)
{
+ if (semanticId.Contains(_submodelElementIndexContextPrefix, StringComparison.Ordinal))
+ {
+ var indexPrefixIndex = semanticId.IndexOf(_submodelElementIndexContextPrefix, StringComparison.OrdinalIgnoreCase);
+ semanticId = semanticId[..indexPrefixIndex];
+ }
+
var matches = new List();
foreach (var vt in valueTrees.OfType())
diff --git a/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/PluginDataProvider/Services/PluginDataHandler.cs b/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/PluginDataProvider/Services/PluginDataHandler.cs
index 98623a3..e7d6306 100644
--- a/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/PluginDataProvider/Services/PluginDataHandler.cs
+++ b/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/PluginDataProvider/Services/PluginDataHandler.cs
@@ -11,6 +11,7 @@
using AAS.TwinEngine.DataEngine.DomainModel.Plugin;
using AAS.TwinEngine.DataEngine.DomainModel.SubmodelRepository;
using AAS.TwinEngine.DataEngine.Infrastructure.Providers.PluginDataProvider.Helper;
+using AAS.TwinEngine.DataEngine.Infrastructure.Shared;
using Json.Schema;
@@ -82,7 +83,7 @@ public async Task GetDataForAllShellDescriptorsAsync(i
try
{
- var shellDescriptorData = JsonSerializer.Deserialize(responseContent);
+ var shellDescriptorData = JsonSerializer.Deserialize(responseContent, JsonSerializationOptions.DeserializationOption);
if (shellDescriptorData == null)
{
logger.LogError("Failed to deserialize All ShellDescriptorData. Response content: {Content}", responseContent);
diff --git a/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/TemplateProvider/Services/ShellTemplateMappingProvider.cs b/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/TemplateProvider/Services/ShellTemplateMappingProvider.cs
index 1d59b88..30b7577 100644
--- a/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/TemplateProvider/Services/ShellTemplateMappingProvider.cs
+++ b/source/AAS.TwinEngine.DataEngine/Infrastructure/Providers/TemplateProvider/Services/ShellTemplateMappingProvider.cs
@@ -43,7 +43,7 @@ public string GetProductIdFromRule(string aasIdentifier)
})
.Where(x => x.Parts is { Length: >= 1 } && x.Rule.Index > 0 && x.Parts.Length >= x.Rule.Index)
.Select(x => x.Parts![x.Rule.Index - 1])
- .FirstOrDefault();
+ .FirstOrDefault(extractedId => !string.Equals(extractedId, aasIdentifier, StringComparison.Ordinal));
if (!string.IsNullOrEmpty(productId))
{
diff --git a/source/AAS.TwinEngine.DataEngine/Infrastructure/Shared/JsonSerializationOptions.cs b/source/AAS.TwinEngine.DataEngine/Infrastructure/Shared/JsonSerializationOptions.cs
index b3e4a39..5b38e80 100644
--- a/source/AAS.TwinEngine.DataEngine/Infrastructure/Shared/JsonSerializationOptions.cs
+++ b/source/AAS.TwinEngine.DataEngine/Infrastructure/Shared/JsonSerializationOptions.cs
@@ -25,4 +25,9 @@ public static class JsonSerializationOptions
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }
};
+
+ public static readonly JsonSerializerOptions DeserializationOption = new()
+ {
+ PropertyNameCaseInsensitive = true
+ };
}
diff --git a/source/AAS.TwinEngine.DataEngine/Program.cs b/source/AAS.TwinEngine.DataEngine/Program.cs
index b603dc6..ff0b43a 100644
--- a/source/AAS.TwinEngine.DataEngine/Program.cs
+++ b/source/AAS.TwinEngine.DataEngine/Program.cs
@@ -1,6 +1,4 @@
-using System.Globalization;
-
-using AAS.TwinEngine.DataEngine.ApplicationLogic.Exceptions.Infrastructure;
+using AAS.TwinEngine.DataEngine.ApplicationLogic.Exceptions.Infrastructure;
using AAS.TwinEngine.DataEngine.Infrastructure.Monitoring;
using AAS.TwinEngine.DataEngine.Infrastructure.Providers.PluginDataProvider.Services;
using AAS.TwinEngine.DataEngine.ServiceConfiguration;
diff --git a/source/AAS.TwinEngine.DataEngine/appsettings.development.json b/source/AAS.TwinEngine.DataEngine/appsettings.development.json
index bbce44b..071ae0f 100644
--- a/source/AAS.TwinEngine.DataEngine/appsettings.development.json
+++ b/source/AAS.TwinEngine.DataEngine/appsettings.development.json
@@ -13,10 +13,6 @@
{
"PluginName": "Plugin1",
"PluginUrl": "http://localhost:8086"
- },
- {
- "PluginName": "Plugin2",
- "PluginUrl": "http://localhost:8087"
}
]
},
@@ -56,6 +52,18 @@
{
"templateId": "https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0",
"pattern": [ "ContactInformation" ]
+ },
+ {
+ "templateId": "https://admin-shell.io/ZVEI/TechnicalData/Submodel/1/2",
+ "pattern": [ "TechnicalData" ]
+ },
+ {
+ "templateId": "https://admin-shell.io/idta/SubmodelTemplate/CarbonFootprint/1/0",
+ "pattern": [ "CarbonFootprint" ]
+ },
+ {
+ "templateId": "https://admin-shell.io/idta/SubmodelTemplate/HandoverDocumentation/2/0",
+ "pattern": [ "HandoverDocumentation" ]
}
],
"ShellTemplateMappings": [
diff --git a/source/AAS.TwinEngine.DataEngine/appsettings.json b/source/AAS.TwinEngine.DataEngine/appsettings.json
index bbce44b..3c8b7ac 100644
--- a/source/AAS.TwinEngine.DataEngine/appsettings.json
+++ b/source/AAS.TwinEngine.DataEngine/appsettings.json
@@ -11,12 +11,8 @@
"PluginConfig": {
"Plugins": [
{
- "PluginName": "Plugin1",
- "PluginUrl": "http://localhost:8086"
- },
- {
- "PluginName": "Plugin2",
- "PluginUrl": "http://localhost:8087"
+ "PluginName": "",
+ "PluginUrl": ""
}
]
},
@@ -41,35 +37,22 @@
},
"AasRegistryPreComputed": {
"ShellDescriptorCron": "0 */3 * * * *",
- "IsPreComputed": true
+ "IsPreComputed": false
},
"TemplateMappingRules": {
"SubmodelTemplateMappings": [
{
- "templateId": "https://admin-shell.io/idta/SubmodelTemplate/Reliability/1/0",
- "pattern": [ "Reliability" ]
- },
- {
- "templateId": "https://admin-shell.io/idta/SubmodelTemplate/DigitalNameplate/3/0",
- "pattern": [ "Nameplate" ]
- },
- {
- "templateId": "https://admin-shell.io/idta/SubmodelTemplate/ContactInformation/1/0",
- "pattern": [ "ContactInformation" ]
+ "templateId": "",
+ "pattern": [ "" ]
}
],
"ShellTemplateMappings": [
{
- "templateId": "https://mm-software.com/aas/aasTemplate",
+ "templateId": "",
"pattern": [ "" ]
}
],
"AasIdExtractionRules": [
- {
- "Pattern": "Regex",
- "Index": 3,
- "Separator": ":"
- },
{
"Pattern": "Regex",
"Index": 6,
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/AAS.TwinEngine.Plugin.TestPlugin.UnitTests.csproj b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/AAS.TwinEngine.Plugin.TestPlugin.UnitTests.csproj
new file mode 100644
index 0000000..617925c
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/AAS.TwinEngine.Plugin.TestPlugin.UnitTests.csproj
@@ -0,0 +1,34 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+ true
+ IDE1006, IDE0058
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/Handler/ManifestHandlerTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/Handler/ManifestHandlerTests.cs
new file mode 100644
index 0000000..520ea07
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/Handler/ManifestHandlerTests.cs
@@ -0,0 +1,42 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Manifest.Handler;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Manifest.Responses;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Services.Manifest;
+using AAS.TwinEngine.Plugin.TestPlugin.DomainModel.Manifest;
+
+using Microsoft.Extensions.Logging;
+
+using NSubstitute;
+using NSubstitute.ExceptionExtensions;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.Manifest.Handler;
+
+public class ManifestHandlerTests
+{
+ private readonly ILogger _logger = Substitute.For>();
+ private readonly IManifestService _manifestService = Substitute.For();
+ private readonly ManifestHandler _sut;
+
+ public ManifestHandlerTests() => _sut = new ManifestHandler(_logger, _manifestService);
+
+ [Fact]
+ public async Task GetManifestData_ShouldReturnDto_WhenManifestIsAvailable()
+ {
+ var manifest = new ManifestData { Capabilities = new CapabilitiesData { HasAssetInformation = true, HasShellDescriptor = true }, SupportedSemanticIds = ["test"] };
+ var expectedDto = new ManifestDto { Capabilities = new CapabilitiesDto { HasAssetInformation = true, HasShellDescriptor = true }, SupportedSemanticIds = ["test"] };
+ _manifestService.GetManifestData(Arg.Any())
+ .Returns(Task.FromResult(manifest));
+
+ var result = await _sut.GetManifestData(CancellationToken.None);
+
+ Assert.Equal(expectedDto.ToString(), result.ToString());
+ }
+
+ [Fact]
+ public async Task GetManifestData_ShouldThrowException_WhenServiceThrows()
+ {
+ _manifestService.GetManifestData(Arg.Any())
+ .Throws(new Exception("Service failure"));
+
+ await Assert.ThrowsAsync(() => _sut.GetManifestData(CancellationToken.None));
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/ManifestControllerTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/ManifestControllerTests.cs
new file mode 100644
index 0000000..c21027b
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/ManifestControllerTests.cs
@@ -0,0 +1,30 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Manifest;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Manifest.Handler;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Manifest.Responses;
+
+using Microsoft.AspNetCore.Mvc;
+
+using NSubstitute;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.Manifest;
+
+public class ManifestControllerTests
+{
+ private readonly IManifestHandler _manifestHandler = Substitute.For();
+ private readonly ManifestController _sut;
+
+ public ManifestControllerTests() => _sut = new ManifestController(_manifestHandler);
+
+ [Fact]
+ public async Task RetrieveManifestDataAsync_ShouldReturnOk_WhenDataIsAvailable()
+ {
+ var expectedManifest = new ManifestDto { Capabilities = new CapabilitiesDto(), SupportedSemanticIds = ["abc"] };
+ _manifestHandler.GetManifestData(Arg.Any())
+ .Returns(Task.FromResult(expectedManifest));
+
+ var result = await _sut.RetrieveManifestDataAsync(CancellationToken.None);
+
+ var okResult = Assert.IsType(result.Result);
+ Assert.Equal(expectedManifest, okResult.Value);
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/MappingProfiles/ManifestMappingProfileTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/MappingProfiles/ManifestMappingProfileTests.cs
new file mode 100644
index 0000000..81bcc8d
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Manifest/MappingProfiles/ManifestMappingProfileTests.cs
@@ -0,0 +1,37 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Manifest.MappingProfiles;
+using AAS.TwinEngine.Plugin.TestPlugin.DomainModel.Manifest;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.Manifest.MappingProfiles;
+
+public class ManifestMappingProfileTests
+{
+ [Fact]
+ public void ToDto_ShouldMapManifestDataToManifestDtoCorrectly()
+ {
+ var manifestData = new ManifestData
+ {
+ Capabilities = new CapabilitiesData
+ {
+ HasAssetInformation = true,
+ HasShellDescriptor = false
+ },
+ SupportedSemanticIds = ["semantic1", "semantic2"]
+ };
+
+ var result = manifestData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.NotNull(result.Capabilities);
+ Assert.Equal(manifestData.Capabilities.HasAssetInformation, result.Capabilities.HasAssetInformation);
+ Assert.Equal(manifestData.Capabilities.HasShellDescriptor, result.Capabilities.HasShellDescriptor);
+ Assert.Equal(manifestData.SupportedSemanticIds, result.SupportedSemanticIds);
+ }
+
+ [Fact]
+ public void ToDto_ShouldThrowException_WhenManifestDataIsNull()
+ {
+ ManifestData? manifestData = null;
+
+ Assert.Throws(() => manifestData!.ToDto());
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/Handler/MetaDataHandlerTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/Handler/MetaDataHandlerTests.cs
new file mode 100644
index 0000000..da6ea4f
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/Handler/MetaDataHandlerTests.cs
@@ -0,0 +1,101 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData.Handler;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData.Requests;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Constants;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Exceptions;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Services.MetaData;
+using AAS.TwinEngine.Plugin.TestPlugin.DomainModel.MetaData;
+
+using Microsoft.Extensions.Logging;
+
+using NSubstitute;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.MetaData.Handler;
+
+public class MetaDataHandlerTests
+{
+ private readonly ILogger _logger = Substitute.For>();
+ private readonly IMetaDataService _shellDescriptorService = Substitute.For();
+ private readonly MetaDataHandler _sut;
+
+ public MetaDataHandlerTests() => _sut = new MetaDataHandler(_logger, _shellDescriptorService);
+
+ [Fact]
+ public async Task GetShellDescriptors_ReturnsShellDescriptorsDto_WhenDescriptorsExist()
+ {
+ var request = new GetShellDescriptorsRequest(10, "cursor123");
+ var shellDescriptorsData = new ShellDescriptorsData
+ {
+ PagingMetaData = new PagingMetaData() { Cursor = "nextCursor" },
+ Result = new List()
+ {
+ new() { Id = "desc1" },
+ new() { Id = "desc2" }
+ }
+ };
+ _shellDescriptorService.GetShellDescriptorsAsync(request.Limit, request.Cursor, Arg.Any())
+ .Returns(shellDescriptorsData);
+
+ var result = await _sut.GetShellDescriptors(request, CancellationToken.None);
+
+ Assert.NotNull(result);
+ Assert.Equal(2, result.Result!.Count);
+ Assert.Equal("desc1", result.Result![0].Id);
+ Assert.Equal("desc2", result.Result![1].Id);
+ Assert.Equal("nextCursor", result.PagingMetaData!.Cursor);
+ }
+
+ [Fact]
+ public async Task GetShellDescriptors_ThrowBadRequest_WhenLimitIsZero()
+ {
+ var request = new GetShellDescriptorsRequest(0, "cursor123");
+
+ var record = await Assert.ThrowsAsync(() =>
+ _sut.GetShellDescriptors(request, CancellationToken.None));
+ Assert.Equal(ExceptionMessages.InvalidRequestedLimit, record.Message);
+ }
+
+ [Fact]
+ public async Task GetShellDescriptor_ReturnsShellDescriptor_WhenExists()
+ {
+ var request = new GetShellDescriptorRequest("test");
+ var shellMetaData = new ShellDescriptorData { Id = "test" };
+ _shellDescriptorService.GetShellDescriptorAsync("test", Arg.Any()).Returns(shellMetaData);
+
+ var result = await _sut.GetShellDescriptor(request, CancellationToken.None);
+
+ Assert.Equal(result.Id, shellMetaData.Id);
+ }
+
+ [Fact]
+ public async Task GetShellDescriptor_ThrowsNotFoundException_WhenShellDoesNotExist()
+ {
+ var request = new GetShellDescriptorRequest("test");
+ _shellDescriptorService.GetShellDescriptorAsync("test", Arg.Any())!.Returns((ShellDescriptorData)null!);
+
+ await Assert.ThrowsAsync(() => _sut.GetShellDescriptor(request, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetAsset_ReturnsAsset_WhenExists()
+ {
+ var request = new GetAssetRequest("test-shell");
+ var assetMetaData = new AssetData { GlobalAssetId = "test-shell" };
+ _shellDescriptorService.GetAssetAsync("test-shell", Arg.Any())
+ .Returns(assetMetaData);
+
+ var result = await _sut.GetAsset(request, CancellationToken.None);
+
+ Assert.Equal(assetMetaData.GlobalAssetId, result.GlobalAssetId);
+ }
+
+ [Fact]
+ public async Task GetAsset_ThrowsNotFoundException_WhenAssetDoesNotExist()
+ {
+ var request = new GetAssetRequest("test-shell");
+ _shellDescriptorService.GetAssetAsync("test-shell", Arg.Any())
+ .Returns((AssetData)null!);
+
+ await Assert.ThrowsAsync(() =>
+ _sut.GetAsset(request, CancellationToken.None));
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/AssetMappingProfileTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/AssetMappingProfileTests.cs
new file mode 100644
index 0000000..030b175
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/AssetMappingProfileTests.cs
@@ -0,0 +1,69 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData.MappingProfiles;
+using AAS.TwinEngine.Plugin.TestPlugin.DomainModel.MetaData;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.MetaData.MappingProfiles;
+
+public class AssetMappingProfileTests
+{
+ [Fact]
+ public void ToDto_MapsAllFieldsCorrectly_WhenThumbnailIsPresent()
+ {
+ var assetData = new AssetData
+ {
+ GlobalAssetId = "asset-001",
+ SpecificAssetIds = [new SpecificAssetIdsData { Name = "SerialNumber", Value = "SN001" }],
+ DefaultThumbnail = new DefaultThumbnailData
+ {
+ ContentType = "image/png",
+ Path = "/images/thumb.png"
+ }
+ };
+
+ var result = assetData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.Equal("asset-001", result.GlobalAssetId);
+ Assert.Single(result.SpecificAssetIds!);
+ Assert.Equal("SerialNumber", result.SpecificAssetIds![0].Name);
+ Assert.Equal("SN001", result.SpecificAssetIds[0].Value);
+ Assert.NotNull(result.DefaultThumbnail);
+ Assert.Equal("image/png", result.DefaultThumbnail.ContentType);
+ Assert.Equal("/images/thumb.png", result.DefaultThumbnail.Path);
+ }
+
+ [Fact]
+ public void ToDto_SetsDefaultThumbnailToNull_WhenThumbnailIsMissing()
+ {
+ var assetData = new AssetData
+ {
+ GlobalAssetId = "asset-002",
+ SpecificAssetIds = [],
+ DefaultThumbnail = null
+ };
+
+ var result = assetData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.Equal("asset-002", result.GlobalAssetId);
+ Assert.Empty(result.SpecificAssetIds!);
+ Assert.Null(result.DefaultThumbnail);
+ }
+
+ [Fact]
+ public void ToDto_HandlesNullSpecificAssetIds()
+ {
+ var assetData = new AssetData
+ {
+ GlobalAssetId = "asset-003",
+ SpecificAssetIds = null,
+ DefaultThumbnail = null
+ };
+
+ var result = assetData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.Equal("asset-003", result.GlobalAssetId);
+ Assert.Null(result.DefaultThumbnail);
+ Assert.Null(result.SpecificAssetIds);
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/ShellDescriptorProfileTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/ShellDescriptorProfileTests.cs
new file mode 100644
index 0000000..700a250
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/ShellDescriptorProfileTests.cs
@@ -0,0 +1,73 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData.MappingProfiles;
+using AAS.TwinEngine.Plugin.TestPlugin.DomainModel.MetaData;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.MetaData.MappingProfiles;
+
+public class ShellDescriptorProfileTests
+{
+ [Fact]
+ public void ToDto_MapsAllFieldsCorrectly()
+ {
+ var shellDescriptorData = new ShellDescriptorData
+ {
+ Id = "shell-001",
+ GlobalAssetId = "asset-001",
+ IdShort = "Shell001",
+ SpecificAssetIds =
+ [
+ new SpecificAssetIdsData { Name = "SerialNumber", Value = "SN001" },
+ new SpecificAssetIdsData { Name = "PartNumber", Value = "PN001" }
+ ]
+ };
+
+ var result = shellDescriptorData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.Equal("shell-001", result.Id);
+ Assert.Equal("asset-001", result.GlobalAssetId);
+ Assert.Equal("Shell001", result.IdShort);
+ Assert.Equal(2, result.SpecificAssetIds!.Count);
+ Assert.Equal("SerialNumber", result.SpecificAssetIds[0].Name);
+ Assert.Equal("SN001", result.SpecificAssetIds[0].Value);
+ }
+
+ [Fact]
+ public void ToDto_HandlesNullSpecificAssetIds()
+ {
+ var shellDescriptorData = new ShellDescriptorData
+ {
+ Id = "shell-002",
+ GlobalAssetId = "asset-002",
+ IdShort = "Shell002",
+ SpecificAssetIds = null
+ };
+
+ var result = shellDescriptorData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.Equal("shell-002", result.Id);
+ Assert.Equal("asset-002", result.GlobalAssetId);
+ Assert.Equal("Shell002", result.IdShort);
+ Assert.Null(result.SpecificAssetIds);
+ }
+
+ [Fact]
+ public void ToDto_HandlesEmptySpecificAssetIds()
+ {
+ var shellDescriptorData = new ShellDescriptorData
+ {
+ Id = "shell-003",
+ GlobalAssetId = "asset-003",
+ IdShort = "Shell003",
+ SpecificAssetIds = []
+ };
+
+ var result = shellDescriptorData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.Equal("shell-003", result.Id);
+ Assert.Equal("asset-003", result.GlobalAssetId);
+ Assert.Equal("Shell003", result.IdShort);
+ Assert.Empty(result.SpecificAssetIds!);
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/ShellDescriptorsProfileTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/ShellDescriptorsProfileTests.cs
new file mode 100644
index 0000000..b6db442
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MappingProfiles/ShellDescriptorsProfileTests.cs
@@ -0,0 +1,56 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData.MappingProfiles;
+using AAS.TwinEngine.Plugin.TestPlugin.DomainModel.MetaData;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.MetaData.MappingProfiles;
+
+public class ShellDescriptorsProfileTests
+{
+ [Fact]
+ public void ToDto_MapsAllFieldsCorrectly()
+ {
+ var shellDescriptorsData = new ShellDescriptorsData
+ {
+ PagingMetaData = new PagingMetaData { Cursor = "cursor-123" },
+ Result = new List
+ {
+ new()
+ {
+ Id = "shell-001",
+ GlobalAssetId = "asset-001",
+ IdShort = "Shell001",
+ SpecificAssetIds = [new SpecificAssetIdsData { Name = "SerialNumber", Value = "SN001" }]
+ }
+ }
+ };
+
+ var result = shellDescriptorsData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.NotNull(result.PagingMetaData);
+ Assert.Equal("cursor-123", result.PagingMetaData.Cursor);
+ Assert.Single(result.Result!);
+ Assert.Equal("shell-001", result.Result![0].Id);
+ Assert.Equal("asset-001", result.Result[0].GlobalAssetId);
+ Assert.Equal("Shell001", result.Result[0].IdShort);
+ Assert.Single(result.Result[0]!.SpecificAssetIds!);
+ Assert.Equal("SerialNumber", result.Result[0].SpecificAssetIds?[0]!.Name);
+ Assert.Equal("SN001", result.Result[0].SpecificAssetIds?[0].Value);
+ }
+
+ [Fact]
+ public void ToDto_HandlesNullResultList()
+ {
+ var shellDescriptorsData = new ShellDescriptorsData
+ {
+ PagingMetaData = new PagingMetaData { Cursor = "cursor-456" },
+ Result = null
+ };
+
+ var result = shellDescriptorsData.ToDto();
+
+ Assert.NotNull(result);
+ Assert.NotNull(result.PagingMetaData);
+ Assert.Equal("cursor-456", result.PagingMetaData.Cursor);
+ Assert.Null(result.Result);
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MetaDataControllerTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MetaDataControllerTests.cs
new file mode 100644
index 0000000..08e1ee9
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/MetaData/MetaDataControllerTests.cs
@@ -0,0 +1,148 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData.Handler;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData.Requests;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.MetaData.Responses;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Exceptions;
+
+using Microsoft.AspNetCore.Mvc;
+
+using NSubstitute;
+using NSubstitute.ExceptionExtensions;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.MetaData;
+
+public class MetaDataControllerTests
+{
+ private readonly IMetaDataHandler _handler = Substitute.For();
+ private readonly MetaDataController _sut;
+ private const string AasIdentifier = "dGVzdA==";
+
+ public MetaDataControllerTests() => _sut = new MetaDataController(_handler);
+
+ [Fact]
+ public async Task GetShellDescriptorsAsync_ReturnsOk_WithShellList()
+ {
+ var request = new GetShellDescriptorsRequest(null, null);
+ var expectedShells = new ShellDescriptorsDto();
+ _handler.GetShellDescriptors(request, Arg.Any()).Returns(expectedShells);
+
+ var result = await _sut.GetShellDescriptorsAsync(null, null, CancellationToken.None);
+
+ var okResult = Assert.IsType(result.Result);
+ var actualShells = Assert.IsType(okResult.Value);
+ Assert.Equal(expectedShells, actualShells);
+ }
+
+ [Fact]
+ public async Task GetShellDescriptorsAsync_ThrowsNotFoundException_Returns404()
+ {
+ var request = new GetShellDescriptorsRequest(null, null);
+ _handler.GetShellDescriptors(request, Arg.Any())
+ .Throws(new NotFoundException("Shell not found"));
+
+ await Assert.ThrowsAsync(() => _sut.GetShellDescriptorsAsync(null, null, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetShellDescriptorsAsync_ThrowsBadRequestException_Returns400()
+ {
+ var request = new GetShellDescriptorsRequest(null, null);
+ _handler.GetShellDescriptors(request, Arg.Any())
+ .Throws(new BadRequestException("Invalid request"));
+
+ await Assert.ThrowsAsync(() => _sut.GetShellDescriptorsAsync(null, null, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetShellDescriptorsAsync_ThrowsException_Returns500()
+ {
+ var request = new GetShellDescriptorsRequest(null, null);
+ _handler.GetShellDescriptors(request, Arg.Any())
+ .Throws(new Exception("Unexpected error"));
+
+ await Assert.ThrowsAsync(() => _sut.GetShellDescriptorsAsync(null, null, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetShellDescriptorAsync_ReturnsOk_WithShell()
+ {
+ var expectedShell = new ShellDescriptorDto();
+ _handler.GetShellDescriptor(Arg.Any(), Arg.Any())
+ .Returns(expectedShell);
+
+ var result = await _sut.GetShellDescriptorAsync(AasIdentifier, CancellationToken.None);
+
+ var okResult = Assert.IsType(result.Result);
+ var actualShell = Assert.IsType(okResult.Value);
+ Assert.Equal(expectedShell, actualShell);
+ }
+
+ [Fact]
+ public async Task GetShellDescriptorAsync_ThrowsNotFoundException_Returns404()
+ {
+ _handler.GetShellDescriptor(Arg.Any(), Arg.Any())
+ .Throws(new NotFoundException("Shell not found"));
+
+ await Assert.ThrowsAsync(() => _sut.GetShellDescriptorAsync(AasIdentifier, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetShellDescriptorAsync_ThrowsBadRequestException_Returns400()
+ {
+ _handler.GetShellDescriptor(Arg.Any(), Arg.Any())
+ .Throws(new BadRequestException("Invalid AAS identifier"));
+
+ await Assert.ThrowsAsync(() => _sut.GetShellDescriptorAsync(AasIdentifier, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetShellDescriptorAsync_ThrowsException_Returns500()
+ {
+ _handler.GetShellDescriptor(Arg.Any(), Arg.Any())
+ .Throws(new Exception("Unexpected error"));
+
+ await Assert.ThrowsAsync(() => _sut.GetShellDescriptorAsync(AasIdentifier, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetAssetAsync_ReturnsOk_WithAssetInformation()
+ {
+ var expectedAssetInfo = new AssetDto();
+ _handler.GetAsset(Arg.Any(), Arg.Any())
+ .Returns(expectedAssetInfo);
+
+ var result = await _sut.GetAssetAsync(AasIdentifier, CancellationToken.None);
+
+ var okResult = Assert.IsType(result.Result);
+ var actualAssetInfo = Assert.IsType(okResult.Value);
+ Assert.Equal(expectedAssetInfo, actualAssetInfo);
+ }
+
+ [Fact]
+ public async Task GetAssetAsync_ThrowsNotFoundException_Returns404()
+ {
+ _handler.GetAsset(Arg.Any(), Arg.Any())
+ .Throws(new NotFoundException("Asset not found"));
+
+ await Assert.ThrowsAsync(() => _sut.GetAssetAsync(AasIdentifier, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetAssetAsync_ThrowsBadRequestException_Returns400()
+ {
+ _handler.GetAsset(Arg.Any(), Arg.Any())
+ .Throws(new BadRequestException("Invalid request"));
+
+ await Assert.ThrowsAsync(() => _sut.GetAssetAsync(AasIdentifier, CancellationToken.None));
+ }
+
+ [Fact]
+ public async Task GetAssetAsync_ThrowsException_Returns500()
+ {
+ _handler.GetAsset(Arg.Any(), Arg.Any())
+ .Throws(new Exception("Unexpected error"));
+
+ await Assert.ThrowsAsync(() =>
+ _sut.GetAssetAsync(AasIdentifier, CancellationToken.None));
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Handler/SubmodelHandlerTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Handler/SubmodelHandlerTests.cs
new file mode 100644
index 0000000..cabd0f7
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Handler/SubmodelHandlerTests.cs
@@ -0,0 +1,143 @@
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using System.Text.Json.Serialization;
+
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Submodel.Handler;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Submodel.Requests;
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Submodel.Services;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Services.Submodel;
+using AAS.TwinEngine.Plugin.TestPlugin.DomainModel.Submodel;
+
+using Json.Schema;
+
+using Microsoft.Extensions.Logging;
+
+using NSubstitute;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.Submodel.Handler;
+
+public class SubmodelHandlerTests
+{
+ private const string JsonSchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""https://admin-shell.io/zvei/nameplate/1/0/ContactInformations"": {
+ ""type"": ""object"",
+ ""properties"": {
+ ""https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation"": {
+ ""anyOf"": [
+ { ""$ref"": ""#/definitions/ContactInformation"" },
+ {
+ ""type"": ""array"",
+ ""items"": { ""$ref"": ""#/definitions/ContactInformation"" }
+ }
+ ]
+ }
+ },
+ ""required"": [
+ ""https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation""
+ ]
+ }
+ },
+ ""definitions"": {
+ ""ContactInformation"": {
+ ""type"": ""object"",
+ ""properties"": {
+ ""0173-1#02-AAO204#003"": { ""type"": ""string"" },
+ ""https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language"": { ""type"": ""string"" }
+ },
+ ""required"": [
+ ""0173-1#02-AAO204#003"",
+ ""https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language""
+ ]
+ }
+ }}";
+
+ private const string JsonResponse = @"{
+ ""https://admin-shell.io/zvei/nameplate/1/0/ContactInformations"": {
+ ""https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation"": {
+ ""0173-1#02-AAO204#003"": ""John Doe"",
+ ""https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language"": ""en""
+ }
+ }
+ }";
+
+ private readonly JsonSerializerOptions _options = new()
+ {
+ PropertyNameCaseInsensitive = true,
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
+ ReadCommentHandling = JsonCommentHandling.Skip,
+ AllowTrailingCommas = true,
+ Converters =
+ {
+ new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
+ }
+ };
+
+ private readonly JsonSchema JsonSchemaRequest;
+ private readonly JsonObject _expectedResponse;
+ private readonly ILogger _logger = Substitute.For>();
+ private readonly ISubmodelService _pluginService = Substitute.For();
+ private readonly IJsonSchemaParser _jsonSchemaParser = Substitute.For();
+ private readonly SubmodelHandler _sut;
+ private readonly GetSubmodelDataRequest _request;
+ private readonly SemanticBranchNode _semanticTree;
+ private readonly SemanticBranchNode _sematicTreeWithData;
+ private readonly ISemanticTreeHandler _semanticTreeHandler = Substitute.For();
+
+ public SubmodelHandlerTests()
+ {
+ _semanticTree = new SemanticBranchNode("https://admin-shell.io/zvei/nameplate/1/0/ContactInformations", DataType.Object);
+ var contactNode = new SemanticBranchNode("https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation", DataType.Object);
+ contactNode.AddChild(new SemanticLeafNode("0173-1#02-AAO204#003", DataType.String, ""));
+ contactNode.AddChild(new SemanticLeafNode(
+ "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language", DataType.String, ""));
+ _semanticTree.AddChild(contactNode);
+
+ _sematicTreeWithData = new SemanticBranchNode("https://admin-shell.io/zvei/nameplate/1/0/ContactInformations", DataType.Object);
+ var contactNodeWithData = new SemanticBranchNode("https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation", DataType.Object);
+ contactNodeWithData.AddChild(new SemanticLeafNode("0173-1#02-AAO204#003", DataType.String, "John Doe"));
+ contactNodeWithData.AddChild(new SemanticLeafNode(
+ "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language", DataType.String, "en"));
+ _sematicTreeWithData.AddChild(contactNodeWithData);
+
+ _expectedResponse = JsonNode.Parse(JsonResponse)!.AsObject();
+ JsonSchemaRequest = JsonSerializer.Deserialize(JsonSchemaString, _options);
+ _sut = new SubmodelHandler(_logger, _pluginService, _jsonSchemaParser, _semanticTreeHandler);
+ _request = new GetSubmodelDataRequest("ContactInformation", JsonSchemaRequest);
+ }
+
+ [Fact]
+ public async Task Handle_ReturnsJsonObject_WhenParserAndServiceSucceed()
+ {
+ _jsonSchemaParser.ParseJsonSchema(JsonSchemaRequest).Returns(_semanticTree);
+ _pluginService.GetValuesBySemanticIds(_semanticTree, "ContactInformation").Returns(_sematicTreeWithData);
+ _semanticTreeHandler.GetJson(_sematicTreeWithData, JsonSchemaRequest).Returns(_expectedResponse);
+
+ var actual = await _sut.GetSubmodelData(_request, CancellationToken.None);
+
+ Assert.Same(_expectedResponse, actual);
+ _jsonSchemaParser.Received(1).ParseJsonSchema(JsonSchemaRequest);
+ _pluginService.Received(1).GetValuesBySemanticIds(_semanticTree, "ContactInformation");
+ _semanticTreeHandler.Received(1).GetJson(_sematicTreeWithData, JsonSchemaRequest);
+ }
+
+ [Fact]
+ public async Task Handle_CallsServiceEvenWhenParserReturnsEmptyList()
+ {
+ var emptyBranch = new SemanticBranchNode("emptyRoot", DataType.Object);
+ _jsonSchemaParser.ParseJsonSchema(JsonSchemaRequest).Returns(emptyBranch);
+ var emptyResponse = new JsonObject();
+ _pluginService.GetValuesBySemanticIds(emptyBranch, "ContactInformation").Returns(emptyBranch);
+ _semanticTreeHandler.GetJson(emptyBranch, JsonSchemaRequest).Returns(emptyResponse);
+
+ var actual = await _sut.GetSubmodelData(_request, CancellationToken.None);
+
+ Assert.Same(emptyResponse, actual);
+ _jsonSchemaParser.Received(1).ParseJsonSchema(JsonSchemaRequest);
+ _pluginService.Received(1).GetValuesBySemanticIds(emptyBranch, "ContactInformation");
+ _semanticTreeHandler.Received(1).GetJson(emptyBranch, JsonSchemaRequest);
+ }
+}
+
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Services/JsonSchemaParserTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Services/JsonSchemaParserTests.cs
new file mode 100644
index 0000000..a0513cd
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Services/JsonSchemaParserTests.cs
@@ -0,0 +1,389 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Submodel.Services;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Exceptions;
+using AAS.TwinEngine.Plugin.TestPlugin.DomainModel.Submodel;
+
+using Json.Schema;
+
+using Microsoft.Extensions.Logging;
+
+using NSubstitute;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.Submodel.Services;
+
+public class JsonSchemaParserTests
+{
+ private readonly JsonSerializerOptions _options = new()
+ {
+ PropertyNameCaseInsensitive = true,
+ DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
+ ReadCommentHandling = JsonCommentHandling.Skip,
+ AllowTrailingCommas = true,
+ Converters =
+ {
+ new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
+ }
+ };
+
+ private readonly string _invalidJson = @"{""Invalid json"": {}}";
+
+ private const string ValidationFailSchemaString = @"{ ""type"" : ""null"" }";
+
+ private const string NoPropertiesSchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object""
+ }";
+
+ private const string SimpleSchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""foo"": { ""type"": ""string"" }
+ }}";
+
+ private const string NestedSchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""parent"": {
+ ""type"": ""object"",
+ ""properties"": {
+ ""child"": { ""type"": ""number"" }
+ }}}}";
+
+ private const string ArraySchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""list"": {
+ ""type"": ""array"",
+ ""properties"": { ""id"": { ""type"": ""integer"" } }
+ }}}";
+
+ private const string ArrayWithRefSchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""items"": {
+ ""type"": ""array"",
+ ""$ref"": ""#/definitions/ItemDef""
+ }
+ },
+ ""definitions"": {
+ ""ItemDef"": {
+ ""type"": ""object"",
+ ""properties"": { ""val"": { ""type"": ""integer"" } }
+ }
+ }
+ }";
+
+ private const string AllDataTypesSchemaWithRefString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""root"" :{
+ ""type"" : ""array"",
+ ""properties"" : {
+ ""stringField"": { ""type"": ""string"" },
+ ""numberField"": { ""type"": ""number"" },
+ ""integerField"": { ""type"": ""integer"" },
+ ""booleanField"": { ""type"": ""boolean"" },
+ ""arrayField"": {
+ ""$ref"" : ""#/definitions/itemField""
+ },
+ ""objectField"": {
+ ""type"": ""object"",
+ ""properties"": {
+ ""nestedProp"": { ""type"": ""string"" }
+ }
+ },
+ ""nullField"": { ""type"": ""null"" }
+ }
+ }
+ },
+ ""definitions"" : {
+ ""itemField"":{
+ ""type"":""array"",
+ ""properties"": {
+ ""items"": { ""type"": ""string"" }
+ }
+ }
+ }
+ }";
+
+ private readonly ILogger _logger;
+ private readonly JsonSchemaParser _sut;
+
+ public JsonSchemaParserTests()
+ {
+ _logger = Substitute.For>();
+ _sut = new JsonSchemaParser(_logger);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_InvalidJson_ThrowsBadRequestException()
+ {
+ var InvalidJsonSchema = JsonSerializer.Deserialize(_invalidJson, _options);
+
+ Assert.Throws(() => _sut.ParseJsonSchema(InvalidJsonSchema));
+ }
+
+ [Fact]
+ public void ParseJsonSchema_SchemaValidationFails_ThrowsBadRequestException()
+ {
+ var ValidationFailSchema = JsonSerializer.Deserialize(ValidationFailSchemaString, _options);
+
+ Assert.Throws(() => _sut.ParseJsonSchema(ValidationFailSchema));
+ }
+
+ [Fact]
+ public void ParseJsonSchema_NoRootProperties_ThrowsBadRequestException()
+ {
+ var NoPropertiesSchema = JsonSerializer.Deserialize(NoPropertiesSchemaString, _options);
+
+ Assert.Throws(() => _sut.ParseJsonSchema(NoPropertiesSchema));
+ }
+
+ [Fact]
+ public void ParseJsonSchema_SimpleSchema_ReturnsLeafNode()
+ {
+ var SimpleSchema = JsonSerializer.Deserialize(SimpleSchemaString, _options);
+
+ var node = _sut.ParseJsonSchema(SimpleSchema);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var leaf = (SemanticLeafNode)node;
+ Assert.Equal("foo", leaf.SemanticId);
+ Assert.Equal(string.Empty, leaf.Value);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_NestedObject_ReturnsBranchNodeWithChild()
+ {
+ var NestedSchema = JsonSerializer.Deserialize(NestedSchemaString, _options);
+
+ var node = _sut.ParseJsonSchema(NestedSchema);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var branch = (SemanticBranchNode)node;
+ Assert.Equal("parent", branch.SemanticId);
+ Assert.Single(branch.Children);
+ var child = branch.Children[0] as SemanticLeafNode;
+ Assert.NotNull(child);
+ Assert.Equal("child", child.SemanticId);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_ArrayOfObjects_ReturnsBranchNodeWithLeafChild()
+ {
+ var arraySchema = JsonSerializer.Deserialize(ArraySchemaString, _options);
+
+ var node = _sut.ParseJsonSchema(arraySchema!);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var branch = (SemanticBranchNode)node;
+ Assert.Equal("list", branch.SemanticId);
+ Assert.Single(branch.Children);
+ var child = branch.Children[0] as SemanticLeafNode;
+ Assert.NotNull(child);
+ Assert.Equal("id", child.SemanticId);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_ArrayWithRef_ReturnsBranchNodeWithLeafChild()
+ {
+ var arrayWithRefSchema = JsonSerializer.Deserialize(ArrayWithRefSchemaString, _options);
+
+ var node = _sut.ParseJsonSchema(arrayWithRefSchema!);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var branch = (SemanticBranchNode)node;
+ Assert.Equal("items", branch.SemanticId);
+ Assert.Single(branch.Children);
+ var child = branch.Children[0] as SemanticLeafNode;
+ Assert.NotNull(child);
+ Assert.Equal("val", child.SemanticId);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_AllDataTypeSchemaWithRef_ReturnsBranchNodeWithLeafChild()
+ {
+ var allDataTypesSchemaWithRef = JsonSerializer.Deserialize(AllDataTypesSchemaWithRefString, _options);
+
+ var node = _sut.ParseJsonSchema(allDataTypesSchemaWithRef!);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var branch = (SemanticBranchNode)node;
+ Assert.Equal("root", branch.SemanticId);
+ Assert.Equal(DataType.Array, branch.DataType);
+ var child1 = branch.Children[0] as SemanticLeafNode;
+ Assert.Equal("stringField", child1!.SemanticId);
+ Assert.Equal(DataType.String, child1.DataType);
+ var child2 = branch.Children[1] as SemanticLeafNode;
+ Assert.Equal("numberField", child2!.SemanticId);
+ Assert.Equal(DataType.Number, child2.DataType);
+ var child3 = branch.Children[2] as SemanticLeafNode;
+ Assert.Equal("integerField", child3!.SemanticId);
+ Assert.Equal(DataType.Integer, child3.DataType);
+ var child4 = branch.Children[3] as SemanticLeafNode;
+ Assert.Equal("booleanField", child4!.SemanticId);
+ Assert.Equal(DataType.Boolean, child4.DataType);
+ var branch1 = branch.Children[4] as SemanticBranchNode;
+ Assert.Equal("arrayField", branch1?.SemanticId);
+ Assert.Equal(DataType.Array, branch1?.DataType);
+ var leaf1 = branch1!.Children[0] as SemanticLeafNode;
+ Assert.Equal("items", leaf1!.SemanticId);
+ Assert.Equal(DataType.String, leaf1.DataType);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_ReferenceNotFound_ReturnsLeafNode()
+ {
+ const string SchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""mystery"": { ""$ref"": ""#/definitions/DoesNotExist"" }
+ }
+ }";
+ var schema = JsonSerializer.Deserialize(SchemaString, _options);
+
+ var node = _sut.ParseJsonSchema(schema!);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var leaf = (SemanticLeafNode)node;
+ Assert.Equal("mystery", leaf.SemanticId);
+ Assert.Equal(DataType.Unknown, leaf.DataType);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_ReferenceToObjectDefinition_ReturnsBranchNode()
+ {
+ const string SchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""person"": { ""$ref"": ""#/definitions/Person"" }
+ },
+ ""definitions"": {
+ ""Person"": {
+ ""type"": ""object"",
+ ""properties"": {
+ ""name"": { ""type"": ""string"" },
+ ""age"": { ""type"": ""integer"" }
+ }
+ }
+ }
+ }";
+ var schema = JsonSerializer.Deserialize(SchemaString, _options);
+
+ var node = _sut.ParseJsonSchema(schema);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var branch = (SemanticBranchNode)node;
+ Assert.Equal("person", branch.SemanticId);
+ Assert.Equal(DataType.Object, branch.DataType);
+ Assert.Collection(branch.Children,
+ child =>
+ {
+ var leaf = Assert.IsType(child);
+ Assert.Equal("name", leaf.SemanticId);
+ Assert.Equal(DataType.String, leaf.DataType);
+ },
+ child =>
+ {
+ var leaf = Assert.IsType(child);
+ Assert.Equal("age", leaf.SemanticId);
+ Assert.Equal(DataType.Integer, leaf.DataType);
+ });
+ }
+
+ [Fact]
+ public void ParseJsonSchema_ReferenceToArrayDefinition_ReturnsBranchNode()
+ {
+ const string SchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""primes"": { ""$ref"": ""#/definitions/PrimeList"" }
+ },
+ ""definitions"": {
+ ""PrimeList"": {
+ ""type"": ""array""
+ }
+ }
+ }";
+ var schema = JsonSerializer.Deserialize(SchemaString, _options);
+
+ var node = _sut.ParseJsonSchema(schema);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var branch = (SemanticBranchNode)node;
+ Assert.Equal("primes", branch.SemanticId);
+ Assert.Equal(DataType.Array, branch.DataType);
+ Assert.Empty(branch.Children);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_ReferenceToLeafNodeDefinition_ReturnsLeafNode()
+ {
+ const string SchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""person"": { ""$ref"": ""#/definitions/Person"" }
+ },
+ ""definitions"": {
+ ""Person"": {
+ ""type"": ""string""
+ }
+ }
+ }";
+ var schema = JsonSerializer.Deserialize(SchemaString, _options);
+
+ var node = _sut.ParseJsonSchema(schema);
+
+ Assert.NotNull(node);
+ Assert.IsType(node);
+ var branch = (SemanticLeafNode)node;
+ Assert.Equal("person", branch.SemanticId);
+ Assert.Equal(DataType.String, branch.DataType);
+ }
+
+ [Fact]
+ public void ParseJsonSchema_InlineObjectWithNoProperties_CoversProcessObjectFallback()
+ {
+ const string SchemaString = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""object"",
+ ""properties"": {
+ ""outer"": {
+ ""type"": ""object"",
+ ""properties"": {
+ ""inner"": { ""type"": ""object"" }
+ }
+ }
+ }
+ }";
+ var schema = JsonSerializer.Deserialize(SchemaString, _options);
+
+ var root = _sut.ParseJsonSchema(schema);
+
+ var outerBranch = Assert.IsType(root);
+ Assert.Equal("outer", outerBranch.SemanticId);
+ Assert.Single(outerBranch.Children);
+ var innerBranch = Assert.IsType(outerBranch.Children[0]);
+ Assert.Equal("inner", innerBranch.SemanticId);
+ Assert.Empty(innerBranch.Children);
+ }
+}
diff --git a/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Services/JsonSchemaValidatorTests.cs b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Services/JsonSchemaValidatorTests.cs
new file mode 100644
index 0000000..808a410
--- /dev/null
+++ b/source/AAS.TwinEngine.Plugin.TestPlugin.UnitTests/Api/Submodel/Services/JsonSchemaValidatorTests.cs
@@ -0,0 +1,180 @@
+using AAS.TwinEngine.Plugin.TestPlugin.Api.Submodel.Services;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Exceptions;
+using AAS.TwinEngine.Plugin.TestPlugin.ApplicationLogic.Services.Submodel.Config;
+
+using Json.Schema;
+
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+using NSubstitute;
+
+namespace AAS.TwinEngine.Plugin.TestPlugin.UnitTests.Api.Submodel.Services;
+
+public class JsonSchemaValidatorTests
+{
+ private readonly JsonSchemaValidator _sut;
+
+ public static IEnumerable