diff --git a/.github/workflows/gitleaks.yml b/.github/workflows/gitleaks.yml
index f86851c9..08cd4860 100644
--- a/.github/workflows/gitleaks.yml
+++ b/.github/workflows/gitleaks.yml
@@ -1,8 +1,28 @@
+# Copyright (c) 2021-2022 Copyright (c) 2021-2022 Robert Bosch Manufacturing Solutions GmbH
+# Copyright (c) 2021-2022 Contributors to the Eclipse Foundation
+
+# See the NOTICE file(s) distributed with this work for additional
+# information regarding copyright ownership.
+
+# This program and the accompanying materials are made available under the
+# terms of the Apache License, Version 2.0 which is available at
+# https://www.apache.org/licenses/LICENSE-2.0.
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# SPDX-License-Identifier: Apache-2.0
name: gitleaks
on: [push, pull_request, workflow_dispatch]
jobs:
- gitleaks:
+ gitleaks-run:
runs-on: ubuntu-latest
+ container:
+ image: zricethezav/gitleaks:latest
+ options: --user root
steps:
- name: Checkout
uses: actions/checkout@v2
@@ -11,30 +31,29 @@ jobs:
- name: Run Gitleaks
id: gitleaks
- uses: DariuszPorowski/github-action-gitleaks@v2
- with:
- report_format: "sarif"
- fail: true
- # config: "/.gitleaks/GitleaksUdmCombo.toml"
-
- - name: Get the output from the gitleaks step
run: |
- echo "exitcode: ${{ steps.gitleaks.outputs.exitcode }}"
- echo "result: ${{ steps.gitleaks.outputs.result }}"
- echo "output: ${{ steps.gitleaks.outputs.output }}"
- echo "command: ${{ steps.gitleaks.outputs.command }}"
- echo "report: ${{ steps.gitleaks.outputs.report }}"
- if: always()
+ git config --global --add safe.directory $PWD
+ gitleaks detect -f sarif -r ./gitleaks-report-semantic-hub.sarif --exit-code 0
- - name: Upload Gitleaks output as artifact
- uses: actions/upload-artifact@v1
+ - name: Upload artifact
+ uses: actions/upload-artifact@v3
with:
- name: gitleaks.sarif
- path: ${{ steps.gitleaks.outputs.report }}
- if: always()
+ name: gitleaks-report
+ path: ./gitleaks-report-semantic-hub.sarif
+
+ gitleaks-upload:
+ runs-on: ubuntu-latest
+ needs: gitleaks-run
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Download artifact
+ uses: actions/download-artifact@v3
+ with:
+ name: gitleaks-report
- name: Upload SARIF report
if: always()
- uses: github/codeql-action/upload-sarif@v1
+ uses: github/codeql-action/upload-sarif@v2
with:
- sarif_file: ${{ steps.gitleaks.outputs.report }}
+ sarif_file: ./gitleaks-report-semantic-hub.sarif
diff --git a/.github/workflows/helm-release.yml b/.github/workflows/helm-release.yml
new file mode 100644
index 00000000..3e64fdf2
--- /dev/null
+++ b/.github/workflows/helm-release.yml
@@ -0,0 +1,55 @@
+# Copyright (c) 2021-2022 Copyright (c) 2021-2022 Robert Bosch Manufacturing Solutions GmbH
+# Copyright (c) 2021-2022 Contributors to the Eclipse Foundation
+
+# See the NOTICE file(s) distributed with this work for additional
+# information regarding copyright ownership.
+
+# This program and the accompanying materials are made available under the
+# terms of the Apache License, Version 2.0 which is available at
+# https://www.apache.org/licenses/LICENSE-2.0.
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# SPDX-License-Identifier: Apache-2.0
+---
+
+name: Release - Helm Charts
+
+on:
+ push:
+ paths:
+ - 'charts/**'
+ branches:
+ - main
+ workflow_dispatch:
+
+jobs:
+ release:
+ permissions:
+ contents: write
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Configure Git
+ run: |
+ git config user.name "$GITHUB_ACTOR"
+ git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
+
+ - name: Install Helm
+ uses: azure/setup-helm@v3
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Run chart-releaser
+ uses: helm/chart-releaser-action@v1.4.1
+ env:
+ CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
\ No newline at end of file
diff --git a/.github/workflows/kics.yml b/.github/workflows/kics.yml
new file mode 100644
index 00000000..e9ae7138
--- /dev/null
+++ b/.github/workflows/kics.yml
@@ -0,0 +1,72 @@
+# Copyright (c) 2021-2022 Copyright (c) 2021-2022 Robert Bosch Manufacturing Solutions GmbH
+# Copyright (c) 2021-2022 Contributors to the Eclipse Foundation
+
+# See the NOTICE file(s) distributed with this work for additional
+# information regarding copyright ownership.
+
+# This program and the accompanying materials are made available under the
+# terms of the Apache License, Version 2.0 which is available at
+# https://www.apache.org/licenses/LICENSE-2.0.
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# SPDX-License-Identifier: Apache-2.0
+---
+
+name: "KICS"
+
+on:
+ push:
+ branches: [main, master]
+ # pull_request:
+ # The branches below must be a subset of the branches above
+ # branches: [main, master]
+ # paths-ignore:
+ # - "**/*.md"
+ # - "**/*.txt"
+ schedule:
+ - cron: "0 0 * * *"
+ workflow_dispatch:
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: KICS scan
+ uses: checkmarx/kics-github-action@master
+ with:
+ # Scanning directory .
+ path: "."
+ # Exclude paths from scan by providing the paths as comma separated list
+ # exclude_paths: "postgres-init.yaml,templates/sharedidp.yaml"
+ # Exclude queries by providing the query / rule ID as comma separated list
+ # exclude_queries: "b9c83569-459b-4110-8f79-6305aa33cb37"
+ # Fail on HIGH severity results
+ fail_on: high
+ # Disable secrets detection - we use GitGuardian
+ disable_secrets: true
+ # When provided with a directory on output_path
+ # it will generate the specified reports file named 'results.{extension}'
+ # in this example it will generate:
+ # - results-dir/results.json and results-dir/results.sarif
+ output_path: kicsResults/
+ output_formats: "json,sarif"
+
+ # Upload findings to GitHub Advanced Security Dashboard
+ - name: Upload SARIF file for GitHub Advanced Security Dashboard
+ if: always()
+ uses: github/codeql-action/upload-sarif@v2
+ with:
+ sarif_file: kicsResults/results.sarif
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f0a51f84..d0244066 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,3 +1,20 @@
+# Copyright (c) 2021-2022 Copyright (c) 2021-2022 Robert Bosch Manufacturing Solutions GmbH
+# Copyright (c) 2021-2022 Contributors to the Eclipse Foundation
+
+# See the NOTICE file(s) distributed with this work for additional
+# information regarding copyright ownership.
+
+# This program and the accompanying materials are made available under the
+# terms of the Apache License, Version 2.0 which is available at
+# https://www.apache.org/licenses/LICENSE-2.0.
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# SPDX-License-Identifier: Apache-2.0
---
name: "Create new version tag"
diff --git a/.github/workflows/trivy-scan.yml b/.github/workflows/trivy-scan.yml
deleted file mode 100644
index 63c75688..00000000
--- a/.github/workflows/trivy-scan.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-name: Trivy Scan
-
-on:
- schedule:
- - cron: 0 2 * * 0
- workflow_dispatch:
-
-jobs:
- analyze-semantic-hub:
- runs-on: ubuntu-latest
- permissions:
- actions: read
- contents: read
- security-events: write
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v2
- - uses: actions/setup-java@v3
- with:
- distribution: 'temurin'
- java-version: '11'
- - name: Build JAR
- run: mvn clean package
- - name: Build Image
- run: docker build -t semantic-hub ./backend
- - name: Run Trivy vulnerability scanner
- uses: aquasecurity/trivy-action@master
- with:
- image-ref: semantic-hub
- # ignore-unfixed: true
- exit-code: "1"
- hide-progress: false
- format: "sarif"
- output: "trivy-results-semantic-hub.sarif"
- severity: "CRITICAL,HIGH"
-
- - name: Upload Trivy scan results to GitHub Security tab
- uses: github/codeql-action/upload-sarif@v1
- if: always()
- with:
- sarif_file: "trivy-results-semantic-hub.sarif"
diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml
new file mode 100644
index 00000000..174b1d98
--- /dev/null
+++ b/.github/workflows/trivy.yml
@@ -0,0 +1,90 @@
+# Copyright (c) 2021-2022 Copyright (c) 2021-2022 Robert Bosch Manufacturing Solutions GmbH
+# Copyright (c) 2021-2022 Contributors to the Eclipse Foundation
+
+# See the NOTICE file(s) distributed with this work for additional
+# information regarding copyright ownership.
+
+# This program and the accompanying materials are made available under the
+# terms of the Apache License, Version 2.0 which is available at
+# https://www.apache.org/licenses/LICENSE-2.0.
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# SPDX-License-Identifier: Apache-2.0
+name: Trivy
+
+on:
+ schedule:
+ - cron: 0 0 * * *
+ workflow_dispatch:
+
+jobs:
+ analyze-config:
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Run Trivy vulnerability scanner in repo mode
+ uses: aquasecurity/trivy-action@master
+ with:
+ scan-type: "config"
+ # ignore-unfixed: true
+ exit-code: "1"
+ hide-progress: false
+ format: "sarif"
+ output: "trivy-results1.sarif"
+ severity: "CRITICAL,HIGH"
+
+ - name: Upload Trivy scan results to GitHub Security tab
+ uses: github/codeql-action/upload-sarif@v2
+ if: always()
+ with:
+ sarif_file: "trivy-results1.sarif"
+
+ analyze-semantic-hub:
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - uses: actions/setup-java@v3
+ with:
+ distribution: 'temurin'
+ java-version: '11'
+ - name: Build JAR
+ run: mvn clean package
+
+ - name: Build Image
+ run: docker build -t semantic-hub ./backend
+
+ - name: Run Trivy vulnerability scanner
+ uses: aquasecurity/trivy-action@master
+ with:
+ image-ref: semantic-hub
+ # ignore-unfixed: true
+ exit-code: "1"
+ hide-progress: false
+ format: "sarif"
+ output: "trivy-results-semantic-hub.sarif"
+ severity: "CRITICAL,HIGH"
+
+ - name: Upload Trivy scan results to GitHub Security tab
+ uses: github/codeql-action/upload-sarif@v2
+ if: always()
+ with:
+ sarif_file: "trivy-results-semantic-hub.sarif"
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..6e8c0e31
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,45 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## 0.1.0-M2
+### Added
+- Swagger UI now integrated with Portal Authentication
+- Filter endpoint for search of list of URNs
+- Helm Charts available via helm Repository at Eclipse Foundation
+
+### Fixed
+- Update jackson-databind to version 2.13.3
+- Update snakeyaml to version to 1.31
+
+### Changed
+- Update of Spring Boot version to 2.7.3
+
+## 0.1.0-M1
+### Fixed
+- Adjust tests to avoid duplicates
+### Changed
+- Deactivate name search
+
+## 0.0.1-M2
+### Added
+- The Semantic Hub now allows the generation and export of AAS files
+### Changed
+- Switched to BAMM SDK version 2.0.0
+
+## 0.0.1-M1
+### Added
+- The Semantic Hub allows the creation, update, deletion of Semantic models in the RDF based format BAMM Aspect Meta Model (short BAMM)
+- Users can use the Semantic Hub API to view models and their meta information (such as version and current status, e.g. whether it is ready to be used)
+- The Semantic Hub provides endpoints to generate artifacts from the BAMM models:
+ - example payload JSON
+ - detailed HTML documentation describing the model
+ - a diagram of the model
+ - an OpenAPI description
+ - an Asset Administration Shell representation of the model as a submodel template
+ - a JSON schema representation of the model
+- The Semantic Hub allows the reuse of model components between different BAMM aspects and can resolve these dependencies
+- The Semantic Hub prevents unauthenticated access by checking whether an access token is provided by a CX user
+- The Semantic Hub enforces that only users with the correct role can read/create/update/delete semantic models
diff --git a/README.md b/README.md
index 6576c7a9..e3076380 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ The source code under this folder contains reference implementations of the SLDT
Run `mvn install` to run unit tests, build and install the package.
## Run Package Locally
-To check whether the build was successful, you can start the resulting JAR file from the build process by running `java -jar target/semantic-hub-{current-version}.jar`.
+To check whether the build was successful, you can start the resulting JAR file from the build process by running `java -jar target/semantic-hub-backend-{current-version}.jar`.
## Build Docker
Run `docker build -t semantic-hub .`
@@ -35,7 +35,7 @@ Run `docker build -t semantic-hub .`
In case you want to publish your image into a remote container registry, apply the tag accordingly and `docker push` the image.
## Deploy using Helm and K8s
-If you have a running Kubernetes cluster available, you can deploy the Semantic Hub using our Helm Chart, which is located under `./deployment/semantic-hub`.
+If you have a running Kubernetes cluster available, you can deploy the Semantic Hub using our Helm Chart, which is located under `./charts/semantic-hub`.
In case you don't have a running cluster, you can set up one by yourself locally, using [minikube](https://minikube.sigs.k8s.io/docs/start/).
In the following, we will use a minikube cluster for reference.
@@ -47,9 +47,11 @@ Before deploying the Semantic Hub, enable a few add-ons in your minikube cluster
`minikube addons enable ingress`
+If you want to use the in-memory triple store that is not persistent (useful for local deployments) set `embeddedTripleStore: true`.
+
In order to deploy the helm chart, first create a new namespace "semantics": `kubectl create namespace semantics`.
-Then run `helm install hub -n semantics ./deployment/semantic-hub`. This will set up a new helm deployment in the semantics namespace. By default, the deployment contains the Semantic Hub instance itself, and a Fuseki Triplestore.
+Then run `helm install hub -n semantics ./charts/semantic-hub`. This will set up a new helm deployment in the semantics namespace. By default, the deployment contains the Semantic Hub instance itself, and a Fuseki Triplestore.
Check that the two containers are running by calling `kubectl get pod -n semantics`.
diff --git a/backend/deployment/semantic-hub/Chart.lock b/backend/deployment/semantic-hub/Chart.lock
deleted file mode 100644
index ef93b5ce..00000000
--- a/backend/deployment/semantic-hub/Chart.lock
+++ /dev/null
@@ -1,6 +0,0 @@
-dependencies:
-- name: cert-manager
- repository: https://charts.jetstack.io
- version: v1.7.1
-digest: sha256:7996cd611e44d44b023a677c2ff4beb4104aedede18f5d4e182c11323b957a23
-generated: "2022-03-22T14:25:36.810497+01:00"
diff --git a/backend/pom.xml b/backend/pom.xml
index 17f3416f..b603cf17 100644
--- a/backend/pom.xml
+++ b/backend/pom.xml
@@ -25,7 +25,7 @@
org.eclipse.tractusx
semantic-hub
- 0.1.0-M2
+ DEV-SNAPSHOT
../pom.xml
@@ -110,7 +110,16 @@
jackson-dataformat-xml
com.fasterxml.jackson.dataformat
- 2.12.7
+
+
+ com.fasterxml.woodstox
+ woodstox-core
+
+
+
+
+ com.fasterxml.woodstox
+ woodstox-core
io.openmanufacturing
diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/hub/bamm/BammHelper.java b/backend/src/main/java/org/eclipse/tractusx/semantics/hub/bamm/BammHelper.java
index 6429cfc5..a15d9507 100644
--- a/backend/src/main/java/org/eclipse/tractusx/semantics/hub/bamm/BammHelper.java
+++ b/backend/src/main/java/org/eclipse/tractusx/semantics/hub/bamm/BammHelper.java
@@ -58,129 +58,122 @@
@Component
public class BammHelper {
- public Try loadBammModel(String ttl) {
- InputStream targetStream = new ByteArrayInputStream(ttl.getBytes());
+ public Try loadBammModel( String ttl ) {
+ InputStream targetStream = new ByteArrayInputStream( ttl.getBytes() );
- Try model = TurtleLoader.loadTurtle(targetStream);
+ Try model = TurtleLoader.loadTurtle( targetStream );
- StaticResolutionStrategy resolutionStrategy = new StaticResolutionStrategy(model);
+ StaticResolutionStrategy resolutionStrategy = new StaticResolutionStrategy( model );
+ AspectModelResolver resolver = new AspectModelResolver();
- AspectModelUrn startUrn = AspectModelUrn
- .fromUrn( "urn:bamm:org.eclipse.tractusx:1.0.0#Aspect" );
+ Try versionedModel = resolver.resolveAspectModel( resolutionStrategy, resolutionStrategy.getAspectModelUrn() );
-
- AspectModelResolver resolver = new AspectModelResolver();
+ if ( resolutionStrategy.getResolvementCounter() > 1 ) {
+ return Try.failure( new ResolutionException( "The definition must be self contained!" ) );
+ }
- Try versionedModel = resolver.resolveAspectModel(resolutionStrategy, startUrn);
+ return versionedModel;
+ }
- if(resolutionStrategy.getResolvementCounter() > 1) {
- return Try.failure(new ResolutionException("The definition must be self contained!"));
- }
+ public Try getAspectFromVersionedModel( VersionedModel versionedModel ) {
- return versionedModel;
- }
+ return AspectModelLoader.fromVersionedModel( versionedModel );
+ }
- public Try getAspectFromVersionedModel(VersionedModel versionedModel) {
+ public ValidationReport validateModel( Try model ) {
+ final AspectModelValidator validator = new AspectModelValidator();
+ final ValidationReport validationReport = validator.validate( model );
- return AspectModelLoader.fromVersionedModel(versionedModel);
- }
+ return validationReport;
+ }
- public ValidationReport validateModel(Try model) {
- final AspectModelValidator validator = new AspectModelValidator();
- final ValidationReport validationReport = validator.validate(model);
+ public byte[] generatePng( VersionedModel versionedModel ) {
+ final AspectModelDiagramGenerator generator = new AspectModelDiagramGenerator( versionedModel );
- return validationReport;
- }
+ try {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ generator.generateDiagram( Format.PNG, Locale.ENGLISH, output );
+ final byte[] bytes = output.toByteArray();
- public byte[] generatePng(VersionedModel versionedModel) {
- final AspectModelDiagramGenerator generator = new AspectModelDiagramGenerator(versionedModel);
-
- try {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- generator.generateDiagram(Format.PNG, Locale.ENGLISH, output);
+ return bytes;
+ } catch ( IOException e ) {
+ e.printStackTrace();
- final byte[] bytes = output.toByteArray();
-
- return bytes;
- } catch (IOException e) {
- e.printStackTrace();
+ return null;
+ }
+ }
- return null;
- }
- }
+ public JsonNode getJsonSchema( Aspect aspect ) {
+ AspectModelJsonSchemaGenerator jsonSchemaGenerator = new AspectModelJsonSchemaGenerator();
- public JsonNode getJsonSchema(Aspect aspect) {
- AspectModelJsonSchemaGenerator jsonSchemaGenerator = new AspectModelJsonSchemaGenerator();
+ JsonNode json = jsonSchemaGenerator.apply( aspect );
- JsonNode json = jsonSchemaGenerator.apply(aspect);
+ return json;
+ }
- return json;
- }
+ public Try getHtmlDocu( VersionedModel versionedModel ) {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ AspectModelDocumentationGenerator documentationGenerator = new AspectModelDocumentationGenerator( versionedModel );
- public Try getHtmlDocu(VersionedModel versionedModel) {
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- AspectModelDocumentationGenerator documentationGenerator = new AspectModelDocumentationGenerator(versionedModel);
+ Map options = new HashMap();
- Map options = new HashMap();
+ try {
+ InputStream ompCSS = getClass().getResourceAsStream( "/catena-template.css" );
+ String defaultCSS = CharStreams.toString( new InputStreamReader( ompCSS ) );
- try {
- InputStream ompCSS = getClass().getResourceAsStream("/catena-template.css");
- String defaultCSS = CharStreams.toString(new InputStreamReader(ompCSS));
+ options.put( HtmlGenerationOption.STYLESHEET, defaultCSS );
+ } catch ( IOException e ) {
+ return Try.failure( e );
+ }
- options.put(HtmlGenerationOption.STYLESHEET, defaultCSS);
- } catch (IOException e) {
- return Try.failure(e);
- }
+ try {
+ documentationGenerator.generate( ( String a ) -> {
+ return output;
+ }, options );
+ return Try.success( output.toByteArray() );
+ } catch ( IOException e ) {
+ return Try.failure( e );
+ }
+ }
- try {
- documentationGenerator.generate((String a) -> {
- return output;
- }, options);
+ public String getOpenApiDefinitionJson( Aspect aspect, String baseUrl ) {
+ AspectModelOpenApiGenerator openApiGenerator = new AspectModelOpenApiGenerator();
- return Try.success(output.toByteArray());
- } catch (IOException e) {
- return Try.failure(e);
- }
- }
+ JsonNode resultJson = openApiGenerator.applyForJson( aspect, true, baseUrl, Optional.empty(), Optional.empty(), false, Optional.empty() );
- public String getOpenApiDefinitionJson(Aspect aspect, String baseUrl) {
- AspectModelOpenApiGenerator openApiGenerator = new AspectModelOpenApiGenerator();
+ return resultJson.toString();
+ }
- JsonNode resultJson = openApiGenerator.applyForJson(aspect, true, baseUrl, Optional.empty(), Optional.empty(), false, Optional.empty());
+ public Try getExamplePayloadJson( Aspect aspect ) {
+ AspectModelJsonPayloadGenerator payloadGenerator = new AspectModelJsonPayloadGenerator( aspect );
- return resultJson.toString();
- }
+ return Try.of( payloadGenerator::generateJson );
+ }
- public Try getExamplePayloadJson(Aspect aspect) {
- AspectModelJsonPayloadGenerator payloadGenerator = new AspectModelJsonPayloadGenerator(aspect);
+ public Try getAasSubmodelTemplate( Aspect aspect, AasFormat aasFormat ) {
+ AspectModelAASGenerator aasGenerator = new AspectModelAASGenerator();
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
- return Try.of(payloadGenerator::generateJson);
- }
+ try {
+ switch ( aasFormat ) {
+ case FILE:
+ aasGenerator.generateAASXFile( aspect, ( String s ) -> {
+ return stream;
+ } );
+ return Try.of( stream::toByteArray );
+ case XML:
+ aasGenerator.generateAasXmlFile( aspect, ( String s ) -> {
+ return stream;
+ } );
+ return Try.of( stream::toString );
+ default:
+ return Try.failure( new Exception( String.format( "Wrong AAS output format %s", aasFormat.toString() ) ) );
- public Try getAasSubmodelTemplate(Aspect aspect, AasFormat aasFormat) {
- AspectModelAASGenerator aasGenerator = new AspectModelAASGenerator();
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
-
- try {
- switch(aasFormat) {
- case FILE:
- aasGenerator.generateAASXFile(aspect, (String s) -> {
- return stream;
- });
- return Try.of(stream::toByteArray);
- case XML:
- aasGenerator.generateAasXmlFile(aspect, (String s) -> {
- return stream;
- });
- return Try.of(stream::toString);
- default:
- return Try.failure(new Exception(String.format("Wrong AAS output format %s", aasFormat.toString())));
-
- }
- } catch (IOException e) {
- return Try.failure(e);
- }
- }
+ }
+ } catch ( IOException e ) {
+ return Try.failure( e );
+ }
+ }
}
diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/hub/bamm/StaticResolutionStrategy.java b/backend/src/main/java/org/eclipse/tractusx/semantics/hub/bamm/StaticResolutionStrategy.java
index c89cb5a4..b2b188db 100644
--- a/backend/src/main/java/org/eclipse/tractusx/semantics/hub/bamm/StaticResolutionStrategy.java
+++ b/backend/src/main/java/org/eclipse/tractusx/semantics/hub/bamm/StaticResolutionStrategy.java
@@ -19,28 +19,60 @@
********************************************************************************/
package org.eclipse.tractusx.semantics.hub.bamm;
-import org.apache.jena.rdf.model.Model;
-
+import io.openmanufacturing.sds.aspectmetamodel.KnownVersion;
import io.openmanufacturing.sds.aspectmodel.resolver.AbstractResolutionStrategy;
import io.openmanufacturing.sds.aspectmodel.urn.AspectModelUrn;
+import io.openmanufacturing.sds.aspectmodel.vocabulary.BAMM;
+import io.vavr.NotImplementedError;
import io.vavr.control.Try;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.StmtIterator;
+import org.apache.jena.vocabulary.RDF;
+
+import java.util.List;
+import java.util.Optional;
+
public class StaticResolutionStrategy extends AbstractResolutionStrategy {
- private int counter;
- private final Try model;
-
- public StaticResolutionStrategy(Try model) {
- this.model = model;
- }
-
- @Override
- public Try apply(AspectModelUrn t) {
- counter++;
-
- return this.model;
- }
-
- public int getResolvementCounter() {
- return counter;
- }
+ private int counter;
+ private final Try model;
+
+ public StaticResolutionStrategy( Try model ) {
+ this.model = model;
+ }
+
+ @Override
+ public Try apply( AspectModelUrn t ) {
+ counter++;
+ return this.model;
+ }
+
+ public int getResolvementCounter() {
+ return counter;
+ }
+
+ public AspectModelUrn getAspectModelUrn() {
+ final Optional stmtIterator = getStmtIterator();
+
+ final String aspectModelUrn = stmtIterator.orElseThrow(
+ () -> new NotImplementedError( "AspectModelUrn cannot be found." ) )
+ .next().getSubject().getURI();
+
+ return AspectModelUrn.fromUrn( aspectModelUrn );
+ }
+
+ private Optional getStmtIterator() {
+ for ( final KnownVersion version : KnownVersion.getVersions() ) {
+ final BAMM bamm = new BAMM( version );
+ final List resources = List.of( bamm.Aspect(), bamm.Property(), bamm.Entity(), bamm.Characteristic() );
+ final Optional stmtIterator = resources.stream().filter(
+ resource -> model.get().listStatements( null, RDF.type, resource ).hasNext() ).findFirst()
+ .map( resource -> model.get().listStatements( null, RDF.type, resource ) );
+ if ( stmtIterator.isPresent() ) {
+ return stmtIterator;
+ }
+ }
+ return Optional.empty();
+ }
}
diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/hub/persistence/triplestore/SparqlQueries.java b/backend/src/main/java/org/eclipse/tractusx/semantics/hub/persistence/triplestore/SparqlQueries.java
index dbb6c8a7..100b843b 100644
--- a/backend/src/main/java/org/eclipse/tractusx/semantics/hub/persistence/triplestore/SparqlQueries.java
+++ b/backend/src/main/java/org/eclipse/tractusx/semantics/hub/persistence/triplestore/SparqlQueries.java
@@ -148,7 +148,23 @@ public class SparqlQueries {
+ "BIND(iri(concat(strbefore(str(?aspect ), \"#\"), \"#\")) AS ?package)\n"
+ "?package aux:status ?status\n"
+ "FILTER ( !bound(?statusFilter) || contains(str(?status), ?statusFilter) )\n"
- + "FILTER ( !bound(?namespaceFilter) || contains(str(?aspect), ?namespaceFilter ) )\n"
+ + "FILTER ( !bound(?namespaceFilter) || contains(lcase(str(?aspect)), lcase(?namespaceFilter) ) )\n"
+ + "}\n";
+
+ private static final String FILTER_QUERY_MINIMAL_WHERE_CLAUSE_SELECTIVE = "WHERE {\n"
+ + "BIND($bammAspectUrnRegexParam AS ?bammAspectUrnRegex)\n"
+ + "BIND(iri($bammFieldToSearchInParam) AS ?bammFieldToSearchIn)\n"
+ + "BIND($bammFieldSearchValueParam AS ?bammFieldSearchValue)\n"
+ + "BIND($statusFilterParam AS ?statusFilter)\n"
+ + "BIND($namespaceFilterParam AS ?namespaceFilter)\n"
+ + "VALUES (?urns) { ?urnParamList } \n"
+ + "?aspect a ?bammAspect .\n"
+ + "FILTER regex(str(?bammAspect), ?bammAspectUrnRegex, \"\")\n"
+ + "BIND(iri(concat(strbefore(str(?aspect ), \"#\"), \"#\")) AS ?package)\n"
+ + "?package aux:status ?status\n"
+ + "FILTER ( !bound(?statusFilter) || contains(str(?status), ?statusFilter) )\n"
+ + "FILTER ( !bound(?namespaceFilter) || contains(lcase(str(?aspect)), lcase(?namespaceFilter) ) )\n"
+ + "FILTER ( str(?aspect) IN (?urns) ) "
+ "}\n";
private static final String FILTER_QUERY_MINIMAL_WHERE_CLAUSE_SELECTIVE = "WHERE {\n"
diff --git a/backend/src/main/java/org/eclipse/tractusx/semantics/hub/persistence/triplestore/TripleStorePersistence.java b/backend/src/main/java/org/eclipse/tractusx/semantics/hub/persistence/triplestore/TripleStorePersistence.java
index 5aa9b9b3..1d60bc22 100644
--- a/backend/src/main/java/org/eclipse/tractusx/semantics/hub/persistence/triplestore/TripleStorePersistence.java
+++ b/backend/src/main/java/org/eclipse/tractusx/semantics/hub/persistence/triplestore/TripleStorePersistence.java
@@ -30,6 +30,9 @@
import javax.annotation.Nullable;
+import io.openmanufacturing.sds.aspectmodel.urn.UrnSyntaxException;
+import io.vavr.control.Try;
+
import org.eclipse.tractusx.semantics.hub.AspectModelNotFoundException;
import org.eclipse.tractusx.semantics.hub.ModelPackageNotFoundException;
import org.eclipse.tractusx.semantics.hub.domain.ModelPackage;
@@ -52,6 +55,7 @@
import io.openmanufacturing.sds.aspectmodel.resolver.AspectModelResolver;
import io.openmanufacturing.sds.aspectmodel.urn.AspectModelUrn;
+
import org.eclipse.tractusx.semantics.hub.InvalidStateTransitionException;
import org.eclipse.tractusx.semantics.hub.persistence.PersistenceLayer;
@@ -67,8 +71,8 @@ public TripleStorePersistence( final RDFConnectionRemoteBuilder rdfConnectionRem
}
@Override
- public SemanticModelList getModels(String namespaceFilter,
- @Nullable ModelPackageStatus status, Integer page, Integer pageSize ) {
+ public SemanticModelList getModels( String namespaceFilter,
+ @Nullable ModelPackageStatus status, Integer page, Integer pageSize ) {
final Query query = SparqlQueries.buildFindAllQuery( namespaceFilter, status, page,
pageSize );
final AtomicReference> aspectModels = new AtomicReference<>();
@@ -79,7 +83,7 @@ public SemanticModelList getModels(String namespaceFilter,
} );
}
int totalSemanticModelCount = getTotalItemsCount( namespaceFilter, status );
- int totalPages = getTotalPages(totalSemanticModelCount, pageSize );
+ int totalPages = getTotalPages( totalSemanticModelCount, pageSize );
SemanticModelList modelList = new SemanticModelList();
List semanticModels = aspectModels.get();
modelList.setCurrentPage( page );
@@ -90,11 +94,11 @@ public SemanticModelList getModels(String namespaceFilter,
return modelList;
}
- private static int getTotalPages(int totalItemsCount, int pageSize){
- if(totalItemsCount == 0 || pageSize == 0){
+ private static int getTotalPages( int totalItemsCount, int pageSize ) {
+ if ( totalItemsCount == 0 || pageSize == 0 ) {
return 0;
}
- return (int) Math.ceil( ((double) totalItemsCount) / (double) pageSize);
+ return (int) Math.ceil( ((double) totalItemsCount) / (double) pageSize );
}
@Override
@@ -103,35 +107,35 @@ public SemanticModel getModel( final AspectModelUrn urn ) {
}
@Override
- public SemanticModel save(SemanticModelType type, String newModel, SemanticModelStatus status ) {
+ public SemanticModel save( SemanticModelType type, String newModel, SemanticModelStatus status ) {
final Model rdfModel = sdsSdk.load( newModel.getBytes( StandardCharsets.UTF_8 ) );
final AspectModelUrn modelUrn = sdsSdk.getAspectUrn( rdfModel );
Optional existsByPackage = findByPackageByUrn( ModelPackageUrn.fromUrn( modelUrn ) );
if ( existsByPackage.isPresent() ) {
ModelPackageStatus persistedModelStatus = existsByPackage.get().getStatus();
- final ModelPackageStatus desiredModelStatus = ModelPackageStatus.valueOf( status.name() );
+ final ModelPackageStatus desiredModelStatus = ModelPackageStatus.valueOf( status.name() );
switch ( persistedModelStatus ) {
- case DRAFT:
- if(desiredModelStatus.equals(ModelPackageStatus.RELEASED) && !hasReferenceToDraftPackage(modelUrn, rdfModel)) {
- throw new InvalidStateTransitionException("It is not allowed to release an aspect that has dependencies in DRAFT state.");
- }
+ case DRAFT:
+ if ( desiredModelStatus.equals( ModelPackageStatus.RELEASED ) && !hasReferenceToDraftPackage( modelUrn, rdfModel ) ) {
+ throw new InvalidStateTransitionException( "It is not allowed to release an aspect that has dependencies in DRAFT state." );
+ }
+ deleteByUrn( ModelPackageUrn.fromUrn( modelUrn ) );
+ break;
+ case RELEASED:
+ // released models can only be updated when the new state is deprecated
+ if ( desiredModelStatus.equals( ModelPackageStatus.DEPRECATED ) ) {
deleteByUrn( ModelPackageUrn.fromUrn( modelUrn ) );
- break;
- case RELEASED:
- // released models can only be updated when the new state is deprecated
- if(desiredModelStatus.equals(ModelPackageStatus.DEPRECATED)){
- deleteByUrn( ModelPackageUrn.fromUrn( modelUrn ) );
- } else {
- throw new IllegalArgumentException(
- String.format( "The package %s is already in status %s and cannot be modified. Only a transition to DEPRECATED is possible.",
- ModelPackageUrn.fromUrn( modelUrn ).getUrn(), persistedModelStatus.name() ) );
- }
- break;
- case DEPRECATED:
+ } else {
throw new IllegalArgumentException(
- String.format( "The package %s is already in status %s and cannot be modified.",
+ String.format( "The package %s is already in status %s and cannot be modified. Only a transition to DEPRECATED is possible.",
ModelPackageUrn.fromUrn( modelUrn ).getUrn(), persistedModelStatus.name() ) );
+ }
+ break;
+ case DEPRECATED:
+ throw new IllegalArgumentException(
+ String.format( "The package %s is already in status %s and cannot be modified.",
+ ModelPackageUrn.fromUrn( modelUrn ).getUrn(), persistedModelStatus.name() ) );
}
}
@@ -173,7 +177,7 @@ public void deleteModelsPackage( final ModelPackageUrn urn ) {
}
@Override
- public SemanticModelList findModelListByUrns(List urns, int page, int pageSize) {
+ public SemanticModelList findModelListByUrns( List urns, int page, int pageSize ) {
final Query query = SparqlQueries.buildFindListByUrns( urns, page, pageSize );
final AtomicReference> aspectModels = new AtomicReference<>();
try ( final RDFConnection rdfConnection = rdfConnectionRemoteBuilder.build() ) {
@@ -183,7 +187,7 @@ public SemanticModelList findModelListByUrns(List urns, int page
} );
}
int totalSemanticModelCount = getSelectiveItemsCount( null, null, null, null, urns );
- int totalPages = getTotalPages(totalSemanticModelCount, pageSize );
+ int totalPages = getTotalPages( totalSemanticModelCount, pageSize );
SemanticModelList modelList = new SemanticModelList();
List semanticModels = aspectModels.get();
modelList.setCurrentPage( page );
@@ -197,22 +201,21 @@ public SemanticModelList findModelListByUrns(List urns, int page
public boolean echo() {
final RDFConnection rdfConnection = rdfConnectionRemoteBuilder.build();
- return rdfConnection.queryAsk(SparqlQueries.echoQuery());
+ return rdfConnection.queryAsk( SparqlQueries.echoQuery() );
}
- private boolean hasReferenceToDraftPackage(AspectModelUrn modelUrn, Model model) {
- Pattern pattern = Pattern.compile(SparqlQueries.ALL_BAMM_ASPECT_URN_PREFIX);
-
- List urns = AspectModelResolver.getAllUrnsInModel(model).stream().map((AspectModelUrn urn) -> {
- return urn.getUrnPrefix();
- })
- .distinct()
- .collect(Collectors.toList());
-
- for(var entry : urns) {
- Matcher matcher = pattern.matcher(entry);
- if(!matcher.find() && !modelUrn.getUrnPrefix().equals(entry)) {
- if(findByPackageByUrn(ModelPackageUrn.fromUrn(entry)).get().getStatus().equals(ModelPackageStatus.DRAFT)) {
+ private boolean hasReferenceToDraftPackage( AspectModelUrn modelUrn, Model model ) {
+ Pattern pattern = Pattern.compile( SparqlQueries.ALL_BAMM_ASPECT_URN_PREFIX );
+
+ List urns = AspectModelResolver.getAllUrnsInModel( model ).stream().filter( urn -> getAspectModelUrn( urn ).isSuccess() )
+ .map( urn -> getAspectModelUrn( urn ).get().getUrnPrefix() )
+ .distinct()
+ .collect( Collectors.toList() );
+
+ for ( var entry : urns ) {
+ Matcher matcher = pattern.matcher( entry );
+ if ( !matcher.find() && !modelUrn.getUrnPrefix().equals( entry ) ) {
+ if ( findByPackageByUrn( ModelPackageUrn.fromUrn( entry ) ).get().getStatus().equals( ModelPackageStatus.DRAFT ) ) {
return false;
}
}
@@ -294,12 +297,20 @@ private Model findJenaModelByUrn( final AspectModelUrn urn ) {
}
}
+ private Try getAspectModelUrn( String urn ) {
+ try {
+ return Try.success( AspectModelUrn.fromUrn( urn ) );
+ } catch ( UrnSyntaxException var2 ) {
+ return Try.failure( var2 );
+ }
+ }
+
private static List aspectModelFrom(
final List querySolutions ) {
- return querySolutions
- .stream()
- .map( TripleStorePersistence::aspectModelFrom )
- .collect(Collectors.toList());
+ return querySolutions
+ .stream()
+ .map( TripleStorePersistence::aspectModelFrom )
+ .collect( Collectors.toList() );
}
private static SemanticModel aspectModelFrom( final QuerySolution querySolution ) {
diff --git a/backend/src/main/resources/static/semantic-hub-openapi.yaml b/backend/src/main/resources/static/semantic-hub-openapi.yaml
index aea287c0..46310e16 100644
--- a/backend/src/main/resources/static/semantic-hub-openapi.yaml
+++ b/backend/src/main/resources/static/semantic-hub-openapi.yaml
@@ -152,6 +152,7 @@ paths:
application/json:
schema:
type: array
+ maxItems: 10000
items:
type: string
responses:
@@ -441,6 +442,7 @@ components:
items:
title: Items
type: array
+ maxItems: 10000
items:
$ref: '#/components/schemas/SemanticModel'
totalItems:
diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/hub/ModelsApiFilterTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/hub/ModelsApiFilterTest.java
index f9a900cd..272a5a34 100644
--- a/backend/src/test/java/org/eclipse/tractusx/semantics/hub/ModelsApiFilterTest.java
+++ b/backend/src/test/java/org/eclipse/tractusx/semantics/hub/ModelsApiFilterTest.java
@@ -76,6 +76,22 @@ public void testGetByNamespaceExpectResultsFound() throws Exception {
.andExpect( MockMvcResultMatchers.status().isOk() );
}
+ @Test
+ public void testGetByNamespaceWithCaseInsensitiveExpectResultsFound() throws Exception {
+ mvc.perform(
+ MockMvcRequestBuilders.get(
+ "/api/v1/models?namespaceFilter=urn:bamm:org.eclipse.TRACtusx.TraceaBiliTy" )
+ .accept( MediaType.APPLICATION_JSON )
+ .with(jwtTokenFactory.allRoles())
+ )
+ .andDo( MockMvcResultHandlers.print() )
+ .andExpect( jsonPath( "$.items" ).isArray() )
+ .andExpect( jsonPath( "$.items.length()" ).value( 1 ) )
+ .andExpect( jsonPath( "$.totalItems", equalTo( 1 ) ) )
+ .andExpect( jsonPath( "$.itemCount", equalTo( 1 ) ) )
+ .andExpect( MockMvcResultMatchers.status().isOk() );
+ }
+
@Test
public void testGetModelListByAvailablePropertyTypeExpectResultsFound() throws Exception {
mvc.perform(
diff --git a/backend/src/test/java/org/eclipse/tractusx/semantics/hub/bamm/BammHelperTest.java b/backend/src/test/java/org/eclipse/tractusx/semantics/hub/bamm/BammHelperTest.java
index c2d92860..f570a112 100644
--- a/backend/src/test/java/org/eclipse/tractusx/semantics/hub/bamm/BammHelperTest.java
+++ b/backend/src/test/java/org/eclipse/tractusx/semantics/hub/bamm/BammHelperTest.java
@@ -19,13 +19,12 @@
********************************************************************************/
package org.eclipse.tractusx.semantics.hub.bamm;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
-import org.eclipse.tractusx.semantics.hub.bamm.BammHelper;
import io.openmanufacturing.sds.aspectmodel.resolver.services.VersionedModel;
+import io.vavr.NotImplementedError;
import io.vavr.control.Try;
public class BammHelperTest {
@@ -68,4 +67,24 @@ public void testBammValidationWithInvalidModel() {
assertFalse(bammHelper.validateModel(model).conforms());
}
+
+ @Test
+ public void testBammLoaderInVersion2_0_0_WithValidModelExpectSuccess() {
+ final String modelString = "@prefix bamm: .\n @prefix bamm-c: .\n @prefix bamm-e: .\n @prefix unit: .\n @prefix rdf: .\n @prefix rdfs: .\n @prefix xsd: .\n @prefix : .\n \n :Movement a bamm:Aspect;\n bamm:name \"Movement\";\n bamm:preferredName \"Movement\"@en;\n bamm:description \"Aspect for movement information\"@en;\n bamm:properties (:isMoving :speedLimitWarning :position);\n bamm:operations ().\n :isMoving a bamm:Property;\n bamm:name \"isMoving\";\n bamm:preferredName \"Moving\"@en;\n bamm:description \"Flag indicating whether the asset is currently moving\"@en;\n bamm:characteristic bamm-c:Boolean.\n :speedLimitWarning a bamm:Property;\n bamm:name \"speedLimitWarning\";\n bamm:preferredName \"Speed Limit Warning\"@en;\n bamm:description \"Indicates if the speed limit is adhered to.\"@en;\n bamm:characteristic :TrafficLight.\n :position a bamm:Property;\n bamm:name \"position\";\n bamm:preferredName \"Position\"@en;\n bamm:description \"Indicates a position\"@en;\n bamm:characteristic :SpatialPositionCharacteristic.\n :TrafficLight a bamm-c:Enumeration;\n bamm:name \"TrafficLight\";\n bamm:preferredName \"Warning Level\"@en;\n bamm:description \"Represents if speed of position change is within specification (green), within tolerance (yellow), or outside specification (red).\"@en;\n bamm:dataType xsd:string;\n bamm-c:values (\"green\" \"yellow\" \"red\").\n :SpatialPosition a bamm:Entity;\n bamm:name \"SpatialPosition\";\n bamm:preferredName \"Spatial Position\"@en;\n bamm:description \"Position in space, described along three axis, with the third axis optional, if all positions are in a plane.\"@en;\n bamm:properties (:x :y :z).\n :x a bamm:Property;\n bamm:name \"x\";\n bamm:preferredName \"x\"@en;\n bamm:description \"x coordinate in space\"@en;\n bamm:characteristic :Coordinate.\n :y a bamm:Property;\n bamm:name \"y\";\n bamm:preferredName \"y\"@en;\n bamm:description \"y coordinate in space\"@en;\n bamm:characteristic :Coordinate.\n :z a bamm:Property;\n bamm:name \"z\";\n bamm:preferredName \"z\"@en;\n bamm:description \"z coordinate in space\"@en;\n bamm:characteristic :Coordinate;\n bamm:optional \"true\"^^xsd:boolean.\n :Coordinate a bamm-c:Measurement;\n bamm:name \"Coordinate\";\n bamm:preferredName \"Coordinate\"@en;\n bamm:description \"Represents a coordinate along an axis in space.\"@en;\n bamm:dataType xsd:float;\n bamm-c:unit unit:metre.\n :SpatialPositionCharacteristic a bamm-c:SingleEntity;\n bamm:name \"SpatialPositionCharacteristic\";\n bamm:preferredName \"Spatial Position Characteristic\"@en;\n bamm:description \"Represents a single position in space with optional z coordinate.\"@en;\n bamm:dataType :SpatialPosition.\n";
+
+ BammHelper bammHelper = new BammHelper();
+
+ assertTrue(bammHelper.loadBammModel(modelString).isSuccess());
+ }
+
+ @Test
+ public void testBammLoaderInUnknownVersion0_0_0_WithInvalidModelExpectFailure() {
+ final String modelString = "@prefix bamm: .\n @prefix bamm-c: .\n @prefix bamm-e: .\n @prefix unit: .\n @prefix rdf: .\n @prefix rdfs: .\n @prefix xsd: .\n @prefix : .\n \n :Movement a bamm:Aspect;\n bamm:name \"Movement\";\n bamm:preferredName \"Movement\"@en;\n bamm:description \"Aspect for movement information\"@en;\n bamm:properties (:isMoving :speedLimitWarning :position);\n bamm:operations ().\n :isMoving a bamm:Property;\n bamm:name \"isMoving\";\n bamm:preferredName \"Moving\"@en;\n bamm:description \"Flag indicating whether the asset is currently moving\"@en;\n bamm:characteristic bamm-c:Boolean.\n :speedLimitWarning a bamm:Property;\n bamm:name \"speedLimitWarning\";\n bamm:preferredName \"Speed Limit Warning\"@en;\n bamm:description \"Indicates if the speed limit is adhered to.\"@en;\n bamm:characteristic :TrafficLight.\n :position a bamm:Property;\n bamm:name \"position\";\n bamm:preferredName \"Position\"@en;\n bamm:description \"Indicates a position\"@en;\n bamm:characteristic :SpatialPositionCharacteristic.\n :TrafficLight a bamm-c:Enumeration;\n bamm:name \"TrafficLight\";\n bamm:preferredName \"Warning Level\"@en;\n bamm:description \"Represents if speed of position change is within specification (green), within tolerance (yellow), or outside specification (red).\"@en;\n bamm:dataType xsd:string;\n bamm-c:values (\"green\" \"yellow\" \"red\").\n :SpatialPosition a bamm:Entity;\n bamm:name \"SpatialPosition\";\n bamm:preferredName \"Spatial Position\"@en;\n bamm:description \"Position in space, described along three axis, with the third axis optional, if all positions are in a plane.\"@en;\n bamm:properties (:x :y :z).\n :x a bamm:Property;\n bamm:name \"x\";\n bamm:preferredName \"x\"@en;\n bamm:description \"x coordinate in space\"@en;\n bamm:characteristic :Coordinate.\n :y a bamm:Property;\n bamm:name \"y\";\n bamm:preferredName \"y\"@en;\n bamm:description \"y coordinate in space\"@en;\n bamm:characteristic :Coordinate.\n :z a bamm:Property;\n bamm:name \"z\";\n bamm:preferredName \"z\"@en;\n bamm:description \"z coordinate in space\"@en;\n bamm:characteristic :Coordinate;\n bamm:optional \"true\"^^xsd:boolean.\n :Coordinate a bamm-c:Measurement;\n bamm:name \"Coordinate\";\n bamm:preferredName \"Coordinate\"@en;\n bamm:description \"Represents a coordinate along an axis in space.\"@en;\n bamm:dataType xsd:float;\n bamm-c:unit unit:metre.\n :SpatialPositionCharacteristic a bamm-c:SingleEntity;\n bamm:name \"SpatialPositionCharacteristic\";\n bamm:preferredName \"Spatial Position Characteristic\"@en;\n bamm:description \"Represents a single position in space with optional z coordinate.\"@en;\n bamm:dataType :SpatialPosition.\n";
+
+ BammHelper bammHelper = new BammHelper();
+
+ assertEquals(
+ "AspectModelUrn cannot be found.",
+ assertThrows( NotImplementedError.class, () -> bammHelper.loadBammModel( modelString )).getMessage() );
+ }
}
diff --git a/backend/deployment/semantic-hub/.helmignore b/charts/semantic-hub/.helmignore
similarity index 100%
rename from backend/deployment/semantic-hub/.helmignore
rename to charts/semantic-hub/.helmignore
diff --git a/backend/deployment/semantic-hub/Chart.yaml b/charts/semantic-hub/Chart.yaml
similarity index 76%
rename from backend/deployment/semantic-hub/Chart.yaml
rename to charts/semantic-hub/Chart.yaml
index b2a1cc1c..4462fb05 100644
--- a/backend/deployment/semantic-hub/Chart.yaml
+++ b/charts/semantic-hub/Chart.yaml
@@ -3,5 +3,5 @@ name: semantic-hub
description: Helm Chart for the Catena-X Semantic Hub Application
type: application
-version: 0.1.0
-appVersion: 0.1.0-M1
\ No newline at end of file
+version: 0.1.3
+appVersion: 0.1.0-M2
diff --git a/backend/deployment/semantic-hub/templates/_helpers.tpl b/charts/semantic-hub/templates/_helpers.tpl
similarity index 100%
rename from backend/deployment/semantic-hub/templates/_helpers.tpl
rename to charts/semantic-hub/templates/_helpers.tpl
diff --git a/backend/deployment/semantic-hub/templates/graphdb/graphdb-deployment.yaml b/charts/semantic-hub/templates/graphdb/graphdb-deployment.yaml
similarity index 100%
rename from backend/deployment/semantic-hub/templates/graphdb/graphdb-deployment.yaml
rename to charts/semantic-hub/templates/graphdb/graphdb-deployment.yaml
diff --git a/backend/deployment/semantic-hub/templates/graphdb/graphdb-pvc.yaml b/charts/semantic-hub/templates/graphdb/graphdb-pvc.yaml
similarity index 100%
rename from backend/deployment/semantic-hub/templates/graphdb/graphdb-pvc.yaml
rename to charts/semantic-hub/templates/graphdb/graphdb-pvc.yaml
diff --git a/backend/deployment/semantic-hub/templates/graphdb/graphdb-service.yaml b/charts/semantic-hub/templates/graphdb/graphdb-service.yaml
similarity index 100%
rename from backend/deployment/semantic-hub/templates/graphdb/graphdb-service.yaml
rename to charts/semantic-hub/templates/graphdb/graphdb-service.yaml
diff --git a/backend/deployment/semantic-hub/templates/hub/hub-deployment.yaml b/charts/semantic-hub/templates/hub/hub-deployment.yaml
similarity index 96%
rename from backend/deployment/semantic-hub/templates/hub/hub-deployment.yaml
rename to charts/semantic-hub/templates/hub/hub-deployment.yaml
index 901b856a..be88f854 100644
--- a/backend/deployment/semantic-hub/templates/hub/hub-deployment.yaml
+++ b/charts/semantic-hub/templates/hub/hub-deployment.yaml
@@ -66,14 +66,14 @@ spec:
livenessProbe:
httpGet:
path: /actuator/health/liveness
- port: { { .Values.hub.containerPort } }
+ port: {{ .Values.hub.containerPort }}
initialDelaySeconds: 100
periodSeconds: 3
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
- port: { { .Values.hub.containerPort } }
+ port: {{ .Values.hub.containerPort }}
initialDelaySeconds: 60
periodSeconds: 3
failureThreshold: 3
diff --git a/backend/deployment/semantic-hub/templates/hub/hub-ingress.yaml b/charts/semantic-hub/templates/hub/hub-ingress.yaml
similarity index 100%
rename from backend/deployment/semantic-hub/templates/hub/hub-ingress.yaml
rename to charts/semantic-hub/templates/hub/hub-ingress.yaml
diff --git a/backend/deployment/semantic-hub/templates/hub/hub-secret.yaml b/charts/semantic-hub/templates/hub/hub-secret.yaml
similarity index 95%
rename from backend/deployment/semantic-hub/templates/hub/hub-secret.yaml
rename to charts/semantic-hub/templates/hub/hub-secret.yaml
index 3c30c433..bc595e14 100644
--- a/backend/deployment/semantic-hub/templates/hub/hub-secret.yaml
+++ b/charts/semantic-hub/templates/hub/hub-secret.yaml
@@ -29,6 +29,7 @@ metadata:
type: Opaque
data:
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI: {{ .Values.hub.idpIssuerUri | b64enc }}
+ HUB_GENERAL_IDM_PUBLIC_CLIENT_ID: {{ .Values.hub.idpClientId | b64enc }}
# the fuseki instance does not require authentication yet
# this variables need to be provided because they are mandatory in the application
HUB_TRIPLE_STORE_USERNAME: {{ .Values.graphdb.username | b64enc }}
diff --git a/backend/deployment/semantic-hub/templates/hub/hub-service.yaml b/charts/semantic-hub/templates/hub/hub-service.yaml
similarity index 100%
rename from backend/deployment/semantic-hub/templates/hub/hub-service.yaml
rename to charts/semantic-hub/templates/hub/hub-service.yaml
diff --git a/backend/deployment/semantic-hub/values.yaml b/charts/semantic-hub/values.yaml
similarity index 97%
rename from backend/deployment/semantic-hub/values.yaml
rename to charts/semantic-hub/values.yaml
index f5737a66..087ea5be 100644
--- a/backend/deployment/semantic-hub/values.yaml
+++ b/charts/semantic-hub/values.yaml
@@ -19,7 +19,7 @@
###############################################################
hub:
- image: semantic-hub:0.1.0-M1
+ image: semantic-hub:0.1.0-M2
imagePullPolicy: IfNotPresent
replicaCount: 1
containerPort: 4242
@@ -29,6 +29,7 @@ hub:
## If 'authentication' is set to false, no OAuth authentication is enforced
authentication: false
idpIssuerUri: https://idp-url
+ idpClientId: idpClientID
## Ignored if 'graphdb.enabled' is set to true
graphdbBaseUrl: http://graphdb:3030
service:
diff --git a/docs/documentation.md b/docs/documentation.md
new file mode 100644
index 00000000..cd1b229b
--- /dev/null
+++ b/docs/documentation.md
@@ -0,0 +1,83 @@
+## Architectural Overview
+The SLDT Semantic Hub stores Semantic Model definitions and allows the generation of several artifacts. It restricts access to the models by authentication via a token and authorization via roles in the token claims. Therefore, the Hub interacts with a Keycloak instance. The models are created in the Hub during our governance process as depicted below.
+
+![](img/image001.png)
+
+## Implementation
+The following section describes the use cases implemented for the semantic hub.
+
+### Upload of an aspect model
+![](img/image002.png)
+
+
+| Validation | Description Value |
+|---|---|
+| BAMM compliance | Checks if the model is compliant with the BAMM. The BAMM SDK does provide the validation logic. |
+| Model Status check (RELEASE vs DRAFT) | Uploads will always accepted when there are no existing namespace:version combination in the TripleStore. For a model in DRAFT state, uploads will always be accepted. For a model in RELEASE state, uploads will be denied. RELEASED models are immutable. |
+| External reference check | It will be checked if all exernal references are available in the TripleStore. The BAMM SDK does provide a mechanisim where the resolving against the TripleStore can be integrated. |
+
+
+
+## Example:
+Example Aspect Model
+```
+@prefix xsd: .
+@prefix bamm: .
+@prefix : .
+
+
+:DocumentationSimple a bamm:Aspect;
+bamm:name "ManufacturerDocumentationSimple";
+bamm:preferredName "ManufacturerDocumentation"@en;
+bamm:description "The Submodel defines a simplified set of manufacturer documentation to bring about information from manufacturer to operator of industrial equipment."@en;
+
+:documents a bamm:Property;
+bamm:name "documents";
+bamm:preferredName "documents"@en;
+bamm:description "Set of documents"@en;
+```
+
+The Semantic Hub will add the release status as triple upon upload:
+Release Status
+```
+@prefix aux:
+
+ aux:releaseStatus aux:DRAFT .
+```
+
+## Package
+| No | Rule | Example |
+|---|---|---|
+| 1. | A package is defined by the urn prefix until "#". | net.catenax.semantics.product:1.2.0# |
+| 2. | A package can contain one or multiple aspects. | Example 1: net.catenax.semantics.traceability:1.2.0#Traceability Example 2: net.catenax.semantics.product:1.2.0#ProductDescription net.catenax.semantics.product:1.2.0#ProductUsage net.catenax.semantics.product:1.2.0#ProductDetails|
+| 3. | Multiple versions of a package can exists. | Possible: net.catenax.semantics.product:1.2.0 net.catenax.semantics.product:4.2.0 |
+| 4. | The versioning applies to the package. All aspects and model elements scoped to a package have the same version.| Possible: net.catenax.semantics.product:1.2.0#ProductDescription net.catenax.semantics.product:1.2.0#ProductUsage net.catenax.semantics.product:1.2.0#ProductDetails Possible:net.catenax.semantics.product:4.3.0#ProductDescription net.catenax.semantics.product:4.3.0#ProductUsage net.catenax.semantics.product:4.3.0#ProductDetails Not Possible: net.catenax.semantics.product:1.3.0#ProductDescription net.catenax.semantics.product:1.2.0#ProductUsage net.catenax.semantics.product:3.2.0#ProductDetails |
+| 5. | All aspect models and model elements scoped to a package have the same status. | Possible: net.catenax.semantics.product:1.2.0#ProductDescription → RELEASE, net.catenax.semantics.product:1.2.0#ProductUsage → RELEASE net.catenax.semantics.product:1.2.0#ProductDetails → RELEASE Not Possible: net.catenax.semantics.product:1.2.0#ProductDescription → RELEASE, net.catenax.semantics.product:1.2.0#ProductUsage → DRAFT
+
+
+
+## Download of the documentation of an Aspect Model
+![](img/image003.png)
+
+Example queries to resolve an aspect model with all references:
+Construct Query
+```
+@prefix ns:
+
+CONSTRUCT {
+?s ?p ?o .
+} WHERE {
+bind( ns: as ?aspect)
+?aspect (<>|!<>)* ?s . // resolves all references
+?s ?p ?o .
+}
+Search for Aspect Models
+The current search API can stay as is. Below is an example query for selecting bamm properties:
+Search Queries
+CONSTRUCT {
+?s ?p ?o .
+} WHERE {
+FILTER ( $param == ?o ) // Custom filter can be added here.
+?s ?p ?o .
+}
+```
diff --git a/docs/img/image001.png b/docs/img/image001.png
new file mode 100644
index 00000000..2180bbc7
Binary files /dev/null and b/docs/img/image001.png differ
diff --git a/docs/img/image002.png b/docs/img/image002.png
new file mode 100644
index 00000000..34b6d82d
Binary files /dev/null and b/docs/img/image002.png differ
diff --git a/docs/img/image003.png b/docs/img/image003.png
new file mode 100644
index 00000000..13a6bb32
Binary files /dev/null and b/docs/img/image003.png differ
diff --git a/pom.xml b/pom.xml
index 08d22820..f5bb4629 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,13 +25,13 @@
org.springframework.boot
spring-boot-starter-parent
- 2.7.3
+ 2.7.6
org.eclipse.tractusx
semantic-hub
- 0.1.0-M2
+ DEV-SNAPSHOT
Tractus-X Semantic Hub
Root Module of the Tractus-X Semantic Hub
pom
@@ -65,7 +65,7 @@
- 2.7.3
+ 2.7.6
3.1.3
1.6.6
2.9.2
@@ -78,7 +78,7 @@
0.10.3
2.11.0
3.0.2
- 1.31
+ 1.33
1.7.32
@@ -86,10 +86,13 @@
2.13.1
+ 2.14.0
+ 2.12.7
20211205
+ 6.4.0
- 2.0.0
+ 2.0.6
4.2.0
1.3.1
@@ -240,6 +243,18 @@
org.openapitools
jackson-databind-nullable
0.1.0
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.databind.version}
@@ -248,6 +263,16 @@
jackson-datatype-jsr310
${jackson.version}
+
+ jackson-dataformat-xml
+ com.fasterxml.jackson.dataformat
+ ${jackson.dataformat.version}
+
+
+ com.fasterxml.woodstox
+ woodstox-core
+ ${woodstoxcore.version}
+
@@ -257,16 +282,28 @@
-
- io.openmanufacturing
- sds-aspect-model-starter
- ${bamm.sdk.version}
-
+
+ io.openmanufacturing
+ sds-aspect-model-starter
+ ${bamm.sdk.version}
+
+
+
+ org.apache.commons
+ commons-text
+
+
+
+
+ org.apache.commons
+ commons-text
+ 1.10.0
+
io.openmanufacturing
sds-aspect-model-aas-generator
${bamm.sdk.version}
-
+
org.apache.jena
jena-core