From 5b61ba49cdb6548f496d19da6ff7c8a9efa26f97 Mon Sep 17 00:00:00 2001 From: Frank Schnicke Date: Mon, 3 Apr 2023 14:44:24 +0200 Subject: [PATCH 01/63] Updates version to 1.5.0-SNAPSHOT Signed-off-by: Frank Schnicke --- .../basyx.components.AASServer/pom.xml | 4 ++-- .../basyx.components.AASServer/src/test/resources/.env | 2 +- .../basyx.components.registry/pom.xml | 2 +- .../basyx.components.registry/src/test/resources/.env | 2 +- basyx.components/basyx.components.docker/pom.xml | 4 ++-- basyx.components/basyx.components.lib/pom.xml | 2 +- basyx.components/pom.xml | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 36777c42..6bc7786c 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -7,7 +7,7 @@ org.eclipse.basyx basyx.components.docker - 1.4.0 + 1.5.0-SNAPSHOT basyx.components.AASServer @@ -121,7 +121,7 @@ org.eclipse.basyx basyx.components.registry - 1.4.0 + 1.5.0-SNAPSHOT test diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env index 6a62d5eb..e028edd1 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env @@ -28,7 +28,7 @@ BASYX_IMAGE_NAME=eclipsebasyx/aas-server # ################## # The image tag of the image that is build for this component -BASYX_IMAGE_TAG=1.4.0 +BASYX_IMAGE_TAG=1.5.0-SNAPSHOT # ################## # Container Name diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index a5dadd74..aba697e5 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -6,7 +6,7 @@ org.eclipse.basyx basyx.components.docker - 1.4.0 + 1.5.0-SNAPSHOT basyx.components.registry diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env b/basyx.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env index 733ae6fa..b7c472cc 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env +++ b/basyx.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env @@ -28,7 +28,7 @@ BASYX_IMAGE_NAME=eclipsebasyx/aas-registry # ################## # The image tag of the image that is build for this component -BASYX_IMAGE_TAG=1.4.0 +BASYX_IMAGE_TAG=1.5.0-SNAPSHOT # ################## # Container Name diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index 1962072a..19676fdf 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -7,7 +7,7 @@ org.eclipse.basyx basyx.components - 1.4.0 + 1.5.0-SNAPSHOT basyx.components.docker @@ -223,7 +223,7 @@ org.eclipse.basyx basyx.components.lib - 1.4.0 + 1.5.0-SNAPSHOT diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 1b7fe57f..417c261c 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -6,7 +6,7 @@ org.eclipse.basyx basyx.components - 1.4.0 + 1.5.0-SNAPSHOT basyx.components.lib diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index c1eb7622..833648be 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -5,7 +5,7 @@ org.eclipse.basyx basyx.components - 1.4.0 + 1.5.0-SNAPSHOT BaSyx Components BaSyx Off-the-Shelf Components https://www.eclipse.org/basyx/ @@ -277,14 +277,14 @@ org.eclipse.basyx basyx.sdk - 1.4.0 + 1.5.0-SNAPSHOT org.eclipse.basyx basyx.sdk - 1.4.0 + 1.5.0-SNAPSHOT tests test From 6d4f1041e77c8ecab5b28f44fe6ec4d5c179d1d9 Mon Sep 17 00:00:00 2001 From: Frank Schnicke <77283144+FrankSchnicke@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:48:23 +0200 Subject: [PATCH 02/63] Update pom.xml --- basyx.components/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index 833648be..69e9bf9b 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -33,6 +33,10 @@ false + + Eclipse BaSyx SDK GitHub Packages + https://maven.pkg.github.com/eclipse-basyx/basyx-java-sdk + From 0a3699d1f6e55c7df8d6ccc683c877fc65459701 Mon Sep 17 00:00:00 2001 From: Frank Schnicke <77283144+FrankSchnicke@users.noreply.github.com> Date: Wed, 5 Apr 2023 09:59:56 +0200 Subject: [PATCH 03/63] Fixes MongoDBAASAggregator opening a mongo connection per AAS (#317) Signed-off-by: Frank Schnicke --- .../aas/mongodb/MongoDBAASAggregator.java | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java index fbbc7322..5f440dcb 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java @@ -115,6 +115,8 @@ public class MongoDBAASAggregator implements IAASAggregator { protected ISubmodelAggregator submodelAggregator; protected ISubmodelAggregatorFactory submodelAggregatorFactory; + private MongoClient mongoClient; + /** * Receives a BaSyxMongoDBConfiguration and a registry to create a persistent * MongoDB backend. @@ -417,31 +419,18 @@ public void setRegistry(IAASRegistry registry) { * @deprecated This method is used with the old, deprecated Constructors. Use * {@link MongoDBAASServerComponentFactory} instead */ - @SuppressWarnings("deprecation") @Deprecated public void setConfiguration(BaSyxMongoDBConfiguration config) { - // set mongoDB configuration - this.config = config; MongoClient client = MongoClients.create(config.getConnectionUrl()); - this.mongoOps = new MongoTemplate(client, config.getDatabase()); - this.aasCollection = config.getAASCollection(); - this.smCollection = config.getSubmodelCollection(); + setMongoDBConfiguration(config, client); - // Create API factories with the given configuration - this.aasApiProvider = aas -> { - MongoDBAASAPI api = new MongoDBAASAPI(config, aas.getIdentification().getId()); - api.setAAS(aas); - return api; - }; - this.smApiProvider = sm -> { - MongoDBSubmodelAPI api = new MongoDBSubmodelAPI(config, sm.getIdentification().getId()); - api.setSubmodel(sm); - return api; - }; + this.aasApiProvider = new MongoDBAASAPIFactory(config, client); + this.smApiProvider = new MongoDBSubmodelAPIFactory(config, client); } private void setMongoDBConfiguration(BaSyxMongoDBConfiguration config, MongoClient client) { this.config = config; + this.mongoClient = client; this.mongoOps = new MongoTemplate(client, config.getDatabase()); this.aasCollection = config.getAASCollection(); this.smCollection = config.getSubmodelCollection(); @@ -456,13 +445,12 @@ public void reset() { aasProviderMap.clear(); } - @SuppressWarnings("deprecation") private void init() { List data = mongoOps.findAll(AssetAdministrationShell.class, aasCollection); for (AssetAdministrationShell aas : data) { String aasId = aas.getIdentification().getId(); logger.info("Adding AAS from DB: " + aasId); - MongoDBAASAPI aasApi = new MongoDBAASAPI(config, aasId); + MongoDBAASAPI aasApi = new MongoDBAASAPI(config, aasId, mongoClient); MultiSubmodelProvider provider = createMultiSubmodelProvider(aasApi); addSubmodelsFromDB(provider, aas); aasProviderMap.put(aas.getIdentification().getId(), provider); @@ -531,9 +519,8 @@ private String getSubmodelId(String idShort) { return null; } - @SuppressWarnings("deprecation") private void addSubmodelProvidersById(String smId, MultiSubmodelProvider provider) { - ISubmodelAPI smApi = new MongoDBSubmodelAPI(config, smId); + ISubmodelAPI smApi = new MongoDBSubmodelAPI(config, smId, mongoClient); SubmodelProvider smProvider = new SubmodelProvider(smApi); provider.addSubmodel(smProvider); } From 7bb750f782fe3c5223394cfad562f5bccca03adf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Apr 2023 02:02:20 +0000 Subject: [PATCH 04/63] Bump docker-maven-plugin from 0.42.0 to 0.42.1 in /basyx.components Bumps [docker-maven-plugin](https://github.com/fabric8io/docker-maven-plugin) from 0.42.0 to 0.42.1. - [Release notes](https://github.com/fabric8io/docker-maven-plugin/releases) - [Changelog](https://github.com/fabric8io/docker-maven-plugin/blob/master/doc/changelog.md) - [Commits](https://github.com/fabric8io/docker-maven-plugin/compare/v0.42.0...v0.42.1) --- updated-dependencies: - dependency-name: io.fabric8:docker-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.docker/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index 19676fdf..b984c181 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -95,7 +95,7 @@ io.fabric8 docker-maven-plugin - 0.42.0 + 0.42.1 From fb6a945fc9794f9def4112fe05b132f4bf504235 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Apr 2023 02:02:25 +0000 Subject: [PATCH 05/63] Bump mongodb-driver-sync from 4.9.0 to 4.9.1 in /basyx.components Bumps [mongodb-driver-sync](https://github.com/mongodb/mongo-java-driver) from 4.9.0 to 4.9.1. - [Release notes](https://github.com/mongodb/mongo-java-driver/releases) - [Commits](https://github.com/mongodb/mongo-java-driver/compare/r4.9.0...r4.9.1) --- updated-dependencies: - dependency-name: org.mongodb:mongodb-driver-sync dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 6bc7786c..3a06354b 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -80,7 +80,7 @@ org.mongodb mongodb-driver-sync - 4.9.0 + 4.9.1 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index aba697e5..0d329b07 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -77,7 +77,7 @@ org.mongodb mongodb-driver-sync - 4.9.0 + 4.9.1 From f451aaa88b817a999cae885caddfc83fe5011ac6 Mon Sep 17 00:00:00 2001 From: Rene Fischer <33397768+FischerRene@users.noreply.github.com> Date: Tue, 11 Apr 2023 09:34:57 +0200 Subject: [PATCH 06/63] Renames registry.host to aas.externalurl (#316) --- .../BaSyxAASServerConfiguration.java | 48 ++++++++++--------- .../src/main/resources/aas.properties | 8 ++-- .../test/resources/aasServerConfig.properties | 2 +- .../aas_multiple_different_source.properties | 2 +- .../aas_single_json_source.properties | 2 +- .../resources/aas_single_source.properties | 2 +- 6 files changed, 33 insertions(+), 31 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/configuration/BaSyxAASServerConfiguration.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/configuration/BaSyxAASServerConfiguration.java index 0402af6d..fe197792 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/configuration/BaSyxAASServerConfiguration.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/configuration/BaSyxAASServerConfiguration.java @@ -70,10 +70,11 @@ public class BaSyxAASServerConfiguration extends BaSyxConfiguration { public static final String DEFAULT_CLIENT_SCOPES = "[]"; public static final String DEFAULT_PROPERTY_DELEGATION = FEATURE_ENABLED; - // Configuration keys public static final String REGISTRY = "registry.path"; + @Deprecated public static final String HOSTPATH = "registry.host"; + public static final String HOSTPATH_NEW = "aas.externalurl"; public static final String SUBMODELS = "registry.submodels"; public static final String ID = "aas.id"; public static final String BACKEND = "aas.backend"; @@ -100,7 +101,7 @@ public static Map getDefaultProperties() { defaultProps.put(BACKEND, DEFAULT_BACKEND); defaultProps.put(SOURCE, DEFAULT_SOURCE); defaultProps.put(REGISTRY, DEFAULT_REGISTRY); - defaultProps.put(HOSTPATH, DEFAULT_HOSTPATH); + defaultProps.put(HOSTPATH_NEW, DEFAULT_HOSTPATH); defaultProps.put(SUBMODELS, DEFAULT_SUBMODELS); defaultProps.put(EVENTS, DEFAULT_EVENTS); defaultProps.put(AASX_UPLOAD, DEFAULT_AASX_UPLOAD); @@ -175,10 +176,7 @@ public BaSyxAASServerConfiguration(Map values) { } public void loadFromEnvironmentVariables() { - String[] properties = { - REGISTRY, BACKEND, SOURCE, EVENTS, HOSTPATH, AASX_UPLOAD, AUTHORIZATION, TOKEN_ENDPOINT, - CLIENT_ID, CLIENT_SECRET, CLIENT_SCOPES, PROPERTY_DELEGATION, ID - }; + String[] properties = { REGISTRY, BACKEND, SOURCE, EVENTS, HOSTPATH, HOSTPATH_NEW, AASX_UPLOAD, AUTHORIZATION, TOKEN_ENDPOINT, CLIENT_ID, CLIENT_SECRET, CLIENT_SCOPES, PROPERTY_DELEGATION, ID }; loadFromEnvironmentVariables(ENV_PREFIX, properties); } @@ -186,17 +184,17 @@ public void loadFromDefaultSource() { loadFileOrDefaultResource(DEFAULT_FILE_KEY, DEFAULT_CONFIG_PATH); loadFromEnvironmentVariables(); } - + public IAuthorizationSupplier configureAndGetAuthorizationSupplier() { - if(!isAuthorizationCredentialsForSecuredRegistryConfigured()) { + if (!isAuthorizationCredentialsForSecuredRegistryConfigured()) { throw new AuthorizationConfigurationException("Authorization credentials for the secured registry is not configured"); } - + return new OAuth2ClientCredentialsBasedAuthorizationSupplier(getTokenEndpoint(), getClientId(), getClientSecret(), getClientScopes()); } - + public String getAASId() { - return getProperty(ID); + return getProperty(ID); } public AASServerBackend getAASBackend() { @@ -282,11 +280,15 @@ public void setSubmodels(List submodels) { } public String getHostpath() { - return getProperty(HOSTPATH); + if (getProperty(HOSTPATH_NEW).equals("") && getProperty(HOSTPATH) != null) { + return getProperty(HOSTPATH); + } else { + return getProperty(HOSTPATH_NEW); + } } public void setHostpath(String hostPath) { - setProperty(HOSTPATH, hostPath); + setProperty(HOSTPATH_NEW, hostPath); } @SuppressWarnings("unchecked") @@ -298,7 +300,7 @@ private List parseFromJson(String property) { return fromJson; } } - + private T parseFromJson(String property, Class classTypeT) { T fromJson = new Gson().fromJson(property, (Type) classTypeT); if (fromJson == null) { @@ -327,7 +329,7 @@ public void disableAuthorization() { public String getTokenEndpoint() { return getProperty(TOKEN_ENDPOINT); } - + public void setTokenEndpoint(String tokenEndpoint) { setProperty(TOKEN_ENDPOINT, tokenEndpoint); } @@ -335,7 +337,7 @@ public void setTokenEndpoint(String tokenEndpoint) { public String getClientId() { return getProperty(CLIENT_ID); } - + public void setClientId(String clientId) { setProperty(CLIENT_ID, clientId); } @@ -343,7 +345,7 @@ public void setClientId(String clientId) { public String getClientSecret() { return getProperty(CLIENT_SECRET); } - + public void setClientSecret(String clientSecret) { setProperty(CLIENT_SECRET, clientSecret); } @@ -352,11 +354,11 @@ public void setClientSecret(String clientSecret) { public Set getClientScopes() { return parseFromJson(getProperty(CLIENT_SCOPES), Set.class); } - + public void setClientScopes(String clientScopes) { setProperty(CLIENT_SCOPES, clientScopes); } - + public void enablePropertyDelegation() { setProperty(PROPERTY_DELEGATION, FEATURE_ENABLED); } @@ -364,11 +366,11 @@ public void enablePropertyDelegation() { public void disablePropertyDelegation() { setProperty(PROPERTY_DELEGATION, FEATURE_DISABLED); } - + public boolean isPropertyDelegationEnabled() { return getProperty(PROPERTY_DELEGATION).equals(FEATURE_ENABLED); } - + public boolean isAuthorizationCredentialsForSecuredRegistryConfigured() { return isTokenEndpointConfigured() && isClientIdConfigured() && isClientSecretConfigured() && isScopeConfigured(); } @@ -376,7 +378,7 @@ public boolean isAuthorizationCredentialsForSecuredRegistryConfigured() { private boolean isTokenEndpointConfigured() { return getProperty(TOKEN_ENDPOINT) != null && !getProperty(TOKEN_ENDPOINT).isEmpty(); } - + private boolean isClientIdConfigured() { return getProperty(CLIENT_ID) != null && !getProperty(CLIENT_ID).isEmpty(); } @@ -384,7 +386,7 @@ private boolean isClientIdConfigured() { private boolean isClientSecretConfigured() { return getProperty(CLIENT_SECRET) != null && !getProperty(CLIENT_SECRET).isEmpty(); } - + private boolean isScopeConfigured() { return getProperty(CLIENT_SCOPES) != null && !getProperty(CLIENT_SCOPES).isEmpty(); } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aas.properties b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aas.properties index e26cc8aa..025d0018 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aas.properties +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aas.properties @@ -59,12 +59,12 @@ aas.aasxUpload=Enabled # registry.path=http://localhost:4000/registry/ # ############################# -# Host +# External URL # ############################# -# Host specifies the endpoint of the deployed AAS component -# If host is empty, the registered AAS endpoint is derived from the context properties +# The external URL specifies the endpoint of the deployed AAS component +# If it is empty, the registered AAS endpoint is derived from the context properties -# registry.host= +# aas.externalurl= # ############################# # Submodels diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aasServerConfig.properties b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aasServerConfig.properties index c52a96cf..3119afa2 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aasServerConfig.properties +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aasServerConfig.properties @@ -59,7 +59,7 @@ registry.path=http://localhost:4000/registry # Host specifies the endpoint of the deployed AAS component # If host is empty, the registered AAS endpoint is derived from the context properties -#registry.host=localhost +# aas.externalurl= # ############################# # Submodels diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_multiple_different_source.properties b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_multiple_different_source.properties index 5f4f3676..3efd83aa 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_multiple_different_source.properties +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_multiple_different_source.properties @@ -58,7 +58,7 @@ aas.aasxUpload=Enabled # Host specifies the endpoint of the deployed AAS component # If host is empty, the registered AAS endpoint is derived from the context properties -# registry.host= +# aas.externalurl= # ############################# # Submodels diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_single_json_source.properties b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_single_json_source.properties index c59c459a..37ea65cb 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_single_json_source.properties +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_single_json_source.properties @@ -58,7 +58,7 @@ aas.aasxUpload=Enabled # Host specifies the endpoint of the deployed AAS component # If host is empty, the registered AAS endpoint is derived from the context properties -# registry.host= +# aas.externalurl= # ############################# # Submodels diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_single_source.properties b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_single_source.properties index 2283d0fa..6988052a 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_single_source.properties +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/aas_single_source.properties @@ -58,7 +58,7 @@ aas.aasxUpload=Enabled # Host specifies the endpoint of the deployed AAS component # If host is empty, the registered AAS endpoint is derived from the context properties -# registry.host= +# aas.externalurl= # ############################# # Submodels From 9f9799fa7dc40c99cbc7922b7a57a40baa34b1c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 02:02:02 +0000 Subject: [PATCH 07/63] Bump camunda-bpmn-model from 7.18.0 to 7.19.0 in /basyx.components Bumps camunda-bpmn-model from 7.18.0 to 7.19.0. --- updated-dependencies: - dependency-name: org.camunda.bpm.model:camunda-bpmn-model dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.lib/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 417c261c..a8b96dfc 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -89,7 +89,7 @@ org.camunda.bpm.model camunda-bpmn-model - 7.18.0 + 7.19.0 From 7c9fdc3c9af8aa3ac6e3d0ac36293830259c5ab1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 02:02:04 +0000 Subject: [PATCH 08/63] Bump camunda-engine from 7.18.0 to 7.19.0 in /basyx.components Bumps camunda-engine from 7.18.0 to 7.19.0. --- updated-dependencies: - dependency-name: org.camunda.bpm:camunda-engine dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.lib/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 417c261c..adb24800 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -83,7 +83,7 @@ org.camunda.bpm camunda-engine - 7.18.0 + 7.19.0 From 877500156f5a9accb9e6a200918be4db18abdc2b Mon Sep 17 00:00:00 2001 From: Rene-Pascal Fischer Date: Wed, 12 Apr 2023 16:44:08 +0200 Subject: [PATCH 09/63] Fixes MongoDB SubmodelElement duplicate bug --- .../aas/mongodb/MongoDBSubmodelAPI.java | 40 +++++++++++-------- .../mongodb/TestMongoDBSubmodelAPI.java | 32 +++++++++++++++ 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java index c02cf109..6f506b2c 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java @@ -43,6 +43,7 @@ import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; import org.eclipse.basyx.submodel.metamodel.api.ISubmodel; import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; +import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElementCollection; import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation; import org.eclipse.basyx.submodel.metamodel.facade.submodelelement.SubmodelElementFacadeFactory; import org.eclipse.basyx.submodel.metamodel.map.Submodel; @@ -112,13 +113,11 @@ public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, MongoCl } @Deprecated - public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, - DelegatedInvocationManager invocationHelper) { + public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, DelegatedInvocationManager invocationHelper) { this(config, smId, invocationHelper, MongoClients.create(config.getConnectionUrl())); } - public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, - DelegatedInvocationManager invocationHelper, MongoClient client) { + public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { this.client = client; this.setConfiguration(config); this.setSubmodelId(smId); @@ -152,8 +151,7 @@ public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvoc this.invocationHelper = invocationHelper; } - public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvocationManager invocationHelper, - MongoClient client) { + public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { config = new BaSyxMongoDBConfiguration(); config.loadFromResource(resourceConfigPath); this.client = client; @@ -245,8 +243,7 @@ public ISubmodel getSubmodel() { // Cast all SubmodelElement maps to ISubmodelElements before returning the // submodel Map elements = new HashMap<>(); - Map> elemMaps = (Map>) result - .get(Submodel.SUBMODELELEMENT); + Map> elemMaps = (Map>) result.get(Submodel.SUBMODELELEMENT); for (Entry> entry : elemMaps.entrySet()) { String shortId = entry.getKey(); Map elemMap = entry.getValue(); @@ -348,14 +345,26 @@ private void updateSubmodelElementInDB(List idShorts, Object newValue) { SubmodelElementProvider smeProvider = new SubmodelElementProvider(mapProvider); smeProvider.setValue(Property.VALUE, newValue); - ISubmodelElement updatedElement = SubmodelElementFacadeFactory - .createSubmodelElement((Map) smeProvider.getValue("")); + ISubmodelElement updatedLastLevelElement = SubmodelElementFacadeFactory.createSubmodelElement((Map) smeProvider.getValue("")); + ISubmodelElement updatedNestedElement = createNestedSubmodelElement(sm, updatedLastLevelElement, idShorts); - sm.addSubmodelElement(updatedElement); + sm.addSubmodelElement(updatedNestedElement); writeSubmodelInDB(sm); } + private ISubmodelElement createNestedSubmodelElement(Submodel sm, ISubmodelElement updatedLastLevelElement, List idShorts) { + ISubmodelElement updatedNestedElement = updatedLastLevelElement; + for (int i = idShorts.size() - 1; i > 0; i--) { + idShorts = idShorts.subList(0, i); + ISubmodelElementCollection nextLevelElementCollection = (ISubmodelElementCollection) getNestedSubmodelElement(sm, idShorts); + nextLevelElementCollection.addSubmodelElement(updatedNestedElement); + updatedNestedElement = nextLevelElementCollection; + } + + return updatedNestedElement; + } + @Override public void uploadSubmodelElementFile(String idShortPath, InputStream fileStream) { String[] splitted = VABPathTools.splitPath(idShortPath); @@ -428,14 +437,12 @@ private ISubmodelElement getNestedSubmodelElement(Submodel sm, List idSh if (elem instanceof SubmodelElementCollection) { elemMap = ((SubmodelElementCollection) elem).getSubmodelElements(); } else { - throw new ResourceNotFoundException( - idShort + " in the nested submodel element path could not be resolved."); + throw new ResourceNotFoundException(idShort + " in the nested submodel element path could not be resolved."); } } String lastIdShort = idShorts.get(idShorts.size() - 1); if (!elemMap.containsKey(lastIdShort)) { - throw new ResourceNotFoundException( - lastIdShort + " in the nested submodel element path could not be resolved."); + throw new ResourceNotFoundException(lastIdShort + " in the nested submodel element path could not be resolved."); } return elemMap.get(lastIdShort); } @@ -529,8 +536,7 @@ public Object getSubmodelElementValue(String idShortPath) { @SuppressWarnings("unchecked") @Override public Object invokeOperation(String idShortPath, Object... params) { - Operation operation = (Operation) SubmodelElementFacadeFactory - .createSubmodelElement((Map) getSubmodelElement(idShortPath)); + Operation operation = (Operation) SubmodelElementFacadeFactory.createSubmodelElement((Map) getSubmodelElement(idShortPath)); if (!DelegatedInvocationManager.isDelegatingOperation(operation)) { throw new MalformedRequestException("This backend supports only delegating operations."); } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java index c631ad49..d41d1e93 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java @@ -37,8 +37,10 @@ import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; import org.eclipse.basyx.submodel.metamodel.map.Submodel; import org.eclipse.basyx.submodel.metamodel.map.qualifier.LangStrings; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.MultiLanguageProperty; +import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; import org.junit.Test; import com.mongodb.MongoGridFSException; @@ -104,6 +106,36 @@ public void fileSubmodelElementFileIsAutomaticallyDeleted() throws FileNotFoundE bucket.downloadToStream("fileSmeIdShort.xml", os); } + @Test + public void submodelElementInCollection() { + MongoDBSubmodelAPI submodelAPI = createAPIWithPreconfiguredSubmodel(); + SubmodelElementCollection collection = new SubmodelElementCollection("collection"); + MultiLanguageProperty mlprop = new MultiLanguageProperty("myMLP"); + collection.addSubmodelElement(mlprop); + submodelAPI.addSubmodelElement(collection); + + LangStrings expected = new LangStrings("de", "Hallo!"); + submodelAPI.updateSubmodelElement(collection.getIdShort() + "/" + mlprop.getIdShort(), expected); + + Object value = submodelAPI.getSubmodelElementValue(collection.getIdShort() + "/" + mlprop.getIdShort()); + + assertEquals(expected, value); + } + + @Test(expected = ResourceNotFoundException.class) + public void submodelElementInCollectionNotExistingAsHighLevelElement() { + MongoDBSubmodelAPI submodelAPI = createAPIWithPreconfiguredSubmodel(); + SubmodelElementCollection collection = new SubmodelElementCollection("collection"); + MultiLanguageProperty mlprop = new MultiLanguageProperty("myMLP"); + collection.addSubmodelElement(mlprop); + submodelAPI.addSubmodelElement(collection); + + LangStrings expected = new LangStrings("de", "Hallo!"); + submodelAPI.updateSubmodelElement(collection.getIdShort() + "/" + mlprop.getIdShort(), expected); + + submodelAPI.getSubmodelElementValue(mlprop.getIdShort()); + } + private void uploadDummyFile(MongoDBSubmodelAPI submodelAPI, String idShort) throws FileNotFoundException { File file = new File("application/xml"); file.setValue(""); From fc008fc351f4e9121593f4a49008c20b1a07f845 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Apr 2023 02:06:59 +0000 Subject: [PATCH 10/63] Bump spring-data-mongodb from 3.4.10 to 3.4.11 in /basyx.components Bumps [spring-data-mongodb](https://github.com/spring-projects/spring-data-mongodb) from 3.4.10 to 3.4.11. - [Release notes](https://github.com/spring-projects/spring-data-mongodb/releases) - [Commits](https://github.com/spring-projects/spring-data-mongodb/compare/3.4.10...3.4.11) --- updated-dependencies: - dependency-name: org.springframework.data:spring-data-mongodb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 3a06354b..1c2b0a8c 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -87,7 +87,7 @@ org.springframework.data spring-data-mongodb - 3.4.10 + 3.4.11 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 0d329b07..93f03cc6 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -84,7 +84,7 @@ org.springframework.data spring-data-mongodb - 3.4.10 + 3.4.11 From f2bf407552e0906bb6397d3e874c9bbbdf0fc09e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 02:02:00 +0000 Subject: [PATCH 11/63] Bump logback-classic from 1.4.6 to 1.4.7 in /basyx.components Bumps [logback-classic](https://github.com/qos-ch/logback) from 1.4.6 to 1.4.7. - [Release notes](https://github.com/qos-ch/logback/releases) - [Commits](https://github.com/qos-ch/logback/compare/v_1.4.6...v_1.4.7) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index 69e9bf9b..b9bbf10f 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -273,7 +273,7 @@ ch.qos.logback logback-classic - 1.4.6 + 1.4.7 From dd2e02326a04ed29f730db660f57b8c5c83c9e97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 02:07:11 +0000 Subject: [PATCH 12/63] Bump jackson-core from 2.14.2 to 2.15.0 in /basyx.components Bumps [jackson-core](https://github.com/FasterXML/jackson-core) from 2.14.2 to 2.15.0. - [Release notes](https://github.com/FasterXML/jackson-core/releases) - [Changelog](https://github.com/FasterXML/jackson-core/blob/jackson-core-2.15.0/release.properties) - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.14.2...jackson-core-2.15.0) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 93f03cc6..7ea4c0b0 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -112,7 +112,7 @@ com.fasterxml.jackson.core jackson-core - 2.14.2 + 2.15.0 From bc8eaa9892831e9a2107f5781449c21730740ed9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Apr 2023 02:07:16 +0000 Subject: [PATCH 13/63] Bump jackson-annotations from 2.14.2 to 2.15.0 in /basyx.components Bumps [jackson-annotations](https://github.com/FasterXML/jackson) from 2.14.2 to 2.15.0. - [Release notes](https://github.com/FasterXML/jackson/releases) - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 93f03cc6..5c74c0b0 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -119,7 +119,7 @@ com.fasterxml.jackson.core jackson-annotations - 2.14.2 + 2.15.0 From 3d4d930f5ded42ba9ff2af2cc0051addb56f365f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zai=20M=C3=BCller-Zhang?= <97607180+zhangzai123@users.noreply.github.com> Date: Fri, 5 May 2023 12:50:41 +0200 Subject: [PATCH 14/63] =?UTF-8?q?Add=20Mongodb=20indexing=20based=20on=20a?= =?UTF-8?q?as-identifier=20for=20AAS-repository,=20subm=E2=80=A6=20(#334)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Zai Zhang --- .../basyx/components/aas/mongodb/MongoDBAASAPI.java | 7 +++++++ .../basyx/components/aas/mongodb/MongoDBSubmodelAPI.java | 7 +++++++ .../registry/mongodb/MongoDBRegistryHandler.java | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPI.java index 5ee5e2e4..a3441f0d 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPI.java @@ -42,6 +42,7 @@ import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.index.TextIndexDefinition; import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.MongoClient; @@ -80,6 +81,12 @@ public MongoDBAASAPI(BaSyxMongoDBConfiguration config, String aasId) { public MongoDBAASAPI(BaSyxMongoDBConfiguration config, String aasId, MongoClient client) { this.setConfiguration(config, client); this.setAASId(aasId); + configureIndexForAasId(mongoOps); + } + + private void configureIndexForAasId(MongoOperations mongoOps) { + TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(AASIDPATH).build(); + mongoOps.indexOps(AssetAdministrationShell.class).ensureIndex(idIndex); } /** diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java index 6f506b2c..54d50a2f 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java @@ -66,6 +66,7 @@ import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.index.TextIndexDefinition; import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.MongoClient; @@ -122,6 +123,12 @@ public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, Delegat this.setConfiguration(config); this.setSubmodelId(smId); this.invocationHelper = invocationHelper; + configureIndexForSubmodelId(mongoOps); + } + + private void configureIndexForSubmodelId(MongoOperations mongoOps) { + TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(SMIDPATH).build(); + mongoOps.indexOps(Submodel.class).ensureIndex(idIndex); } /** diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBRegistryHandler.java b/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBRegistryHandler.java index e5fa19f7..1f3ae601 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBRegistryHandler.java +++ b/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBRegistryHandler.java @@ -37,6 +37,7 @@ import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.index.TextIndexDefinition; import org.springframework.data.mongodb.core.query.Criteria; import com.mongodb.client.MongoClient; @@ -74,6 +75,12 @@ public MongoDBRegistryHandler(String resourceConfigPath) { config = new BaSyxMongoDBConfiguration(); config.loadFromResource(resourceConfigPath); this.setConfiguration(config); + configureIndexForAasId(mongoOps); + } + + private void configureIndexForAasId(MongoOperations mongoOps) { + TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(AASID).build(); + mongoOps.indexOps(AASDescriptor.class).ensureIndex(idIndex); } /** From 9c8b11f7adfcaa4c0df9e19c451a6e62a67784ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 06:45:49 +0200 Subject: [PATCH 15/63] Bump maven-failsafe-plugin from 3.0.0 to 3.1.0 in /basyx.components (#335) Bumps [maven-failsafe-plugin](https://github.com/apache/maven-surefire) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0...surefire-3.1.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- basyx.components/basyx.components.docker/pom.xml | 2 +- basyx.components/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index b984c181..77ee03ea 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -170,7 +170,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0 + 3.1.0 diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index b9bbf10f..5fe7472e 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -141,7 +141,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.0.0 + 3.1.0 From 8c663c6b1bc8c42d6f63a3e06207a64cb056ffc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 06:45:57 +0200 Subject: [PATCH 16/63] Bump maven-surefire-plugin from 3.0.0 to 3.1.0 in /basyx.components (#337) Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0...surefire-3.1.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- basyx.components/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index 5fe7472e..97bef7fa 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -128,7 +128,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0 + 3.1.0 **/*HTTP* From 2b9f15791a6c02f7ae430ab420c0886da09033d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 06:46:03 +0200 Subject: [PATCH 17/63] Bump maven-gpg-plugin from 3.0.1 to 3.1.0 in /basyx.components (#336) Bumps [maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.0.1 to 3.1.0. - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.0.1...maven-gpg-plugin-3.1.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- basyx.components/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index 97bef7fa..bb03a2cb 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -174,7 +174,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.1.0 sign-artifacts From 15e8c4c542ce9a89974618712292360b4dc80709 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 02:08:24 +0000 Subject: [PATCH 18/63] Bump spring-data-mongodb from 3.4.11 to 3.4.12 in /basyx.components Bumps [spring-data-mongodb](https://github.com/spring-projects/spring-data-mongodb) from 3.4.11 to 3.4.12. - [Release notes](https://github.com/spring-projects/spring-data-mongodb/releases) - [Commits](https://github.com/spring-projects/spring-data-mongodb/compare/3.4.11...3.4.12) --- updated-dependencies: - dependency-name: org.springframework.data:spring-data-mongodb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 1c2b0a8c..0174b27a 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -87,7 +87,7 @@ org.springframework.data spring-data-mongodb - 3.4.11 + 3.4.12 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 7e321a5c..3a77b5aa 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -84,7 +84,7 @@ org.springframework.data spring-data-mongodb - 3.4.11 + 3.4.12 From efe8c323281f755e3c957a555b7327e12802e21a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 May 2023 02:01:09 +0000 Subject: [PATCH 19/63] Bump jackson-core from 2.15.0 to 2.15.1 in /basyx.components Bumps [jackson-core](https://github.com/FasterXML/jackson-core) from 2.15.0 to 2.15.1. - [Release notes](https://github.com/FasterXML/jackson-core/releases) - [Changelog](https://github.com/FasterXML/jackson-core/blob/jackson-core-2.15.1/release.properties) - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.15.0...jackson-core-2.15.1) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 3a77b5aa..cf605cda 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -112,7 +112,7 @@ com.fasterxml.jackson.core jackson-core - 2.15.0 + 2.15.1 From 66e8a4a9b448b1bbd4da8b2e10528ff2b9199c80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 May 2023 02:01:15 +0000 Subject: [PATCH 20/63] Bump jackson-annotations from 2.15.0 to 2.15.1 in /basyx.components Bumps [jackson-annotations](https://github.com/FasterXML/jackson) from 2.15.0 to 2.15.1. - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 3a77b5aa..9e6311e4 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -119,7 +119,7 @@ com.fasterxml.jackson.core jackson-annotations - 2.15.0 + 2.15.1 From ca4a89a3a68516fbc27d54efac1bdf63776be4c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 02:11:56 +0000 Subject: [PATCH 21/63] Bump maven-source-plugin from 3.2.1 to 3.3.0 in /basyx.components Bumps [maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.2.1 to 3.3.0. - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.1...maven-source-plugin-3.3.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- basyx.components/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index bb03a2cb..95788a99 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -92,7 +92,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 attach-sources From a58ab5e31120fbf1b98c8518320cf5c295f50dbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 02:12:09 +0000 Subject: [PATCH 22/63] Bump docker-maven-plugin from 0.42.1 to 0.43.0 in /basyx.components Bumps [docker-maven-plugin](https://github.com/fabric8io/docker-maven-plugin) from 0.42.1 to 0.43.0. - [Release notes](https://github.com/fabric8io/docker-maven-plugin/releases) - [Changelog](https://github.com/fabric8io/docker-maven-plugin/blob/master/doc/changelog.md) - [Commits](https://github.com/fabric8io/docker-maven-plugin/compare/v0.42.1...v0.43.0) --- updated-dependencies: - dependency-name: io.fabric8:docker-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.docker/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index 77ee03ea..f24a4fdb 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -95,7 +95,7 @@ io.fabric8 docker-maven-plugin - 0.42.1 + 0.43.0 From 2f8bb3a2d4ddd1af90f69f45480259f89df2b945 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 02:01:08 +0000 Subject: [PATCH 23/63] Bump jackson-core from 2.15.1 to 2.15.2 in /basyx.components Bumps [jackson-core](https://github.com/FasterXML/jackson-core) from 2.15.1 to 2.15.2. - [Release notes](https://github.com/FasterXML/jackson-core/releases) - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.15.1...jackson-core-2.15.2) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index a624b331..cf916f4e 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -112,7 +112,7 @@ com.fasterxml.jackson.core jackson-core - 2.15.1 + 2.15.2 From 7a575c9c821b792c946cd76437220cded1d5f8d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 02:01:11 +0000 Subject: [PATCH 24/63] Bump jackson-annotations from 2.15.1 to 2.15.2 in /basyx.components Bumps [jackson-annotations](https://github.com/FasterXML/jackson) from 2.15.1 to 2.15.2. - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index a624b331..8d2cc485 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -119,7 +119,7 @@ com.fasterxml.jackson.core jackson-annotations - 2.15.1 + 2.15.2 From 2a089df114a84c77cdc94a8c8c1bb4589ae33e23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jun 2023 02:01:30 +0000 Subject: [PATCH 25/63] Bump mock from 0.13.0 to 0.14.0 in /basyx.components Bumps [mock](https://github.com/TNG/keycloak-mock) from 0.13.0 to 0.14.0. - [Release notes](https://github.com/TNG/keycloak-mock/releases) - [Commits](https://github.com/TNG/keycloak-mock/compare/v0.13.0...v0.14.0) --- updated-dependencies: - dependency-name: com.tngtech.keycloakmock:mock dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 0174b27a..e558d8dc 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -128,7 +128,7 @@ com.tngtech.keycloakmock mock test - 0.13.0 + 0.14.0 From 9e9c1af4dd57f5e7f949a6f3a933d0158516abc1 Mon Sep 17 00:00:00 2001 From: Rene Fischer <33397768+FischerRene@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:31:40 +0200 Subject: [PATCH 26/63] Update MongoDB to use StorageAPI (#327) --- .../aas/internal/StorageSubmodelAPI.java | 376 +++++++++++++ .../aas/mongodb/MongoDBSubmodelAPI.java | 532 ++---------------- .../mongodb/MongoDBSubmodelAPIFactory.java | 5 + basyx.components/basyx.components.lib/pom.xml | 14 + .../mongodb/MongoDBBaSyxStorageAPI.java | 165 ++++++ .../MongoDBBaSyxStorageAPIFactory.java | 95 ++++ .../internal/mongodb/MongoDBFileHelper.java | 99 ++++ 7 files changed, 810 insertions(+), 476 deletions(-) create mode 100644 basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java create mode 100644 basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java create mode 100644 basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPIFactory.java create mode 100644 basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBFileHelper.java diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java new file mode 100644 index 00000000..6c234cfc --- /dev/null +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java @@ -0,0 +1,376 @@ +/******************************************************************************* + * Copyright (C) 2023 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.basyx.components.aas.internal; + +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.eclipse.basyx.extensions.internal.storage.BaSyxStorageAPI; +import org.eclipse.basyx.submodel.metamodel.api.ISubmodel; +import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; +import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElementCollection; +import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation; +import org.eclipse.basyx.submodel.metamodel.facade.submodelelement.SubmodelElementFacadeFactory; +import org.eclipse.basyx.submodel.metamodel.map.Submodel; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElement; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation; +import org.eclipse.basyx.submodel.restapi.SubmodelElementProvider; +import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI; +import org.eclipse.basyx.submodel.restapi.operation.DelegatedInvocationManager; +import org.eclipse.basyx.vab.exception.provider.MalformedRequestException; +import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; +import org.eclipse.basyx.vab.modelprovider.VABPathTools; +import org.eclipse.basyx.vab.modelprovider.api.IModelProvider; +import org.eclipse.basyx.vab.modelprovider.lambda.VABLambdaProvider; +import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider; + +/** + * Abstract submodel api for storage backends. + * + * @author fischer + * + */ +public abstract class StorageSubmodelAPI implements ISubmodelAPI { + protected BaSyxStorageAPI storageApi; + private String identificationId; + private DelegatedInvocationManager invocationManager; + + protected StorageSubmodelAPI(BaSyxStorageAPI storageAPI, String identificationId, DelegatedInvocationManager invocatonManager) { + this.storageApi = storageAPI; + this.identificationId = identificationId; + this.invocationManager = invocatonManager; + } + + public String getSubmodelId() { + return identificationId; + } + + /** + * Sets the submodel id, so that this API points to the submodel with smId. Can + * be changed to point to a different submodel in the database. + * + * @param identificationId + */ + public void setSubmodelId(String identificationId) { + this.identificationId = identificationId; + } + + /** + * Depending on whether the model is already in the db, this method inserts or + * replaces the existing data. The new submodel id for this API is taken from + * the given submodel. + * + * @param submodel + */ + public void setSubmodel(Submodel submodel) { + String submodelId = submodel.getIdentification().getId(); + setSubmodelId(submodelId); + storageApi.update(submodel, submodelId); + } + + @Override + public ISubmodel getSubmodel() { + return storageApi.retrieve(identificationId); + } + + @Override + public void addSubmodelElement(ISubmodelElement elem) { + Submodel submodel = (Submodel) getSubmodel(); + submodel.addSubmodelElement(elem); + storageApi.update(submodel, identificationId); + } + + @Override + public void addSubmodelElement(String idShortPath, ISubmodelElement elem) { + List idShorts = idShortsPathAsList(idShortPath); + addNestedSubmodelElement(idShorts, elem); + } + + private void addNestedSubmodelElement(List idShorts, ISubmodelElement element) { + Submodel submodel = (Submodel) getSubmodel(); + if (idShorts.size() > 1) { + idShorts = removeLastElement(idShorts); + ISubmodelElement parentElement = getNestedSubmodelElement(submodel, idShorts); + if (parentElement instanceof SubmodelElementCollection) { + addToSubmodelElementCollection(element, submodel, parentElement); + } + } else { + submodel.addSubmodelElement(element); + storageApi.update(submodel, identificationId); + } + } + + private List removeLastElement(List list) { + return list.subList(0, list.size() - 1); + } + + private void addToSubmodelElementCollection(ISubmodelElement element, Submodel submodel, ISubmodelElement parentElement) { + ((SubmodelElementCollection) parentElement).addSubmodelElement(element); + submodel.addSubmodelElement(parentElement); + storageApi.update(submodel, identificationId); + } + + private ISubmodelElement getNestedSubmodelElement(Submodel submodel, List idShorts) { + Map elementMap = submodel.getSubmodelElements(); + Map resolvedElementMap = resolveElementPath(idShorts, elementMap); + + String lastIdShort = idShorts.get(idShorts.size() - 1); + if (!resolvedElementMap.containsKey(lastIdShort)) { + throwPathCouldNotBeResolvedException(lastIdShort); + } + + return resolvedElementMap.get(lastIdShort); + } + + private Map resolveElementPath(List idShorts, Map elementMap) { + var elementMapWrapper = new Object() { + Map wrappedElementMap = elementMap; + }; + + String lastIdShort = idShorts.get(idShorts.size() - 1); + idShorts.stream().takeWhile(idShort -> !lastIdShort.equals(idShort)).forEachOrdered(idShort -> { + ISubmodelElement element = elementMapWrapper.wrappedElementMap.get(idShort); + if (element instanceof SubmodelElementCollection) { + elementMapWrapper.wrappedElementMap = ((SubmodelElementCollection) element).getSubmodelElements(); + } else { + throwPathCouldNotBeResolvedException(idShort); + } + }); + return elementMapWrapper.wrappedElementMap; + } + + private void throwPathCouldNotBeResolvedException(String idShort) { + throw new ResourceNotFoundException(idShort + " in the nested submodel element path could not be resolved."); + } + + @Override + public ISubmodelElement getSubmodelElement(String idShortPath) { + if (idShortPath.contains("/")) { + List idShorts = idShortsPathAsList(idShortPath); + return getNestedSubmodelElement(idShorts); + } else { + return getTopLevelSubmodelElement(idShortPath); + } + } + + private ISubmodelElement getNestedSubmodelElement(List idShorts) { + Submodel submodel = (Submodel) getSubmodel(); + return convertSubmodelElement(getNestedSubmodelElement(submodel, idShorts)); + } + + private ISubmodelElement getTopLevelSubmodelElement(String idShort) { + Submodel submodel = (Submodel) getSubmodel(); + Map submodelElements = submodel.getSubmodelElements(); + ISubmodelElement element = submodelElements.get(idShort); + if (element == null) { + throw new ResourceNotFoundException("The element \"" + idShort + "\" could not be found"); + } + return convertSubmodelElement(element); + } + + @SuppressWarnings("unchecked") + private ISubmodelElement convertSubmodelElement(ISubmodelElement element) { + Map elementMap = (Map) element; + IModelProvider elementProvider = new SubmodelElementProvider(new VABMapProvider(elementMap)); + Object elementVABObj = elementProvider.getValue(""); + return SubmodelElement.createAsFacade((Map) elementVABObj); + } + + @Override + public void deleteSubmodelElement(String idShortPath) { + if (idShortPath.contains("/")) { + List idShorts = idShortsPathAsList(idShortPath); + deleteNestedSubmodelElement(idShorts); + } else { + deleteTopLevelSubmodelElement(idShortPath); + } + + } + + private void deleteNestedSubmodelElement(List idShorts) { + if (idShorts.size() == 1) { + deleteSubmodelElement(idShorts.get(0)); + return; + } + Submodel submodel = (Submodel) getSubmodel(); + List parentIdShorts = removeLastElement(idShorts); + ISubmodelElement parentElement = getNestedSubmodelElement(submodel, parentIdShorts); + SubmodelElementCollection elementCollection = (SubmodelElementCollection) parentElement; + elementCollection.deleteSubmodelElement(idShorts.get(idShorts.size() - 1)); + storageApi.update(submodel, identificationId); + } + + private void deleteTopLevelSubmodelElement(String idShort) { + Submodel submodel = (Submodel) getSubmodel(); + storageApi.deleteFile(submodel, idShort); + submodel.getSubmodelElements().remove(idShort); + storageApi.update(submodel, identificationId); + } + + @Override + public Collection getOperations() { + Submodel submodel = (Submodel) getSubmodel(); + return submodel.getOperations().values(); + } + + @Override + public Collection getSubmodelElements() { + Submodel submodel = (Submodel) getSubmodel(); + return submodel.getSubmodelElements().values(); + } + + @Override + public void updateSubmodelElement(String idShortPath, Object newValue) { + List idShorts = idShortsPathAsList(idShortPath); + updateSubmodelElement(idShorts, newValue); + } + + @SuppressWarnings("unchecked") + private void updateSubmodelElement(List idShorts, Object newValue) { + Submodel submodel = (Submodel) getSubmodel(); + ISubmodelElement element = getNestedSubmodelElement(submodel, idShorts); + + IModelProvider mapProvider = new VABLambdaProvider((Map) element); + IModelProvider smeProvider = new SubmodelElementProvider(mapProvider); + + smeProvider.setValue(Property.VALUE, newValue); + ISubmodelElement updatedLastLevelElement = SubmodelElementFacadeFactory.createSubmodelElement((Map) smeProvider.getValue("")); + ISubmodelElement updatedNestedElement = createUpdatedNestedSubmodelElement(submodel, updatedLastLevelElement, idShorts); + + submodel.addSubmodelElement(updatedNestedElement); + + storageApi.update(submodel, identificationId); + } + + @Override + public Object getSubmodelElementValue(String idShortPath) { + if (idShortPath.contains("/")) { + List idShorts = idShortsPathAsList(idShortPath); + return getNestedSubmodelElementValue(idShorts); + } else { + return getTopLevelSubmodelElementValue(idShortPath); + } + } + + private Object getTopLevelSubmodelElementValue(String idShort) { + Submodel submodel = (Submodel) getSubmodel(); + return getElementProvider(submodel, idShort).getValue("/value"); + } + + @SuppressWarnings("unchecked") + private IModelProvider getElementProvider(Submodel submodel, String idShortPath) { + ISubmodelElement elem = submodel.getSubmodelElement(idShortPath); + IModelProvider mapProvider = new VABMapProvider((Map) elem); + return new SubmodelElementProvider(mapProvider); + } + + @SuppressWarnings("unchecked") + private Object getNestedSubmodelElementValue(List idShorts) { + ISubmodelElement lastElement = getNestedSubmodelElement(idShorts); + IModelProvider mapProvider = new VABMapProvider((Map) lastElement); + return new SubmodelElementProvider(mapProvider).getValue("/value"); + } + + @SuppressWarnings("unchecked") + protected Object unwrapParameter(Object parameter) { + if (parameter instanceof Map) { + Map map = (Map) parameter; + // Parameters have a strictly defined order and may not be omitted at all. + // Enforcing the structure with valueType is ok, but we should unwrap null + // values, too. + if (map.get("valueType") != null && map.containsKey("value")) { + return map.get("value"); + } + } + return parameter; + } + + @SuppressWarnings("unchecked") + @Override + public Object invokeOperation(String idShortPath, Object... params) { + Operation operation = (Operation) SubmodelElementFacadeFactory.createSubmodelElement((Map) getSubmodelElement(idShortPath)); + if (!DelegatedInvocationManager.isDelegatingOperation(operation)) { + throw new MalformedRequestException("This backend supports only delegating operations."); + } + return invocationManager.invokeDelegatedOperation(operation, params); + } + + @Override + public Object invokeAsync(String idShortPath, Object... params) { + List idShorts = idShortsPathAsList(idShortPath); + return invokeNestedOperationAsync(idShorts, params); + } + + private List idShortsPathAsList(String idShortPath) { + String[] splittedIdShortPath = VABPathTools.splitPath(idShortPath); + return Arrays.asList(splittedIdShortPath); + } + + private Object invokeNestedOperationAsync(List idShorts, Object... params) { + throw new MalformedRequestException("Invoke not supported by this backend"); + } + + @Override + public Object getOperationResult(String idShort, String requestId) { + throw new MalformedRequestException("Invoke not supported by this backend"); + } + + private ISubmodelElement createUpdatedNestedSubmodelElement(Submodel sm, ISubmodelElement updatedLastLevelElement, List idShorts) { + ISubmodelElement updatedNestedElement = updatedLastLevelElement; + for (int i = idShorts.size() - 1; i > 0; i--) { + idShorts = idShorts.subList(0, i); + ISubmodelElementCollection nextLevelElementCollection = (ISubmodelElementCollection) getNestedSubmodelElement(sm, idShorts); + nextLevelElementCollection.addSubmodelElement(updatedNestedElement); + updatedNestedElement = nextLevelElementCollection; + } + + return updatedNestedElement; + } + + @SuppressWarnings("unchecked") + @Override + public java.io.File getSubmodelElementFile(String idShortPath) { + Map submodelElement = (Map) getSubmodelElement(idShortPath); + String parentKey = getSubmodel().getIdentification().getId(); + return storageApi.getFile(idShortPath, parentKey, submodelElement); + } + + @Override + public void uploadSubmodelElementFile(String idShortPath, InputStream fileStream) { + String[] splitted = VABPathTools.splitPath(idShortPath); + List idShorts = Arrays.asList(splitted); + Submodel sm = (Submodel) getSubmodel(); + ISubmodelElement element = getNestedSubmodelElement(sm, idShorts); + String fileName = storageApi.writeFile(idShortPath, getSubmodel().getIdentification().getId(), fileStream, element); + updateSubmodelElement(idShorts, fileName); + } + +} diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java index 54d50a2f..56edbb9c 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java @@ -24,74 +24,32 @@ ******************************************************************************/ package org.eclipse.basyx.components.aas.mongodb; -import static org.springframework.data.mongodb.core.query.Criteria.where; -import static org.springframework.data.mongodb.core.query.Query.query; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.tika.mime.MimeType; -import org.apache.tika.mime.MimeTypeException; -import org.apache.tika.mime.MimeTypes; +import org.eclipse.basyx.components.aas.internal.StorageSubmodelAPI; import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; -import org.eclipse.basyx.submodel.metamodel.api.ISubmodel; -import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; -import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElementCollection; -import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation; -import org.eclipse.basyx.submodel.metamodel.facade.submodelelement.SubmodelElementFacadeFactory; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; +import org.eclipse.basyx.extensions.internal.storage.BaSyxStorageAPI; import org.eclipse.basyx.submodel.metamodel.map.Submodel; import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier; import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; -import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElement; -import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection; -import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; -import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property; -import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation; -import org.eclipse.basyx.submodel.restapi.SubmodelElementProvider; -import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI; import org.eclipse.basyx.submodel.restapi.operation.DelegatedInvocationManager; -import org.eclipse.basyx.vab.exception.provider.MalformedRequestException; -import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; -import org.eclipse.basyx.vab.modelprovider.VABPathTools; -import org.eclipse.basyx.vab.modelprovider.api.IModelProvider; -import org.eclipse.basyx.vab.modelprovider.lambda.VABLambdaProvider; -import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider; import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.index.TextIndexDefinition; -import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; -import com.mongodb.client.MongoDatabase; -import com.mongodb.client.gridfs.GridFSBucket; -import com.mongodb.client.gridfs.GridFSBuckets; -import com.mongodb.client.model.Filters; /** * Implements the ISubmodelAPI for a mongoDB backend. * - * @author espen + * @author fischer */ -public class MongoDBSubmodelAPI implements ISubmodelAPI { +public class MongoDBSubmodelAPI extends StorageSubmodelAPI { private static final String DEFAULT_CONFIG_PATH = "mongodb.properties"; public static final String SMIDPATH = Identifiable.IDENTIFICATION + "." + Identifier.ID; protected DelegatedInvocationManager invocationHelper; protected BaSyxMongoDBConfiguration config; - protected MongoOperations mongoOps; protected String collection; - protected String smId; - private MongoClient client; /** * Receives the path of the configuration.properties file in its constructor. @@ -104,33 +62,11 @@ public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId) { this(config, smId, new DelegatedInvocationManager(new HTTPConnectorFactory())); } - /** - * Receives the path of the configuration.properties file in its constructor. - * - * @param config - */ - public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, MongoClient client) { - this(config, smId, new DelegatedInvocationManager(new HTTPConnectorFactory()), client); - } - @Deprecated public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, DelegatedInvocationManager invocationHelper) { this(config, smId, invocationHelper, MongoClients.create(config.getConnectionUrl())); } - public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { - this.client = client; - this.setConfiguration(config); - this.setSubmodelId(smId); - this.invocationHelper = invocationHelper; - configureIndexForSubmodelId(mongoOps); - } - - private void configureIndexForSubmodelId(MongoOperations mongoOps) { - TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(SMIDPATH).build(); - mongoOps.indexOps(Submodel.class).ensureIndex(idIndex); - } - /** * Receives the path of the .properties file in its constructor from a resource. * @@ -142,44 +78,36 @@ public MongoDBSubmodelAPI(String resourceConfigPath, String smId) { } /** - * Receives the path of the .properties file in its constructor from a resource. + * Constructor using default MongoDB connections + * + * @deprecated Use the new constructor using a MongoClient */ - public MongoDBSubmodelAPI(String resourceConfigPath, String smId, MongoClient client) { - this(resourceConfigPath, smId, new DelegatedInvocationManager(new HTTPConnectorFactory()), client); + @Deprecated + public MongoDBSubmodelAPI(String smId) { + this(DEFAULT_CONFIG_PATH, smId); } @Deprecated - public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvocationManager invocationHelper) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - this.client = MongoClients.create(config.getConnectionUrl()); - this.setConfiguration(config); - this.setSubmodelId(smId); - this.invocationHelper = invocationHelper; + public MongoDBSubmodelAPI(String smId, DelegatedInvocationManager invocationHelper) { + this(DEFAULT_CONFIG_PATH, smId, invocationHelper); } - public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - this.client = client; + @Deprecated + public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvocationManager invocationHelper) { + super(createSubmodelStorageAPI(createConfig(resourceConfigPath)), smId, invocationHelper); + this.config = createConfig(resourceConfigPath); this.setConfiguration(config); this.setSubmodelId(smId); this.invocationHelper = invocationHelper; } /** - * Constructor using default MongoDB connections + * Receives the path of the configuration.properties file in its constructor. * - * @deprecated Use the new constructor using a MongoClient + * @param config */ - @Deprecated - public MongoDBSubmodelAPI(String smId) { - this(DEFAULT_CONFIG_PATH, smId); - } - - @Deprecated - public MongoDBSubmodelAPI(String smId, DelegatedInvocationManager invocationHelper) { - this(DEFAULT_CONFIG_PATH, smId, invocationHelper); + public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, MongoClient client) { + this(config, smId, new DelegatedInvocationManager(new HTTPConnectorFactory()), client); } /** @@ -193,408 +121,60 @@ public MongoDBSubmodelAPI(String smId, DelegatedInvocationManager invocationHelp this(DEFAULT_CONFIG_PATH, smId, invocationHelper, client); } - /** - * Sets the db configuration for the submodel API. - * - * @param config - */ - public void setConfiguration(BaSyxMongoDBConfiguration config) { - this.config = config; - this.mongoOps = new MongoTemplate(client, config.getDatabase()); - this.collection = config.getSubmodelCollection(); + // NEUER KONSTRUKTOR? + public MongoDBSubmodelAPI(BaSyxStorageAPI storageAPI, String identificationId, BaSyxMongoDBConfiguration config) { + super(storageAPI, identificationId, new DelegatedInvocationManager(new HTTPConnectorFactory())); + this.setConfiguration(config); } - /** - * Sets the submodel id, so that this API points to the submodel with smId. Can - * be changed to point to a different submodel in the database. - * - * @param smId - */ - public void setSubmodelId(String smId) { - this.smId = smId; + public MongoDBSubmodelAPI(BaSyxStorageAPI storageAPI, String identificationId) { + super(storageAPI, identificationId, new DelegatedInvocationManager(new HTTPConnectorFactory())); } /** - * Depending on whether the model is already in the db, this method inserts or - * replaces the existing data. The new submodel id for this API is taken from - * the given submodel. - * - * @param sm + * Receives the path of the .properties file in its constructor from a resource. */ - public void setSubmodel(Submodel sm) { - String id = sm.getIdentification().getId(); - this.setSubmodelId(id); - - Submodel replaced = writeSubmodelInDB(sm); - if (replaced == null) { - mongoOps.insert(sm, collection); - } - // Remove mongoDB-specific map attribute from SM - // mongoOps modify sm on save - thus _id has to be removed here... - sm.remove("_id"); - } - - @SuppressWarnings("unchecked") - @Override - public ISubmodel getSubmodel() { - // Query Submodel from MongoDB - Query hasId = query(where(SMIDPATH).is(smId)); - Submodel result = mongoOps.findOne(hasId, Submodel.class, collection); - if (result == null) { - throw new ResourceNotFoundException("The submodel " + smId + " could not be found in the database."); - } - - // Remove mongoDB-specific map attribute from AASDescriptor - result.remove("_id"); - - // Cast all SubmodelElement maps to ISubmodelElements before returning the - // submodel - Map elements = new HashMap<>(); - Map> elemMaps = (Map>) result.get(Submodel.SUBMODELELEMENT); - for (Entry> entry : elemMaps.entrySet()) { - String shortId = entry.getKey(); - Map elemMap = entry.getValue(); - ISubmodelElement element = SubmodelElementFacadeFactory.createSubmodelElement(elemMap); - elements.put(shortId, element); - } - // Replace the element map in the submodel - result.put(Submodel.SUBMODELELEMENT, elements); - // Return the "fixed" submodel - return result; - } - - @Override - public void addSubmodelElement(ISubmodelElement elem) { - // Get sm from db - Submodel sm = (Submodel) getSubmodel(); - // Add element - sm.addSubmodelElement(elem); - writeSubmodelInDB(sm); - } - - private ISubmodelElement getTopLevelSubmodelElement(String idShort) { - Submodel sm = (Submodel) getSubmodel(); - Map submodelElements = sm.getSubmodelElements(); - ISubmodelElement element = submodelElements.get(idShort); - if (element == null) { - throw new ResourceNotFoundException("The element \"" + idShort + "\" could not be found"); - } - return convertSubmodelElement(element); - } - - @SuppressWarnings("unchecked") - private ISubmodelElement convertSubmodelElement(ISubmodelElement element) { - // FIXME: Convert internal data structure of ISubmodelElement - Map elementMap = (Map) element; - IModelProvider elementProvider = new SubmodelElementProvider(new VABMapProvider(elementMap)); - Object elementVABObj = elementProvider.getValue(""); - return SubmodelElement.createAsFacade((Map) elementVABObj); - } - - private void deleteTopLevelSubmodelElement(String idShort) { - // Get sm from db - Submodel sm = (Submodel) getSubmodel(); - // Remove element - - deleteAllFilesFromGridFsIfIsFileSubmodelElement(idShort, sm); - - sm.getSubmodelElements().remove(idShort); - writeSubmodelInDB(sm); - - } - - @SuppressWarnings("unchecked") - private void deleteAllFilesFromGridFsIfIsFileSubmodelElement(String idShort, Submodel sm) { - Map submodelElement = (Map) sm.getSubmodelElement(idShort); - if (!File.isFile(submodelElement)) - return; - File file = File.createAsFacade(submodelElement); - GridFSBucket bucket = getGridFSBucket(); - bucket.find(Filters.eq("filename", file.getValue())).forEach(gridFile -> bucket.delete(gridFile.getObjectId())); - } - - @Override - public Collection getOperations() { - Submodel sm = (Submodel) getSubmodel(); - return sm.getOperations().values(); - } - - private void addNestedSubmodelElement(List idShorts, ISubmodelElement elem) { - Submodel sm = (Submodel) getSubmodel(); - // > 1 idShorts => add new sm element to an existing sm element - if (idShorts.size() > 1) { - idShorts = idShorts.subList(0, idShorts.size() - 1); - // Get parent SM element if more than 1 idShort - ISubmodelElement parentElement = getNestedSubmodelElement(sm, idShorts); - if (parentElement instanceof SubmodelElementCollection) { - ((SubmodelElementCollection) parentElement).addSubmodelElement(elem); - writeSubmodelInDB(sm); - } - } else { - // else => directly add it to the submodel - sm.addSubmodelElement(elem); - writeSubmodelInDB(sm); - } - } - - @Override - public Collection getSubmodelElements() { - Submodel sm = (Submodel) getSubmodel(); - return sm.getSubmodelElements().values(); - } - - @SuppressWarnings("unchecked") - private void updateSubmodelElementInDB(List idShorts, Object newValue) { - Submodel sm = (Submodel) getSubmodel(); - ISubmodelElement element = getNestedSubmodelElement(sm, idShorts); - - IModelProvider mapProvider = new VABLambdaProvider((Map) element); - SubmodelElementProvider smeProvider = new SubmodelElementProvider(mapProvider); - - smeProvider.setValue(Property.VALUE, newValue); - ISubmodelElement updatedLastLevelElement = SubmodelElementFacadeFactory.createSubmodelElement((Map) smeProvider.getValue("")); - ISubmodelElement updatedNestedElement = createNestedSubmodelElement(sm, updatedLastLevelElement, idShorts); - - sm.addSubmodelElement(updatedNestedElement); - - writeSubmodelInDB(sm); - } - - private ISubmodelElement createNestedSubmodelElement(Submodel sm, ISubmodelElement updatedLastLevelElement, List idShorts) { - ISubmodelElement updatedNestedElement = updatedLastLevelElement; - for (int i = idShorts.size() - 1; i > 0; i--) { - idShorts = idShorts.subList(0, i); - ISubmodelElementCollection nextLevelElementCollection = (ISubmodelElementCollection) getNestedSubmodelElement(sm, idShorts); - nextLevelElementCollection.addSubmodelElement(updatedNestedElement); - updatedNestedElement = nextLevelElementCollection; - } - - return updatedNestedElement; - } - - @Override - public void uploadSubmodelElementFile(String idShortPath, InputStream fileStream) { - String[] splitted = VABPathTools.splitPath(idShortPath); - List idShorts = Arrays.asList(splitted); - Submodel sm = (Submodel) getSubmodel(); - ISubmodelElement element = getNestedSubmodelElement(sm, idShorts); - String fileName = updateFileInDB(fileStream, element, idShortPath); - updateSubmodelElementInDB(idShorts, fileName); - } - - @SuppressWarnings("unchecked") - private String updateFileInDB(InputStream newValue, ISubmodelElement element, String idShortPath) { - File file = File.createAsFacade((Map) element); - GridFSBucket bucket = getGridFSBucket(); - String fileName = constructFileName(file, idShortPath); - deleteAllDuplicateFiles(bucket, fileName); - bucket.uploadFromStream(fileName, newValue); - return fileName; - } - - private void deleteAllDuplicateFiles(GridFSBucket bucket, String fileName) { - bucket.find(Filters.eq("filename", fileName)).forEach(gridFile -> bucket.delete(gridFile.getObjectId())); - } - - private GridFSBucket getGridFSBucket() { - MongoDatabase database = client.getDatabase(config.getDatabase()); - GridFSBucket bucket = GridFSBuckets.create(database, config.getFileCollection()); - return bucket; - } - - private Object getTopLevelSubmodelElementValue(String idShort) { - Submodel sm = (Submodel) getSubmodel(); - return getElementProvider(sm, idShort).getValue("/value"); - } - - @SuppressWarnings("unchecked") - private Object getNestedSubmodelElementValue(List idShorts) { - ISubmodelElement lastElement = getNestedSubmodelElement(idShorts); - IModelProvider mapProvider = new VABLambdaProvider((Map) lastElement); - return new SubmodelElementProvider(mapProvider).getValue("/value"); - } - - @SuppressWarnings("unchecked") - protected Object unwrapParameter(Object parameter) { - if (parameter instanceof Map) { - Map map = (Map) parameter; - // Parameters have a strictly defined order and may not be omitted at all. - // Enforcing the structure with valueType is ok, but we should unwrap null - // values, too. - if (map.get("valueType") != null && map.containsKey("value")) { - return map.get("value"); - } - } - return parameter; - } - - @SuppressWarnings("unchecked") - private static SubmodelElementProvider getElementProvider(Submodel sm, String idShort) { - ISubmodelElement elem = sm.getSubmodelElement(idShort); - IModelProvider mapProvider = new VABMapProvider((Map) elem); - return new SubmodelElementProvider(mapProvider); - } - - private ISubmodelElement getNestedSubmodelElement(Submodel sm, List idShorts) { - Map elemMap = sm.getSubmodelElements(); - // Get last nested submodel element - for (int i = 0; i < idShorts.size() - 1; i++) { - String idShort = idShorts.get(i); - ISubmodelElement elem = elemMap.get(idShort); - if (elem instanceof SubmodelElementCollection) { - elemMap = ((SubmodelElementCollection) elem).getSubmodelElements(); - } else { - throw new ResourceNotFoundException(idShort + " in the nested submodel element path could not be resolved."); - } - } - String lastIdShort = idShorts.get(idShorts.size() - 1); - if (!elemMap.containsKey(lastIdShort)) { - throw new ResourceNotFoundException(lastIdShort + " in the nested submodel element path could not be resolved."); - } - return elemMap.get(lastIdShort); - } - - private ISubmodelElement getNestedSubmodelElement(List idShorts) { - // Get sm from db - Submodel sm = (Submodel) getSubmodel(); - // Get nested sm element from this sm - return convertSubmodelElement(getNestedSubmodelElement(sm, idShorts)); - } - - private void deleteNestedSubmodelElement(List idShorts) { - if (idShorts.size() == 1) { - deleteSubmodelElement(idShorts.get(0)); - return; - } - - // Get sm from db - Submodel sm = (Submodel) getSubmodel(); - // Get parent collection - List parentIds = idShorts.subList(0, idShorts.size() - 1); - ISubmodelElement parentElement = getNestedSubmodelElement(sm, parentIds); - // Remove element - SubmodelElementCollection coll = (SubmodelElementCollection) parentElement; - coll.deleteSubmodelElement(idShorts.get(idShorts.size() - 1)); - writeSubmodelInDB(sm); + public MongoDBSubmodelAPI(String resourceConfigPath, String smId, MongoClient client) { + this(resourceConfigPath, smId, new DelegatedInvocationManager(new HTTPConnectorFactory()), client); } - private Object invokeNestedOperationAsync(List idShorts, Object... params) { - // not possible to invoke operations on a submodel that is stored in a db - throw new MalformedRequestException("Invoke not supported by this backend"); + public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { + super(createSubmodelStorageAPI(config, client), smId, invocationHelper); + this.setConfiguration(config); + this.setSubmodelId(smId); + this.invocationHelper = invocationHelper; } - @Override - public Object getOperationResult(String idShort, String requestId) { - // not possible to invoke operations on a submodel that is stored in a db - throw new MalformedRequestException("Invoke not supported by this backend"); + public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { + super(createSubmodelStorageAPI(createConfig(resourceConfigPath), client), smId, invocationHelper); + this.config = createConfig(resourceConfigPath); + this.setConfiguration(config); + this.setSubmodelId(smId); + this.invocationHelper = invocationHelper; } - @Override - public ISubmodelElement getSubmodelElement(String idShortPath) { - if (idShortPath.contains("/")) { - String[] splitted = VABPathTools.splitPath(idShortPath); - List idShorts = Arrays.asList(splitted); - return getNestedSubmodelElement(idShorts); - } else { - return getTopLevelSubmodelElement(idShortPath); - } + private static BaSyxStorageAPI createSubmodelStorageAPI(BaSyxMongoDBConfiguration config) { + MongoDBBaSyxStorageAPIFactory storageAPIFactory = new MongoDBBaSyxStorageAPIFactory<>(config, Submodel.class, config.getSubmodelCollection()); + return storageAPIFactory.create(); } - @Override - public void deleteSubmodelElement(String idShortPath) { - if (idShortPath.contains("/")) { - String[] splitted = VABPathTools.splitPath(idShortPath); - List idShorts = Arrays.asList(splitted); - deleteNestedSubmodelElement(idShorts); - } else { - deleteTopLevelSubmodelElement(idShortPath); - } + private static BaSyxStorageAPI createSubmodelStorageAPI(BaSyxMongoDBConfiguration config, MongoClient client) { + MongoDBBaSyxStorageAPIFactory storageAPIFactory = new MongoDBBaSyxStorageAPIFactory<>(config, Submodel.class, config.getSubmodelCollection(), client); + return storageAPIFactory.create(); } - @Override - public void updateSubmodelElement(String idShortPath, Object newValue) { - String[] splitted = VABPathTools.splitPath(idShortPath); - List idShorts = Arrays.asList(splitted); - updateSubmodelElementInDB(idShorts, newValue); + private static BaSyxMongoDBConfiguration createConfig(String resourceConfigPath) { + BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration(); + config.loadFromResource(resourceConfigPath); + return config; } /** - * Returns the updated Submodel or null if not found + * Sets the db configuration for the submodel API. * - * @param sm - * @return + * @param config */ - private Submodel writeSubmodelInDB(Submodel sm) { - Query hasId = query(where(SMIDPATH).is(smId)); - return mongoOps.findAndReplace(hasId, sm, collection); - } - - @Override - public Object getSubmodelElementValue(String idShortPath) { - if (idShortPath.contains("/")) { - String[] splitted = VABPathTools.splitPath(idShortPath); - List idShorts = Arrays.asList(splitted); - return getNestedSubmodelElementValue(idShorts); - } else { - return getTopLevelSubmodelElementValue(idShortPath); - } - } - - @SuppressWarnings("unchecked") - @Override - public Object invokeOperation(String idShortPath, Object... params) { - Operation operation = (Operation) SubmodelElementFacadeFactory.createSubmodelElement((Map) getSubmodelElement(idShortPath)); - if (!DelegatedInvocationManager.isDelegatingOperation(operation)) { - throw new MalformedRequestException("This backend supports only delegating operations."); - } - return invocationHelper.invokeDelegatedOperation(operation, params); - } - - @Override - public Object invokeAsync(String idShortPath, Object... params) { - String[] splitted = VABPathTools.splitPath(idShortPath); - List idShorts = Arrays.asList(splitted); - return invokeNestedOperationAsync(idShorts, params); - } - - @Override - public void addSubmodelElement(String idShortPath, ISubmodelElement elem) { - String[] splitted = VABPathTools.splitPath(idShortPath); - List idShorts = Arrays.asList(splitted); - addNestedSubmodelElement(idShorts, elem); - } - - @SuppressWarnings("unchecked") - @Override - public java.io.File getSubmodelElementFile(String idShortPath) { - try { - Map submodelElement = (Map) getSubmodelElement(idShortPath); - File fileSubmodelElement = File.createAsFacade(submodelElement); - GridFSBucket bucket = getGridFSBucket(); - String fileName = constructFileName(fileSubmodelElement, idShortPath); - java.io.File file = new java.io.File(fileName); - FileOutputStream fileOutputStream; - fileOutputStream = new FileOutputStream(file); - bucket.downloadToStream(fileName, fileOutputStream); - return file; - } catch (FileNotFoundException e) { - throw new ResourceNotFoundException("The File Submodel Element does not contain a File"); - } - } - - private String constructFileName(File file, String idShortPath) { - Submodel sm = (Submodel) getSubmodel(); - return sm.getIdentification().getId() + "-" + idShortPath.replaceAll("/", "-") + getFileExtension(file); - } - - private String getFileExtension(File file) { - MimeTypes allTypes = MimeTypes.getDefaultMimeTypes(); - try { - MimeType mimeType = allTypes.forName(file.getMimeType()); - return mimeType.getExtension(); - } catch (MimeTypeException e) { - e.printStackTrace(); - return ""; - } + public void setConfiguration(BaSyxMongoDBConfiguration config) { + this.storageApi = createSubmodelStorageAPI(config); } -} +} \ No newline at end of file diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPIFactory.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPIFactory.java index 6b11b1f7..14ebf51a 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPIFactory.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPIFactory.java @@ -54,6 +54,7 @@ public MongoDBSubmodelAPIFactory(BaSyxMongoDBConfiguration config, MongoClient c this.client = client; } + @Deprecated @Override public ISubmodelAPI getSubmodelAPI(Submodel submodel) { MongoDBSubmodelAPI api = new MongoDBSubmodelAPI(config, submodel.getIdentification().getId(), client); @@ -61,4 +62,8 @@ public ISubmodelAPI getSubmodelAPI(Submodel submodel) { return api; } + public ISubmodelAPI create(Submodel submodel) { + return getSubmodelAPI(submodel); + } + } diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 977a6ae9..c82802b8 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -80,6 +80,20 @@ 42.6.0 + + + org.mongodb + mongodb-driver-sync + 4.9.1 + + + + + org.springframework.data + spring-data-mongodb + 3.4.10 + + org.camunda.bpm camunda-engine diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java new file mode 100644 index 00000000..6fbf24d3 --- /dev/null +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (C) 2023 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.basyx.components.internal.mongodb; + +import static org.springframework.data.mongodb.core.query.Criteria.where; +import static org.springframework.data.mongodb.core.query.Query.query; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.Collection; +import java.util.Map; + +import org.apache.commons.lang3.NotImplementedException; +import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.extensions.internal.storage.BaSyxStorageAPI; +import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; +import org.eclipse.basyx.submodel.metamodel.map.Submodel; +import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier; +import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; +import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; +import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.index.TextIndexDefinition; +import org.springframework.data.mongodb.core.query.Query; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.gridfs.GridFSBucket; + +/** + * Provides BaSyxStorageAPI implementation for MongoDB + * + * @author fischer + * + * @param + */ +public class MongoDBBaSyxStorageAPI extends BaSyxStorageAPI { + private static final String SMIDPATH = Identifiable.IDENTIFICATION + "." + Identifier.ID; + + protected BaSyxMongoDBConfiguration config; + protected MongoClient client; + protected MongoOperations mongoOps; + + public MongoDBBaSyxStorageAPI(String collectionName, Class type, BaSyxMongoDBConfiguration config) { + this(collectionName, type, config, MongoClients.create(config.getConnectionUrl())); + } + + public MongoDBBaSyxStorageAPI(String collectionName, Class type, BaSyxMongoDBConfiguration config, MongoClient client) { + super(collectionName, type); + this.config = config; + this.client = client; + this.mongoOps = new MongoTemplate(client, config.getDatabase()); + this.configureIndexForSubmodelId(); + } + + private void configureIndexForSubmodelId() { + TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(SMIDPATH).build(); + this.mongoOps.indexOps(Submodel.class).ensureIndex(idIndex); + } + + @Override + public T createOrUpdate(T obj) { + throw new NotImplementedException(); + } + + @Override + public T update(T obj, String key) { + Query hasId = query(where(SMIDPATH).is(key)); + T replaced = mongoOps.findAndReplace(hasId, obj, COLLECTION_NAME); + if (replaced == null) { + mongoOps.insert(obj, COLLECTION_NAME); + } + // Remove mongoDB-specific map attribute from SM + // mongoOps modify sm on save - thus _id has to be removed here... + ((Submodel) obj).remove("_id"); + return obj; + } + + @Override + public Collection retrieveAll() { + throw new NotImplementedException(); + } + + @Override + public boolean delete(String key) { + throw new NotImplementedException(); + } + + @Override + public void createCollectionIfNotExists(String collectionName) { + throw new NotImplementedException(); + } + + @Override + public void deleteCollection() { + throw new NotImplementedException(); + } + + @SuppressWarnings("unchecked") + @Override + public T rawRetrieve(String key) { + // Query Submodel from MongoDB + Query hasId = query(where(SMIDPATH).is(key)); + Submodel result = mongoOps.findOne(hasId, Submodel.class, COLLECTION_NAME); + if (result == null) { + throw new ResourceNotFoundException("The submodel " + key + " could not be found in the database."); + } + + // Remove mongoDB-specific map attribute from AASDescriptor + result.remove("_id"); + + return (T) result; + } + + @Override + public java.io.File getFile(String idShortPath, String parentKey, Map objMap) { + try { + File fileSubmodelElement = File.createAsFacade(objMap); + GridFSBucket bucket = MongoDBFileHelper.getGridFSBucket(client, config); + String fileName = MongoDBFileHelper.constructFileName(parentKey, fileSubmodelElement, idShortPath); + java.io.File file = new java.io.File(fileName); + FileOutputStream fileOutputStream; + fileOutputStream = new FileOutputStream(file); + bucket.downloadToStream(fileName, fileOutputStream); + return file; + } catch (FileNotFoundException e) { + throw new ResourceNotFoundException("The File Submodel Element does not contain a File"); + } + } + + @Override + public String writeFile(String idShortPath, String parentKey, InputStream inputStream, ISubmodelElement element) { + return MongoDBFileHelper.updateFileInDB(client, config, parentKey, inputStream, element, idShortPath); + } + + @Override + public void deleteFile(Submodel submodel, String idShort) { + MongoDBFileHelper.deleteAllFilesFromGridFsIfIsFileSubmodelElement(client, config, submodel, idShort); + } +} diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPIFactory.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPIFactory.java new file mode 100644 index 00000000..3f74275c --- /dev/null +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPIFactory.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (C) 2023 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.basyx.components.internal.mongodb; + +import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mongodb.client.MongoClient; + +/** + * + * @author fischer + * + * @param + * Generic type of the objects to be managed by the produced API + */ +public class MongoDBBaSyxStorageAPIFactory { + private Logger logger = LoggerFactory.getLogger(getClass()); + + private final BaSyxMongoDBConfiguration config; + private final Class type; + private final String collectionName; + private final MongoClient client; + + /** + * Constructor for a generic BaSyxMongoDBAPIFactory + * + * @param config + * BaSyx MongoDB Configuration + * @param type + * Must be the exact same type as the type of the generic parameter + * {@code } + * @param collectionName + * The name of the collection, managed by the produced API + */ + public MongoDBBaSyxStorageAPIFactory(BaSyxMongoDBConfiguration config, Class type, String collectionName) { + this.config = config; + this.type = type; + this.collectionName = collectionName; + this.client = null; + } + + /** + * Constructor for a generic BaSyxMongoDBAPIFactory + * + * @param config + * BaSyx MongoDB Configuration + * @param type + * Must be the exact same type as the type of the generic parameter + * {@code } + * @param collectionName + * The name of the collection, managed by the produced API + * @param client + * The client of the MongoDB connection + */ + public MongoDBBaSyxStorageAPIFactory(BaSyxMongoDBConfiguration config, Class type, String collectionName, MongoClient client) { + this.config = config; + this.type = type; + this.collectionName = collectionName; + this.client = client; + } + + public MongoDBBaSyxStorageAPI create() { + logger.info("Create MongoDB client..."); + if (client == null) { + return new MongoDBBaSyxStorageAPI(collectionName, type, config); + } else { + return new MongoDBBaSyxStorageAPI(collectionName, type, config, client); + } + } +} diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBFileHelper.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBFileHelper.java new file mode 100644 index 00000000..c64d8e3f --- /dev/null +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBFileHelper.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (C) 2023 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.basyx.components.internal.mongodb; + +import java.io.InputStream; +import java.util.Map; + +import org.apache.tika.mime.MimeType; +import org.apache.tika.mime.MimeTypeException; +import org.apache.tika.mime.MimeTypes; +import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; +import org.eclipse.basyx.submodel.metamodel.map.Submodel; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.gridfs.GridFSBucket; +import com.mongodb.client.gridfs.GridFSBuckets; +import com.mongodb.client.model.Filters; + +/** + * Supports MongoDB file handling + * + * @author fischer + * + */ +public class MongoDBFileHelper { + private MongoDBFileHelper() { + } + + @SuppressWarnings("unchecked") + public static String updateFileInDB(MongoClient client, BaSyxMongoDBConfiguration config, String submodelId, InputStream newValue, ISubmodelElement element, String idShortPath) { + File file = File.createAsFacade((Map) element); + GridFSBucket bucket = getGridFSBucket(client, config); + String fileName = constructFileName(submodelId, file, idShortPath); + deleteAllDuplicateFiles(bucket, fileName); + bucket.uploadFromStream(fileName, newValue); + return fileName; + } + + @SuppressWarnings("unchecked") + public static void deleteAllFilesFromGridFsIfIsFileSubmodelElement(MongoClient client, BaSyxMongoDBConfiguration config, Submodel sm, String idShort) { + Map submodelElement = (Map) sm.getSubmodelElement(idShort); + if (!File.isFile(submodelElement)) + return; + File file = File.createAsFacade(submodelElement); + GridFSBucket bucket = MongoDBFileHelper.getGridFSBucket(client, config); + bucket.find(Filters.eq("filename", file.getValue())).forEach(gridFile -> bucket.delete(gridFile.getObjectId())); + } + + public static GridFSBucket getGridFSBucket(MongoClient client, BaSyxMongoDBConfiguration config) { + MongoDatabase database = client.getDatabase(config.getDatabase()); + return GridFSBuckets.create(database, config.getFileCollection()); + } + + private static void deleteAllDuplicateFiles(GridFSBucket bucket, String fileName) { + bucket.find(Filters.eq("filename", fileName)).forEach(gridFile -> bucket.delete(gridFile.getObjectId())); + } + + public static String constructFileName(String submodelId, File file, String idShortPath) { + return submodelId + "-" + idShortPath.replaceAll("/", "-") + getFileExtension(file); + } + + private static String getFileExtension(File file) { + MimeTypes allTypes = MimeTypes.getDefaultMimeTypes(); + try { + MimeType mimeType = allTypes.forName(file.getMimeType()); + return mimeType.getExtension(); + } catch (MimeTypeException e) { + e.printStackTrace(); + return ""; + } + } + +} From 1ec1c9424bc17cdd465bfd42865a069a3bcbb895 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish <62088117+mdanish98@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:13:16 +0200 Subject: [PATCH 27/63] Fixes files not served issue (#346) Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../components/aas/AASServerComponent.java | 45 +++++++++++++++++-- .../basyx/regression/AASServer/AASXSuite.java | 4 +- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java index 9ef7a4c7..8c8d154c 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java @@ -24,6 +24,7 @@ ******************************************************************************/ package org.eclipse.basyx.components.aas; +import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -35,9 +36,13 @@ import java.util.Map; import java.util.Set; +import javax.servlet.http.HttpServlet; import javax.xml.parsers.ParserConfigurationException; +import org.apache.catalina.Context; +import org.apache.catalina.core.StandardContext; import org.apache.catalina.servlets.DefaultServlet; +import org.apache.catalina.startup.Tomcat; import org.apache.commons.io.IOUtils; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.eclipse.basyx.aas.aggregator.AASAggregatorAPIHelper; @@ -93,6 +98,7 @@ import org.eclipse.basyx.vab.exception.provider.ProviderException; import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; import org.eclipse.basyx.vab.modelprovider.VABPathTools; +import org.eclipse.basyx.vab.protocol.http.server.BaSyxChildContext; import org.eclipse.basyx.vab.protocol.http.server.BaSyxContext; import org.eclipse.basyx.vab.protocol.http.server.BaSyxHTTPServer; import org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface; @@ -131,6 +137,9 @@ public class AASServerComponent implements IComponent { private boolean isAASXUploadEnabled = false; private static final String PREFIX_SUBMODEL_PATH = "/aas/submodels/"; + private static final String AASX_RES_FILE_CONTEXT_PATH = "/basyx-temp"; + private static final String AASX_RES_FILE_DOCBASE_PATH = System.getProperty("java.io.tmpdir") + AASX_RES_FILE_CONTEXT_PATH; + private static final String AASX_RES_FILE_SERVLET_MAPPING_PATTERN = "/files/*"; /** * Constructs an empty AAS server using the passed context @@ -251,11 +260,12 @@ public void startComponent() { // An initial AAS has been loaded from the drive? if (aasBundles != null) { - // 1. Also provide the files - context.addServletMapping("/files/*", createDefaultServlet()); + createBasyxResourceDirectoryIfNotExists(); + + addAasxFilesResourceServlet(context); // 2. Fix the file paths according to the servlet configuration - modifyFilePaths(contextConfig.getHostname(), contextConfig.getPort(), contextConfig.getContextPath()); + modifyFilePaths(contextConfig.getHostname(), contextConfig.getPort(), contextConfig.getContextPath() + AASX_RES_FILE_CONTEXT_PATH); registerWhitelistedSubmodels(); } @@ -775,4 +785,33 @@ private String getMqttAASClientId() { private String getMqttSubmodelClientId() { return getMqttAASClientId() + "/submodelAggregator"; } + + private void addAasxFilesResourceServlet(BaSyxContext context) { + HttpServlet httpServlet = createDefaultServlet(); + + String childContextPath = contextConfig.getContextPath() + AASX_RES_FILE_CONTEXT_PATH; + + Context childContext = createChildContextForAasxResourceFiles(childContextPath, AASX_RES_FILE_DOCBASE_PATH); + + context.addChildContext(new BaSyxChildContext(childContext, httpServlet, AASX_RES_FILE_SERVLET_MAPPING_PATTERN)); + } + + private Context createChildContextForAasxResourceFiles(String childContextPath, String childDocbasePath) { + Context childContext = new StandardContext(); + childContext.setPath(childContextPath); + childContext.setDocBase(childDocbasePath); + childContext.addLifecycleListener(new Tomcat.FixContextListener()); + + return childContext; + } + + private void createBasyxResourceDirectoryIfNotExists() { + File directory = new File(AASX_RES_FILE_DOCBASE_PATH); + + if (directory.exists()) + return; + + directory.mkdir(); + } + } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/AASXSuite.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/AASXSuite.java index c838afe9..6351abc5 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/AASXSuite.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/AASXSuite.java @@ -116,8 +116,8 @@ public void testGetSingleSubmodel() throws Exception { @Test public void testGetSingleModule() throws Exception { - final String FILE_ENDING = "files/aasx/Nameplate/marking_rcm.jpg"; - final String FILE_PATH = rootEndpoint + "files/aasx/Nameplate/marking_rcm.jpg"; + final String FILE_ENDING = "basyx-temp/files/aasx/Nameplate/marking_rcm.jpg"; + final String FILE_PATH = rootEndpoint + "basyx-temp/files/aasx/Nameplate/marking_rcm.jpg"; checkFile(FILE_PATH); // Get the submdoel nameplate From 873f6a2b9f3bc431ac332f1cf0065d432638d618 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish <62088117+mdanish98@users.noreply.github.com> Date: Thu, 1 Jun 2023 16:15:04 +0200 Subject: [PATCH 28/63] Fixes files not served issue (#346) Signed-off-by: Mohammad Ghazanfar Ali Danish From 56128a7f6d73a373938d5aaa36cf56e0ca4e3cd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Jun 2023 02:00:32 +0000 Subject: [PATCH 29/63] Bump spring-data-mongodb from 3.4.10 to 3.4.12 in /basyx.components Bumps [spring-data-mongodb](https://github.com/spring-projects/spring-data-mongodb) from 3.4.10 to 3.4.12. - [Release notes](https://github.com/spring-projects/spring-data-mongodb/releases) - [Commits](https://github.com/spring-projects/spring-data-mongodb/compare/3.4.10...3.4.12) --- updated-dependencies: - dependency-name: org.springframework.data:spring-data-mongodb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.lib/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index c82802b8..0b92f974 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -91,7 +91,7 @@ org.springframework.data spring-data-mongodb - 3.4.10 + 3.4.12 From 1f8a413b6456383b33a06ebc79319e2736ab759b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 02:01:11 +0000 Subject: [PATCH 30/63] Bump maven-surefire-plugin from 3.1.0 to 3.1.2 in /basyx.components Bumps [maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.0 to 3.1.2. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.0...surefire-3.1.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index 95788a99..e7636d18 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -128,7 +128,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.0 + 3.1.2 **/*HTTP* From 7f35bfb5070781456f7d267e6e0c5ee1009c6854 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 02:01:15 +0000 Subject: [PATCH 31/63] Bump maven-failsafe-plugin from 3.1.0 to 3.1.2 in /basyx.components Bumps [maven-failsafe-plugin](https://github.com/apache/maven-surefire) from 3.1.0 to 3.1.2. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.0...surefire-3.1.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.docker/pom.xml | 2 +- basyx.components/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index f24a4fdb..6743b442 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -170,7 +170,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.1.0 + 3.1.2 diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index 95788a99..9222379d 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -141,7 +141,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 3.1.0 + 3.1.2 From 12357b783b71965423a0c3760815bec1cf382c57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jun 2023 02:01:13 +0000 Subject: [PATCH 32/63] Bump logback-classic from 1.4.7 to 1.4.8 in /basyx.components Bumps [logback-classic](https://github.com/qos-ch/logback) from 1.4.7 to 1.4.8. - [Commits](https://github.com/qos-ch/logback/compare/v_1.4.7...v_1.4.8) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index b5201161..dd4d90ef 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -273,7 +273,7 @@ ch.qos.logback logback-classic - 1.4.7 + 1.4.8 From c840d8af9a469aefdc72fda3380239954e694b95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Jun 2023 02:00:44 +0000 Subject: [PATCH 33/63] Bump mock from 0.14.0 to 0.15.0 in /basyx.components Bumps [mock](https://github.com/TNG/keycloak-mock) from 0.14.0 to 0.15.0. - [Release notes](https://github.com/TNG/keycloak-mock/releases) - [Commits](https://github.com/TNG/keycloak-mock/compare/v0.14.0...v0.15.0) --- updated-dependencies: - dependency-name: com.tngtech.keycloakmock:mock dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index e558d8dc..d513c32b 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -128,7 +128,7 @@ com.tngtech.keycloakmock mock test - 0.14.0 + 0.15.0 From f5eb38e7c0560d0f57ade5d52faf291b8b4568a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Jun 2023 02:03:54 +0000 Subject: [PATCH 34/63] Bump spring-data-mongodb from 3.4.12 to 3.4.13 in /basyx.components Bumps [spring-data-mongodb](https://github.com/spring-projects/spring-data-mongodb) from 3.4.12 to 3.4.13. - [Release notes](https://github.com/spring-projects/spring-data-mongodb/releases) - [Commits](https://github.com/spring-projects/spring-data-mongodb/compare/3.4.12...3.4.13) --- updated-dependencies: - dependency-name: org.springframework.data:spring-data-mongodb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- basyx.components/basyx.components.lib/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index e558d8dc..46531d92 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -87,7 +87,7 @@ org.springframework.data spring-data-mongodb - 3.4.12 + 3.4.13 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 32c8c5f8..3cee369a 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -84,7 +84,7 @@ org.springframework.data spring-data-mongodb - 3.4.12 + 3.4.13 diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 0b92f974..ac66d141 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -91,7 +91,7 @@ org.springframework.data spring-data-mongodb - 3.4.12 + 3.4.13 From 44a8d939f6bd65811ddf30279397ca4bf7e9a06c Mon Sep 17 00:00:00 2001 From: Daniel Espen Date: Tue, 20 Jun 2023 13:44:57 +0200 Subject: [PATCH 35/63] Fixes storageAPI not converting to specific element types Signed-off-by: Daniel Espen --- .../aas/internal/StorageSubmodelAPI.java | 28 +++++-------------- .../mongodb/TestMongoDBSubmodelAPI.java | 11 ++++++++ 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java index 6c234cfc..80ef3d5d 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java @@ -36,6 +36,7 @@ import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElementCollection; import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation; +import org.eclipse.basyx.submodel.metamodel.facade.SubmodelElementMapCollectionConverter; import org.eclipse.basyx.submodel.metamodel.facade.submodelelement.SubmodelElementFacadeFactory; import org.eclipse.basyx.submodel.metamodel.map.Submodel; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElement; @@ -173,35 +174,20 @@ private void throwPathCouldNotBeResolvedException(String idShort) { @Override public ISubmodelElement getSubmodelElement(String idShortPath) { - if (idShortPath.contains("/")) { - List idShorts = idShortsPathAsList(idShortPath); - return getNestedSubmodelElement(idShorts); - } else { - return getTopLevelSubmodelElement(idShortPath); - } + List idShorts = idShortsPathAsList(idShortPath); + ISubmodelElement submodelElement = getNestedSubmodelElement(idShorts); + return convertSubmodelElement(submodelElement); } private ISubmodelElement getNestedSubmodelElement(List idShorts) { Submodel submodel = (Submodel) getSubmodel(); - return convertSubmodelElement(getNestedSubmodelElement(submodel, idShorts)); - } - - private ISubmodelElement getTopLevelSubmodelElement(String idShort) { - Submodel submodel = (Submodel) getSubmodel(); - Map submodelElements = submodel.getSubmodelElements(); - ISubmodelElement element = submodelElements.get(idShort); - if (element == null) { - throw new ResourceNotFoundException("The element \"" + idShort + "\" could not be found"); - } - return convertSubmodelElement(element); + return getNestedSubmodelElement(submodel, idShorts); } @SuppressWarnings("unchecked") private ISubmodelElement convertSubmodelElement(ISubmodelElement element) { - Map elementMap = (Map) element; - IModelProvider elementProvider = new SubmodelElementProvider(new VABMapProvider(elementMap)); - Object elementVABObj = elementProvider.getValue(""); - return SubmodelElement.createAsFacade((Map) elementVABObj); + Map convertedCollectionMap = SubmodelElementMapCollectionConverter.smElementToMap((Map) element); + return SubmodelElement.createAsFacade(convertedCollectionMap); } @Override diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java index d41d1e93..a05dbee2 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java @@ -31,15 +31,19 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; +import java.util.Collection; +import java.util.Map; import org.eclipse.basyx.aas.metamodel.map.descriptor.CustomId; import org.eclipse.basyx.components.aas.mongodb.MongoDBSubmodelAPI; import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; import org.eclipse.basyx.submodel.metamodel.map.Submodel; import org.eclipse.basyx.submodel.metamodel.map.qualifier.LangStrings; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.MultiLanguageProperty; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property; import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; import org.junit.Test; @@ -106,6 +110,7 @@ public void fileSubmodelElementFileIsAutomaticallyDeleted() throws FileNotFoundE bucket.downloadToStream("fileSmeIdShort.xml", os); } + @SuppressWarnings("unchecked") @Test public void submodelElementInCollection() { MongoDBSubmodelAPI submodelAPI = createAPIWithPreconfiguredSubmodel(); @@ -119,6 +124,12 @@ public void submodelElementInCollection() { Object value = submodelAPI.getSubmodelElementValue(collection.getIdShort() + "/" + mlprop.getIdShort()); + Collection updatedSubmodelElements = submodelAPI.getSubmodelElements(); + Map updatedCollectionMap = (Map) submodelAPI.getSubmodelElement("collection"); + Collection collectionValue = (Collection) updatedCollectionMap.get(Property.VALUE); + + assertEquals(1, updatedSubmodelElements.size()); + assertEquals(1, collectionValue.size()); assertEquals(expected, value); } From 613ee4208ceebcd54009c82e2ee913fc72012a30 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish <62088117+mdanish98@users.noreply.github.com> Date: Thu, 22 Jun 2023 08:08:02 +0200 Subject: [PATCH 36/63] Adapts the AASXToMetamodelConverter usage as per changes in SDK (#350) Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../basyx/components/aas/AASServerComponent.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java index 8c8d154c..27338433 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java @@ -557,13 +557,14 @@ private static Set loadBundleFromAASX(String aasxPath) throws IOExcep logger.info("Loading aas from aasx \"" + aasxPath + "\""); // Instantiate the aasx package manager - AASXToMetamodelConverter packageManager = new AASXPackageManager(aasxPath); + try (AASXToMetamodelConverter packageManager = new AASXToMetamodelConverter(aasxPath)) { + // Unpack the files referenced by the aas + packageManager.unzipRelatedFiles(); - // Unpack the files referenced by the aas - packageManager.unzipRelatedFiles(); - - // Retrieve the aas from the package - return packageManager.retrieveAASBundles(); + // Retrieve the aas from the package + return packageManager.retrieveAASBundles(); + } + } private void addAASServerFeaturesToContext(BaSyxContext context) { From c14e29517ec246030ba315600a85f81e692ac9ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jun 2023 02:00:40 +0000 Subject: [PATCH 37/63] Bump mongodb-driver-sync from 4.9.1 to 4.10.0 in /basyx.components Bumps [mongodb-driver-sync](https://github.com/mongodb/mongo-java-driver) from 4.9.1 to 4.10.0. - [Release notes](https://github.com/mongodb/mongo-java-driver/releases) - [Commits](https://github.com/mongodb/mongo-java-driver/compare/r4.9.1...r4.10.0) --- updated-dependencies: - dependency-name: org.mongodb:mongodb-driver-sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- basyx.components/basyx.components.lib/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index ef6bf93f..c52c9ff9 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -80,7 +80,7 @@ org.mongodb mongodb-driver-sync - 4.9.1 + 4.10.0 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 3cee369a..8fe37508 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -77,7 +77,7 @@ org.mongodb mongodb-driver-sync - 4.9.1 + 4.10.0 diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index ac66d141..e290e1ee 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -84,7 +84,7 @@ org.mongodb mongodb-driver-sync - 4.9.1 + 4.10.0 From 615ef7231d544c30efe2776cae3f98d49f10da1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 02:01:43 +0000 Subject: [PATCH 38/63] Bump mongodb-driver-sync from 4.10.0 to 4.10.1 in /basyx.components Bumps [mongodb-driver-sync](https://github.com/mongodb/mongo-java-driver) from 4.10.0 to 4.10.1. - [Release notes](https://github.com/mongodb/mongo-java-driver/releases) - [Commits](https://github.com/mongodb/mongo-java-driver/compare/r4.10.0...r4.10.1) --- updated-dependencies: - dependency-name: org.mongodb:mongodb-driver-sync dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- basyx.components/basyx.components.lib/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index c52c9ff9..0c82dff3 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -80,7 +80,7 @@ org.mongodb mongodb-driver-sync - 4.10.0 + 4.10.1 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 8fe37508..2bba28b7 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -77,7 +77,7 @@ org.mongodb mongodb-driver-sync - 4.10.0 + 4.10.1 diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index e290e1ee..595457d5 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -84,7 +84,7 @@ org.mongodb mongodb-driver-sync - 4.10.0 + 4.10.1 From 08c7ab89cc64bdf30b5296ce3c479436ae97be96 Mon Sep 17 00:00:00 2001 From: Frank Schnicke <77283144+FrankSchnicke@users.noreply.github.com> Date: Mon, 3 Jul 2023 15:21:12 +0200 Subject: [PATCH 39/63] Logging Exclusion (#358) Signed-off-by: Frank Schnicke --- .../components/aas/AASServerComponent.java | 2 - .../BaSyxAASServerConfiguration.java | 12 +++-- .../AASServer/TestAASXPackageManager.java | 1 + .../BaSyxRegistryConfiguration.java | 7 +-- .../configuration/BaSyxConfiguration.java | 48 ++++++++++++++++--- .../BaSyxContextConfiguration.java | 10 +++- .../BaSyxDockerConfiguration.java | 5 +- .../BaSyxMongoDBConfiguration.java | 10 +++- .../configuration/BaSyxMqttConfiguration.java | 11 +++-- .../configuration/BaSyxSQLConfiguration.java | 10 +++- .../BaSyxSecurityConfiguration.java | 5 +- .../DummyBaSyxConfiguration.java | 3 +- 12 files changed, 96 insertions(+), 28 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java index 27338433..157aa60e 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java @@ -66,7 +66,6 @@ import org.eclipse.basyx.components.aas.aascomponent.IAASServerFeature; import org.eclipse.basyx.components.aas.aascomponent.InMemoryAASServerComponentFactory; import org.eclipse.basyx.components.aas.aascomponent.MongoDBAASServerComponentFactory; -import org.eclipse.basyx.components.aas.aasx.AASXPackageManager; import org.eclipse.basyx.components.aas.authorization.AuthorizedAASServerFeature; import org.eclipse.basyx.components.aas.authorization.internal.AuthorizedAASServerFeatureFactory; import org.eclipse.basyx.components.aas.authorization.internal.AuthorizedDefaultServlet; @@ -113,7 +112,6 @@ * * @author schnicke, espen, fried, fischer, danish, wege */ -@SuppressWarnings("deprecation") public class AASServerComponent implements IComponent { private static Logger logger = LoggerFactory.getLogger(AASServerComponent.class); diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/configuration/BaSyxAASServerConfiguration.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/configuration/BaSyxAASServerConfiguration.java index fe197792..bb4b6a49 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/configuration/BaSyxAASServerConfiguration.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/configuration/BaSyxAASServerConfiguration.java @@ -27,6 +27,7 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -118,7 +119,7 @@ public static Map getDefaultProperties() { * Empty Constructor - use default values */ public BaSyxAASServerConfiguration() { - super(getDefaultProperties()); + super(getDefaultProperties(), getPropertiesExcludedFromLogging()); } /** @@ -130,7 +131,7 @@ public BaSyxAASServerConfiguration() { * The file source for the AASServer (e.g. an .aasx file) */ public BaSyxAASServerConfiguration(AASServerBackend backend, String source) { - super(getDefaultProperties()); + this(); setAASBackend(backend); setAASSourceAsList(source); } @@ -172,7 +173,7 @@ public BaSyxAASServerConfiguration(AASServerBackend backend, String source, Stri * Constructor with predefined value map */ public BaSyxAASServerConfiguration(Map values) { - super(values); + super(values, getPropertiesExcludedFromLogging()); } public void loadFromEnvironmentVariables() { @@ -390,4 +391,9 @@ private boolean isClientSecretConfigured() { private boolean isScopeConfigured() { return getProperty(CLIENT_SCOPES) != null && !getProperty(CLIENT_SCOPES).isEmpty(); } + + private static List getPropertiesExcludedFromLogging() { + return Collections.singletonList(CLIENT_SECRET); + } + } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestAASXPackageManager.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestAASXPackageManager.java index 1efce60e..79d10494 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestAASXPackageManager.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestAASXPackageManager.java @@ -145,6 +145,7 @@ public void testCheckAasxConverter() { /** * Creates a new .aasx using the AASXFactory and tries to parse it */ + @SuppressWarnings("resource") @Test public void testLoadGeneratedAASX() throws InvalidFormatException, IOException, ParserConfigurationException, SAXException, TransformerException, URISyntaxException { diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/configuration/BaSyxRegistryConfiguration.java b/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/configuration/BaSyxRegistryConfiguration.java index 3e999e90..b5269b7c 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/configuration/BaSyxRegistryConfiguration.java +++ b/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/configuration/BaSyxRegistryConfiguration.java @@ -24,6 +24,7 @@ ******************************************************************************/ package org.eclipse.basyx.components.registry.configuration; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -73,16 +74,16 @@ public static Map getDefaultProperties() { } public BaSyxRegistryConfiguration() { - super(getDefaultProperties()); + super(getDefaultProperties(), Collections.emptyList()); } public BaSyxRegistryConfiguration(RegistryBackend backend) { - super(getDefaultProperties()); + super(getDefaultProperties(), Collections.emptyList()); setRegistryBackend(backend); } public BaSyxRegistryConfiguration(Map values) { - super(values); + super(values, Collections.emptyList()); } public void loadFromEnvironmentVariables() { diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxConfiguration.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxConfiguration.java index baae5470..b0d1e27b 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxConfiguration.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxConfiguration.java @@ -43,16 +43,33 @@ public class BaSyxConfiguration { // Properties in this configuration private Map values; + private List propertiesExcludedFromLogging; + + @Deprecated /** * Constructor that takes the configuration's default values. All the keys in * the map are the name of the properties that are stored and loaded in this * configuration. + * + * @param defaultValues + * @deprecated Use {@link #BaSyxConfiguration(Map, List)} to ensure proper + * exclusion is configured */ public BaSyxConfiguration(Map defaultValues) { this.values = defaultValues; } + /** + * + * @param defaultValues + * @param propertiesExcludedFromLogging + */ + public BaSyxConfiguration(Map defaultValues, List propertiesExcludedFromLogging) { + this(defaultValues); + this.propertiesExcludedFromLogging = propertiesExcludedFromLogging; + } + public static InputStream getResourceStream(String relativeResourcePath) { ClassLoader classLoader = BaSyxConfiguration.class.getClassLoader(); return classLoader.getResourceAsStream(relativeResourcePath); @@ -150,15 +167,14 @@ public void loadFromProperties(Properties properties) { for (Object property : properties.keySet()) { String propertyName = (String) property; String loaded = properties.getProperty(propertyName); - if (values.containsKey(propertyName)) { - logger.info(propertyName + ": '" + loaded + "'"); - } else { - logger.debug(propertyName + ": '" + loaded + "'"); - } + + logPropertyVariable(propertyName, loaded); + values.put(propertyName, loaded); } } + /** * Method for subclasses to read specific environment variables * @@ -182,7 +198,7 @@ protected void loadFromEnvironmentVariables(String prefix, String... properties) for (String propName : properties) { String result = getEnvironmentVariable(prefix, propName, usesDeprecatedNamingConvention); if (result != null) { - logger.info("Environment - " + propName + ": " + result); + logEnvironmentVariable(propName, result); setProperty(propName, result); } } @@ -191,6 +207,26 @@ protected void loadFromEnvironmentVariables(String prefix, String... properties) } } + private void logPropertyVariable(String propertyName, String result) { + if (isPropertyExcludedFromLogging(propertyName)) { + result = "*****"; + } + + logger.info("Property File - " + propertyName + ": '" + result + "'"); + } + + private void logEnvironmentVariable(String propertyName, String result) { + if (isPropertyExcludedFromLogging(propertyName)) { + result = "*****"; + } + + logger.info("Environment - " + propertyName + ": " + result); + } + + private boolean isPropertyExcludedFromLogging(String propertyName) { + return propertiesExcludedFromLogging.contains(propertyName); + } + private String getEnvironmentVariable(String prefix, String propName, boolean usesDeprecatedNamingConvention) { if (usesDeprecatedNamingConvention) { return getEnvironmentVariableDeprecatedNamingConvention(prefix, propName); diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxContextConfiguration.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxContextConfiguration.java index cfe157dc..59799622 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxContextConfiguration.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxContextConfiguration.java @@ -24,7 +24,9 @@ ******************************************************************************/ package org.eclipse.basyx.components.configuration; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.basyx.vab.modelprovider.VABPathTools; @@ -85,14 +87,14 @@ public static Map getDefaultProperties() { * Empty Constructor - use default values */ public BaSyxContextConfiguration() { - super(getDefaultProperties()); + super(getDefaultProperties(), getPropertiesExcludedFromLogging()); } /** * Constructor with predefined value map */ public BaSyxContextConfiguration(Map values) { - super(values); + super(values, getPropertiesExcludedFromLogging()); } /** @@ -287,4 +289,8 @@ private String getProtocol() { } return "http://"; } + + private static List getPropertiesExcludedFromLogging() { + return Collections.singletonList(SSL_KEY_PASSWORD); + } } diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxDockerConfiguration.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxDockerConfiguration.java index 12ea074e..6971281e 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxDockerConfiguration.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxDockerConfiguration.java @@ -24,6 +24,7 @@ ******************************************************************************/ package org.eclipse.basyx.components.configuration; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -68,14 +69,14 @@ public static Map getDefaultProperties() { * Empty Constructor - use default values */ public BaSyxDockerConfiguration() { - super(getDefaultProperties()); + super(getDefaultProperties(), Collections.emptyList()); } /** * Constructor with predefined value map */ public BaSyxDockerConfiguration(Map values) { - super(values); + super(values, Collections.emptyList()); } /** diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxMongoDBConfiguration.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxMongoDBConfiguration.java index e0e04788..7cac1e79 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxMongoDBConfiguration.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxMongoDBConfiguration.java @@ -24,7 +24,9 @@ ******************************************************************************/ package org.eclipse.basyx.components.configuration; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -74,14 +76,14 @@ public static Map getDefaultProperties() { * Constructor with predefined value map */ public BaSyxMongoDBConfiguration(Map values) { - super(values); + super(values, getPropertiesExcludedFromLogging()); } /** * Empty Constructor - use default values */ public BaSyxMongoDBConfiguration() { - super(getDefaultProperties()); + super(getDefaultProperties(), getPropertiesExcludedFromLogging()); } /** @@ -202,4 +204,8 @@ public String getFileCollection() { public void setFileCollection(String fileCollection) { setProperty(FILE_COLLECTION, fileCollection); } + + private static List getPropertiesExcludedFromLogging() { + return Collections.singletonList(CONNECTIONURL); + } } diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxMqttConfiguration.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxMqttConfiguration.java index d53ddf9d..43fb22c6 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxMqttConfiguration.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxMqttConfiguration.java @@ -24,6 +24,7 @@ ******************************************************************************/ package org.eclipse.basyx.components.configuration; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -81,14 +82,14 @@ public static Map getDefaultProperties() { * Constructor with predefined value map */ public BaSyxMqttConfiguration(Map values) { - super(values); + super(values, getPropertiesExcludedFromLogging()); } /** * Empty Constructor - use default values */ public BaSyxMqttConfiguration() { - super(getDefaultProperties()); + super(getDefaultProperties(), getPropertiesExcludedFromLogging()); } /** @@ -209,6 +210,10 @@ public void setWhitelist(String submodelId, List elementIds) { } public String getClientId() { - return getProperty(CLIENT_ID); + return getProperty(CLIENT_ID); + } + + private static List getPropertiesExcludedFromLogging() { + return Collections.singletonList(PASS); } } diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxSQLConfiguration.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxSQLConfiguration.java index 936ec09f..dd77a62f 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxSQLConfiguration.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxSQLConfiguration.java @@ -24,7 +24,9 @@ ******************************************************************************/ package org.eclipse.basyx.components.configuration; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -71,14 +73,14 @@ public static Map getDefaultProperties() { * Constructor with predefined value map */ public BaSyxSQLConfiguration(Map values) { - super(values); + super(values, getPropertiesExcludedFromLogging()); } /** * Empty Constructor - use default values */ public BaSyxSQLConfiguration() { - super(getDefaultProperties()); + super(getDefaultProperties(), getPropertiesExcludedFromLogging()); } /** @@ -153,4 +155,8 @@ public String getPrefix() { public void setPrefix(String prefix) { setProperty(PREFIX, prefix); } + + private static List getPropertiesExcludedFromLogging() { + return Collections.singletonList(PASS); + } } diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxSecurityConfiguration.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxSecurityConfiguration.java index aab653cc..ebe8fff5 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxSecurityConfiguration.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/configuration/BaSyxSecurityConfiguration.java @@ -24,6 +24,7 @@ ******************************************************************************/ package org.eclipse.basyx.components.configuration; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -78,14 +79,14 @@ public static Map getDefaultProperties() { * Constructor with predefined value map */ public BaSyxSecurityConfiguration(Map values) { - super(values); + super(values, Collections.emptyList()); } /** * Empty Constructor - use default values */ public BaSyxSecurityConfiguration() { - super(getDefaultProperties()); + super(getDefaultProperties(), Collections.emptyList()); } /** diff --git a/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/support/configuration/DummyBaSyxConfiguration.java b/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/support/configuration/DummyBaSyxConfiguration.java index 3621ff3c..6030ac7b 100644 --- a/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/support/configuration/DummyBaSyxConfiguration.java +++ b/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/support/configuration/DummyBaSyxConfiguration.java @@ -1,5 +1,6 @@ package org.eclipse.basyx.regression.support.configuration; +import java.util.Collections; import java.util.HashMap; import org.eclipse.basyx.components.configuration.BaSyxConfiguration; @@ -19,7 +20,7 @@ public class DummyBaSyxConfiguration extends BaSyxConfiguration { public static final String AASX_UPLOAD = "aas.aasxUpload"; public DummyBaSyxConfiguration() { - super(new HashMap()); + super(new HashMap(), Collections.emptyList()); } public void loadFromEnvironmentVariables() { From 5df2c605e277702f0b0e2f6a11c0de63be8f2584 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 01:50:29 +0000 Subject: [PATCH 40/63] Bump h2 from 2.1.214 to 2.2.220 in /basyx.components Bumps [h2](https://github.com/h2database/h2database) from 2.1.214 to 2.2.220. - [Release notes](https://github.com/h2database/h2database/releases) - [Commits](https://github.com/h2database/h2database/compare/version-2.1.214...version-2.2.220) --- updated-dependencies: - dependency-name: com.h2database:h2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.lib/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 595457d5..85fa61f4 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -109,7 +109,7 @@ com.h2database h2 - 2.1.214 + 2.2.220 From 65114e6756e2249f97f2a7b2a6f294fddc8239fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 01:50:32 +0000 Subject: [PATCH 41/63] Bump mock from 0.15.0 to 0.15.1 in /basyx.components Bumps [mock](https://github.com/TNG/keycloak-mock) from 0.15.0 to 0.15.1. - [Release notes](https://github.com/TNG/keycloak-mock/releases) - [Commits](https://github.com/TNG/keycloak-mock/compare/v0.15.0...v0.15.1) --- updated-dependencies: - dependency-name: com.tngtech.keycloakmock:mock dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 0c82dff3..5085e14e 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -128,7 +128,7 @@ com.tngtech.keycloakmock mock test - 0.15.0 + 0.15.1 From 64a6ccd7b8cc2e1baef94d03aee8eb57abb1d7a3 Mon Sep 17 00:00:00 2001 From: jannisjung <92165516+jannisjung@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:24:54 +0200 Subject: [PATCH 42/63] Implements MongoDB Backend with BaSyxStorgeAPI (#359) Co-authored-by: Marie Witt Signed-off-by: Jannis Jung --- .gitignore | 4 + .../components/aas/mongodb/MongoDBAASAPI.java | 214 +++---- .../aas/mongodb/MongoDBAASAPIFactory.java | 26 +- .../aas/mongodb/MongoDBAASAggregator.java | 549 +++++++++--------- .../mongodb/MongoDBAASAggregatorFactory.java | 50 +- .../aas/mongodb/MongoDBSubmodelAPI.java | 119 ++-- .../mongodb/MongoDBSubmodelAPIFactory.java | 12 +- .../mongodb/MongoDBSubmodelAggregator.java | 56 +- .../MongoDBSubmodelAggregatorFactory.java | 12 +- .../AASServer/mongodb/TestMongoDBAAASAPI.java | 124 ++++ .../mongodb/MongoDBRegistryHandler.java | 92 ++- .../mongodb/MongoDBTaggedDirectory.java | 22 +- .../mongodb/MongoDBBaSyxStorageAPI.java | 106 +++- .../MongoDBBaSyxStorageAPIFactory.java | 75 ++- .../mongodb/TestMongoDBBaSyxStorageAPI.java | 92 +++ .../TestMongoDBBaSyxStorageAPIFactory.java | 70 +++ 16 files changed, 977 insertions(+), 646 deletions(-) create mode 100644 basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAAASAPI.java create mode 100644 basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/components/internal/mongodb/TestMongoDBBaSyxStorageAPI.java create mode 100644 basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/components/internal/mongodb/TestMongoDBBaSyxStorageAPIFactory.java diff --git a/.gitignore b/.gitignore index 42416d97..aef5e14f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ .lck *.class +/basyx.components/basyx.components.docker/basyx.components.AASServer/fileSmeIdShort.xml +/basyx.components/basyx.components.docker/basyx.components.AASServer/mySubmodelId-fileSmeIdShort.xml +/basyx.components/basyx.components.docker/basyx.components.registry/.moquette_uuid + /components/basys.components/WebContent/WEB-INF/lib/jdbc/postgresql-42.2.2.jar /components/basys.components/WebContent/WEB-INF/lib/jersey/ext/aopalliance-repackaged-2.5.0-b42.jar /components/basys.components/WebContent/WEB-INF/lib/jersey/ext/cdi-api-1.1.jar diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPI.java index a3441f0d..e99ce950 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPI.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021 the Eclipse BaSyx Authors + * Copyright (C) 2021, 2023 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 @@ -24,92 +24,83 @@ ******************************************************************************/ package org.eclipse.basyx.components.aas.mongodb; -import static org.springframework.data.mongodb.core.query.Criteria.where; -import static org.springframework.data.mongodb.core.query.Query.query; - import java.util.Collection; -import java.util.Iterator; -import java.util.List; +import java.util.Optional; import org.eclipse.basyx.aas.metamodel.api.IAssetAdministrationShell; import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell; import org.eclipse.basyx.aas.restapi.api.IAASAPI; import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; import org.eclipse.basyx.submodel.metamodel.api.reference.IKey; import org.eclipse.basyx.submodel.metamodel.api.reference.IReference; -import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier; -import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; -import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.index.TextIndexDefinition; -import org.springframework.data.mongodb.core.query.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; /** * Implements the IAASAPI for a mongoDB backend. * - * @author espen + * @author espen, jungjan, witt */ public class MongoDBAASAPI implements IAASAPI { + private Logger logger = LoggerFactory.getLogger(getClass()); private static final String DEFAULT_CONFIG_PATH = "mongodb.properties"; - private static final String AASIDPATH = Identifiable.IDENTIFICATION + "." + Identifier.ID; - protected BaSyxMongoDBConfiguration config; - protected MongoOperations mongoOps; - protected String collection; - protected String aasId; + protected String collectionName; + private MongoDBBaSyxStorageAPI storageApi; + private String shellIdentificationId; /** * Receives the path of the configuration.properties file in its constructor. * * @param config - * @deprecated Use the new constructor using a MongoClient */ - @Deprecated - public MongoDBAASAPI(BaSyxMongoDBConfiguration config, String aasId) { - this(config, aasId, MongoClients.create(config.getConnectionUrl())); + public MongoDBAASAPI(BaSyxMongoDBConfiguration config, String shellIdentificationId, MongoClient client) { + this(MongoDBBaSyxStorageAPIFactory.create(config.getAASCollection(), AssetAdministrationShell.class, config, client), shellIdentificationId); + } + + public MongoDBAASAPI(MongoDBBaSyxStorageAPI mongoDBStorageAPI, String shellIdentificationId) { + super(); + this.storageApi = mongoDBStorageAPI; + this.shellIdentificationId = shellIdentificationId; } /** - * Receives the path of the configuration.properties file in its constructor. - * - * @param config + * Receives the path of the .properties file in its constructor from a resource. */ - public MongoDBAASAPI(BaSyxMongoDBConfiguration config, String aasId, MongoClient client) { - this.setConfiguration(config, client); - this.setAASId(aasId); - configureIndexForAasId(mongoOps); + public MongoDBAASAPI(String resourceConfigPath, String shellIdentificationId, MongoClient client) { + this(MongoDBBaSyxStorageAPIFactory.create(configFromResource(resourceConfigPath).getSubmodelCollection(), AssetAdministrationShell.class, configFromResource(resourceConfigPath), client), shellIdentificationId); } - private void configureIndexForAasId(MongoOperations mongoOps) { - TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(AASIDPATH).build(); - mongoOps.indexOps(AssetAdministrationShell.class).ensureIndex(idIndex); + /** + * Constructor using default MongoDB connections + */ + public MongoDBAASAPI(String shellIdentificationId, MongoClient client) { + this(DEFAULT_CONFIG_PATH, shellIdentificationId, client); } /** - * Receives the path of the .properties file in its constructor from a resource. + * Receives the path of the configuration.properties file in its constructor. * + * @param config * @deprecated Use the new constructor using a MongoClient */ @Deprecated - public MongoDBAASAPI(String resourceConfigPath, String aasId) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - this.setConfiguration(config); - this.setAASId(aasId); + public MongoDBAASAPI(BaSyxMongoDBConfiguration config, String shellIdentificationId) { + this(MongoDBBaSyxStorageAPIFactory.create(config.getAASCollection(), AssetAdministrationShell.class, config), shellIdentificationId); } /** * Receives the path of the .properties file in its constructor from a resource. + * + * @deprecated Use the new constructor using a MongoClient */ - public MongoDBAASAPI(String resourceConfigPath, String aasId, MongoClient client) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - this.setConfiguration(config, client); - this.setAASId(aasId); + @Deprecated + public MongoDBAASAPI(String resourceConfigPath, String shellIdentificationId) { + this(MongoDBBaSyxStorageAPIFactory.create(configFromResource(resourceConfigPath).getSubmodelCollection(), AssetAdministrationShell.class, configFromResource(resourceConfigPath)), shellIdentificationId); } /** @@ -118,113 +109,94 @@ public MongoDBAASAPI(String resourceConfigPath, String aasId, MongoClient client * @deprecated Use the new constructor using a MongoClient */ @Deprecated - public MongoDBAASAPI(String aasId) { - this(DEFAULT_CONFIG_PATH, aasId); + public MongoDBAASAPI(String shellIdentificationId) { + this(DEFAULT_CONFIG_PATH, shellIdentificationId); } - /** - * Constructor using default MongoDB connections - */ - public MongoDBAASAPI(String aasId, MongoClient client) { - this(DEFAULT_CONFIG_PATH, aasId, client); + private static BaSyxMongoDBConfiguration configFromResource(String resourceConfigPath) { + BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration(); + config.loadFromResource(resourceConfigPath); + return config; } - @Deprecated + /** + * This Method enables to switch the BaSyxMongoDBConfiguration at runtime + * + * @param config + */ public void setConfiguration(BaSyxMongoDBConfiguration config) { - MongoClient client = MongoClients.create(config.getConnectionUrl()); - setConfiguration(config, client); + this.collectionName = config.getAASCollection(); + MongoDBBaSyxStorageAPIFactory storageApiFactory = new MongoDBBaSyxStorageAPIFactory<>(config, AssetAdministrationShell.class, this.collectionName); + this.storageApi = storageApiFactory.create(); } + /** + * This Method enables to switch the BaSyxMongoDBConfiguration at runtime + * + * @param config + */ public void setConfiguration(BaSyxMongoDBConfiguration config, MongoClient client) { - this.config = config; - this.mongoOps = new MongoTemplate(client, config.getDatabase()); - this.collection = config.getAASCollection(); + this.collectionName = config.getAASCollection(); + MongoDBBaSyxStorageAPIFactory storageApiFactory = new MongoDBBaSyxStorageAPIFactory<>(config, AssetAdministrationShell.class, this.collectionName, client); + this.storageApi = storageApiFactory.create(); } /** - * Sets the aas id, so that this API points to the aas with aasId. Can be - * changed to point to a different aas in the database. + * Sets the shellIdentificationId, so that this API points to the shell with + * shellIdentificationId. Can be changed to point to a different shell in the + * database. * - * @param aasId + * @param shellIdentificationId */ - public void setAASId(String aasId) { - this.aasId = aasId; + public void setAASId(String shellIdentificationId) { + this.shellIdentificationId = shellIdentificationId; } /** * Depending on whether the model is already in the db, this method inserts or - * replaces the existing data. The new aas id for this API is taken from the - * given aas. + * replaces the existing data. The new shell id for this API is taken from the + * given shell. * - * @param aas + * @param shell */ - public void setAAS(AssetAdministrationShell aas) { - String id = aas.getIdentification().getId(); + public void setAAS(AssetAdministrationShell shell) { + String id = shell.getIdentification().getId(); this.setAASId(id); - - Query hasId = query(where(AASIDPATH).is(aasId)); - // Try to replace if already present - otherwise: insert it - Object replaced = mongoOps.findAndReplace(hasId, aas, collection); - if (replaced == null) { - mongoOps.insert(aas, collection); - } - // Remove mongoDB-specific map attribute from AAS. - // mongoOps modify aas on save - thus _id has to be removed here... - aas.remove("_id"); + storageApi.createOrUpdate(shell); } @Override public IAssetAdministrationShell getAAS() { - Query hasId = query(where(AASIDPATH).is(aasId)); - AssetAdministrationShell aas = mongoOps.findOne(hasId, AssetAdministrationShell.class, collection); - if (aas == null) { - throw new ResourceNotFoundException("The AAS " + aasId + " could not be found in the database."); - } - // Remove mongoDB-specific map attribute from AAS - aas.remove("_id"); - return aas; + return storageApi.retrieve(shellIdentificationId); } @Override - public void addSubmodel(IReference submodel) { - // Get AAS from db - Query hasId = query(where(AASIDPATH).is(aasId)); - AssetAdministrationShell aas = mongoOps.findOne(hasId, AssetAdministrationShell.class, collection); - if (aas == null) { - throw new ResourceNotFoundException("The AAS " + aasId + " could not be found in the database."); - } - // Add reference - aas.addSubmodelReference(submodel); - // Update db entry - mongoOps.findAndReplace(hasId, aas, collection); + public void addSubmodel(IReference submodelReference) { + AssetAdministrationShell shell = (AssetAdministrationShell) getAAS(); + shell.addSubmodelReference(submodelReference); + storageApi.update(shell, shellIdentificationId); } @Override - public void removeSubmodel(String id) { - // Get AAS from db - Query hasId = query(where(AASIDPATH).is(aasId)); - AssetAdministrationShell aas = mongoOps.findOne(hasId, AssetAdministrationShell.class, collection); - if (aas == null) { - throw new ResourceNotFoundException("The AAS " + aasId + " could not be found in the database."); - } - // Remove reference - Collection smReferences = aas.getSubmodelReferences(); - // Reference to submodel could be either by idShort (=> local) or directly via - // its identifier - for (Iterator iterator = smReferences.iterator(); iterator.hasNext();) { - IReference ref = iterator.next(); - List keys = ref.getKeys(); - IKey lastKey = keys.get(keys.size() - 1); - String idValue = lastKey.getValue(); - // remove this reference, if the last key points to the submodel - if (idValue.equals(id)) { - iterator.remove(); - break; - } + public void removeSubmodel(String submodelIdShort) { + AssetAdministrationShell shell = (AssetAdministrationShell) this.getAAS(); + Collection submodelReferences = shell.getSubmodelReferences(); + + Optional toBeRemoved = submodelReferences.stream().filter(submodelReference -> getLastSubmodelReferenceKey(submodelReference).getValue().equals(submodelIdShort)).findFirst(); + if (!toBeRemoved.isPresent() || toBeRemoved.isEmpty()) { + logger.warn("Submodel reference could not be removed. Shell with identification id '{}' does not contain submodel with idShort '{}'.", shell.getIdentification().getId(), submodelIdShort); + return; } - aas.setSubmodelReferences(smReferences); - // Update db entry - mongoOps.findAndReplace(hasId, aas, collection); + submodelReferences.remove(toBeRemoved.get()); + shell.setSubmodelReferences(submodelReferences); + storageApi.update(shell, submodelIdShort); } + private IKey getLastSubmodelReferenceKey(IReference submodelReference) { + return submodelReference.getKeys().get(getLastSubmodelReferenceReferenceIndex(submodelReference)); + } + + private int getLastSubmodelReferenceReferenceIndex(IReference submodelReference) { + return submodelReference.getKeys().size() - 1; + } } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPIFactory.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPIFactory.java index 3fabc1d6..8498242b 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPIFactory.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPIFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2022 the Eclipse BaSyx Authors + * Copyright (C) 2022, 2023 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,36 +28,40 @@ import org.eclipse.basyx.aas.restapi.api.IAASAPI; import org.eclipse.basyx.aas.restapi.api.IAASAPIFactory; import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; /** * * Factory for creating a MongoDBAASAPI * - * @author fried + * @author fried, jungjan, witt * */ public class MongoDBAASAPIFactory implements IAASAPIFactory { - private BaSyxMongoDBConfiguration config; - private MongoClient client; + private MongoDBBaSyxStorageAPI storageAPI; @Deprecated public MongoDBAASAPIFactory(BaSyxMongoDBConfiguration config) { - this(config, MongoClients.create(config.getConnectionUrl())); + this(MongoDBBaSyxStorageAPIFactory.create(config.getAASCollection(), AssetAdministrationShell.class, config)); } public MongoDBAASAPIFactory(BaSyxMongoDBConfiguration config, MongoClient client) { - this.config = config; - this.client = client; + this(MongoDBBaSyxStorageAPIFactory.create(config.getAASCollection(), AssetAdministrationShell.class, config, client)); + } + + public MongoDBAASAPIFactory(MongoDBBaSyxStorageAPI mongoDBStorageAPI) { + this.storageAPI = mongoDBStorageAPI; } @Override - public IAASAPI getAASApi(AssetAdministrationShell aas) { - MongoDBAASAPI api = new MongoDBAASAPI(config, aas.getIdentification().getId(), client); - api.setAAS(aas); + public IAASAPI getAASApi(AssetAdministrationShell shell) { + new MongoDBAASAPI(storageAPI, shell.getIdentification().getId()); + MongoDBAASAPI api = new MongoDBAASAPI(storageAPI, shell.getIdentification().getId()); + api.setAAS(shell); return api; } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java index 5f440dcb..8c158345 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021 the Eclipse BaSyx Authors + * Copyright (C) 2021, 2023 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 @@ -24,10 +24,6 @@ ******************************************************************************/ package org.eclipse.basyx.components.aas.mongodb; -import static org.springframework.data.mongodb.core.query.Criteria.where; -import static org.springframework.data.mongodb.core.query.Query.query; - -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -46,6 +42,8 @@ import org.eclipse.basyx.aas.restapi.api.IAASAPIFactory; import org.eclipse.basyx.components.aas.aascomponent.MongoDBAASServerComponentFactory; import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; import org.eclipse.basyx.extensions.shared.authorization.internal.NotAuthorizedException; import org.eclipse.basyx.submodel.aggregator.SubmodelAggregatorFactory; import org.eclipse.basyx.submodel.aggregator.api.ISubmodelAggregator; @@ -55,9 +53,6 @@ import org.eclipse.basyx.submodel.metamodel.api.reference.IReference; import org.eclipse.basyx.submodel.metamodel.api.reference.enums.KeyType; import org.eclipse.basyx.submodel.metamodel.map.Submodel; -import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier; -import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; -import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable; import org.eclipse.basyx.submodel.restapi.SubmodelProvider; import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI; import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPIFactory; @@ -65,11 +60,6 @@ import org.eclipse.basyx.vab.modelprovider.api.IModelProvider; import org.eclipse.basyx.vab.protocol.api.IConnectorFactory; import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; @@ -79,32 +69,23 @@ * * @see AASAggregator AASAggregator for the "InMemory"-variant * - * @author espen, wege + * @author espen, wege, witt, jugnjan * */ public class MongoDBAASAggregator implements IAASAggregator { - private static Logger logger = LoggerFactory.getLogger(MongoDBAASAggregator.class); - - private static final String IDSHORTPATH = Referable.IDSHORT; - private static final String IDPATH = Identifiable.IDENTIFICATION + "." + Identifier.ID; - - protected Map aasProviderMap = new HashMap<>(); - protected BaSyxMongoDBConfiguration config; - protected MongoOperations mongoOps; - protected String aasCollection; - protected String smCollection; + protected Map shellProviderMap = new HashMap<>(); private IAASRegistry registry; /** * Store AAS API Provider. By default, uses the MongoDB API Provider */ - protected IAASAPIFactory aasApiProvider; + protected IAASAPIFactory shellApiFactory; /** * Store Submodel API Provider. By default, uses a MongoDB Submodel Provider */ - protected ISubmodelAPIFactory smApiProvider; + protected ISubmodelAPIFactory submodelApiFactory; /** * Store SubmodelAggregator. By default, uses standard SubmodelAggregator @@ -115,23 +96,90 @@ public class MongoDBAASAggregator implements IAASAggregator { protected ISubmodelAggregator submodelAggregator; protected ISubmodelAggregatorFactory submodelAggregatorFactory; - private MongoClient mongoClient; + private MongoDBBaSyxStorageAPI submodelStorageApi; + private MongoDBBaSyxStorageAPI shellStorageApi; + + public MongoDBAASAggregator(IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoDBBaSyxStorageAPI submodelStorageApi, + MongoDBBaSyxStorageAPI shellStorageApi) { + this.submodelStorageApi = submodelStorageApi; + this.shellStorageApi = shellStorageApi; + this.shellApiFactory = shellAPIFactory; + this.submodelAggregatorFactory = submodelAggregatorFactory; + this.registry = registry; + init(); + } /** - * Receives a BaSyxMongoDBConfiguration and a registry to create a persistent - * MongoDB backend. - * + * Receives a BaSyxMongoDBConfiguration, IAASRegistry, IAASAPIFactory, + * ISubmodelAggregatorFactory and a MongoClient to create a persistent MongoDB + * backend. + * * @param config - * The MongoDB Configuration + * @param registry + * @param shellAPIFactory + * @param submodelAggregatorFactory * - * @deprecated Use new MongoDBAASAggregator with the - * {@link MongoDBAASServerComponentFactory}. */ - @Deprecated - public MongoDBAASAggregator(BaSyxMongoDBConfiguration config) { - this.setConfiguration(config); - submodelAggregatorFactory = new SubmodelAggregatorFactory(smApiProvider); - init(); + public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + this(registry, shellAPIFactory, submodelAggregatorFactory, submodelStorageApiFromConfig(config, client), shellStorageApiFromConfig(config, client)); + } + + /** + * Receives a BaSyxMongoDBConfiguration, + * IAASAPIFactory,ISubmodelAggregatorFactory and a MongoClient to create a + * persistent MongoDB backend. + * + * @param config + * @param shellAPIFactory + * @param submodelAggregatorFactory + * @param client + * + */ + public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + this(config, null, shellAPIFactory, submodelAggregatorFactory, client); + } + + /** + * Receives a resourceConfigPath, IAASRegistry, IAASAPIFactory, + * ISubmodelAggregatorFactory and a MongoClient to create a persistent MongoDB + * backend. + * + * @param resourceConfigPath + * @param registry + * @param shellAPIFactory + * @param submodelAggregatorFactory + * @param client + * Use the new constructor using a MongoClient + * + */ + public MongoDBAASAggregator(String resourceConfigPath, IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + this(loadConfigFromPath(resourceConfigPath), registry, shellAPIFactory, submodelAggregatorFactory, client); + } + + /** + * Receives a resourceConfigPath, IAASAPIFactory, ISubmodelAggregatorFactory and + * a MongoClient to create a persistent MongoDB backend. + * + * @param resourceConfigPath + * @param shellAPIFactory + * @param submodelAggregatorFactory + * @param client + * + */ + public MongoDBAASAggregator(String resourceConfigPath, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + this(loadConfigFromPath(resourceConfigPath), shellAPIFactory, submodelAggregatorFactory, client); + } + + /** + * Constructor using the default configuration, with the given + * IAASAPIFactory,ISubmodelAggregatorFactory and MongoClient. + * + * @param shellAPIFactory + * @param submodelAggregatorFactory + * @param client + */ + public MongoDBAASAggregator(IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + this(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH, shellAPIFactory, submodelAggregatorFactory, client); } /** @@ -140,18 +188,13 @@ public MongoDBAASAggregator(BaSyxMongoDBConfiguration config) { * * @param config * The MongoDB Configuration - * @param registry - * The registry * * @deprecated Use new MongoDBAASAggregator with the * {@link MongoDBAASServerComponentFactory}. */ @Deprecated - public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASRegistry registry) { - this.setConfiguration(config); - this.registry = registry; - submodelAggregatorFactory = new SubmodelAggregatorFactory(smApiProvider); - init(); + public MongoDBAASAggregator(BaSyxMongoDBConfiguration config) { + this(config, null); } /** @@ -166,11 +209,7 @@ public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASRegistry regis */ @Deprecated public MongoDBAASAggregator(String resourceConfigPath) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - this.setConfiguration(config); - submodelAggregatorFactory = new SubmodelAggregatorFactory(smApiProvider); - init(); + this(loadConfigFromPath(resourceConfigPath)); } /** @@ -186,12 +225,24 @@ public MongoDBAASAggregator(String resourceConfigPath) { */ @Deprecated public MongoDBAASAggregator(String resourceConfigPath, IAASRegistry registry) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - this.setConfiguration(config); - submodelAggregatorFactory = new SubmodelAggregatorFactory(smApiProvider); - this.registry = registry; - init(); + this(loadConfigFromPath(resourceConfigPath), registry); + } + + /** + * Receives a BaSyxMongoDBConfiguration and a registry to create a persistent + * MongoDB backend. + * + * @param config + * The MongoDB Configuration + * @param registry + * The registry + * + * @deprecated Use new MongoDBAASAggregator with the + * {@link MongoDBAASServerComponentFactory}. + */ + @Deprecated + public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASRegistry registry) { + this(registry, initShellApiFactory(config), initSubmodelAggregatorFactory(config), submodelStorageApiFromConfig(config, null), shellStorageApiFromConfig(config, null)); } /** @@ -224,33 +275,13 @@ public MongoDBAASAggregator(IAASRegistry registry) { * * @param config * @param registry - * @param aasAPIFactory + * @param shellAPIFactory * @param submodelAggregatorFactory * @deprecated Use the new constructor using a MongoClient */ @Deprecated - public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASRegistry registry, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { - this(config, registry, aasAPIFactory, submodelAggregatorFactory, MongoClients.create(config.getConnectionUrl())); - } - - /** - * Receives a BaSyxMongoDBConfiguration, IAASRegistry, IAASAPIFactory, - * ISubmodelAggregatorFactory and a MongoClient to create a persistent MongoDB - * backend. - * - * @param config - * @param registry - * @param aasAPIFactory - * @param submodelAggregatorFactory - * - */ - public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASRegistry registry, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { - setMongoDBConfiguration(config, client); - this.config = config; - this.registry = registry; - this.aasApiProvider = aasAPIFactory; - this.submodelAggregatorFactory = submodelAggregatorFactory; - init(); + public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + this(config, registry, shellAPIFactory, submodelAggregatorFactory, MongoClients.create(config.getConnectionUrl())); } /** @@ -258,32 +289,13 @@ public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASRegistry regis * ISubmodelAggregatorFactory to create a persistent MongoDB backend. * * @param config - * @param aasAPIFactory + * @param shellAPIFactory * @param submodelAggregatorFactory * @deprecated Use the new constructor using a MongoClient */ @Deprecated - public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { - this(config, aasAPIFactory, submodelAggregatorFactory, MongoClients.create(config.getConnectionUrl())); - } - - /** - * Receives a BaSyxMongoDBConfiguration, - * IAASAPIFactory,ISubmodelAggregatorFactory and a MongoClient to create a - * persistent MongoDB backend. - * - * @param config - * @param aasAPIFactory - * @param submodelAggregatorFactory - * @param client - * - */ - public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { - setMongoDBConfiguration(config, client); - this.config = config; - this.aasApiProvider = aasAPIFactory; - this.submodelAggregatorFactory = submodelAggregatorFactory; - init(); + public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + this(config, shellAPIFactory, submodelAggregatorFactory, MongoClients.create(config.getConnectionUrl())); } /** @@ -292,42 +304,13 @@ public MongoDBAASAggregator(BaSyxMongoDBConfiguration config, IAASAPIFactory aas * * @param resourceConfigPath * @param registry - * @param aasAPIFactory + * @param shellAPIFactory * @param submodelAggregatorFactory * @deprecated Use the new constructor using a MongoClient */ @Deprecated - public MongoDBAASAggregator(String resourceConfigPath, IAASRegistry registry, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - setMongoDBConfiguration(config, MongoClients.create(config.getConnectionUrl())); - this.registry = registry; - this.aasApiProvider = aasAPIFactory; - this.submodelAggregatorFactory = submodelAggregatorFactory; - init(); - } - - /** - * Receives a resourceConfigPath, IAASRegistry, IAASAPIFactory, - * ISubmodelAggregatorFactory and a MongoClient to create a persistent MongoDB - * backend. - * - * @param resourceConfigPath - * @param registry - * @param aasAPIFactory - * @param submodelAggregatorFactory - * @param client - * Use the new constructor using a MongoClient - * - */ - public MongoDBAASAggregator(String resourceConfigPath, IAASRegistry registry, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - setMongoDBConfiguration(config, client); - this.registry = registry; - this.aasApiProvider = aasAPIFactory; - this.submodelAggregatorFactory = submodelAggregatorFactory; - init(); + public MongoDBAASAggregator(String resourceConfigPath, IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + this(loadConfigFromPath(resourceConfigPath), registry, shellAPIFactory, submodelAggregatorFactory); } /** @@ -335,62 +318,67 @@ public MongoDBAASAggregator(String resourceConfigPath, IAASRegistry registry, IA * ISubmodelAggregatorFactory to create a persistent MongoDB backend. * * @param resourceConfigPath - * @param aasAPIFactory + * @param shellAPIFactory * @param submodelAggregatorFactory * @deprecated Use the new constructor using a MongoClient */ @Deprecated - public MongoDBAASAggregator(String resourceConfigPath, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - setMongoDBConfiguration(config, MongoClients.create(config.getConnectionUrl())); - this.aasApiProvider = aasAPIFactory; - this.submodelAggregatorFactory = submodelAggregatorFactory; - init(); - } - - /** - * Receives a resourceConfigPath, IAASAPIFactory, ISubmodelAggregatorFactory and - * a MongoClient to create a persistent MongoDB backend. - * - * @param resourceConfigPath - * @param aasAPIFactory - * @param submodelAggregatorFactory - * @param client - * - */ - public MongoDBAASAggregator(String resourceConfigPath, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - setMongoDBConfiguration(config, client); - this.aasApiProvider = aasAPIFactory; - this.submodelAggregatorFactory = submodelAggregatorFactory; - init(); + public MongoDBAASAggregator(String resourceConfigPath, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + this(loadConfigFromPath(resourceConfigPath), shellAPIFactory, submodelAggregatorFactory); } /** * Constructor using the default configuration, with the given IAASAPIFactory * and ISubmodelAggregatorFactory. * - * @param aasAPIFactory + * @param shellAPIFactory * @param submodelAggregatorFactory * @deprecated Use the new constructor using a MongoClient */ @Deprecated - public MongoDBAASAggregator(IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { - this(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH, aasAPIFactory, submodelAggregatorFactory); + public MongoDBAASAggregator(IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + this(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH, shellAPIFactory, submodelAggregatorFactory); } - /** - * Constructor using the default configuration, with the given - * IAASAPIFactory,ISubmodelAggregatorFactory and MongoClient. - * - * @param aasAPIFactory - * @param submodelAggregatorFactory - * @param client - */ - public MongoDBAASAggregator(IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { - this(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH, aasAPIFactory, submodelAggregatorFactory, client); + private static ISubmodelAggregatorFactory initSubmodelAggregatorFactory(BaSyxMongoDBConfiguration config) { + ISubmodelAPIFactory submodelApiFactory = initSubmodelApiFactory(config); + return new SubmodelAggregatorFactory(submodelApiFactory); + } + + private static ISubmodelAPIFactory initSubmodelApiFactory(BaSyxMongoDBConfiguration config) { + return new MongoDBSubmodelAPIFactory(config); + } + + private MongoDBSubmodelAPI createAPI(Submodel submodel, BaSyxMongoDBConfiguration config) { + MongoDBSubmodelAPI api = new MongoDBSubmodelAPI(config, submodel.getIdentification().getId()); + api.setSubmodel(submodel); + return api; + } + + private static IAASAPIFactory initShellApiFactory(BaSyxMongoDBConfiguration config) { + return new MongoDBAASAPIFactory(config); + } + + private static MongoDBBaSyxStorageAPI submodelStorageApiFromConfig(BaSyxMongoDBConfiguration config, MongoClient client) { + String submodelCollectionName = config.getSubmodelCollection(); + MongoDBBaSyxStorageAPI submodelStorageApi = client == null + ? MongoDBBaSyxStorageAPIFactory.create(submodelCollectionName, Submodel.class, config) + : MongoDBBaSyxStorageAPIFactory.create(submodelCollectionName, Submodel.class, config, client); + return submodelStorageApi; + } + + private static MongoDBBaSyxStorageAPI shellStorageApiFromConfig(BaSyxMongoDBConfiguration config, MongoClient client) { + String shellCollectionName = config.getAASCollection(); + MongoDBBaSyxStorageAPI shellStorageApi = client == null + ? MongoDBBaSyxStorageAPIFactory.create(shellCollectionName, AssetAdministrationShell.class, config) + : MongoDBBaSyxStorageAPIFactory.create(shellCollectionName, AssetAdministrationShell.class, config, client); + return shellStorageApi; + } + + private static BaSyxMongoDBConfiguration loadConfigFromPath(String resourceConfigPath) { + BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration(); + config.loadFromResource(resourceConfigPath); + return config; } /** @@ -410,64 +398,43 @@ public void setRegistry(IAASRegistry registry) { this.registry = registry; } - /** - * Sets the db configuration for this Aggregator. - * - * @param config - * The MongoDB Configuration - * - * @deprecated This method is used with the old, deprecated Constructors. Use - * {@link MongoDBAASServerComponentFactory} instead - */ - @Deprecated - public void setConfiguration(BaSyxMongoDBConfiguration config) { - MongoClient client = MongoClients.create(config.getConnectionUrl()); - setMongoDBConfiguration(config, client); - - this.aasApiProvider = new MongoDBAASAPIFactory(config, client); - this.smApiProvider = new MongoDBSubmodelAPIFactory(config, client); - } - - private void setMongoDBConfiguration(BaSyxMongoDBConfiguration config, MongoClient client) { - this.config = config; - this.mongoClient = client; - this.mongoOps = new MongoTemplate(client, config.getDatabase()); - this.aasCollection = config.getAASCollection(); - this.smCollection = config.getSubmodelCollection(); - } - /** * Removes all persistent AAS and submodels */ public void reset() { - mongoOps.dropCollection(aasCollection); - mongoOps.dropCollection(smCollection); - aasProviderMap.clear(); + Collection shells = shellStorageApi.retrieveAll(); + Collection submodels = submodelStorageApi.retrieveAll(); + shells.forEach(shell -> shellStorageApi.delete(shell.getIdentification().getId())); + submodels.forEach(shell -> submodelStorageApi.delete(shell.getIdentification().getId())); + shellProviderMap.clear(); } private void init() { - List data = mongoOps.findAll(AssetAdministrationShell.class, aasCollection); - for (AssetAdministrationShell aas : data) { - String aasId = aas.getIdentification().getId(); - logger.info("Adding AAS from DB: " + aasId); - MongoDBAASAPI aasApi = new MongoDBAASAPI(config, aasId, mongoClient); - MultiSubmodelProvider provider = createMultiSubmodelProvider(aasApi); - addSubmodelsFromDB(provider, aas); - aasProviderMap.put(aas.getIdentification().getId(), provider); - } + Collection data = shellStorageApi.retrieveAll(); + data.forEach(shell -> { + String shellIdentificationId = shell.getIdentification().getId(); + IAASAPI shellApi = shellApiFactory.create(shell); + MultiSubmodelProvider provider = createMultiSubmodelProvider(shellApi); + addSubmodelsFromDB(provider, shell); + shellProviderMap.put(shell.getIdentification().getId(), provider); + }); } /** * Initializes and returns a VABMultiSubmodelProvider with only the * AssetAdministrationShell */ - private MultiSubmodelProvider createMultiSubmodelProvider(IAASAPI aasApi) { - AASModelProvider aasProvider = new AASModelProvider(aasApi); - IConnectorFactory connProvider = new HTTPConnectorFactory(); + private MultiSubmodelProvider createMultiSubmodelProvider(IAASAPI shellApi) { + AASModelProvider contentProvider = createContentProvider(shellApi); + IConnectorFactory connectorFactory = new HTTPConnectorFactory(); + + ISubmodelAggregator submodelAggregator = getSubmodelAggregatorInstance(); - ISubmodelAggregator usedAggregator = getSubmodelAggregatorInstance(); + return new MultiSubmodelProvider(contentProvider, this.registry, connectorFactory, this.shellApiFactory, submodelAggregator); + } - return new MultiSubmodelProvider(aasProvider, registry, connProvider, aasApiProvider, usedAggregator); + private AASModelProvider createContentProvider(IAASAPI shellApi) { + return new AASModelProvider(shellApi); } private ISubmodelAggregator getSubmodelAggregatorInstance() { @@ -481,115 +448,139 @@ private ISubmodelAggregator getSubmodelAggregatorInstance() { /** * Adds submodel providers for submodels in the MongoDB */ - private void addSubmodelsFromDB(MultiSubmodelProvider provider, AssetAdministrationShell aas) { - // Get ids and idShorts from aas - Collection submodelRefs = aas.getSubmodelReferences(); - List smIds = new ArrayList<>(); - List smIdShorts = new ArrayList<>(); - for (IReference ref : submodelRefs) { - List keys = ref.getKeys(); - IKey lastKey = keys.get(keys.size() - 1); - if (lastKey.getIdType() == KeyType.IDSHORT) { - smIdShorts.add(lastKey.getValue()); - } else { - smIds.add(lastKey.getValue()); - } - } + private void addSubmodelsFromDB(MultiSubmodelProvider provider, AssetAdministrationShell shell) { + Collection submodelRefs = shell.getSubmodelReferences(); + List submodelIdentificationIds = getSubmodelIdentificationIdsFromSubmodelReferences(submodelRefs); + List submodelIdShorts = getSubmodelIdShortsFromSubmodelReferences(submodelRefs); + submodelIdentificationIds = completeSubmodelIdentificationsIdsByIdShorts(submodelIdentificationIds, submodelIdShorts); + + createProviderForSubmodels(provider, submodelIdentificationIds); + } + + private void createProviderForSubmodels(MultiSubmodelProvider provider, List submodelIdentificationIds) { + submodelIdentificationIds.forEach(submodelIdentificationId -> addSubmodelProvidersById(submodelIdentificationId, provider)); + } - // Add submodel ids by id shorts - for (String idShort : smIdShorts) { - String id = getSubmodelId(idShort); + private List completeSubmodelIdentificationsIdsByIdShorts(List submodelIdentificationIds, List submodelIdShorts) { + submodelIdShorts.forEach(idShort -> { + String id = getSubmodelIdByIdShort(idShort); if (id != null) { - smIds.add(id); + submodelIdentificationIds.add(id); } - } + }); + return submodelIdentificationIds; + } - // Create a provider for each submodel - for (String id : smIds) { - logger.info("Adding Submodel from DB: " + id); - addSubmodelProvidersById(id, provider); - } + private List getSubmodelIdentificationIdsFromSubmodelReferences(Collection submodelRefs) { + List submodelIdentificationIds = submodelRefs.stream() + .map(this::getLastKeyFromReference) + .filter(lastKey -> lastKey.getIdType() != KeyType.IDSHORT) + .map(lastKey -> lastKey.getValue()).collect(Collectors.toList()); + return submodelIdentificationIds; } - private String getSubmodelId(String idShort) { - Submodel sm = mongoOps.findOne(query(where(IDSHORTPATH).is(idShort)), Submodel.class); - if (sm != null) { - return sm.getIdentification().getId(); + private List getSubmodelIdShortsFromSubmodelReferences(Collection submodelRefs) { + List submodelIdShorts = submodelRefs.stream() + .map(this::getLastKeyFromReference) + .filter(lastKey -> lastKey.getIdType() == KeyType.IDSHORT) + .map(lastKey -> lastKey.getValue()).collect(Collectors.toList()); + return submodelIdShorts; + } + + private IKey getLastKeyFromReference(IReference reference) { + List keys = reference.getKeys(); + IKey lastKey = keys.get(keys.size() - 1); + return lastKey; + } + + private String getSubmodelIdByIdShort(String idShort) { + Submodel submodel = submodelStorageApi.retrieve(idShort); + if (submodel != null) { + return submodel.getIdentification().getId(); } return null; } - private void addSubmodelProvidersById(String smId, MultiSubmodelProvider provider) { - ISubmodelAPI smApi = new MongoDBSubmodelAPI(config, smId, mongoClient); - SubmodelProvider smProvider = new SubmodelProvider(smApi); - provider.addSubmodel(smProvider); + private void addSubmodelProvidersById(String submodelIdentificationId, MultiSubmodelProvider provider) { + ISubmodelAPI submodelApi = new MongoDBSubmodelAPI(this.submodelStorageApi, submodelIdentificationId); + SubmodelProvider submodelProvider = new SubmodelProvider(submodelApi); + provider.addSubmodel(submodelProvider); } @SuppressWarnings("unchecked") @Override public Collection getAASList() { - return aasProviderMap.values().stream().map(p -> { + return shellProviderMap.values().stream().map(provider -> { try { - return p.getValue("/aas"); + return provider.getValue("/aas"); } catch (NotAuthorizedException e) { return null; } catch (Exception e1) { e1.printStackTrace(); throw new RuntimeException(); } - }).filter(Objects::nonNull).map(m -> { - AssetAdministrationShell aas = new AssetAdministrationShell(); - aas.putAll((Map) m); - return aas; + }).filter(Objects::nonNull).map(shellMap -> { + AssetAdministrationShell shell = new AssetAdministrationShell(); + shell.putAll((Map) shellMap); + return shell; }).collect(Collectors.toList()); } @SuppressWarnings("unchecked") @Override - public IAssetAdministrationShell getAAS(IIdentifier aasId) { - IModelProvider aasProvider = getAASProvider(aasId); + public IAssetAdministrationShell getAAS(IIdentifier shellIdentification) { + IModelProvider shellProvider = getAASProvider(shellIdentification); - // get all Elements from provider - Map aasMap = (Map) aasProvider.getValue("/aas"); - return AssetAdministrationShell.createAsFacade(aasMap); + Map shellMap = (Map) shellProvider.getValue("/aas"); + return AssetAdministrationShell.createAsFacade(shellMap); } @Override - public void createAAS(AssetAdministrationShell aas) { - IAASAPI aasApi = this.aasApiProvider.create(aas); - MultiSubmodelProvider provider = createMultiSubmodelProvider(aasApi); - aasProviderMap.put(aas.getIdentification().getId(), provider); + public void createAAS(AssetAdministrationShell shell) { + IAASAPI shellApi = this.shellApiFactory.create(shell); + MultiSubmodelProvider provider = createMultiSubmodelProvider(shellApi); + shellProviderMap.put(shell.getIdentification().getId(), provider); } @Override - public void updateAAS(AssetAdministrationShell aas) { - MultiSubmodelProvider oldProvider = (MultiSubmodelProvider) getAASProvider(aas.getIdentification()); - IAASAPI aasApi = aasApiProvider.create(aas); - AASModelProvider contentProvider = new AASModelProvider(aasApi); - IConnectorFactory connectorFactory = oldProvider.getConnectorFactory(); + public void updateAAS(AssetAdministrationShell shell) { + IIdentifier shellIdentification = shell.getIdentification(); + String shellIdentificationId = shellIdentification.getId(); - MultiSubmodelProvider updatedProvider = new MultiSubmodelProvider(contentProvider, registry, connectorFactory, aasApiProvider, oldProvider.getSmAggregator()); + MultiSubmodelProvider oldProvider = (MultiSubmodelProvider) getAASProvider(shellIdentification); - aasProviderMap.put(aas.getIdentification().getId(), updatedProvider); + IAASAPI shellApi = this.shellApiFactory.create(shell); + MultiSubmodelProvider updatedProvider = updateAASProvider(shellApi, oldProvider); + + shellProviderMap.put(shellIdentificationId, updatedProvider); + } + + private MultiSubmodelProvider updateAASProvider(IAASAPI shellApi, MultiSubmodelProvider oldProvider) { + AASModelProvider contentProvider = createContentProvider(shellApi); + IConnectorFactory connectorFactory = oldProvider.getConnectorFactory(); + ISubmodelAggregator submodelAggregator = oldProvider.getSmAggregator(); + + return new MultiSubmodelProvider(contentProvider, this.registry, connectorFactory, shellApiFactory, submodelAggregator); } + @Override - public void deleteAAS(IIdentifier aasId) { - Query hasId = query(where(IDPATH).is(aasId.getId())); - mongoOps.remove(hasId, aasCollection); - aasProviderMap.remove(aasId.getId()); + public void deleteAAS(IIdentifier shellIdentifier) { + String shellIdentificationId = shellIdentifier.getId(); + shellStorageApi.delete(shellIdentificationId); + shellProviderMap.remove(shellIdentificationId); } - public MultiSubmodelProvider getProviderForAASId(String aasId) { - return aasProviderMap.get(aasId); + public MultiSubmodelProvider getProviderForAASId(String shellIdentificationId) { + return shellProviderMap.get(shellIdentificationId); } @Override - public IModelProvider getAASProvider(IIdentifier aasId) { - MultiSubmodelProvider provider = aasProviderMap.get(aasId.getId()); + public IModelProvider getAASProvider(IIdentifier shellIdentificationId) { + MultiSubmodelProvider provider = shellProviderMap.get(shellIdentificationId.getId()); if (provider == null) { - throw new ResourceNotFoundException("AAS with Id " + aasId.getId() + " does not exist"); + throw new ResourceNotFoundException("AAS with Id " + shellIdentificationId.getId() + " does not exist"); } return provider; diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregatorFactory.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregatorFactory.java index 2128129e..29e4712e 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregatorFactory.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregatorFactory.java @@ -45,87 +45,87 @@ public class MongoDBAASAggregatorFactory implements IAASAggregatorFactory { private BaSyxMongoDBConfiguration config; private IAASRegistry registry; - private IAASAPIFactory aasAPIFactory; + private IAASAPIFactory shellAPIFactory; private ISubmodelAggregatorFactory submodelAggregatorFactory; private String resourceConfigPath; private MongoClient client; @Deprecated - public MongoDBAASAggregatorFactory(BaSyxMongoDBConfiguration config, IAASRegistry registry, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { - this(config, registry, aasAPIFactory, submodelAggregatorFactory, MongoClients.create(config.getConnectionUrl())); + public MongoDBAASAggregatorFactory(BaSyxMongoDBConfiguration config, IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + this(config, registry, shellAPIFactory, submodelAggregatorFactory, MongoClients.create(config.getConnectionUrl())); } @Deprecated - public MongoDBAASAggregatorFactory(BaSyxMongoDBConfiguration config, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { - this(config, aasAPIFactory, submodelAggregatorFactory, MongoClients.create(config.getConnectionUrl())); + public MongoDBAASAggregatorFactory(BaSyxMongoDBConfiguration config, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + this(config, shellAPIFactory, submodelAggregatorFactory, MongoClients.create(config.getConnectionUrl())); } @Deprecated - public MongoDBAASAggregatorFactory(String resourceConfigPath, IAASRegistry registry, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + public MongoDBAASAggregatorFactory(String resourceConfigPath, IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { this.resourceConfigPath = resourceConfigPath; this.registry = registry; - this.aasAPIFactory = aasAPIFactory; + this.shellAPIFactory = shellAPIFactory; this.submodelAggregatorFactory = submodelAggregatorFactory; this.client = MongoClients.create(config.getConnectionUrl()); } @Deprecated - public MongoDBAASAggregatorFactory(String resourceConfigPath, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + public MongoDBAASAggregatorFactory(String resourceConfigPath, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { this.resourceConfigPath = resourceConfigPath; - this.aasAPIFactory = aasAPIFactory; + this.shellAPIFactory = shellAPIFactory; this.submodelAggregatorFactory = submodelAggregatorFactory; this.client = MongoClients.create(config.getConnectionUrl()); } @Deprecated - public MongoDBAASAggregatorFactory(IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { - this(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH, aasAPIFactory, submodelAggregatorFactory); + public MongoDBAASAggregatorFactory(IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory) { + this(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH, shellAPIFactory, submodelAggregatorFactory); } - public MongoDBAASAggregatorFactory(BaSyxMongoDBConfiguration config, IAASRegistry registry, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + public MongoDBAASAggregatorFactory(BaSyxMongoDBConfiguration config, IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { this.config = config; this.registry = registry; - this.aasAPIFactory = aasAPIFactory; + this.shellAPIFactory = shellAPIFactory; this.submodelAggregatorFactory = submodelAggregatorFactory; this.client = client; } - public MongoDBAASAggregatorFactory(BaSyxMongoDBConfiguration config, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + public MongoDBAASAggregatorFactory(BaSyxMongoDBConfiguration config, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { this.config = config; - this.aasAPIFactory = aasAPIFactory; + this.shellAPIFactory = shellAPIFactory; this.submodelAggregatorFactory = submodelAggregatorFactory; this.client = client; } - public MongoDBAASAggregatorFactory(String resourceConfigPath, IAASRegistry registry, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + public MongoDBAASAggregatorFactory(String resourceConfigPath, IAASRegistry registry, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { this.resourceConfigPath = resourceConfigPath; this.registry = registry; - this.aasAPIFactory = aasAPIFactory; + this.shellAPIFactory = shellAPIFactory; this.submodelAggregatorFactory = submodelAggregatorFactory; this.client = client; } - public MongoDBAASAggregatorFactory(String resourceConfigPath, IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + public MongoDBAASAggregatorFactory(String resourceConfigPath, IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { this.resourceConfigPath = resourceConfigPath; - this.aasAPIFactory = aasAPIFactory; + this.shellAPIFactory = shellAPIFactory; this.submodelAggregatorFactory = submodelAggregatorFactory; this.client = client; } - public MongoDBAASAggregatorFactory(IAASAPIFactory aasAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { - this(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH, aasAPIFactory, submodelAggregatorFactory); + public MongoDBAASAggregatorFactory(IAASAPIFactory shellAPIFactory, ISubmodelAggregatorFactory submodelAggregatorFactory, MongoClient client) { + this(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH, shellAPIFactory, submodelAggregatorFactory); } @Override public IAASAggregator create() { if (this.config != null && this.registry != null) { - return new MongoDBAASAggregator(this.config, this.registry, this.aasAPIFactory, this.submodelAggregatorFactory, this.client); + return new MongoDBAASAggregator(this.config, this.registry, this.shellAPIFactory, this.submodelAggregatorFactory, this.client); } else if (this.config != null) { - return new MongoDBAASAggregator(this.config, this.aasAPIFactory, this.submodelAggregatorFactory, this.client); + return new MongoDBAASAggregator(this.config, this.shellAPIFactory, this.submodelAggregatorFactory, this.client); } else if (this.resourceConfigPath != null && this.registry != null) { - return new MongoDBAASAggregator(this.resourceConfigPath, this.registry, this.aasAPIFactory, this.submodelAggregatorFactory, this.client); + return new MongoDBAASAggregator(this.resourceConfigPath, this.registry, this.shellAPIFactory, this.submodelAggregatorFactory, this.client); } else { - return new MongoDBAASAggregator(this.resourceConfigPath, this.aasAPIFactory, this.submodelAggregatorFactory, this.client); + return new MongoDBAASAggregator(this.resourceConfigPath, this.shellAPIFactory, this.submodelAggregatorFactory, this.client); } } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java index 56edbb9c..b87e069d 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021 the Eclipse BaSyx Authors + * Copyright (C) 2021, 2023 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 @@ -51,53 +51,56 @@ public class MongoDBSubmodelAPI extends StorageSubmodelAPI { protected BaSyxMongoDBConfiguration config; protected String collection; + /** * Receives the path of the configuration.properties file in its constructor. * * @param config - * @deprecated Use the new constructor using a MongoClient */ - @Deprecated - public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId) { - this(config, smId, new DelegatedInvocationManager(new HTTPConnectorFactory())); - } - - @Deprecated - public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, DelegatedInvocationManager invocationHelper) { - this(config, smId, invocationHelper, MongoClients.create(config.getConnectionUrl())); + public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String submdoelIdentificationId, MongoClient client) { + this(config, submdoelIdentificationId, new DelegatedInvocationManager(new HTTPConnectorFactory()), client); } /** - * Receives the path of the .properties file in its constructor from a resource. - * - * @deprecated Use the new constructor using a MongoClient + * Constructor using default MongoDB connections */ - @Deprecated - public MongoDBSubmodelAPI(String resourceConfigPath, String smId) { - this(resourceConfigPath, smId, new DelegatedInvocationManager(new HTTPConnectorFactory())); + public MongoDBSubmodelAPI(String submodelIdentificationId, MongoClient client) { + this(DEFAULT_CONFIG_PATH, submodelIdentificationId, client); + } + + public MongoDBSubmodelAPI(String submodelIdentificationId, DelegatedInvocationManager invocationHelper, MongoClient client) { + this(DEFAULT_CONFIG_PATH, submodelIdentificationId, invocationHelper, client); + } + + // NEUER KONSTRUKTOR? + public MongoDBSubmodelAPI(BaSyxStorageAPI storageAPI, String identificationId, BaSyxMongoDBConfiguration config) { + super(storageAPI, identificationId, new DelegatedInvocationManager(new HTTPConnectorFactory())); + this.setConfiguration(config); + } + + public MongoDBSubmodelAPI(BaSyxStorageAPI storageAPI, String identificationId) { + super(storageAPI, identificationId, new DelegatedInvocationManager(new HTTPConnectorFactory())); } /** - * Constructor using default MongoDB connections - * - * @deprecated Use the new constructor using a MongoClient + * Receives the path of the .properties file in its constructor from a resource. */ - @Deprecated - public MongoDBSubmodelAPI(String smId) { - this(DEFAULT_CONFIG_PATH, smId); + public MongoDBSubmodelAPI(String resourceConfigPath, String submodelIdentificationId, MongoClient client) { + this(resourceConfigPath, submodelIdentificationId, new DelegatedInvocationManager(new HTTPConnectorFactory()), client); } - @Deprecated - public MongoDBSubmodelAPI(String smId, DelegatedInvocationManager invocationHelper) { - this(DEFAULT_CONFIG_PATH, smId, invocationHelper); + public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String submodelIdentificationId, DelegatedInvocationManager invocationHelper, MongoClient client) { + super(createSubmodelStorageAPI(config, client), submodelIdentificationId, invocationHelper); + this.setConfiguration(config); + this.setSubmodelId(submodelIdentificationId); + this.invocationHelper = invocationHelper; } - @Deprecated - public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvocationManager invocationHelper) { - super(createSubmodelStorageAPI(createConfig(resourceConfigPath)), smId, invocationHelper); + public MongoDBSubmodelAPI(String resourceConfigPath, String submodelIdentificationId, DelegatedInvocationManager invocationHelper, MongoClient client) { + super(createSubmodelStorageAPI(createConfig(resourceConfigPath), client), submodelIdentificationId, invocationHelper); this.config = createConfig(resourceConfigPath); this.setConfiguration(config); - this.setSubmodelId(smId); + this.setSubmodelId(submodelIdentificationId); this.invocationHelper = invocationHelper; } @@ -105,51 +108,49 @@ public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvoc * Receives the path of the configuration.properties file in its constructor. * * @param config + * @deprecated Use the new constructor using a MongoClient */ - public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, MongoClient client) { - this(config, smId, new DelegatedInvocationManager(new HTTPConnectorFactory()), client); - } - - /** - * Constructor using default MongoDB connections - */ - public MongoDBSubmodelAPI(String smId, MongoClient client) { - this(DEFAULT_CONFIG_PATH, smId, client); - } - - public MongoDBSubmodelAPI(String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { - this(DEFAULT_CONFIG_PATH, smId, invocationHelper, client); + @Deprecated + public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String submodelIdentificationId) { + this(config, submodelIdentificationId, new DelegatedInvocationManager(new HTTPConnectorFactory())); } - // NEUER KONSTRUKTOR? - public MongoDBSubmodelAPI(BaSyxStorageAPI storageAPI, String identificationId, BaSyxMongoDBConfiguration config) { - super(storageAPI, identificationId, new DelegatedInvocationManager(new HTTPConnectorFactory())); - this.setConfiguration(config); + @Deprecated + public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String submodelIdentificationId, DelegatedInvocationManager invocationHelper) { + this(config, submodelIdentificationId, invocationHelper, MongoClients.create(config.getConnectionUrl())); } - public MongoDBSubmodelAPI(BaSyxStorageAPI storageAPI, String identificationId) { - super(storageAPI, identificationId, new DelegatedInvocationManager(new HTTPConnectorFactory())); + /** + * Receives the path of the .properties file in its constructor from a resource. + * + * @deprecated Use the new constructor using a MongoClient + */ + @Deprecated + public MongoDBSubmodelAPI(String resourceConfigPath, String submodelIdentificationId) { + this(resourceConfigPath, submodelIdentificationId, new DelegatedInvocationManager(new HTTPConnectorFactory())); } /** - * Receives the path of the .properties file in its constructor from a resource. + * Constructor using default MongoDB connections + * + * @deprecated Use the new constructor using a MongoClient */ - public MongoDBSubmodelAPI(String resourceConfigPath, String smId, MongoClient client) { - this(resourceConfigPath, smId, new DelegatedInvocationManager(new HTTPConnectorFactory()), client); + @Deprecated + public MongoDBSubmodelAPI(String submodelIdentificationId) { + this(DEFAULT_CONFIG_PATH, submodelIdentificationId); } - public MongoDBSubmodelAPI(BaSyxMongoDBConfiguration config, String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { - super(createSubmodelStorageAPI(config, client), smId, invocationHelper); - this.setConfiguration(config); - this.setSubmodelId(smId); - this.invocationHelper = invocationHelper; + @Deprecated + public MongoDBSubmodelAPI(String submodelIdentificationId, DelegatedInvocationManager invocationHelper) { + this(DEFAULT_CONFIG_PATH, submodelIdentificationId, invocationHelper); } - public MongoDBSubmodelAPI(String resourceConfigPath, String smId, DelegatedInvocationManager invocationHelper, MongoClient client) { - super(createSubmodelStorageAPI(createConfig(resourceConfigPath), client), smId, invocationHelper); + @Deprecated + public MongoDBSubmodelAPI(String resourceConfigPath, String submodelIdentificationId, DelegatedInvocationManager invocationHelper) { + super(createSubmodelStorageAPI(createConfig(resourceConfigPath)), submodelIdentificationId, invocationHelper); this.config = createConfig(resourceConfigPath); this.setConfiguration(config); - this.setSubmodelId(smId); + this.setSubmodelId(submodelIdentificationId); this.invocationHelper = invocationHelper; } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPIFactory.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPIFactory.java index 14ebf51a..af864a80 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPIFactory.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPIFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2022 the Eclipse BaSyx Authors + * Copyright (C) 2022, 2023 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 @@ -44,16 +44,16 @@ public class MongoDBSubmodelAPIFactory implements ISubmodelAPIFactory { private BaSyxMongoDBConfiguration config; private MongoClient client; - @Deprecated - public MongoDBSubmodelAPIFactory(BaSyxMongoDBConfiguration config) { - this(config, MongoClients.create(config.getConnectionUrl())); - } - public MongoDBSubmodelAPIFactory(BaSyxMongoDBConfiguration config, MongoClient client) { this.config = config; this.client = client; } + @Deprecated + public MongoDBSubmodelAPIFactory(BaSyxMongoDBConfiguration config) { + this(config, MongoClients.create(config.getConnectionUrl())); + } + @Deprecated @Override public ISubmodelAPI getSubmodelAPI(Submodel submodel) { diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregator.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregator.java index e8d74184..3ba1f2ab 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregator.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2022 the Eclipse BaSyx Authors + * Copyright (C) 2022, 2023 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 @@ -25,64 +25,52 @@ package org.eclipse.basyx.components.aas.mongodb; -import static org.springframework.data.mongodb.core.query.Criteria.where; -import static org.springframework.data.mongodb.core.query.Query.query; - import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; import org.eclipse.basyx.submodel.aggregator.SubmodelAggregator; import org.eclipse.basyx.submodel.metamodel.api.ISubmodel; import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier; +import org.eclipse.basyx.submodel.metamodel.map.Submodel; import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPIFactory; -import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; /** * Extends the {@link SubmodelAggregator} for the needs of MongoDB * - * @author schnicke + * @author schnicke, jungjan, witt * */ public class MongoDBSubmodelAggregator extends SubmodelAggregator { + private MongoDBBaSyxStorageAPI storageApi; - private String smCollection; - private MongoTemplate mongoOps; - - @Deprecated - public MongoDBSubmodelAggregator(ISubmodelAPIFactory smApiFactory, BaSyxMongoDBConfiguration config) { - this(smApiFactory, config, MongoClients.create(config.getConnectionUrl())); + public MongoDBSubmodelAggregator(ISubmodelAPIFactory submodelApiFactory, BaSyxMongoDBConfiguration config, MongoClient client) { + this(submodelApiFactory, MongoDBBaSyxStorageAPIFactory.create(config.getSubmodelCollection(), Submodel.class, config, client)); } - public MongoDBSubmodelAggregator(ISubmodelAPIFactory smApiFactory, BaSyxMongoDBConfiguration config, MongoClient client) { - super(smApiFactory); - - smCollection = config.getSubmodelCollection(); + public MongoDBSubmodelAggregator(ISubmodelAPIFactory submodelApiFactory, MongoDBBaSyxStorageAPI storageApi) { + super(submodelApiFactory); + this.storageApi = storageApi; + } - mongoOps = new MongoTemplate(client, config.getDatabase()); + @Deprecated + public MongoDBSubmodelAggregator(ISubmodelAPIFactory submodelApiFactory, BaSyxMongoDBConfiguration config) { + this(submodelApiFactory, MongoDBBaSyxStorageAPIFactory.create(config.getSubmodelCollection(), Submodel.class, config)); } + @Override - public void deleteSubmodelByIdentifier(IIdentifier identifier) { - super.deleteSubmodelByIdentifier(identifier); - deleteSubmodelFromDB(identifier); + public void deleteSubmodelByIdentifier(IIdentifier submodelIdentifier) { + super.deleteSubmodelByIdentifier(submodelIdentifier); + storageApi.delete(submodelIdentifier.getId()); } @Override public void deleteSubmodelByIdShort(String idShort) { - try { - ISubmodel sm = getSubmodelbyIdShort(idShort); - super.deleteSubmodelByIdShort(idShort); - deleteSubmodelFromDB(sm.getIdentification()); - } catch (ResourceNotFoundException e) { - // Nothing to do - } + ISubmodel submodel = getSubmodelbyIdShort(idShort); + super.deleteSubmodelByIdShort(idShort); + storageApi.delete(submodel.getIdentification().getId()); } - private void deleteSubmodelFromDB(IIdentifier identifier) { - Query hasId = query(where(MongoDBSubmodelAPI.SMIDPATH).is(identifier.getId())); - mongoOps.remove(hasId, smCollection); - } } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregatorFactory.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregatorFactory.java index 0bf1bc2e..72c5a051 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregatorFactory.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregatorFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2022 the Eclipse BaSyx Authors + * Copyright (C) 2022, 2023 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 @@ -46,17 +46,17 @@ public class MongoDBSubmodelAggregatorFactory implements ISubmodelAggregatorFact private ISubmodelAPIFactory submodelAPIFactory; private MongoClient client; - @Deprecated - public MongoDBSubmodelAggregatorFactory(BaSyxMongoDBConfiguration config, ISubmodelAPIFactory submodelAPIFactory) { - this(config, submodelAPIFactory, MongoClients.create(config.getConnectionUrl())); - } - public MongoDBSubmodelAggregatorFactory(BaSyxMongoDBConfiguration config, ISubmodelAPIFactory submodelAPIFactory, MongoClient client) { this.config = config; this.client = client; this.submodelAPIFactory = submodelAPIFactory; } + @Deprecated + public MongoDBSubmodelAggregatorFactory(BaSyxMongoDBConfiguration config, ISubmodelAPIFactory submodelAPIFactory) { + this(config, submodelAPIFactory, MongoClients.create(config.getConnectionUrl())); + } + @Override public ISubmodelAggregator create() { return new MongoDBSubmodelAggregator(submodelAPIFactory, config, client); diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAAASAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAAASAPI.java new file mode 100644 index 00000000..21cd3d8f --- /dev/null +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAAASAPI.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (C) 2023 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.basyx.regression.AASServer.mongodb; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Collection; + +import org.eclipse.basyx.aas.metamodel.api.IAssetAdministrationShell; +import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell; +import org.eclipse.basyx.aas.metamodel.map.descriptor.CustomId; +import org.eclipse.basyx.components.aas.mongodb.MongoDBAASAPI; +import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; +import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier; +import org.eclipse.basyx.submodel.metamodel.api.reference.IReference; +import org.eclipse.basyx.submodel.metamodel.map.Submodel; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * + * @author jungjan, witt + * + */ +public class TestMongoDBAAASAPI { + private static MongoDBAASAPI shellAPI; + private final static String COLLECTION_NAME = "testCollection"; + private final static BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration(); + private static MongoDBBaSyxStorageAPI mongoDBStorageAPI; + private final static String SHELL_IDENTIFICATION_ID = "testIdentificationId"; + + @BeforeClass + public static void setUpClass() { + mongoDBStorageAPI = new MongoDBBaSyxStorageAPI<>(COLLECTION_NAME, AssetAdministrationShell.class, config); + shellAPI = new MongoDBAASAPI(mongoDBStorageAPI, SHELL_IDENTIFICATION_ID); + } + + @Before + public void before() { + Collection shells = mongoDBStorageAPI.retrieveAll(); + shells.forEach(shell -> mongoDBStorageAPI.delete(shell.getIdentification().getId())); + } + + @Test + public void setAndGetAAS() { + String idShort = "testIdShort"; + + IIdentifier identification = new CustomId(SHELL_IDENTIFICATION_ID); + AssetAdministrationShell expectedShell = new AssetAdministrationShell(idShort, identification, null); + + shellAPI.setAAS(expectedShell); + AssetAdministrationShell resultShell = (AssetAdministrationShell) shellAPI.getAAS(); + + assertEquals(expectedShell, resultShell); + } + + @Test + public void addSubmodel() { + String idShortShell = "testIdShortShell"; + String idShortSubmodel = "testIdShortSubmodel"; + + IIdentifier identification = new CustomId(SHELL_IDENTIFICATION_ID); + + AssetAdministrationShell expectedShell = new AssetAdministrationShell(idShortShell, identification, null); + shellAPI.setAAS(expectedShell); + + Submodel expectedSubmodel = new Submodel(idShortSubmodel, identification); + IReference testReference = expectedSubmodel.getReference(); + + expectedShell.addSubmodelReference(testReference); + shellAPI.addSubmodel(testReference); + + Object resultShell = shellAPI.getAAS(); + + assertEquals(expectedShell, resultShell); + + } + + @Test + public void removeSubmodel() { + String idShortShell = "testIdShortShell"; + String idShortSubmodel = "testIdShortSubmodel"; + + IIdentifier identification = new CustomId(SHELL_IDENTIFICATION_ID); + + AssetAdministrationShell testShell = new AssetAdministrationShell(idShortShell, identification, null); + + Submodel expectedSubmodel = new Submodel(idShortSubmodel, identification); + IReference testReference = expectedSubmodel.getReference(); + + shellAPI.setAAS(testShell); + shellAPI.addSubmodel(testReference); + shellAPI.removeSubmodel(expectedSubmodel.getIdentification().getId()); + + IAssetAdministrationShell resultShell = shellAPI.getAAS(); + Collection submodelReferences = resultShell.getSubmodelReferences(); + assertTrue(submodelReferences.isEmpty()); + } +} diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBRegistryHandler.java b/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBRegistryHandler.java index 1f3ae601..5f4bfeae 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBRegistryHandler.java +++ b/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBRegistryHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021 the Eclipse BaSyx Authors + * Copyright (C) 2021, 2023 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,31 +32,26 @@ import org.eclipse.basyx.aas.metamodel.map.descriptor.AASDescriptor; import org.eclipse.basyx.aas.registration.memory.IRegistryHandler; import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier; import org.eclipse.basyx.submodel.metamodel.map.identifier.Identifier; import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.index.TextIndexDefinition; import org.springframework.data.mongodb.core.query.Criteria; -import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; - /** * A registry handler based on MongoDB * - * @author espen + * @author espen, jungjan, witt */ public class MongoDBRegistryHandler implements IRegistryHandler { private static final String DEFAULT_CONFIG_PATH = "mongodb.properties"; - protected BaSyxMongoDBConfiguration config; - protected MongoOperations mongoOps; - protected String collection; + private MongoDBBaSyxStorageAPI storageApi; - private static final String AASID = Identifiable.IDENTIFICATION + "." + Identifier.ID; - private static final String ASSETID = AASDescriptor.ASSET + "." + Identifiable.IDENTIFICATION + "." + Identifier.ID; + private static final String SHELL_IDENTIFICATION_ID = Identifiable.IDENTIFICATION + "." + Identifier.ID; + private static final String ASSET_IDENTIFICATION_ID = AASDescriptor.ASSET + "." + Identifiable.IDENTIFICATION + "." + Identifier.ID; /** * Receives the path of the configuration.properties file in it's constructor. @@ -64,7 +59,7 @@ public class MongoDBRegistryHandler implements IRegistryHandler { * @param config */ public MongoDBRegistryHandler(BaSyxMongoDBConfiguration config) { - this.setConfiguration(config); + this.initStorageApi(config); } /** @@ -72,15 +67,13 @@ public MongoDBRegistryHandler(BaSyxMongoDBConfiguration config) { * resource. */ public MongoDBRegistryHandler(String resourceConfigPath) { - config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(resourceConfigPath); - this.setConfiguration(config); - configureIndexForAasId(mongoOps); + this(configFromResource(resourceConfigPath)); } - private void configureIndexForAasId(MongoOperations mongoOps) { - TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(AASID).build(); - mongoOps.indexOps(AASDescriptor.class).ensureIndex(idIndex); + private static BaSyxMongoDBConfiguration configFromResource(String resourceConfigPath) { + BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration(); + config.loadFromResource(resourceConfigPath); + return config; } /** @@ -91,67 +84,58 @@ public MongoDBRegistryHandler() { } public void setConfiguration(BaSyxMongoDBConfiguration config) { - this.config = config; - MongoClient client = MongoClients.create(config.getConnectionUrl()); - this.mongoOps = new MongoTemplate(client, config.getDatabase()); - this.collection = config.getRegistryCollection(); + this.initStorageApi(config); + } + + private void initStorageApi(BaSyxMongoDBConfiguration config) { + String collectionName = config.getRegistryCollection(); + MongoDBBaSyxStorageAPIFactory storageApiFactory = new MongoDBBaSyxStorageAPIFactory<>(config, AASDescriptor.class, collectionName); + this.storageApi = storageApiFactory.create(); } @Override public boolean contains(IIdentifier identifier) { - String id = identifier.getId(); + String identificationId = identifier.getId(); Criteria hasId = new Criteria(); - hasId.orOperator(where(AASID).is(id), where(ASSETID).is(id)); - return mongoOps.exists(query(hasId), collection); + hasId.orOperator(where(SHELL_IDENTIFICATION_ID).is(identificationId), where(ASSET_IDENTIFICATION_ID).is(identificationId)); + + return getStorageConnection().exists(query(hasId), this.storageApi.getCollectionName()); + } + + private MongoOperations getStorageConnection() { + return (MongoOperations) this.storageApi.getStorageConnection(); } @Override public void remove(IIdentifier identifier) { - String id = identifier.getId(); + String indentificationId = identifier.getId(); Criteria hasId = new Criteria(); - hasId.orOperator(where(AASID).is(id), where(ASSETID).is(id)); - mongoOps.remove(query(hasId), collection); + hasId.orOperator(where(SHELL_IDENTIFICATION_ID).is(indentificationId), where(ASSET_IDENTIFICATION_ID).is(indentificationId)); + getStorageConnection().remove(query(hasId), this.storageApi.getCollectionName()); } @Override public void insert(AASDescriptor descriptor) { - mongoOps.insert(descriptor, collection); - // mongoOps added "_id" to descriptor after insert - removeMongoDBSpecificId(descriptor); + this.update(descriptor); } @Override public void update(AASDescriptor descriptor) { - String aasId = descriptor.getIdentifier().getId(); - Object result = mongoOps.findAndReplace(query(where(AASID).is(aasId)), descriptor, collection); - if (result == null) { - insert(descriptor); - } + this.storageApi.createOrUpdate(descriptor); } @Override public AASDescriptor get(IIdentifier identifier) { - String id = identifier.getId(); + String indentificationId = identifier.getId(); Criteria hasId = new Criteria(); - hasId.orOperator(where(AASID).is(id), where(ASSETID).is(id)); - AASDescriptor result = mongoOps.findOne(query(hasId), AASDescriptor.class, collection); - removeMongoDBSpecificId(result); - - return result; - } + hasId.orOperator(where(SHELL_IDENTIFICATION_ID).is(indentificationId), where(ASSET_IDENTIFICATION_ID).is(indentificationId)); - private void removeMongoDBSpecificId(AASDescriptor result) { - if (result != null) { - // Remove mongoDB-specific map attribute from AASDescriptor - result.remove("_id"); - } + AASDescriptor result = getStorageConnection().findOne(query(hasId), AASDescriptor.class, this.storageApi.getCollectionName()); + return this.storageApi.handleMongoDbIdAttribute(result); } @Override public List getAll() { - List result = mongoOps.findAll(AASDescriptor.class, collection); - // Remove mongoDB-specific map attribute from AASDescriptor - result.forEach(desc -> desc.remove("_id")); - return result; + return (List) this.storageApi.retrieveAll(); } } diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBTaggedDirectory.java b/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBTaggedDirectory.java index 68676631..5db11836 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBTaggedDirectory.java +++ b/basyx.components/basyx.components.docker/basyx.components.registry/src/main/java/org/eclipse/basyx/components/registry/mongodb/MongoDBTaggedDirectory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021-2022 the Eclipse BaSyx Authors + * Copyright (C) 2021, 2022, 2023 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 @@ -64,18 +64,18 @@ private boolean isTaggedDescriptor(ModelDescriptor descriptor) { } @Override - public void registerSubmodel(IIdentifier aas, TaggedSubmodelDescriptor descriptor) { - super.register(aas, descriptor); + public void registerSubmodel(IIdentifier shellIdentifier, TaggedSubmodelDescriptor descriptor) { + super.register(shellIdentifier, descriptor); addSubmodelTags(descriptor); - updateTagMap(aas, descriptor); + updateTagMap(shellIdentifier, descriptor); } - private void updateTagMap(IIdentifier aas, TaggedSubmodelDescriptor descriptor) { + private void updateTagMap(IIdentifier shellIdentifier, TaggedSubmodelDescriptor descriptor) { tagMap.values().forEach(tagSet -> { - tagSet.forEach(tagDesc -> { - if (descriptorEqualsToGivenAASId(aas, tagDesc)) { - if (!containsSubmodelDescriptor(descriptor, tagDesc)) - tagDesc.addSubmodelDescriptor(descriptor); + tagSet.forEach(taggedDescriptor -> { + if (descriptorEqualsToGivenAASId(shellIdentifier, taggedDescriptor)) { + if (!containsSubmodelDescriptor(descriptor, taggedDescriptor)) + taggedDescriptor.addSubmodelDescriptor(descriptor); } }); }); @@ -85,7 +85,7 @@ private boolean containsSubmodelDescriptor(TaggedSubmodelDescriptor descriptor, return tagDesc.getSubmodelDescriptorFromIdShort(descriptor.getIdShort()) != null; } - private boolean descriptorEqualsToGivenAASId(IIdentifier aas, TaggedAASDescriptor tagDesc) { - return tagDesc.getIdentifier().getId().equals(aas.getId()); + private boolean descriptorEqualsToGivenAASId(IIdentifier shellIdentifier, TaggedAASDescriptor taggedDescriptor) { + return taggedDescriptor.getIdentifier().getId().equals(shellIdentifier.getId()); } } diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java index 6fbf24d3..39f7484a 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java @@ -33,8 +33,8 @@ import java.io.InputStream; import java.util.Collection; import java.util.Map; +import java.util.stream.Collectors; -import org.apache.commons.lang3.NotImplementedException; import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; import org.eclipse.basyx.extensions.internal.storage.BaSyxStorageAPI; import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; @@ -43,6 +43,7 @@ import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; +import org.springframework.data.mongodb.core.FindAndReplaceOptions; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.index.TextIndexDefinition; @@ -51,21 +52,27 @@ import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.gridfs.GridFSBucket; +import com.mongodb.client.result.DeleteResult; /** * Provides BaSyxStorageAPI implementation for MongoDB * - * @author fischer + * @author fischer, jungjan, witt * * @param */ public class MongoDBBaSyxStorageAPI extends BaSyxStorageAPI { - private static final String SMIDPATH = Identifiable.IDENTIFICATION + "." + Identifier.ID; + private final String INDEX_KEY = Identifiable.IDENTIFICATION + "." + Identifier.ID; protected BaSyxMongoDBConfiguration config; protected MongoClient client; protected MongoOperations mongoOps; + /** + * @deprecated Please use the other constructor with MongoClient client. + * Using this constructor may lead to inefficient resource utilization. + */ + @Deprecated public MongoDBBaSyxStorageAPI(String collectionName, Class type, BaSyxMongoDBConfiguration config) { this(collectionName, type, config, MongoClients.create(config.getConnectionUrl())); } @@ -75,65 +82,86 @@ public MongoDBBaSyxStorageAPI(String collectionName, Class type, BaSyxMongoDB this.config = config; this.client = client; this.mongoOps = new MongoTemplate(client, config.getDatabase()); - this.configureIndexForSubmodelId(); + this.configureIndexKey(); } - private void configureIndexForSubmodelId() { - TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(SMIDPATH).build(); - this.mongoOps.indexOps(Submodel.class).ensureIndex(idIndex); + private void configureIndexKey() { + TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(INDEX_KEY).build(); + this.mongoOps.indexOps(TYPE).ensureIndex(idIndex); } @Override public T createOrUpdate(T obj) { - throw new NotImplementedException(); + String key = getKey(obj); + if (alreadyExists(key)) { + return update(obj, key); + } + + T created = mongoOps.insert(obj, getCollectionName()); + return handleMongoDbIdAttribute(created); + } + + private boolean alreadyExists(String key) { + Query hasId = query(where(INDEX_KEY).is(key)); + return mongoOps.exists(hasId, getCollectionName()); } @Override public T update(T obj, String key) { - Query hasId = query(where(SMIDPATH).is(key)); - T replaced = mongoOps.findAndReplace(hasId, obj, COLLECTION_NAME); + T replaced = findAndReplaceIfExists(obj, key); if (replaced == null) { - mongoOps.insert(obj, COLLECTION_NAME); + logger.warn("Could not execute update for key {} as it does not exist in the database; Creating new entry...", key); + return createOrUpdate(obj); } - // Remove mongoDB-specific map attribute from SM - // mongoOps modify sm on save - thus _id has to be removed here... - ((Submodel) obj).remove("_id"); - return obj; + replaced = handleMongoDbIdAttribute(replaced); + return replaced; } - @Override - public Collection retrieveAll() { - throw new NotImplementedException(); + private T findAndReplaceIfExists(T obj, String key) { + Query hasId = query(where(INDEX_KEY).is(key)); + FindAndReplaceOptions replacementOptions = setupReplacemantOptionsToReturnNew(); + T replaced = mongoOps.findAndReplace(hasId, obj, replacementOptions.returnNew(), getCollectionName()); + return replaced; + } + + private FindAndReplaceOptions setupReplacemantOptionsToReturnNew() { + FindAndReplaceOptions replacementOptions = FindAndReplaceOptions.empty(); + replacementOptions.returnNew(); + return replacementOptions; + } + + @SuppressWarnings("unchecked") + public T handleMongoDbIdAttribute(T data) { + if (data instanceof Map) + ((Map) data).remove("_id"); + return data; } @Override public boolean delete(String key) { - throw new NotImplementedException(); + Query hasId = query(where(INDEX_KEY).is(key)); + DeleteResult result = mongoOps.remove(hasId, getCollectionName()); + return result.getDeletedCount() == 1L; } @Override public void createCollectionIfNotExists(String collectionName) { - throw new NotImplementedException(); + // MongoOperations implicitly creates Collections. } @Override public void deleteCollection() { - throw new NotImplementedException(); + mongoOps.dropCollection(getCollectionName()); } - @SuppressWarnings("unchecked") @Override public T rawRetrieve(String key) { - // Query Submodel from MongoDB - Query hasId = query(where(SMIDPATH).is(key)); - Submodel result = mongoOps.findOne(hasId, Submodel.class, COLLECTION_NAME); + Query hasId = query(where(INDEX_KEY).is(key)); + var result = mongoOps.findOne(hasId, TYPE, getCollectionName()); if (result == null) { - throw new ResourceNotFoundException("The submodel " + key + " could not be found in the database."); + throw new ResourceNotFoundException("No Object for key '" + key + "' found in the database."); } - - // Remove mongoDB-specific map attribute from AASDescriptor - result.remove("_id"); - + result = handleMongoDbIdAttribute(result); return (T) result; } @@ -162,4 +190,22 @@ public String writeFile(String idShortPath, String parentKey, InputStream inputS public void deleteFile(Submodel submodel, String idShort) { MongoDBFileHelper.deleteAllFilesFromGridFsIfIsFileSubmodelElement(client, config, submodel, idShort); } + + @Override + public Collection rawRetrieveAll() { + Collection data = mongoOps.findAll(TYPE, getCollectionName()); + data = data.stream() + .map(this::handleMongoDbIdAttribute) + .collect(Collectors.toList()); + return data; + } + + @Override + public Object getStorageConnection() { + return mongoOps; + } + + public MongoClient getClient() { + return client; + } } diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPIFactory.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPIFactory.java index 3f74275c..ed20484c 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPIFactory.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPIFactory.java @@ -25,21 +25,23 @@ package org.eclipse.basyx.components.internal.mongodb; +import java.util.HashMap; +import java.util.Map; + import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; /** * - * @author fischer + * @author fischer, jung * * @param * Generic type of the objects to be managed by the produced API */ public class MongoDBBaSyxStorageAPIFactory { - private Logger logger = LoggerFactory.getLogger(getClass()); + private static Map knownClients = new HashMap<>(); private final BaSyxMongoDBConfiguration config; private final Class type; @@ -84,12 +86,65 @@ public MongoDBBaSyxStorageAPIFactory(BaSyxMongoDBConfiguration config, Class this.client = client; } - public MongoDBBaSyxStorageAPI create() { - logger.info("Create MongoDB client..."); - if (client == null) { - return new MongoDBBaSyxStorageAPI(collectionName, type, config); - } else { - return new MongoDBBaSyxStorageAPI(collectionName, type, config, client); + /** + * Creates a generic MongoDBBaSyxStorageAPI. This method has been designed to + * ensure efficient resource utilization by reusing existing storage clients if + * they already exist. + * + * @param + * @param config + * BaSyx MongoDB Configuration + * @param type + * Must be the exact same type as the type of the generic parameter + * {@code } + * @param collectionName + * The name of the collection, managed by the produced API + * @param client + * The client of the MongoDB connection + * @return + */ + public static synchronized MongoDBBaSyxStorageAPI create(String collectionName, Class type, BaSyxMongoDBConfiguration config, MongoClient client) { + String connectionUrl = config.getConnectionUrl(); + if (!knownClients.containsKey(connectionUrl)) { + knownClients.put(connectionUrl, client); } + return new MongoDBBaSyxStorageAPI(collectionName, type, config, knownClients.get(connectionUrl)); + } + + /** + * Creates a generic MongoDBBaSyxStorageAPI. If an appropriate MongoClient + * already exists, it will be reused. + * + * @param + * @param config + * BaSyx MongoDB Configuration + * @param type + * Must be the exact same type as the type of the generic parameter + * {@code } + * @param collectionName + * The name of the collection, managed by the produced API + * @return + */ + public static synchronized MongoDBBaSyxStorageAPI create(String collectionName, Class type, BaSyxMongoDBConfiguration config) { + String connectionUrl = config.getConnectionUrl(); + return knownClients.containsKey(connectionUrl) + ? create(collectionName, type, config, knownClients.get(connectionUrl)) + : create(collectionName, type, config, createNewClient(config)); + } + + private static MongoClient createNewClient(BaSyxMongoDBConfiguration config) { + return MongoClients.create(config.getConnectionUrl()); + } + + /** + * Creates a generic MongoDBBaSyxStorageAPI. If an appropriate MongoClient + * already exists, it will be reused + * + * @return + */ + public MongoDBBaSyxStorageAPI create() { + return this.client == null + ? MongoDBBaSyxStorageAPIFactory.create(collectionName, type, config) + : MongoDBBaSyxStorageAPIFactory.create(collectionName, type, config, client); } } diff --git a/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/components/internal/mongodb/TestMongoDBBaSyxStorageAPI.java b/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/components/internal/mongodb/TestMongoDBBaSyxStorageAPI.java new file mode 100644 index 00000000..a9e373e3 --- /dev/null +++ b/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/components/internal/mongodb/TestMongoDBBaSyxStorageAPI.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (C) 2023 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.basyx.regression.components.internal.mongodb; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; +import org.eclipse.basyx.extensions.internal.storage.BaSyxStorageAPI; +import org.eclipse.basyx.submodel.metamodel.map.Submodel; +import org.eclipse.basyx.testsuite.regression.extensions.storage.BaSyxStorageAPISuite; +import org.junit.After; +import org.springframework.data.mongodb.core.MongoOperations; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; + +public class TestMongoDBBaSyxStorageAPI extends BaSyxStorageAPISuite { + private final static String connectionString = "mongodb://localhost:27017"; + private final static String testSubmodelCollectioName = "testsubnmodels"; + + private static BaSyxMongoDBConfiguration config = createTestConfig(connectionString, testSubmodelCollectioName); + + private static BaSyxMongoDBConfiguration createTestConfig(String connectionstring, String submodelcollectioname) { + BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration(); + config.setConnectionUrl(connectionstring); + config.setSubmodelCollection(submodelcollectioname); + return config; + } + + @After + public void cleanUp() { + this.storageAPI.deleteCollection(); + } + + @Override + protected BaSyxStorageAPI getStorageAPI() { + MongoDBBaSyxStorageAPIFactory storageAPIFactory = new MongoDBBaSyxStorageAPIFactory(config, Submodel.class, config.getSubmodelCollection()); + return storageAPIFactory.create(); + } + + @Override + protected BaSyxStorageAPI getSecondStorageAPI() { + // Please use the MongoDBBaSyxStorageAPIFactory in production code. + MongoClient client = MongoClients.create(connectionString); + return new MongoDBBaSyxStorageAPI(testSubmodelCollectioName, Submodel.class, config, client); + } + + @Override + public void createCollectionIfNotExists() { + // Not Implemented for MongoDBBaSyxStorageAPI as Collections are created + // dynamically. + } + + @Override + public void deleteCollection() { + triggerCollectionCreation(); + MongoOperations mongoOps = (MongoOperations) storageAPI.getStorageConnection(); + assertTrue(mongoOps.collectionExists(testSubmodelCollectioName)); + + this.storageAPI.deleteCollection(); + assertFalse(mongoOps.collectionExists(testSubmodelCollectioName)); + } + + private void triggerCollectionCreation() { + this.storageAPI.createOrUpdate(testSubmodel); + } +} diff --git a/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/components/internal/mongodb/TestMongoDBBaSyxStorageAPIFactory.java b/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/components/internal/mongodb/TestMongoDBBaSyxStorageAPIFactory.java new file mode 100644 index 00000000..099e6cc1 --- /dev/null +++ b/basyx.components/basyx.components.lib/src/test/java/org/eclipse/basyx/regression/components/internal/mongodb/TestMongoDBBaSyxStorageAPIFactory.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (C) 2023 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.basyx.regression.components.internal.mongodb; + +import static org.junit.Assert.assertSame; + +import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; +import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; +import org.eclipse.basyx.testsuite.regression.extensions.storage.VABTestType; +import org.junit.Test; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; + +public class TestMongoDBBaSyxStorageAPIFactory { + static BaSyxMongoDBConfiguration config = createTestConfig("mongodb://localhost:27017"); + static MongoClient client = MongoClients.create(config.getConnectionUrl()); + + private static BaSyxMongoDBConfiguration createTestConfig(String connectionUrl) { + BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration(); + config.setConnectionUrl(connectionUrl); + return config; + } + + @Test + public void assureFactoryReusesMongoClient() throws NoSuchFieldException, SecurityException { + MongoDBBaSyxStorageAPI storageAPI0 = new MongoDBBaSyxStorageAPIFactory(config, VABTestType.class, "c0", client).create(); + MongoDBBaSyxStorageAPI storageAPI1 = new MongoDBBaSyxStorageAPIFactory(config, VABTestType.class, "c1", client).create(); + MongoDBBaSyxStorageAPI storageAPI2 = new MongoDBBaSyxStorageAPIFactory(config, VABTestType.class, "c2").create(); + MongoDBBaSyxStorageAPI storageAPI3 = MongoDBBaSyxStorageAPIFactory.create("c3", VABTestType.class, config, client); + MongoDBBaSyxStorageAPI storageAPI4 = MongoDBBaSyxStorageAPIFactory.create("c4", VABTestType.class, config); + + assertSame(storageAPI0.getClient(), storageAPI1.getClient()); + assertSame(storageAPI0.getClient(), storageAPI2.getClient()); + assertSame(storageAPI0.getClient(), storageAPI3.getClient()); + assertSame(storageAPI0.getClient(), storageAPI4.getClient()); + } + + @Test + public void dynamicCreatedFirst() { + MongoDBBaSyxStorageAPI storageAPI0 = new MongoDBBaSyxStorageAPIFactory(config, VABTestType.class, "c0").create(); + MongoDBBaSyxStorageAPI storageAPI1 = new MongoDBBaSyxStorageAPIFactory(config, VABTestType.class, "c1", client).create(); + + assertSame(storageAPI0.getClient(), storageAPI1.getClient()); + } + +} From 119d933594407df01ab7328c70aef959a26e64cd Mon Sep 17 00:00:00 2001 From: Christian Frank <111001119+chf73@users.noreply.github.com> Date: Tue, 11 Jul 2023 18:01:57 +0200 Subject: [PATCH 43/63] Mongodb file download fix (#333) --- README.md | 3 ++ .../mongodb/TestMongoDBSubmodelAPI.java | 3 +- .../mongodb/MongoDBBaSyxStorageAPI.java | 15 ++++++--- .../internal/mongodb/MongoDBFileHelper.java | 33 ++++++++++++++++--- 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9a501fae..f080f2b5 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ [![Components Lib javadoc](https://javadoc.io/badge2/org.eclipse.basyx/basyx.components.lib/javadoc.svg)](https://javadoc.io/doc/org.eclipse.basyx/basyx.components.lib) Components Lib +This repository contains BaSyx Java V1. If you're looking for BaSyx Java V2, see [here](https://github.com/eclipse-basyx/basyx-java-server-sdk). + + The Eclipse BaSyx Java Components are part of the [Eclipse BaSyx middleware](https://www.eclipse.org/basyx/). The Components utilize the [BaSyx Java SDK](https://github.com/eclipse-basyx/basyx-java-sdk) to provide easy to use off-the-shelf components and have been created within the [BaSys](https://www.basys40.de/) project. ## Eclipse Wiki diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java index a05dbee2..3068c067 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBSubmodelAPI.java @@ -33,6 +33,7 @@ import java.io.OutputStream; import java.util.Collection; import java.util.Map; +import java.util.Objects; import org.eclipse.basyx.aas.metamodel.map.descriptor.CustomId; import org.eclipse.basyx.components.aas.mongodb.MongoDBSubmodelAPI; @@ -91,7 +92,7 @@ public void fileSubmodelElementFileUpload() throws FileNotFoundException { java.io.File value = submodelAPI.getSubmodelElementFile("fileSmeIdShort"); - assertEquals("mySubmodelId-fileSmeIdShort.xml", value.getName()); + assertEquals("#"+ Objects.hashCode(submodelAPI.getSubmodelId())+"#mySubmodelId-fileSmeIdShort.xml", value.getName()); assertEquals(expected.length(), value.length()); } diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java index 39f7484a..393faf7c 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java @@ -30,6 +30,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.Map; @@ -172,11 +173,17 @@ public java.io.File getFile(String idShortPath, String parentKey, Map) element); GridFSBucket bucket = getGridFSBucket(client, config); String fileName = constructFileName(submodelId, file, idShortPath); - deleteAllDuplicateFiles(bucket, fileName); + deleteAllDuplicateFiles(bucket, fileName, legacyFileName(submodelId, file, idShortPath)); bucket.uploadFromStream(fileName, newValue); return fileName; } @@ -69,7 +72,11 @@ public static void deleteAllFilesFromGridFsIfIsFileSubmodelElement(MongoClient c return; File file = File.createAsFacade(submodelElement); GridFSBucket bucket = MongoDBFileHelper.getGridFSBucket(client, config); - bucket.find(Filters.eq("filename", file.getValue())).forEach(gridFile -> bucket.delete(gridFile.getObjectId())); + deleteAllDuplicateFiles(bucket, constructFileName(sm.getIdentification().getId(), file, idShort), legacyFileName(sm.getIdentification().getId(), file, idShort)); + } + + protected static boolean fileExists(GridFSBucket bucket, String fileName) { + return bucket.find(Filters.eq("filename", fileName)).first() != null; } public static GridFSBucket getGridFSBucket(MongoClient client, BaSyxMongoDBConfiguration config) { @@ -77,14 +84,32 @@ public static GridFSBucket getGridFSBucket(MongoClient client, BaSyxMongoDBConfi return GridFSBuckets.create(database, config.getFileCollection()); } - private static void deleteAllDuplicateFiles(GridFSBucket bucket, String fileName) { - bucket.find(Filters.eq("filename", fileName)).forEach(gridFile -> bucket.delete(gridFile.getObjectId())); + private static void deleteAllDuplicateFiles(GridFSBucket bucket, String... fileNames) { + bucket.find(Filters.or( + Arrays.stream(fileNames) + .map(fileName -> Filters.eq("filename", fileName)) + .collect(Collectors.toList()))) + .forEach(gridFile -> bucket.delete(gridFile.getObjectId())); } public static String constructFileName(String submodelId, File file, String idShortPath) { + String fileName = submodelId + "-" + idShortPath.replaceAll("/", "-") + getFileExtension(file); + // replace those chars that are not permitted on filesystems + fileName = fileName.replaceAll("[^a-zA-Z0-9-_\\.]", "_"); + // ensure the filename is still unique to be used as key in MongoDB storage layer + return String.format("#%s#", Objects.hashCode(submodelId)).concat(fileName); + } + /** + * This method is kept for backwards compatibility to still find files from DB which where stored with old scheme. + * @param file the filename of this file is requested. + * @param idShortPath the shortId of the given file. + * @return the filename as it was constructed in older versions. + */ + public static String legacyFileName(String submodelId, File file, String idShortPath) { return submodelId + "-" + idShortPath.replaceAll("/", "-") + getFileExtension(file); } + private static String getFileExtension(File file) { MimeTypes allTypes = MimeTypes.getDefaultMimeTypes(); try { From 628391bb981c2fa93c923f543bd8dc7e2cef0517 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Jul 2023 01:37:48 +0000 Subject: [PATCH 44/63] Bump mongodb-driver-sync from 4.10.1 to 4.10.2 in /basyx.components Bumps [mongodb-driver-sync](https://github.com/mongodb/mongo-java-driver) from 4.10.1 to 4.10.2. - [Release notes](https://github.com/mongodb/mongo-java-driver/releases) - [Commits](https://github.com/mongodb/mongo-java-driver/compare/r4.10.1...r4.10.2) --- updated-dependencies: - dependency-name: org.mongodb:mongodb-driver-sync dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- basyx.components/basyx.components.lib/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 5085e14e..10c658c4 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -80,7 +80,7 @@ org.mongodb mongodb-driver-sync - 4.10.1 + 4.10.2 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 2bba28b7..23c87f15 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -77,7 +77,7 @@ org.mongodb mongodb-driver-sync - 4.10.1 + 4.10.2 diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 85fa61f4..fec71bdb 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -84,7 +84,7 @@ org.mongodb mongodb-driver-sync - 4.10.1 + 4.10.2 From d2ca2056ab31db6317b383cbfef19cb001bb0f6f Mon Sep 17 00:00:00 2001 From: Daespen Date: Wed, 12 Jul 2023 16:01:25 +0200 Subject: [PATCH 45/63] Fixes file collisions for multiple aasx source files (#362) Signed-off-by: Daniel Espen --- .../components/aas/AASServerComponent.java | 92 ++++++++++++------ .../src/main/resources/aasx/a.aasx | Bin 0 -> 2813 bytes .../src/main/resources/aasx/b.aasx | Bin 0 -> 2814 bytes .../basyx/regression/AASServer/AASXSuite.java | 63 ++++++++---- .../AASServer/TestAASXAASServer.java | 11 ++- 5 files changed, 117 insertions(+), 49 deletions(-) create mode 100644 basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aasx/a.aasx create mode 100644 basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aasx/b.aasx diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java index 157aa60e..7c8d78c4 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/AASServerComponent.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -125,19 +124,17 @@ public class AASServerComponent implements IComponent { private BaSyxMongoDBConfiguration mongoDBConfig; private BaSyxSecurityConfiguration securityConfig; - private List aasServerFeatureList = new ArrayList(); - - // Initial AASBundle - protected Collection aasBundles; + private List aasServerFeatureList = new ArrayList<>(); + protected List> aasBundles = new ArrayList<>(); private IAASAggregator aggregator; // Watcher for AAS Aggregator functionality private boolean isAASXUploadEnabled = false; private static final String PREFIX_SUBMODEL_PATH = "/aas/submodels/"; - private static final String AASX_RES_FILE_CONTEXT_PATH = "/basyx-temp"; - private static final String AASX_RES_FILE_DOCBASE_PATH = System.getProperty("java.io.tmpdir") + AASX_RES_FILE_CONTEXT_PATH; - private static final String AASX_RES_FILE_SERVLET_MAPPING_PATTERN = "/files/*"; + private static final String AASX_RES_FILE_CONTEXT_PATH = AASXToMetamodelConverter.TEMP_DIRECTORY; + private static final String AASX_RES_FILE_DOCBASE_PATH = VABPathTools.append(System.getProperty("java.io.tmpdir"), AASX_RES_FILE_CONTEXT_PATH); + private static final String AASX_RES_FILE_SERVLET_MAPPING_PATTERN = "/*"; /** * Constructs an empty AAS server using the passed context @@ -217,7 +214,8 @@ public void setRegistry(IAASRegistry registry) { * The bundles that will be loaded during startup */ public void setAASBundles(Collection aasBundles) { - this.aasBundles = aasBundles; + this.aasBundles = new ArrayList<>(); + this.aasBundles.add(aasBundles); } /** @@ -227,7 +225,9 @@ public void setAASBundles(Collection aasBundles) { * The bundle that will be loaded during startup */ public void setAASBundle(AASBundle aasBundle) { - this.aasBundles = Collections.singleton(aasBundle); + this.aasBundles = new ArrayList<>(); + Collection firstBundleSet = Collections.singleton(aasBundle); + this.aasBundles.add(firstBundleSet); } /** @@ -263,7 +263,7 @@ public void startComponent() { addAasxFilesResourceServlet(context); // 2. Fix the file paths according to the servlet configuration - modifyFilePaths(contextConfig.getHostname(), contextConfig.getPort(), contextConfig.getContextPath() + AASX_RES_FILE_CONTEXT_PATH); + modifyFilePaths(contextConfig.getHostname(), contextConfig.getPort(), getRootFilePathWithContext(contextConfig.getContextPath())); registerWhitelistedSubmodels(); } @@ -275,6 +275,10 @@ public void startComponent() { registerPreexistingAASAndSMIfPossible(); } + private String getRootFilePathWithContext(String contextPath) { + return VABPathTools.append(contextPath, AASX_RES_FILE_CONTEXT_PATH); + } + private DefaultServlet createDefaultServlet() { if (aasConfig.isAuthorizationEnabled()) { final AuthorizedDefaultServletParams params = getAuthorizedDefaultServletParams(); @@ -551,13 +555,13 @@ private Set loadBundleFromJSON(String jsonPath) throws IOException { return new JSONAASBundleFactory(jsonContent).create(); } - private static Set loadBundleFromAASX(String aasxPath) throws IOException, ParserConfigurationException, SAXException, InvalidFormatException, URISyntaxException { + private static Set loadBundleFromAASX(String aasxPath, String childFilePath) throws IOException, ParserConfigurationException, SAXException, InvalidFormatException, URISyntaxException { logger.info("Loading aas from aasx \"" + aasxPath + "\""); // Instantiate the aasx package manager try (AASXToMetamodelConverter packageManager = new AASXToMetamodelConverter(aasxPath)) { // Unpack the files referenced by the aas - packageManager.unzipRelatedFiles(); + packageManager.unzipRelatedFilesToChildPath(childFilePath); // Retrieve the aas from the package return packageManager.retrieveAASBundles(); @@ -571,13 +575,21 @@ private void addAASServerFeaturesToContext(BaSyxContext context) { } } + private Collection getFlatAASBundles() { + Collection result = new ArrayList(); + for (Collection bundle : this.aasBundles) { + result.addAll(bundle); + } + return result; + } + private VABHTTPInterface createAggregatorServlet() { aggregator = createAASAggregator(); loadAASBundles(); if (aasBundles != null) { try (final var ignored = ElevatedCodeAuthentication.enterElevatedCodeAuthenticationArea()) { - AASBundleHelper.integrate(aggregator, aasBundles); + AASBundleHelper.integrate(aggregator, getFlatAASBundles()); } } @@ -623,7 +635,7 @@ private List createAASServerDecoratorList() { } private void loadAASBundles() { - if (aasBundles != null) { + if (!aasBundles.isEmpty()) { return; } @@ -631,22 +643,31 @@ private void loadAASBundles() { aasBundles = loadAASFromSource(aasSources); } - private Set loadAASFromSource(List aasSources) { + private List> loadAASFromSource(List aasSources) { if (aasSources.isEmpty()) { - return Collections.emptySet(); + return new ArrayList<>(); } - Set aasBundlesSet = new HashSet<>(); + List> aasBundlesSet = new ArrayList<>(); - aasSources.stream().map(this::loadBundleFromFile).forEach(aasBundlesSet::addAll); + for (int i = 0; i < aasSources.size(); i++) { + String aasSource = aasSources.get(i); + String subFilePath = getAASXFileSubPath(i); + Set loadedBundles = loadBundleFromFile(aasSource, subFilePath); + aasBundlesSet.add(loadedBundles); + } return aasBundlesSet; } - private Set loadBundleFromFile(String aasSource) { + private String getAASXFileSubPath(int aasxIndex) { + return "aasx" + Integer.toString(aasxIndex); + } + + private Set loadBundleFromFile(String aasSource, String childFilePath) { try { if (aasSource.endsWith(".aasx")) { - return loadBundleFromAASX(aasSource); + return loadBundleFromAASX(aasSource, childFilePath); } else if (aasSource.endsWith(".json")) { return loadBundleFromJSON(aasSource); } else if (aasSource.endsWith(".xml")) { @@ -739,7 +760,8 @@ private String getSMEndpoint(IIdentifier smId) { } private String getSMIdShortFromSMId(IIdentifier smId) { - for (AASBundle bundle : aasBundles) { + Collection flatAasBundles = getFlatAASBundles(); + for (AASBundle bundle : flatAasBundles) { for (ISubmodel sm : bundle.getSubmodels()) { if (smId.getId().equals(sm.getIdentification().getId())) { return sm.getIdShort(); @@ -750,7 +772,8 @@ private String getSMIdShortFromSMId(IIdentifier smId) { } private String getAASIdFromSMId(IIdentifier smId) { - for (AASBundle bundle : aasBundles) { + Collection flatAasBundles = getFlatAASBundles(); + for (AASBundle bundle : flatAasBundles) { for (ISubmodel sm : bundle.getSubmodels()) { if (smId.getId().equals(sm.getIdentification().getId())) { return bundle.getAAS().getIdentification().getId(); @@ -765,11 +788,18 @@ private String getAASIdFromSMId(IIdentifier smId) { * configuration */ private void modifyFilePaths(String hostName, int port, String rootPath) { - rootPath = rootPath + "/files"; - for (AASBundle bundle : aasBundles) { + for (int i = 0; i < aasBundles.size(); i++) { + Collection bundleSet = aasBundles.get(i); + String bundleFileRootPath = VABPathTools.concatenatePaths(rootPath, getAASXFileSubPath(i), "files"); + modifyFilePathsInBundleSet(bundleSet, hostName, port, bundleFileRootPath); + } + } + + private void modifyFilePathsInBundleSet(Collection bundleSet, String hostName, int port, String bundleFileRootPath) { + for (AASBundle bundle : bundleSet) { Set submodels = bundle.getSubmodels(); for (ISubmodel sm : submodels) { - SubmodelFileEndpointLoader.setRelativeFileEndpoints(sm, hostName, port, rootPath); + SubmodelFileEndpointLoader.setRelativeFileEndpoints(sm, hostName, port, bundleFileRootPath); } } } @@ -778,7 +808,11 @@ private String getMqttAASClientId() { if (aasBundles == null || aasBundles.isEmpty()) { return "defaultNoShellId"; } - return aasBundles.stream().findFirst().get().getAAS().getIdShort(); + Collection firstBundleSet = aasBundles.get(0); + if (firstBundleSet == null || firstBundleSet.isEmpty()) { + return "defaultNoShellId"; + } + return firstBundleSet.stream().findFirst().get().getAAS().getIdShort(); } private String getMqttSubmodelClientId() { @@ -788,8 +822,7 @@ private String getMqttSubmodelClientId() { private void addAasxFilesResourceServlet(BaSyxContext context) { HttpServlet httpServlet = createDefaultServlet(); - String childContextPath = contextConfig.getContextPath() + AASX_RES_FILE_CONTEXT_PATH; - + String childContextPath = VABPathTools.append(contextConfig.getContextPath(), AASX_RES_FILE_CONTEXT_PATH); Context childContext = createChildContextForAasxResourceFiles(childContextPath, AASX_RES_FILE_DOCBASE_PATH); context.addChildContext(new BaSyxChildContext(childContext, httpServlet, AASX_RES_FILE_SERVLET_MAPPING_PATTERN)); @@ -800,7 +833,6 @@ private Context createChildContextForAasxResourceFiles(String childContextPath, childContext.setPath(childContextPath); childContext.setDocBase(childDocbasePath); childContext.addLifecycleListener(new Tomcat.FixContextListener()); - return childContext; } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aasx/a.aasx b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aasx/a.aasx new file mode 100644 index 0000000000000000000000000000000000000000..a22b8a14f22d19905e3932ac63ee75770555b59e GIT binary patch literal 2813 zcmWIWW@Zs#U}E54Se1J%Ov)o+h8P0_g9s1{Fvu_@CKgxdg9zRHqRjNnJcUIP3>phS zvY6oW8EwzA+9%JP_dauSWr)XFU5%Ajm>B|q=5v7+gUokaeo=;>k%0k(xq;@#7p3MD z>+69?d`7?Dz2C;ZA~#2&EVZaOGe6H($xzQgNg*{aIX@*cFWpwDv?NW}Ldo9FCMY#0 zu>`21I3u&5SOKUduh>>8qokz3N?*S?IU_YUu~;v^ATh*bDY=<>y2Tl(IXQZn`QX4pH32#NloUb| zi_%j|Y?UAik%Cr9!865HDab6{79H`m5EB?{m zpqq0hTz>iFLd2&OrfRj8!@-L#8|PaUclyV~Ocyy|t-5^WdVA1tTz%3bbQRn&QU>n@(whsQJ(+~jYw-?aDfb)I~P zT`h5~s?*e23_h)FM;)K4UhQ>s=G@7&%Fwjy`0UzQs~!H!>3LXRYToGbQFeWaqfK4i z=^H}#ZlF+I(r&e=pmZeGo19* z&skB#pk(d)HPR+~mdulX5E7m~$LADFubIGUL3gQRQx46Ya;48gTF7p}>FM{5-&|sI z%#rP~-E79Ey+PHI|E&^Ur%d18u>V+UWXsF6*A~4NzK5zZd1AM>l^)eh;C_?zsKN6v z|5bs+tZO@#itK0hU)@%`PkYwizY8mW@GEcfc~akCTPAhRYoS(mY;|_u@t~=;29e=K zm%ab8qK4JuSveByz_4NkVqsWVrDf)%7VDR!R+Q+KRFvS$%-%jaVIC~tQX5e#EX@pK z*bg*M02u!9Ff)lLJ@g@QM1)FMIYTfGL;Jn+nhgZnfN>}{d*7uMhf?O|PT}_Xz!27x zTdCGKZ*8~S%5aU)rK@!QUswMdFF*fm;>@O9!HM%1wX(-HFS?=n{BgoVwc4%i&bQ}i zELg)USDUugPbpf$_0w#_JG~}~ucv6P^PGRGWz#9689jGJ*^T;3_ZmO7XWr&hT6g}7 z`<&;Ii)YuYsaPVg#h-2Bblr!?SN)h)%ussFXhOt~wO{Q7q!+qw(P4V^LTAp0mzUng z>Fe)!|2qBowb{#Z&pZqN&5IgWobr7Fw}Ii>0Ss4ATtz$Q=ar=9mBfQ8nc`SN1#j&H zM^JipU7u9hJ&7|mghTZu)2>#%9S2U#R1xdTy?ObRZM3*dr}l##IS!%b(~kZBTY0G_ ze&4Ows2+>Jj$1eV?5_2Sq)e6GGS{l|$;PTlyZ8OIsP0l)Y*tp3_U$}F;Mpw+Yv!uY zo_w*D)v`a4ssEL*dXw+v97oI3DLWsPw!gU@F7+`Z;!W_seOb&iHIAMZjftJ>^1e6h zgk}3=*?*C%;+^NtZtdLs?V}=d&;ei9&VLd!gbvSTQ{Q*>1KU>Jx!-HHEnpX7=lRp- zt;S%u>{E!|i%iz{xeZ0v|FH*nGcxG{TOrunCBPs<0iZ$vxt4|K#?|UT)|vq1Ahkh| zt;MWbku`1sMj6;zA`&+#6)mz0FpEB97ffS;x&V7Yh;9&SxqxiYAz)Df_6lk#fo=e5 xA%JXv7#j&;L0*x7?ikdZgY1|*VBv=)9|d@`0$s_#zz&3gz{b)vU}K4a0RUJh>YM-o literal 0 HcmV?d00001 diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aasx/b.aasx b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/resources/aasx/b.aasx new file mode 100644 index 0000000000000000000000000000000000000000..2cb692bd51475cbad0ac4592b5bdac3b3e5c4512 GIT binary patch literal 2814 zcmWIWW@Zs#U}E54Se1J%Ov)o+h8P0_g9s1{Fvu_@CKgxdg9zRHqRjNnJcUIP3>phS zvY6oW8EwzA+9%JP_dauSWr)XFU5%Ajm>B|q=5v7+gUokaeo=;>k%0k(xq;@#7p3MD z>+69?d`7?Dz2C;ZA~#2&EVZaOGe6H($xzQgNg*{aIX@*cFWpwDv?NW}Ldo9FCMY#0 zu>`21I3u&5SOKUduh>>8qokz3N?*S?IU_YUu~;v^ATh*bDY=<>y2Tl(IXQZn`QX4pH32#NloUb| zi_%j|Y?UAik%Cr9!865HDab6C+h0zni@KqxmY;5>JyXy!Se{Mp?5V?d7R&GS~NU+to)U@o@iizO-1CQB&udKfiXh zzRNy`7bRAf77tD49++qF>;lipFK1?-i+Q4aJ%0_&*PNf)1d zwN=;t{g6TFahbrpnWi&+_EkK5Qz%z=_3ZB2Gm@eY#W!Uy_Wjel$65WGbyjCrORnM1 zxSZ7Y2FyRd&6*?oplU@+S@j~v%T^{c;?Fi7o|ev;XvA2XHusK(t}~=o>=R&jPr?mU|GlYlQS%%Id8K|9Mb-9o;ht2o8~Uj zSjBk~4=25fTx|ODq3x>HI=nVbv|cr7N;u|G7|R8|Yj7b$*fwciZ-!VsmHN_Zj^{9o(~4 zH?N(Vb0+++vfv*kL>dQ`8zpIdE3X4fkpN)1Aq`98kir8g3lS_wdMEh$9X1efTc33H zo_*t%tiU;1LOM65#U1cc>vT&->KRe*gI|aPGR#N8$`8 zef4uz6fr1S`+kkI$(|+i@#nNjga9Yq^>e!S+bEjPCvyc|DTX1^%z2i5R z*c@|YyKFa`@o8^Rwd8-Rgx4w4w>RuRmKxdeGVQfRuZ8cSs!X2P?QNw;H50hsBt2^I zJj{PpATjIOj-?{|nf+I{74OrY_4n_>${+m7n|z+sH`ta*o%33#)g4=%-FG}_s;xm} zc+q9=zpSWX#VOw>a2ps_9l)>>28LC%bADb)YF!RMF;hjXFZbrWG!=O|wUHedPOLx-3MWuP(of6GNiEhdNv$Z+E2${KSL}KF=!AJN zf$KL&Sqw6BQpm20`+(*N0K+~WW+oBktUe?y6QL4TA`?vOq5YnIN5JuT)vm0=$ymd0 z{mpH^n3nFC6k)OL=_<8{IXV_X;R+m_6Q9nX_hrAG-R{rZSiZWo)^>@#E8*>WG+|Ev z8J&F_7fxQsP&xlf`0u@JE-vC~eb$ix*YUB2@5 z values = marking_rcm.getValue(); @@ -139,6 +160,24 @@ public void testGetSingleModule() throws Exception { } } } + + @Test + public void testCollidingFiles() throws Exception { + final String FILE_ENDING_A = "basyx-temp/aasx1/files/aasx/files/text.txt"; + final String FILE_ENDING_B = "basyx-temp/aasx2/files/aasx/files/text.txt"; + + checkFile(rootEndpoint + FILE_ENDING_A); + checkFile(rootEndpoint + FILE_ENDING_B); + + ISubmodel smA = manager.retrieveSubmodel(aasAId, smAId); + ISubmodel smB = manager.retrieveSubmodel(aasBId, smBId); + + String fileAValue = (String) smA.getSubmodelElement("file").getValue(); + String fileBValue = (String) smB.getSubmodelElement("file").getValue(); + + assertTrue(fileAValue.endsWith(FILE_ENDING_A)); + assertTrue(fileBValue.endsWith(FILE_ENDING_B)); + } @Test public void testAllFiles() throws Exception { @@ -187,14 +226,4 @@ private void checkFile(String absolutePath) { private ConnectedAssetAdministrationShell getConnectedAssetAdministrationShell() throws Exception { return manager.retrieveAAS(aasId); } - - /** - * Gets the connected Submodel - * - * @return connected SM - * @throws Exception - */ - private ISubmodel getConnectedSubmodel() { - return manager.retrieveSubmodel(aasId, smId); - } } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestAASXAASServer.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestAASXAASServer.java index b8baca8d..cd8e3473 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestAASXAASServer.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/TestAASXAASServer.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.net.URISyntaxException; +import java.net.URLEncoder; import java.nio.file.Paths; import javax.servlet.ServletException; @@ -59,7 +60,7 @@ public static void setUpClass() throws ParserConfigurationException, SAXExceptio // Setup component's test configuration BaSyxContextConfiguration contextConfig = new BaSyxContextConfiguration(); contextConfig.loadFromResource(BaSyxContextConfiguration.DEFAULT_CONFIG_PATH); - BaSyxAASServerConfiguration aasConfig = new BaSyxAASServerConfiguration(AASServerBackend.INMEMORY, "aasx/01_Festo.aasx"); + BaSyxAASServerConfiguration aasConfig = new BaSyxAASServerConfiguration(AASServerBackend.INMEMORY, "[\"aasx/01_Festo.aasx\", \"aasx/a.aasx\", \"aasx/b.aasx\"]"); String docBasepath = Paths.get(FileUtils.getTempDirectory().getAbsolutePath(), AASXToMetamodelConverter.TEMP_DIRECTORY).toAbsolutePath().toString(); contextConfig.setDocBasePath(docBasepath); @@ -70,7 +71,13 @@ public static void setUpClass() throws ParserConfigurationException, SAXExceptio rootEndpoint = contextConfig.getUrl() + "/"; aasEndpoint = rootEndpoint + "/" + AASAggregatorProvider.PREFIX + "/" + aasId.getEncodedURN() + "/aas"; - smEndpoint = aasEndpoint + "/submodels/" + smShortId + "/submodel"; + smEndpoint = aasEndpoint + "/submodels/" + smIdShort + "/submodel"; + String encodedAasAId = URLEncoder.encode(aasAId.getId(), "UTF-8"); + aasAEndpoint = rootEndpoint + "/" + AASAggregatorProvider.PREFIX + "/" + encodedAasAId + "/aas"; + smAEndpoint = aasAEndpoint + "/submodels/" + smAIdShort + "/submodel"; + String encodedAasBId = URLEncoder.encode(aasBId.getId(), "UTF-8"); + aasBEndpoint = rootEndpoint + "/" + AASAggregatorProvider.PREFIX + "/" + encodedAasBId + "/aas"; + smBEndpoint = aasBEndpoint + "/submodels/" + smBIdShort + "/submodel"; logger.info("AAS URL for servlet test: " + aasEndpoint); } From 4cb477728e8f4679eeaf32e885b53ca1bd624dff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 01:56:49 +0000 Subject: [PATCH 46/63] Bump spring-data-mongodb from 3.4.13 to 3.4.14 in /basyx.components Bumps [spring-data-mongodb](https://github.com/spring-projects/spring-data-mongodb) from 3.4.13 to 3.4.14. - [Release notes](https://github.com/spring-projects/spring-data-mongodb/releases) - [Commits](https://github.com/spring-projects/spring-data-mongodb/compare/3.4.13...3.4.14) --- updated-dependencies: - dependency-name: org.springframework.data:spring-data-mongodb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- basyx.components/basyx.components.lib/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 10c658c4..f0faf1f9 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -87,7 +87,7 @@ org.springframework.data spring-data-mongodb - 3.4.13 + 3.4.14 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 23c87f15..bc0fa74d 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -84,7 +84,7 @@ org.springframework.data spring-data-mongodb - 3.4.13 + 3.4.14 diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index fec71bdb..2bf84e10 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -91,7 +91,7 @@ org.springframework.data spring-data-mongodb - 3.4.13 + 3.4.14 From ac1be78cacdb9a910871a31403fcf67ef27aeb71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Jul 2023 01:47:41 +0000 Subject: [PATCH 47/63] Bump org.codehaus.mojo:properties-maven-plugin in /basyx.components Bumps [org.codehaus.mojo:properties-maven-plugin](https://github.com/mojohaus/properties-maven-plugin) from 1.1.0 to 1.2.0. - [Release notes](https://github.com/mojohaus/properties-maven-plugin/releases) - [Commits](https://github.com/mojohaus/properties-maven-plugin/compare/properties-maven-plugin-1.1.0...1.2.0) --- updated-dependencies: - dependency-name: org.codehaus.mojo:properties-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.docker/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index 6743b442..5606df0d 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -28,7 +28,7 @@ org.codehaus.mojo properties-maven-plugin - 1.1.0 + 1.2.0 initialize From d6d4b8fc0152d5cacd78c8cc8a4f95300bbef66f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 01:40:18 +0000 Subject: [PATCH 48/63] Bump io.fabric8:docker-maven-plugin in /basyx.components Bumps [io.fabric8:docker-maven-plugin](https://github.com/fabric8io/docker-maven-plugin) from 0.43.0 to 0.43.2. - [Release notes](https://github.com/fabric8io/docker-maven-plugin/releases) - [Changelog](https://github.com/fabric8io/docker-maven-plugin/blob/master/doc/changelog.md) - [Commits](https://github.com/fabric8io/docker-maven-plugin/compare/v0.43.0...v0.43.2) --- updated-dependencies: - dependency-name: io.fabric8:docker-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.docker/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index 5606df0d..c04f73c5 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -95,7 +95,7 @@ io.fabric8 docker-maven-plugin - 0.43.0 + 0.43.2 From 70a4bb6c3a4282269cb3bf06c3ce182ab12ec229 Mon Sep 17 00:00:00 2001 From: Jannik Fried Date: Thu, 10 Aug 2023 08:33:43 +0200 Subject: [PATCH 49/63] Simplifies StorageSubmodelAPI --- .../aas/internal/StorageSubmodelAPI.java | 188 ++---------------- 1 file changed, 19 insertions(+), 169 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java index 80ef3d5d..0df5f9f8 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/internal/StorageSubmodelAPI.java @@ -32,26 +32,17 @@ import java.util.Map; import org.eclipse.basyx.extensions.internal.storage.BaSyxStorageAPI; -import org.eclipse.basyx.submodel.metamodel.api.ISubmodel; import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement; -import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElementCollection; import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation; -import org.eclipse.basyx.submodel.metamodel.facade.SubmodelElementMapCollectionConverter; import org.eclipse.basyx.submodel.metamodel.facade.submodelelement.SubmodelElementFacadeFactory; import org.eclipse.basyx.submodel.metamodel.map.Submodel; -import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElement; -import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection; -import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation; -import org.eclipse.basyx.submodel.restapi.SubmodelElementProvider; import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI; import org.eclipse.basyx.submodel.restapi.operation.DelegatedInvocationManager; +import org.eclipse.basyx.submodel.restapi.vab.VABSubmodelAPI; import org.eclipse.basyx.vab.exception.provider.MalformedRequestException; -import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; import org.eclipse.basyx.vab.modelprovider.VABPathTools; -import org.eclipse.basyx.vab.modelprovider.api.IModelProvider; import org.eclipse.basyx.vab.modelprovider.lambda.VABLambdaProvider; -import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider; /** * Abstract submodel api for storage backends. @@ -98,7 +89,7 @@ public void setSubmodel(Submodel submodel) { } @Override - public ISubmodel getSubmodel() { + public Submodel getSubmodel() { return storageApi.retrieve(identificationId); } @@ -111,115 +102,25 @@ public void addSubmodelElement(ISubmodelElement elem) { @Override public void addSubmodelElement(String idShortPath, ISubmodelElement elem) { - List idShorts = idShortsPathAsList(idShortPath); - addNestedSubmodelElement(idShorts, elem); - } - - private void addNestedSubmodelElement(List idShorts, ISubmodelElement element) { - Submodel submodel = (Submodel) getSubmodel(); - if (idShorts.size() > 1) { - idShorts = removeLastElement(idShorts); - ISubmodelElement parentElement = getNestedSubmodelElement(submodel, idShorts); - if (parentElement instanceof SubmodelElementCollection) { - addToSubmodelElementCollection(element, submodel, parentElement); - } - } else { - submodel.addSubmodelElement(element); - storageApi.update(submodel, identificationId); - } - } - - private List removeLastElement(List list) { - return list.subList(0, list.size() - 1); - } - - private void addToSubmodelElementCollection(ISubmodelElement element, Submodel submodel, ISubmodelElement parentElement) { - ((SubmodelElementCollection) parentElement).addSubmodelElement(element); - submodel.addSubmodelElement(parentElement); - storageApi.update(submodel, identificationId); - } - - private ISubmodelElement getNestedSubmodelElement(Submodel submodel, List idShorts) { - Map elementMap = submodel.getSubmodelElements(); - Map resolvedElementMap = resolveElementPath(idShorts, elementMap); - - String lastIdShort = idShorts.get(idShorts.size() - 1); - if (!resolvedElementMap.containsKey(lastIdShort)) { - throwPathCouldNotBeResolvedException(lastIdShort); - } - - return resolvedElementMap.get(lastIdShort); + VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel())); + api.addSubmodelElement(idShortPath, elem); + storageApi.update(api.getSubmodel(), identificationId); } - private Map resolveElementPath(List idShorts, Map elementMap) { - var elementMapWrapper = new Object() { - Map wrappedElementMap = elementMap; - }; - - String lastIdShort = idShorts.get(idShorts.size() - 1); - idShorts.stream().takeWhile(idShort -> !lastIdShort.equals(idShort)).forEachOrdered(idShort -> { - ISubmodelElement element = elementMapWrapper.wrappedElementMap.get(idShort); - if (element instanceof SubmodelElementCollection) { - elementMapWrapper.wrappedElementMap = ((SubmodelElementCollection) element).getSubmodelElements(); - } else { - throwPathCouldNotBeResolvedException(idShort); - } - }); - return elementMapWrapper.wrappedElementMap; - } - - private void throwPathCouldNotBeResolvedException(String idShort) { - throw new ResourceNotFoundException(idShort + " in the nested submodel element path could not be resolved."); - } @Override public ISubmodelElement getSubmodelElement(String idShortPath) { - List idShorts = idShortsPathAsList(idShortPath); - ISubmodelElement submodelElement = getNestedSubmodelElement(idShorts); - return convertSubmodelElement(submodelElement); - } - - private ISubmodelElement getNestedSubmodelElement(List idShorts) { - Submodel submodel = (Submodel) getSubmodel(); - return getNestedSubmodelElement(submodel, idShorts); - } - - @SuppressWarnings("unchecked") - private ISubmodelElement convertSubmodelElement(ISubmodelElement element) { - Map convertedCollectionMap = SubmodelElementMapCollectionConverter.smElementToMap((Map) element); - return SubmodelElement.createAsFacade(convertedCollectionMap); + VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel())); + return api.getSubmodelElement(idShortPath); } @Override public void deleteSubmodelElement(String idShortPath) { - if (idShortPath.contains("/")) { - List idShorts = idShortsPathAsList(idShortPath); - deleteNestedSubmodelElement(idShorts); - } else { - deleteTopLevelSubmodelElement(idShortPath); - } - + VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel())); + api.deleteSubmodelElement(idShortPath); + storageApi.update(api.getSubmodel(), identificationId); } - private void deleteNestedSubmodelElement(List idShorts) { - if (idShorts.size() == 1) { - deleteSubmodelElement(idShorts.get(0)); - return; - } - Submodel submodel = (Submodel) getSubmodel(); - List parentIdShorts = removeLastElement(idShorts); - ISubmodelElement parentElement = getNestedSubmodelElement(submodel, parentIdShorts); - SubmodelElementCollection elementCollection = (SubmodelElementCollection) parentElement; - elementCollection.deleteSubmodelElement(idShorts.get(idShorts.size() - 1)); - storageApi.update(submodel, identificationId); - } - - private void deleteTopLevelSubmodelElement(String idShort) { - Submodel submodel = (Submodel) getSubmodel(); - storageApi.deleteFile(submodel, idShort); - submodel.getSubmodelElements().remove(idShort); - storageApi.update(submodel, identificationId); - } @Override public Collection getOperations() { @@ -235,56 +136,19 @@ public Collection getSubmodelElements() { @Override public void updateSubmodelElement(String idShortPath, Object newValue) { - List idShorts = idShortsPathAsList(idShortPath); - updateSubmodelElement(idShorts, newValue); + VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel())); + api.updateSubmodelElement(idShortPath, newValue); + storageApi.update(api.getSubmodel(), identificationId); } - @SuppressWarnings("unchecked") - private void updateSubmodelElement(List idShorts, Object newValue) { - Submodel submodel = (Submodel) getSubmodel(); - ISubmodelElement element = getNestedSubmodelElement(submodel, idShorts); - - IModelProvider mapProvider = new VABLambdaProvider((Map) element); - IModelProvider smeProvider = new SubmodelElementProvider(mapProvider); - - smeProvider.setValue(Property.VALUE, newValue); - ISubmodelElement updatedLastLevelElement = SubmodelElementFacadeFactory.createSubmodelElement((Map) smeProvider.getValue("")); - ISubmodelElement updatedNestedElement = createUpdatedNestedSubmodelElement(submodel, updatedLastLevelElement, idShorts); - - submodel.addSubmodelElement(updatedNestedElement); - - storageApi.update(submodel, identificationId); - } @Override public Object getSubmodelElementValue(String idShortPath) { - if (idShortPath.contains("/")) { - List idShorts = idShortsPathAsList(idShortPath); - return getNestedSubmodelElementValue(idShorts); - } else { - return getTopLevelSubmodelElementValue(idShortPath); - } - } - - private Object getTopLevelSubmodelElementValue(String idShort) { - Submodel submodel = (Submodel) getSubmodel(); - return getElementProvider(submodel, idShort).getValue("/value"); - } - - @SuppressWarnings("unchecked") - private IModelProvider getElementProvider(Submodel submodel, String idShortPath) { - ISubmodelElement elem = submodel.getSubmodelElement(idShortPath); - IModelProvider mapProvider = new VABMapProvider((Map) elem); - return new SubmodelElementProvider(mapProvider); - } - - @SuppressWarnings("unchecked") - private Object getNestedSubmodelElementValue(List idShorts) { - ISubmodelElement lastElement = getNestedSubmodelElement(idShorts); - IModelProvider mapProvider = new VABMapProvider((Map) lastElement); - return new SubmodelElementProvider(mapProvider).getValue("/value"); + VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel())); + return api.getSubmodelElementValue(idShortPath); } + @Deprecated @SuppressWarnings("unchecked") protected Object unwrapParameter(Object parameter) { if (parameter instanceof Map) { @@ -329,18 +193,6 @@ public Object getOperationResult(String idShort, String requestId) { throw new MalformedRequestException("Invoke not supported by this backend"); } - private ISubmodelElement createUpdatedNestedSubmodelElement(Submodel sm, ISubmodelElement updatedLastLevelElement, List idShorts) { - ISubmodelElement updatedNestedElement = updatedLastLevelElement; - for (int i = idShorts.size() - 1; i > 0; i--) { - idShorts = idShorts.subList(0, i); - ISubmodelElementCollection nextLevelElementCollection = (ISubmodelElementCollection) getNestedSubmodelElement(sm, idShorts); - nextLevelElementCollection.addSubmodelElement(updatedNestedElement); - updatedNestedElement = nextLevelElementCollection; - } - - return updatedNestedElement; - } - @SuppressWarnings("unchecked") @Override public java.io.File getSubmodelElementFile(String idShortPath) { @@ -351,12 +203,10 @@ public java.io.File getSubmodelElementFile(String idShortPath) { @Override public void uploadSubmodelElementFile(String idShortPath, InputStream fileStream) { - String[] splitted = VABPathTools.splitPath(idShortPath); - List idShorts = Arrays.asList(splitted); - Submodel sm = (Submodel) getSubmodel(); - ISubmodelElement element = getNestedSubmodelElement(sm, idShorts); + VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel())); + ISubmodelElement element = api.getSubmodelElement(idShortPath); String fileName = storageApi.writeFile(idShortPath, getSubmodel().getIdentification().getId(), fileStream, element); - updateSubmodelElement(idShorts, fileName); + updateSubmodelElement(idShortPath, fileName); } } From 9034a3ab37f9e9552762186b0ca347f6258682a0 Mon Sep 17 00:00:00 2001 From: Jannik Fried Date: Tue, 1 Aug 2023 12:03:05 +0200 Subject: [PATCH 50/63] Adapts MongoDB Indexing to support Cosomos DB Signed-off-by: Jannik Fried --- .../components/internal/mongodb/MongoDBBaSyxStorageAPI.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java index 393faf7c..53599743 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java @@ -28,7 +28,6 @@ import static org.springframework.data.mongodb.core.query.Criteria.where; import static org.springframework.data.mongodb.core.query.Query.query; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -44,10 +43,11 @@ import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; +import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.FindAndReplaceOptions; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.index.TextIndexDefinition; +import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.MongoClient; @@ -87,7 +87,7 @@ public MongoDBBaSyxStorageAPI(String collectionName, Class type, BaSyxMongoDB } private void configureIndexKey() { - TextIndexDefinition idIndex = TextIndexDefinition.builder().onField(INDEX_KEY).build(); + Index idIndex = new Index().on(INDEX_KEY, Direction.ASC); this.mongoOps.indexOps(TYPE).ensureIndex(idIndex); } From faf361e5a659847ab46c7111b9117e7b816ffc3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 06:54:47 +0000 Subject: [PATCH 51/63] Bump ch.qos.logback:logback-classic in /basyx.components Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.4.8 to 1.4.11. - [Commits](https://github.com/qos-ch/logback/compare/v_1.4.8...v_1.4.11) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index dd4d90ef..2284d638 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -273,7 +273,7 @@ ch.qos.logback logback-classic - 1.4.8 + 1.4.11 From ae2102a62e4879032498628375deb74201010ab3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Aug 2023 06:55:07 +0000 Subject: [PATCH 52/63] Bump io.moquette:moquette-broker from 0.16 to 0.17 in /basyx.components Bumps [io.moquette:moquette-broker](https://github.com/moquette-io/moquette) from 0.16 to 0.17. - [Release notes](https://github.com/moquette-io/moquette/releases) - [Changelog](https://github.com/moquette-io/moquette/blob/main/ChangeLog.txt) - [Commits](https://github.com/moquette-io/moquette/compare/v0.16...v0.17.0) --- updated-dependencies: - dependency-name: io.moquette:moquette-broker dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index f0faf1f9..6b3b8ff4 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -108,7 +108,7 @@ io.moquette moquette-broker - 0.16 + 0.17 test diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index bc0fa74d..8e6b272c 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -91,7 +91,7 @@ io.moquette moquette-broker - 0.16 + 0.17 test From dcedeb18faaf41b68823f1d92a3826fed926b58a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 01:29:42 +0000 Subject: [PATCH 53/63] Bump org.springframework.data:spring-data-mongodb in /basyx.components Bumps [org.springframework.data:spring-data-mongodb](https://github.com/spring-projects/spring-data-mongodb) from 3.4.14 to 3.4.15. - [Release notes](https://github.com/spring-projects/spring-data-mongodb/releases) - [Commits](https://github.com/spring-projects/spring-data-mongodb/compare/3.4.14...3.4.15) --- updated-dependencies: - dependency-name: org.springframework.data:spring-data-mongodb dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- .../basyx.components.docker/basyx.components.registry/pom.xml | 2 +- basyx.components/basyx.components.lib/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 6b3b8ff4..a8b62df6 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -87,7 +87,7 @@ org.springframework.data spring-data-mongodb - 3.4.14 + 3.4.15 diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 8e6b272c..04cdd50f 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -84,7 +84,7 @@ org.springframework.data spring-data-mongodb - 3.4.14 + 3.4.15 diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 2bf84e10..21de58e1 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -91,7 +91,7 @@ org.springframework.data spring-data-mongodb - 3.4.14 + 3.4.15 From d84a0d9beb275e36a4de9982640c6efeb3bc3f13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 01:29:46 +0000 Subject: [PATCH 54/63] Bump io.fabric8:docker-maven-plugin in /basyx.components Bumps [io.fabric8:docker-maven-plugin](https://github.com/fabric8io/docker-maven-plugin) from 0.43.2 to 0.43.4. - [Release notes](https://github.com/fabric8io/docker-maven-plugin/releases) - [Changelog](https://github.com/fabric8io/docker-maven-plugin/blob/master/doc/changelog.md) - [Commits](https://github.com/fabric8io/docker-maven-plugin/compare/v0.43.2...v0.43.4) --- updated-dependencies: - dependency-name: io.fabric8:docker-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.docker/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index c04f73c5..ac5aa1f2 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -95,7 +95,7 @@ io.fabric8 docker-maven-plugin - 0.43.2 + 0.43.4 From fccd05cd7fd6f3486ea004fbdcf24a3a4331f67d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 01:26:53 +0000 Subject: [PATCH 55/63] Bump com.h2database:h2 from 2.2.220 to 2.2.222 in /basyx.components Bumps [com.h2database:h2](https://github.com/h2database/h2database) from 2.2.220 to 2.2.222. - [Release notes](https://github.com/h2database/h2database/releases) - [Commits](https://github.com/h2database/h2database/compare/version-2.2.220...version-2.2.222) --- updated-dependencies: - dependency-name: com.h2database:h2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.lib/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 21de58e1..48ca21ec 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -109,7 +109,7 @@ com.h2database h2 - 2.2.220 + 2.2.222 From 45311699f01052d4b9e1bac09a7929f81e2eb672 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 01:18:20 +0000 Subject: [PATCH 56/63] Bump com.tngtech.keycloakmock:mock in /basyx.components Bumps [com.tngtech.keycloakmock:mock](https://github.com/TNG/keycloak-mock) from 0.15.1 to 0.15.2. - [Release notes](https://github.com/TNG/keycloak-mock/releases) - [Commits](https://github.com/TNG/keycloak-mock/compare/v0.15.1...v0.15.2) --- updated-dependencies: - dependency-name: com.tngtech.keycloakmock:mock dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../basyx.components.docker/basyx.components.AASServer/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index a8b62df6..9add92a1 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -128,7 +128,7 @@ com.tngtech.keycloakmock mock test - 0.15.1 + 0.15.2 From c8eaf2c2667ef96daacf30de102f6b11d522e669 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 01:25:47 +0000 Subject: [PATCH 57/63] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/maven-publish-snapshot.yml | 2 +- .github/workflows/maven-run-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven-publish-snapshot.yml b/.github/workflows/maven-publish-snapshot.yml index 77e4f548..ded98ec9 100644 --- a/.github/workflows/maven-publish-snapshot.yml +++ b/.github/workflows/maven-publish-snapshot.yml @@ -37,7 +37,7 @@ jobs: packages: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/maven-run-tests.yml b/.github/workflows/maven-run-tests.yml index b297cda0..19f93c8d 100644 --- a/.github/workflows/maven-run-tests.yml +++ b/.github/workflows/maven-run-tests.yml @@ -49,7 +49,7 @@ jobs: - 27017:27017 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 uses: actions/setup-java@v3 with: From 3c82630aaddd7c063c8f24745e3f24465520bac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zai=20M=C3=BCller-Zhang?= <97607180+zhangzai123@users.noreply.github.com> Date: Tue, 12 Sep 2023 06:37:10 +0200 Subject: [PATCH 58/63] Make MongoDB stateless (#372) Co-authored-by: Daniel Espen Co-authored-by: Jannis Jung Signed-off-by: Zai Zhang --- .../aas/mongodb/MongoDBAASAPIFactory.java | 7 +- .../aas/mongodb/MongoDBAASAggregator.java | 114 +++++------------- .../mongodb/MongoDBSubmodelAggregator.java | 100 ++++++++++++++- .../MongoDBSubmodelAggregatorFactory.java | 4 +- .../mongodb/TestMongoDBAggregator.java | 23 ++-- .../AASServer/mongodb/TestMongoDBServer.java | 2 +- 6 files changed, 149 insertions(+), 101 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPIFactory.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPIFactory.java index 8498242b..8f0f70ca 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPIFactory.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAPIFactory.java @@ -30,6 +30,7 @@ import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; +import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier; import com.mongodb.client.MongoClient; @@ -59,10 +60,14 @@ public MongoDBAASAPIFactory(MongoDBBaSyxStorageAPI mon @Override public IAASAPI getAASApi(AssetAdministrationShell shell) { - new MongoDBAASAPI(storageAPI, shell.getIdentification().getId()); MongoDBAASAPI api = new MongoDBAASAPI(storageAPI, shell.getIdentification().getId()); api.setAAS(shell); return api; } + @Override + public IAASAPI create(IIdentifier aasId) { + return new MongoDBAASAPI(storageAPI, aasId.getId()); + } + } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java index 8c158345..623e76f4 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java @@ -25,10 +25,8 @@ package org.eclipse.basyx.components.aas.mongodb; import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.stream.Collectors; import org.eclipse.basyx.aas.aggregator.AASAggregator; @@ -44,7 +42,6 @@ import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; -import org.eclipse.basyx.extensions.shared.authorization.internal.NotAuthorizedException; import org.eclipse.basyx.submodel.aggregator.SubmodelAggregatorFactory; import org.eclipse.basyx.submodel.aggregator.api.ISubmodelAggregator; import org.eclipse.basyx.submodel.aggregator.api.ISubmodelAggregatorFactory; @@ -60,6 +57,8 @@ import org.eclipse.basyx.vab.modelprovider.api.IModelProvider; import org.eclipse.basyx.vab.protocol.api.IConnectorFactory; import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; @@ -69,12 +68,11 @@ * * @see AASAggregator AASAggregator for the "InMemory"-variant * - * @author espen, wege, witt, jugnjan + * @author espen, wege, witt, jugnjan, zhangzai * */ public class MongoDBAASAggregator implements IAASAggregator { - protected Map shellProviderMap = new HashMap<>(); - + private Logger logger = LoggerFactory.getLogger(this.getClass()); private IAASRegistry registry; /** @@ -106,7 +104,6 @@ public MongoDBAASAggregator(IAASRegistry registry, IAASAPIFactory shellAPIFactor this.shellApiFactory = shellAPIFactory; this.submodelAggregatorFactory = submodelAggregatorFactory; this.registry = registry; - init(); } /** @@ -361,16 +358,14 @@ private static IAASAPIFactory initShellApiFactory(BaSyxMongoDBConfiguration conf private static MongoDBBaSyxStorageAPI submodelStorageApiFromConfig(BaSyxMongoDBConfiguration config, MongoClient client) { String submodelCollectionName = config.getSubmodelCollection(); - MongoDBBaSyxStorageAPI submodelStorageApi = client == null - ? MongoDBBaSyxStorageAPIFactory.create(submodelCollectionName, Submodel.class, config) + MongoDBBaSyxStorageAPI submodelStorageApi = client == null ? MongoDBBaSyxStorageAPIFactory.create(submodelCollectionName, Submodel.class, config) : MongoDBBaSyxStorageAPIFactory.create(submodelCollectionName, Submodel.class, config, client); return submodelStorageApi; } private static MongoDBBaSyxStorageAPI shellStorageApiFromConfig(BaSyxMongoDBConfiguration config, MongoClient client) { String shellCollectionName = config.getAASCollection(); - MongoDBBaSyxStorageAPI shellStorageApi = client == null - ? MongoDBBaSyxStorageAPIFactory.create(shellCollectionName, AssetAdministrationShell.class, config) + MongoDBBaSyxStorageAPI shellStorageApi = client == null ? MongoDBBaSyxStorageAPIFactory.create(shellCollectionName, AssetAdministrationShell.class, config) : MongoDBBaSyxStorageAPIFactory.create(shellCollectionName, AssetAdministrationShell.class, config, client); return shellStorageApi; } @@ -406,18 +401,6 @@ public void reset() { Collection submodels = submodelStorageApi.retrieveAll(); shells.forEach(shell -> shellStorageApi.delete(shell.getIdentification().getId())); submodels.forEach(shell -> submodelStorageApi.delete(shell.getIdentification().getId())); - shellProviderMap.clear(); - } - - private void init() { - Collection data = shellStorageApi.retrieveAll(); - data.forEach(shell -> { - String shellIdentificationId = shell.getIdentification().getId(); - IAASAPI shellApi = shellApiFactory.create(shell); - MultiSubmodelProvider provider = createMultiSubmodelProvider(shellApi); - addSubmodelsFromDB(provider, shell); - shellProviderMap.put(shell.getIdentification().getId(), provider); - }); } /** @@ -428,7 +411,7 @@ private MultiSubmodelProvider createMultiSubmodelProvider(IAASAPI shellApi) { AASModelProvider contentProvider = createContentProvider(shellApi); IConnectorFactory connectorFactory = new HTTPConnectorFactory(); - ISubmodelAggregator submodelAggregator = getSubmodelAggregatorInstance(); + ISubmodelAggregator submodelAggregator = getSubmodelAggregatorInstance(shellApi.getAAS().getIdentification()); return new MultiSubmodelProvider(contentProvider, this.registry, connectorFactory, this.shellApiFactory, submodelAggregator); } @@ -437,12 +420,12 @@ private AASModelProvider createContentProvider(IAASAPI shellApi) { return new AASModelProvider(shellApi); } - private ISubmodelAggregator getSubmodelAggregatorInstance() { + private ISubmodelAggregator getSubmodelAggregatorInstance(IIdentifier shellId) { if (submodelAggregatorFactory == null) { return submodelAggregator; } - return submodelAggregatorFactory.create(); + return submodelAggregatorFactory.create(shellId); } /** @@ -455,6 +438,7 @@ private void addSubmodelsFromDB(MultiSubmodelProvider provider, AssetAdministrat submodelIdentificationIds = completeSubmodelIdentificationsIdsByIdShorts(submodelIdentificationIds, submodelIdShorts); createProviderForSubmodels(provider, submodelIdentificationIds); + } private void createProviderForSubmodels(MultiSubmodelProvider provider, List submodelIdentificationIds) { @@ -472,21 +456,15 @@ private List completeSubmodelIdentificationsIdsByIdShorts(List s } private List getSubmodelIdentificationIdsFromSubmodelReferences(Collection submodelRefs) { - List submodelIdentificationIds = submodelRefs.stream() - .map(this::getLastKeyFromReference) - .filter(lastKey -> lastKey.getIdType() != KeyType.IDSHORT) - .map(lastKey -> lastKey.getValue()).collect(Collectors.toList()); + List submodelIdentificationIds = submodelRefs.stream().map(this::getLastKeyFromReference).filter(lastKey -> lastKey.getIdType() != KeyType.IDSHORT).map(lastKey -> lastKey.getValue()).collect(Collectors.toList()); return submodelIdentificationIds; } private List getSubmodelIdShortsFromSubmodelReferences(Collection submodelRefs) { - List submodelIdShorts = submodelRefs.stream() - .map(this::getLastKeyFromReference) - .filter(lastKey -> lastKey.getIdType() == KeyType.IDSHORT) - .map(lastKey -> lastKey.getValue()).collect(Collectors.toList()); + List submodelIdShorts = submodelRefs.stream().map(this::getLastKeyFromReference).filter(lastKey -> lastKey.getIdType() == KeyType.IDSHORT).map(lastKey -> lastKey.getValue()).collect(Collectors.toList()); return submodelIdShorts; } - + private IKey getLastKeyFromReference(IReference reference) { List keys = reference.getKeys(); IKey lastKey = keys.get(keys.size() - 1); @@ -503,27 +481,19 @@ private String getSubmodelIdByIdShort(String idShort) { private void addSubmodelProvidersById(String submodelIdentificationId, MultiSubmodelProvider provider) { ISubmodelAPI submodelApi = new MongoDBSubmodelAPI(this.submodelStorageApi, submodelIdentificationId); - SubmodelProvider submodelProvider = new SubmodelProvider(submodelApi); - provider.addSubmodel(submodelProvider); + try { + SubmodelProvider submodelProvider = new SubmodelProvider(submodelApi); + provider.addSubmodel(submodelProvider); + } catch (ResourceNotFoundException noSubmodelsInDB) { + // ignore + logger.warn("Could not add submodel with identificationId '{}'.", submodelIdentificationId); + } + } - @SuppressWarnings("unchecked") @Override public Collection getAASList() { - return shellProviderMap.values().stream().map(provider -> { - try { - return provider.getValue("/aas"); - } catch (NotAuthorizedException e) { - return null; - } catch (Exception e1) { - e1.printStackTrace(); - throw new RuntimeException(); - } - }).filter(Objects::nonNull).map(shellMap -> { - AssetAdministrationShell shell = new AssetAdministrationShell(); - shell.putAll((Map) shellMap); - return shell; - }).collect(Collectors.toList()); + return shellStorageApi.retrieveAll().stream().map(aas -> (IAssetAdministrationShell) aas).collect(Collectors.toList()); } @SuppressWarnings("unchecked") @@ -537,52 +507,32 @@ public IAssetAdministrationShell getAAS(IIdentifier shellIdentification) { @Override public void createAAS(AssetAdministrationShell shell) { - IAASAPI shellApi = this.shellApiFactory.create(shell); - MultiSubmodelProvider provider = createMultiSubmodelProvider(shellApi); - shellProviderMap.put(shell.getIdentification().getId(), provider); + this.shellApiFactory.create(shell); } @Override public void updateAAS(AssetAdministrationShell shell) { - IIdentifier shellIdentification = shell.getIdentification(); - String shellIdentificationId = shellIdentification.getId(); - - MultiSubmodelProvider oldProvider = (MultiSubmodelProvider) getAASProvider(shellIdentification); - - IAASAPI shellApi = this.shellApiFactory.create(shell); - MultiSubmodelProvider updatedProvider = updateAASProvider(shellApi, oldProvider); - - shellProviderMap.put(shellIdentificationId, updatedProvider); + this.shellApiFactory.create(shell); } - private MultiSubmodelProvider updateAASProvider(IAASAPI shellApi, MultiSubmodelProvider oldProvider) { - AASModelProvider contentProvider = createContentProvider(shellApi); - IConnectorFactory connectorFactory = oldProvider.getConnectorFactory(); - ISubmodelAggregator submodelAggregator = oldProvider.getSmAggregator(); - - return new MultiSubmodelProvider(contentProvider, this.registry, connectorFactory, shellApiFactory, submodelAggregator); - } - - @Override public void deleteAAS(IIdentifier shellIdentifier) { String shellIdentificationId = shellIdentifier.getId(); shellStorageApi.delete(shellIdentificationId); - shellProviderMap.remove(shellIdentificationId); } public MultiSubmodelProvider getProviderForAASId(String shellIdentificationId) { - return shellProviderMap.get(shellIdentificationId); + AssetAdministrationShell shell = shellStorageApi.retrieve(shellIdentificationId); + + IAASAPI shellApi = this.shellApiFactory.create(shell.getIdentification()); + MultiSubmodelProvider provider = createMultiSubmodelProvider(shellApi); + + addSubmodelsFromDB(provider, shell); + return provider; } @Override public IModelProvider getAASProvider(IIdentifier shellIdentificationId) { - MultiSubmodelProvider provider = shellProviderMap.get(shellIdentificationId.getId()); - - if (provider == null) { - throw new ResourceNotFoundException("AAS with Id " + shellIdentificationId.getId() + " does not exist"); - } - - return provider; + return getProviderForAASId(shellIdentificationId.getId()); } } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregator.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregator.java index 3ba1f2ab..d92a5913 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregator.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregator.java @@ -25,14 +25,25 @@ package org.eclipse.basyx.components.aas.mongodb; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.eclipse.basyx.aas.metamodel.map.AssetAdministrationShell; import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration; import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPI; import org.eclipse.basyx.components.internal.mongodb.MongoDBBaSyxStorageAPIFactory; import org.eclipse.basyx.submodel.aggregator.SubmodelAggregator; import org.eclipse.basyx.submodel.metamodel.api.ISubmodel; import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier; +import org.eclipse.basyx.submodel.metamodel.api.reference.IKey; +import org.eclipse.basyx.submodel.metamodel.api.reference.IReference; import org.eclipse.basyx.submodel.metamodel.map.Submodel; +import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI; import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPIFactory; +import org.eclipse.basyx.submodel.restapi.vab.VABSubmodelAPIFactory; +import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; import com.mongodb.client.MongoClient; @@ -44,11 +55,19 @@ */ public class MongoDBSubmodelAggregator extends SubmodelAggregator { private MongoDBBaSyxStorageAPI storageApi; + private MongoDBBaSyxStorageAPI aasStorageApi; + private IIdentifier shellId; public MongoDBSubmodelAggregator(ISubmodelAPIFactory submodelApiFactory, BaSyxMongoDBConfiguration config, MongoClient client) { this(submodelApiFactory, MongoDBBaSyxStorageAPIFactory.create(config.getSubmodelCollection(), Submodel.class, config, client)); } + public MongoDBSubmodelAggregator(ISubmodelAPIFactory submodelApiFactory, BaSyxMongoDBConfiguration config, MongoClient client, IIdentifier shellId) { + this(submodelApiFactory, MongoDBBaSyxStorageAPIFactory.create(config.getSubmodelCollection(), Submodel.class, config, client)); + aasStorageApi = MongoDBBaSyxStorageAPIFactory.create(config.getAASCollection(), AssetAdministrationShell.class, config, client); + this.shellId = shellId; + } + public MongoDBSubmodelAggregator(ISubmodelAPIFactory submodelApiFactory, MongoDBBaSyxStorageAPI storageApi) { super(submodelApiFactory); this.storageApi = storageApi; @@ -59,18 +78,93 @@ public MongoDBSubmodelAggregator(ISubmodelAPIFactory submodelApiFactory, BaSyxMo this(submodelApiFactory, MongoDBBaSyxStorageAPIFactory.create(config.getSubmodelCollection(), Submodel.class, config)); } - @Override public void deleteSubmodelByIdentifier(IIdentifier submodelIdentifier) { - super.deleteSubmodelByIdentifier(submodelIdentifier); storageApi.delete(submodelIdentifier.getId()); } @Override public void deleteSubmodelByIdShort(String idShort) { ISubmodel submodel = getSubmodelbyIdShort(idShort); - super.deleteSubmodelByIdShort(idShort); storageApi.delete(submodel.getIdentification().getId()); } + @Override + public Collection getSubmodelList() { + if (shellId == null) + return returnAllSubmodels(); + + AssetAdministrationShell shell = aasStorageApi.retrieve(shellId.getId()); + Collection submodelRefs = shell.getSubmodelReferences(); + + if (submodelRefs.isEmpty()) { + return findSubmodelsWithGivenParentId(); + } + List submodelIds = submodelRefs.stream().map(ref -> { + return getLastKeyFromReference(ref).getValue(); + }).collect(Collectors.toList()); + + return submodelIds.stream().map(sm -> { + return storageApi.retrieve(sm); + }).collect(Collectors.toList()); + } + + private List returnAllSubmodels() { + return storageApi.retrieveAll().stream().map(submodel -> (ISubmodel) submodel).collect(Collectors.toList()); + } + + private List findSubmodelsWithGivenParentId(){ + return storageApi.retrieveAll().stream().filter(submodel -> { + IReference parentRef = submodel.getParent(); + return (parentRef != null) && (parentRef.getKeys().get(0).getValue().equals(shellId.getId())); + }).collect(Collectors.toList()); + } + + private IKey getLastKeyFromReference(IReference reference) { + List keys = reference.getKeys(); + IKey lastKey = keys.get(keys.size() - 1); + return lastKey; + } + + @Override + public ISubmodel getSubmodel(IIdentifier identifier) throws ResourceNotFoundException { + return storageApi.retrieve(identifier.getId()); + } + + @Override + public void createSubmodel(Submodel submodel) { + storageApi.createOrUpdate(submodel); + } + + @Override + public void updateSubmodel(Submodel submodel) throws ResourceNotFoundException { + storageApi.createOrUpdate(submodel); + } + + @Override + public void createSubmodel(ISubmodelAPI submodelAPI) { + storageApi.createOrUpdate((Submodel) submodelAPI.getSubmodel()); + } + + @Override + public ISubmodel getSubmodelbyIdShort(String idShort) throws ResourceNotFoundException { + Optional submodelOptional = getSubmodelList().stream().filter(submodel -> { + return submodel.getIdShort().equals(idShort); + }).findAny(); + if (submodelOptional.isEmpty()) + throw new ResourceNotFoundException("The submodel with idShort '" + idShort + "' could not be found"); + return submodelOptional.get(); + } + + @Override + public ISubmodelAPI getSubmodelAPIById(IIdentifier identifier) throws ResourceNotFoundException { + Submodel submodel = (Submodel) getSubmodel(identifier); + return new VABSubmodelAPIFactory().create(submodel); + } + + @Override + public ISubmodelAPI getSubmodelAPIByIdShort(String idShort) throws ResourceNotFoundException { + Submodel submodel = (Submodel) getSubmodelbyIdShort(idShort); + return new VABSubmodelAPIFactory().create(submodel); + } } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregatorFactory.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregatorFactory.java index 72c5a051..d5c63dfc 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregatorFactory.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAggregatorFactory.java @@ -63,8 +63,8 @@ public ISubmodelAggregator create() { } @Override - public ISubmodelAggregator create(IIdentifier ignored) { - return create(); + public ISubmodelAggregator create(IIdentifier shellId) { + return new MongoDBSubmodelAggregator(submodelAPIFactory, config, client, shellId); } } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAggregator.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAggregator.java index f655c944..380a0db0 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAggregator.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAggregator.java @@ -109,7 +109,11 @@ public static void setUpClass() throws ParserConfigurationException, SAXExceptio component.setRegistry(registry); component.startComponent(); + } + @Override + public void setup() { + super.setup(); createAssetAdministrationShell(AAS_ID); createSubmodel(SM_IDSHORT, SM_IDENTIFICATION, AAS_ID); } @@ -152,14 +156,11 @@ private static void createSubmodel(String smIdShort, Identifier smIdentifier, St @Test public void testDeleteReachesDatabase() { - final BaSyxMongoDBConfiguration config = new BaSyxMongoDBConfiguration(); - config.loadFromResource(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH); - - final MongoClient client = MongoClients.create(config.getConnectionUrl()); + final MongoClient client = MongoClients.create(mongoDBConfig.getConnectionUrl()); - final MongoTemplate mongoOps = new MongoTemplate(client, config.getDatabase()); + final MongoTemplate mongoOps = new MongoTemplate(client, mongoDBConfig.getDatabase()); - final String aasCollection = config.getAASCollection(); + final String aasCollection = mongoDBConfig.getAASCollection(); final IAASAggregator aggregator = getAggregator(); @@ -198,16 +199,16 @@ public void testDeleteReachesDatabase() { @SuppressWarnings("deprecation") @Override protected IAASAggregator getAggregator() { - MongoDBAASAggregator aggregator = new MongoDBAASAggregator(BaSyxMongoDBConfiguration.DEFAULT_CONFIG_PATH); + MongoDBAASAggregator aggregator = new MongoDBAASAggregator(mongoDBConfig, registry); aggregator.reset(); - return aggregator; } @SuppressWarnings("deprecation") @Test public void checkInitialSetupAfterCreatingAndRegisteringAasAndSubmodel() { - MongoDBAASAggregator aggregator = new MongoDBAASAggregator(mongoDBConfig); + MongoDBAASAggregator aggregator = new MongoDBAASAggregator(mongoDBConfig, registry); + ISubmodel persistentSubmodel = getSubmodelFromAggregator(aggregator, AAS_ID, SM_IDSHORT); assertEquals(SM_IDSHORT, persistentSubmodel.getIdShort()); @@ -248,9 +249,6 @@ private void assertSubmodelsAreResolvedCorrectly(ISubmodel persistentSubmodel, I } private void createAASWithSubmodelWithCollidingIdShort() { - createAssetAdministrationShell(AAS_ID); - createSubmodel(SM_IDSHORT, SM_IDENTIFICATION, AAS_ID); - createAssetAdministrationShell(AAS_ID_2); createSubmodel(SM_IDSHORT, SM_IDENTIFICATION_2, AAS_ID_2); } @@ -273,6 +271,7 @@ public void checkNoExceptionIsObservedAfterPassingRegistry() { restartAasServer(); MongoDBAASAggregator aggregator = new MongoDBAASAggregator(mongoDBConfig, registry); + MultiSubmodelProvider aasProvider = (MultiSubmodelProvider) getAssetAdministrationShellProviderFromMongoDBAggregator(aggregator, AAS_ID, SM_IDSHORT); Map submodelObject = (Map) aasProvider.getValue(PREFIX_SUBMODEL_PATH + SM_IDSHORT + SUFFIX_SUBMODEL_PATH); diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBServer.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBServer.java index 2fb38045..d6fc380c 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBServer.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBServer.java @@ -130,7 +130,7 @@ public void testAggregatorPersistency() throws Exception { createAssetAdministrationShell(); createSubmodel(); - MongoDBAASAggregator aggregator = new MongoDBAASAggregator(mongoDBConfig); + MongoDBAASAggregator aggregator = new MongoDBAASAggregator(mongoDBConfig, aasRegistry); ISubmodel persistentSM = getSubmodelFromAggregator(aggregator); assertEquals(SM_IDSHORT, persistentSM.getIdShort()); From b6875490350b3d67c428035dcd40bc8fa9784c20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 01:44:37 +0000 Subject: [PATCH 59/63] Bump org.apache.maven.plugins:maven-javadoc-plugin in /basyx.components Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.5.0...maven-javadoc-plugin-3.6.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- basyx.components/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index 2284d638..fc85fc7f 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -155,7 +155,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.0 8 From a9187e769790a35e467ac4d137e173d1bd125b18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 01:26:02 +0000 Subject: [PATCH 60/63] Bump com.h2database:h2 from 2.2.222 to 2.2.224 in /basyx.components Bumps [com.h2database:h2](https://github.com/h2database/h2database) from 2.2.222 to 2.2.224. - [Release notes](https://github.com/h2database/h2database/releases) - [Commits](https://github.com/h2database/h2database/compare/version-2.2.222...version-2.2.224) --- updated-dependencies: - dependency-name: com.h2database:h2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- basyx.components/basyx.components.lib/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 48ca21ec..11e2fe0c 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -109,7 +109,7 @@ com.h2database h2 - 2.2.222 + 2.2.224 From 53af334bbb4d0e96c22db23d0a983d051ae8e7ff Mon Sep 17 00:00:00 2001 From: Frank Schnicke Date: Wed, 4 Oct 2023 07:17:43 +0200 Subject: [PATCH 61/63] Removes indexing * Does not work with CosmosDB at the moment Signed-off-by: Frank Schnicke --- .../components/aas/mongodb/MongoDBAASAggregator.java | 8 ++------ .../AASServer/mongodb/TestMongoDBAAASAPI.java | 1 + .../internal/mongodb/MongoDBBaSyxStorageAPI.java | 10 +--------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java index 623e76f4..5632cc22 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBAASAggregator.java @@ -342,16 +342,12 @@ private static ISubmodelAggregatorFactory initSubmodelAggregatorFactory(BaSyxMon return new SubmodelAggregatorFactory(submodelApiFactory); } + @SuppressWarnings("deprecation") private static ISubmodelAPIFactory initSubmodelApiFactory(BaSyxMongoDBConfiguration config) { return new MongoDBSubmodelAPIFactory(config); } - private MongoDBSubmodelAPI createAPI(Submodel submodel, BaSyxMongoDBConfiguration config) { - MongoDBSubmodelAPI api = new MongoDBSubmodelAPI(config, submodel.getIdentification().getId()); - api.setSubmodel(submodel); - return api; - } - + @SuppressWarnings("deprecation") private static IAASAPIFactory initShellApiFactory(BaSyxMongoDBConfiguration config) { return new MongoDBAASAPIFactory(config); } diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAAASAPI.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAAASAPI.java index 21cd3d8f..c7770652 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAAASAPI.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/java/org/eclipse/basyx/regression/AASServer/mongodb/TestMongoDBAAASAPI.java @@ -54,6 +54,7 @@ public class TestMongoDBAAASAPI { private static MongoDBBaSyxStorageAPI mongoDBStorageAPI; private final static String SHELL_IDENTIFICATION_ID = "testIdentificationId"; + @SuppressWarnings("deprecation") @BeforeClass public static void setUpClass() { mongoDBStorageAPI = new MongoDBBaSyxStorageAPI<>(COLLECTION_NAME, AssetAdministrationShell.class, config); diff --git a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java index 53599743..5df97a9a 100644 --- a/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java +++ b/basyx.components/basyx.components.lib/src/main/java/org/eclipse/basyx/components/internal/mongodb/MongoDBBaSyxStorageAPI.java @@ -43,11 +43,9 @@ import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException; -import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.FindAndReplaceOptions; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.query.Query; import com.mongodb.client.MongoClient; @@ -83,12 +81,6 @@ public MongoDBBaSyxStorageAPI(String collectionName, Class type, BaSyxMongoDB this.config = config; this.client = client; this.mongoOps = new MongoTemplate(client, config.getDatabase()); - this.configureIndexKey(); - } - - private void configureIndexKey() { - Index idIndex = new Index().on(INDEX_KEY, Direction.ASC); - this.mongoOps.indexOps(TYPE).ensureIndex(idIndex); } @Override @@ -163,7 +155,7 @@ public T rawRetrieve(String key) { throw new ResourceNotFoundException("No Object for key '" + key + "' found in the database."); } result = handleMongoDbIdAttribute(result); - return (T) result; + return result; } @Override From 1461345ab630ec7781d2bc2760c04e50f4a4c171 Mon Sep 17 00:00:00 2001 From: FlorianWege-IESE Date: Wed, 4 Oct 2023 08:16:22 +0200 Subject: [PATCH 62/63] Fix PathTargetInformation equals check and toString Signed-off-by: FlorianWege-IESE --- .../aas/authorization/internal/PathTargetInformation.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/authorization/internal/PathTargetInformation.java b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/authorization/internal/PathTargetInformation.java index 9facfed6..a6a1ac1f 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/authorization/internal/PathTargetInformation.java +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/authorization/internal/PathTargetInformation.java @@ -31,7 +31,6 @@ import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.eclipse.basyx.extensions.shared.authorization.internal.TagTargetInformation; import org.eclipse.basyx.extensions.shared.authorization.internal.TargetInformation; import com.fasterxml.jackson.annotation.JsonCreator; @@ -73,7 +72,7 @@ public boolean equals(final Object o) { return true; } - if (!(o instanceof TagTargetInformation)) { + if (!(o instanceof PathTargetInformation)) { return false; } @@ -89,6 +88,6 @@ public int hashCode() { @Override public String toString() { - return new StringBuilder("BaSyxObjectTargetInformation{").append("tag='").append(path).append('\'').append('}').toString(); + return new StringBuilder("PathTargetInformation{").append("path='").append(path).append('\'').append('}').toString(); } } From 44422c3c53996c20417413d87d807c07649ddc31 Mon Sep 17 00:00:00 2001 From: Frank Schnicke Date: Wed, 4 Oct 2023 08:37:10 +0200 Subject: [PATCH 63/63] Updates version to 1.5.0 Signed-off-by: Frank Schnicke --- .../basyx.components.AASServer/pom.xml | 4 ++-- .../basyx.components.AASServer/src/test/resources/.env | 2 +- .../basyx.components.registry/pom.xml | 2 +- .../basyx.components.registry/src/test/resources/.env | 2 +- basyx.components/basyx.components.docker/pom.xml | 4 ++-- basyx.components/basyx.components.lib/pom.xml | 2 +- basyx.components/pom.xml | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml index 9add92a1..5d457d3a 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/pom.xml @@ -7,7 +7,7 @@ org.eclipse.basyx basyx.components.docker - 1.5.0-SNAPSHOT + 1.5.0 basyx.components.AASServer @@ -121,7 +121,7 @@ org.eclipse.basyx basyx.components.registry - 1.5.0-SNAPSHOT + 1.5.0 test diff --git a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env index e028edd1..425f95c4 100644 --- a/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env +++ b/basyx.components/basyx.components.docker/basyx.components.AASServer/src/test/resources/.env @@ -28,7 +28,7 @@ BASYX_IMAGE_NAME=eclipsebasyx/aas-server # ################## # The image tag of the image that is build for this component -BASYX_IMAGE_TAG=1.5.0-SNAPSHOT +BASYX_IMAGE_TAG=1.5.0 # ################## # Container Name diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml index 04cdd50f..c55aaf23 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml +++ b/basyx.components/basyx.components.docker/basyx.components.registry/pom.xml @@ -6,7 +6,7 @@ org.eclipse.basyx basyx.components.docker - 1.5.0-SNAPSHOT + 1.5.0 basyx.components.registry diff --git a/basyx.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env b/basyx.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env index b7c472cc..8fdd96e3 100644 --- a/basyx.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env +++ b/basyx.components/basyx.components.docker/basyx.components.registry/src/test/resources/.env @@ -28,7 +28,7 @@ BASYX_IMAGE_NAME=eclipsebasyx/aas-registry # ################## # The image tag of the image that is build for this component -BASYX_IMAGE_TAG=1.5.0-SNAPSHOT +BASYX_IMAGE_TAG=1.5.0 # ################## # Container Name diff --git a/basyx.components/basyx.components.docker/pom.xml b/basyx.components/basyx.components.docker/pom.xml index ac5aa1f2..0eb8d0ec 100644 --- a/basyx.components/basyx.components.docker/pom.xml +++ b/basyx.components/basyx.components.docker/pom.xml @@ -7,7 +7,7 @@ org.eclipse.basyx basyx.components - 1.5.0-SNAPSHOT + 1.5.0 basyx.components.docker @@ -223,7 +223,7 @@ org.eclipse.basyx basyx.components.lib - 1.5.0-SNAPSHOT + 1.5.0 diff --git a/basyx.components/basyx.components.lib/pom.xml b/basyx.components/basyx.components.lib/pom.xml index 11e2fe0c..dab3f087 100644 --- a/basyx.components/basyx.components.lib/pom.xml +++ b/basyx.components/basyx.components.lib/pom.xml @@ -6,7 +6,7 @@ org.eclipse.basyx basyx.components - 1.5.0-SNAPSHOT + 1.5.0 basyx.components.lib diff --git a/basyx.components/pom.xml b/basyx.components/pom.xml index fc85fc7f..059ab2c7 100644 --- a/basyx.components/pom.xml +++ b/basyx.components/pom.xml @@ -5,7 +5,7 @@ org.eclipse.basyx basyx.components - 1.5.0-SNAPSHOT + 1.5.0 BaSyx Components BaSyx Off-the-Shelf Components https://www.eclipse.org/basyx/ @@ -281,14 +281,14 @@ org.eclipse.basyx basyx.sdk - 1.5.0-SNAPSHOT + 1.5.0 org.eclipse.basyx basyx.sdk - 1.5.0-SNAPSHOT + 1.5.0 tests test