From 0419e6b1748edae77de17af899ede41a8e294b66 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Mon, 3 Jun 2024 11:26:36 +0200 Subject: [PATCH 01/36] wip: Add a registry hierarchy feature module to AAS Registry --- .../Readme.md | 3 + .../pom.xml | 24 ++++ .../HierarchalAasRegistryFeature.java | 62 +++++++++ .../HierarchalAasRegistryStorage.java | 118 ++++++++++++++++++ basyx.aasregistry/pom.xml | 1 + ci/docker-compose.yml | 11 ++ pom.xml | 6 + 7 files changed, 225 insertions(+) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryFeature.java create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryStorage.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md new file mode 100644 index 000000000..0e27291e6 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md @@ -0,0 +1,3 @@ +# AssetAdministrationShell Registry - Hierarchy + +This feature enables hierarchy AssetAdministrationShell Registries. diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml new file mode 100644 index 000000000..98da5ad33 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml @@ -0,0 +1,24 @@ + + 4.0.0 + + + org.eclipse.digitaltwin.basyx + basyx.aasregistry + ${revision} + + + basyx.aasregistry-feature-hierarchy + + + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-service + + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-service-basemodel + + + \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryFeature.java new file mode 100644 index 000000000..bc14f7e85 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryFeature.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization; + +import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; +import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorageFeature; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.stereotype.Component; + +/** + * Feature for hierarchal {@link AasRegistryStorage} + * + * @author mateusmolina + */ +@Component +@ConditionalOnExpression("${" + HierarchalAasRegistryFeature.FEATURENAME + ".enabled:false}") +public class HierarchalAasRegistryFeature implements AasRegistryStorageFeature { + public static final String FEATURENAME = "basyx.aasregistry.feature.hierarchy"; + + @Value("${" + FEATURENAME + ".enabled:false}") + private boolean enabled; + + @Override + public AasRegistryStorage decorate(AasRegistryStorage storage) { + return new HierarchalAasRegistryStorage(storage); + } + + @Override + public String getName() { + return "AasRegistry Hierarchy"; + } + + @Override + public boolean isEnabled() { + return enabled; + } + +} \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryStorage.java new file mode 100644 index 000000000..feb932e0f --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryStorage.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization; + +import java.util.List; +import java.util.Set; + +import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchRequest; +import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchResponse; +import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorAlreadyExistsException; +import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; +import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.SubmodelAlreadyExistsException; +import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.SubmodelNotFoundException; +import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; +import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.DescriptorFilter; +import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; + + +/** + * Decorator for hierarchal {@link AasRegistryStorage} + * + * @author mateusmolina + */ +public class HierarchalAasRegistryStorage implements AasRegistryStorage { + + private AasRegistryStorage decorated; + + public HierarchalAasRegistryStorage(AasRegistryStorage decorated) { + this.decorated = decorated; + } + + @Override + public CursorResult> getAllAasDescriptors(PaginationInfo pRequest, DescriptorFilter filter) { + return decorated.getAllAasDescriptors(pRequest, filter); + } + + @Override + public AssetAdministrationShellDescriptor getAasDescriptor(String aasDescriptorId) throws AasDescriptorNotFoundException { + return decorated.getAasDescriptor(aasDescriptorId); + } + + @Override + public void insertAasDescriptor(AssetAdministrationShellDescriptor descr) throws AasDescriptorAlreadyExistsException { + decorated.insertAasDescriptor(descr); + } + + @Override + public void replaceAasDescriptor(String aasDescriptorId, AssetAdministrationShellDescriptor descriptor) throws AasDescriptorNotFoundException { + decorated.replaceAasDescriptor(aasDescriptorId, descriptor); + } + + @Override + public void removeAasDescriptor(String aasDescriptorId) throws AasDescriptorNotFoundException { + decorated.removeAasDescriptor(aasDescriptorId); + } + + @Override + public CursorResult> getAllSubmodels(String aasDescriptorId, PaginationInfo pRequest) throws AasDescriptorNotFoundException { + return decorated.getAllSubmodels(aasDescriptorId, pRequest); + } + + @Override + public SubmodelDescriptor getSubmodel(String aasDescriptorId, String submodelId) throws AasDescriptorNotFoundException, SubmodelNotFoundException { + return decorated.getSubmodel(aasDescriptorId, submodelId); + } + + @Override + public void insertSubmodel(String aasDescriptorId, SubmodelDescriptor submodel) throws AasDescriptorNotFoundException, SubmodelAlreadyExistsException { + decorated.insertSubmodel(aasDescriptorId, submodel); + } + + @Override + public void replaceSubmodel(String aasDescriptorId, String submodelId, SubmodelDescriptor submodel) throws AasDescriptorNotFoundException, SubmodelNotFoundException { + decorated.replaceSubmodel(aasDescriptorId, submodelId, submodel); + } + + @Override + public void removeSubmodel(String aasDescriptorId, String submodelId) throws AasDescriptorNotFoundException, SubmodelNotFoundException { + decorated.removeSubmodel(aasDescriptorId, submodelId); + } + + @Override + public Set clear() { + return decorated.clear(); + } + + @Override + public ShellDescriptorSearchResponse searchAasDescriptors(ShellDescriptorSearchRequest request) { + return decorated.searchAasDescriptors(request); + } + +} diff --git a/basyx.aasregistry/pom.xml b/basyx.aasregistry/pom.xml index c190e1ffc..172f16be4 100644 --- a/basyx.aasregistry/pom.xml +++ b/basyx.aasregistry/pom.xml @@ -54,6 +54,7 @@ basyx.aasregistry-service-release-kafka-mem basyx.aasregistry-service-release-kafka-mongodb basyx.aasregistry-feature-authorization + basyx.aasregistry-feature-hierarchy diff --git a/ci/docker-compose.yml b/ci/docker-compose.yml index 681c1c0bb..5019aae9b 100644 --- a/ci/docker-compose.yml +++ b/ci/docker-compose.yml @@ -84,6 +84,17 @@ services: restart: always networks: - basyx-java-server-sdk + + aas-registry-log-mem-delegated: + image: eclipsebasyx/aas-registry-log-mem:2.0.0-SNAPSHOT + container_name: aas-registry-log-mem-delegated + ports: + - "8051:8080" + environment: + SERVER_SERVLET_CONTEXT_PATH: / + restart: always + networks: + - basyx-java-server-sdk sm-registry-log-mem: image: eclipsebasyx/submodel-registry-log-mem:2.0.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 255501885..bf33fbea6 100644 --- a/pom.xml +++ b/pom.xml @@ -1071,6 +1071,12 @@ ${revision} tests + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-feature-hierarchy + ${revision} + tests + org.eclipse.digitaltwin.basyx basyx.submodelregistry-feature-authorization From 579ec7610e1507aa71ecd36fc78bd1d2c5b49e11 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Mon, 3 Jun 2024 11:30:20 +0200 Subject: [PATCH 02/36] wip: Revert ci compose change --- ci/docker-compose.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/ci/docker-compose.yml b/ci/docker-compose.yml index 5019aae9b..681c1c0bb 100644 --- a/ci/docker-compose.yml +++ b/ci/docker-compose.yml @@ -84,17 +84,6 @@ services: restart: always networks: - basyx-java-server-sdk - - aas-registry-log-mem-delegated: - image: eclipsebasyx/aas-registry-log-mem:2.0.0-SNAPSHOT - container_name: aas-registry-log-mem-delegated - ports: - - "8051:8080" - environment: - SERVER_SERVLET_CONTEXT_PATH: / - restart: always - networks: - - basyx-java-server-sdk sm-registry-log-mem: image: eclipsebasyx/submodel-registry-log-mem:2.0.0-SNAPSHOT From 188e9a0115b96260deba03aca194a386733195cd Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Mon, 3 Jun 2024 11:35:44 +0200 Subject: [PATCH 03/36] wip: Rename package --- .../HierarchalAasRegistryFeature.java | 2 +- .../HierarchalAasRegistryStorage.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/{authorization => hierarchy}/HierarchalAasRegistryFeature.java (97%) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/{authorization => hierarchy}/HierarchalAasRegistryStorage.java (98%) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java similarity index 97% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryFeature.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java index bc14f7e85..2672e4acd 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryFeature.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java @@ -23,7 +23,7 @@ * SPDX-License-Identifier: MIT ******************************************************************************/ -package org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization; +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorageFeature; diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java similarity index 98% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryStorage.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java index feb932e0f..8f6494cba 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/authorization/HierarchalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java @@ -23,7 +23,7 @@ * SPDX-License-Identifier: MIT ******************************************************************************/ -package org.eclipse.digitaltwin.basyx.aasregistry.feature.authorization; +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; import java.util.List; import java.util.Set; From bd776ea1a563342e16f3e16092ed6df97c8a30af Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Mon, 3 Jun 2024 11:35:53 +0200 Subject: [PATCH 04/36] wip: Initial Test Setup --- .../hierarchy/DummyAasRegistryComponent.java | 44 ++++++++++++++++++ .../hierarchy/TestHierarchalAasRegistry.java | 36 +++++++++++++++ .../src/test/resources/application.yml | 46 +++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasRegistryComponent.java create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasRegistryComponent.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasRegistryComponent.java new file mode 100644 index 000000000..9c846a9f6 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasRegistryComponent.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.regression.feature.hierarchy; + +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Creates and starts the {@link HierarchalAasRegistryFeature} for tests + * + * @author mateusmolina + * + */ +@SpringBootApplication(scanBasePackages = { "org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy", "org.eclipse.digitaltwin.basyx.aasregistry.service.api", "org.eclipse.digitaltwin.basyx.aasregistry.service.events", + "org.eclipse.digitaltwin.basyx.aasregistry.service.configuration", "org.eclipse.digitaltwin.basyx.aasregistry.service.errors" }) +public class DummyAasRegistryComponent { + public static void main(String[] args) { + SpringApplication.run(DummyAasRegistryComponent.class, args); + } +} \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java new file mode 100644 index 000000000..8791571cc --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.regression.feature.hierarchy; + +/** + * TestHierarchalAasRegistry + * + * @author mateusmolina + * + */ +public class TestHierarchalAasRegistry { + +} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml new file mode 100644 index 000000000..5f709ae8a --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml @@ -0,0 +1,46 @@ +--- +events: + sink: log +description: + profiles: https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRegistryServiceSpecification/SSP-001 +springdoc: + api-docs: + path: /api-docs +springfox: + documentation: + enabled: true + # open-api.v3.path: /api-docs +management: + endpoints: + web: + exposure: + include: "health,metrics" +logging: + level: + root: INFO +server: + shutdown: graceful + port: 8080 + error: + whitelabel: + enabled: false +spring: + application: + name: Basyx Aas Registry + jackson: + date-format: org.eclipse.digitaltwin.basyx.aasregistry.service.RFC3339DateFormat + serialization: + WRITE_DATES_AS_TIMESTAMPS: false + profiles: + active: logEvents,inMemoryStorage + +registry: + type: inMemory + +basyx: + cors: + allowed-origins: "*" + allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" + feature: + hierarchy: + enabled: true \ No newline at end of file From ae02819f17b971411bddb86a160a07f5a80162af Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Mon, 3 Jun 2024 15:25:06 +0200 Subject: [PATCH 05/36] wip: Implement tests for Hierarchal AasRegistry --- .../pom.xml | 10 ++ .../hierarchy/DummyAasDescriptorFactory.java | 130 ++++++++++++++++++ .../hierarchy/TestHierarchalAasRegistry.java | 86 +++++++++++- 3 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml index 98da5ad33..3457d56f2 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml @@ -20,5 +20,15 @@ org.eclipse.digitaltwin.basyx basyx.aasregistry-service-basemodel + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-client-native + test + + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-service-inmemory-storage + test + \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java new file mode 100644 index 000000000..027778da0 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.regression.feature.hierarchy; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetKind; +import org.eclipse.digitaltwin.basyx.aasregistry.model.Endpoint; +import org.eclipse.digitaltwin.basyx.aasregistry.model.ProtocolInformation; +import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; +import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * DummyAasDescriptorFactory + * + * @author mateusmolina + * + */ +public class DummyAasDescriptorFactory { + public static final String AASDESCRIPTOR_ID_HIERARCHALONLY = "AASDESCRIPTOR_ID_HIERARCHALONLY"; + public static final String AASDESCRIPTOR_ID_DELEGATEDONLY = "AASDESCRIPTOR_ID_DELEGATEDONLY"; + private final String repoBaseUrl; + + public DummyAasDescriptorFactory(String repoBaseUrl) { + this.repoBaseUrl = repoBaseUrl; + } + + public AssetAdministrationShellDescriptor getAasDescriptor_HierarchalOnly() { + return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_HIERARCHALONLY, buildTestAasIdShort(AASDESCRIPTOR_ID_HIERARCHALONLY)); + } + + public AssetAdministrationShellDescriptor getAasDescriptor_DelegatedOnly() { + return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_DELEGATEDONLY, buildTestAasIdShort(AASDESCRIPTOR_ID_DELEGATEDONLY)); + } + + public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor convertToClientAasDescriptor(ObjectMapper objectMapper, AssetAdministrationShellDescriptor aasRegistryDescriptor) { + try { + return objectMapper.convertValue(aasRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor.class); + } catch (Exception e) { + throw new RuntimeException("Conversion error", e); + } + } + + private static AssetAdministrationShellDescriptor createDummyDescriptor(String baseUrl, String shellId, String shellIdShort) { + AssetAdministrationShellDescriptor descriptor = new AssetAdministrationShellDescriptor(shellId); + descriptor.setIdShort(shellIdShort); + descriptor.setAssetKind(AssetKind.TYPE); + descriptor.setAssetType("TestAsset"); + + setEndpointItem(baseUrl, shellId, descriptor); + descriptor.setGlobalAssetId("DummyGlobalAssetId"); + descriptor.addSubmodelDescriptorsItem(createDummySubmodelDescriptor(baseUrl, shellId + "-SM", shellIdShort + "-SM")); + + return descriptor; + } + + private static SubmodelDescriptor createDummySubmodelDescriptor(String baseUrl, String submodelId, String submodelIdShort) { + SubmodelDescriptor descriptor = new SubmodelDescriptor(submodelId, new ArrayList<>()); + descriptor.setIdShort(submodelIdShort); + descriptor.setEndpoints(List.of(new Endpoint("AAS-3.0", createSmProtocolInformation(baseUrl, submodelId)))); + + return descriptor; + } + + private static void setEndpointItem(String baseUrl, String shellId, AssetAdministrationShellDescriptor descriptor) { + ProtocolInformation protocolInformation = createProtocolInformation(baseUrl, shellId); + + Endpoint endpoint = new Endpoint("AAS-3.0", protocolInformation); + descriptor.addEndpointsItem(endpoint); + } + + private static ProtocolInformation createProtocolInformation(String baseUrl, String shellId) { + String href = String.format("%s/%s", baseUrl + "/shells", Base64UrlEncodedIdentifier.encodeIdentifier(shellId)); + + ProtocolInformation protocolInformation = new ProtocolInformation(href); + protocolInformation.endpointProtocol(getProtocol(href)); + + return protocolInformation; + } + + private static ProtocolInformation createSmProtocolInformation(String baseUrl, String smId) { + String href = String.format("%s/%s", baseUrl + "/submodels", Base64UrlEncodedIdentifier.encodeIdentifier(smId)); + + ProtocolInformation protocolInformation = new ProtocolInformation(href); + protocolInformation.endpointProtocol(getProtocol(href)); + + return protocolInformation; + } + + private static String getProtocol(String endpoint) { + try { + return new URL(endpoint).getProtocol(); + } catch (MalformedURLException e) { + throw new RuntimeException(); + } + } + + private static String buildTestAasIdShort(String aasId) { + return aasId + "IdShort"; + } +} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java index 8791571cc..f7c51a6f3 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java @@ -25,12 +25,96 @@ package org.eclipse.digitaltwin.basyx.aasregistry.regression.feature.hierarchy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import java.io.FileNotFoundException; +import java.io.IOException; + +import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; +import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; +import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; +import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; + +import com.fasterxml.jackson.databind.ObjectMapper; + /** - * TestHierarchalAasRegistry + * Test for {@link HierarchalAasRegistryFeature} * * @author mateusmolina * */ public class TestHierarchalAasRegistry { + private static final String DELEGATED_REGISTRY_URL = "http://localhost:8050"; + private static final String REPO_BASE_URL = "http://127.0.0.1:8080"; + + private static DummyAasDescriptorFactory aasDescriptorFactory = new DummyAasDescriptorFactory(REPO_BASE_URL); + + private static ConfigurableApplicationContext appContext; + private static AasRegistryStorage aasRegistryHierarchal; + private static ObjectMapper objectMapper; + + @BeforeClass + public static void setUp() throws FileNotFoundException, IOException, ApiException { + appContext = new SpringApplication(DummyAasRegistryComponent.class).run(new String[] {}); + + aasRegistryHierarchal = appContext.getBean(AasRegistryStorage.class); + objectMapper = appContext.getBean(ObjectMapper.class); + + setupDelegatedRegistry(); + setupHierarchalRegistry(); + } + + @AfterClass + public static void cleanUp() throws ApiException { + cleanUpDelegatedRegistry(); + appContext.close(); + } + + @Test + public void getAasDescriptor_InHierarchal() { + AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchal.getAasDescriptor(DummyAasDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY); + + AssetAdministrationShellDescriptor expectedDescriptor = aasDescriptorFactory.getAasDescriptor_HierarchalOnly(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getAasDescriptor_ThroughDelegated() { + AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchal.getAasDescriptor(DummyAasDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); + + AssetAdministrationShellDescriptor expectedDescriptor = aasDescriptorFactory.getAasDescriptor_DelegatedOnly(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getNonExistingDescriptor() { + assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchal.getAasDescriptor("nonExistingAasDescriptor")); + } + + private static void setupHierarchalRegistry() { + aasRegistryHierarchal.insertAasDescriptor(aasDescriptorFactory.getAasDescriptor_HierarchalOnly()); + } + + private static void setupDelegatedRegistry() throws ApiException { + RegistryAndDiscoveryInterfaceApi clientFacade = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); + AssetAdministrationShellDescriptor descriptor = aasDescriptorFactory.getAasDescriptor_DelegatedOnly(); + + clientFacade.postAssetAdministrationShellDescriptor(DummyAasDescriptorFactory.convertToClientAasDescriptor(objectMapper, descriptor)); + } + + private static void cleanUpDelegatedRegistry() throws ApiException { + RegistryAndDiscoveryInterfaceApi clientFacade = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); + clientFacade.deleteAllShellDescriptors(); + } } From 60fcc126fe48c3958606d6b5aa4c7985b71e2287 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Mon, 3 Jun 2024 16:27:42 +0200 Subject: [PATCH 06/36] Implement getAasDescriptor hierarchal method --- .../pom.xml | 1 - .../HierarchalAasRegistryFeature.java | 5 +- .../HierarchalAasRegistryStorage.java | 30 +++++++++-- .../HierarchalAasRegistryStorageHelper.java | 54 +++++++++++++++++++ .../hierarchy/DummyAasDescriptorFactory.java | 10 ---- .../hierarchy/TestHierarchalAasRegistry.java | 4 +- .../src/test/resources/application.yml | 8 +-- 7 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorageHelper.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml index 3457d56f2..95ee463b9 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml @@ -23,7 +23,6 @@ org.eclipse.digitaltwin.basyx basyx.aasregistry-client-native - test org.eclipse.digitaltwin.basyx diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java index 2672e4acd..73a4ff5b3 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java @@ -44,9 +44,12 @@ public class HierarchalAasRegistryFeature implements AasRegistryStorageFeature { @Value("${" + FEATURENAME + ".enabled:false}") private boolean enabled; + @Value("${" + FEATURENAME + ".delegatedUrl}") + private String delegatedUrl; + @Override public AasRegistryStorage decorate(AasRegistryStorage storage) { - return new HierarchalAasRegistryStorage(storage); + return new HierarchalAasRegistryStorage(storage, delegatedUrl); } @Override diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java index 8f6494cba..22c0c6abd 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java @@ -28,6 +28,8 @@ import java.util.List; import java.util.Set; +import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; +import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchRequest; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchResponse; @@ -40,7 +42,10 @@ import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.DescriptorFilter; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import com.fasterxml.jackson.databind.ObjectMapper; /** * Decorator for hierarchal {@link AasRegistryStorage} @@ -49,10 +54,15 @@ */ public class HierarchalAasRegistryStorage implements AasRegistryStorage { - private AasRegistryStorage decorated; + private final AasRegistryStorage decorated; - public HierarchalAasRegistryStorage(AasRegistryStorage decorated) { + private final RegistryAndDiscoveryInterfaceApi delegatedClientApi; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + public HierarchalAasRegistryStorage(AasRegistryStorage decorated, String delegatedUrl) { this.decorated = decorated; + this.delegatedClientApi = new RegistryAndDiscoveryInterfaceApi(delegatedUrl); } @Override @@ -62,7 +72,15 @@ public CursorResult> getAllAasDescripto @Override public AssetAdministrationShellDescriptor getAasDescriptor(String aasDescriptorId) throws AasDescriptorNotFoundException { - return decorated.getAasDescriptor(aasDescriptorId); + try { + return decorated.getAasDescriptor(aasDescriptorId); + } catch (AasDescriptorNotFoundException e) { + try { + return HierarchalAasRegistryStorageHelper.mapEqModel(objectMapper, delegatedClientApi.getAssetAdministrationShellDescriptorById(aasDescriptorId)); + } catch (ApiException e1) { + throw mapApiException(e1, aasDescriptorId); + } + } } @Override @@ -115,4 +133,10 @@ public ShellDescriptorSearchResponse searchAasDescriptors(ShellDescriptorSearchR return decorated.searchAasDescriptors(request); } + private RuntimeException mapApiException(ApiException e, String aasDescriptorId) { + if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND)) + return new AasDescriptorNotFoundException(aasDescriptorId); + + return new RuntimeException(e); + } } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorageHelper.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorageHelper.java new file mode 100644 index 000000000..4067db1ab --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorageHelper.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; + +import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * HierarchalAasRegistryStorageHelper + * + * @author mateusmolina + * + */ +public final class HierarchalAasRegistryStorageHelper { + public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor mapEqModel(ObjectMapper objectMapper, AssetAdministrationShellDescriptor aasRegistryDescriptor) { + try { + return objectMapper.convertValue(aasRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor.class); + } catch (Exception e) { + throw new RuntimeException("Conversion error", e); + } + } + + public static AssetAdministrationShellDescriptor mapEqModel(ObjectMapper objectMapper, org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor aasRegistryDescriptor) { + try { + return objectMapper.convertValue(aasRegistryDescriptor, AssetAdministrationShellDescriptor.class); + } catch (Exception e) { + throw new RuntimeException("Conversion error", e); + } + } +} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java index 027778da0..7ee381fdb 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java @@ -37,8 +37,6 @@ import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * DummyAasDescriptorFactory * @@ -62,14 +60,6 @@ public AssetAdministrationShellDescriptor getAasDescriptor_DelegatedOnly() { return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_DELEGATEDONLY, buildTestAasIdShort(AASDESCRIPTOR_ID_DELEGATEDONLY)); } - public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor convertToClientAasDescriptor(ObjectMapper objectMapper, AssetAdministrationShellDescriptor aasRegistryDescriptor) { - try { - return objectMapper.convertValue(aasRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor.class); - } catch (Exception e) { - throw new RuntimeException("Conversion error", e); - } - } - private static AssetAdministrationShellDescriptor createDummyDescriptor(String baseUrl, String shellId, String shellIdShort) { AssetAdministrationShellDescriptor descriptor = new AssetAdministrationShellDescriptor(shellId); descriptor.setIdShort(shellIdShort); diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java index f7c51a6f3..452152ffb 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java @@ -34,6 +34,7 @@ import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryStorageHelper; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; @@ -68,6 +69,7 @@ public static void setUp() throws FileNotFoundException, IOException, ApiExcepti aasRegistryHierarchal = appContext.getBean(AasRegistryStorage.class); objectMapper = appContext.getBean(ObjectMapper.class); + cleanUpDelegatedRegistry(); setupDelegatedRegistry(); setupHierarchalRegistry(); } @@ -109,7 +111,7 @@ private static void setupDelegatedRegistry() throws ApiException { RegistryAndDiscoveryInterfaceApi clientFacade = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); AssetAdministrationShellDescriptor descriptor = aasDescriptorFactory.getAasDescriptor_DelegatedOnly(); - clientFacade.postAssetAdministrationShellDescriptor(DummyAasDescriptorFactory.convertToClientAasDescriptor(objectMapper, descriptor)); + clientFacade.postAssetAdministrationShellDescriptor(HierarchalAasRegistryStorageHelper.mapEqModel(objectMapper, descriptor)); } private static void cleanUpDelegatedRegistry() throws ApiException { diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml index 5f709ae8a..ae0daf0f7 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml @@ -41,6 +41,8 @@ basyx: cors: allowed-origins: "*" allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" - feature: - hierarchy: - enabled: true \ No newline at end of file + aasregistry: + feature: + hierarchy: + enabled: true + delegatedUrl: http://localhost:8050 \ No newline at end of file From 951ba236e28836ef13e0fc7ea1fd9d1cdac75d8b Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Tue, 4 Jun 2024 11:36:17 +0200 Subject: [PATCH 07/36] Implement hierarchal getSubmodelDescriptor --- ...elper.java => AasRegistryModelMapper.java} | 28 ++++++++-- .../HierarchalAasRegistryStorage.java | 30 ++++++++--- ...ctory.java => DummyDescriptorFactory.java} | 28 +++++++--- .../hierarchy/TestHierarchalAasRegistry.java | 51 ++++++++++++++----- 4 files changed, 104 insertions(+), 33 deletions(-) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/{HierarchalAasRegistryStorageHelper.java => AasRegistryModelMapper.java} (63%) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/{DummyAasDescriptorFactory.java => DummyDescriptorFactory.java} (80%) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorageHelper.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java similarity index 63% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorageHelper.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java index 4067db1ab..08de6cff4 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorageHelper.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java @@ -26,17 +26,21 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; import com.fasterxml.jackson.databind.ObjectMapper; /** - * HierarchalAasRegistryStorageHelper + * AasRegistryModelMapper * * @author mateusmolina * */ -public final class HierarchalAasRegistryStorageHelper { - public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor mapEqModel(ObjectMapper objectMapper, AssetAdministrationShellDescriptor aasRegistryDescriptor) { +public final class AasRegistryModelMapper { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor mapEqModel(AssetAdministrationShellDescriptor aasRegistryDescriptor) { try { return objectMapper.convertValue(aasRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor.class); } catch (Exception e) { @@ -44,11 +48,27 @@ public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdmini } } - public static AssetAdministrationShellDescriptor mapEqModel(ObjectMapper objectMapper, org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor aasRegistryDescriptor) { + public static AssetAdministrationShellDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor aasRegistryDescriptor) { try { return objectMapper.convertValue(aasRegistryDescriptor, AssetAdministrationShellDescriptor.class); } catch (Exception e) { throw new RuntimeException("Conversion error", e); } } + + public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor mapEqModel(SubmodelDescriptor smRegistryDescriptor) { + try { + return objectMapper.convertValue(smRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor.class); + } catch (Exception e) { + throw new RuntimeException("Conversion error", e); + } + } + + public static SubmodelDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor smRegistryDescriptor) { + try { + return objectMapper.convertValue(smRegistryDescriptor, SubmodelDescriptor.class); + } catch (Exception e) { + throw new RuntimeException("Conversion error", e); + } + } } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java index 22c0c6abd..f2ac789f6 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java @@ -45,8 +45,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * Decorator for hierarchal {@link AasRegistryStorage} * @@ -58,8 +56,6 @@ public class HierarchalAasRegistryStorage implements AasRegistryStorage { private final RegistryAndDiscoveryInterfaceApi delegatedClientApi; - private final ObjectMapper objectMapper = new ObjectMapper(); - public HierarchalAasRegistryStorage(AasRegistryStorage decorated, String delegatedUrl) { this.decorated = decorated; this.delegatedClientApi = new RegistryAndDiscoveryInterfaceApi(delegatedUrl); @@ -76,7 +72,7 @@ public AssetAdministrationShellDescriptor getAasDescriptor(String aasDescriptorI return decorated.getAasDescriptor(aasDescriptorId); } catch (AasDescriptorNotFoundException e) { try { - return HierarchalAasRegistryStorageHelper.mapEqModel(objectMapper, delegatedClientApi.getAssetAdministrationShellDescriptorById(aasDescriptorId)); + return AasRegistryModelMapper.mapEqModel(delegatedClientApi.getAssetAdministrationShellDescriptorById(aasDescriptorId)); } catch (ApiException e1) { throw mapApiException(e1, aasDescriptorId); } @@ -105,7 +101,15 @@ public CursorResult> getAllSubmodels(String aasDescript @Override public SubmodelDescriptor getSubmodel(String aasDescriptorId, String submodelId) throws AasDescriptorNotFoundException, SubmodelNotFoundException { - return decorated.getSubmodel(aasDescriptorId, submodelId); + try { + return decorated.getSubmodel(aasDescriptorId, submodelId); + } catch (AasDescriptorNotFoundException e) { + try { + return AasRegistryModelMapper.mapEqModel(delegatedClientApi.getSubmodelDescriptorByIdThroughSuperpath(aasDescriptorId, submodelId)); + } catch (ApiException e1) { + throw mapApiException(e1, aasDescriptorId, submodelId); + } + } } @Override @@ -133,10 +137,22 @@ public ShellDescriptorSearchResponse searchAasDescriptors(ShellDescriptorSearchR return decorated.searchAasDescriptors(request); } - private RuntimeException mapApiException(ApiException e, String aasDescriptorId) { + private static RuntimeException mapApiException(ApiException e, String aasDescriptorId) { if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND)) return new AasDescriptorNotFoundException(aasDescriptorId); return new RuntimeException(e); } + + private static RuntimeException mapApiException(ApiException e, String aasDescriptorId, String smId) { + if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND) && checkIfSubmodelNotFound(e, aasDescriptorId, smId)) + return new SubmodelNotFoundException(aasDescriptorId, smId); + + return mapApiException(e, aasDescriptorId); + } + + private static boolean checkIfSubmodelNotFound(ApiException e, String aasDescriptorId, String smId) { + SubmodelNotFoundException expectedException = new SubmodelNotFoundException(aasDescriptorId, smId); + return e.getMessage().contains(expectedException.getReason()); + } } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyDescriptorFactory.java similarity index 80% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyDescriptorFactory.java index 7ee381fdb..ceae21e39 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasDescriptorFactory.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyDescriptorFactory.java @@ -38,29 +38,41 @@ import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier; /** - * DummyAasDescriptorFactory + * DummyDescriptorFactory * * @author mateusmolina * */ -public class DummyAasDescriptorFactory { +public class DummyDescriptorFactory { public static final String AASDESCRIPTOR_ID_HIERARCHALONLY = "AASDESCRIPTOR_ID_HIERARCHALONLY"; + public static final String SMDESCRIPTOR_ID_HIERARCHALONLY = "SMDESCRIPTOR_ID_HIERARCHALONLY"; + public static final String AASDESCRIPTOR_ID_DELEGATEDONLY = "AASDESCRIPTOR_ID_DELEGATEDONLY"; + public static final String SMDESCRIPTOR_ID_DELEGATEDONLY = "SMDESCRIPTOR_ID_DELEGATEDONLY"; + private final String repoBaseUrl; - public DummyAasDescriptorFactory(String repoBaseUrl) { + public DummyDescriptorFactory(String repoBaseUrl) { this.repoBaseUrl = repoBaseUrl; } public AssetAdministrationShellDescriptor getAasDescriptor_HierarchalOnly() { - return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_HIERARCHALONLY, buildTestAasIdShort(AASDESCRIPTOR_ID_HIERARCHALONLY)); + return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_HIERARCHALONLY, buildIdShort(AASDESCRIPTOR_ID_HIERARCHALONLY), getSmDescriptor_HierarchalOnly()); + } + + public SubmodelDescriptor getSmDescriptor_HierarchalOnly() { + return createDummySubmodelDescriptor(repoBaseUrl, SMDESCRIPTOR_ID_HIERARCHALONLY, buildIdShort(SMDESCRIPTOR_ID_HIERARCHALONLY)); } public AssetAdministrationShellDescriptor getAasDescriptor_DelegatedOnly() { - return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_DELEGATEDONLY, buildTestAasIdShort(AASDESCRIPTOR_ID_DELEGATEDONLY)); + return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(AASDESCRIPTOR_ID_DELEGATEDONLY), getSmDescriptor_DelegatedOnly()); + } + + public SubmodelDescriptor getSmDescriptor_DelegatedOnly() { + return createDummySubmodelDescriptor(repoBaseUrl, SMDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(SMDESCRIPTOR_ID_DELEGATEDONLY)); } - private static AssetAdministrationShellDescriptor createDummyDescriptor(String baseUrl, String shellId, String shellIdShort) { + private static AssetAdministrationShellDescriptor createDummyDescriptor(String baseUrl, String shellId, String shellIdShort, SubmodelDescriptor submodelDescriptor) { AssetAdministrationShellDescriptor descriptor = new AssetAdministrationShellDescriptor(shellId); descriptor.setIdShort(shellIdShort); descriptor.setAssetKind(AssetKind.TYPE); @@ -68,7 +80,7 @@ private static AssetAdministrationShellDescriptor createDummyDescriptor(String b setEndpointItem(baseUrl, shellId, descriptor); descriptor.setGlobalAssetId("DummyGlobalAssetId"); - descriptor.addSubmodelDescriptorsItem(createDummySubmodelDescriptor(baseUrl, shellId + "-SM", shellIdShort + "-SM")); + descriptor.addSubmodelDescriptorsItem(submodelDescriptor); return descriptor; } @@ -114,7 +126,7 @@ private static String getProtocol(String endpoint) { } } - private static String buildTestAasIdShort(String aasId) { + private static String buildIdShort(String aasId) { return aasId + "IdShort"; } } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java index 452152ffb..4c2c51bea 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java @@ -33,10 +33,12 @@ import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.AasRegistryModelMapper; import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryStorageHelper; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; +import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.SubmodelNotFoundException; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -44,8 +46,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.context.ConfigurableApplicationContext; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * Test for {@link HierarchalAasRegistryFeature} * @@ -56,18 +56,16 @@ public class TestHierarchalAasRegistry { private static final String DELEGATED_REGISTRY_URL = "http://localhost:8050"; private static final String REPO_BASE_URL = "http://127.0.0.1:8080"; - private static DummyAasDescriptorFactory aasDescriptorFactory = new DummyAasDescriptorFactory(REPO_BASE_URL); + private static DummyDescriptorFactory descriptorFactory = new DummyDescriptorFactory(REPO_BASE_URL); private static ConfigurableApplicationContext appContext; private static AasRegistryStorage aasRegistryHierarchal; - private static ObjectMapper objectMapper; @BeforeClass public static void setUp() throws FileNotFoundException, IOException, ApiException { appContext = new SpringApplication(DummyAasRegistryComponent.class).run(new String[] {}); aasRegistryHierarchal = appContext.getBean(AasRegistryStorage.class); - objectMapper = appContext.getBean(ObjectMapper.class); cleanUpDelegatedRegistry(); setupDelegatedRegistry(); @@ -82,36 +80,61 @@ public static void cleanUp() throws ApiException { @Test public void getAasDescriptor_InHierarchal() { - AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchal.getAasDescriptor(DummyAasDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY); + AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchal.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY); - AssetAdministrationShellDescriptor expectedDescriptor = aasDescriptorFactory.getAasDescriptor_HierarchalOnly(); + AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_HierarchalOnly(); assertEquals(expectedDescriptor, actualDescriptor); } @Test public void getAasDescriptor_ThroughDelegated() { - AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchal.getAasDescriptor(DummyAasDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); + AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchal.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); - AssetAdministrationShellDescriptor expectedDescriptor = aasDescriptorFactory.getAasDescriptor_DelegatedOnly(); + AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_DelegatedOnly(); assertEquals(expectedDescriptor, actualDescriptor); } @Test - public void getNonExistingDescriptor() { + public void getNonExistingAasDescriptor() { assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchal.getAasDescriptor("nonExistingAasDescriptor")); } + @Test + public void getSubmodelDescriptor_InHierarchal() { + SubmodelDescriptor actualDescriptor = aasRegistryHierarchal.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_HIERARCHALONLY); + + SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_HierarchalOnly(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getSubmodelDescriptor_ThroughDelegated() { + SubmodelDescriptor actualDescriptor = aasRegistryHierarchal.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_DELEGATEDONLY); + + SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_DelegatedOnly(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getNonExistingSmDescriptor() { + assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchal.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, "nonExistingSubmodel")); + assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchal.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, "nonExistingSubmodel")); + assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchal.getSubmodel("nonExistingAas", "nonExistingSubmodel")); + } + private static void setupHierarchalRegistry() { - aasRegistryHierarchal.insertAasDescriptor(aasDescriptorFactory.getAasDescriptor_HierarchalOnly()); + aasRegistryHierarchal.insertAasDescriptor(descriptorFactory.getAasDescriptor_HierarchalOnly()); } private static void setupDelegatedRegistry() throws ApiException { RegistryAndDiscoveryInterfaceApi clientFacade = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); - AssetAdministrationShellDescriptor descriptor = aasDescriptorFactory.getAasDescriptor_DelegatedOnly(); + AssetAdministrationShellDescriptor descriptor = descriptorFactory.getAasDescriptor_DelegatedOnly(); - clientFacade.postAssetAdministrationShellDescriptor(HierarchalAasRegistryStorageHelper.mapEqModel(objectMapper, descriptor)); + clientFacade.postAssetAdministrationShellDescriptor(AasRegistryModelMapper.mapEqModel(descriptor)); } private static void cleanUpDelegatedRegistry() throws ApiException { From ede6f7fe81e5d4418a2e46b79d0b521b0366601f Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Tue, 4 Jun 2024 14:09:47 +0200 Subject: [PATCH 08/36] Extract ApiExpectionMappers to helper class --- .../HierarchalAasRegistryStorage.java | 25 ++-------- .../{ => mappers}/AasRegistryModelMapper.java | 49 ++++++++++++------- .../hierarchy/TestHierarchalAasRegistry.java | 2 +- 3 files changed, 35 insertions(+), 41 deletions(-) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/{ => mappers}/AasRegistryModelMapper.java (66%) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java index f2ac789f6..267294713 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java @@ -30,6 +30,7 @@ import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.mappers.AasRegistryModelMapper; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchRequest; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchResponse; @@ -42,8 +43,6 @@ import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.DescriptorFilter; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; -import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; /** * Decorator for hierarchal {@link AasRegistryStorage} @@ -74,7 +73,7 @@ public AssetAdministrationShellDescriptor getAasDescriptor(String aasDescriptorI try { return AasRegistryModelMapper.mapEqModel(delegatedClientApi.getAssetAdministrationShellDescriptorById(aasDescriptorId)); } catch (ApiException e1) { - throw mapApiException(e1, aasDescriptorId); + throw AasRegistryModelMapper.mapApiException(e1, aasDescriptorId); } } } @@ -107,7 +106,7 @@ public SubmodelDescriptor getSubmodel(String aasDescriptorId, String submodelId) try { return AasRegistryModelMapper.mapEqModel(delegatedClientApi.getSubmodelDescriptorByIdThroughSuperpath(aasDescriptorId, submodelId)); } catch (ApiException e1) { - throw mapApiException(e1, aasDescriptorId, submodelId); + throw AasRegistryModelMapper.mapApiException(e1, aasDescriptorId, submodelId); } } } @@ -137,22 +136,4 @@ public ShellDescriptorSearchResponse searchAasDescriptors(ShellDescriptorSearchR return decorated.searchAasDescriptors(request); } - private static RuntimeException mapApiException(ApiException e, String aasDescriptorId) { - if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND)) - return new AasDescriptorNotFoundException(aasDescriptorId); - - return new RuntimeException(e); - } - - private static RuntimeException mapApiException(ApiException e, String aasDescriptorId, String smId) { - if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND) && checkIfSubmodelNotFound(e, aasDescriptorId, smId)) - return new SubmodelNotFoundException(aasDescriptorId, smId); - - return mapApiException(e, aasDescriptorId); - } - - private static boolean checkIfSubmodelNotFound(ApiException e, String aasDescriptorId, String smId) { - SubmodelNotFoundException expectedException = new SubmodelNotFoundException(aasDescriptorId, smId); - return e.getMessage().contains(expectedException.getReason()); - } } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/mappers/AasRegistryModelMapper.java similarity index 66% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/mappers/AasRegistryModelMapper.java index 08de6cff4..6c15894ef 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/mappers/AasRegistryModelMapper.java @@ -23,15 +23,21 @@ * SPDX-License-Identifier: MIT ******************************************************************************/ -package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.mappers; +import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryStorage; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; +import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.SubmodelNotFoundException; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import com.fasterxml.jackson.databind.ObjectMapper; /** - * AasRegistryModelMapper + * Maps objects conversions for {@link HierarchalAasRegistryStorage} * * @author mateusmolina * @@ -40,35 +46,42 @@ public final class AasRegistryModelMapper { private static final ObjectMapper objectMapper = new ObjectMapper(); + private AasRegistryModelMapper() { + } + public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor mapEqModel(AssetAdministrationShellDescriptor aasRegistryDescriptor) { - try { return objectMapper.convertValue(aasRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor.class); - } catch (Exception e) { - throw new RuntimeException("Conversion error", e); - } } public static AssetAdministrationShellDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor aasRegistryDescriptor) { - try { return objectMapper.convertValue(aasRegistryDescriptor, AssetAdministrationShellDescriptor.class); - } catch (Exception e) { - throw new RuntimeException("Conversion error", e); - } } public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor mapEqModel(SubmodelDescriptor smRegistryDescriptor) { - try { return objectMapper.convertValue(smRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor.class); - } catch (Exception e) { - throw new RuntimeException("Conversion error", e); - } } public static SubmodelDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor smRegistryDescriptor) { - try { return objectMapper.convertValue(smRegistryDescriptor, SubmodelDescriptor.class); - } catch (Exception e) { - throw new RuntimeException("Conversion error", e); - } } + + public static RuntimeException mapApiException(ApiException e, String aasDescriptorId) { + if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND)) + return new AasDescriptorNotFoundException(aasDescriptorId); + + return new RuntimeException(e); + } + + public static RuntimeException mapApiException(ApiException e, String aasDescriptorId, String smId) { + if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND) && checkIfSubmodelNotFound(e, aasDescriptorId, smId)) + return new SubmodelNotFoundException(aasDescriptorId, smId); + + return mapApiException(e, aasDescriptorId); + } + + private static boolean checkIfSubmodelNotFound(ApiException e, String aasDescriptorId, String smId) { + SubmodelNotFoundException expectedException = new SubmodelNotFoundException(aasDescriptorId, smId); + return e.getMessage().contains(expectedException.getReason()); + } + } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java index 4c2c51bea..0a0598a29 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java @@ -33,8 +33,8 @@ import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.AasRegistryModelMapper; import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.mappers.AasRegistryModelMapper; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; From e0c8a8903ec46b74be07fd4f28fe8bc4fc61d387 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Tue, 4 Jun 2024 14:41:29 +0200 Subject: [PATCH 09/36] Extract delegation strategy to own component --- .../HierarchalAasRegistryFeature.java | 10 ++-- .../delegation/DelegationStrategy.java | 41 +++++++++++++++ .../DirectUrlDelegationStrategy.java | 50 +++++++++++++++++++ 3 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java index 73a4ff5b3..232959657 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java @@ -25,6 +25,7 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation.DelegationStrategy; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorageFeature; import org.springframework.beans.factory.annotation.Value; @@ -44,12 +45,15 @@ public class HierarchalAasRegistryFeature implements AasRegistryStorageFeature { @Value("${" + FEATURENAME + ".enabled:false}") private boolean enabled; - @Value("${" + FEATURENAME + ".delegatedUrl}") - private String delegatedUrl; + private DelegationStrategy delegationStrategy; + + public HierarchalAasRegistryFeature(DelegationStrategy delegationStrategy) { + this.delegationStrategy = delegationStrategy; + } @Override public AasRegistryStorage decorate(AasRegistryStorage storage) { - return new HierarchalAasRegistryStorage(storage, delegatedUrl); + return new HierarchalAasRegistryStorage(storage, delegationStrategy.buildDelegationUrl()); } @Override diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java new file mode 100644 index 000000000..beab5bf59 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; + +/** + * Defines a strategy for building the DelegationUrl + * + * @author mateusmolina + * + */ +public interface DelegationStrategy { + /** + * Builds the URL for the delegation AAS Registry + * + * @return URL of the registry, to which the request will be delegated + */ + public String buildDelegationUrl(); +} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java new file mode 100644 index 000000000..0d84002fe --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; + +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.stereotype.Component; + +/** + * Generates delegation URL based on value of delegatedUrl property + * + * @author mateusmolina + * + */ +@Component +@ConditionalOnMissingBean +public class DirectUrlDelegationStrategy implements DelegationStrategy { + @Value("${" + HierarchalAasRegistryFeature.FEATURENAME + ".delegatedUrl}") + private String delegatedUrl; + + @Override + public String buildDelegationUrl() { + return delegatedUrl; + } + +} From 1d8795022d0a45dae8efd81df0ddc695359eebae Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Tue, 4 Jun 2024 15:00:30 +0200 Subject: [PATCH 10/36] Clean up code and improve javadocs --- .../{mappers => }/AasRegistryModelMapper.java | 19 ++++++++-------- .../HierarchalAasRegistryStorage.java | 3 +-- ...va => HierarchicalAasRegistryFeature.java} | 15 ++++++++----- .../DirectUrlDelegationStrategy.java | 6 ++--- .../hierarchy/DummyAasRegistryComponent.java | 5 ++--- .../hierarchy/DummyDescriptorFactory.java | 22 +++++++++---------- .../TestHierarchicalAasRegistry.java} | 8 +++---- 7 files changed, 38 insertions(+), 40 deletions(-) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/{mappers => }/AasRegistryModelMapper.java (75%) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/{HierarchalAasRegistryFeature.java => HierarchicalAasRegistryFeature.java} (83%) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/{regression => }/feature/hierarchy/DummyAasRegistryComponent.java (88%) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/{regression => }/feature/hierarchy/DummyDescriptorFactory.java (85%) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/{regression/feature/hierarchy/TestHierarchalAasRegistry.java => feature/hierarchy/TestHierarchicalAasRegistry.java} (94%) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/mappers/AasRegistryModelMapper.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java similarity index 75% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/mappers/AasRegistryModelMapper.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java index 6c15894ef..bb3cca9c5 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/mappers/AasRegistryModelMapper.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java @@ -23,10 +23,9 @@ * SPDX-License-Identifier: MIT ******************************************************************************/ -package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.mappers; +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryStorage; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; @@ -37,42 +36,42 @@ import com.fasterxml.jackson.databind.ObjectMapper; /** - * Maps objects conversions for {@link HierarchalAasRegistryStorage} + * Handles internal model mapping for {@link HierarchalAasRegistryStorage} * * @author mateusmolina * */ -public final class AasRegistryModelMapper { +final class AasRegistryModelMapper { private static final ObjectMapper objectMapper = new ObjectMapper(); private AasRegistryModelMapper() { } - public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor mapEqModel(AssetAdministrationShellDescriptor aasRegistryDescriptor) { + static org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor mapEqModel(AssetAdministrationShellDescriptor aasRegistryDescriptor) { return objectMapper.convertValue(aasRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor.class); } - public static AssetAdministrationShellDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor aasRegistryDescriptor) { + static AssetAdministrationShellDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor aasRegistryDescriptor) { return objectMapper.convertValue(aasRegistryDescriptor, AssetAdministrationShellDescriptor.class); } - public static org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor mapEqModel(SubmodelDescriptor smRegistryDescriptor) { + static org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor mapEqModel(SubmodelDescriptor smRegistryDescriptor) { return objectMapper.convertValue(smRegistryDescriptor, org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor.class); } - public static SubmodelDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor smRegistryDescriptor) { + static SubmodelDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor smRegistryDescriptor) { return objectMapper.convertValue(smRegistryDescriptor, SubmodelDescriptor.class); } - public static RuntimeException mapApiException(ApiException e, String aasDescriptorId) { + static RuntimeException mapApiException(ApiException e, String aasDescriptorId) { if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND)) return new AasDescriptorNotFoundException(aasDescriptorId); return new RuntimeException(e); } - public static RuntimeException mapApiException(ApiException e, String aasDescriptorId, String smId) { + static RuntimeException mapApiException(ApiException e, String aasDescriptorId, String smId) { if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND) && checkIfSubmodelNotFound(e, aasDescriptorId, smId)) return new SubmodelNotFoundException(aasDescriptorId, smId); diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java index 267294713..6c3c93ab2 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java @@ -30,7 +30,6 @@ import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.mappers.AasRegistryModelMapper; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchRequest; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchResponse; @@ -45,7 +44,7 @@ import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; /** - * Decorator for hierarchal {@link AasRegistryStorage} + * Decorator for Hierarchical {@link AasRegistryStorage} * * @author mateusmolina */ diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java similarity index 83% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java index 232959657..9043e3d37 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryFeature.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java @@ -33,13 +33,18 @@ import org.springframework.stereotype.Component; /** - * Feature for hierarchal {@link AasRegistryStorage} - * + * Hierarchical {@link AasRegistryStorage} feature + * + * When this feature is enabled, retrieval requests will be delegated to the + * next AasRegistry. + * + * The next AasRegistry is selected via a {@link DelegationStrategy} + * * @author mateusmolina */ @Component -@ConditionalOnExpression("${" + HierarchalAasRegistryFeature.FEATURENAME + ".enabled:false}") -public class HierarchalAasRegistryFeature implements AasRegistryStorageFeature { +@ConditionalOnExpression("${" + HierarchicalAasRegistryFeature.FEATURENAME + ".enabled:false}") +public class HierarchicalAasRegistryFeature implements AasRegistryStorageFeature { public static final String FEATURENAME = "basyx.aasregistry.feature.hierarchy"; @Value("${" + FEATURENAME + ".enabled:false}") @@ -47,7 +52,7 @@ public class HierarchalAasRegistryFeature implements AasRegistryStorageFeature { private DelegationStrategy delegationStrategy; - public HierarchalAasRegistryFeature(DelegationStrategy delegationStrategy) { + public HierarchicalAasRegistryFeature(DelegationStrategy delegationStrategy) { this.delegationStrategy = delegationStrategy; } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java index 0d84002fe..bc5bf6a24 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java @@ -25,9 +25,8 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchicalAasRegistryFeature; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.stereotype.Component; /** @@ -37,9 +36,8 @@ * */ @Component -@ConditionalOnMissingBean public class DirectUrlDelegationStrategy implements DelegationStrategy { - @Value("${" + HierarchalAasRegistryFeature.FEATURENAME + ".delegatedUrl}") + @Value("${" + HierarchicalAasRegistryFeature.FEATURENAME + ".delegatedUrl}") private String delegatedUrl; @Override diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasRegistryComponent.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java similarity index 88% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasRegistryComponent.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java index 9c846a9f6..a3f5fd0a0 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyAasRegistryComponent.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java @@ -23,14 +23,13 @@ * SPDX-License-Identifier: MIT ******************************************************************************/ -package org.eclipse.digitaltwin.basyx.aasregistry.regression.feature.hierarchy; +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * Creates and starts the {@link HierarchalAasRegistryFeature} for tests + * Creates and starts the {@link HierarchicalAasRegistryFeature} for tests * * @author mateusmolina * diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java similarity index 85% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyDescriptorFactory.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java index ceae21e39..f3d1999de 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/DummyDescriptorFactory.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java @@ -23,7 +23,7 @@ * SPDX-License-Identifier: MIT ******************************************************************************/ -package org.eclipse.digitaltwin.basyx.aasregistry.regression.feature.hierarchy; +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; import java.net.MalformedURLException; import java.net.URL; @@ -43,32 +43,32 @@ * @author mateusmolina * */ -public class DummyDescriptorFactory { - public static final String AASDESCRIPTOR_ID_HIERARCHALONLY = "AASDESCRIPTOR_ID_HIERARCHALONLY"; - public static final String SMDESCRIPTOR_ID_HIERARCHALONLY = "SMDESCRIPTOR_ID_HIERARCHALONLY"; +class DummyDescriptorFactory { + static final String AASDESCRIPTOR_ID_HIERARCHALONLY = "AASDESCRIPTOR_ID_HIERARCHALONLY"; + static final String SMDESCRIPTOR_ID_HIERARCHALONLY = "SMDESCRIPTOR_ID_HIERARCHALONLY"; - public static final String AASDESCRIPTOR_ID_DELEGATEDONLY = "AASDESCRIPTOR_ID_DELEGATEDONLY"; - public static final String SMDESCRIPTOR_ID_DELEGATEDONLY = "SMDESCRIPTOR_ID_DELEGATEDONLY"; + static final String AASDESCRIPTOR_ID_DELEGATEDONLY = "AASDESCRIPTOR_ID_DELEGATEDONLY"; + static final String SMDESCRIPTOR_ID_DELEGATEDONLY = "SMDESCRIPTOR_ID_DELEGATEDONLY"; private final String repoBaseUrl; - public DummyDescriptorFactory(String repoBaseUrl) { + DummyDescriptorFactory(String repoBaseUrl) { this.repoBaseUrl = repoBaseUrl; } - public AssetAdministrationShellDescriptor getAasDescriptor_HierarchalOnly() { + AssetAdministrationShellDescriptor getAasDescriptor_HierarchalOnly() { return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_HIERARCHALONLY, buildIdShort(AASDESCRIPTOR_ID_HIERARCHALONLY), getSmDescriptor_HierarchalOnly()); } - public SubmodelDescriptor getSmDescriptor_HierarchalOnly() { + SubmodelDescriptor getSmDescriptor_HierarchalOnly() { return createDummySubmodelDescriptor(repoBaseUrl, SMDESCRIPTOR_ID_HIERARCHALONLY, buildIdShort(SMDESCRIPTOR_ID_HIERARCHALONLY)); } - public AssetAdministrationShellDescriptor getAasDescriptor_DelegatedOnly() { + AssetAdministrationShellDescriptor getAasDescriptor_DelegatedOnly() { return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(AASDESCRIPTOR_ID_DELEGATEDONLY), getSmDescriptor_DelegatedOnly()); } - public SubmodelDescriptor getSmDescriptor_DelegatedOnly() { + SubmodelDescriptor getSmDescriptor_DelegatedOnly() { return createDummySubmodelDescriptor(repoBaseUrl, SMDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(SMDESCRIPTOR_ID_DELEGATEDONLY)); } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java similarity index 94% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java index 0a0598a29..1bf76446c 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/regression/feature/hierarchy/TestHierarchalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java @@ -23,7 +23,7 @@ * SPDX-License-Identifier: MIT ******************************************************************************/ -package org.eclipse.digitaltwin.basyx.aasregistry.regression.feature.hierarchy; +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; @@ -33,8 +33,6 @@ import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchalAasRegistryFeature; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.mappers.AasRegistryModelMapper; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; @@ -47,12 +45,12 @@ import org.springframework.context.ConfigurableApplicationContext; /** - * Test for {@link HierarchalAasRegistryFeature} + * Test for {@link HierarchicalAasRegistryFeature} * * @author mateusmolina * */ -public class TestHierarchalAasRegistry { +public class TestHierarchicalAasRegistry { private static final String DELEGATED_REGISTRY_URL = "http://localhost:8050"; private static final String REPO_BASE_URL = "http://127.0.0.1:8080"; From e46390a31ece1681332b821de18463ab6b97f54a Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Tue, 4 Jun 2024 15:35:58 +0200 Subject: [PATCH 11/36] Improve README --- .../Readme.md | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md index 0e27291e6..d36590cad 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md @@ -1,3 +1,29 @@ # AssetAdministrationShell Registry - Hierarchy -This feature enables hierarchy AssetAdministrationShell Registries. +The Hierarchical AasRegistry Feature enhances the availability of data across multiple registries by allowing retrieval requests to be delegated to another AasRegistry. + +This feature allows the creation of a hierarchical structure of registries, where a registry can delegate retrieval requests to another registry when a given descriptor is not found in its storage. + +## Configuration + +### Enabling the Feature + +To enable the Hierarchical AasRegistry Feature, add the following property to your Spring application's configuration: + +```properties +basyx.aasregistry.feature.hierarchy.enabled=true +``` + +The next step is to set up the desired delegation strategy. + +### Delegation Strategy + +Currently, only one delegation strategy is implemented: + +#### Direct Url Delegation Strategy + +Delegates requests directly to a URL specified by the `basyx.aasregistry.feature.hierarchy.delegatedUrl` property. For example: + +```properties +basyx.aasregistry.feature.hierarchy.delegatedUrl=http://localhost:8050 +``` From def7d304fa610ddccfff88d1ba6a173a79d1ea8a Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Wed, 5 Jun 2024 15:26:34 +0200 Subject: [PATCH 12/36] Implement prefix-based delegation strategy --- .../hierarchy/AasRegistryModelMapper.java | 2 +- .../HierarchicalAasRegistryFeature.java | 2 +- ...va => HierarchicalAasRegistryStorage.java} | 21 +++-- .../delegation/DelegationStrategy.java | 17 +++- ...egy.java => PrefixDelegationStrategy.java} | 50 ++++++++-- .../hierarchy/DummyDescriptorFactory.java | 2 +- .../TestHierarchicalAasRegistry.java | 22 ++--- .../PrefixDelegationStrategyTest.java | 93 +++++++++++++++++++ .../src/test/resources/application.yml | 2 +- 9 files changed, 176 insertions(+), 35 deletions(-) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/{HierarchalAasRegistryStorage.java => HierarchicalAasRegistryStorage.java} (84%) rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/{DirectUrlDelegationStrategy.java => PrefixDelegationStrategy.java} (59%) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java index bb3cca9c5..b62de6b38 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java @@ -36,7 +36,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; /** - * Handles internal model mapping for {@link HierarchalAasRegistryStorage} + * Handles internal model mapping for {@link HierarchicalAasRegistryStorage} * * @author mateusmolina * diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java index 9043e3d37..46caa06b8 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java @@ -58,7 +58,7 @@ public HierarchicalAasRegistryFeature(DelegationStrategy delegationStrategy) { @Override public AasRegistryStorage decorate(AasRegistryStorage storage) { - return new HierarchalAasRegistryStorage(storage, delegationStrategy.buildDelegationUrl()); + return new HierarchicalAasRegistryStorage(storage, delegationStrategy); } @Override diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java similarity index 84% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java index 6c3c93ab2..6179c10fb 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java @@ -30,6 +30,7 @@ import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation.DelegationStrategy; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchRequest; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchResponse; @@ -48,15 +49,15 @@ * * @author mateusmolina */ -public class HierarchalAasRegistryStorage implements AasRegistryStorage { +public class HierarchicalAasRegistryStorage implements AasRegistryStorage { private final AasRegistryStorage decorated; + + private final DelegationStrategy delegationStrategy; - private final RegistryAndDiscoveryInterfaceApi delegatedClientApi; - - public HierarchalAasRegistryStorage(AasRegistryStorage decorated, String delegatedUrl) { + public HierarchicalAasRegistryStorage(AasRegistryStorage decorated, DelegationStrategy delegationStrategy) { this.decorated = decorated; - this.delegatedClientApi = new RegistryAndDiscoveryInterfaceApi(delegatedUrl); + this.delegationStrategy = delegationStrategy; } @Override @@ -70,7 +71,7 @@ public AssetAdministrationShellDescriptor getAasDescriptor(String aasDescriptorI return decorated.getAasDescriptor(aasDescriptorId); } catch (AasDescriptorNotFoundException e) { try { - return AasRegistryModelMapper.mapEqModel(delegatedClientApi.getAssetAdministrationShellDescriptorById(aasDescriptorId)); + return AasRegistryModelMapper.mapEqModel(getDelegatedRegistryApi(aasDescriptorId).getAssetAdministrationShellDescriptorById(aasDescriptorId)); } catch (ApiException e1) { throw AasRegistryModelMapper.mapApiException(e1, aasDescriptorId); } @@ -103,7 +104,7 @@ public SubmodelDescriptor getSubmodel(String aasDescriptorId, String submodelId) return decorated.getSubmodel(aasDescriptorId, submodelId); } catch (AasDescriptorNotFoundException e) { try { - return AasRegistryModelMapper.mapEqModel(delegatedClientApi.getSubmodelDescriptorByIdThroughSuperpath(aasDescriptorId, submodelId)); + return AasRegistryModelMapper.mapEqModel(getDelegatedRegistryApi(aasDescriptorId).getSubmodelDescriptorByIdThroughSuperpath(aasDescriptorId, submodelId)); } catch (ApiException e1) { throw AasRegistryModelMapper.mapApiException(e1, aasDescriptorId, submodelId); } @@ -134,5 +135,9 @@ public Set clear() { public ShellDescriptorSearchResponse searchAasDescriptors(ShellDescriptorSearchRequest request) { return decorated.searchAasDescriptors(request); } - + + private RegistryAndDiscoveryInterfaceApi getDelegatedRegistryApi(String aasId) { + String delegationUrl = delegationStrategy.buildDelegatedRegistryUrl(aasId).orElseThrow(() -> new AasDescriptorNotFoundException(aasId)); + return new RegistryAndDiscoveryInterfaceApi(delegationUrl); + } } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java index beab5bf59..df7496a20 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java @@ -25,17 +25,24 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; +import java.util.Optional; + /** - * Defines a strategy for building the DelegationUrl + * DelegationStrategy * * @author mateusmolina * */ +@FunctionalInterface public interface DelegationStrategy { /** - * Builds the URL for the delegation AAS Registry - * - * @return URL of the registry, to which the request will be delegated + * Builds the URL for the delegation AAS Registry. + * + * @param aasId + * The ID of the AAS for which the delegated registry URL is to be + * built. + * @return An Optional containing the delegated AAS Registry URL if it can be + * constructed, or an empty Optional otherwise. */ - public String buildDelegationUrl(); + public Optional buildDelegatedRegistryUrl(String aasId); } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java similarity index 59% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java index bc5bf6a24..0e3d33861 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DirectUrlDelegationStrategy.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java @@ -25,24 +25,60 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Optional; + import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchicalAasRegistryFeature; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** - * Generates delegation URL based on value of delegatedUrl property + * Generates delegation URL based on value of the prefix attribute. Default + * value is 'registry'. * * @author mateusmolina * */ @Component -public class DirectUrlDelegationStrategy implements DelegationStrategy { - @Value("${" + HierarchicalAasRegistryFeature.FEATURENAME + ".delegatedUrl}") - private String delegatedUrl; +public class PrefixDelegationStrategy implements DelegationStrategy { + private final String prefix; + + public PrefixDelegationStrategy(@Value("${" + HierarchicalAasRegistryFeature.FEATURENAME + ".prefix:registry}") String prefix) { + this.prefix = prefix; + } @Override - public String buildDelegationUrl() { - return delegatedUrl; + public Optional buildDelegatedRegistryUrl(String aasId) { + return Optional.ofNullable(aasId).map(this::extractDelegationUrl); } -} + private String extractDelegationUrl(String aasId) { + URL url; + + try { + url = new URL(aasId); + } catch (MalformedURLException e) { + return null; + } + + String host = url.getHost(); + int port = url.getPort(); + String protocol = url.getProtocol(); + + StringBuilder registryUrl = new StringBuilder(); + + registryUrl.append(protocol).append("://"); + + if (prefix != null && !prefix.isBlank()) + registryUrl.append(prefix).append("."); + + registryUrl.append(host); + + if (port != -1) { + registryUrl.append(":").append(port); + } + + return registryUrl.toString(); + } +} \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java index f3d1999de..6aba89cf0 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java @@ -47,7 +47,7 @@ class DummyDescriptorFactory { static final String AASDESCRIPTOR_ID_HIERARCHALONLY = "AASDESCRIPTOR_ID_HIERARCHALONLY"; static final String SMDESCRIPTOR_ID_HIERARCHALONLY = "SMDESCRIPTOR_ID_HIERARCHALONLY"; - static final String AASDESCRIPTOR_ID_DELEGATEDONLY = "AASDESCRIPTOR_ID_DELEGATEDONLY"; + static final String AASDESCRIPTOR_ID_DELEGATEDONLY = "http://localhost:8050/test/aas"; static final String SMDESCRIPTOR_ID_DELEGATEDONLY = "SMDESCRIPTOR_ID_DELEGATEDONLY"; private final String repoBaseUrl; diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java index 1bf76446c..7f5052631 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java @@ -57,13 +57,13 @@ public class TestHierarchicalAasRegistry { private static DummyDescriptorFactory descriptorFactory = new DummyDescriptorFactory(REPO_BASE_URL); private static ConfigurableApplicationContext appContext; - private static AasRegistryStorage aasRegistryHierarchal; + private static AasRegistryStorage aasRegistryHierarchical; @BeforeClass public static void setUp() throws FileNotFoundException, IOException, ApiException { appContext = new SpringApplication(DummyAasRegistryComponent.class).run(new String[] {}); - aasRegistryHierarchal = appContext.getBean(AasRegistryStorage.class); + aasRegistryHierarchical = appContext.getBean(AasRegistryStorage.class); cleanUpDelegatedRegistry(); setupDelegatedRegistry(); @@ -78,7 +78,7 @@ public static void cleanUp() throws ApiException { @Test public void getAasDescriptor_InHierarchal() { - AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchal.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY); + AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchical.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY); AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_HierarchalOnly(); @@ -87,7 +87,7 @@ public void getAasDescriptor_InHierarchal() { @Test public void getAasDescriptor_ThroughDelegated() { - AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchal.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); + AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchical.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_DelegatedOnly(); @@ -96,12 +96,12 @@ public void getAasDescriptor_ThroughDelegated() { @Test public void getNonExistingAasDescriptor() { - assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchal.getAasDescriptor("nonExistingAasDescriptor")); + assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchical.getAasDescriptor("nonExistingAasDescriptor")); } @Test public void getSubmodelDescriptor_InHierarchal() { - SubmodelDescriptor actualDescriptor = aasRegistryHierarchal.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_HIERARCHALONLY); + SubmodelDescriptor actualDescriptor = aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_HIERARCHALONLY); SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_HierarchalOnly(); @@ -110,7 +110,7 @@ public void getSubmodelDescriptor_InHierarchal() { @Test public void getSubmodelDescriptor_ThroughDelegated() { - SubmodelDescriptor actualDescriptor = aasRegistryHierarchal.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_DELEGATEDONLY); + SubmodelDescriptor actualDescriptor = aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_DELEGATEDONLY); SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_DelegatedOnly(); @@ -119,13 +119,13 @@ public void getSubmodelDescriptor_ThroughDelegated() { @Test public void getNonExistingSmDescriptor() { - assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchal.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, "nonExistingSubmodel")); - assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchal.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, "nonExistingSubmodel")); - assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchal.getSubmodel("nonExistingAas", "nonExistingSubmodel")); + assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, "nonExistingSubmodel")); + assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, "nonExistingSubmodel")); + assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchical.getSubmodel("nonExistingAas", "nonExistingSubmodel")); } private static void setupHierarchalRegistry() { - aasRegistryHierarchal.insertAasDescriptor(descriptorFactory.getAasDescriptor_HierarchalOnly()); + aasRegistryHierarchical.insertAasDescriptor(descriptorFactory.getAasDescriptor_HierarchalOnly()); } private static void setupDelegatedRegistry() throws ApiException { diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java new file mode 100644 index 000000000..105e4fc22 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +/** + * PrefixDelegationStrategyTest + * + * @author mateusmolina + * + */ + +public class PrefixDelegationStrategyTest { + + private PrefixDelegationStrategy prefixDelegationStrategy; + + @Before + public void setUp() { + prefixDelegationStrategy = new PrefixDelegationStrategy("registry"); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithPort() { + String aasId = "http://fraunhofer:8042/example/aas"; + String expectedUrl = "http://registry.fraunhofer:8042"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithoutPort() { + String aasId = "http://fraunhofer/example/aas"; + String expectedUrl = "http://registry.fraunhofer"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithTLD() { + String aasId = "http://fraunhofer.com:8080/example/aas"; + String expectedUrl = "http://registry.fraunhofer.com:8080"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_InvalidUrl() { + String aasId = "invalid_url"; + assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).isEmpty()); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithBlankPrefix() { + PrefixDelegationStrategy blankPrefixDelegationStrategy = new PrefixDelegationStrategy(""); + String aasId = "http://fraunhofer.com:8080/example/aas"; + String expectedUrl = "http://fraunhofer.com:8080"; + String actualUrl = blankPrefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_NullAasId() { + assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(null).isEmpty()); + } +} \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml index ae0daf0f7..58a23a247 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml @@ -45,4 +45,4 @@ basyx: feature: hierarchy: enabled: true - delegatedUrl: http://localhost:8050 \ No newline at end of file + prefix: \ No newline at end of file From d97ee547e29cc5ae435cc66afa8efa591e038ffb Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Wed, 5 Jun 2024 15:32:47 +0200 Subject: [PATCH 13/36] Document prefix strategy in README --- .../basyx.aasregistry-feature-hierarchy/Readme.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md index d36590cad..9f496dad9 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md @@ -14,16 +14,18 @@ To enable the Hierarchical AasRegistry Feature, add the following property to yo basyx.aasregistry.feature.hierarchy.enabled=true ``` -The next step is to set up the desired delegation strategy. - ### Delegation Strategy Currently, only one delegation strategy is implemented: -#### Direct Url Delegation Strategy +#### Prefix Delegation Strategy + +Delegates requests based on the `aasDescriptorId` value. If the ID is an URL, a prefix (defaut `registry`) is appended to the URL and used as delegation endpoint. -Delegates requests directly to a URL specified by the `basyx.aasregistry.feature.hierarchy.delegatedUrl` property. For example: +The prefix can be configured by the property `basyx.aasregistry.feature.hierarchy.prefix`. Please refer to the example below: ```properties -basyx.aasregistry.feature.hierarchy.delegatedUrl=http://localhost:8050 +basyx.aasregistry.feature.hierarchy.prefix=registry ``` + +If this property is left with an empty string, no prefix is appended to the URL contained in the `aasDecriptorId`. From 01424df0d816405a7ab6f87ed5932c2698702d78 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Wed, 5 Jun 2024 15:55:18 +0200 Subject: [PATCH 14/36] Implement hierarchical getAllSubmodels --- .../hierarchy/AasRegistryModelMapper.java | 11 ++++++++ .../HierarchicalAasRegistryStorage.java | 10 ++++++- .../TestHierarchicalAasRegistry.java | 26 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java index b62de6b38..791071dfc 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java @@ -25,14 +25,19 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; +import java.util.List; + import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.GetSubmodelDescriptorsResult; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.SubmodelNotFoundException; +import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; /** @@ -64,6 +69,12 @@ static SubmodelDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.aasregistry.c return objectMapper.convertValue(smRegistryDescriptor, SubmodelDescriptor.class); } + static CursorResult> mapEqModel(GetSubmodelDescriptorsResult descriptorResult) { + List submodelDescs = objectMapper.convertValue(descriptorResult.getResult(), new TypeReference>() { + }); + return new CursorResult<>(descriptorResult.getPagingMetadata().getCursor(), submodelDescs); + } + static RuntimeException mapApiException(ApiException e, String aasDescriptorId) { if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND)) return new AasDescriptorNotFoundException(aasDescriptorId); diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java index 6179c10fb..b5008150c 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java @@ -95,7 +95,15 @@ public void removeAasDescriptor(String aasDescriptorId) throws AasDescriptorNotF @Override public CursorResult> getAllSubmodels(String aasDescriptorId, PaginationInfo pRequest) throws AasDescriptorNotFoundException { - return decorated.getAllSubmodels(aasDescriptorId, pRequest); + try { + return decorated.getAllSubmodels(aasDescriptorId, pRequest); + } catch (AasDescriptorNotFoundException e) { + try { + return AasRegistryModelMapper.mapEqModel(getDelegatedRegistryApi(aasDescriptorId).getAllSubmodelDescriptorsThroughSuperpath(aasDescriptorId, pRequest.getLimit(), pRequest.getCursor())); + } catch (ApiException e1) { + throw AasRegistryModelMapper.mapApiException(e1, aasDescriptorId); + } + } } @Override diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java index 7f5052631..a9fb00fa5 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java @@ -30,6 +30,8 @@ import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Arrays; +import java.util.List; import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; @@ -38,6 +40,8 @@ import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.SubmodelNotFoundException; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; +import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -117,6 +121,28 @@ public void getSubmodelDescriptor_ThroughDelegated() { assertEquals(expectedDescriptor, actualDescriptor); } + @Test + public void getAllSubmodelDescriptor_InHierarchal() { + CursorResult> actualDescriptors = aasRegistryHierarchical.getAllSubmodels(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, new PaginationInfo(1, null)); + + SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_HierarchalOnly(); + + List expectedDescriptors = Arrays.asList(expectedDescriptor); + + assertEquals(expectedDescriptors, actualDescriptors.getResult()); + } + + @Test + public void getAllSubmodelDescriptor_ThroughDelegated() { + CursorResult> actualDescriptors = aasRegistryHierarchical.getAllSubmodels(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, new PaginationInfo(1, null)); + + SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_DelegatedOnly(); + + List expectedDescriptors = Arrays.asList(expectedDescriptor); + + assertEquals(expectedDescriptors, actualDescriptors.getResult()); + } + @Test public void getNonExistingSmDescriptor() { assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, "nonExistingSubmodel")); From f17c6cc0dfdc54b012d6ccd2d41a0eccc59c3fac Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Wed, 5 Jun 2024 15:59:13 +0200 Subject: [PATCH 15/36] Improve test understandability --- .../hierarchy/DummyDescriptorFactory.java | 12 +++--- .../TestHierarchicalAasRegistry.java | 42 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java index 6aba89cf0..113402731 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java @@ -44,8 +44,8 @@ * */ class DummyDescriptorFactory { - static final String AASDESCRIPTOR_ID_HIERARCHALONLY = "AASDESCRIPTOR_ID_HIERARCHALONLY"; - static final String SMDESCRIPTOR_ID_HIERARCHALONLY = "SMDESCRIPTOR_ID_HIERARCHALONLY"; + static final String AASDESCRIPTOR_ID_ROOTONLY = "AASDESCRIPTOR_ID_ROOTONLY"; + static final String SMDESCRIPTOR_ID_ROOTONLY = "SMDESCRIPTOR_ID_ROOTONLY"; static final String AASDESCRIPTOR_ID_DELEGATEDONLY = "http://localhost:8050/test/aas"; static final String SMDESCRIPTOR_ID_DELEGATEDONLY = "SMDESCRIPTOR_ID_DELEGATEDONLY"; @@ -56,12 +56,12 @@ class DummyDescriptorFactory { this.repoBaseUrl = repoBaseUrl; } - AssetAdministrationShellDescriptor getAasDescriptor_HierarchalOnly() { - return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_HIERARCHALONLY, buildIdShort(AASDESCRIPTOR_ID_HIERARCHALONLY), getSmDescriptor_HierarchalOnly()); + AssetAdministrationShellDescriptor getAasDescriptor_RootOnly() { + return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_ROOTONLY, buildIdShort(AASDESCRIPTOR_ID_ROOTONLY), getSmDescriptor_RootOnly()); } - SubmodelDescriptor getSmDescriptor_HierarchalOnly() { - return createDummySubmodelDescriptor(repoBaseUrl, SMDESCRIPTOR_ID_HIERARCHALONLY, buildIdShort(SMDESCRIPTOR_ID_HIERARCHALONLY)); + SubmodelDescriptor getSmDescriptor_RootOnly() { + return createDummySubmodelDescriptor(repoBaseUrl, SMDESCRIPTOR_ID_ROOTONLY, buildIdShort(SMDESCRIPTOR_ID_ROOTONLY)); } AssetAdministrationShellDescriptor getAasDescriptor_DelegatedOnly() { diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java index a9fb00fa5..62267e612 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java @@ -61,17 +61,17 @@ public class TestHierarchicalAasRegistry { private static DummyDescriptorFactory descriptorFactory = new DummyDescriptorFactory(REPO_BASE_URL); private static ConfigurableApplicationContext appContext; - private static AasRegistryStorage aasRegistryHierarchical; + private static AasRegistryStorage rootAasRegistry; @BeforeClass public static void setUp() throws FileNotFoundException, IOException, ApiException { appContext = new SpringApplication(DummyAasRegistryComponent.class).run(new String[] {}); - aasRegistryHierarchical = appContext.getBean(AasRegistryStorage.class); + rootAasRegistry = appContext.getBean(AasRegistryStorage.class); cleanUpDelegatedRegistry(); setupDelegatedRegistry(); - setupHierarchalRegistry(); + setupRootRegistry(); } @AfterClass @@ -81,17 +81,17 @@ public static void cleanUp() throws ApiException { } @Test - public void getAasDescriptor_InHierarchal() { - AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchical.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY); + public void getAasDescriptor_InRoot() { + AssetAdministrationShellDescriptor actualDescriptor = rootAasRegistry.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY); - AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_HierarchalOnly(); + AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_RootOnly(); assertEquals(expectedDescriptor, actualDescriptor); } @Test public void getAasDescriptor_ThroughDelegated() { - AssetAdministrationShellDescriptor actualDescriptor = aasRegistryHierarchical.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); + AssetAdministrationShellDescriptor actualDescriptor = rootAasRegistry.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_DelegatedOnly(); @@ -100,21 +100,21 @@ public void getAasDescriptor_ThroughDelegated() { @Test public void getNonExistingAasDescriptor() { - assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchical.getAasDescriptor("nonExistingAasDescriptor")); + assertThrows(AasDescriptorNotFoundException.class, () -> rootAasRegistry.getAasDescriptor("nonExistingAasDescriptor")); } @Test - public void getSubmodelDescriptor_InHierarchal() { - SubmodelDescriptor actualDescriptor = aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_HIERARCHALONLY); + public void getSubmodelDescriptor_InRoot() { + SubmodelDescriptor actualDescriptor = rootAasRegistry.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_ROOTONLY); - SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_HierarchalOnly(); + SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_RootOnly(); assertEquals(expectedDescriptor, actualDescriptor); } @Test public void getSubmodelDescriptor_ThroughDelegated() { - SubmodelDescriptor actualDescriptor = aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_DELEGATEDONLY); + SubmodelDescriptor actualDescriptor = rootAasRegistry.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_DELEGATEDONLY); SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_DelegatedOnly(); @@ -122,10 +122,10 @@ public void getSubmodelDescriptor_ThroughDelegated() { } @Test - public void getAllSubmodelDescriptor_InHierarchal() { - CursorResult> actualDescriptors = aasRegistryHierarchical.getAllSubmodels(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, new PaginationInfo(1, null)); + public void getAllSubmodelDescriptor_InRoot() { + CursorResult> actualDescriptors = rootAasRegistry.getAllSubmodels(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, new PaginationInfo(1, null)); - SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_HierarchalOnly(); + SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_RootOnly(); List expectedDescriptors = Arrays.asList(expectedDescriptor); @@ -134,7 +134,7 @@ public void getAllSubmodelDescriptor_InHierarchal() { @Test public void getAllSubmodelDescriptor_ThroughDelegated() { - CursorResult> actualDescriptors = aasRegistryHierarchical.getAllSubmodels(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, new PaginationInfo(1, null)); + CursorResult> actualDescriptors = rootAasRegistry.getAllSubmodels(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, new PaginationInfo(1, null)); SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_DelegatedOnly(); @@ -145,13 +145,13 @@ public void getAllSubmodelDescriptor_ThroughDelegated() { @Test public void getNonExistingSmDescriptor() { - assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_HIERARCHALONLY, "nonExistingSubmodel")); - assertThrows(SubmodelNotFoundException.class, () -> aasRegistryHierarchical.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, "nonExistingSubmodel")); - assertThrows(AasDescriptorNotFoundException.class, () -> aasRegistryHierarchical.getSubmodel("nonExistingAas", "nonExistingSubmodel")); + assertThrows(SubmodelNotFoundException.class, () -> rootAasRegistry.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, "nonExistingSubmodel")); + assertThrows(SubmodelNotFoundException.class, () -> rootAasRegistry.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, "nonExistingSubmodel")); + assertThrows(AasDescriptorNotFoundException.class, () -> rootAasRegistry.getSubmodel("nonExistingAas", "nonExistingSubmodel")); } - private static void setupHierarchalRegistry() { - aasRegistryHierarchical.insertAasDescriptor(descriptorFactory.getAasDescriptor_HierarchalOnly()); + private static void setupRootRegistry() { + rootAasRegistry.insertAasDescriptor(descriptorFactory.getAasDescriptor_RootOnly()); } private static void setupDelegatedRegistry() throws ApiException { From 8e82728ac223b663c741e593aaa242e62ad3745f Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Thu, 6 Jun 2024 08:10:14 +0200 Subject: [PATCH 16/36] Add feature to parent/components poms --- .../basyx.aasregistry-service-release-log-mem/pom.xml | 4 ++++ .../basyx.aasregistry-service-release-log-mongodb/pom.xml | 4 ++++ basyx.aasregistry/pom.xml | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/basyx.aasregistry/basyx.aasregistry-service-release-log-mem/pom.xml b/basyx.aasregistry/basyx.aasregistry-service-release-log-mem/pom.xml index 83a635fad..8fdef0705 100644 --- a/basyx.aasregistry/basyx.aasregistry-service-release-log-mem/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-service-release-log-mem/pom.xml @@ -25,6 +25,10 @@ org.eclipse.digitaltwin.basyx basyx.aasregistry-feature-authorization + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-feature-hierarchy + org.eclipse.digitaltwin.basyx basyx.authorization diff --git a/basyx.aasregistry/basyx.aasregistry-service-release-log-mongodb/pom.xml b/basyx.aasregistry/basyx.aasregistry-service-release-log-mongodb/pom.xml index 396b026ea..6e2193f42 100644 --- a/basyx.aasregistry/basyx.aasregistry-service-release-log-mongodb/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-service-release-log-mongodb/pom.xml @@ -29,6 +29,10 @@ org.eclipse.digitaltwin.basyx basyx.aasregistry-feature-authorization + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-feature-hierarchy + org.eclipse.digitaltwin.basyx basyx.aasregistry-service-mongodb-storage diff --git a/basyx.aasregistry/pom.xml b/basyx.aasregistry/pom.xml index 172f16be4..9b030880b 100644 --- a/basyx.aasregistry/pom.xml +++ b/basyx.aasregistry/pom.xml @@ -159,6 +159,11 @@ basyx.aasregistry-feature-authorization ${project.version} + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-feature-hierarchy + ${project.version} + org.eclipse.digitaltwin.basyx basyx.aasregistry-service-basetests From d1238c07c62f6926fe78eec0e501aebaa493fb95 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Thu, 6 Jun 2024 16:51:34 +0200 Subject: [PATCH 17/36] Add example module --- .../Dockerfile | 11 +++++ .../docker-compose.yml | 28 +++++++++++ .../pom.xml | 36 ++++++++++++++ .../src/main/resources/application.yml | 47 +++++++++++++++++++ ...ry.java => HierarchicalAasRegistryIT.java} | 2 +- basyx.aasregistry/pom.xml | 1 + 6 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Dockerfile create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/docker-compose.yml create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/pom.xml create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application.yml rename basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/{TestHierarchicalAasRegistry.java => HierarchicalAasRegistryIT.java} (99%) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Dockerfile b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Dockerfile new file mode 100644 index 000000000..f0291e92d --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Dockerfile @@ -0,0 +1,11 @@ +FROM amazoncorretto:17 +USER nobody +WORKDIR /application +ARG JAR_FILE=target/*-exec.jar +COPY ${JAR_FILE} basyxExecutable.jar +COPY src/main/resources/application.yml application.yml +ARG PORT=8081 +ENV SERVER_PORT=${PORT} +EXPOSE ${SERVER_PORT} +HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=15s CMD curl --fail http://localhost:${SERVER_PORT}/actuator/health || exit 1 +ENTRYPOINT ["java","-jar","basyxExecutable.jar"] diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/docker-compose.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/docker-compose.yml new file mode 100644 index 000000000..f321070c4 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3.9" +services: + + aas-registry-root: + build: + context: . + container_name: aas-registry-root + ports: + - "8051:8080" + environment: + SERVER_SERVLET_CONTEXT_PATH: / + networks: + - basyx-aasregistry-feature-hierarchy-example + + registry.delegated-aas-registry: + image: eclipsebasyx/aas-registry-log-mem:2.0.0-SNAPSHOT + container_name: registry.delegated-aas-registry + ports: + - "8052:8080" + environment: + SERVER_SERVLET_CONTEXT_PATH: / + networks: + - basyx-aasregistry-feature-hierarchy-example + +networks: + basyx-aasregistry-feature-hierarchy-example: + name: basyx-aasregistry-feature-hierarchy-example + driver: bridge diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/pom.xml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/pom.xml new file mode 100644 index 000000000..c83a34c6f --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + + org.eclipse.digitaltwin.basyx + basyx.aasregistry + ${revision} + + + basyx.aasregistry-feature-hierarchy-example + + + org.eclipse.digitaltwin.basyx.aasregistry.service.OpenApiGeneratorApplication + + + + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-service-release-log-mem + ${project.version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + exec + + + + + \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application.yml new file mode 100644 index 000000000..0ea32089a --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application.yml @@ -0,0 +1,47 @@ +--- +events: + sink: log +description: + profiles: https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRegistryServiceSpecification/SSP-001 +springdoc: + api-docs: + path: /api-docs +springfox: + documentation: + enabled: true + # open-api.v3.path: /api-docs +management: + endpoints: + web: + exposure: + include: "health,metrics" +logging: + level: + root: INFO +server: + shutdown: graceful + port: 8080 + error: + whitelabel: + enabled: false +spring: + application: + name: Basyx Aas Registry + jackson: + date-format: org.eclipse.digitaltwin.basyx.aasregistry.service.RFC3339DateFormat + serialization: + WRITE_DATES_AS_TIMESTAMPS: false + profiles: + active: logEvents,inMemoryStorage + +registry: + type: inMemory + +basyx: + cors: + allowed-origins: "*" + allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" + aasregistry: + feature: + hierarchy: + enabled: true diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryIT.java similarity index 99% rename from basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java rename to basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryIT.java index 62267e612..87e9d114d 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/TestHierarchicalAasRegistry.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryIT.java @@ -54,7 +54,7 @@ * @author mateusmolina * */ -public class TestHierarchicalAasRegistry { +abstract class HierarchicalAasRegistryIT { private static final String DELEGATED_REGISTRY_URL = "http://localhost:8050"; private static final String REPO_BASE_URL = "http://127.0.0.1:8080"; diff --git a/basyx.aasregistry/pom.xml b/basyx.aasregistry/pom.xml index 9b030880b..2cba1e203 100644 --- a/basyx.aasregistry/pom.xml +++ b/basyx.aasregistry/pom.xml @@ -55,6 +55,7 @@ basyx.aasregistry-service-release-kafka-mongodb basyx.aasregistry-feature-authorization basyx.aasregistry-feature-hierarchy + basyx.aasregistry-feature-hierarchy-example From 03d2b15908c1aaeba7c324ad688f28d11a85337b Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Fri, 14 Jun 2024 09:05:34 +0200 Subject: [PATCH 18/36] Fix feature not being found during storage creation --- .../feature/hierarchy/HierarchicalAasRegistryFeature.java | 7 +++++-- .../hierarchy/delegation/PrefixDelegationStrategy.java | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java index 46caa06b8..8bf39b856 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java @@ -30,6 +30,7 @@ import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorageFeature; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** @@ -43,11 +44,13 @@ * @author mateusmolina */ @Component -@ConditionalOnExpression("${" + HierarchicalAasRegistryFeature.FEATURENAME + ".enabled:false}") +@ConditionalOnExpression("${" + HierarchicalAasRegistryFeature.ENABLED_PROPERTY_KEY + ":false}") +@Order(1) public class HierarchicalAasRegistryFeature implements AasRegistryStorageFeature { public static final String FEATURENAME = "basyx.aasregistry.feature.hierarchy"; + public static final String ENABLED_PROPERTY_KEY = FEATURENAME + ".enabled"; - @Value("${" + FEATURENAME + ".enabled:false}") + @Value("${" + ENABLED_PROPERTY_KEY + "}") private boolean enabled; private DelegationStrategy delegationStrategy; diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java index 0e3d33861..ca2713a6e 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java @@ -42,9 +42,10 @@ */ @Component public class PrefixDelegationStrategy implements DelegationStrategy { + public static final String PREFIX_PROPERTY_KEY = HierarchicalAasRegistryFeature.FEATURENAME + ".prefix"; private final String prefix; - public PrefixDelegationStrategy(@Value("${" + HierarchicalAasRegistryFeature.FEATURENAME + ".prefix:registry}") String prefix) { + public PrefixDelegationStrategy(@Value("${" + PREFIX_PROPERTY_KEY + ":registry}") String prefix) { this.prefix = prefix; } From 76a47ebd067b480c64b43ed46e5f89405eebbfca Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Fri, 14 Jun 2024 09:19:25 +0200 Subject: [PATCH 19/36] Refactor tests to use http for both root and delegated regs. --- .../hierarchy/DummyDescriptorFactory.java | 42 ++--- .../hierarchy/HierarchicalAasRegistryIT.java | 169 ------------------ .../HierarchicalAasRegistryTestSuite.java | 160 +++++++++++++++++ .../LocalhostHierarchicalAasRegistryTest.java | 78 ++++++++ .../src/test/resources/application.yml | 4 +- 5 files changed, 261 insertions(+), 192 deletions(-) delete mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryIT.java create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java index 113402731..42ecf4c79 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java @@ -27,14 +27,13 @@ import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; import java.util.List; -import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; -import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetKind; -import org.eclipse.digitaltwin.basyx.aasregistry.model.Endpoint; -import org.eclipse.digitaltwin.basyx.aasregistry.model.ProtocolInformation; -import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetKind; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.Endpoint; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.ProtocolInformation; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor; import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier; /** @@ -43,37 +42,38 @@ * @author mateusmolina * */ -class DummyDescriptorFactory { +public class DummyDescriptorFactory { static final String AASDESCRIPTOR_ID_ROOTONLY = "AASDESCRIPTOR_ID_ROOTONLY"; static final String SMDESCRIPTOR_ID_ROOTONLY = "SMDESCRIPTOR_ID_ROOTONLY"; - static final String AASDESCRIPTOR_ID_DELEGATEDONLY = "http://localhost:8050/test/aas"; + static String AASDESCRIPTOR_ID_DELEGATEDONLY; static final String SMDESCRIPTOR_ID_DELEGATEDONLY = "SMDESCRIPTOR_ID_DELEGATEDONLY"; - private final String repoBaseUrl; + static String REPO_BASE_URL; - DummyDescriptorFactory(String repoBaseUrl) { - this.repoBaseUrl = repoBaseUrl; + public DummyDescriptorFactory(String repoBaseUrl, String delegatedAasId) { + AASDESCRIPTOR_ID_DELEGATEDONLY = delegatedAasId; + REPO_BASE_URL = repoBaseUrl; } AssetAdministrationShellDescriptor getAasDescriptor_RootOnly() { - return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_ROOTONLY, buildIdShort(AASDESCRIPTOR_ID_ROOTONLY), getSmDescriptor_RootOnly()); + return createDummyDescriptor(REPO_BASE_URL, AASDESCRIPTOR_ID_ROOTONLY, buildIdShort(AASDESCRIPTOR_ID_ROOTONLY), getSmDescriptor_RootOnly()); } SubmodelDescriptor getSmDescriptor_RootOnly() { - return createDummySubmodelDescriptor(repoBaseUrl, SMDESCRIPTOR_ID_ROOTONLY, buildIdShort(SMDESCRIPTOR_ID_ROOTONLY)); + return createDummySubmodelDescriptor(REPO_BASE_URL, SMDESCRIPTOR_ID_ROOTONLY, buildIdShort(SMDESCRIPTOR_ID_ROOTONLY)); } AssetAdministrationShellDescriptor getAasDescriptor_DelegatedOnly() { - return createDummyDescriptor(repoBaseUrl, AASDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(AASDESCRIPTOR_ID_DELEGATEDONLY), getSmDescriptor_DelegatedOnly()); + return createDummyDescriptor(REPO_BASE_URL, AASDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(AASDESCRIPTOR_ID_DELEGATEDONLY), getSmDescriptor_DelegatedOnly()); } SubmodelDescriptor getSmDescriptor_DelegatedOnly() { - return createDummySubmodelDescriptor(repoBaseUrl, SMDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(SMDESCRIPTOR_ID_DELEGATEDONLY)); + return createDummySubmodelDescriptor(REPO_BASE_URL, SMDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(SMDESCRIPTOR_ID_DELEGATEDONLY)); } private static AssetAdministrationShellDescriptor createDummyDescriptor(String baseUrl, String shellId, String shellIdShort, SubmodelDescriptor submodelDescriptor) { - AssetAdministrationShellDescriptor descriptor = new AssetAdministrationShellDescriptor(shellId); + AssetAdministrationShellDescriptor descriptor = new AssetAdministrationShellDescriptor().id(shellId); descriptor.setIdShort(shellIdShort); descriptor.setAssetKind(AssetKind.TYPE); descriptor.setAssetType("TestAsset"); @@ -86,9 +86,9 @@ private static AssetAdministrationShellDescriptor createDummyDescriptor(String b } private static SubmodelDescriptor createDummySubmodelDescriptor(String baseUrl, String submodelId, String submodelIdShort) { - SubmodelDescriptor descriptor = new SubmodelDescriptor(submodelId, new ArrayList<>()); + SubmodelDescriptor descriptor = new SubmodelDescriptor().id(submodelId); descriptor.setIdShort(submodelIdShort); - descriptor.setEndpoints(List.of(new Endpoint("AAS-3.0", createSmProtocolInformation(baseUrl, submodelId)))); + descriptor.setEndpoints(List.of(new Endpoint()._interface("AAS-3.0").protocolInformation(createSmProtocolInformation(baseUrl, submodelId)))); return descriptor; } @@ -96,14 +96,14 @@ private static SubmodelDescriptor createDummySubmodelDescriptor(String baseUrl, private static void setEndpointItem(String baseUrl, String shellId, AssetAdministrationShellDescriptor descriptor) { ProtocolInformation protocolInformation = createProtocolInformation(baseUrl, shellId); - Endpoint endpoint = new Endpoint("AAS-3.0", protocolInformation); + Endpoint endpoint = new Endpoint()._interface("AAS-3.0").protocolInformation(protocolInformation); descriptor.addEndpointsItem(endpoint); } private static ProtocolInformation createProtocolInformation(String baseUrl, String shellId) { String href = String.format("%s/%s", baseUrl + "/shells", Base64UrlEncodedIdentifier.encodeIdentifier(shellId)); - ProtocolInformation protocolInformation = new ProtocolInformation(href); + ProtocolInformation protocolInformation = new ProtocolInformation().href(href); protocolInformation.endpointProtocol(getProtocol(href)); return protocolInformation; @@ -112,7 +112,7 @@ private static ProtocolInformation createProtocolInformation(String baseUrl, Str private static ProtocolInformation createSmProtocolInformation(String baseUrl, String smId) { String href = String.format("%s/%s", baseUrl + "/submodels", Base64UrlEncodedIdentifier.encodeIdentifier(smId)); - ProtocolInformation protocolInformation = new ProtocolInformation(href); + ProtocolInformation protocolInformation = new ProtocolInformation().href(href); protocolInformation.endpointProtocol(getProtocol(href)); return protocolInformation; diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryIT.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryIT.java deleted file mode 100644 index 87e9d114d..000000000 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryIT.java +++ /dev/null @@ -1,169 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; - -import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; -import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; -import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; -import org.eclipse.digitaltwin.basyx.aasregistry.model.SubmodelDescriptor; -import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.AasDescriptorNotFoundException; -import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.SubmodelNotFoundException; -import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; -import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; -import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.springframework.boot.SpringApplication; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * Test for {@link HierarchicalAasRegistryFeature} - * - * @author mateusmolina - * - */ -abstract class HierarchicalAasRegistryIT { - private static final String DELEGATED_REGISTRY_URL = "http://localhost:8050"; - private static final String REPO_BASE_URL = "http://127.0.0.1:8080"; - - private static DummyDescriptorFactory descriptorFactory = new DummyDescriptorFactory(REPO_BASE_URL); - - private static ConfigurableApplicationContext appContext; - private static AasRegistryStorage rootAasRegistry; - - @BeforeClass - public static void setUp() throws FileNotFoundException, IOException, ApiException { - appContext = new SpringApplication(DummyAasRegistryComponent.class).run(new String[] {}); - - rootAasRegistry = appContext.getBean(AasRegistryStorage.class); - - cleanUpDelegatedRegistry(); - setupDelegatedRegistry(); - setupRootRegistry(); - } - - @AfterClass - public static void cleanUp() throws ApiException { - cleanUpDelegatedRegistry(); - appContext.close(); - } - - @Test - public void getAasDescriptor_InRoot() { - AssetAdministrationShellDescriptor actualDescriptor = rootAasRegistry.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY); - - AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_RootOnly(); - - assertEquals(expectedDescriptor, actualDescriptor); - } - - @Test - public void getAasDescriptor_ThroughDelegated() { - AssetAdministrationShellDescriptor actualDescriptor = rootAasRegistry.getAasDescriptor(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); - - AssetAdministrationShellDescriptor expectedDescriptor = descriptorFactory.getAasDescriptor_DelegatedOnly(); - - assertEquals(expectedDescriptor, actualDescriptor); - } - - @Test - public void getNonExistingAasDescriptor() { - assertThrows(AasDescriptorNotFoundException.class, () -> rootAasRegistry.getAasDescriptor("nonExistingAasDescriptor")); - } - - @Test - public void getSubmodelDescriptor_InRoot() { - SubmodelDescriptor actualDescriptor = rootAasRegistry.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_ROOTONLY); - - SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_RootOnly(); - - assertEquals(expectedDescriptor, actualDescriptor); - } - - @Test - public void getSubmodelDescriptor_ThroughDelegated() { - SubmodelDescriptor actualDescriptor = rootAasRegistry.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_DELEGATEDONLY); - - SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_DelegatedOnly(); - - assertEquals(expectedDescriptor, actualDescriptor); - } - - @Test - public void getAllSubmodelDescriptor_InRoot() { - CursorResult> actualDescriptors = rootAasRegistry.getAllSubmodels(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, new PaginationInfo(1, null)); - - SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_RootOnly(); - - List expectedDescriptors = Arrays.asList(expectedDescriptor); - - assertEquals(expectedDescriptors, actualDescriptors.getResult()); - } - - @Test - public void getAllSubmodelDescriptor_ThroughDelegated() { - CursorResult> actualDescriptors = rootAasRegistry.getAllSubmodels(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, new PaginationInfo(1, null)); - - SubmodelDescriptor expectedDescriptor = descriptorFactory.getSmDescriptor_DelegatedOnly(); - - List expectedDescriptors = Arrays.asList(expectedDescriptor); - - assertEquals(expectedDescriptors, actualDescriptors.getResult()); - } - - @Test - public void getNonExistingSmDescriptor() { - assertThrows(SubmodelNotFoundException.class, () -> rootAasRegistry.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, "nonExistingSubmodel")); - assertThrows(SubmodelNotFoundException.class, () -> rootAasRegistry.getSubmodel(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, "nonExistingSubmodel")); - assertThrows(AasDescriptorNotFoundException.class, () -> rootAasRegistry.getSubmodel("nonExistingAas", "nonExistingSubmodel")); - } - - private static void setupRootRegistry() { - rootAasRegistry.insertAasDescriptor(descriptorFactory.getAasDescriptor_RootOnly()); - } - - private static void setupDelegatedRegistry() throws ApiException { - RegistryAndDiscoveryInterfaceApi clientFacade = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); - AssetAdministrationShellDescriptor descriptor = descriptorFactory.getAasDescriptor_DelegatedOnly(); - - clientFacade.postAssetAdministrationShellDescriptor(AasRegistryModelMapper.mapEqModel(descriptor)); - } - - private static void cleanUpDelegatedRegistry() throws ApiException { - RegistryAndDiscoveryInterfaceApi clientFacade = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); - - clientFacade.deleteAllShellDescriptors(); - } -} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java new file mode 100644 index 000000000..c29ac8aa8 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; +import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.GetSubmodelDescriptorsResult; +import org.eclipse.digitaltwin.basyx.aasregistry.client.model.SubmodelDescriptor; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpStatus; + +/** + * Test for {@link HierarchicalAasRegistryFeature} + * + * @author mateusmolina + * + */ +public abstract class HierarchicalAasRegistryTestSuite { + + protected abstract RegistryAndDiscoveryInterfaceApi getRootRegistryApi(); + protected abstract RegistryAndDiscoveryInterfaceApi getDelegatedRegistryApi(); + protected abstract DummyDescriptorFactory getDescriptorFactory(); + + @Before + public void setUp() throws FileNotFoundException, IOException, ApiException { + cleanUpRegistries(); + setupDelegatedRegistry(); + setupRootRegistry(); + } + + @Test + public void getAasDescriptor_InRoot() throws ApiException { + AssetAdministrationShellDescriptor actualDescriptor = getRootRegistryApi().getAssetAdministrationShellDescriptorById(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY); + + AssetAdministrationShellDescriptor expectedDescriptor = getDescriptorFactory().getAasDescriptor_RootOnly(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getAasDescriptor_ThroughDelegated() throws ApiException { + AssetAdministrationShellDescriptor actualDescriptor = getRootRegistryApi().getAssetAdministrationShellDescriptorById(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); + + AssetAdministrationShellDescriptor expectedDescriptor = getDescriptorFactory().getAasDescriptor_DelegatedOnly(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getNonExistingAasDescriptor() { + ApiException exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getAssetAdministrationShellDescriptorById("nonExistingAasDescriptor")); + assertHttpCodeIsNotFound(exception); + } + + @Test + public void getSubmodelDescriptor_InRoot() throws ApiException { + SubmodelDescriptor actualDescriptor = getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_ROOTONLY); + + SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getSmDescriptor_RootOnly(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getSubmodelDescriptor_ThroughDelegated() throws ApiException { + SubmodelDescriptor actualDescriptor = getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_DELEGATEDONLY); + + SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getSmDescriptor_DelegatedOnly(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getAllSubmodelDescriptor_InRoot() throws ApiException { + GetSubmodelDescriptorsResult actualDescriptors = getRootRegistryApi().getAllSubmodelDescriptorsThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, 1, null); + + SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getSmDescriptor_RootOnly(); + + List expectedDescriptors = Arrays.asList(expectedDescriptor); + + assertEquals(expectedDescriptors, actualDescriptors.getResult()); + } + + @Test + public void getAllSubmodelDescriptor_ThroughDelegated() throws ApiException { + getDescriptorFactory(); + GetSubmodelDescriptorsResult actualDescriptors = getRootRegistryApi().getAllSubmodelDescriptorsThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, 1, null); + + SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getSmDescriptor_DelegatedOnly(); + + List expectedDescriptors = Arrays.asList(expectedDescriptor); + + assertEquals(expectedDescriptors, actualDescriptors.getResult()); + } + + @Test + public void getNonExistingSmDescriptor() { + ApiException exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, + "nonExistingSubmodel")); + assertHttpCodeIsNotFound(exception); + + exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, "nonExistingSubmodel")); + assertHttpCodeIsNotFound(exception); + + exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath("nonExistingAas", "nonExistingSubmodel")); + assertHttpCodeIsNotFound(exception); + } + + private void setupRootRegistry() throws ApiException { + getRootRegistryApi().postAssetAdministrationShellDescriptor(getDescriptorFactory().getAasDescriptor_RootOnly()); + } + + private void setupDelegatedRegistry() throws ApiException { + AssetAdministrationShellDescriptor descriptor = getDescriptorFactory().getAasDescriptor_DelegatedOnly(); + + getDelegatedRegistryApi().postAssetAdministrationShellDescriptor(descriptor); + } + + private void cleanUpRegistries() throws ApiException { + getRootRegistryApi().deleteAllShellDescriptors(); + getDelegatedRegistryApi().deleteAllShellDescriptors(); + } + + private static void assertHttpCodeIsNotFound(ApiException e) { + assertEquals(HttpStatus.NOT_FOUND.value(), e.getCode()); + } +} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java new file mode 100644 index 000000000..61038538c --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; + +import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * LocalhostHierarchicalAasRegistryTest + * + * @author mateusmolina + * + */ +public class LocalhostHierarchicalAasRegistryTest extends HierarchicalAasRegistryTestSuite { + + private static final String ROOT_REGISTRY_URL = "http://localhost:8081"; + private static final String DELEGATED_REGISTRY_URL = "http://localhost:8050"; + + private static final String REPO_BASE_URL = "http://localhost:8080"; + private static final String DELEGATED_AASID = "http://localhost:8050/test/aas"; + + private static final RegistryAndDiscoveryInterfaceApi rootRegistryApi = new RegistryAndDiscoveryInterfaceApi(ROOT_REGISTRY_URL); + private static final RegistryAndDiscoveryInterfaceApi delegatedRegistryApi = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); + + private static ConfigurableApplicationContext appContext; + + @BeforeClass + public static void setupRootRegistry() { + appContext = new SpringApplication(DummyAasRegistryComponent.class).run(new String[] {}); + } + + @AfterClass + public static void tearDownRootRegistry() { + appContext.close(); + } + + @Override + protected RegistryAndDiscoveryInterfaceApi getRootRegistryApi() { + return rootRegistryApi; + } + + @Override + protected RegistryAndDiscoveryInterfaceApi getDelegatedRegistryApi() { + return delegatedRegistryApi; + } + + @Override + protected DummyDescriptorFactory getDescriptorFactory() { + return new DummyDescriptorFactory(REPO_BASE_URL, DELEGATED_AASID); + } + +} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml index 58a23a247..31949762c 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml @@ -20,7 +20,7 @@ logging: root: INFO server: shutdown: graceful - port: 8080 + port: 8081 error: whitelabel: enabled: false @@ -45,4 +45,4 @@ basyx: feature: hierarchy: enabled: true - prefix: \ No newline at end of file + prefix: From ec5e244029fd071377817b43251c870e9f0d2630 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Fri, 14 Jun 2024 09:21:36 +0200 Subject: [PATCH 20/36] Refactor hierarchy-example to use mvn docker plugin to build image --- .../Dockerfile | 11 ----- .../aas-registry-delegated.yml | 5 ++ .../docker-compose.yml | 5 +- .../pom.xml | 25 +++++----- .../src/main/docker/Dockerfile | 21 +++++++++ .../main/resources/application-hierarchy.yml | 10 ++++ .../src/main/resources/application.yml | 47 ------------------- 7 files changed, 51 insertions(+), 73 deletions(-) delete mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Dockerfile create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/aas-registry-delegated.yml create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/docker/Dockerfile create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml delete mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application.yml diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Dockerfile b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Dockerfile deleted file mode 100644 index f0291e92d..000000000 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM amazoncorretto:17 -USER nobody -WORKDIR /application -ARG JAR_FILE=target/*-exec.jar -COPY ${JAR_FILE} basyxExecutable.jar -COPY src/main/resources/application.yml application.yml -ARG PORT=8081 -ENV SERVER_PORT=${PORT} -EXPOSE ${SERVER_PORT} -HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=15s CMD curl --fail http://localhost:${SERVER_PORT}/actuator/health || exit 1 -ENTRYPOINT ["java","-jar","basyxExecutable.jar"] diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/aas-registry-delegated.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/aas-registry-delegated.yml new file mode 100644 index 000000000..eb3b0feb3 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/aas-registry-delegated.yml @@ -0,0 +1,5 @@ +--- +basyx: + cors: + allowed-origins: "*" + allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/docker-compose.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/docker-compose.yml index f321070c4..adc3e0f24 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/docker-compose.yml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/docker-compose.yml @@ -2,8 +2,7 @@ version: "3.9" services: aas-registry-root: - build: - context: . + image: aas-registry-test/aas-registry-feature-hierarchy-example:2.0.0-SNAPSHOT container_name: aas-registry-root ports: - "8051:8080" @@ -19,6 +18,8 @@ services: - "8052:8080" environment: SERVER_SERVLET_CONTEXT_PATH: / + volumes: + - ./aas-registry-delegated.yml:/workspace/config/application.yml networks: - basyx-aasregistry-feature-hierarchy-example diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/pom.xml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/pom.xml index c83a34c6f..e1ad0ecce 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/pom.xml @@ -10,27 +10,26 @@ basyx.aasregistry-feature-hierarchy-example + BaSyx AAS Registry Feature Hierarchy Example + BaSyx AAS Registry Feature Hierarchy Example - org.eclipse.digitaltwin.basyx.aasregistry.service.OpenApiGeneratorApplication + 2020.0.4 + org.eclipse.digitaltwin.basyx.aasregistry.service.OpenApiGeneratorApplication + aas-registry-feature-hierarchy-example org.eclipse.digitaltwin.basyx basyx.aasregistry-service-release-log-mem - ${project.version} + ${revision} + + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-feature-hierarchy + tests + test - - - - org.springframework.boot - spring-boot-maven-plugin - - exec - - - - \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/docker/Dockerfile b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/docker/Dockerfile new file mode 100644 index 000000000..2c5546b47 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/docker/Dockerfile @@ -0,0 +1,21 @@ +FROM amazoncorretto:17 as builder +COPY maven/${project.build.finalName}.jar ./ +RUN java -Djarmode=layertools -jar ${project.build.finalName}.jar extract + +FROM amazoncorretto:17 +RUN mkdir /workspace +WORKDIR /workspace +COPY --from=builder dependencies/ ./ +COPY --from=builder snapshot-dependencies/ ./ +RUN true +COPY --from=builder spring-boot-loader/ ./ +COPY --from=builder application/ ./ +ENV SPRING_PROFILES_ACTIVE=logEvents,inMemoryStorage,hierarchy +ARG PORT=8080 +ENV SERVER_PORT=${PORT} +ARG CONTEXT_PATH=/ +ENV SERVER_SERVLET_CONTEXT_PATH=${CONTEXT_PATH} +EXPOSE ${SERVER_PORT} +HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=15s CMD curl --fail http://localhost:${SERVER_PORT}${SERVER_SERVLET_CONTEXT_PATH%/}/actuator/health || exit 1 +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/.urandom", "org.springframework.boot.loader.JarLauncher"] + diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml new file mode 100644 index 000000000..07bd50c22 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml @@ -0,0 +1,10 @@ +--- +basyx: + cors: + allowed-origins: "*" + allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" + aasregistry: + feature: + hierarchy: + enabled: true + \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application.yml deleted file mode 100644 index 0ea32089a..000000000 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application.yml +++ /dev/null @@ -1,47 +0,0 @@ ---- -events: - sink: log -description: - profiles: https://admin-shell.io/aas/API/3/0/AssetAdministrationShellRegistryServiceSpecification/SSP-001 -springdoc: - api-docs: - path: /api-docs -springfox: - documentation: - enabled: true - # open-api.v3.path: /api-docs -management: - endpoints: - web: - exposure: - include: "health,metrics" -logging: - level: - root: INFO -server: - shutdown: graceful - port: 8080 - error: - whitelabel: - enabled: false -spring: - application: - name: Basyx Aas Registry - jackson: - date-format: org.eclipse.digitaltwin.basyx.aasregistry.service.RFC3339DateFormat - serialization: - WRITE_DATES_AS_TIMESTAMPS: false - profiles: - active: logEvents,inMemoryStorage - -registry: - type: inMemory - -basyx: - cors: - allowed-origins: "*" - allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" - aasregistry: - feature: - hierarchy: - enabled: true From 9ff716473c8405761e15cc0dbf45cb29369525c6 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Fri, 14 Jun 2024 09:22:06 +0200 Subject: [PATCH 21/36] Add example scenario IT to example --- .../example/HierachicalAasRegistryIT.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java new file mode 100644 index 000000000..1266d3d0a --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.example; + +import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.DummyDescriptorFactory; +import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchicalAasRegistryTestSuite; + +/** + * HierachicalAasRegistryIT + * + * @author mateusmolina + * + */ +public class HierachicalAasRegistryIT extends HierarchicalAasRegistryTestSuite { + + private static final String ROOT_REGISTRY_URL = "http://localhost:8051"; + private static final String DELEGATED_REGISTRY_URL = "http://localhost:8052"; + + private static final String REPO_BASE_URL = "http://localhost:8080"; + private static final String DELEGATED_AASID = "http://delegated-aas-registry:8080/test/aas"; + + private static final DummyDescriptorFactory factory = new DummyDescriptorFactory(REPO_BASE_URL, DELEGATED_AASID); + + private static final RegistryAndDiscoveryInterfaceApi rootRegistryApi = new RegistryAndDiscoveryInterfaceApi(ROOT_REGISTRY_URL); + private static final RegistryAndDiscoveryInterfaceApi delegatedRegistryApi = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); + + @Override + protected RegistryAndDiscoveryInterfaceApi getRootRegistryApi() { + return rootRegistryApi; + } + + @Override + protected RegistryAndDiscoveryInterfaceApi getDelegatedRegistryApi() { + return delegatedRegistryApi; + } + + @Override + protected DummyDescriptorFactory getDescriptorFactory() { + return factory; + } + +} From cc6c83e1c06ccd3735d5542d1202e28e1936a818 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Fri, 14 Jun 2024 09:40:37 +0200 Subject: [PATCH 22/36] Add Readme to example module --- .../Readme.md | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Readme.md diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Readme.md b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Readme.md new file mode 100644 index 000000000..e2fb0cfb6 --- /dev/null +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/Readme.md @@ -0,0 +1,42 @@ +# AssetAdministrationShell Registry - Hierarchy - Example + +This example showcases the working principle of the hierarchical registries feature. + +## Scenario description + +```mermaid +sequenceDiagram + actor Client + participant Root as Root Registry + participant Delegated as Delegated Registry + + Client ->> Root: Request resolution for AAS-ID "http://delegated-aas-registry:8080/test/aas" + activate Root + + Root ->> Root: Check local records + alt Not found locally + Root ->> Root: Determine registry based on URI prefix + Root ->> Delegated: Resolve AAS-ID "http://delegated-aas-registry:8080/test/aas" at registry.delegated-aas-registry:8080 + activate Delegated + Delegated ->> Delegated: Resolve AAS-ID + Delegated ->> Root: Resolution result + deactivate Delegated + end + + Root ->> Client: Return resolution result + deactivate Root +``` + +## Running the scenario + +In order to run the example, please make sure that all aasregistries maven modules are correctly installed in your local Maven repository. + +1. Generate the Docker image: `mvn clean install -Ddocker.namespace=aas-registry-test` + +2. Run the docker compose: `docker compose up` + +Two containers should start: (1) one for the root AAS Registry - to which the http request are going to be made; (2) one for the delegated AAS Registry - to which requests may be delegated to. + +They are visibile within the bridged Docker network as (1) aas-registry-root:8080 and (2) registry.delegated-aas-registry:8080 + +3. Run the scenario [HierarchicalAasRegistryIT](/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java) From e727d9ac8c8061d32c11033a835b93b65562d22b Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Fri, 14 Jun 2024 09:42:41 +0200 Subject: [PATCH 23/36] Add feature to kafka releases --- .../basyx.aasregistry-service-release-kafka-mem/pom.xml | 4 ++++ .../basyx.aasregistry-service-release-kafka-mongodb/pom.xml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/basyx.aasregistry/basyx.aasregistry-service-release-kafka-mem/pom.xml b/basyx.aasregistry/basyx.aasregistry-service-release-kafka-mem/pom.xml index 10b50cf46..600a7eefe 100644 --- a/basyx.aasregistry/basyx.aasregistry-service-release-kafka-mem/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-service-release-kafka-mem/pom.xml @@ -32,6 +32,10 @@ org.eclipse.digitaltwin.basyx basyx.aasregistry-feature-authorization + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-feature-hierarchy + org.eclipse.digitaltwin.basyx basyx.aasregistry-service-kafka-events diff --git a/basyx.aasregistry/basyx.aasregistry-service-release-kafka-mongodb/pom.xml b/basyx.aasregistry/basyx.aasregistry-service-release-kafka-mongodb/pom.xml index 5788f88f6..ee69f9c12 100644 --- a/basyx.aasregistry/basyx.aasregistry-service-release-kafka-mongodb/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-service-release-kafka-mongodb/pom.xml @@ -24,6 +24,10 @@ org.eclipse.digitaltwin.basyx basyx.aasregistry-feature-authorization + + org.eclipse.digitaltwin.basyx + basyx.aasregistry-feature-hierarchy + org.eclipse.digitaltwin.basyx basyx.authorization From 7bbae908cb0867e83f077156f267d4ff9733c395 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Mon, 2 Dec 2024 11:24:13 +0100 Subject: [PATCH 24/36] feat: add SubmodelRegistry Hierarchy Feature --- .../Readme.md | 31 +++++ .../pom.xml | 33 +++++ .../HierarchicalSubmodelRegistryFeature.java | 77 ++++++++++++ .../HierarchicalSubmodelRegistryStorage.java | 103 +++++++++++++++ .../SubmodelRegistryModelMapper.java | 77 ++++++++++++ .../delegation/DelegationStrategy.java | 48 +++++++ .../delegation/PrefixDelegationStrategy.java | 85 +++++++++++++ .../hierarchy/DummyDescriptorFactory.java | 100 +++++++++++++++ .../DummySubmodelRegistryComponent.java | 43 +++++++ ...HierarchicalSubmodelRegistryTestSuite.java | 119 ++++++++++++++++++ ...lhostHierarchicalSubmodelRegistryTest.java | 80 ++++++++++++ .../PrefixDelegationStrategyTest.java | 93 ++++++++++++++ .../src/test/resources/application.yml | 46 +++++++ basyx.submodelregistry/pom.xml | 6 + pom.xml | 6 + 15 files changed, 947 insertions(+) create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/SubmodelRegistryModelMapper.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/DelegationStrategy.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummyDescriptorFactory.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/LocalhostHierarchicalSubmodelRegistryTest.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/resources/application.yml diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md new file mode 100644 index 000000000..9dc526c06 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md @@ -0,0 +1,31 @@ +# Submodel Registry - Hierarchy + +The Hierarchical SubmodelRegistry Feature enhances the availability of data across multiple registries by allowing retrieval requests to be delegated to another SubmodelRegistry. + +This feature allows the creation of a hierarchical structure of registries, where a registry can delegate retrieval requests to another registry when a given descriptor is not found in its storage. + +## Configuration + +### Enabling the Feature + +To enable the Hierarchical SubmodelRegistry Feature, add the following property to your Spring application's configuration: + +```properties +basyx.submodelregistry.feature.hierarchy.enabled=true +``` + +### Delegation Strategy + +Currently, only one delegation strategy is implemented: + +#### Prefix Delegation Strategy + +Delegates requests based on the `submodelDescriptorId` value. If the ID is an URL, a prefix (defaut `registry`) is appended to the URL and used as delegation endpoint. + +The prefix can be configured by the property `basyx.submodelregistry.feature.hierarchy.prefix`. Please refer to the example below: + +```properties +basyx.submodelregistry.feature.hierarchy.prefix=registry +``` + +If this property is left with an empty string, no prefix is appended to the URL contained in the `submodelDecriptorId`. diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml new file mode 100644 index 000000000..03c1531d4 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml @@ -0,0 +1,33 @@ + + 4.0.0 + + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry + ${revision} + + + basyx.submodelregistry-feature-hierarchy + + + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-service + + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-service-basemodel + + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-client-native + + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-service-inmemory-storage + test + + + \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java new file mode 100644 index 000000000..0e477c2f3 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy; + +import org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation.DelegationStrategy; +import org.eclipse.digitaltwin.basyx.submodelregistry.service.storage.SubmodelRegistryStorage; +import org.eclipse.digitaltwin.basyx.submodelregistry.service.storage.SubmodelRegistryStorageFeature; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * Hierarchical {@link SubmodelRegistryStorage} feature + * + * When this feature is enabled, retrieval requests will be delegated to the + * next SubmodelRegistry. + * + * The next SubmodelRegistry is selected via a {@link DelegationStrategy} + * + * @author mateusmolina + */ +@Component +@ConditionalOnExpression("${" + HierarchicalSubmodelRegistryFeature.ENABLED_PROPERTY_KEY + ":false}") +@Order(1) +public class HierarchicalSubmodelRegistryFeature implements SubmodelRegistryStorageFeature { + public static final String FEATURENAME = "basyx.submodelregistry.feature.hierarchy"; + public static final String ENABLED_PROPERTY_KEY = FEATURENAME + ".enabled"; + + @Value("${" + ENABLED_PROPERTY_KEY + "}") + private boolean enabled; + + private DelegationStrategy delegationStrategy; + + public HierarchicalSubmodelRegistryFeature(DelegationStrategy delegationStrategy) { + this.delegationStrategy = delegationStrategy; + } + + @Override + public SubmodelRegistryStorage decorate(SubmodelRegistryStorage storage) { + return new HierarchicalSubmodelRegistryStorage(storage, delegationStrategy); + } + + @Override + public String getName() { + return "SubmodelRegistry Hierarchy"; + } + + @Override + public boolean isEnabled() { + return enabled; + } + +} \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java new file mode 100644 index 000000000..b539e76d3 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy; + +import java.util.List; +import java.util.Set; + +import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.ApiException; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.api.SubmodelRegistryApi; +import org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation.DelegationStrategy; +import org.eclipse.digitaltwin.basyx.submodelregistry.model.SubmodelDescriptor; +import org.eclipse.digitaltwin.basyx.submodelregistry.service.errors.SubmodelAlreadyExistsException; +import org.eclipse.digitaltwin.basyx.submodelregistry.service.errors.SubmodelNotFoundException; +import org.eclipse.digitaltwin.basyx.submodelregistry.service.storage.SubmodelRegistryStorage; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Decorator for Hierarchical {@link AasRegistryStorage} + * + * @author mateusmolina + */ +public class HierarchicalSubmodelRegistryStorage implements SubmodelRegistryStorage { + + private final SubmodelRegistryStorage decorated; + + private final DelegationStrategy delegationStrategy; + + private final SubmodelRegistryModelMapper mapper = new SubmodelRegistryModelMapper(new ObjectMapper()); + + public HierarchicalSubmodelRegistryStorage(SubmodelRegistryStorage decorated, DelegationStrategy delegationStrategy) { + this.decorated = decorated; + this.delegationStrategy = delegationStrategy; + } + + @Override + public Set clear() { + return decorated.clear(); + } + + @Override + public CursorResult> getAllSubmodelDescriptors(PaginationInfo pRequest) { + return decorated.getAllSubmodelDescriptors(pRequest); + } + + @Override + public SubmodelDescriptor getSubmodelDescriptor(String submodelId) throws SubmodelNotFoundException { + try { + return decorated.getSubmodelDescriptor(submodelId); + } catch (SubmodelNotFoundException e) { + try { + return mapper.mapEqModel(getDelegatedRegistryApi(submodelId).getSubmodelDescriptorById(submodelId)); + } catch (ApiException e1) { + throw SubmodelRegistryModelMapper.mapApiException(e1, submodelId); + } + } + } + + @Override + public void insertSubmodelDescriptor(SubmodelDescriptor descr) throws SubmodelAlreadyExistsException { + decorated.insertSubmodelDescriptor(descr); + } + + @Override + public void replaceSubmodelDescriptor(String submodelId, SubmodelDescriptor descr) throws SubmodelNotFoundException { + decorated.replaceSubmodelDescriptor(submodelId, descr); + } + + @Override + public void removeSubmodelDescriptor(String submodelId) throws SubmodelNotFoundException { + decorated.removeSubmodelDescriptor(submodelId); + } + + private SubmodelRegistryApi getDelegatedRegistryApi(String smId) { + String delegationUrl = delegationStrategy.buildDelegatedRegistryUrl(smId).orElseThrow(() -> new SubmodelNotFoundException(smId)); + return new SubmodelRegistryApi(delegationUrl); + } +} diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/SubmodelRegistryModelMapper.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/SubmodelRegistryModelMapper.java new file mode 100644 index 000000000..2a48f99c7 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/SubmodelRegistryModelMapper.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy; + +import java.util.List; + +import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.ApiException; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.model.GetSubmodelDescriptorsResult; +import org.eclipse.digitaltwin.basyx.submodelregistry.model.SubmodelDescriptor; +import org.eclipse.digitaltwin.basyx.submodelregistry.service.errors.SubmodelNotFoundException; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Handles internal model mapping for + * {@link HierarchicalsubmodelRegistryStorage} + * + * @author mateusmolina + * + */ +final class SubmodelRegistryModelMapper { + + private final ObjectMapper objectMapper; + + SubmodelRegistryModelMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + SubmodelDescriptor mapEqModel(org.eclipse.digitaltwin.basyx.submodelregistry.client.model.SubmodelDescriptor submodelRegistryDescriptor) { + return objectMapper.convertValue(submodelRegistryDescriptor, SubmodelDescriptor.class); + } + + org.eclipse.digitaltwin.basyx.submodelregistry.client.model.SubmodelDescriptor mapEqModel(SubmodelDescriptor smRegistryDescriptor) { + return objectMapper.convertValue(smRegistryDescriptor, org.eclipse.digitaltwin.basyx.submodelregistry.client.model.SubmodelDescriptor.class); + } + + CursorResult> mapEqModel(GetSubmodelDescriptorsResult descriptorResult) { + List submodelDescs = objectMapper.convertValue(descriptorResult.getResult(), new TypeReference>() { + }); + return new CursorResult<>(descriptorResult.getPagingMetadata().getCursor(), submodelDescs); + } + + static RuntimeException mapApiException(ApiException e, String submodelDescriptorId) { + if (HttpStatusCode.valueOf(e.getCode()).equals(HttpStatus.NOT_FOUND)) + return new SubmodelNotFoundException(submodelDescriptorId); + + return new RuntimeException(e); + } + +} diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/DelegationStrategy.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/DelegationStrategy.java new file mode 100644 index 000000000..250b06d15 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/DelegationStrategy.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation; + +import java.util.Optional; + +/** + * DelegationStrategy + * + * @author mateusmolina + * + */ +@FunctionalInterface +public interface DelegationStrategy { + /** + * Builds the URL for the delegation AAS Registry. + * + * @param aasId + * The ID of the AAS for which the delegated registry URL is to be + * built. + * @return An Optional containing the delegated AAS Registry URL if it can be + * constructed, or an empty Optional otherwise. + */ + public Optional buildDelegatedRegistryUrl(String aasId); +} diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java new file mode 100644 index 000000000..bbdaf5113 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Optional; + +import org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.HierarchicalSubmodelRegistryFeature; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * Generates delegation URL based on value of the prefix attribute. Default + * value is 'registry'. + * + * @author mateusmolina + * + */ +@Component +public class PrefixDelegationStrategy implements DelegationStrategy { + public static final String PREFIX_PROPERTY_KEY = HierarchicalSubmodelRegistryFeature.FEATURENAME + ".prefix"; + private final String prefix; + + public PrefixDelegationStrategy(@Value("${" + PREFIX_PROPERTY_KEY + ":registry}") String prefix) { + this.prefix = prefix; + } + + @Override + public Optional buildDelegatedRegistryUrl(String smId) { + return Optional.ofNullable(smId).map(this::extractDelegationUrl); + } + + private String extractDelegationUrl(String smId) { + URL url; + + try { + url = new URL(smId); + } catch (MalformedURLException e) { + return null; + } + + String host = url.getHost(); + int port = url.getPort(); + String protocol = url.getProtocol(); + + StringBuilder registryUrl = new StringBuilder(); + + registryUrl.append(protocol).append("://"); + + if (prefix != null && !prefix.isBlank()) + registryUrl.append(prefix).append("."); + + registryUrl.append(host); + + if (port != -1) { + registryUrl.append(":").append(port); + } + + return registryUrl.toString(); + } +} \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummyDescriptorFactory.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummyDescriptorFactory.java new file mode 100644 index 000000000..222b9323c --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummyDescriptorFactory.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.model.Endpoint; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.model.ProtocolInformation; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.model.SubmodelDescriptor; + +/** + * DummyDescriptorFactory + * + * @author mateusmolina + * + */ +public class DummyDescriptorFactory { + static final String ROOT_ONLY_SM_ID = "SMDESCRIPTOR_ID_ROOTONLY"; + + private static final String SUBMODEL_INTERFACE = "SUBMODEL-3.0"; + + private final String repoBaseUrl; + private final String delegatedOnlySmId; + + public DummyDescriptorFactory(String repoBaseUrl, String delegatedSmId) { + this.repoBaseUrl = repoBaseUrl; + this.delegatedOnlySmId = delegatedSmId; + } + + SubmodelDescriptor getRootOnlySmDescriptor() { + return createDummySubmodelDescriptor(repoBaseUrl, ROOT_ONLY_SM_ID, buildIdShort(ROOT_ONLY_SM_ID)); + } + + SubmodelDescriptor getDelegatedOnlySmDescriptor() { + return createDummySubmodelDescriptor(repoBaseUrl, delegatedOnlySmId, buildIdShort(delegatedOnlySmId)); + } + + String getDelegatedOnlySmId() { + return delegatedOnlySmId; + } + + String getRepoBaseUrl() { + return repoBaseUrl; + } + + private static SubmodelDescriptor createDummySubmodelDescriptor(String baseUrl, String submodelId, String submodelIdShort) { + SubmodelDescriptor descriptor = new SubmodelDescriptor().id(submodelId); + descriptor.setIdShort(submodelIdShort); + descriptor.setEndpoints(List.of(new Endpoint()._interface(SUBMODEL_INTERFACE).protocolInformation(createSmProtocolInformation(baseUrl, submodelId)))); + + return descriptor; + } + + private static ProtocolInformation createSmProtocolInformation(String baseUrl, String smId) { + String href = String.format("%s/%s", baseUrl + "/submodels", Base64UrlEncodedIdentifier.encodeIdentifier(smId)); + + ProtocolInformation protocolInformation = new ProtocolInformation().href(href); + protocolInformation.endpointProtocol(getProtocol(href)); + + return protocolInformation; + } + + private static String getProtocol(String endpoint) { + try { + return new URL(endpoint).getProtocol(); + } catch (MalformedURLException e) { + throw new RuntimeException(); + } + } + + private static String buildIdShort(String smId) { + return smId + "IdShort"; + } +} diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java new file mode 100644 index 000000000..adb2046a5 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Creates and starts the {@link HierarchicalSubmodelRegistryFeature} for tests + * + * @author mateusmolina + * + */ +@SpringBootApplication(scanBasePackages = { "org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy", "org.eclipse.digitaltwin.basyx.submodelregistry.service.api", "org.eclipse.digitaltwin.basyx.submodelregistry.service.events", + "org.eclipse.digitaltwin.basyx.submodelregistry.service.configuration", "org.eclipse.digitaltwin.basyx.submodelregistry.service.errors" }) +public class DummySubmodelRegistryComponent { + public static void main(String[] args) { + SpringApplication.run(DummySubmodelRegistryComponent.class, args); + } +} \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java new file mode 100644 index 000000000..ac24c9f46 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.digitaltwin.basyx.submodelregistry.client.ApiException; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.api.SubmodelRegistryApi; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.model.GetSubmodelDescriptorsResult; +import org.eclipse.digitaltwin.basyx.submodelregistry.client.model.SubmodelDescriptor; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpStatus; + +/** + * Test for {@link HierarchicalSubmodelRegistryFeature} + * + * @author mateusmolina + * + */ +public abstract class HierarchicalSubmodelRegistryTestSuite { + + protected abstract SubmodelRegistryApi getRootRegistryApi(); + + protected abstract SubmodelRegistryApi getDelegatedRegistryApi(); + + protected abstract DummyDescriptorFactory getDescriptorFactory(); + + @Before + public void setUp() throws ApiException { + cleanUpRegistries(); + setupDelegatedRegistry(); + setupRootRegistry(); + } + + @Test + public void getSubmodelDescriptor_InRoot() throws ApiException { + SubmodelDescriptor actualDescriptor = getRootRegistryApi().getSubmodelDescriptorById(DummyDescriptorFactory.ROOT_ONLY_SM_ID); + + SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getRootOnlySmDescriptor(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getSubmodelDescriptor_ThroughDelegated() throws ApiException { + SubmodelDescriptor actualDescriptor = getRootRegistryApi().getSubmodelDescriptorById(getDescriptorFactory().getDelegatedOnlySmId()); + + SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getDelegatedOnlySmDescriptor(); + + assertEquals(expectedDescriptor, actualDescriptor); + } + + @Test + public void getAllSubmodelDescriptor_InRoot() throws ApiException { + GetSubmodelDescriptorsResult actualDescriptors = getRootRegistryApi().getAllSubmodelDescriptors(1, null); + + SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getRootOnlySmDescriptor(); + + List expectedDescriptors = Arrays.asList(expectedDescriptor); + + assertEquals(expectedDescriptors, actualDescriptors.getResult()); + } + + @Test + public void getNonExistingSmDescriptor() { + ApiException exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorById("nonExistingSubmodel")); + assertHttpCodeIsNotFound(exception); + + exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorById("nonExistingSubmodel")); + assertHttpCodeIsNotFound(exception); + + } + + private void setupRootRegistry() throws ApiException { + getRootRegistryApi().postSubmodelDescriptor(getDescriptorFactory().getRootOnlySmDescriptor()); + } + + private void setupDelegatedRegistry() throws ApiException { + SubmodelDescriptor descriptor = getDescriptorFactory().getDelegatedOnlySmDescriptor(); + + getDelegatedRegistryApi().postSubmodelDescriptor(descriptor); + } + + private void cleanUpRegistries() throws ApiException { + getRootRegistryApi().deleteAllSubmodelDescriptors(); + getDelegatedRegistryApi().deleteAllSubmodelDescriptors(); + } + + private static void assertHttpCodeIsNotFound(ApiException e) { + assertEquals(HttpStatus.NOT_FOUND.value(), e.getCode()); + } +} diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/LocalhostHierarchicalSubmodelRegistryTest.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/LocalhostHierarchicalSubmodelRegistryTest.java new file mode 100644 index 000000000..f571c1124 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/LocalhostHierarchicalSubmodelRegistryTest.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy; + +import org.eclipse.digitaltwin.basyx.submodelregistry.client.api.SubmodelRegistryApi; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * LocalhostHierarchicalSubmodelRegistryTest + * + * @author mateusmolina + * + */ +public class LocalhostHierarchicalSubmodelRegistryTest extends HierarchicalSubmodelRegistryTestSuite { + + private static final String ROOT_REGISTRY_URL = "http://localhost:8081"; + private static final String DELEGATED_REGISTRY_URL = "http://localhost:8060"; + + private static final String REPO_BASE_URL = "http://localhost:8080"; + private static final String DELEGATED_SMID = "http://localhost:8060/test/sm"; + + private static final SubmodelRegistryApi rootRegistryApi = new SubmodelRegistryApi(ROOT_REGISTRY_URL); + private static final SubmodelRegistryApi delegatedRegistryApi = new SubmodelRegistryApi(DELEGATED_REGISTRY_URL); + + private static final DummyDescriptorFactory factory = new DummyDescriptorFactory(REPO_BASE_URL, DELEGATED_SMID); + + private static ConfigurableApplicationContext appContext; + + @BeforeClass + public static void setupRootRegistry() { + appContext = new SpringApplication(DummySubmodelRegistryComponent.class).run(new String[] {}); + } + + @AfterClass + public static void tearDownRootRegistry() { + appContext.close(); + } + + @Override + protected SubmodelRegistryApi getRootRegistryApi() { + return rootRegistryApi; + } + + @Override + protected SubmodelRegistryApi getDelegatedRegistryApi() { + return delegatedRegistryApi; + } + + @Override + protected DummyDescriptorFactory getDescriptorFactory() { + return factory; + } + +} diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java new file mode 100644 index 000000000..c03941de8 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +/** + * PrefixDelegationStrategyTest + * + * @author mateusmolina + * + */ + +public class PrefixDelegationStrategyTest { + + private PrefixDelegationStrategy prefixDelegationStrategy; + + @Before + public void setUp() { + prefixDelegationStrategy = new PrefixDelegationStrategy("registry"); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithPort() { + String aasId = "http://fraunhofer:8042/example/aas"; + String expectedUrl = "http://registry.fraunhofer:8042"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithoutPort() { + String aasId = "http://fraunhofer/example/aas"; + String expectedUrl = "http://registry.fraunhofer"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithTLD() { + String aasId = "http://fraunhofer.com:8080/example/aas"; + String expectedUrl = "http://registry.fraunhofer.com:8080"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_InvalidUrl() { + String aasId = "invalid_url"; + assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).isEmpty()); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithBlankPrefix() { + PrefixDelegationStrategy blankPrefixDelegationStrategy = new PrefixDelegationStrategy(""); + String aasId = "http://fraunhofer.com:8080/example/aas"; + String expectedUrl = "http://fraunhofer.com:8080"; + String actualUrl = blankPrefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_NullAasId() { + assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(null).isEmpty()); + } +} \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/resources/application.yml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/resources/application.yml new file mode 100644 index 000000000..cea367045 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/resources/application.yml @@ -0,0 +1,46 @@ +--- +events: + sink: log +description: + profiles: https://admin-shell.io/aas/API/3/0/SubmodelRegistryServiceSpecification/SSP-001 +springdoc: + api-docs: + path: /api-docs +springfox: + documentation: + enabled: true + # open-api.v3.path: /api-docs +management: + endpoints: + web: + exposure: + include: "health,metrics" +logging: + level: + root: INFO +server: + shutdown: graceful + port: 8081 + error: + whitelabel: + enabled: false +spring: + application: + name: Basyx Submodel Registry + jackson: + date-format: org.eclipse.digitaltwin.basyx.submodelregistry.service.RFC3339DateFormat + serialization: + WRITE_DATES_AS_TIMESTAMPS: false + +registry: + type: inMemory + +basyx: + cors: + allowed-origins: "*" + allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" + submodelregistry: + feature: + hierarchy: + enabled: true + prefix: diff --git a/basyx.submodelregistry/pom.xml b/basyx.submodelregistry/pom.xml index 8cb518ecb..05ebc0a25 100644 --- a/basyx.submodelregistry/pom.xml +++ b/basyx.submodelregistry/pom.xml @@ -51,6 +51,7 @@ basyx.submodelregistry-service-release-log-mongodb basyx.submodelregistry-service-release-kafka-mongodb basyx.submodelregistry-feature-authorization + basyx.submodelregistry-feature-hierarchy @@ -190,6 +191,11 @@ basyx.submodelregistry-feature-authorization ${project.version} + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-feature-hierarchy + ${project.version} + diff --git a/pom.xml b/pom.xml index 19a2b79e5..34f07eb17 100644 --- a/pom.xml +++ b/pom.xml @@ -1124,6 +1124,12 @@ ${revision} tests + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-feature-hierarchy + ${revision} + tests + org.eclipse.digitaltwin.basyx basyx.submodelregistry-client-native From 970a79903b1fb268805f03f38238b11c9543ab25 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Mon, 2 Dec 2024 11:27:04 +0100 Subject: [PATCH 25/36] feat: add hierarchy features to all releases --- .../basyx.submodelregistry-service-release-kafka-mem/pom.xml | 4 ++++ .../pom.xml | 4 ++++ .../basyx.submodelregistry-service-release-log-mem/pom.xml | 4 ++++ .../pom.xml | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/basyx.submodelregistry/basyx.submodelregistry-service-release-kafka-mem/pom.xml b/basyx.submodelregistry/basyx.submodelregistry-service-release-kafka-mem/pom.xml index 66f1c919c..94c787593 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-service-release-kafka-mem/pom.xml +++ b/basyx.submodelregistry/basyx.submodelregistry-service-release-kafka-mem/pom.xml @@ -24,6 +24,10 @@ org.eclipse.digitaltwin.basyx basyx.submodelregistry-feature-authorization + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-feature-hierarchy + org.eclipse.digitaltwin.basyx basyx.authorization diff --git a/basyx.submodelregistry/basyx.submodelregistry-service-release-kafka-mongodb/pom.xml b/basyx.submodelregistry/basyx.submodelregistry-service-release-kafka-mongodb/pom.xml index e91d80cc8..94f2dc4b2 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-service-release-kafka-mongodb/pom.xml +++ b/basyx.submodelregistry/basyx.submodelregistry-service-release-kafka-mongodb/pom.xml @@ -24,6 +24,10 @@ org.eclipse.digitaltwin.basyx basyx.submodelregistry-feature-authorization + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-feature-hierarchy + org.eclipse.digitaltwin.basyx basyx.authorization diff --git a/basyx.submodelregistry/basyx.submodelregistry-service-release-log-mem/pom.xml b/basyx.submodelregistry/basyx.submodelregistry-service-release-log-mem/pom.xml index 5cf7112ad..a515a2ca0 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-service-release-log-mem/pom.xml +++ b/basyx.submodelregistry/basyx.submodelregistry-service-release-log-mem/pom.xml @@ -25,6 +25,10 @@ org.eclipse.digitaltwin.basyx basyx.submodelregistry-feature-authorization + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-feature-hierarchy + org.eclipse.digitaltwin.basyx basyx.authorization diff --git a/basyx.submodelregistry/basyx.submodelregistry-service-release-log-mongodb/pom.xml b/basyx.submodelregistry/basyx.submodelregistry-service-release-log-mongodb/pom.xml index 751d571c1..6c50463fe 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-service-release-log-mongodb/pom.xml +++ b/basyx.submodelregistry/basyx.submodelregistry-service-release-log-mongodb/pom.xml @@ -24,6 +24,10 @@ org.eclipse.digitaltwin.basyx basyx.submodelregistry-feature-authorization + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-feature-hierarchy + org.eclipse.digitaltwin.basyx basyx.authorization From 6024711711dc315e6ea477545af7f4e3e341bfe7 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Mon, 2 Dec 2024 15:26:51 +0100 Subject: [PATCH 26/36] feat: add submodelRegistry Hierarchy Example --- .../Readme.md | 42 ++++++++++++ .../docker-compose.yml | 29 ++++++++ .../pom.xml | 36 ++++++++++ .../src/main/docker/Dockerfile | 21 ++++++ .../main/resources/application-hierarchy.yml | 10 +++ .../HierachicalSubmodelRegistryIT.java | 66 +++++++++++++++++++ .../submodel-registry-delegated.yml | 5 ++ basyx.submodelregistry/pom.xml | 1 + 8 files changed, 210 insertions(+) create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/Readme.md create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/docker-compose.yml create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/pom.xml create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/docker/Dockerfile create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java create mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/submodel-registry-delegated.yml diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/Readme.md b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/Readme.md new file mode 100644 index 000000000..a580a7cc0 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/Readme.md @@ -0,0 +1,42 @@ +# Submodel Registry - Hierarchy - Example + +This example showcases the working principle of the hierarchical registries feature. + +## Scenario description + +```mermaid +sequenceDiagram + actor Client + participant Root as Root Registry + participant Delegated as Delegated Registry + + Client ->> Root: Request resolution for Submodel-ID "http://delegated-submodel-registry:8080/test/submodel" + activate Root + + Root ->> Root: Check local records + alt Not found locally + Root ->> Root: Determine registry based on URI prefix + Root ->> Delegated: Resolve Submodel-ID "http://delegated-submodel-registry:8080/test/submodel" at registry.delegated-submodel-registry:8080 + activate Delegated + Delegated ->> Delegated: Resolve Submodel- + Delegated ->> Root: Resolution result + deactivate Delegated + end + + Root ->> Client: Return resolution result + deactivate Root +``` + +## Running the scenario + +In order to run the example, please make sure that all submodel registries maven modules are correctly installed in your local Maven repository. + +1. Generate the Docker image: `mvn clean install -Ddocker.namespace=submodel-registry-test` + +2. Run the docker compose: `docker compose up` + +Two containers should start: (1) one for the root Submodel Registry - to which the http request are going to be made; (2) one for the delegated Submodel Registry - to which requests may be delegated to. + +They are visibile within the bridged Docker network as (1) submodel-registry-root:8080 and (2) registry.delegated-submodel-registry:8080 + +3. Run the scenario [HierarchicalSubmodelRegistryIT](/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java) diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/docker-compose.yml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/docker-compose.yml new file mode 100644 index 000000000..03452b721 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/docker-compose.yml @@ -0,0 +1,29 @@ +version: "3.9" +services: + + submodel-registry-root: + image: submodel-registry-test/submodel-registry-feature-hierarchy-example:2.0.0-SNAPSHOT + container_name: submodel-registry-root + ports: + - "8051:8080" + environment: + SERVER_SERVLET_CONTEXT_PATH: / + networks: + - basyx-submodelregistry-feature-hierarchy-example + + registry.delegated-submodel-registry: + image: eclipsebasyx/submodel-registry-log-mem:2.0.0-SNAPSHOT + container_name: registry.delegated-submodel-registry + ports: + - "8052:8080" + environment: + SERVER_SERVLET_CONTEXT_PATH: / + volumes: + - ./submodel-registry-delegated.yml:/workspace/config/application.yml + networks: + - basyx-submodelregistry-feature-hierarchy-example + +networks: + basyx-submodelregistry-feature-hierarchy-example: + name: basyx-submodelregistry-feature-hierarchy-example + driver: bridge diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/pom.xml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/pom.xml new file mode 100644 index 000000000..32c3b8e73 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry + ${revision} + + + basyx.submodelregistry-feature-hierarchy-example + BaSyx Submodel Registry Feature Hierarchy Example + BaSyx Submodel Registry Feature Hierarchy Example + + + 2020.0.4 + + org.eclipse.digitaltwin.basyx.submodelregistry.service.OpenApiGeneratorApplication + submodel-registry-feature-hierarchy-example + + + + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-service-release-log-mem + ${revision} + + + org.eclipse.digitaltwin.basyx + basyx.submodelregistry-feature-hierarchy + tests + test + + + \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/docker/Dockerfile b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/docker/Dockerfile new file mode 100644 index 000000000..d0f923d2b --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/docker/Dockerfile @@ -0,0 +1,21 @@ +FROM eclipse-temurin:17 as builder +COPY maven/${project.build.finalName}.jar ./ +RUN java -Djarmode=layertools -jar ${project.build.finalName}.jar extract + +FROM eclipse-temurin:17 +RUN mkdir /workspace +WORKDIR /workspace +COPY --from=builder dependencies/ ./ +COPY --from=builder snapshot-dependencies/ ./ +RUN true +COPY --from=builder spring-boot-loader/ ./ +COPY --from=builder application/ ./ +ENV SPRING_PROFILES_ACTIVE=logEvents,inMemoryStorage,hierarchy +ARG PORT=8080 +ENV SERVER_PORT=${PORT} +ARG CONTEXT_PATH=/ +ENV SERVER_SERVLET_CONTEXT_PATH=${CONTEXT_PATH} +EXPOSE ${SERVER_PORT} +HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=15s CMD curl --fail http://localhost:${SERVER_PORT}${SERVER_SERVLET_CONTEXT_PATH%/}/actuator/health || exit 1 +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/.urandom", "org.springframework.boot.loader.launch.JarLauncher"] + diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml new file mode 100644 index 000000000..7a0adee13 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml @@ -0,0 +1,10 @@ +--- +basyx: + cors: + allowed-origins: "*" + allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" + submodelregistry: + feature: + hierarchy: + enabled: true + \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java new file mode 100644 index 000000000..0134fada4 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.example; + +import org.eclipse.digitaltwin.basyx.submodelregistry.client.api.SubmodelRegistryApi; +import org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.DummyDescriptorFactory; +import org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.HierarchicalSubmodelRegistryTestSuite; + +/** + * HierachicalSubmodelRegistryIT + * + * @author mateusmolina + * + */ +public class HierachicalSubmodelRegistryIT extends HierarchicalSubmodelRegistryTestSuite { + + private static final String ROOT_REGISTRY_URL = "http://localhost:8051"; + private static final String DELEGATED_REGISTRY_URL = "http://localhost:8052"; + + private static final String REPO_BASE_URL = "http://localhost:8080"; + private static final String DELEGATED_SMID = "http://delegated-submodel-registry:8080/test/submodel"; + + private static final DummyDescriptorFactory factory = new DummyDescriptorFactory(REPO_BASE_URL, DELEGATED_SMID); + + private static final SubmodelRegistryApi rootRegistryApi = new SubmodelRegistryApi(ROOT_REGISTRY_URL); + private static final SubmodelRegistryApi delegatedRegistryApi = new SubmodelRegistryApi(DELEGATED_REGISTRY_URL); + + @Override + protected SubmodelRegistryApi getRootRegistryApi() { + return rootRegistryApi; + } + + @Override + protected SubmodelRegistryApi getDelegatedRegistryApi() { + return delegatedRegistryApi; + } + + @Override + protected DummyDescriptorFactory getDescriptorFactory() { + return factory; + } + +} diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/submodel-registry-delegated.yml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/submodel-registry-delegated.yml new file mode 100644 index 000000000..eb3b0feb3 --- /dev/null +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/submodel-registry-delegated.yml @@ -0,0 +1,5 @@ +--- +basyx: + cors: + allowed-origins: "*" + allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" \ No newline at end of file diff --git a/basyx.submodelregistry/pom.xml b/basyx.submodelregistry/pom.xml index 05ebc0a25..f5c3028f9 100644 --- a/basyx.submodelregistry/pom.xml +++ b/basyx.submodelregistry/pom.xml @@ -52,6 +52,7 @@ basyx.submodelregistry-service-release-kafka-mongodb basyx.submodelregistry-feature-authorization basyx.submodelregistry-feature-hierarchy + basyx.submodelregistry-feature-hierarchy-example From 1f7930f560ee81960017140aa702bd0b93119035 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Mon, 2 Dec 2024 15:27:23 +0100 Subject: [PATCH 27/36] fix: aasregistry hierarchy example dockerfile failing to launch --- .../src/main/docker/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/docker/Dockerfile b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/docker/Dockerfile index 2c5546b47..d0f923d2b 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/docker/Dockerfile +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/docker/Dockerfile @@ -1,8 +1,8 @@ -FROM amazoncorretto:17 as builder +FROM eclipse-temurin:17 as builder COPY maven/${project.build.finalName}.jar ./ RUN java -Djarmode=layertools -jar ${project.build.finalName}.jar extract -FROM amazoncorretto:17 +FROM eclipse-temurin:17 RUN mkdir /workspace WORKDIR /workspace COPY --from=builder dependencies/ ./ @@ -17,5 +17,5 @@ ARG CONTEXT_PATH=/ ENV SERVER_SERVLET_CONTEXT_PATH=${CONTEXT_PATH} EXPOSE ${SERVER_PORT} HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=15s CMD curl --fail http://localhost:${SERVER_PORT}${SERVER_SERVLET_CONTEXT_PATH%/}/actuator/health || exit 1 -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/.urandom", "org.springframework.boot.loader.JarLauncher"] +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/.urandom", "org.springframework.boot.loader.launch.JarLauncher"] From 124d0136e6981b8bb9509de754ac9bf87eaee4e6 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Tue, 3 Dec 2024 11:25:40 +0100 Subject: [PATCH 28/36] refactor: extract DelegationStrategy to common --- basyx.common/basyx.hierarchy/pom.xml | 30 ++++++ .../hierarchy/CommonHierarchyProperties.java | 11 +++ .../delegation/DelegationStrategy.java | 48 ++++++++++ .../delegation/PrefixDelegationStrategy.java | 84 +++++++++++++++++ .../PrefixDelegationStrategyTest.java | 93 +++++++++++++++++++ basyx.common/pom.xml | 1 + pom.xml | 5 + 7 files changed, 272 insertions(+) create mode 100644 basyx.common/basyx.hierarchy/pom.xml create mode 100644 basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/CommonHierarchyProperties.java create mode 100644 basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/DelegationStrategy.java create mode 100644 basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategy.java create mode 100644 basyx.common/basyx.hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategyTest.java diff --git a/basyx.common/basyx.hierarchy/pom.xml b/basyx.common/basyx.hierarchy/pom.xml new file mode 100644 index 000000000..e04e5a17d --- /dev/null +++ b/basyx.common/basyx.hierarchy/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + + org.eclipse.digitaltwin.basyx + basyx.common + ${revision} + + basyx.hierarchy + BaSyx Hierarchy Core + BaSyx Hierarchy Core + + + + org.springframework + spring-context + + + org.springframework.boot + spring-boot-starter + + + junit + junit + test + + + + \ No newline at end of file diff --git a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/CommonHierarchyProperties.java b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/CommonHierarchyProperties.java new file mode 100644 index 000000000..5ad7a8fd5 --- /dev/null +++ b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/CommonHierarchyProperties.java @@ -0,0 +1,11 @@ +package org.eclipse.digitaltwin.basyx.common.hierarchy; + +public final class CommonHierarchyProperties { + + private CommonHierarchyProperties() { + } + + public static final String HIERARCHY_FEATURE_NAME = "basyx.feature.hierarchy"; + public static final String HIERARCHY_FEATURE_ENABLED = "basyx.feature.hierarchy.enabled"; + public static final String HIERARCHY_FEATURE_DELEGATION_PREFIX = "basyx.feature.hierarchy.prefix"; +} diff --git a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/DelegationStrategy.java b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/DelegationStrategy.java new file mode 100644 index 000000000..41be5de24 --- /dev/null +++ b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/DelegationStrategy.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.common.hierarchy.delegation; + +import java.util.Optional; + +/** + * DelegationStrategy + * + * @author mateusmolina + * + */ +@FunctionalInterface +public interface DelegationStrategy { + /** + * Builds the URL for the delegation. + * + * @param identifier + * The ID of the AAS for which the delegated registry URL is to be + * built. + * @return An Optional containing the delegated URL if it can be + * constructed, or an empty Optional otherwise. + */ + public Optional buildDelegatedRegistryUrl(String identifier); +} diff --git a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategy.java b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategy.java new file mode 100644 index 000000000..14fc49134 --- /dev/null +++ b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategy.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.common.hierarchy.delegation; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Optional; + +import org.eclipse.digitaltwin.basyx.common.hierarchy.CommonHierarchyProperties; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * Generates delegation URL based on value of the prefix attribute. Default + * value is 'registry'. + * + * @author mateusmolina + * + */ +@Component +public class PrefixDelegationStrategy implements DelegationStrategy { + private final String prefix; + + public PrefixDelegationStrategy(@Value("${" + CommonHierarchyProperties.HIERARCHY_FEATURE_DELEGATION_PREFIX + ":registry}") String prefix) { + this.prefix = prefix; + } + + @Override + public Optional buildDelegatedRegistryUrl(String identifier) { + return Optional.ofNullable(identifier).map(this::extractDelegationUrl); + } + + private String extractDelegationUrl(String identifier) { + URL url; + + try { + url = new URL(identifier); + } catch (MalformedURLException e) { + return null; + } + + String host = url.getHost(); + int port = url.getPort(); + String protocol = url.getProtocol(); + + StringBuilder registryUrl = new StringBuilder(); + + registryUrl.append(protocol).append("://"); + + if (prefix != null && !prefix.isBlank()) + registryUrl.append(prefix).append("."); + + registryUrl.append(host); + + if (port != -1) { + registryUrl.append(":").append(port); + } + + return registryUrl.toString(); + } +} \ No newline at end of file diff --git a/basyx.common/basyx.hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategyTest.java b/basyx.common/basyx.hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategyTest.java new file mode 100644 index 000000000..9bb11ec75 --- /dev/null +++ b/basyx.common/basyx.hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategyTest.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.common.hierarchy.delegation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +/** + * PrefixDelegationStrategyTest + * + * @author mateusmolina + * + */ + +public class PrefixDelegationStrategyTest { + + private PrefixDelegationStrategy prefixDelegationStrategy; + + @Before + public void setUp() { + prefixDelegationStrategy = new PrefixDelegationStrategy("registry"); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithPort() { + String aasId = "http://fraunhofer:8042/example/aas"; + String expectedUrl = "http://registry.fraunhofer:8042"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithoutPort() { + String aasId = "http://fraunhofer/example/aas"; + String expectedUrl = "http://registry.fraunhofer"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithTLD() { + String aasId = "http://fraunhofer.com:8080/example/aas"; + String expectedUrl = "http://registry.fraunhofer.com:8080"; + String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_InvalidUrl() { + String aasId = "invalid_url"; + assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).isEmpty()); + } + + @Test + public void testBuildDelegatedRegistryUrl_WithBlankPrefix() { + PrefixDelegationStrategy blankPrefixDelegationStrategy = new PrefixDelegationStrategy(""); + String aasId = "http://fraunhofer.com:8080/example/aas"; + String expectedUrl = "http://fraunhofer.com:8080"; + String actualUrl = blankPrefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); + assertEquals(expectedUrl, actualUrl); + } + + @Test + public void testBuildDelegatedRegistryUrl_NullAasId() { + assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(null).isEmpty()); + } +} \ No newline at end of file diff --git a/basyx.common/pom.xml b/basyx.common/pom.xml index fe6807eaa..ee719ca26 100644 --- a/basyx.common/pom.xml +++ b/basyx.common/pom.xml @@ -19,6 +19,7 @@ basyx.mqttcore basyx.mongocore basyx.authorization + basyx.hierarchy basyx.client basyx.backend.inmemory.core basyx.filerepository-backend diff --git a/pom.xml b/pom.xml index 34f07eb17..d6f03e000 100644 --- a/pom.xml +++ b/pom.xml @@ -423,6 +423,11 @@ basyx.authorization ${revision} + + org.eclipse.digitaltwin.basyx + basyx.hierarchy + ${revision} + org.eclipse.digitaltwin.basyx basyx.authorization.rules.rbac.backend.inmemory From cc5ccf0eb80559e3f99dc7187085f04ff6ca1e10 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Tue, 3 Dec 2024 11:26:55 +0100 Subject: [PATCH 29/36] refactor: existing feature impl to use the common DelegationStrategy --- .../main/resources/application-hierarchy.yml | 7 +- .../Readme.md | 8 +- .../pom.xml | 4 + .../HierarchicalAasRegistryFeature.java | 9 +- .../HierarchicalAasRegistryStorage.java | 2 +- .../delegation/DelegationStrategy.java | 48 ---------- .../delegation/PrefixDelegationStrategy.java | 85 ----------------- .../PrefixDelegationStrategyTest.java | 93 ------------------- .../src/test/resources/application.yml | 9 +- .../main/resources/application-hierarchy.yml | 7 +- .../Readme.md | 6 +- .../pom.xml | 4 + .../HierarchicalSubmodelRegistryFeature.java | 10 +- .../HierarchicalSubmodelRegistryStorage.java | 2 +- .../delegation/DelegationStrategy.java | 48 ---------- .../delegation/PrefixDelegationStrategy.java | 85 ----------------- .../PrefixDelegationStrategyTest.java | 93 ------------------- .../src/test/resources/application.yml | 9 +- 18 files changed, 39 insertions(+), 490 deletions(-) delete mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java delete mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java delete mode 100644 basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java delete mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/DelegationStrategy.java delete mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java delete mode 100644 basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml index 07bd50c22..2c39855f5 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml @@ -3,8 +3,7 @@ basyx: cors: allowed-origins: "*" allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" - aasregistry: - feature: - hierarchy: - enabled: true + feature: + hierarchy: + enabled: true \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md index 9f496dad9..62fc04185 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md @@ -11,7 +11,7 @@ This feature allows the creation of a hierarchical structure of registries, wher To enable the Hierarchical AasRegistry Feature, add the following property to your Spring application's configuration: ```properties -basyx.aasregistry.feature.hierarchy.enabled=true +basyx.feature.hierarchy.enabled=true ``` ### Delegation Strategy @@ -20,12 +20,12 @@ Currently, only one delegation strategy is implemented: #### Prefix Delegation Strategy -Delegates requests based on the `aasDescriptorId` value. If the ID is an URL, a prefix (defaut `registry`) is appended to the URL and used as delegation endpoint. +Delegates requests based on the `aasDescriptorId` value. If the ID is an URL, a prefix (defaut `registry`) is appended to the URL and used as delegation endpoint. -The prefix can be configured by the property `basyx.aasregistry.feature.hierarchy.prefix`. Please refer to the example below: +The prefix can be configured by the property `basyx.feature.hierarchy.prefix`. Please refer to the example below: ```properties -basyx.aasregistry.feature.hierarchy.prefix=registry +basyx.feature.hierarchy.prefix=registry ``` If this property is left with an empty string, no prefix is appended to the URL contained in the `aasDecriptorId`. diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml index 95ee463b9..caac980ed 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml @@ -12,6 +12,10 @@ basyx.aasregistry-feature-hierarchy + + org.eclipse.digitaltwin.basyx + basyx.hierarchy + org.eclipse.digitaltwin.basyx basyx.aasregistry-service diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java index 8bf39b856..e0ed87497 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java @@ -25,9 +25,10 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation.DelegationStrategy; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorageFeature; +import org.eclipse.digitaltwin.basyx.common.hierarchy.CommonHierarchyProperties; +import org.eclipse.digitaltwin.basyx.common.hierarchy.delegation.DelegationStrategy; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.core.annotation.Order; @@ -44,13 +45,11 @@ * @author mateusmolina */ @Component -@ConditionalOnExpression("${" + HierarchicalAasRegistryFeature.ENABLED_PROPERTY_KEY + ":false}") +@ConditionalOnExpression("${" + CommonHierarchyProperties.HIERARCHY_FEATURE_ENABLED + ":false}") @Order(1) public class HierarchicalAasRegistryFeature implements AasRegistryStorageFeature { - public static final String FEATURENAME = "basyx.aasregistry.feature.hierarchy"; - public static final String ENABLED_PROPERTY_KEY = FEATURENAME + ".enabled"; - @Value("${" + ENABLED_PROPERTY_KEY + "}") + @Value("${" + CommonHierarchyProperties.HIERARCHY_FEATURE_ENABLED + "}") private boolean enabled; private DelegationStrategy delegationStrategy; diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java index b5008150c..428e3e5c6 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java @@ -30,7 +30,6 @@ import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.api.RegistryAndDiscoveryInterfaceApi; -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation.DelegationStrategy; import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchRequest; import org.eclipse.digitaltwin.basyx.aasregistry.model.ShellDescriptorSearchResponse; @@ -41,6 +40,7 @@ import org.eclipse.digitaltwin.basyx.aasregistry.service.errors.SubmodelNotFoundException; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.AasRegistryStorage; import org.eclipse.digitaltwin.basyx.aasregistry.service.storage.DescriptorFilter; +import org.eclipse.digitaltwin.basyx.common.hierarchy.delegation.DelegationStrategy; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java deleted file mode 100644 index df7496a20..000000000 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/DelegationStrategy.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; - -import java.util.Optional; - -/** - * DelegationStrategy - * - * @author mateusmolina - * - */ -@FunctionalInterface -public interface DelegationStrategy { - /** - * Builds the URL for the delegation AAS Registry. - * - * @param aasId - * The ID of the AAS for which the delegated registry URL is to be - * built. - * @return An Optional containing the delegated AAS Registry URL if it can be - * constructed, or an empty Optional otherwise. - */ - public Optional buildDelegatedRegistryUrl(String aasId); -} diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java deleted file mode 100644 index ca2713a6e..000000000 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Optional; - -import org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.HierarchicalAasRegistryFeature; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -/** - * Generates delegation URL based on value of the prefix attribute. Default - * value is 'registry'. - * - * @author mateusmolina - * - */ -@Component -public class PrefixDelegationStrategy implements DelegationStrategy { - public static final String PREFIX_PROPERTY_KEY = HierarchicalAasRegistryFeature.FEATURENAME + ".prefix"; - private final String prefix; - - public PrefixDelegationStrategy(@Value("${" + PREFIX_PROPERTY_KEY + ":registry}") String prefix) { - this.prefix = prefix; - } - - @Override - public Optional buildDelegatedRegistryUrl(String aasId) { - return Optional.ofNullable(aasId).map(this::extractDelegationUrl); - } - - private String extractDelegationUrl(String aasId) { - URL url; - - try { - url = new URL(aasId); - } catch (MalformedURLException e) { - return null; - } - - String host = url.getHost(); - int port = url.getPort(); - String protocol = url.getProtocol(); - - StringBuilder registryUrl = new StringBuilder(); - - registryUrl.append(protocol).append("://"); - - if (prefix != null && !prefix.isBlank()) - registryUrl.append(prefix).append("."); - - registryUrl.append(host); - - if (port != -1) { - registryUrl.append(":").append(port); - } - - return registryUrl.toString(); - } -} \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java deleted file mode 100644 index 105e4fc22..000000000 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy.delegation; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; - -/** - * PrefixDelegationStrategyTest - * - * @author mateusmolina - * - */ - -public class PrefixDelegationStrategyTest { - - private PrefixDelegationStrategy prefixDelegationStrategy; - - @Before - public void setUp() { - prefixDelegationStrategy = new PrefixDelegationStrategy("registry"); - } - - @Test - public void testBuildDelegatedRegistryUrl_WithPort() { - String aasId = "http://fraunhofer:8042/example/aas"; - String expectedUrl = "http://registry.fraunhofer:8042"; - String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testBuildDelegatedRegistryUrl_WithoutPort() { - String aasId = "http://fraunhofer/example/aas"; - String expectedUrl = "http://registry.fraunhofer"; - String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testBuildDelegatedRegistryUrl_WithTLD() { - String aasId = "http://fraunhofer.com:8080/example/aas"; - String expectedUrl = "http://registry.fraunhofer.com:8080"; - String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testBuildDelegatedRegistryUrl_InvalidUrl() { - String aasId = "invalid_url"; - assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).isEmpty()); - } - - @Test - public void testBuildDelegatedRegistryUrl_WithBlankPrefix() { - PrefixDelegationStrategy blankPrefixDelegationStrategy = new PrefixDelegationStrategy(""); - String aasId = "http://fraunhofer.com:8080/example/aas"; - String expectedUrl = "http://fraunhofer.com:8080"; - String actualUrl = blankPrefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testBuildDelegatedRegistryUrl_NullAasId() { - assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(null).isEmpty()); - } -} \ No newline at end of file diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml index 31949762c..32b89c554 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/resources/application.yml @@ -41,8 +41,7 @@ basyx: cors: allowed-origins: "*" allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" - aasregistry: - feature: - hierarchy: - enabled: true - prefix: + feature: + hierarchy: + enabled: true + prefix: \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml index 7a0adee13..2c39855f5 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/main/resources/application-hierarchy.yml @@ -3,8 +3,7 @@ basyx: cors: allowed-origins: "*" allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" - submodelregistry: - feature: - hierarchy: - enabled: true + feature: + hierarchy: + enabled: true \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md index 9dc526c06..7a856df27 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md @@ -11,7 +11,7 @@ This feature allows the creation of a hierarchical structure of registries, wher To enable the Hierarchical SubmodelRegistry Feature, add the following property to your Spring application's configuration: ```properties -basyx.submodelregistry.feature.hierarchy.enabled=true +basyx.feature.hierarchy.enabled=true ``` ### Delegation Strategy @@ -22,10 +22,10 @@ Currently, only one delegation strategy is implemented: Delegates requests based on the `submodelDescriptorId` value. If the ID is an URL, a prefix (defaut `registry`) is appended to the URL and used as delegation endpoint. -The prefix can be configured by the property `basyx.submodelregistry.feature.hierarchy.prefix`. Please refer to the example below: +The prefix can be configured by the property `basyx.feature.hierarchy.prefix`. Please refer to the example below: ```properties -basyx.submodelregistry.feature.hierarchy.prefix=registry +basyx.feature.hierarchy.prefix=registry ``` If this property is left with an empty string, no prefix is appended to the URL contained in the `submodelDecriptorId`. diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml index 03c1531d4..ab0d44995 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml @@ -12,6 +12,10 @@ basyx.submodelregistry-feature-hierarchy + + org.eclipse.digitaltwin.basyx + basyx.hierarchy + org.eclipse.digitaltwin.basyx basyx.submodelregistry-service diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java index 0e477c2f3..095525019 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java @@ -25,7 +25,8 @@ package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy; -import org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation.DelegationStrategy; +import org.eclipse.digitaltwin.basyx.common.hierarchy.CommonHierarchyProperties; +import org.eclipse.digitaltwin.basyx.common.hierarchy.delegation.DelegationStrategy; import org.eclipse.digitaltwin.basyx.submodelregistry.service.storage.SubmodelRegistryStorage; import org.eclipse.digitaltwin.basyx.submodelregistry.service.storage.SubmodelRegistryStorageFeature; import org.springframework.beans.factory.annotation.Value; @@ -44,13 +45,10 @@ * @author mateusmolina */ @Component -@ConditionalOnExpression("${" + HierarchicalSubmodelRegistryFeature.ENABLED_PROPERTY_KEY + ":false}") +@ConditionalOnExpression("${" + CommonHierarchyProperties.HIERARCHY_FEATURE_ENABLED + ":false}") @Order(1) public class HierarchicalSubmodelRegistryFeature implements SubmodelRegistryStorageFeature { - public static final String FEATURENAME = "basyx.submodelregistry.feature.hierarchy"; - public static final String ENABLED_PROPERTY_KEY = FEATURENAME + ".enabled"; - - @Value("${" + ENABLED_PROPERTY_KEY + "}") + @Value("${" + CommonHierarchyProperties.HIERARCHY_FEATURE_ENABLED + "}") private boolean enabled; private DelegationStrategy delegationStrategy; diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java index b539e76d3..6ecb0ade8 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java @@ -28,11 +28,11 @@ import java.util.List; import java.util.Set; +import org.eclipse.digitaltwin.basyx.common.hierarchy.delegation.DelegationStrategy; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.eclipse.digitaltwin.basyx.submodelregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.submodelregistry.client.api.SubmodelRegistryApi; -import org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation.DelegationStrategy; import org.eclipse.digitaltwin.basyx.submodelregistry.model.SubmodelDescriptor; import org.eclipse.digitaltwin.basyx.submodelregistry.service.errors.SubmodelAlreadyExistsException; import org.eclipse.digitaltwin.basyx.submodelregistry.service.errors.SubmodelNotFoundException; diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/DelegationStrategy.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/DelegationStrategy.java deleted file mode 100644 index 250b06d15..000000000 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/DelegationStrategy.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation; - -import java.util.Optional; - -/** - * DelegationStrategy - * - * @author mateusmolina - * - */ -@FunctionalInterface -public interface DelegationStrategy { - /** - * Builds the URL for the delegation AAS Registry. - * - * @param aasId - * The ID of the AAS for which the delegated registry URL is to be - * built. - * @return An Optional containing the delegated AAS Registry URL if it can be - * constructed, or an empty Optional otherwise. - */ - public Optional buildDelegatedRegistryUrl(String aasId); -} diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java deleted file mode 100644 index bbdaf5113..000000000 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategy.java +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Optional; - -import org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.HierarchicalSubmodelRegistryFeature; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -/** - * Generates delegation URL based on value of the prefix attribute. Default - * value is 'registry'. - * - * @author mateusmolina - * - */ -@Component -public class PrefixDelegationStrategy implements DelegationStrategy { - public static final String PREFIX_PROPERTY_KEY = HierarchicalSubmodelRegistryFeature.FEATURENAME + ".prefix"; - private final String prefix; - - public PrefixDelegationStrategy(@Value("${" + PREFIX_PROPERTY_KEY + ":registry}") String prefix) { - this.prefix = prefix; - } - - @Override - public Optional buildDelegatedRegistryUrl(String smId) { - return Optional.ofNullable(smId).map(this::extractDelegationUrl); - } - - private String extractDelegationUrl(String smId) { - URL url; - - try { - url = new URL(smId); - } catch (MalformedURLException e) { - return null; - } - - String host = url.getHost(); - int port = url.getPort(); - String protocol = url.getProtocol(); - - StringBuilder registryUrl = new StringBuilder(); - - registryUrl.append(protocol).append("://"); - - if (prefix != null && !prefix.isBlank()) - registryUrl.append(prefix).append("."); - - registryUrl.append(host); - - if (port != -1) { - registryUrl.append(":").append(port); - } - - return registryUrl.toString(); - } -} \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java deleted file mode 100644 index c03941de8..000000000 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/delegation/PrefixDelegationStrategyTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy.delegation; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; - -/** - * PrefixDelegationStrategyTest - * - * @author mateusmolina - * - */ - -public class PrefixDelegationStrategyTest { - - private PrefixDelegationStrategy prefixDelegationStrategy; - - @Before - public void setUp() { - prefixDelegationStrategy = new PrefixDelegationStrategy("registry"); - } - - @Test - public void testBuildDelegatedRegistryUrl_WithPort() { - String aasId = "http://fraunhofer:8042/example/aas"; - String expectedUrl = "http://registry.fraunhofer:8042"; - String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testBuildDelegatedRegistryUrl_WithoutPort() { - String aasId = "http://fraunhofer/example/aas"; - String expectedUrl = "http://registry.fraunhofer"; - String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testBuildDelegatedRegistryUrl_WithTLD() { - String aasId = "http://fraunhofer.com:8080/example/aas"; - String expectedUrl = "http://registry.fraunhofer.com:8080"; - String actualUrl = prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testBuildDelegatedRegistryUrl_InvalidUrl() { - String aasId = "invalid_url"; - assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).isEmpty()); - } - - @Test - public void testBuildDelegatedRegistryUrl_WithBlankPrefix() { - PrefixDelegationStrategy blankPrefixDelegationStrategy = new PrefixDelegationStrategy(""); - String aasId = "http://fraunhofer.com:8080/example/aas"; - String expectedUrl = "http://fraunhofer.com:8080"; - String actualUrl = blankPrefixDelegationStrategy.buildDelegatedRegistryUrl(aasId).get(); - assertEquals(expectedUrl, actualUrl); - } - - @Test - public void testBuildDelegatedRegistryUrl_NullAasId() { - assertTrue(prefixDelegationStrategy.buildDelegatedRegistryUrl(null).isEmpty()); - } -} \ No newline at end of file diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/resources/application.yml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/resources/application.yml index cea367045..9a6351f54 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/resources/application.yml +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/resources/application.yml @@ -39,8 +39,7 @@ basyx: cors: allowed-origins: "*" allowed-methods: "GET,POST,PATCH,DELETE,PUT,OPTIONS,HEAD" - submodelregistry: - feature: - hierarchy: - enabled: true - prefix: + feature: + hierarchy: + enabled: true + prefix: From 92bff5c5d465cdb74753f4356467ff69e42b95f7 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Tue, 3 Dec 2024 11:34:14 +0100 Subject: [PATCH 30/36] chore: update POM names --- basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml | 1 + .../basyx.submodelregistry-feature-hierarchy/pom.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml index caac980ed..76fd301fe 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/pom.xml @@ -10,6 +10,7 @@ basyx.aasregistry-feature-hierarchy + BaSyx AAS Registry feature-hierarchy diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml index ab0d44995..106f97287 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/pom.xml @@ -10,6 +10,7 @@ basyx.submodelregistry-feature-hierarchy + BaSyx Submodel Registry feature-hierarchy From 4dce1f6f08f7dac36a72a6cf927a4debf4e69ec1 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Tue, 3 Dec 2024 11:44:20 +0100 Subject: [PATCH 31/36] test: fix components not finding DelegationStrategy bean --- .../feature/hierarchy/DummyAasRegistryComponent.java | 2 +- .../feature/hierarchy/DummySubmodelRegistryComponent.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java index a3f5fd0a0..e749a2acb 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java @@ -35,7 +35,7 @@ * */ @SpringBootApplication(scanBasePackages = { "org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy", "org.eclipse.digitaltwin.basyx.aasregistry.service.api", "org.eclipse.digitaltwin.basyx.aasregistry.service.events", - "org.eclipse.digitaltwin.basyx.aasregistry.service.configuration", "org.eclipse.digitaltwin.basyx.aasregistry.service.errors" }) + "org.eclipse.digitaltwin.basyx.aasregistry.service.configuration", "org.eclipse.digitaltwin.basyx.aasregistry.service.errors", "org.eclipse.digitaltwin.basyx.common.hierarchy" }) public class DummyAasRegistryComponent { public static void main(String[] args) { SpringApplication.run(DummyAasRegistryComponent.class, args); diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java index adb2046a5..355162dd9 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java @@ -35,7 +35,7 @@ * */ @SpringBootApplication(scanBasePackages = { "org.eclipse.digitaltwin.basyx.submodelregistry.feature.hierarchy", "org.eclipse.digitaltwin.basyx.submodelregistry.service.api", "org.eclipse.digitaltwin.basyx.submodelregistry.service.events", - "org.eclipse.digitaltwin.basyx.submodelregistry.service.configuration", "org.eclipse.digitaltwin.basyx.submodelregistry.service.errors" }) + "org.eclipse.digitaltwin.basyx.submodelregistry.service.configuration", "org.eclipse.digitaltwin.basyx.submodelregistry.service.errors", "org.eclipse.digitaltwin.basyx.common.hierarchy" }) public class DummySubmodelRegistryComponent { public static void main(String[] args) { SpringApplication.run(DummySubmodelRegistryComponent.class, args); From 49bc8f62fbfbea29483b80e172e70470708d86f8 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Tue, 3 Dec 2024 13:51:39 +0100 Subject: [PATCH 32/36] test: refactor aasregistry fixture factory to be consistent with smregistry.hierarchy --- .../hierarchy/DummyDescriptorFactory.java | 36 ++++++++++++------- .../HierarchicalAasRegistryTestSuite.java | 24 ++++++------- .../LocalhostHierarchicalAasRegistryTest.java | 3 +- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java index 42ecf4c79..512b3217d 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java @@ -43,33 +43,43 @@ * */ public class DummyDescriptorFactory { - static final String AASDESCRIPTOR_ID_ROOTONLY = "AASDESCRIPTOR_ID_ROOTONLY"; - static final String SMDESCRIPTOR_ID_ROOTONLY = "SMDESCRIPTOR_ID_ROOTONLY"; + static final String ROOT_ONLY_AASDESCRIPTOR_ID = "AASDESCRIPTOR_ID_ROOTONLY"; + static final String ROOT_ONLY_SMDESCRIPTOR_ID = "SMDESCRIPTOR_ID_ROOTONLY"; + static final String DELEGATED_ONLY_SMDESCRIPTOR_ID = "SMDESCRIPTOR_ID_DELEGATEDONLY"; - static String AASDESCRIPTOR_ID_DELEGATEDONLY; - static final String SMDESCRIPTOR_ID_DELEGATEDONLY = "SMDESCRIPTOR_ID_DELEGATEDONLY"; + private static final String AAS_INTERFACE = "AAS-3.0"; + private static final String SM_INTERFACE = "SUBMODEL-3.0"; - static String REPO_BASE_URL; + private final String delegatedOnlyAasDescriptorId; + private final String repoBaseUrl; public DummyDescriptorFactory(String repoBaseUrl, String delegatedAasId) { - AASDESCRIPTOR_ID_DELEGATEDONLY = delegatedAasId; - REPO_BASE_URL = repoBaseUrl; + this.delegatedOnlyAasDescriptorId = delegatedAasId; + this.repoBaseUrl = repoBaseUrl; } AssetAdministrationShellDescriptor getAasDescriptor_RootOnly() { - return createDummyDescriptor(REPO_BASE_URL, AASDESCRIPTOR_ID_ROOTONLY, buildIdShort(AASDESCRIPTOR_ID_ROOTONLY), getSmDescriptor_RootOnly()); + return createDummyDescriptor(repoBaseUrl, ROOT_ONLY_AASDESCRIPTOR_ID, buildIdShort(ROOT_ONLY_AASDESCRIPTOR_ID), getSmDescriptor_RootOnly()); } SubmodelDescriptor getSmDescriptor_RootOnly() { - return createDummySubmodelDescriptor(REPO_BASE_URL, SMDESCRIPTOR_ID_ROOTONLY, buildIdShort(SMDESCRIPTOR_ID_ROOTONLY)); + return createDummySubmodelDescriptor(repoBaseUrl, ROOT_ONLY_SMDESCRIPTOR_ID, buildIdShort(ROOT_ONLY_SMDESCRIPTOR_ID)); } AssetAdministrationShellDescriptor getAasDescriptor_DelegatedOnly() { - return createDummyDescriptor(REPO_BASE_URL, AASDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(AASDESCRIPTOR_ID_DELEGATEDONLY), getSmDescriptor_DelegatedOnly()); + return createDummyDescriptor(repoBaseUrl, delegatedOnlyAasDescriptorId, buildIdShort(delegatedOnlyAasDescriptorId), getSmDescriptor_DelegatedOnly()); } SubmodelDescriptor getSmDescriptor_DelegatedOnly() { - return createDummySubmodelDescriptor(REPO_BASE_URL, SMDESCRIPTOR_ID_DELEGATEDONLY, buildIdShort(SMDESCRIPTOR_ID_DELEGATEDONLY)); + return createDummySubmodelDescriptor(repoBaseUrl, DELEGATED_ONLY_SMDESCRIPTOR_ID, buildIdShort(DELEGATED_ONLY_SMDESCRIPTOR_ID)); + } + + String getDelegatedOnlyAasDescriptorId() { + return delegatedOnlyAasDescriptorId; + } + + String getRepoBaseUrl() { + return repoBaseUrl; } private static AssetAdministrationShellDescriptor createDummyDescriptor(String baseUrl, String shellId, String shellIdShort, SubmodelDescriptor submodelDescriptor) { @@ -88,7 +98,7 @@ private static AssetAdministrationShellDescriptor createDummyDescriptor(String b private static SubmodelDescriptor createDummySubmodelDescriptor(String baseUrl, String submodelId, String submodelIdShort) { SubmodelDescriptor descriptor = new SubmodelDescriptor().id(submodelId); descriptor.setIdShort(submodelIdShort); - descriptor.setEndpoints(List.of(new Endpoint()._interface("AAS-3.0").protocolInformation(createSmProtocolInformation(baseUrl, submodelId)))); + descriptor.setEndpoints(List.of(new Endpoint()._interface(SM_INTERFACE).protocolInformation(createSmProtocolInformation(baseUrl, submodelId)))); return descriptor; } @@ -96,7 +106,7 @@ private static SubmodelDescriptor createDummySubmodelDescriptor(String baseUrl, private static void setEndpointItem(String baseUrl, String shellId, AssetAdministrationShellDescriptor descriptor) { ProtocolInformation protocolInformation = createProtocolInformation(baseUrl, shellId); - Endpoint endpoint = new Endpoint()._interface("AAS-3.0").protocolInformation(protocolInformation); + Endpoint endpoint = new Endpoint()._interface(AAS_INTERFACE).protocolInformation(protocolInformation); descriptor.addEndpointsItem(endpoint); } diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java index c29ac8aa8..99bcb8573 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java @@ -25,11 +25,8 @@ package org.eclipse.digitaltwin.basyx.aasregistry.feature.hierarchy; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; +import static org.junit.Assert.*; -import java.io.FileNotFoundException; -import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -55,7 +52,7 @@ public abstract class HierarchicalAasRegistryTestSuite { protected abstract DummyDescriptorFactory getDescriptorFactory(); @Before - public void setUp() throws FileNotFoundException, IOException, ApiException { + public void setUp() throws ApiException { cleanUpRegistries(); setupDelegatedRegistry(); setupRootRegistry(); @@ -63,7 +60,7 @@ public void setUp() throws FileNotFoundException, IOException, ApiException { @Test public void getAasDescriptor_InRoot() throws ApiException { - AssetAdministrationShellDescriptor actualDescriptor = getRootRegistryApi().getAssetAdministrationShellDescriptorById(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY); + AssetAdministrationShellDescriptor actualDescriptor = getRootRegistryApi().getAssetAdministrationShellDescriptorById(DummyDescriptorFactory.ROOT_ONLY_AASDESCRIPTOR_ID); AssetAdministrationShellDescriptor expectedDescriptor = getDescriptorFactory().getAasDescriptor_RootOnly(); @@ -72,7 +69,7 @@ public void getAasDescriptor_InRoot() throws ApiException { @Test public void getAasDescriptor_ThroughDelegated() throws ApiException { - AssetAdministrationShellDescriptor actualDescriptor = getRootRegistryApi().getAssetAdministrationShellDescriptorById(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY); + AssetAdministrationShellDescriptor actualDescriptor = getRootRegistryApi().getAssetAdministrationShellDescriptorById(getDescriptorFactory().getDelegatedOnlyAasDescriptorId()); AssetAdministrationShellDescriptor expectedDescriptor = getDescriptorFactory().getAasDescriptor_DelegatedOnly(); @@ -87,7 +84,7 @@ public void getNonExistingAasDescriptor() { @Test public void getSubmodelDescriptor_InRoot() throws ApiException { - SubmodelDescriptor actualDescriptor = getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_ROOTONLY); + SubmodelDescriptor actualDescriptor = getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.ROOT_ONLY_AASDESCRIPTOR_ID, DummyDescriptorFactory.ROOT_ONLY_SMDESCRIPTOR_ID); SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getSmDescriptor_RootOnly(); @@ -96,7 +93,7 @@ public void getSubmodelDescriptor_InRoot() throws ApiException { @Test public void getSubmodelDescriptor_ThroughDelegated() throws ApiException { - SubmodelDescriptor actualDescriptor = getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, DummyDescriptorFactory.SMDESCRIPTOR_ID_DELEGATEDONLY); + SubmodelDescriptor actualDescriptor = getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(getDescriptorFactory().getDelegatedOnlyAasDescriptorId(), DummyDescriptorFactory.DELEGATED_ONLY_SMDESCRIPTOR_ID); SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getSmDescriptor_DelegatedOnly(); @@ -105,7 +102,7 @@ public void getSubmodelDescriptor_ThroughDelegated() throws ApiException { @Test public void getAllSubmodelDescriptor_InRoot() throws ApiException { - GetSubmodelDescriptorsResult actualDescriptors = getRootRegistryApi().getAllSubmodelDescriptorsThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, 1, null); + GetSubmodelDescriptorsResult actualDescriptors = getRootRegistryApi().getAllSubmodelDescriptorsThroughSuperpath(DummyDescriptorFactory.ROOT_ONLY_AASDESCRIPTOR_ID, 1, null); SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getSmDescriptor_RootOnly(); @@ -117,7 +114,7 @@ public void getAllSubmodelDescriptor_InRoot() throws ApiException { @Test public void getAllSubmodelDescriptor_ThroughDelegated() throws ApiException { getDescriptorFactory(); - GetSubmodelDescriptorsResult actualDescriptors = getRootRegistryApi().getAllSubmodelDescriptorsThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, 1, null); + GetSubmodelDescriptorsResult actualDescriptors = getRootRegistryApi().getAllSubmodelDescriptorsThroughSuperpath(getDescriptorFactory().getDelegatedOnlyAasDescriptorId(), 1, null); SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getSmDescriptor_DelegatedOnly(); @@ -128,11 +125,10 @@ public void getAllSubmodelDescriptor_ThroughDelegated() throws ApiException { @Test public void getNonExistingSmDescriptor() { - ApiException exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_ROOTONLY, - "nonExistingSubmodel")); + ApiException exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.ROOT_ONLY_AASDESCRIPTOR_ID, "nonExistingSubmodel")); assertHttpCodeIsNotFound(exception); - exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(DummyDescriptorFactory.AASDESCRIPTOR_ID_DELEGATEDONLY, "nonExistingSubmodel")); + exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath(getDescriptorFactory().getDelegatedOnlyAasDescriptorId(), "nonExistingSubmodel")); assertHttpCodeIsNotFound(exception); exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorByIdThroughSuperpath("nonExistingAas", "nonExistingSubmodel")); diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java index 61038538c..af32a6ed0 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java @@ -47,6 +47,7 @@ public class LocalhostHierarchicalAasRegistryTest extends HierarchicalAasRegistr private static final RegistryAndDiscoveryInterfaceApi rootRegistryApi = new RegistryAndDiscoveryInterfaceApi(ROOT_REGISTRY_URL); private static final RegistryAndDiscoveryInterfaceApi delegatedRegistryApi = new RegistryAndDiscoveryInterfaceApi(DELEGATED_REGISTRY_URL); + private static final DummyDescriptorFactory factory = new DummyDescriptorFactory(REPO_BASE_URL, DELEGATED_AASID); private static ConfigurableApplicationContext appContext; @@ -72,7 +73,7 @@ protected RegistryAndDiscoveryInterfaceApi getDelegatedRegistryApi() { @Override protected DummyDescriptorFactory getDescriptorFactory() { - return new DummyDescriptorFactory(REPO_BASE_URL, DELEGATED_AASID); + return factory; } } From bc569a56806fbedb87d7e11ba7f4d9e6c04446a4 Mon Sep 17 00:00:00 2001 From: mateusmolina Date: Tue, 3 Dec 2024 14:06:27 +0100 Subject: [PATCH 33/36] fix: it tests not working due to common.hierarchy not being found --- .../templates/openapi2SpringBoot.mustache | 2 +- .../templates/openapi2SpringBoot.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basyx.aasregistry/basyx.aasregistry-service/templates/openapi2SpringBoot.mustache b/basyx.aasregistry/basyx.aasregistry-service/templates/openapi2SpringBoot.mustache index 14b449123..72601025b 100644 --- a/basyx.aasregistry/basyx.aasregistry-service/templates/openapi2SpringBoot.mustache +++ b/basyx.aasregistry/basyx.aasregistry-service/templates/openapi2SpringBoot.mustache @@ -15,7 +15,7 @@ import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGe nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class ) @ComponentScan( - basePackages = {"org.eclipse.digitaltwin.basyx.authorization", "org.eclipse.digitaltwin.basyx.authorization.rbac", "org.eclipse.digitaltwin.basyx.aasregistry.feature", "{{basePackage}}", "{{apiPackage}}" , "{{configPackage}}"}, + basePackages = {"org.eclipse.digitaltwin.basyx.authorization", "org.eclipse.digitaltwin.basyx.common.hierarchy", "org.eclipse.digitaltwin.basyx.authorization.rbac", "org.eclipse.digitaltwin.basyx.aasregistry.feature", "{{basePackage}}", "{{apiPackage}}" , "{{configPackage}}"}, nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class ) public class OpenApiGeneratorApplication { diff --git a/basyx.submodelregistry/basyx.submodelregistry-service/templates/openapi2SpringBoot.mustache b/basyx.submodelregistry/basyx.submodelregistry-service/templates/openapi2SpringBoot.mustache index 3778320ee..8805ecb78 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-service/templates/openapi2SpringBoot.mustache +++ b/basyx.submodelregistry/basyx.submodelregistry-service/templates/openapi2SpringBoot.mustache @@ -15,7 +15,7 @@ import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGe nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class ) @ComponentScan( - basePackages = {"org.eclipse.digitaltwin.basyx.authorization", "org.eclipse.digitaltwin.basyx.authorization.rbac", "org.eclipse.digitaltwin.basyx.submodelregistry.feature", "{{basePackage}}", "{{apiPackage}}" , "{{configPackage}}"}, + basePackages = {"org.eclipse.digitaltwin.basyx.authorization", "org.eclipse.digitaltwin.basyx.common.hierarchy", "org.eclipse.digitaltwin.basyx.authorization.rbac", "org.eclipse.digitaltwin.basyx.submodelregistry.feature", "{{basePackage}}", "{{apiPackage}}" , "{{configPackage}}"}, nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class ) public class OpenApiGeneratorApplication { From 6923996f7dc457086307847a82ce831079988285 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Thu, 30 Jan 2025 08:28:40 +0100 Subject: [PATCH 34/36] docs: reminder of retriving all descriptors not being supported by the feature --- basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md | 2 ++ .../basyx.submodelregistry-feature-hierarchy/Readme.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md index 62fc04185..2da37451d 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/Readme.md @@ -4,6 +4,8 @@ The Hierarchical AasRegistry Feature enhances the availability of data across mu This feature allows the creation of a hierarchical structure of registries, where a registry can delegate retrieval requests to another registry when a given descriptor is not found in its storage. +Retrieving all the stored AasDescriptors with delegation is not currently supported. + ## Configuration ### Enabling the Feature diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md index 7a856df27..a8fb07a87 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/Readme.md @@ -4,6 +4,8 @@ The Hierarchical SubmodelRegistry Feature enhances the availability of data acro This feature allows the creation of a hierarchical structure of registries, where a registry can delegate retrieval requests to another registry when a given descriptor is not found in its storage. +Retrieving all the stored SubmodelDescriptors with delegation is not currently supported. + ## Configuration ### Enabling the Feature From 45a9078f4c9a6a85b8c6d8dab54cd009e013bba2 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Thu, 30 Jan 2025 08:30:23 +0100 Subject: [PATCH 35/36] test: remove unrelated test --- .../HierarchicalSubmodelRegistryTestSuite.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java index ac24c9f46..d9fe61cc5 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java @@ -77,17 +77,6 @@ public void getSubmodelDescriptor_ThroughDelegated() throws ApiException { assertEquals(expectedDescriptor, actualDescriptor); } - @Test - public void getAllSubmodelDescriptor_InRoot() throws ApiException { - GetSubmodelDescriptorsResult actualDescriptors = getRootRegistryApi().getAllSubmodelDescriptors(1, null); - - SubmodelDescriptor expectedDescriptor = getDescriptorFactory().getRootOnlySmDescriptor(); - - List expectedDescriptors = Arrays.asList(expectedDescriptor); - - assertEquals(expectedDescriptors, actualDescriptors.getResult()); - } - @Test public void getNonExistingSmDescriptor() { ApiException exception = assertThrows(ApiException.class, () -> getRootRegistryApi().getSubmodelDescriptorById("nonExistingSubmodel")); From f6b2ae048511c88e2c3decfb801a2f2899068a30 Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Thu, 30 Jan 2025 08:36:17 +0100 Subject: [PATCH 36/36] docs: bump license header year; add missing --- .../example/HierachicalAasRegistryIT.java | 2 +- .../hierarchy/AasRegistryModelMapper.java | 2 +- .../HierarchicalAasRegistryFeature.java | 2 +- .../HierarchicalAasRegistryStorage.java | 2 +- .../hierarchy/DummyAasRegistryComponent.java | 2 +- .../hierarchy/DummyDescriptorFactory.java | 2 +- .../HierarchicalAasRegistryTestSuite.java | 2 +- .../LocalhostHierarchicalAasRegistryTest.java | 2 +- .../hierarchy/CommonHierarchyProperties.java | 31 +++++++++++++++++++ .../delegation/DelegationStrategy.java | 4 +-- .../delegation/PrefixDelegationStrategy.java | 2 +- .../PrefixDelegationStrategyTest.java | 4 +-- .../HierachicalSubmodelRegistryIT.java | 2 +- .../HierarchicalSubmodelRegistryFeature.java | 2 +- .../HierarchicalSubmodelRegistryStorage.java | 2 +- .../SubmodelRegistryModelMapper.java | 2 +- .../hierarchy/DummyDescriptorFactory.java | 2 +- .../DummySubmodelRegistryComponent.java | 2 +- ...HierarchicalSubmodelRegistryTestSuite.java | 2 +- ...lhostHierarchicalSubmodelRegistryTest.java | 2 +- 20 files changed, 52 insertions(+), 21 deletions(-) diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java index 1266d3d0a..b26e02877 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/example/HierachicalAasRegistryIT.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java index 791071dfc..5b529dc86 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/AasRegistryModelMapper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java index e0ed87497..c529cda18 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryFeature.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java index 428e3e5c6..99fa733e6 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryStorage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java index e749a2acb..0303fe138 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyAasRegistryComponent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java index 512b3217d..cc15921ae 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/DummyDescriptorFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java index 99bcb8573..21630a98a 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/HierarchicalAasRegistryTestSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java index af32a6ed0..faed85b39 100644 --- a/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java +++ b/basyx.aasregistry/basyx.aasregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/aasregistry/feature/hierarchy/LocalhostHierarchicalAasRegistryTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/CommonHierarchyProperties.java b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/CommonHierarchyProperties.java index 5ad7a8fd5..5be4a9dda 100644 --- a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/CommonHierarchyProperties.java +++ b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/CommonHierarchyProperties.java @@ -1,5 +1,36 @@ +/******************************************************************************* + * Copyright (C) 2025 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + package org.eclipse.digitaltwin.basyx.common.hierarchy; +/** + * Common configuration properties for the hierarchical feature + * + * @author mateusmolina + * + */ public final class CommonHierarchyProperties { private CommonHierarchyProperties() { diff --git a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/DelegationStrategy.java b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/DelegationStrategy.java index 41be5de24..5b04320ee 100644 --- a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/DelegationStrategy.java +++ b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/DelegationStrategy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ import java.util.Optional; /** - * DelegationStrategy + * Interface for delegation strategies used by the hierarchical feature * * @author mateusmolina * diff --git a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategy.java b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategy.java index 14fc49134..cd62ec360 100644 --- a/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategy.java +++ b/basyx.common/basyx.hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.common/basyx.hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategyTest.java b/basyx.common/basyx.hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategyTest.java index 9bb11ec75..8b29aecf1 100644 --- a/basyx.common/basyx.hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategyTest.java +++ b/basyx.common/basyx.hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/common/hierarchy/delegation/PrefixDelegationStrategyTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ import org.junit.Test; /** - * PrefixDelegationStrategyTest + * Test for the PrefixDelegationStrategy * * @author mateusmolina * diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java index 0134fada4..2ea2f73e3 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy-example/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/example/HierachicalSubmodelRegistryIT.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java index 095525019..d831837b5 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryFeature.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java index 6ecb0ade8..23e231be1 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryStorage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/SubmodelRegistryModelMapper.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/SubmodelRegistryModelMapper.java index 2a48f99c7..54dcd9f2b 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/SubmodelRegistryModelMapper.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/main/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/SubmodelRegistryModelMapper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummyDescriptorFactory.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummyDescriptorFactory.java index 222b9323c..3c78999e3 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummyDescriptorFactory.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummyDescriptorFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java index 355162dd9..35835275d 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/DummySubmodelRegistryComponent.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java index d9fe61cc5..2ec82f112 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/HierarchicalSubmodelRegistryTestSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff --git a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/LocalhostHierarchicalSubmodelRegistryTest.java b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/LocalhostHierarchicalSubmodelRegistryTest.java index f571c1124..bb7e2c3b4 100644 --- a/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/LocalhostHierarchicalSubmodelRegistryTest.java +++ b/basyx.submodelregistry/basyx.submodelregistry-feature-hierarchy/src/test/java/org/eclipse/digitaltwin/basyx/submodelregistry/feature/hierarchy/LocalhostHierarchicalSubmodelRegistryTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors + * Copyright (C) 2025 the Eclipse BaSyx Authors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the