From 6a51b5c52fabd2fe5d8aa48d24ab4bee440d1bff Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Wed, 16 Oct 2024 17:01:37 +0200 Subject: [PATCH 1/9] Moves InMemory CrudRepository to inmemory core module Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../basyx.aasrepository-backend/pom.xml | 4 + .../backend/CrudAasRepository.java | 15 ++- .../basyx.backend.inmemory.core/pom.xml | 26 +++++ .../inmemory/core/InMemoryCrudRepository.java | 95 +++++++++++++++++++ .../pagination/BaSyxAggregationOperation.java | 7 ++ basyx.common/basyx.mongocore/pom.xml | 4 + .../mongocore/MongoDBCrudRepository.java | 35 +++++++ .../common/mongocore/MongoDBUtilities.java | 17 ++++ basyx.common/pom.xml | 1 + 9 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 basyx.common/basyx.backend.inmemory.core/pom.xml create mode 100644 basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java create mode 100644 basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/BaSyxAggregationOperation.java create mode 100644 basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java diff --git a/basyx.aasrepository/basyx.aasrepository-backend/pom.xml b/basyx.aasrepository/basyx.aasrepository-backend/pom.xml index 5936dd14a..598ee779a 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend/pom.xml +++ b/basyx.aasrepository/basyx.aasrepository-backend/pom.xml @@ -19,6 +19,10 @@ org.eclipse.digitaltwin.basyx basyx.aasrepository-core + + org.eclipse.digitaltwin.basyx + basyx.mongodbcore + org.springframework.data spring-data-commons diff --git a/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java b/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java index f78c7e045..a01a035c7 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java @@ -26,17 +26,22 @@ import java.io.File; import java.io.InputStream; +import java.util.LinkedList; import java.util.List; import java.util.TreeMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation; import org.eclipse.digitaltwin.aas4j.v3.model.Reference; +import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasservice.AasService; import org.eclipse.digitaltwin.basyx.aasservice.AasServiceFactory; +import org.eclipse.digitaltwin.basyx.common.mongocore.MongoDBUtilities; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.IdentificationMismatchException; @@ -45,6 +50,9 @@ import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; +import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.repository.CrudRepository; /** @@ -75,7 +83,12 @@ public CrudAasRepository(AasBackendProvider aasBackendProvider, AasServiceFactor @Override public CursorResult> getAllAas(PaginationInfo pInfo) { - + List allAggregations = new LinkedList(); + + MongoDBUtilities.applyPagination(pInfo, allAggregations); + + AggregationResults results = template.aggregate(Aggregation.newAggregation(allAggregations), AssetAdministrationShellDescriptor.class, AssetAdministrationShellDescriptor.class); + Iterable iterable = aasBackend.findAll(); List allAas = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); diff --git a/basyx.common/basyx.backend.inmemory.core/pom.xml b/basyx.common/basyx.backend.inmemory.core/pom.xml new file mode 100644 index 000000000..579e9c321 --- /dev/null +++ b/basyx.common/basyx.backend.inmemory.core/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + + org.eclipse.digitaltwin.basyx + basyx.common + ${revision} + + basyx.backend.inmemory.core + BaSyx InMemory Backend core + BaSyx InMemory Backend core + + + + org.eclipse.digitaltwin.basyx + basyx.core + + + org.springframework.data + spring-data-commons + + + org.eclipse.digitaltwin.aas4j + aas4j-dataformat-json + + + \ No newline at end of file diff --git a/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java b/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java new file mode 100644 index 000000000..5afe9ca42 --- /dev/null +++ b/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java @@ -0,0 +1,95 @@ +package org.eclipse.digitaltwin.basyx.common.backend.inmemory.core; + +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.lang.NonNull; + +public class InMemoryCrudRepository implements CrudRepository { + + private final ConcurrentMap inMemoryStore = new ConcurrentHashMap<>(); + private Function idGetter; + + public InMemoryCrudRepository(Function idGetter) { + this.idGetter = idGetter; + } + + @Override + public @NonNull S save(@NonNull S entity) { + String id = idGetter.apply(entity); + + inMemoryStore.put(id, entity); + + return entity; + } + + @Override + public @NonNull Iterable saveAll(@NonNull Iterable entities) { + entities.forEach(this::save); + + return entities; + } + + @Override + public @NonNull Optional findById(@NonNull String id) { + return Optional.ofNullable(inMemoryStore.get(id)); + } + + @Override + public boolean existsById(@NonNull String id) { + return inMemoryStore.containsKey(id); + } + + @Override + public @NonNull Iterable findAll() { + return inMemoryStore.values(); + } + + @Override + public @NonNull Iterable findAllById(@NonNull Iterable ids) { + return StreamSupport.stream(ids.spliterator(), false).map(inMemoryStore::get).filter(Objects::nonNull).collect(Collectors.toList()); + } + + @Override + public long count() { + return inMemoryStore.size(); + } + + @Override + public void deleteById(@NonNull String id) { + inMemoryStore.remove(id); + } + + @Override + public void delete(@NonNull T entity) { + String id = idGetter.apply(entity); + + inMemoryStore.remove(id); + } + + @Override + public void deleteAllById(@NonNull Iterable ids) { + for (String id : ids) + inMemoryStore.remove(id); + } + + @Override + public void deleteAll(@NonNull Iterable entities) { + + for (T entity : entities) + inMemoryStore.remove(idGetter.apply(entity)); + } + + @Override + public void deleteAll() { + inMemoryStore.clear(); + } + + +} diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/BaSyxAggregationOperation.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/BaSyxAggregationOperation.java new file mode 100644 index 000000000..325f3436e --- /dev/null +++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/BaSyxAggregationOperation.java @@ -0,0 +1,7 @@ +package org.eclipse.digitaltwin.basyx.core.pagination; + +public interface BaSyxAggregationOperation { + + T getAggregationOperation(); + +} diff --git a/basyx.common/basyx.mongocore/pom.xml b/basyx.common/basyx.mongocore/pom.xml index 99e5f83b6..1a59264a8 100644 --- a/basyx.common/basyx.mongocore/pom.xml +++ b/basyx.common/basyx.mongocore/pom.xml @@ -22,5 +22,9 @@ org.springframework.boot spring-boot-starter-data-mongodb + + org.eclipse.digitaltwin.basyx + basyx.core + \ No newline at end of file diff --git a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java new file mode 100644 index 000000000..ab3927a31 --- /dev/null +++ b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java @@ -0,0 +1,35 @@ +package org.eclipse.digitaltwin.basyx.common.mongocore; + +import java.util.List; + +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; +import org.springframework.data.mongodb.core.aggregation.AggregationResults; +import org.springframework.data.mongodb.repository.query.MongoEntityInformation; +import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; + +public class MongoDBCrudRepository extends SimpleMongoRepository { + + private List allAggregations; + private MongoTemplate template; + private Class clazz; + + public MongoDBCrudRepository(MongoEntityInformation metadata, MongoTemplate mongoTemplate, List allAggregations, Class clazz) { + super(metadata, mongoTemplate); + + this.template = mongoTemplate; + this.allAggregations = allAggregations; + this.clazz = clazz; + } + + @Override + public List findAll() { + + AggregationResults results = template.aggregate(Aggregation.newAggregation(allAggregations), clazz, clazz); + + return results.getMappedResults(); + } + + +} diff --git a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java index f6d46ac7b..3cba55e31 100644 --- a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java +++ b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java @@ -24,7 +24,13 @@ ******************************************************************************/ package org.eclipse.digitaltwin.basyx.common.mongocore; +import java.util.List; + +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; +import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; /** @@ -33,6 +39,8 @@ * */ public class MongoDBUtilities { + + private static final String ID = "_id"; /** * Removes all documents from the specified collection. @@ -43,4 +51,13 @@ public class MongoDBUtilities { public static void clearCollection(MongoTemplate template, String collection) { template.remove(new Query(), collection); } + + public static void applyPagination(PaginationInfo pRequest, List allAggregations) { + + if (pRequest.getCursor() != null) + allAggregations.add(Aggregation.match(Criteria.where(ID).gt(pRequest.getCursor()))); + + if (pRequest.getLimit() != null) + allAggregations.add(Aggregation.limit(pRequest.getLimit())); + } } diff --git a/basyx.common/pom.xml b/basyx.common/pom.xml index 9ac32b4b3..fe6807eaa 100644 --- a/basyx.common/pom.xml +++ b/basyx.common/pom.xml @@ -20,6 +20,7 @@ basyx.mongocore basyx.authorization basyx.client + basyx.backend.inmemory.core basyx.filerepository-backend basyx.filerepository-backend-inmemory basyx.filerepository-backend-mongodb From 47c8c186f153d240184f219cc5546e4ef1b1628a Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Thu, 17 Oct 2024 13:00:17 +0200 Subject: [PATCH 2/9] Refactors *InMemory Crud Repo to common Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../pom.xml | 7 +- .../AasDiscoveryInMemoryBackendProvider.java | 3 +- .../AasDiscoveryInMemoryCrudRepository.java | 138 ------------------ .../pom.xml | 4 + .../backend/inmemory/AasInMemoryBackend.java | 117 --------------- .../inmemory/AasInMemoryBackendProvider.java | 5 +- .../backend/CrudAasRepository.java | 15 +- .../inmemory/core/InMemoryCrudRepository.java | 30 ++++ .../pagination/BaSyxAggregationOperation.java | 7 - basyx.common/basyx.mongocore/pom.xml | 4 - .../mongocore/MongoDBCrudRepository.java | 35 ----- .../common/mongocore/MongoDBUtilities.java | 17 --- .../pom.xml | 4 + .../ConceptDescriptionInMemoryBackend.java | 116 --------------- ...eptDescriptionInMemoryBackendProvider.java | 3 +- .../pom.xml | 4 + .../SubmodelInMemoryBackend.java | 116 --------------- .../SubmodelInMemoryBackendProvider.java | 3 +- pom.xml | 5 + 19 files changed, 62 insertions(+), 571 deletions(-) delete mode 100644 basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryCrudRepository.java delete mode 100644 basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackend.java delete mode 100644 basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/BaSyxAggregationOperation.java delete mode 100644 basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java delete mode 100644 basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackend.java delete mode 100644 basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackend.java diff --git a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/pom.xml b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/pom.xml index 7d7849257..62201b56d 100644 --- a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/pom.xml +++ b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/pom.xml @@ -19,8 +19,11 @@ org.eclipse.digitaltwin.basyx basyx.aasdiscoveryservice-backend - - + + + org.eclipse.digitaltwin.basyx + basyx.backend.inmemory.core + org.eclipse.digitaltwin.basyx basyx.aasdiscoveryservice-core diff --git a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryBackendProvider.java b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryBackendProvider.java index 46971ba9c..21720e822 100644 --- a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryBackendProvider.java +++ b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryBackendProvider.java @@ -27,6 +27,7 @@ import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend.AasDiscoveryBackendProvider; import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend.AasDiscoveryDocument; +import org.eclipse.digitaltwin.basyx.common.backend.inmemory.core.InMemoryCrudRepository; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; @@ -41,7 +42,7 @@ @Component public class AasDiscoveryInMemoryBackendProvider implements AasDiscoveryBackendProvider { - private AasDiscoveryInMemoryCrudRepository repository = new AasDiscoveryInMemoryCrudRepository(); + private CrudRepository repository = new InMemoryCrudRepository(AasDiscoveryDocument::getShellIdentifier); @Override public CrudRepository getCrudRepository() { diff --git a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryCrudRepository.java b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryCrudRepository.java deleted file mode 100644 index 7fdf732c7..000000000 --- a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryCrudRepository.java +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend.inmemory; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.stream.StreamSupport; - -import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; -import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend.AasDiscoveryDocument; -import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.core.model.AssetLink; -import org.springframework.data.repository.CrudRepository; -import org.springframework.lang.NonNull; - -/** - * In-memory implementation of the {@link CrudRepository} for the AAS Discovery - * - * @author zielstor, fried, mateusmolina - */ -public class AasDiscoveryInMemoryCrudRepository implements CrudRepository { - - private final ConcurrentMap> assetLinks = new ConcurrentHashMap<>(); - private final ConcurrentMap> assetIds = new ConcurrentHashMap<>(); - - @Override - public synchronized @NonNull S save(@NonNull S entity) { - String shellId = entity.getShellIdentifier(); - - this.assetLinks.put(shellId, entity.getAssetLinks()); - this.assetIds.put(shellId, entity.getSpecificAssetIds()); - - return entity; - } - - @Override - public @NonNull Iterable saveAll(@NonNull Iterable entities) { - entities.forEach(this::save); - return entities; - } - - @Override - public @NonNull Optional findById(@NonNull String id) { - return Optional.ofNullable(buildAasDiscoveryDocument(id)); - } - - @Override - public boolean existsById(@NonNull String id) { - return this.assetLinks.containsKey(id); - } - - @Override - public @NonNull Iterable findAll() { - return assetLinks.keySet().stream().map(this::buildAasDiscoveryDocument).toList(); - } - - @Override - public @NonNull Iterable findAllById(@NonNull Iterable ids) { - return StreamSupport.stream(ids.spliterator(), false).map(this::buildAasDiscoveryDocument).toList(); - } - - @Override - public long count() { - return this.assetLinks.size(); - } - - @Override - public synchronized void deleteById(@NonNull String id) { - this.assetLinks.remove(id); - this.assetIds.remove(id); - } - - @Override - public void delete(@NonNull AasDiscoveryDocument entity) { - this.deleteById(entity.getShellIdentifier()); - } - - @Override - public void deleteAllById(@NonNull Iterable ids) { - for (String id : ids) { - this.deleteById(id); - } - } - - @Override - public void deleteAll(@NonNull Iterable entities) { - for (AasDiscoveryDocument entity : entities) { - this.deleteById(entity.getShellIdentifier()); - } - } - - @Override - public synchronized void deleteAll() { - this.assetLinks.clear(); - this.assetIds.clear(); - } - - private synchronized AasDiscoveryDocument buildAasDiscoveryDocument(String shellId) { - Set assetLinksSet = assetLinks.get(shellId); - List assetIdsList = assetIds.get(shellId); - - if (assetIdsList == null) - assetIdsList = new ArrayList<>(); - - if (assetLinksSet == null) - assetLinksSet = new HashSet<>(); - - return new AasDiscoveryDocument(shellId, assetLinksSet, assetIdsList); - } - -} diff --git a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/pom.xml b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/pom.xml index 3f6b3a9b8..45c8dc476 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/pom.xml +++ b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/pom.xml @@ -22,6 +22,10 @@ org.eclipse.digitaltwin.basyx basyx.aasrepository-backend + + org.eclipse.digitaltwin.basyx + basyx.backend.inmemory.core + org.eclipse.digitaltwin.basyx basyx.aasrepository-core diff --git a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackend.java b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackend.java deleted file mode 100644 index aeb02fd99..000000000 --- a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackend.java +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************* - * 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.digitaltwin.basyx.aasrepository.backend.inmemory; - -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; -import org.springframework.data.repository.CrudRepository; -import org.springframework.lang.NonNull; - -/** - * InMemory implementation for the AAS backend - * - * @author mateusmolina - * - */ -public class AasInMemoryBackend implements CrudRepository { - - private final ConcurrentMap inMemoryStore = new ConcurrentHashMap<>(); - - @Override - public @NonNull S save(@NonNull S entity) { - inMemoryStore.put(entity.getId(), entity); - - return entity; - } - - @Override - public @NonNull Iterable saveAll(@NonNull Iterable entities) { - entities.forEach(this::save); - - return entities; - } - - @Override - public @NonNull Optional findById(@NonNull String id) { - return Optional.ofNullable(inMemoryStore.get(id)); - } - - @Override - public boolean existsById(@NonNull String id) { - return inMemoryStore.containsKey(id); - } - - @Override - public @NonNull Iterable findAll() { - return inMemoryStore.values(); - } - - @Override - public @NonNull Iterable findAllById(@NonNull Iterable ids) { - return StreamSupport.stream(ids.spliterator(), false).map(inMemoryStore::get).filter(Objects::nonNull).collect(Collectors.toList()); - } - - @Override - public long count() { - return inMemoryStore.size(); - } - - @Override - public void deleteById(@NonNull String id) { - inMemoryStore.remove(id); - } - - @Override - public void delete(@NonNull AssetAdministrationShell entity) { - inMemoryStore.remove(entity.getId()); - } - - @Override - public void deleteAllById(@NonNull Iterable ids) { - for (String id : ids) - inMemoryStore.remove(id); - } - - @Override - public void deleteAll(@NonNull Iterable entities) { - for (AssetAdministrationShell entity : entities) - inMemoryStore.remove(entity.getId()); - } - - @Override - public void deleteAll() { - inMemoryStore.clear(); - } - - -} - diff --git a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackendProvider.java b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackendProvider.java index 0a8a4e788..44860711d 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackendProvider.java +++ b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackendProvider.java @@ -27,6 +27,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; import org.eclipse.digitaltwin.basyx.aasrepository.backend.AasBackendProvider; +import org.eclipse.digitaltwin.basyx.common.backend.inmemory.core.InMemoryCrudRepository; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; @@ -35,7 +36,7 @@ * * InMemory backend provider for the AAS * - * @author mateusmolina + * @author mateusmolina, danish */ @ConditionalOnExpression("'${basyx.backend}'.equals('InMemory')") @Component @@ -43,7 +44,7 @@ public class AasInMemoryBackendProvider implements AasBackendProvider { @Override public CrudRepository getCrudRepository() { - return new AasInMemoryBackend(); + return new InMemoryCrudRepository(AssetAdministrationShell::getId); } } diff --git a/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java b/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java index a01a035c7..f78c7e045 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java @@ -26,22 +26,17 @@ import java.io.File; import java.io.InputStream; -import java.util.LinkedList; import java.util.List; import java.util.TreeMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation; import org.eclipse.digitaltwin.aas4j.v3.model.Reference; -import org.eclipse.digitaltwin.basyx.aasregistry.model.AssetAdministrationShellDescriptor; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasservice.AasService; import org.eclipse.digitaltwin.basyx.aasservice.AasServiceFactory; -import org.eclipse.digitaltwin.basyx.common.mongocore.MongoDBUtilities; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.IdentificationMismatchException; @@ -50,9 +45,6 @@ import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport; import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.mongodb.core.aggregation.Aggregation; -import org.springframework.data.mongodb.core.aggregation.AggregationOperation; -import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.repository.CrudRepository; /** @@ -83,12 +75,7 @@ public CrudAasRepository(AasBackendProvider aasBackendProvider, AasServiceFactor @Override public CursorResult> getAllAas(PaginationInfo pInfo) { - List allAggregations = new LinkedList(); - - MongoDBUtilities.applyPagination(pInfo, allAggregations); - - AggregationResults results = template.aggregate(Aggregation.newAggregation(allAggregations), AssetAdministrationShellDescriptor.class, AssetAdministrationShellDescriptor.class); - + Iterable iterable = aasBackend.findAll(); List allAas = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); diff --git a/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java b/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java index 5afe9ca42..8c5267266 100644 --- a/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java +++ b/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java @@ -1,3 +1,28 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + package org.eclipse.digitaltwin.basyx.common.backend.inmemory.core; import java.util.Objects; @@ -11,6 +36,11 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.lang.NonNull; +/** + * CrudRepository implementation for InMemory backends + * + * @author danish + */ public class InMemoryCrudRepository implements CrudRepository { private final ConcurrentMap inMemoryStore = new ConcurrentHashMap<>(); diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/BaSyxAggregationOperation.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/BaSyxAggregationOperation.java deleted file mode 100644 index 325f3436e..000000000 --- a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/BaSyxAggregationOperation.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.eclipse.digitaltwin.basyx.core.pagination; - -public interface BaSyxAggregationOperation { - - T getAggregationOperation(); - -} diff --git a/basyx.common/basyx.mongocore/pom.xml b/basyx.common/basyx.mongocore/pom.xml index 1a59264a8..99e5f83b6 100644 --- a/basyx.common/basyx.mongocore/pom.xml +++ b/basyx.common/basyx.mongocore/pom.xml @@ -22,9 +22,5 @@ org.springframework.boot spring-boot-starter-data-mongodb - - org.eclipse.digitaltwin.basyx - basyx.core - \ No newline at end of file diff --git a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java deleted file mode 100644 index ab3927a31..000000000 --- a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.eclipse.digitaltwin.basyx.common.mongocore; - -import java.util.List; - -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.aggregation.Aggregation; -import org.springframework.data.mongodb.core.aggregation.AggregationOperation; -import org.springframework.data.mongodb.core.aggregation.AggregationResults; -import org.springframework.data.mongodb.repository.query.MongoEntityInformation; -import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; - -public class MongoDBCrudRepository extends SimpleMongoRepository { - - private List allAggregations; - private MongoTemplate template; - private Class clazz; - - public MongoDBCrudRepository(MongoEntityInformation metadata, MongoTemplate mongoTemplate, List allAggregations, Class clazz) { - super(metadata, mongoTemplate); - - this.template = mongoTemplate; - this.allAggregations = allAggregations; - this.clazz = clazz; - } - - @Override - public List findAll() { - - AggregationResults results = template.aggregate(Aggregation.newAggregation(allAggregations), clazz, clazz); - - return results.getMappedResults(); - } - - -} diff --git a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java index 3cba55e31..f6d46ac7b 100644 --- a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java +++ b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java @@ -24,13 +24,7 @@ ******************************************************************************/ package org.eclipse.digitaltwin.basyx.common.mongocore; -import java.util.List; - -import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.aggregation.Aggregation; -import org.springframework.data.mongodb.core.aggregation.AggregationOperation; -import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; /** @@ -39,8 +33,6 @@ * */ public class MongoDBUtilities { - - private static final String ID = "_id"; /** * Removes all documents from the specified collection. @@ -51,13 +43,4 @@ public class MongoDBUtilities { public static void clearCollection(MongoTemplate template, String collection) { template.remove(new Query(), collection); } - - public static void applyPagination(PaginationInfo pRequest, List allAggregations) { - - if (pRequest.getCursor() != null) - allAggregations.add(Aggregation.match(Criteria.where(ID).gt(pRequest.getCursor()))); - - if (pRequest.getLimit() != null) - allAggregations.add(Aggregation.limit(pRequest.getLimit())); - } } diff --git a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/pom.xml b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/pom.xml index 3d9e795dd..12471a489 100644 --- a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/pom.xml +++ b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/pom.xml @@ -20,6 +20,10 @@ org.eclipse.digitaltwin.basyx basyx.conceptdescriptionrepository-backend + + + org.eclipse.digitaltwin.basyx + basyx.backend.inmemory.core org.eclipse.digitaltwin.basyx diff --git a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackend.java b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackend.java deleted file mode 100644 index 38d8afa27..000000000 --- a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackend.java +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.conceptdescriptionrepository; - -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; -import org.springframework.data.repository.CrudRepository; -import org.springframework.lang.NonNull; - -/** - * InMemory implementation for the {@link ConceptDescription} backend - * - * @author danish, mateusmolina - * - */ -public class ConceptDescriptionInMemoryBackend implements CrudRepository { - - private final ConcurrentMap inMemoryStore = new ConcurrentHashMap<>(); - - @Override - public @NonNull S save(@NonNull S entity) { - inMemoryStore.put(entity.getId(), entity); - - return entity; - } - - @Override - public @NonNull Iterable saveAll(@NonNull Iterable entities) { - entities.forEach(this::save); - - return entities; - } - - @Override - public @NonNull Optional findById(@NonNull String id) { - return Optional.ofNullable(inMemoryStore.get(id)); - } - - @Override - public boolean existsById(@NonNull String id) { - return inMemoryStore.containsKey(id); - } - - @Override - public @NonNull Iterable findAll() { - return inMemoryStore.values(); - } - - @Override - public @NonNull Iterable findAllById(@NonNull Iterable ids) { - return StreamSupport.stream(ids.spliterator(), false).map(inMemoryStore::get).filter(Objects::nonNull).collect(Collectors.toList()); - } - - @Override - public long count() { - return inMemoryStore.size(); - } - - @Override - public void deleteById(@NonNull String id) { - inMemoryStore.remove(id); - } - - @Override - public void delete(@NonNull ConceptDescription entity) { - inMemoryStore.remove(entity.getId()); - } - - @Override - public void deleteAllById(@NonNull Iterable ids) { - for (String id : ids) - inMemoryStore.remove(id); - } - - @Override - public void deleteAll(@NonNull Iterable entities) { - for (ConceptDescription entity : entities) - inMemoryStore.remove(entity.getId()); - } - - @Override - public void deleteAll() { - inMemoryStore.clear(); - } - -} - diff --git a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackendProvider.java b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackendProvider.java index b2dae7e65..e5775d9e7 100644 --- a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackendProvider.java +++ b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackendProvider.java @@ -27,6 +27,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; import org.eclipse.digitaltwin.basyx.aasrepository.backend.ConceptDescriptionBackendProvider; +import org.eclipse.digitaltwin.basyx.common.backend.inmemory.core.InMemoryCrudRepository; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; @@ -42,7 +43,7 @@ public class ConceptDescriptionInMemoryBackendProvider implements ConceptDescrip @Override public CrudRepository getCrudRepository() { - return new ConceptDescriptionInMemoryBackend(); + return new InMemoryCrudRepository(ConceptDescription::getId); } } diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/pom.xml b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/pom.xml index 11d97c975..1edfa7be2 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/pom.xml +++ b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/pom.xml @@ -24,6 +24,10 @@ org.eclipse.digitaltwin.basyx basyx.submodelservice-core + + + org.eclipse.digitaltwin.basyx + basyx.backend.inmemory.core org.eclipse.digitaltwin.basyx diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackend.java b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackend.java deleted file mode 100644 index 91afca35d..000000000 --- a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackend.java +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2024 the Eclipse BaSyx Authors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * SPDX-License-Identifier: MIT - ******************************************************************************/ - -package org.eclipse.digitaltwin.basyx.submodelrepository; - -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; -import org.springframework.data.repository.CrudRepository; -import org.springframework.lang.NonNull; - -/** - * InMemory implementation for the Submodel backend - * - * @author mateusmolina, danish - * - */ -public class SubmodelInMemoryBackend implements CrudRepository { - - private final ConcurrentMap inMemoryStore = new ConcurrentHashMap<>(); - - @Override - public @NonNull S save(@NonNull S entity) { - inMemoryStore.put(entity.getId(), entity); - - return entity; - } - - @Override - public @NonNull Iterable saveAll(@NonNull Iterable entities) { - entities.forEach(this::save); - - return entities; - } - - @Override - public @NonNull Optional findById(String id) { - return Optional.ofNullable(inMemoryStore.get(id)); - } - - @Override - public boolean existsById(@NonNull String id) { - return inMemoryStore.containsKey(id); - } - - @Override - public @NonNull Iterable findAll() { - return inMemoryStore.values(); - } - - @Override - public @NonNull Iterable findAllById(@NonNull Iterable ids) { - return StreamSupport.stream(ids.spliterator(), false).map(inMemoryStore::get).filter(Objects::nonNull).collect(Collectors.toList()); - } - - @Override - public long count() { - return inMemoryStore.size(); - } - - @Override - public void deleteById(@NonNull String id) { - inMemoryStore.remove(id); - } - - @Override - public void delete(@NonNull Submodel entity) { - inMemoryStore.remove(entity.getId()); - } - - @Override - public void deleteAllById(@NonNull Iterable ids) { - for (String id : ids) - inMemoryStore.remove(id); - } - - @Override - public void deleteAll(@NonNull Iterable entities) { - for (Submodel entity : entities) - inMemoryStore.remove(entity.getId()); - } - - @Override - public void deleteAll() { - inMemoryStore.clear(); - } - -} - diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackendProvider.java b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackendProvider.java index 79b69eb2a..bf65b85dc 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackendProvider.java +++ b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackendProvider.java @@ -26,6 +26,7 @@ package org.eclipse.digitaltwin.basyx.submodelrepository; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; +import org.eclipse.digitaltwin.basyx.common.backend.inmemory.core.InMemoryCrudRepository; import org.eclipse.digitaltwin.basyx.submodelrepository.backend.SubmodelBackendProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.data.repository.CrudRepository; @@ -43,7 +44,7 @@ public class SubmodelInMemoryBackendProvider implements SubmodelBackendProvider @Override public CrudRepository getCrudRepository() { - return new SubmodelInMemoryBackend(); + return new InMemoryCrudRepository(Submodel::getId); } } diff --git a/pom.xml b/pom.xml index 079e995d4..7ece3f8bb 100644 --- a/pom.xml +++ b/pom.xml @@ -448,6 +448,11 @@ basyx.filerepository-backend-mongodb ${revision} + + org.eclipse.digitaltwin.basyx + basyx.backend.inmemory.core + ${revision} + org.eclipse.digitaltwin.basyx From f8ed64b36195bc9240a905fa62978322844350c5 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Thu, 17 Oct 2024 16:44:16 +0200 Subject: [PATCH 3/9] Removes NO_LIMIT_PAGINATION_INFO Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../basyx/submodelrepository/core/SubmodelRepositorySuite.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/basyx.submodelrepository/basyx.submodelrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/core/SubmodelRepositorySuite.java b/basyx.submodelrepository/basyx.submodelrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/core/SubmodelRepositorySuite.java index 82fa5b6b5..ce9c3aa04 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/core/SubmodelRepositorySuite.java +++ b/basyx.submodelrepository/basyx.submodelrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/core/SubmodelRepositorySuite.java @@ -48,7 +48,6 @@ import org.eclipse.digitaltwin.basyx.core.exceptions.NotInvokableException; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; -import org.eclipse.digitaltwin.basyx.http.Base64UrlEncoder; import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository; import org.eclipse.digitaltwin.basyx.submodelservice.DummySubmodelFactory; import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService; @@ -95,7 +94,7 @@ public void getAllSubmodelsBySemanticIDPreconfigured() { Collection expectedSubmodels = DummySubmodelFactory.getSubmodelsBySemanticid(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_SEMANTIC_ID); SubmodelRepository repo = getSubmodelRepository(expectedSubmodels); - Collection submodels = repo.getAllSubmodels(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_SEMANTIC_ID, NO_LIMIT_PAGINATION_INFO).getResult(); + Collection submodels = repo.getAllSubmodels(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_SEMANTIC_ID, PaginationInfo.NO_LIMIT).getResult(); assertSubmodelsAreContained(expectedSubmodels, submodels); } From 1dd8b8ff3267656919ac1f9dc8c65ea416856b2b Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Fri, 18 Oct 2024 09:40:23 +0200 Subject: [PATCH 4/9] Implements feature for filtering elements at backend only Signed-off-by: Mohammad Ghazanfar Ali Danish --- .github/workflows/basyx_test.yml | 2 + .github/workflows/docker_test.yml | 2 + .../AasDiscoveryInMemoryBackendProvider.java | 6 +- .../AasDiscoveryMongoDBBackendProvider.java | 10 +- .../backend/AasDiscoveryBackendProvider.java | 4 +- .../backend/CrudAasDiscovery.java | 93 +++--- .../backend/CrudAasDiscoveryTest.java | 2 +- .../AasEnvironmentLoaderTest.java | 19 +- ...onfigurationLoaderTextualResourceTest.java | 3 +- .../TestAASEnvironmentSerialization.java | 3 +- ...AuthorizedAasEnvironmentSerialization.java | 3 +- .../TestAuthorizedAasEnvironmentUpload.java | 3 +- .../inmemory/AasInMemoryBackendProvider.java | 6 +- .../inmemory/AasInMemoryFilterResolution.java | 165 +++++++++++ .../TestInMemoryAasFilterResolution.java | 265 ++++++++++++++++++ .../mongodb/AasMongoDBBackendProvider.java | 37 ++- .../mongodb/AasMongoDBFilterResolution.java | 125 +++++++++ .../TestAasMongoDBFilterResolution.java | 119 ++++++++ .../backend/AasBackendProvider.java | 4 +- .../backend/CrudAasRepository.java | 23 +- .../client/ConnectedAasRepository.java | 3 +- .../TestAuthorizedConnectedAasRepository.java | 32 ++- .../client/TestConnectedAasRepository.java | 33 ++- .../basyx/aasrepository/AasFilter.java | 89 ++++++ .../basyx/aasrepository/AasRepository.java | 3 +- .../aasrepository/AasRepositorySuite.java | 93 +++++- .../basyx/aasrepository/DummyAasFactory.java | 65 +++++ .../AuthorizedAasRepository.java | 5 +- .../feature/mqtt/MqttAasRepository.java | 5 +- .../RegistryIntegrationAasRepository.java | 5 +- .../http/AasRepositoryApiHTTPController.java | 44 ++- .../http/AasRepositoryHTTPApi.java | 3 +- .../http/AasRepositoryHTTPSuite.java | 25 ++ .../http/TestAasRepositoryHTTP.java | 3 +- .../src/test/resources/AasSimple_1.json | 17 +- .../src/test/resources/AasSimple_2.json | 30 +- .../src/test/resources/AasSimple_3.json | 17 +- .../src/test/resources/AasSimple_4.json | 37 +++ .../src/test/resources/AllFilteredAAS.json | 80 ++++++ .../src/test/resources/AllPaginatedAas.json | 106 ++++++- .../test/resources/PaginatedAasSimple_1.json | 22 +- .../src/test/resources/assetInfoSimple.json | 21 +- .../TestAuthorizedConnectedAasService.java | 3 +- .../client/TestConnectedAasService.java | 3 +- .../inmemory/core/InMemoryCrudRepository.java | 56 +++- basyx.common/basyx.core/pom.xml | 4 + .../basyx/core/BaSyxCrudRepository.java | 67 +++++ .../digitaltwin/basyx/core/Filter.java | 9 + .../basyx/core/FilterResolution.java | 60 ++++ .../core/pagination/PaginationUtilities.java | 22 ++ basyx.common/basyx.mongocore/pom.xml | 4 + .../mongocore/MongoDBCrudRepository.java | 69 +++++ .../common/mongocore/MongoDBUtilities.java | 42 +++ ...eptDescriptionInMemoryBackendProvider.java | 4 +- ...ceptDescriptionMongoDBBackendProvider.java | 8 +- ...stMongoDBConceptDescriptionRepository.java | 3 - .../ConceptDescriptionBackendProvider.java | 4 +- .../CrudConceptDescriptionRepository.java | 3 +- .../SubmodelInMemoryBackendProvider.java | 4 +- .../SubmodelMongoDBBackendProvider.java | 8 +- .../backend/CrudSubmodelRepository.java | 12 +- .../backend/SubmodelBackendProvider.java | 4 +- .../backend/CrudSubmodelRepositoryTest.java | 4 +- 63 files changed, 1841 insertions(+), 184 deletions(-) create mode 100644 basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryFilterResolution.java create mode 100644 basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/TestInMemoryAasFilterResolution.java create mode 100644 basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBFilterResolution.java create mode 100644 basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/TestAasMongoDBFilterResolution.java create mode 100644 basyx.aasrepository/basyx.aasrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/AasFilter.java create mode 100644 basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_4.json create mode 100644 basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AllFilteredAAS.json create mode 100644 basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/BaSyxCrudRepository.java create mode 100644 basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/Filter.java create mode 100644 basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/FilterResolution.java create mode 100644 basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/PaginationUtilities.java create mode 100644 basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java diff --git a/.github/workflows/basyx_test.yml b/.github/workflows/basyx_test.yml index 1187244a2..04118297c 100644 --- a/.github/workflows/basyx_test.yml +++ b/.github/workflows/basyx_test.yml @@ -1,6 +1,8 @@ name: Build and Test BaSyx on: + push: + branches: [ feature/filter-at-backend ] pull_request: branches: [ main ] paths-ignore: diff --git a/.github/workflows/docker_test.yml b/.github/workflows/docker_test.yml index d10df98fa..a37eafffd 100644 --- a/.github/workflows/docker_test.yml +++ b/.github/workflows/docker_test.yml @@ -4,6 +4,8 @@ name: Build and Start Docker Images on: + push: + branches: [ feature/filter-at-backend ] pull_request: branches: [ main ] paths-ignore: diff --git a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryBackendProvider.java b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryBackendProvider.java index 21720e822..5fafb7171 100644 --- a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryBackendProvider.java +++ b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/inmemory/AasDiscoveryInMemoryBackendProvider.java @@ -28,8 +28,8 @@ import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend.AasDiscoveryBackendProvider; import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend.AasDiscoveryDocument; import org.eclipse.digitaltwin.basyx.common.backend.inmemory.core.InMemoryCrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; /** @@ -42,10 +42,10 @@ @Component public class AasDiscoveryInMemoryBackendProvider implements AasDiscoveryBackendProvider { - private CrudRepository repository = new InMemoryCrudRepository(AasDiscoveryDocument::getShellIdentifier); + private BaSyxCrudRepository repository = new InMemoryCrudRepository(AasDiscoveryDocument::getShellIdentifier); @Override - public CrudRepository getCrudRepository() { + public BaSyxCrudRepository getCrudRepository() { return repository; } diff --git a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/mongodb/AasDiscoveryMongoDBBackendProvider.java b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/mongodb/AasDiscoveryMongoDBBackendProvider.java index dbe06c2a5..7f28caa09 100644 --- a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/mongodb/AasDiscoveryMongoDBBackendProvider.java +++ b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/mongodb/AasDiscoveryMongoDBBackendProvider.java @@ -28,15 +28,14 @@ import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend.AasDiscoveryBackendProvider; import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend.AasDiscoveryDocument; import org.eclipse.digitaltwin.basyx.common.mongocore.BasyxMongoMappingContext; +import org.eclipse.digitaltwin.basyx.common.mongocore.MongoDBCrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.context.annotation.Bean; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation; -import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; -import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; /** @@ -65,11 +64,12 @@ public AasDiscoveryMongoDBBackendProvider(BasyxMongoMappingContext mappingContex } @Override - public CrudRepository getCrudRepository() { + public BaSyxCrudRepository getCrudRepository() { @SuppressWarnings("unchecked") MongoPersistentEntity entity = (MongoPersistentEntity) mappingContext .getPersistentEntity(AasDiscoveryDocument.class); - return new SimpleMongoRepository<>(new MappingMongoEntityInformation<>(entity), template); + + return new MongoDBCrudRepository(new MappingMongoEntityInformation<>(entity), template, AasDiscoveryDocument.class); } diff --git a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/AasDiscoveryBackendProvider.java b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/AasDiscoveryBackendProvider.java index f6ae8e3b7..68c0f1833 100644 --- a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/AasDiscoveryBackendProvider.java +++ b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/AasDiscoveryBackendProvider.java @@ -24,7 +24,7 @@ ******************************************************************************/ package org.eclipse.digitaltwin.basyx.aasdiscoveryservice.backend; -import org.springframework.data.repository.CrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; /** * Backend provider for the AAS Discovery @@ -38,5 +38,5 @@ public interface AasDiscoveryBackendProvider { * * @return The CRUD repository */ - public CrudRepository getCrudRepository(); + public BaSyxCrudRepository getCrudRepository(); } diff --git a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/CrudAasDiscovery.java b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/CrudAasDiscovery.java index 60e1fd1e8..1821f7efb 100644 --- a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/CrudAasDiscovery.java +++ b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/CrudAasDiscovery.java @@ -32,18 +32,18 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.core.AasDiscoveryService; import org.eclipse.digitaltwin.basyx.aasdiscoveryservice.core.model.AssetLink; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.eclipse.digitaltwin.basyx.core.exceptions.AssetLinkDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingAssetLinkException; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; -import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport; +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationUtilities; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.repository.CrudRepository; @@ -56,7 +56,7 @@ */ public class CrudAasDiscovery implements AasDiscoveryService { - private AasDiscoveryBackendProvider provider; + private BaSyxCrudRepository aasDiscoveryBackend; private String aasDiscoveryServiceName; /** @@ -66,7 +66,7 @@ public class CrudAasDiscovery implements AasDiscoveryService { * The backend provider */ public CrudAasDiscovery(AasDiscoveryBackendProvider provider) { - this.provider = provider; + this.aasDiscoveryBackend = provider.getCrudRepository(); } /** @@ -95,9 +95,11 @@ public CrudAasDiscovery(AasDiscoveryBackendProvider provider, */ @Override public CursorResult> getAllAssetAdministrationShellIdsByAssetLink(PaginationInfo pInfo, List assetIds) { - Set shellIds = getShellIdsWithAssetLinks(assetIds); + List shellIds = getShellIdsWithAssetLinks(assetIds, pInfo); - return paginateList(pInfo, new ArrayList<>(shellIds)); + String cursor = PaginationUtilities.resolveCursor(pInfo, shellIds); + + return new CursorResult<>(cursor, shellIds); } /** @@ -110,11 +112,12 @@ public CursorResult> getAllAssetAdministrationShellIdsByAssetLink(P */ @Override public List getAllAssetLinksById(String shellIdentifier) { - Map> assetIds = getAssetIds(); - throwIfSpecificAssetIdLinkDoesNotExist(assetIds, shellIdentifier); - - return assetIds.get(shellIdentifier); + throwIfSpecificAssetIdLinkDoesNotExist(shellIdentifier); + + AasDiscoveryDocument aasDiscoveryDocuments = aasDiscoveryBackend.findById(shellIdentifier).orElseThrow(() -> new AssetLinkDoesNotExistException(shellIdentifier)); + + return aasDiscoveryDocuments.getSpecificAssetIds(); } /** @@ -129,19 +132,13 @@ public List getAllAssetLinksById(String shellIdentifier) { * @return a list of asset identifiers */ @Override - public List createAllAssetLinksById(String shellIdentifier, - List specificAssetIds) { - - Map> assetLinks = getAssetLinks(); + public List createAllAssetLinksById(String shellIdentifier, List specificAssetIds) { - synchronized (assetLinks) { - throwIfAssetLinkExists(assetLinks, shellIdentifier); + throwIfAssetLinkExists(shellIdentifier); - List shellAssetLinks = deriveAssetLinksFromSpecificAssetIds(specificAssetIds); - AasDiscoveryDocument aasDiscoveryDocument = new AasDiscoveryDocument(shellIdentifier, - new HashSet<>(shellAssetLinks), specificAssetIds); - provider.getCrudRepository().save(aasDiscoveryDocument); - } + List shellAssetLinks = deriveAssetLinksFromSpecificAssetIds(specificAssetIds); + AasDiscoveryDocument aasDiscoveryDocument = new AasDiscoveryDocument(shellIdentifier, new HashSet<>(shellAssetLinks), specificAssetIds); + aasDiscoveryBackend.save(aasDiscoveryDocument); return specificAssetIds; } @@ -155,12 +152,10 @@ public List createAllAssetLinksById(String shellIdentifier, */ @Override public void deleteAllAssetLinksById(String shellIdentifier) { - Map> assetLinks = getAssetLinks(); - synchronized (assetLinks) { - throwIfAssetLinkDoesNotExist(assetLinks, shellIdentifier); + + throwIfAssetLinkDoesNotExist(shellIdentifier); - provider.getCrudRepository().deleteById(shellIdentifier); - } + aasDiscoveryBackend.deleteById(shellIdentifier); } @Override @@ -168,33 +163,25 @@ public String getName(){ return aasDiscoveryServiceName == null ? AasDiscoveryService.super.getName() : aasDiscoveryServiceName; } - private void throwIfAssetLinkExists(Map> assetLinks, String shellIdentifier) { - if (assetLinks.containsKey(shellIdentifier)) + private void throwIfAssetLinkExists(String shellIdentifier) { + if (aasDiscoveryBackend.existsById(shellIdentifier)) throw new CollidingAssetLinkException(shellIdentifier); } - private void throwIfAssetLinkDoesNotExist(Map> assetLinks, String shellIdentifier) { - if (!assetLinks.containsKey(shellIdentifier)) + private void throwIfAssetLinkDoesNotExist(String shellIdentifier) { + + if (!aasDiscoveryBackend.existsById(shellIdentifier)) throw new AssetLinkDoesNotExistException(shellIdentifier); + } - private void throwIfSpecificAssetIdLinkDoesNotExist(Map> assetIds, + private void throwIfSpecificAssetIdLinkDoesNotExist( String shellIdentifier) { - if (!assetIds.containsKey(shellIdentifier)) + if (!aasDiscoveryBackend.existsById(shellIdentifier)) throw new AssetLinkDoesNotExistException(shellIdentifier); } - private Map> getAssetIds() { - Iterable aasDiscoveryDocuments = provider.getCrudRepository().findAll(); - List aasDiscoveryDocumentList = StreamSupport - .stream(aasDiscoveryDocuments.spliterator(), false).collect(Collectors.toList()); - Map> assetIds = aasDiscoveryDocumentList.stream().collect( - Collectors.toMap(AasDiscoveryDocument::getShellIdentifier, AasDiscoveryDocument::getSpecificAssetIds)); - return assetIds; - } - - private Map> getAssetLinks() { - Iterable aasDiscoveryDocuments = provider.getCrudRepository().findAll(); + private Map> getAssetLinks(Iterable aasDiscoveryDocuments) { List aasDiscoveryDocumentList = StreamSupport .stream(aasDiscoveryDocuments.spliterator(), false).collect(Collectors.toList()); Map> assetLinks = aasDiscoveryDocumentList.stream() @@ -203,18 +190,16 @@ private Map> getAssetLinks() { return assetLinks; } - private Set getShellIdsWithAssetLinks(List requestedLinks) { - Map> assetLinks = getAssetLinks(); - return assetLinks.entrySet().stream().filter(entry -> entry.getValue().containsAll(requestedLinks)) + private List getShellIdsWithAssetLinks(List requestedLinks, PaginationInfo pInfo) { + + Iterable aasDiscoveryDocuments = aasDiscoveryBackend.findAll(pInfo, null); + + Map> assetLinks = getAssetLinks(aasDiscoveryDocuments); + + Set assetLinksSet = assetLinks.entrySet().stream().filter(entry -> entry.getValue().containsAll(requestedLinks)) .map(Map.Entry::getKey).collect(Collectors.toSet()); + + return new ArrayList<>(assetLinksSet); } - private CursorResult> paginateList(PaginationInfo pInfo, List shellIdentifiers) { - TreeMap shellIdentifierMap = shellIdentifiers.stream() - .collect(Collectors.toMap(Function.identity(), Function.identity(), (a, b) -> a, TreeMap::new)); - - PaginationSupport paginationSupport = new PaginationSupport<>(shellIdentifierMap, Function.identity()); - - return paginationSupport.getPaged(pInfo); - } } diff --git a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/test/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/CrudAasDiscoveryTest.java b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/test/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/CrudAasDiscoveryTest.java index c799181a8..7c337247f 100644 --- a/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/test/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/CrudAasDiscoveryTest.java +++ b/basyx.aasdiscoveryservice/basyx.aasdiscoveryservice-backend/src/test/java/org/eclipse/digitaltwin/basyx/aasdiscoveryservice/backend/CrudAasDiscoveryTest.java @@ -34,7 +34,7 @@ public class CrudAasDiscoveryTest { @Test public void getConfiguredAasDiscoveryName(){ - AasDiscoveryService service = new SimpleAasDiscoveryFactory(null, CONFIGURED_AAS_DISCOVERY_NAME).create(); + AasDiscoveryService service = new SimpleAasDiscoveryFactory(() -> null, CONFIGURED_AAS_DISCOVERY_NAME).create(); assertEquals(CONFIGURED_AAS_DISCOVERY_NAME,service.getName()); } diff --git a/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/AasEnvironmentLoaderTest.java b/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/AasEnvironmentLoaderTest.java index c3fd3001b..70e54c9a5 100644 --- a/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/AasEnvironmentLoaderTest.java +++ b/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/AasEnvironmentLoaderTest.java @@ -33,6 +33,7 @@ import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.DeserializationException; import org.eclipse.digitaltwin.basyx.aasenvironment.base.DefaultAASEnvironment; import org.eclipse.digitaltwin.basyx.aasenvironment.environmentloader.CompleteEnvironment; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.backend.CrudAasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.backend.CrudConceptDescriptionRepository; @@ -94,7 +95,7 @@ protected void loadRepositories(List pathsToLoad) throws IOException, De public void testWithResourceFile_AllElementsAreDeployed() throws InvalidFormatException, IOException, DeserializationException { loadRepositories(List.of(TEST_ENVIRONMENT_JSON)); - Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().size()); + Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().size()); Assert.assertEquals(2, submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().size()); Assert.assertEquals(2, conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().size()); } @@ -110,7 +111,7 @@ public void testDeployedTwiceNoVersion_AllDeployedButNotOverriden() throws Inval Mockito.verify(submodelRepository, Mockito.times(2)).createSubmodel(Mockito.any()); Mockito.verify(submodelRepository, Mockito.times(0)).updateSubmodel(Mockito.anyString(), Mockito.any()); - Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().size()); + Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().size()); Assert.assertEquals(2, submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().size()); Assert.assertEquals(2, conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().size()); } @@ -126,7 +127,7 @@ public void testDeployedTwiceWithSameVersion_AllDeployedButNotOverriden() throws Mockito.verify(submodelRepository, Mockito.times(2)).createSubmodel(Mockito.any()); Mockito.verify(submodelRepository, Mockito.times(0)).updateSubmodel(Mockito.anyString(), Mockito.any()); - Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().size()); + Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().size()); Assert.assertEquals(2, submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().size()); Assert.assertEquals(2, conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().size()); } @@ -142,7 +143,7 @@ public void testDeployedTwiceNewRevision_ElementsAreOverriden() throws InvalidFo Mockito.verify(submodelRepository, Mockito.times(2)).createSubmodel(Mockito.any()); Mockito.verify(submodelRepository, Mockito.times(1)).updateSubmodel(Mockito.anyString(), Mockito.any()); - Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().size()); + Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().size()); Assert.assertEquals(2, submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().size()); Assert.assertEquals(2, conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().size()); } @@ -166,7 +167,7 @@ public void testWithResourceFile_NoExceptionsWhenReuploadAfterElementsAreRemoved loadRepositoriesWithEnvironment(List.of(TEST_ENVIRONMENT_JSON), envLoader); - Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().size()); + Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().size()); Assert.assertEquals(2, submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().size()); Assert.assertEquals(2, conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().size()); @@ -174,7 +175,7 @@ public void testWithResourceFile_NoExceptionsWhenReuploadAfterElementsAreRemoved loadRepositoriesWithEnvironment(List.of(TEST_ENVIRONMENT_JSON), envLoader); - Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().size()); + Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().size()); Assert.assertEquals(2, submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().size()); Assert.assertEquals(2, conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().size()); } @@ -185,7 +186,7 @@ public void testWithResourceFile_ExceptionIsThrownWhenReuploadWithExistingElemen loadRepositoriesWithEnvironment(List.of(TEST_ENVIRONMENT_JSON), envLoader); - Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().size()); + Assert.assertEquals(2, aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().size()); Assert.assertEquals(2, submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().size()); Assert.assertEquals(2, conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().size()); @@ -202,11 +203,11 @@ private void loadRepositoriesWithEnvironment(List pathsToLoad, AasEnviro } private void deleteElementsFromRepos() { - aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().stream().forEach(aas -> aasRepository.deleteAas(aas.getId())); + aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().stream().forEach(aas -> aasRepository.deleteAas(aas.getId())); submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().stream().forEach(sm -> submodelRepository.deleteSubmodel(sm.getId())); conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().stream().forEach(cd -> conceptDescriptionRepository.deleteConceptDescription(cd.getId())); - Assert.assertEquals(0, aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().size()); + Assert.assertEquals(0, aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().size()); Assert.assertEquals(0, submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().size()); Assert.assertEquals(0, conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().size()); } diff --git a/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/PreconfigurationLoaderTextualResourceTest.java b/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/PreconfigurationLoaderTextualResourceTest.java index 7cd689cc3..90c36796c 100644 --- a/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/PreconfigurationLoaderTextualResourceTest.java +++ b/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/PreconfigurationLoaderTextualResourceTest.java @@ -31,6 +31,7 @@ import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.DeserializationException; import org.eclipse.digitaltwin.basyx.aasenvironment.base.DefaultAASEnvironment; import org.eclipse.digitaltwin.basyx.aasenvironment.preconfiguration.AasEnvironmentPreconfigurationLoader; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.junit.Assert; import org.junit.Test; @@ -53,7 +54,7 @@ protected void loadRepositories(List pathsToLoad) throws IOException, In @Test public void testWithEmptyResource_NoElementsAreDeployed() throws InvalidFormatException, IOException, DeserializationException { loadRepositories(List.of()); - Assert.assertTrue(aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().isEmpty()); + Assert.assertTrue(aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().isEmpty()); Assert.assertTrue(submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().isEmpty()); Assert.assertTrue(conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().isEmpty()); diff --git a/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/TestAASEnvironmentSerialization.java b/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/TestAASEnvironmentSerialization.java index 0564b0d4a..57367273d 100644 --- a/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/TestAASEnvironmentSerialization.java +++ b/basyx.aasenvironment/basyx.aasenvironment-core/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/TestAASEnvironmentSerialization.java @@ -51,6 +51,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultConceptDescription; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel; import org.eclipse.digitaltwin.basyx.aasenvironment.base.DefaultAASEnvironment; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.backend.SimpleAasRepositoryFactory; import org.eclipse.digitaltwin.basyx.aasrepository.backend.SimpleConceptDescriptionRepositoryFactory; @@ -265,7 +266,7 @@ private static List retrieveConceptDescriptionIds(Environment aasEnviron } private void validateRepositoriesState() { - assertTrue(aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().containsAll(createDummyShells())); + assertTrue(aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().containsAll(createDummyShells())); assertTrue(submodelRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().containsAll(createDummySubmodels())); assertTrue(conceptDescriptionRepository.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult().containsAll(createDummyConceptDescriptions())); } diff --git a/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/feature/authorization/TestAuthorizedAasEnvironmentSerialization.java b/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/feature/authorization/TestAuthorizedAasEnvironmentSerialization.java index 7676800a3..f210f9c12 100644 --- a/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/feature/authorization/TestAuthorizedAasEnvironmentSerialization.java +++ b/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/feature/authorization/TestAuthorizedAasEnvironmentSerialization.java @@ -41,6 +41,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.basyx.aasenvironment.TestAASEnvironmentSerialization; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.authorization.AccessTokenProvider; import org.eclipse.digitaltwin.basyx.authorization.DummyCredential; @@ -100,7 +101,7 @@ public static void tearDown() { public void reset() throws FileNotFoundException, IOException { configureSecurityContext(); - Collection assetAdministrationShells = aasRepo.getAllAas(PaginationInfo.NO_LIMIT).getResult(); + Collection assetAdministrationShells = aasRepo.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult(); Collection submodels = submodelRepo.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult(); Collection conceptDescriptions = conceptDescriptionRepo.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult(); diff --git a/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/feature/authorization/TestAuthorizedAasEnvironmentUpload.java b/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/feature/authorization/TestAuthorizedAasEnvironmentUpload.java index 3b39566dd..682e4a0db 100644 --- a/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/feature/authorization/TestAuthorizedAasEnvironmentUpload.java +++ b/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/feature/authorization/TestAuthorizedAasEnvironmentUpload.java @@ -41,6 +41,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.authorization.AccessTokenProvider; import org.eclipse.digitaltwin.basyx.authorization.DummyCredential; @@ -93,7 +94,7 @@ public void reset() throws FileNotFoundException, IOException { configureSecurityContext(); - Collection assetAdministrationShells = aasRepo.getAllAas(PaginationInfo.NO_LIMIT).getResult(); + Collection assetAdministrationShells = aasRepo.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult(); Collection submodels = submodelRepo.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult(); Collection conceptDescriptions = conceptDescriptionRepo.getAllConceptDescriptions(PaginationInfo.NO_LIMIT).getResult(); diff --git a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackendProvider.java b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackendProvider.java index 44860711d..9a7e0c204 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackendProvider.java +++ b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryBackendProvider.java @@ -28,8 +28,8 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; import org.eclipse.digitaltwin.basyx.aasrepository.backend.AasBackendProvider; import org.eclipse.digitaltwin.basyx.common.backend.inmemory.core.InMemoryCrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; /** @@ -43,8 +43,8 @@ public class AasInMemoryBackendProvider implements AasBackendProvider { @Override - public CrudRepository getCrudRepository() { - return new InMemoryCrudRepository(AssetAdministrationShell::getId); + public BaSyxCrudRepository getCrudRepository() { + return new InMemoryCrudRepository(AssetAdministrationShell::getId, new AasInMemoryFilterResolution()); } } diff --git a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryFilterResolution.java b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryFilterResolution.java new file mode 100644 index 000000000..b5ce7c940 --- /dev/null +++ b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/AasInMemoryFilterResolution.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasrepository.backend.inmemory; + +import java.util.List; +import java.util.function.Predicate; + +import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; +import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation; +import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; +import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; +import org.eclipse.digitaltwin.basyx.core.FilterResolution; +import org.eclipse.digitaltwin.basyx.core.Filter; + +/** + * This class provides an in-memory implementation of the + * {@link FilterResolution} interface for filtering + * {@link AssetAdministrationShell} based on specified criteria. + * + *

+ * It uses a {@link Predicate} to apply the filter conditions directly on + * instances of {@link AssetAdministrationShell}. This approach is suitable for + * scenarios where filtering needs to be performed in memory, for example, on + * collections already loaded from a data source. + * + *

+ * The filter criteria are derived from an {@link AasFilter} object, which + * contains various filtering attributes, including: + *

    + *
  • AssetKind - the type of asset (e.g., INSTANCE, TYPE, or + * NOT_APPLICABLE)
  • + *
  • AssetType - the specific type of asset
  • + *
  • Ids - a list of asset administration shell IDs to filter by
  • + *
  • IdShort
  • + *
  • SpecificAssetIds - a list of specific asset identifiers (name and value + * pairs)
  • + *
+ * + *

+ * Each attribute of the filter is matched to the corresponding properties of + * {@link AssetAdministrationShell} objects, and the filtering logic ensures + * that only the objects satisfying all specified criteria are returned. + * + * + * @see FilterResolution + * @see AasFilter + * @see AssetAdministrationShell + * + * @author danish + */ +public class AasInMemoryFilterResolution implements FilterResolution> { + + @Override + public Predicate applyFilter(Filter filter) { + return aas -> { + + if (filter == null) + return true; + + if (!(filter instanceof AasFilter)) + throw new RuntimeException("The provided filter is not of type AasFilter"); + + AasFilter aasFilter = (AasFilter) filter; + + AssetKind filterKind = aasFilter.getAssetKind(); + String filterAssetType = aasFilter.getAssetType(); + List filterAasIds = aasFilter.getIds(); + String filterIdShort = aasFilter.getIdShort(); + List filterSpecificAssetIds = aasFilter.getSpecificAssetIds(); + + AssetInformation targetAssetInformation = aas.getAssetInformation(); + + AssetKind targetKind = null; + String targetAssetType = null; + List targetSpecificAssetIds = null; + + if (targetAssetInformation != null) { + targetKind = targetAssetInformation.getAssetKind(); + targetAssetType = targetAssetInformation.getAssetType(); + targetSpecificAssetIds = targetAssetInformation.getSpecificAssetIds(); + } + + String targetAasId = aas.getId(); + String targetIdShort = aas.getIdShort(); + + return matchesId(filterAasIds, targetAasId) && matchesIdShort(filterIdShort, targetIdShort) && matchesAssetInfo(filterKind, targetKind, filterAssetType, targetAssetType) + && matchesSpecificAssetId(filterSpecificAssetIds, targetSpecificAssetIds); + + }; + } + + private boolean matchesId(List filterAasIds, String targetAasId) { + + if (filterAasIds == null || filterAasIds.isEmpty()) + return true; + + return filterAasIds.contains(targetAasId); + } + + private boolean matchesIdShort(String filterIdShort, String targetIdShort) { + + if (filterIdShort == null || filterIdShort.isBlank()) + return true; + + if (targetIdShort == null) + return false; + + return filterIdShort.equals(targetIdShort); + } + + private boolean matchesSpecificAssetId(List filterSpecificAssetIds, List targetSpecificAssetIds) { + + if (filterSpecificAssetIds == null || filterSpecificAssetIds.isEmpty()) + return true; + + if (targetSpecificAssetIds == null) + return false; + + return filterSpecificAssetIds.stream().allMatch(filterAsset -> targetSpecificAssetIds.stream().anyMatch(targetAsset -> targetAsset.getName().equals(filterAsset.getName()) && targetAsset.getValue().equals(filterAsset.getValue()))); + } + + private boolean matchesAssetInfo(AssetKind filterAssetKind, AssetKind targetAssetKind, String filterAssetType, String targetAssetType) { + + if (filterAssetKind == null) + return true; + + if (filterAssetKind == AssetKind.INSTANCE) + return targetAssetKind == AssetKind.INSTANCE; + else if (filterAssetKind == AssetKind.NOT_APPLICABLE) + return targetAssetKind == null; + else if (targetAssetKind != AssetKind.TYPE) + return false; + else { + if (filterAssetType == null) + return true; + + return filterAssetType.equals(targetAssetType); + } + } + +} diff --git a/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/TestInMemoryAasFilterResolution.java b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/TestInMemoryAasFilterResolution.java new file mode 100644 index 000000000..92c4524ec --- /dev/null +++ b/basyx.aasrepository/basyx.aasrepository-backend-inmemory/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/inmemory/TestInMemoryAasFilterResolution.java @@ -0,0 +1,265 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasrepository.backend.inmemory; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Predicate; + +import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; +import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation; +import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; +import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetAdministrationShell; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetInformation; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSpecificAssetId; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; +import org.eclipse.digitaltwin.basyx.core.Filter; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests the {@link AasInMemoryFilterResolution} + * + * @author danish + */ +public class TestInMemoryAasFilterResolution { + + private AasInMemoryFilterResolution filterResolution; + private AssetAdministrationShell aas; + private AssetInformation assetInformation; + + @Before + public void setUp() { + filterResolution = new AasInMemoryFilterResolution(); + + assetInformation = new DefaultAssetInformation(); + aas = new DefaultAssetAdministrationShell(); + aas.setAssetInformation(assetInformation); + } + + @Test + public void nullFilter() { + Predicate predicate = filterResolution.applyFilter(null); + assertTrue(predicate.test(aas)); + } + + @Test(expected = RuntimeException.class) + public void invalidFilterType() { + Filter invalidFilter = new Filter() { + + @Override + public List getIds() { + return null; + } + }; + + Predicate predicate = filterResolution.applyFilter(invalidFilter); + predicate.test(aas); + } + + @Test + public void filterWithMatchingId() { + AasFilter filter = new AasFilter(); + filter.setIds(Arrays.asList("matching-id")); + aas.setId("matching-id"); + + Predicate predicate = filterResolution.applyFilter(filter); + assertTrue(predicate.test(aas)); + } + + @Test + public void filterWithNonMatchingId() { + AasFilter filter = new AasFilter(); + filter.setIds(Arrays.asList("non-matching-id")); + aas.setId("some-other-id"); + + Predicate predicate = filterResolution.applyFilter(filter); + assertFalse(predicate.test(aas)); + } + + @Test + public void filterWithMatchingIdShort() { + AasFilter filter = new AasFilter(); + filter.setIdShort("matching-id-short"); + aas.setIdShort("matching-id-short"); + + Predicate predicate = filterResolution.applyFilter(filter); + assertTrue(predicate.test(aas)); + } + + @Test + public void filterWithNonMatchingIdShort() { + AasFilter filter = new AasFilter(); + filter.setIdShort("filter-id-short"); + aas.setIdShort("other-id-short"); + + Predicate predicate = filterResolution.applyFilter(filter); + assertFalse(predicate.test(aas)); + } + + @Test + public void filterWithMatchingAssetKindAndType() { + AasFilter filter = new AasFilter(); + filter.setAssetKind(AssetKind.INSTANCE); + filter.setAssetType("asset-type"); + + assetInformation.setAssetKind(AssetKind.INSTANCE); + assetInformation.setAssetType("asset-type"); + + Predicate predicate = filterResolution.applyFilter(filter); + assertTrue(predicate.test(aas)); + } + + @Test + public void filterWithNonMatchingAssetKindAndType() { + AasFilter filter = new AasFilter(); + filter.setAssetKind(AssetKind.INSTANCE); + filter.setAssetType("filter-type"); + + assetInformation.setAssetKind(AssetKind.TYPE); + assetInformation.setAssetType("other-type"); + + Predicate predicate = filterResolution.applyFilter(filter); + assertFalse(predicate.test(aas)); + } + + @Test + public void filterWithMatchingSpecificAssetIds() { + SpecificAssetId filterSpecificId = new DefaultSpecificAssetId(); + filterSpecificId.setName("filter-name"); + filterSpecificId.setValue("filter-value"); + + SpecificAssetId targetSpecificId = new DefaultSpecificAssetId(); + targetSpecificId.setName("filter-name"); + targetSpecificId.setValue("filter-value"); + + AasFilter filter = new AasFilter(); + filter.setSpecificAssetIds(Collections.singletonList(filterSpecificId)); + assetInformation.setSpecificAssetIds(Collections.singletonList(targetSpecificId)); + + Predicate predicate = filterResolution.applyFilter(filter); + assertTrue(predicate.test(aas)); + } + + @Test + public void filterWithNonMatchingSpecificAssetIds() { + SpecificAssetId filterSpecificId = new DefaultSpecificAssetId(); + filterSpecificId.setName("filter-name"); + filterSpecificId.setValue("filter-value"); + + SpecificAssetId targetSpecificId = new DefaultSpecificAssetId(); + targetSpecificId.setName("different-name"); + targetSpecificId.setValue("different-value"); + + AasFilter filter = new AasFilter(); + filter.setSpecificAssetIds(Collections.singletonList(filterSpecificId)); + assetInformation.setSpecificAssetIds(Collections.singletonList(targetSpecificId)); + + Predicate predicate = filterResolution.applyFilter(filter); + assertFalse(predicate.test(aas)); + } + + @Test + public void filterWithNullSpecificAssetIds() { + AasFilter filter = new AasFilter(); + filter.setSpecificAssetIds(null); + + Predicate predicate = filterResolution.applyFilter(filter); + assertTrue(predicate.test(aas)); + } + + @Test + public void filterWithEmptySpecificAssetIds() { + AasFilter filter = new AasFilter(); + filter.setSpecificAssetIds(Collections.emptyList()); + + Predicate predicate = filterResolution.applyFilter(filter); + assertTrue(predicate.test(aas)); + } + + @Test + public void allValuesMatch() { + AasFilter filter = new AasFilter(); + filter.setIds(Arrays.asList("matching-id1", "matching-id2")); + filter.setIdShort("matching-id-short"); + filter.setAssetKind(AssetKind.INSTANCE); + filter.setAssetType("asset-type"); + + SpecificAssetId filterSpecificId = new DefaultSpecificAssetId(); + filterSpecificId.setName("specific-id-name"); + filterSpecificId.setValue("specific-id-value"); + filter.setSpecificAssetIds(Collections.singletonList(filterSpecificId)); + + aas.setId("matching-id2"); + aas.setIdShort("matching-id-short"); + + assetInformation.setAssetKind(AssetKind.INSTANCE); + assetInformation.setAssetType("asset-type"); + + SpecificAssetId targetSpecificId = new DefaultSpecificAssetId(); + targetSpecificId.setName("specific-id-name"); + targetSpecificId.setValue("specific-id-value"); + assetInformation.setSpecificAssetIds(Collections.singletonList(targetSpecificId)); + + Predicate predicate = filterResolution.applyFilter(filter); + assertTrue(predicate.test(aas)); + } + + @Test + public void oneValueChanged() { + AasFilter filter = new AasFilter(); + filter.setIds(Arrays.asList("matching-id")); + filter.setIdShort("matching-id-short"); + filter.setAssetKind(AssetKind.INSTANCE); + filter.setAssetType("asset-type"); + + SpecificAssetId filterSpecificId = new DefaultSpecificAssetId(); + filterSpecificId.setName("specific-id-name"); + filterSpecificId.setValue("specific-id-value"); + filter.setSpecificAssetIds(Collections.singletonList(filterSpecificId)); + + aas.setId("matching-id"); + aas.setIdShort("matching-id-short"); + + assetInformation.setAssetKind(AssetKind.INSTANCE); + assetInformation.setAssetType("asset-type"); + + SpecificAssetId targetSpecificId = new DefaultSpecificAssetId(); + targetSpecificId.setName("specific-id-name"); + targetSpecificId.setValue("specific-id-value"); + assetInformation.setSpecificAssetIds(Collections.singletonList(targetSpecificId)); + + filter.setIdShort("non-matching-id-short"); + + Predicate predicate = filterResolution.applyFilter(filter); + assertFalse(predicate.test(aas)); + } + +} diff --git a/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBBackendProvider.java b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBBackendProvider.java index 65ca1d6b2..b055f4e6e 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBBackendProvider.java +++ b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBBackendProvider.java @@ -28,45 +28,62 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; import org.eclipse.digitaltwin.basyx.aasrepository.backend.AasBackendProvider; import org.eclipse.digitaltwin.basyx.common.mongocore.BasyxMongoMappingContext; +import org.eclipse.digitaltwin.basyx.common.mongocore.MongoDBCrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.index.Index; +import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation; -import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; -import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; /** * * MongoDB Backend Provider for the AAS * - * @author mateusmolina, despen + * @author mateusmolina, despen, danish */ @ConditionalOnExpression("'${basyx.backend}'.equals('MongoDB')") @Component public class AasMongoDBBackendProvider implements AasBackendProvider { - + private BasyxMongoMappingContext mappingContext; - + private MongoTemplate template; - + @Autowired public AasMongoDBBackendProvider(BasyxMongoMappingContext mappingContext, @Value("${basyx.aasrepository.mongodb.collectionName:aas-repo}") String collectionName, MongoTemplate template) { super(); this.mappingContext = mappingContext; this.template = template; - + +// configureIndices(this.template); + mappingContext.addEntityMapping(AssetAdministrationShell.class, collectionName); } @Override - public CrudRepository getCrudRepository() { + public BaSyxCrudRepository getCrudRepository() { @SuppressWarnings("unchecked") MongoPersistentEntity entity = (MongoPersistentEntity) mappingContext.getPersistentEntity(AssetAdministrationShell.class); - - return new SimpleMongoRepository<>(new MappingMongoEntityInformation<>(entity), template); + + return new MongoDBCrudRepository(new MappingMongoEntityInformation<>(entity), template, AssetAdministrationShell.class, new AasMongoDBFilterResolution()); + } + + private void configureIndices(MongoTemplate template) { + IndexOperations ops = template.indexOps(AssetAdministrationShell.class); + + ops.ensureIndex(new Index(AasMongoDBFilterResolution.ASSET_KIND, Direction.ASC)); + ops.ensureIndex(new Index(AasMongoDBFilterResolution.ASSET_TYPE, Direction.ASC)); + ops.ensureIndex(new Index(AasMongoDBFilterResolution.IDENTIFIER, Direction.ASC)); + + ops.ensureIndex(new Index(AasMongoDBFilterResolution.ID_SHORT, Direction.ASC)); + + ops.ensureIndex(new Index().on(AasMongoDBFilterResolution.SPECIFIC_ASSET_ID_NAME, Direction.ASC).on(AasMongoDBFilterResolution.SPECIFIC_ASSET_ID_VALUE, Direction.ASC)); } } diff --git a/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBFilterResolution.java b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBFilterResolution.java new file mode 100644 index 000000000..d7484abb4 --- /dev/null +++ b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBFilterResolution.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasrepository.backend.mongodb; + +import java.util.List; + +import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; +import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; +import org.eclipse.digitaltwin.basyx.core.FilterResolution; +import org.eclipse.digitaltwin.basyx.core.Filter; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; +import org.springframework.data.mongodb.core.aggregation.MatchOperation; +import org.springframework.data.mongodb.core.query.Criteria; + +/** + * This class implements the {@link FilterResolution} interface to provide a + * MongoDB-based filter resolution for {@link AssetAdministrationShell}. + * + *

+ * It constructs a MongoDB {@link AggregationOperation} with filtering + * conditions based on the provided {@link AasFilter}. This approach is designed + * for scenarios where filtering should be performed within MongoDB, allowing + * efficient querying directly on the database layer. + * + *

+ * The filtering criteria supported by this class include: + *

    + *
  • AssetKind - allows filtering by specific asset kinds (e.g., INSTANCE, + * TYPE, NOT_APPLICABLE)
  • + *
  • AssetType - filters by the type of asset as a string
  • + *
  • Ids - matches a list of asset administration shell IDs using MongoDB's + * {@code $in} operator
  • + *
  • IdShort
  • + *
  • SpecificAssetIds - matches specific asset identifier name-value pairs + * using {@code $elemMatch}
  • + *
+ * + *

+ * The criteria construction ensures that the generated MongoDB query is as flat + * as possible, minimizing unnecessary nesting for performance efficiency. In + * addition, the class performs type checks for ID fields, ensuring + * compatibility with MongoDB's expected formats. + * + * @see FilterResolution + * @see AasFilter + * @see AggregationOperation + * @see AssetAdministrationShell + * + * @author danish + */ +public class AasMongoDBFilterResolution implements FilterResolution { + + public static final String ASSET_TYPE = "assetInformation.assetType"; + public static final String ASSET_KIND = "assetInformation.assetKind"; + public static final String IDENTIFIER = "_id"; + public static final String ID_SHORT = "idShort"; + public static final String SPECIFIC_ASSET_ID_ARRAY = "assetInformation.specificAssetIds"; + public static final String SPECIFIC_ASSET_ID_NAME = "name"; + public static final String SPECIFIC_ASSET_ID_VALUE = "value"; + + @Override + public AggregationOperation applyFilter(Filter filter) { + + Criteria criteria = new Criteria(); + + if (filter == null) + return new MatchOperation(criteria); + + if (!(filter instanceof AasFilter)) + throw new RuntimeException("The provided filter is not of type AasFilter"); + + AasFilter aasFilter = (AasFilter) filter; + + AssetKind kind = aasFilter.getAssetKind(); + if (kind == AssetKind.NOT_APPLICABLE) + criteria.and(ASSET_KIND).exists(false); + else if (kind != null) + criteria.and(ASSET_KIND).is(kind.name()); + + String assetType = aasFilter.getAssetType(); + if (assetType != null) + criteria.and(ASSET_TYPE).is(assetType); + + List aasIds = aasFilter.getIds(); + if (aasIds != null && !aasIds.isEmpty()) + criteria.and(IDENTIFIER).in(aasIds); + + String idShort = aasFilter.getIdShort(); + if (idShort != null && !idShort.isBlank()) + criteria.and(ID_SHORT).is(idShort); + + List specificAssetIds = aasFilter.getSpecificAssetIds(); + if (specificAssetIds != null && !specificAssetIds.isEmpty()) { + Criteria[] specificCriteriaArray = specificAssetIds.stream() + .map(specId -> Criteria.where(SPECIFIC_ASSET_ID_ARRAY).elemMatch(Criteria.where(SPECIFIC_ASSET_ID_NAME).is(specId.getName()).and(SPECIFIC_ASSET_ID_VALUE).is(specId.getValue()))).toArray(Criteria[]::new); + criteria.andOperator(specificCriteriaArray); + } + + return new MatchOperation(criteria); + } +} diff --git a/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/TestAasMongoDBFilterResolution.java b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/TestAasMongoDBFilterResolution.java new file mode 100644 index 000000000..8c2b9e90b --- /dev/null +++ b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/TestAasMongoDBFilterResolution.java @@ -0,0 +1,119 @@ +package org.eclipse.digitaltwin.basyx.aasrepository.backend.mongodb; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.bson.Document; +import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; +import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSpecificAssetId; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; +import org.eclipse.digitaltwin.basyx.core.Filter; +import org.junit.Before; +import org.junit.Test; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; +import org.springframework.data.mongodb.core.aggregation.MatchOperation; + +public class TestAasMongoDBFilterResolution { + + private AasMongoDBFilterResolution filterResolution; + + @Before + public void setUp() { + filterResolution = new AasMongoDBFilterResolution(); + } + + @Test(expected = RuntimeException.class) + public void testInvalidFilterType() { + Filter invalidFilter = new Filter() { + @Override + public List getIds() { + return null; + } + }; + + filterResolution.applyFilter(invalidFilter); + } + + @Test + public void testAllValuesMatch() { + AasFilter filter = prepareFilter(); + + AggregationOperation operation = filterResolution.applyFilter(filter); + assertTrue(operation instanceof MatchOperation); + + Document queryDocument = ((MatchOperation) operation).toDocument(Aggregation.DEFAULT_CONTEXT); + Document matchDocument = (Document) queryDocument.get("$match"); + + assertEquals("INSTANCE", matchDocument.get("assetInformation.assetKind")); + assertEquals("asset-type", matchDocument.get("assetInformation.assetType")); + assertEquals("matching-id-short", matchDocument.get("idShort")); + + Document idCondition = (Document) matchDocument.get("_id"); + assertNotNull(idCondition); + assertEquals(Collections.singletonList("matching-id"), idCondition.get("$in")); + + @SuppressWarnings("unchecked") + List andConditions = (List) matchDocument.get("$and"); + assertNotNull(andConditions); + assertEquals(1, andConditions.size()); + + Document specificAssetIdsCondition = andConditions.get(0); + Document elemMatch = (Document) ((Document) specificAssetIdsCondition.get("assetInformation.specificAssetIds")).get("$elemMatch"); + assertNotNull(elemMatch); + + assertEquals("specific-id-name", elemMatch.get("name")); + assertEquals("specific-id-value", elemMatch.get("value")); + } + + @Test + public void testOneValueChanged() { + AasFilter filter = prepareFilter(); + filter.setAssetType("non-matching-type"); + + AggregationOperation operation = filterResolution.applyFilter(filter); + assertTrue(operation instanceof MatchOperation); + + Document queryDocument = ((MatchOperation) operation).toDocument(Aggregation.DEFAULT_CONTEXT); + Document matchDocument = (Document) queryDocument.get("$match"); + + assertEquals("INSTANCE", matchDocument.get("assetInformation.assetKind")); + assertEquals("non-matching-type", matchDocument.get("assetInformation.assetType")); + assertEquals("matching-id-short", matchDocument.get("idShort")); + + Document idCondition = (Document) matchDocument.get("_id"); + assertNotNull(idCondition); + assertEquals(Collections.singletonList("matching-id"), idCondition.get("$in")); + + @SuppressWarnings("unchecked") + List andConditions = (List) matchDocument.get("$and"); + assertNotNull(andConditions); + assertEquals(1, andConditions.size()); + + Document specificAssetIdsCondition = andConditions.get(0); + Document elemMatch = (Document) ((Document) specificAssetIdsCondition.get("assetInformation.specificAssetIds")).get("$elemMatch"); + assertNotNull(elemMatch); + + assertEquals("specific-id-name", elemMatch.get("name")); + assertEquals("specific-id-value", elemMatch.get("value")); + } + + private AasFilter prepareFilter() { + AasFilter filter = new AasFilter(); + filter.setIds(Arrays.asList("matching-id")); + filter.setIdShort("matching-id-short"); + filter.setAssetKind(AssetKind.INSTANCE); + filter.setAssetType("asset-type"); + + SpecificAssetId filterSpecificId = new DefaultSpecificAssetId(); + filterSpecificId.setName("specific-id-name"); + filterSpecificId.setValue("specific-id-value"); + filter.setSpecificAssetIds(Collections.singletonList(filterSpecificId)); + + return filter; + } +} diff --git a/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/AasBackendProvider.java b/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/AasBackendProvider.java index 2fe0fd33a..d8fcd6248 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/AasBackendProvider.java +++ b/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/AasBackendProvider.java @@ -25,7 +25,7 @@ package org.eclipse.digitaltwin.basyx.aasrepository.backend; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; -import org.springframework.data.repository.CrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; /** * Backend provider for the AAS @@ -33,5 +33,5 @@ * @author mateusmolina, despen */ public interface AasBackendProvider { - public CrudRepository getCrudRepository(); + public BaSyxCrudRepository getCrudRepository(); } diff --git a/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java b/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java index f78c7e045..66260a3de 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudAasRepository.java @@ -27,7 +27,6 @@ import java.io.File; import java.io.InputStream; import java.util.List; -import java.util.TreeMap; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -37,13 +36,15 @@ import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasservice.AasService; import org.eclipse.digitaltwin.basyx.aasservice.AasServiceFactory; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; +import org.eclipse.digitaltwin.basyx.core.Filter; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.IdentificationMismatchException; import org.eclipse.digitaltwin.basyx.core.exceptions.MissingIdentifierException; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; -import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport; +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationUtilities; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.repository.CrudRepository; @@ -51,12 +52,12 @@ * Default Implementation for the {@link AasRepository} based on Spring * {@link CrudRepository} * - * @author mateusmolina, despen, zhangzai, kammognie + * @author mateusmolina, despen, zhangzai, kammognie, danish * */ public class CrudAasRepository implements AasRepository { - private CrudRepository aasBackend; + private BaSyxCrudRepository aasBackend; private AasServiceFactory aasServiceFactory; @@ -74,16 +75,14 @@ public CrudAasRepository(AasBackendProvider aasBackendProvider, AasServiceFactor } @Override - public CursorResult> getAllAas(PaginationInfo pInfo) { + public CursorResult> getAllAas(PaginationInfo pInfo, Filter filter) { - Iterable iterable = aasBackend.findAll(); - List allAas = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); + Iterable iterableAas = aasBackend.findAll(pInfo, filter); + List filteredAas = StreamSupport.stream(iterableAas.spliterator(), false).collect(Collectors.toList()); - TreeMap aasMap = allAas.stream().collect(Collectors.toMap(AssetAdministrationShell::getId, aas -> aas, (a, b) -> a, TreeMap::new)); - - PaginationSupport paginationSupport = new PaginationSupport<>(aasMap, AssetAdministrationShell::getId); - - return paginationSupport.getPaged(pInfo); + String cursor = PaginationUtilities.resolveCursor(pInfo, filteredAas, AssetAdministrationShell::getId); + + return new CursorResult<>(cursor, filteredAas); } @Override diff --git a/basyx.aasrepository/basyx.aasrepository-client/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/client/ConnectedAasRepository.java b/basyx.aasrepository/basyx.aasrepository-client/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/client/ConnectedAasRepository.java index c302adc52..eea556181 100644 --- a/basyx.aasrepository/basyx.aasrepository-client/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/client/ConnectedAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-client/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/client/ConnectedAasRepository.java @@ -37,6 +37,7 @@ import org.eclipse.digitaltwin.basyx.aasrepository.client.internal.AssetAdministrationShellRepositoryApi; import org.eclipse.digitaltwin.basyx.aasservice.client.ConnectedAasService; import org.eclipse.digitaltwin.basyx.client.internal.ApiException; +import org.eclipse.digitaltwin.basyx.core.Filter; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.IdentificationMismatchException; @@ -77,7 +78,7 @@ public String getBaseUrl() { } @Override - public CursorResult> getAllAas(PaginationInfo pInfo) { + public CursorResult> getAllAas(PaginationInfo pInfo, Filter filter) { String encodedCursor = pInfo.getCursor() == null ? null : Base64UrlEncoder.encode(pInfo.getCursor()); return repoApi.getAllAssetAdministrationShells(null, null, pInfo.getLimit(), encodedCursor); } diff --git a/basyx.aasrepository/basyx.aasrepository-client/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/client/TestAuthorizedConnectedAasRepository.java b/basyx.aasrepository/basyx.aasrepository-client/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/client/TestAuthorizedConnectedAasRepository.java index de85e50fa..55a0fe6c1 100644 --- a/basyx.aasrepository/basyx.aasrepository-client/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/client/TestAuthorizedConnectedAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-client/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/client/TestAuthorizedConnectedAasRepository.java @@ -30,6 +30,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepositorySuite; import org.eclipse.digitaltwin.basyx.aasrepository.DummyAasFactory; @@ -45,6 +46,7 @@ import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; import org.springframework.boot.SpringApplication; @@ -75,7 +77,7 @@ public void removeAasFromRepo() throws FileNotFoundException, IOException { TestAuthorizedConnectedAasService.configureSecurityContext(TestAuthorizedConnectedAasService.getTokenProvider()); AasRepository repo = appContext.getBean(AasRepository.class); - repo.getAllAas(PaginationInfo.NO_LIMIT).getResult().stream().map(s -> s.getId()).forEach(repo::deleteAas); + repo.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().stream().map(s -> s.getId()).forEach(repo::deleteAas); SecurityContextHolder.clearContext(); } @@ -101,6 +103,34 @@ public void sendUnauthorizedRequest() throws IOException { assertEquals(HttpStatus.UNAUTHORIZED.value(), exception.getCode()); } + + @Override + @Test + @Ignore + public void retrieveAllAasWithSpecificAssetIdAndIdShortFiltering() throws Exception { + //TODO: Clients doesn't support filtering, remove this when client has the functionality + } + + @Override + @Test + @Ignore + public void retrieveAllAasWithIdFiltering() throws Exception { + //TODO: Clients doesn't support filtering, remove this when client has the functionality + } + + @Override + @Test + @Ignore + public void retrieveAllAasWithIdShortFiltering() throws Exception { + //TODO: Clients doesn't support filtering, remove this when client has the functionality + } + + @Override + @Test + @Ignore + public void retrieveAllAasWithSpecificAssetIdFiltering() throws Exception { + //TODO: Clients doesn't support filtering, remove this when client has the functionality + } @Override protected AasRepository getAasRepository() { diff --git a/basyx.aasrepository/basyx.aasrepository-client/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/client/TestConnectedAasRepository.java b/basyx.aasrepository/basyx.aasrepository-client/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/client/TestConnectedAasRepository.java index 1ffce0038..c6e70ba45 100644 --- a/basyx.aasrepository/basyx.aasrepository-client/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/client/TestConnectedAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-client/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/client/TestConnectedAasRepository.java @@ -29,6 +29,7 @@ import java.io.IOException; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepositorySuite; import org.eclipse.digitaltwin.basyx.aasrepository.http.DummyAasRepositoryComponent; @@ -38,6 +39,8 @@ import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.ConfigurableApplicationContext; @@ -61,13 +64,41 @@ public static void startAASRepo() throws Exception { @After public void removeAasFromRepo() { AasRepository repo = appContext.getBean(AasRepository.class); - repo.getAllAas(PaginationInfo.NO_LIMIT).getResult().stream().map(s -> s.getId()).forEach(repo::deleteAas); + repo.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().stream().map(s -> s.getId()).forEach(repo::deleteAas); } @AfterClass public static void shutdownAASRepo() { appContext.close(); } + + @Override + @Test + @Ignore + public void retrieveAllAasWithSpecificAssetIdAndIdShortFiltering() throws Exception { + //TODO: Clients doesn't support filtering, remove this when client has the functionality + } + + @Override + @Test + @Ignore + public void retrieveAllAasWithIdFiltering() throws Exception { + //TODO: Clients doesn't support filtering, remove this when client has the functionality + } + + @Override + @Test + @Ignore + public void retrieveAllAasWithIdShortFiltering() throws Exception { + //TODO: Clients doesn't support filtering, remove this when client has the functionality + } + + @Override + @Test + @Ignore + public void retrieveAllAasWithSpecificAssetIdFiltering() throws Exception { + //TODO: Clients doesn't support filtering, remove this when client has the functionality + } @Override protected AasRepository getAasRepository() { diff --git a/basyx.aasrepository/basyx.aasrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/AasFilter.java b/basyx.aasrepository/basyx.aasrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/AasFilter.java new file mode 100644 index 000000000..0834a512d --- /dev/null +++ b/basyx.aasrepository/basyx.aasrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/AasFilter.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.aasrepository; + +import java.util.List; + +import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; +import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; +import org.eclipse.digitaltwin.basyx.core.Filter; + +/** + * An implementation of {@link Filter} for the AAS. It defines attributes for + * filter operations. + * + * @author danish + */ +public class AasFilter implements Filter { + + private List aasIds; + private String idShort; + private AssetKind assetKind; + private String assetType; + private List specificAssetIds; + + @Override + public List getIds() { + return aasIds; + } + + public String getIdShort() { + return idShort; + } + + public void setIds(List aasIds) { + this.aasIds = aasIds; + } + + public AssetKind getAssetKind() { + return assetKind; + } + + public void setAssetKind(AssetKind assetKind) { + this.assetKind = assetKind; + } + + public String getAssetType() { + return assetType; + } + + public void setAssetType(String assetType) { + this.assetType = assetType; + } + + public List getSpecificAssetIds() { + return specificAssetIds; + } + + public void setSpecificAssetIds(List specificAssetIds) { + this.specificAssetIds = specificAssetIds; + } + + public void setIdShort(String idShort) { + this.idShort = idShort; + } + +} diff --git a/basyx.aasrepository/basyx.aasrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/AasRepository.java b/basyx.aasrepository/basyx.aasrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/AasRepository.java index c6550cc67..9611ab071 100644 --- a/basyx.aasrepository/basyx.aasrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/AasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/AasRepository.java @@ -31,6 +31,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation; import org.eclipse.digitaltwin.aas4j.v3.model.Reference; +import org.eclipse.digitaltwin.basyx.core.Filter; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.MissingIdentifierException; @@ -50,7 +51,7 @@ public interface AasRepository { * * @return a list of all found Asset Administration Shells */ - public CursorResult> getAllAas(PaginationInfo pInfo); + public CursorResult> getAllAas(PaginationInfo pInfo, Filter filter); /** * Retrieves a specific AAS diff --git a/basyx.aasrepository/basyx.aasrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/AasRepositorySuite.java b/basyx.aasrepository/basyx.aasrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/AasRepositorySuite.java index 6e50cf903..08dd50618 100644 --- a/basyx.aasrepository/basyx.aasrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/AasRepositorySuite.java +++ b/basyx.aasrepository/basyx.aasrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/AasRepositorySuite.java @@ -25,6 +25,7 @@ package org.eclipse.digitaltwin.basyx.aasrepository; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; @@ -47,7 +48,7 @@ /** * Testsuite for implementations of the AasRepository interface * - * @author schnicke, kammognie, mateusmolina, despen + * @author schnicke, kammognie, mateusmolina, despen, danish * */ public abstract class AasRepositorySuite extends AasServiceSuite { @@ -72,9 +73,91 @@ public void allAasRetrieval() throws Exception { List expected = DummyAasFactory.createShells(); AasRepository aasRepo = getAasRepository(expected); PaginationInfo pInfo = new PaginationInfo(2, null); - Collection coll = aasRepo.getAllAas(pInfo).getResult(); + AasFilter aasFilter = new AasFilter(); + Collection coll = aasRepo.getAllAas(pInfo, aasFilter).getResult(); assertEquals(expected, coll); } + + @Test + public void retrieveAllAasWithNoFiltering() throws Exception { + List expected = DummyAasFactory.createShellsForFiltering(); + AasRepository aasRepo = getAasRepository(expected); + PaginationInfo pInfo = PaginationInfo.NO_LIMIT; + AasFilter aasFilter = new AasFilter(); + Collection coll = aasRepo.getAllAas(pInfo, aasFilter).getResult(); + + assertTrue(expected.containsAll(coll)); + assertTrue(coll.containsAll(expected)); + } + + @Test + public void retrieveAllAasWithIdShortFiltering() throws Exception { + List allShells = DummyAasFactory.createShellsForFiltering(); + AasRepository aasRepo = getAasRepository(allShells); + + List expectedShells = DummyAasFactory.createShellsWithSameIdShort(); + + PaginationInfo pInfo = PaginationInfo.NO_LIMIT; + AasFilter aasFilter = new AasFilter(); + aasFilter.setIdShort(DummyAasFactory.DUMMY_ID_SHORT); + + Collection coll = aasRepo.getAllAas(pInfo, aasFilter).getResult(); + + assertTrue(expectedShells.containsAll(coll)); + assertTrue(coll.containsAll(expectedShells)); + } + + @Test + public void retrieveAllAasWithSpecificAssetIdFiltering() throws Exception { + List allShells = DummyAasFactory.createShellsForFiltering(); + AasRepository aasRepo = getAasRepository(allShells); + + List expectedShells = DummyAasFactory.getAllShellsWithSpecificAssetIds(); + + PaginationInfo pInfo = PaginationInfo.NO_LIMIT; + AasFilter aasFilter = new AasFilter(); + aasFilter.setSpecificAssetIds(DummyAasFactory.getSpecificAssetIdsForFiltering()); + + Collection coll = aasRepo.getAllAas(pInfo, aasFilter).getResult(); + + assertTrue(expectedShells.containsAll(coll)); + assertTrue(coll.containsAll(expectedShells)); + } + + @Test + public void retrieveAllAasWithSpecificAssetIdAndIdShortFiltering() throws Exception { + List allShells = DummyAasFactory.createShellsForFiltering(); + AasRepository aasRepo = getAasRepository(allShells); + + List expectedShells = Arrays.asList(DummyAasFactory.getShellWithIdShortAndSpecificAssetId()); + + PaginationInfo pInfo = PaginationInfo.NO_LIMIT; + AasFilter aasFilter = new AasFilter(); + aasFilter.setIdShort(DummyAasFactory.DUMMY_ID_SHORT); + aasFilter.setSpecificAssetIds(DummyAasFactory.getSpecificAssetIdsForFiltering()); + + Collection coll = aasRepo.getAllAas(pInfo, aasFilter).getResult(); + + assertTrue(expectedShells.containsAll(coll)); + assertTrue(coll.containsAll(expectedShells)); + } + + @Test + public void retrieveAllAasWithIdFiltering() throws Exception { + List allShells = DummyAasFactory.createShellsForFiltering(); + AasRepository aasRepo = getAasRepository(allShells); + + List expectedShells = DummyAasFactory.createShells(); + + PaginationInfo pInfo = PaginationInfo.NO_LIMIT; + AasFilter aasFilter = new AasFilter(); + aasFilter.setIds(Arrays.asList(DummyAasFactory.AASWITHASSETINFORMATION_ID, DummyAasFactory.AASWITHSUBMODELREF_ID)); + + Collection coll = aasRepo.getAllAas(pInfo, aasFilter).getResult(); + + assertTrue(expectedShells.containsAll(coll)); + assertTrue(coll.containsAll(expectedShells)); + } @Test public void getAasByIdentifier() throws CollidingIdentifierException, ElementDoesNotExistException { @@ -222,7 +305,7 @@ public void getPaginatedAssetAdministrationShell() { List expected = DummyAasFactory.createShells(); AasRepository aasRepo = getAasRepository(expected); - CursorResult> result = aasRepo.getAllAas(new PaginationInfo(1, null)); + CursorResult> result = aasRepo.getAllAas(new PaginationInfo(1, null), new AasFilter()); List resultList = result.getResult(); assertEquals(1, resultList.size()); assertEquals(DummyAasFactory.AASWITHSUBMODELREF_ID, resultList.stream().findFirst().get().getId()); @@ -234,11 +317,11 @@ public void getPaginatedAssetAdministrationShellIterating() { AasRepository aasRepo = getAasRepository(expected); List retrieved = new ArrayList<>(); - CursorResult> result = aasRepo.getAllAas(new PaginationInfo(1, null)); + CursorResult> result = aasRepo.getAllAas(new PaginationInfo(1, null), new AasFilter()); retrieved.addAll(result.getResult()); String cursor = result.getCursor(); - result = aasRepo.getAllAas(new PaginationInfo(1, cursor)); + result = aasRepo.getAllAas(new PaginationInfo(1, cursor), new AasFilter()); retrieved.addAll(result.getResult()); assertEquals(expected, retrieved); diff --git a/basyx.aasrepository/basyx.aasrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/DummyAasFactory.java b/basyx.aasrepository/basyx.aasrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/DummyAasFactory.java index fb3188339..c9f71909d 100644 --- a/basyx.aasrepository/basyx.aasrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/DummyAasFactory.java +++ b/basyx.aasrepository/basyx.aasrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/DummyAasFactory.java @@ -26,6 +26,7 @@ package org.eclipse.digitaltwin.basyx.aasrepository; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -34,12 +35,15 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind; import org.eclipse.digitaltwin.aas4j.v3.model.KeyTypes; import org.eclipse.digitaltwin.aas4j.v3.model.Reference; +import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetAdministrationShell; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultAssetInformation; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultKey; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultReference; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSpecificAssetId; public class DummyAasFactory { + public static final String DUMMY_ID_SHORT = "dummyIdShort"; public static final String AASWITHSUBMODELREF_ID = "aas1/s"; public static final String AASWITHASSETINFORMATION_ID = "aas2"; @@ -48,6 +52,67 @@ public class DummyAasFactory { public static List createShells() { return Arrays.asList(createAasWithSubmodelReference(), createAasWithAssetInformation()); } + + public static List createShellsForFiltering() { + List shellsWithSameIdShort = createShellsWithSameIdShort(); + List shellsWithSpecificAssetIds = createShellsWithSpecificAssetIds(); + List shells = createShells(); + + List allShells = new ArrayList(); + allShells.addAll(shellsWithSameIdShort); + allShells.addAll(shellsWithSpecificAssetIds); + allShells.addAll(shells); + + return allShells; + } + + public static List createShellsWithSameIdShort() { + return Arrays.asList(createShell("aasId1", DUMMY_ID_SHORT, null), getShellWithIdShortAndSpecificAssetId()); + } + + public static AssetAdministrationShell getShellWithIdShortAndSpecificAssetId() { + List specificAssetIds = getSpecificAssetIdsForFiltering(); + + return createShell("aasId2", DUMMY_ID_SHORT, specificAssetIds); + } + + public static List createShellsWithSpecificAssetIds() { + + List specificAssetIds = getSpecificAssetIdsForFiltering(); + + return Arrays.asList(createShell("aasId3", "idShort1", specificAssetIds), createShell("aasId4", "idShort2", specificAssetIds)); + } + + public static List getAllShellsWithSpecificAssetIds() { + + List allShells = new ArrayList(); + allShells.addAll(createShellsWithSpecificAssetIds()); + allShells.add(getShellWithIdShortAndSpecificAssetId()); + + return allShells; + } + + public static List getSpecificAssetIdsForFiltering() { + return Arrays.asList(createSpecificAssetId("specificAssetId1_name", "specificAssetId1_value"), createSpecificAssetId("specificAssetId2_name", "specificAssetId2_value")); + } + + private static SpecificAssetId createSpecificAssetId(String name, String value) { + return new DefaultSpecificAssetId.Builder().name(name).value(value).build(); + } + + private static AssetAdministrationShell createShell(String id, String idShort, List specificAssetIds) { + DefaultAssetAdministrationShell.Builder builder = new DefaultAssetAdministrationShell.Builder() + .id(id).idShort(idShort); + + if (specificAssetIds != null) { + AssetInformation assetInformation = createDummyAssetInformation(); + assetInformation.setSpecificAssetIds(specificAssetIds); + builder.assetInformation(assetInformation); + } + + return builder.build(); + + } public static AssetAdministrationShell createAasWithSubmodelReference() { return new DefaultAssetAdministrationShell.Builder() diff --git a/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/AuthorizedAasRepository.java b/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/AuthorizedAasRepository.java index a4f128864..eb325d392 100644 --- a/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/AuthorizedAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-feature-authorization/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/authorization/AuthorizedAasRepository.java @@ -37,6 +37,7 @@ import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.authorization.rbac.Action; import org.eclipse.digitaltwin.basyx.authorization.rbac.RbacPermissionResolver; +import org.eclipse.digitaltwin.basyx.core.Filter; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.InsufficientPermissionException; @@ -61,12 +62,12 @@ public AuthorizedAasRepository(AasRepository decorated, RbacPermissionResolver> getAllAas(PaginationInfo pInfo) { + public CursorResult> getAllAas(PaginationInfo pInfo, Filter filter) { boolean isAuthorized = permissionResolver.hasPermission(Action.READ, new AasTargetInformation(getIdAsList("*"))); throwExceptionIfInsufficientPermission(isAuthorized); - return decorated.getAllAas(pInfo); + return decorated.getAllAas(pInfo, filter); } @Override diff --git a/basyx.aasrepository/basyx.aasrepository-feature-mqtt/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/mqtt/MqttAasRepository.java b/basyx.aasrepository/basyx.aasrepository-feature-mqtt/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/mqtt/MqttAasRepository.java index ce2ed9418..a188e49a8 100644 --- a/basyx.aasrepository/basyx.aasrepository-feature-mqtt/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/mqtt/MqttAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-feature-mqtt/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/mqtt/MqttAasRepository.java @@ -34,6 +34,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation; import org.eclipse.digitaltwin.aas4j.v3.model.Reference; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; +import org.eclipse.digitaltwin.basyx.core.Filter; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; @@ -67,8 +68,8 @@ public MqttAasRepository(AasRepository decorated, IMqttClient mqttClient, MqttAa } @Override - public CursorResult> getAllAas(PaginationInfo pInfo) { - return decorated.getAllAas(pInfo); + public CursorResult> getAllAas(PaginationInfo pInfo, Filter filter) { + return decorated.getAllAas(pInfo, filter); } @Override diff --git a/basyx.aasrepository/basyx.aasrepository-feature-registry-integration/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/registry/integration/RegistryIntegrationAasRepository.java b/basyx.aasrepository/basyx.aasrepository-feature-registry-integration/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/registry/integration/RegistryIntegrationAasRepository.java index 17d93879d..63981bed4 100644 --- a/basyx.aasrepository/basyx.aasrepository-feature-registry-integration/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/registry/integration/RegistryIntegrationAasRepository.java +++ b/basyx.aasrepository/basyx.aasrepository-feature-registry-integration/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/feature/registry/integration/RegistryIntegrationAasRepository.java @@ -37,6 +37,7 @@ import org.eclipse.digitaltwin.basyx.aasregistry.main.client.factory.AasDescriptorFactory; import org.eclipse.digitaltwin.basyx.aasregistry.main.client.mapper.AttributeMapper; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; +import org.eclipse.digitaltwin.basyx.core.Filter; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.RepositoryRegistryLinkException; @@ -67,8 +68,8 @@ public RegistryIntegrationAasRepository(AasRepository decorated, AasRepositoryRe } @Override - public CursorResult> getAllAas(PaginationInfo pInfo) { - return decorated.getAllAas(pInfo); + public CursorResult> getAllAas(PaginationInfo pInfo, Filter filter) { + return decorated.getAllAas(pInfo, filter); } @Override diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryApiHTTPController.java b/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryApiHTTPController.java index 58b3c7afb..a1efc5feb 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryApiHTTPController.java +++ b/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryApiHTTPController.java @@ -29,12 +29,14 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.List; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation; import org.eclipse.digitaltwin.aas4j.v3.model.Reference; import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.http.pagination.GetAssetAdministrationShellsResult; import org.eclipse.digitaltwin.basyx.aasrepository.http.pagination.GetReferencesResult; @@ -56,6 +58,9 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Schema; @@ -67,10 +72,12 @@ public class AasRepositoryApiHTTPController implements AasRepositoryHTTPApi { private final AasRepository aasRepository; - + private final ObjectMapper objectMapper; + @Autowired - public AasRepositoryApiHTTPController(AasRepository aasRepository) { + public AasRepositoryApiHTTPController(AasRepository aasRepository, ObjectMapper objectMapper) { this.aasRepository = aasRepository; + this.objectMapper = objectMapper; } @Override @@ -108,7 +115,7 @@ public ResponseEntity deleteSubmodelReferenceByIdAasRepository(Base64UrlEn } @Override - public ResponseEntity getAllAssetAdministrationShells(@Valid List assetIds, @Valid String idShort, @Min(0) @Valid Integer limit, @Valid Base64UrlEncodedCursor cursor) { + public ResponseEntity getAllAssetAdministrationShells(@Valid List assetIds, @Valid String idShort, @Min(0) @Valid Integer limit, @Valid Base64UrlEncodedCursor cursor) { if (limit == null) { limit = 100; } @@ -117,9 +124,21 @@ public ResponseEntity getAllAssetAdministrationShells(@Valid List decodedAssetLinks; + try { + decodedAssetLinks = getDecodedAssetLinks(assetIds); + } catch (JsonProcessingException e) { + throw new RuntimeException(e.getMessage(), e); + } + + AasFilter aasFilter = new AasFilter(); + + if (assetIds != null && !assetIds.isEmpty()) + aasFilter.setSpecificAssetIds(decodedAssetLinks); PaginationInfo paginationInfo = new PaginationInfo(limit, decodedCursor); - CursorResult> paginatedAAS = aasRepository.getAllAas(paginationInfo); + CursorResult> paginatedAAS = aasRepository.getAllAas(paginationInfo, aasFilter); GetAssetAdministrationShellsResult result = new GetAssetAdministrationShellsResult(); @@ -221,4 +240,21 @@ private void closeInputStream(InputStream fileInputstream) { e.printStackTrace(); } } + + private List getDecodedAssetLinks(List assetIds) throws JsonProcessingException { + List result = new ArrayList<>(); + + if (assetIds == null) + return result; + + for (Base64UrlEncodedIdentifier base64UrlEncodedIdentifier : assetIds) { + + var decodedString = base64UrlEncodedIdentifier.getIdentifier(); + result.add(objectMapper.readValue(decodedString, SpecificAssetId.class)); + + } + + return result; + } + } diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryHTTPApi.java b/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryHTTPApi.java index 97a0965b7..33147fc74 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryHTTPApi.java +++ b/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryHTTPApi.java @@ -31,7 +31,6 @@ import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation; import org.eclipse.digitaltwin.aas4j.v3.model.Reference; import org.eclipse.digitaltwin.aas4j.v3.model.Result; -import org.eclipse.digitaltwin.aas4j.v3.model.SpecificAssetId; import org.eclipse.digitaltwin.basyx.aasrepository.http.pagination.GetAssetAdministrationShellsResult; import org.eclipse.digitaltwin.basyx.aasrepository.http.pagination.GetReferencesResult; import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier; @@ -118,7 +117,7 @@ ResponseEntity deleteSubmodelReferenceByIdAasRepository( @ApiResponse(responseCode = "200", description = "Default error handling for unmentioned status codes", content = @Content(mediaType = "application/json", schema = @Schema(implementation = PagedResult.class))) }) @RequestMapping(value = "/shells", produces = { "application/json" }, method = RequestMethod.GET) ResponseEntity getAllAssetAdministrationShells( - @Parameter(in = ParameterIn.QUERY, description = "A list of specific Asset identifiers", schema = @Schema()) @Valid @RequestParam(value = "assetIds", required = false) List assetIds, + @Parameter(in = ParameterIn.QUERY, description = "A list of specific Asset identifiers", schema = @Schema()) @Valid @RequestParam(value = "assetIds", required = false) List assetIds, @Parameter(in = ParameterIn.QUERY, description = "The Asset Administration Shell’s IdShort", schema = @Schema()) @Valid @RequestParam(value = "idShort", required = false) String idShort, @Min(0) @Parameter(in = ParameterIn.QUERY, description = "The maximum number of elements in the response array", schema = @Schema(allowableValues = { "1" }, minimum = "0")) @Valid @RequestParam(value = "limit", required = false) Integer limit, diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryHTTPSuite.java b/basyx.aasrepository/basyx.aasrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryHTTPSuite.java index 1e2238609..fbdfd64a9 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryHTTPSuite.java +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryHTTPSuite.java @@ -160,6 +160,18 @@ public void getAllPaginatedAas() throws IOException, ParseException { BaSyxHttpTestUtils.assertSameJSONContent(getPaginatedAasJSONString(), getJSONWithoutCursorInfo(actualJsonFromServer)); } + + @Test + public void getAllFilteredAas() throws IOException, ParseException { + createMultipleAasOnServer(); + + CloseableHttpResponse retrievalResponse = requestAllShellIds(); + assertEquals(HttpStatus.OK.value(), retrievalResponse.getCode()); + + String actualJsonFromServer = BaSyxHttpTestUtils.getResponseAsString(retrievalResponse); + + BaSyxHttpTestUtils.assertSameJSONContent(getFilteredAasJSONString(), getJSONWithoutCursorInfo(actualJsonFromServer)); + } @Test public void deleteAas() throws IOException { @@ -388,6 +400,10 @@ public void deleteNonExistingThumbnail() throws FileNotFoundException, Unsupport assertEquals(HttpStatus.NOT_FOUND.value(), response.getCode()); } + + protected CloseableHttpResponse requestAllShellIds() throws IOException, ParseException { + return BaSyxHttpTestUtils.executeGetOnURL(getURL() + "?assetIds=ewoJCSJuYW1lIjogImR1bW15LWFzc2V0MSIsCgkJInZhbHVlIjogImR1bW15LWFzc2V0MS12YWx1ZSIKfQ==,ewoJCSJuYW1lIjogImR1bW15LWFzc2V0MiIsCgkJInZhbHVlIjogImR1bW15LWFzc2V0Mi12YWx1ZSIKfQ=="); + } private String getPaginatedAas1JSONString() throws FileNotFoundException, IOException { return BaSyxHttpTestUtils.readJSONStringFromClasspath("PaginatedAasSimple_1.json"); @@ -405,6 +421,7 @@ private void createMultipleAasOnServer() throws FileNotFoundException, IOExcepti createAasOnServer(getAas1JSONString()); createAasOnServer(getAas2JSONString()); createAasOnServer(getAas3JSONString()); + createAasOnServer(getAas4JSONString()); } private String createDummyAasOnServer(String aasJsonContent) throws FileNotFoundException, IOException { @@ -467,6 +484,10 @@ private String getAas3JSONString() throws FileNotFoundException, IOException { return BaSyxHttpTestUtils.readJSONStringFromClasspath("AasSimple_3.json"); } + private String getAas4JSONString() throws FileNotFoundException, IOException { + return BaSyxHttpTestUtils.readJSONStringFromClasspath("AasSimple_4.json"); + } + private String getAasWithNullIdJSONString() throws FileNotFoundException, IOException { return BaSyxHttpTestUtils.readJSONStringFromClasspath("AasSimpleWithNullId.json"); } @@ -479,6 +500,10 @@ private String getPaginatedAasJSONString() throws FileNotFoundException, IOExcep return BaSyxHttpTestUtils.readJSONStringFromClasspath("AllPaginatedAas.json"); } + private String getFilteredAasJSONString() throws FileNotFoundException, IOException { + return BaSyxHttpTestUtils.readJSONStringFromClasspath("AllFilteredAAS.json"); + } + private String getAas2JSONString() throws FileNotFoundException, IOException { return BaSyxHttpTestUtils.readJSONStringFromClasspath("AasSimple_2.json"); } diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/http/TestAasRepositoryHTTP.java b/basyx.aasrepository/basyx.aasrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/http/TestAasRepositoryHTTP.java index 5e5edea39..5adb9723e 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/http/TestAasRepositoryHTTP.java +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/http/TestAasRepositoryHTTP.java @@ -26,6 +26,7 @@ package org.eclipse.digitaltwin.basyx.aasrepository.http; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.junit.AfterClass; @@ -51,7 +52,7 @@ public static void startAasRepo() throws Exception { @Override public void resetRepository() { AasRepository repo = appContext.getBean(AasRepository.class); - repo.getAllAas(PaginationInfo.NO_LIMIT) + repo.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()) .getResult() .stream() .map(a -> a.getId()) diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_1.json b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_1.json index 16e79e653..f61515067 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_1.json +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_1.json @@ -4,6 +4,21 @@ "id": "customIdentifier", "assetInformation": { "assetKind": "Instance", - "globalAssetId": "globalAssetId" + "globalAssetId": "globalAssetId", + "specificAssetIds": [ + { + "name": "dummy-asset3", + "value": "dummy-asset3-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] } } diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_2.json b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_2.json index b86795a24..b421e6d9d 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_2.json +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_2.json @@ -4,6 +4,34 @@ "id": "dummyAasIdentifier", "assetInformation": { "assetKind": "Instance", - "globalAssetId": "dummyAasAssetId" + "globalAssetId": "dummyAasAssetId", + "specificAssetIds": [ + { + "name": "dummy-asset1", + "value": "dummy-asset1-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + }, + { + "name": "dummy-asset2", + "value": "dummy-asset2-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] } } diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_3.json b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_3.json index 3bdb692e7..2ea13640f 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_3.json +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_3.json @@ -4,6 +4,21 @@ "id": "AasNumber3Identifier", "assetInformation": { "assetKind": "Instance", - "globalAssetId": "AasNumber3AssetId" + "globalAssetId": "AasNumber3AssetId", + "specificAssetIds": [ + { + "name": "dummy-asset4", + "value": "dummy-asset4-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] } } diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_4.json b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_4.json new file mode 100644 index 000000000..520bee8d1 --- /dev/null +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AasSimple_4.json @@ -0,0 +1,37 @@ +{ + "modelType": "AssetAdministrationShell", + "idShort": "ExampleMotor", + "id": "dummyAasIdentifier4", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": "globalAssetId", + "specificAssetIds": [ + { + "name": "dummy-asset1", + "value": "dummy-asset1-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + }, + { + "name": "dummy-asset2", + "value": "dummy-asset2-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] + } +} diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AllFilteredAAS.json b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AllFilteredAAS.json new file mode 100644 index 000000000..913232800 --- /dev/null +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AllFilteredAAS.json @@ -0,0 +1,80 @@ +{ + "paging_metadata": { + }, + "result": [ + { + "modelType": "AssetAdministrationShell", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": "dummyAasAssetId", + "specificAssetIds": [ + { + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + }, + "name": "dummy-asset1", + "value": "dummy-asset1-value" + }, + { + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + }, + "name": "dummy-asset2", + "value": "dummy-asset2-value" + } + ] + }, + "id": "dummyAasIdentifier", + "idShort": "DummyAas" + }, + { + "modelType": "AssetAdministrationShell", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": "globalAssetId", + "specificAssetIds": [ + { + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + }, + "name": "dummy-asset1", + "value": "dummy-asset1-value" + }, + { + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + }, + "name": "dummy-asset2", + "value": "dummy-asset2-value" + } + ] + }, + "id": "dummyAasIdentifier4", + "idShort": "ExampleMotor" + } + ] +} diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AllPaginatedAas.json b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AllPaginatedAas.json index b2d7bb763..09f9b42de 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AllPaginatedAas.json +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/AllPaginatedAas.json @@ -1,11 +1,27 @@ { - "paging_metadata": {}, + "paging_metadata": { + }, "result": [ { "modelType": "AssetAdministrationShell", "assetInformation": { "assetKind": "Instance", - "globalAssetId": "AasNumber3AssetId" + "globalAssetId": "AasNumber3AssetId", + "specificAssetIds": [ + { + "name": "dummy-asset4", + "value": "dummy-asset4-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] }, "id": "AasNumber3Identifier", "idShort": "AasNumber3" @@ -14,7 +30,22 @@ "modelType": "AssetAdministrationShell", "assetInformation": { "assetKind": "Instance", - "globalAssetId": "globalAssetId" + "globalAssetId": "globalAssetId", + "specificAssetIds": [ + { + "name": "dummy-asset3", + "value": "dummy-asset3-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] }, "id": "customIdentifier", "idShort": "ExampleMotor" @@ -23,10 +54,75 @@ "modelType": "AssetAdministrationShell", "assetInformation": { "assetKind": "Instance", - "globalAssetId": "dummyAasAssetId" + "globalAssetId": "dummyAasAssetId", + "specificAssetIds": [ + { + "name": "dummy-asset1", + "value": "dummy-asset1-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + }, + { + "name": "dummy-asset2", + "value": "dummy-asset2-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] }, "id": "dummyAasIdentifier", "idShort": "DummyAas" + }, + { + "modelType": "AssetAdministrationShell", + "idShort": "ExampleMotor", + "id": "dummyAasIdentifier4", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": "globalAssetId", + "specificAssetIds": [ + { + "name": "dummy-asset1", + "value": "dummy-asset1-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + }, + { + "name": "dummy-asset2", + "value": "dummy-asset2-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] + } } ] -} \ No newline at end of file +} diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/PaginatedAasSimple_1.json b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/PaginatedAasSimple_1.json index f43f94410..6127a37dc 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/PaginatedAasSimple_1.json +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/PaginatedAasSimple_1.json @@ -1,14 +1,30 @@ { - "paging_metadata": {}, + "paging_metadata": { + }, "result": [ { "modelType": "AssetAdministrationShell", "assetInformation": { "assetKind": "Instance", - "globalAssetId": "globalAssetId" + "globalAssetId": "globalAssetId", + "specificAssetIds": [ + { + "name": "dummy-asset3", + "value": "dummy-asset3-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] }, "id": "customIdentifier", "idShort": "ExampleMotor" } ] -} \ No newline at end of file +} diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/assetInfoSimple.json b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/assetInfoSimple.json index 70a38c140..a124f07e2 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/assetInfoSimple.json +++ b/basyx.aasrepository/basyx.aasrepository-http/src/test/resources/assetInfoSimple.json @@ -1,4 +1,19 @@ { - "assetKind":"Instance", - "globalAssetId":"globalAssetId" -} \ No newline at end of file + "assetKind": "Instance", + "globalAssetId": "globalAssetId", + "specificAssetIds": [ + { + "name": "dummy-asset3", + "value": "dummy-asset3-value", + "externalSubjectId": { + "keys": [ + { + "type": "GlobalReference", + "value": "https://example.org/ExternalSubject" + } + ], + "type": "ExternalReference" + } + } + ] +} diff --git a/basyx.aasservice/basyx.aasservice-client/src/test/java/org/eclipse/digitaltwin/basyx/aasservice/client/TestAuthorizedConnectedAasService.java b/basyx.aasservice/basyx.aasservice-client/src/test/java/org/eclipse/digitaltwin/basyx/aasservice/client/TestAuthorizedConnectedAasService.java index 0aef42184..a8fc9ba6d 100644 --- a/basyx.aasservice/basyx.aasservice-client/src/test/java/org/eclipse/digitaltwin/basyx/aasservice/client/TestAuthorizedConnectedAasService.java +++ b/basyx.aasservice/basyx.aasservice-client/src/test/java/org/eclipse/digitaltwin/basyx/aasservice/client/TestAuthorizedConnectedAasService.java @@ -33,6 +33,7 @@ import java.security.interfaces.RSAPublicKey; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.DummyAasFactory; import org.eclipse.digitaltwin.basyx.aasrepository.feature.authorization.DummyAuthorizedAasRepositoryComponent; @@ -83,7 +84,7 @@ public static void startAASRepo() throws Exception { @After public void removeAasFromRepo() { AasRepository repo = appContext.getBean(AasRepository.class); - repo.getAllAas(PaginationInfo.NO_LIMIT).getResult().stream().map(s -> s.getId()).forEach(repo::deleteAas); + repo.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().stream().map(s -> s.getId()).forEach(repo::deleteAas); } @AfterClass diff --git a/basyx.aasservice/basyx.aasservice-client/src/test/java/org/eclipse/digitaltwin/basyx/aasservice/client/TestConnectedAasService.java b/basyx.aasservice/basyx.aasservice-client/src/test/java/org/eclipse/digitaltwin/basyx/aasservice/client/TestConnectedAasService.java index 98e89f2d5..51ed1dc35 100644 --- a/basyx.aasservice/basyx.aasservice-client/src/test/java/org/eclipse/digitaltwin/basyx/aasservice/client/TestConnectedAasService.java +++ b/basyx.aasservice/basyx.aasservice-client/src/test/java/org/eclipse/digitaltwin/basyx/aasservice/client/TestConnectedAasService.java @@ -28,6 +28,7 @@ import java.io.IOException; import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.http.DummyAasRepositoryComponent; import org.eclipse.digitaltwin.basyx.aasservice.AasService; @@ -56,7 +57,7 @@ public static void startAASRepo() throws Exception { @After public void removeAasFromRepo() { AasRepository repo = appContext.getBean(AasRepository.class); - repo.getAllAas(PaginationInfo.NO_LIMIT).getResult().stream().map(s -> s.getId()).forEach(repo::deleteAas); + repo.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().stream().map(s -> s.getId()).forEach(repo::deleteAas); } @AfterClass diff --git a/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java b/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java index 8c5267266..9302ab106 100644 --- a/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java +++ b/basyx.common/basyx.backend.inmemory.core/src/main/java/org/eclipse/digitaltwin/basyx/common/backend/inmemory/core/InMemoryCrudRepository.java @@ -25,15 +25,21 @@ package org.eclipse.digitaltwin.basyx.common.backend.inmemory.core; +import java.util.Comparator; import java.util.Objects; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import java.util.stream.StreamSupport; -import org.springframework.data.repository.CrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; +import org.eclipse.digitaltwin.basyx.core.FilterResolution; +import org.eclipse.digitaltwin.basyx.core.Filter; +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.springframework.lang.NonNull; /** @@ -41,21 +47,28 @@ * * @author danish */ -public class InMemoryCrudRepository implements CrudRepository { - +public class InMemoryCrudRepository implements BaSyxCrudRepository { + private final ConcurrentMap inMemoryStore = new ConcurrentHashMap<>(); private Function idGetter; - + private FilterResolution> filterResolution; + public InMemoryCrudRepository(Function idGetter) { this.idGetter = idGetter; } + + public InMemoryCrudRepository(Function idGetter, FilterResolution> filterResolution) { + this(idGetter); + + this.filterResolution = filterResolution; + } @Override public @NonNull S save(@NonNull S entity) { String id = idGetter.apply(entity); - + inMemoryStore.put(id, entity); - + return entity; } @@ -81,6 +94,32 @@ public boolean existsById(@NonNull String id) { return inMemoryStore.values(); } + @Override + public @NonNull Iterable findAll(PaginationInfo paginationInfo, Filter filter) { + + Stream resultStream = inMemoryStore.values().stream(); + + if (filterResolution != null && filter != null) + resultStream = resultStream.filter(filterResolution.applyFilter(filter)); + + resultStream = applySorting(resultStream); + + if (paginationInfo.getCursor() != null) { + resultStream = resultStream.filter(asset -> idGetter.apply(asset).compareTo(paginationInfo.getCursor()) > 0); + } + + if (paginationInfo.getLimit() != null) { + resultStream = resultStream.limit(paginationInfo.getLimit()); + } + + return resultStream.collect(Collectors.toList()); + } + + private Stream applySorting(Stream stream) { + return stream + .sorted(Comparator.comparing(idGetter)); + } + @Override public @NonNull Iterable findAllById(@NonNull Iterable ids) { return StreamSupport.stream(ids.spliterator(), false).map(inMemoryStore::get).filter(Objects::nonNull).collect(Collectors.toList()); @@ -99,7 +138,7 @@ public void deleteById(@NonNull String id) { @Override public void delete(@NonNull T entity) { String id = idGetter.apply(entity); - + inMemoryStore.remove(id); } @@ -111,7 +150,7 @@ public void deleteAllById(@NonNull Iterable ids) { @Override public void deleteAll(@NonNull Iterable entities) { - + for (T entity : entities) inMemoryStore.remove(idGetter.apply(entity)); } @@ -121,5 +160,4 @@ public void deleteAll() { inMemoryStore.clear(); } - } diff --git a/basyx.common/basyx.core/pom.xml b/basyx.common/basyx.core/pom.xml index e0c89f549..ab7885850 100644 --- a/basyx.common/basyx.core/pom.xml +++ b/basyx.common/basyx.core/pom.xml @@ -35,6 +35,10 @@ junit test + + org.springframework.data + spring-data-commons + \ No newline at end of file diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/BaSyxCrudRepository.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/BaSyxCrudRepository.java new file mode 100644 index 000000000..e723cf84d --- /dev/null +++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/BaSyxCrudRepository.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.core; + +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; +import org.springframework.data.repository.CrudRepository; +import org.springframework.lang.NonNull; + +/** + * The {@code BaSyxCrudRepository} interface extends the {@link CrudRepository} + * to provide basic Create, Read, Update, and Delete (CRUD) operations with + * additional support for pagination and filtering. + * + *

+ * This interface is designed to facilitate the retrieval of paginated and + * filtered data. + * + * @param + * the type of entity that this repository manages + * + * @see CrudRepository + * + * @author danish + */ +public interface BaSyxCrudRepository extends CrudRepository { + + /** + * Retrieves all entities of type {@code T} that match the specified + * {@link Filter} criteria, applying the provided {@link PaginationInfo} to + * control the subset of results returned. + * + * @param paginationInfo + * @param filter + * a {@link Filter} object specifying the criteria to apply when + * querying the entities + * @return an {@code Iterable} of entities of type {@code T} that meet the + * filtering and pagination criteria + * @throws IllegalArgumentException + * if {@code paginationInfo} or {@code filter} is null + */ + @NonNull + Iterable findAll(PaginationInfo paginationInfo, Filter filter); + +} diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/Filter.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/Filter.java new file mode 100644 index 000000000..e319c675a --- /dev/null +++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/Filter.java @@ -0,0 +1,9 @@ +package org.eclipse.digitaltwin.basyx.core; + +import java.util.List; + +public interface Filter { + + List getIds(); + +} diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/FilterResolution.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/FilterResolution.java new file mode 100644 index 000000000..96fa7d723 --- /dev/null +++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/FilterResolution.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.core; + +/** + * The {@code FilterResolution} interface defines a contract for applying a {@link Filter} + * to produce a specific output type, {@code O}. This is intended to enable filtering + * operations across different storage or query mechanisms within the Eclipse BaSyx framework. + * + *

The output type {@code O} represents the result of applying the filter, + * which may vary depending on the underlying implementation. For instance, + * it could be a {@code Predicate} for InMemory filtering, or an {@code AggregationOperations} + * object for MongoDB filtering. + * + * @param the type of output expected after applying the {@link Filter}, determined by the context + * in which filtering is applied (e.g., InMemory, MongoDB, S3 etc.) + * + * @author danish + */ +public interface FilterResolution { + + /** + * Applies the specified {@link Filter} to produce an output of type {@code O}. + * + *

This method enables custom filtering logic depending on the storage mechanism + * or query type. Implementing classes are expected to convert the filter criteria + * into the desired format, whether for InMemory filtering, database filtering, or another purpose. + * + * @param filter the {@link Filter} containing criteria to be applied to the data + * @return an instance of {@code O} representing the filtered output, formatted + * according to the underlying filter resolution implementation + * + */ + O applyFilter(Filter filter); + +} + diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/PaginationUtilities.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/PaginationUtilities.java new file mode 100644 index 000000000..8580df216 --- /dev/null +++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/PaginationUtilities.java @@ -0,0 +1,22 @@ +package org.eclipse.digitaltwin.basyx.core.pagination; + +import java.util.List; +import java.util.function.Function; + +public class PaginationUtilities { + + public static String resolveCursor(PaginationInfo pRequest, List foundDescriptors) { + return resolveCursor(pRequest, foundDescriptors, Function.identity()); + } + + public static String resolveCursor(PaginationInfo pRequest, List foundDescriptors, Function idResolver) { + + if (foundDescriptors.isEmpty() || !pRequest.isPaged()) + return null; + + T last = foundDescriptors.get(foundDescriptors.size() - 1); + + return idResolver.apply(last); + } + +} diff --git a/basyx.common/basyx.mongocore/pom.xml b/basyx.common/basyx.mongocore/pom.xml index 99e5f83b6..1a59264a8 100644 --- a/basyx.common/basyx.mongocore/pom.xml +++ b/basyx.common/basyx.mongocore/pom.xml @@ -22,5 +22,9 @@ org.springframework.boot spring-boot-starter-data-mongodb + + org.eclipse.digitaltwin.basyx + basyx.core + \ No newline at end of file diff --git a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java new file mode 100644 index 000000000..f25d4ccb1 --- /dev/null +++ b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java @@ -0,0 +1,69 @@ +package org.eclipse.digitaltwin.basyx.common.mongocore; + +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; +import org.eclipse.digitaltwin.basyx.core.FilterResolution; +import org.eclipse.digitaltwin.basyx.core.Filter; +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; +import org.springframework.data.mongodb.core.aggregation.AggregationResults; +import org.springframework.data.mongodb.repository.query.MongoEntityInformation; +import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; + +/** + * The {@code MongoDBCrudRepository} class is a MongoDB-specific implementation of the {@link BaSyxCrudRepository}, + * extending the basic CRUD functionality with support for pagination and filtering using MongoDB's aggregation framework. + * + *

This repository class allows retrieval of data with custom filtering and pagination capabilities. + * + * @param the type of entity that this repository manages + * + * @see SimpleMongoRepository + * @see BaSyxCrudRepository + * + * @author danish + */ +public class MongoDBCrudRepository extends SimpleMongoRepository implements BaSyxCrudRepository { + + private MongoTemplate mongoTemplate; + private Class clazz; + private MongoEntityInformation metadata; + private FilterResolution filterResolution; + + public MongoDBCrudRepository(MongoEntityInformation metadata, MongoTemplate mongoTemplate, Class clazz) { + super(metadata, mongoTemplate); + + this.metadata = metadata; + this.mongoTemplate = mongoTemplate; + this.clazz = clazz; + } + + public MongoDBCrudRepository(MongoEntityInformation metadata, MongoTemplate mongoTemplate, Class clazz, FilterResolution filterResolution) { + this(metadata, mongoTemplate, clazz); + + this.filterResolution = filterResolution; + } + + @Override + public List findAll(PaginationInfo paginationInfo, Filter filter) { + + List allAggregations = new LinkedList<>(); + + if (filterResolution != null && filter != null) { + AggregationOperation operation = filterResolution.applyFilter(filter); + allAggregations.add(operation); + } + + MongoDBUtilities.applySorting(allAggregations); + MongoDBUtilities.applyPagination(paginationInfo, allAggregations); + + AggregationResults results = mongoTemplate.aggregate(Aggregation.newAggregation(allAggregations), metadata.getCollectionName(), clazz); + + return results.getMappedResults(); + } + +} diff --git a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java index f6d46ac7b..f11553681 100644 --- a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java +++ b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBUtilities.java @@ -24,7 +24,14 @@ ******************************************************************************/ package org.eclipse.digitaltwin.basyx.common.mongocore; +import java.util.List; +import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; +import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; +import org.springframework.data.mongodb.core.aggregation.SortOperation; +import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; /** @@ -33,6 +40,8 @@ * */ public class MongoDBUtilities { + + private static final String ID = "_id"; /** * Removes all documents from the specified collection. @@ -43,4 +52,37 @@ public class MongoDBUtilities { public static void clearCollection(MongoTemplate template, String collection) { template.remove(new Query(), collection); } + + /** + * Creates aggregation operations based on the {@link PaginationInfo}. + * + * @param pRequest + * @param allAggregations + * + * @see AggregationOperation + */ + public static void applyPagination(PaginationInfo pRequest, List allAggregations) { + + if (pRequest.getCursor() != null) { + allAggregations.add(Aggregation.match(Criteria.where(ID).gt(pRequest.getCursor()))); + } + + if (pRequest.getLimit() != null) { + allAggregations.add(Aggregation.limit(pRequest.getLimit())); + } + } + + /** + * Creates sort operation criteria for ascending order sorting based on the identifier. + * + * @param allAggregations + * + * @see SortOperation + */ + public static void applySorting(List allAggregations) { + SortOperation sortOp = Aggregation.sort(Direction.ASC, ID); + + allAggregations.add(sortOp); + } + } diff --git a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackendProvider.java b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackendProvider.java index e5775d9e7..2e23b9872 100644 --- a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackendProvider.java +++ b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionInMemoryBackendProvider.java @@ -28,8 +28,8 @@ import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; import org.eclipse.digitaltwin.basyx.aasrepository.backend.ConceptDescriptionBackendProvider; import org.eclipse.digitaltwin.basyx.common.backend.inmemory.core.InMemoryCrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; /** @@ -42,7 +42,7 @@ public class ConceptDescriptionInMemoryBackendProvider implements ConceptDescriptionBackendProvider { @Override - public CrudRepository getCrudRepository() { + public BaSyxCrudRepository getCrudRepository() { return new InMemoryCrudRepository(ConceptDescription::getId); } diff --git a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionMongoDBBackendProvider.java b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionMongoDBBackendProvider.java index 72ecb6a2f..dbb7ff159 100644 --- a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionMongoDBBackendProvider.java +++ b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/ConceptDescriptionMongoDBBackendProvider.java @@ -28,14 +28,14 @@ import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; import org.eclipse.digitaltwin.basyx.aasrepository.backend.ConceptDescriptionBackendProvider; import org.eclipse.digitaltwin.basyx.common.mongocore.BasyxMongoMappingContext; +import org.eclipse.digitaltwin.basyx.common.mongocore.MongoDBCrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation; -import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; -import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; /** @@ -61,11 +61,11 @@ public ConceptDescriptionMongoDBBackendProvider(BasyxMongoMappingContext mapping } @Override - public CrudRepository getCrudRepository() { + public BaSyxCrudRepository getCrudRepository() { @SuppressWarnings("unchecked") MongoPersistentEntity entity = (MongoPersistentEntity) mappingContext.getPersistentEntity(ConceptDescription.class); - return new SimpleMongoRepository<>(new MappingMongoEntityInformation<>(entity), template); + return new MongoDBCrudRepository(new MappingMongoEntityInformation<>(entity), template, ConceptDescription.class); } } diff --git a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/TestMongoDBConceptDescriptionRepository.java b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/TestMongoDBConceptDescriptionRepository.java index 9f5aa7a26..40e3fa119 100644 --- a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/TestMongoDBConceptDescriptionRepository.java +++ b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/conceptdescriptionrepository/TestMongoDBConceptDescriptionRepository.java @@ -38,9 +38,6 @@ import org.eclipse.digitaltwin.basyx.aasrepository.backend.SimpleConceptDescriptionRepositoryFactory; import org.eclipse.digitaltwin.basyx.common.mongocore.BasyxMongoMappingContext; import org.eclipse.digitaltwin.basyx.common.mongocore.MongoDBUtilities; -import org.eclipse.digitaltwin.basyx.conceptdescriptionrepository.ConceptDescriptionMongoDBBackendProvider; -import org.eclipse.digitaltwin.basyx.conceptdescriptionrepository.ConceptDescriptionRepository; -import org.eclipse.digitaltwin.basyx.conceptdescriptionrepository.ConceptDescriptionRepositoryFactory; import org.eclipse.digitaltwin.basyx.conceptdescriptionrepository.core.ConceptDescriptionRepositorySuite; import org.junit.Test; import org.springframework.data.mongodb.core.MongoTemplate; diff --git a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/ConceptDescriptionBackendProvider.java b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/ConceptDescriptionBackendProvider.java index f84458779..fe899fb83 100644 --- a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/ConceptDescriptionBackendProvider.java +++ b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/ConceptDescriptionBackendProvider.java @@ -25,7 +25,7 @@ package org.eclipse.digitaltwin.basyx.aasrepository.backend; import org.eclipse.digitaltwin.aas4j.v3.model.ConceptDescription; -import org.springframework.data.repository.CrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; /** * Backend provider for the {@link ConceptDescription} @@ -34,6 +34,6 @@ */ public interface ConceptDescriptionBackendProvider { - public CrudRepository getCrudRepository(); + public BaSyxCrudRepository getCrudRepository(); } diff --git a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudConceptDescriptionRepository.java b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudConceptDescriptionRepository.java index 104c57a0d..b7751534f 100644 --- a/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudConceptDescriptionRepository.java +++ b/basyx.conceptdescriptionrepository/basyx.conceptdescriptionrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/CrudConceptDescriptionRepository.java @@ -38,6 +38,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.EmbeddedDataSpecification; import org.eclipse.digitaltwin.aas4j.v3.model.Reference; import org.eclipse.digitaltwin.basyx.conceptdescriptionrepository.ConceptDescriptionRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.IdentificationMismatchException; @@ -56,7 +57,7 @@ */ public class CrudConceptDescriptionRepository implements ConceptDescriptionRepository { - private CrudRepository conceptDescriptionBackend; + private BaSyxCrudRepository conceptDescriptionBackend; private String conceptDescriptionRepositoryName = null; public CrudConceptDescriptionRepository(ConceptDescriptionBackendProvider conceptDescriptionBackendProvider) { diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackendProvider.java b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackendProvider.java index bf65b85dc..cb3dd6b63 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackendProvider.java +++ b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelInMemoryBackendProvider.java @@ -27,9 +27,9 @@ import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.basyx.common.backend.inmemory.core.InMemoryCrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.eclipse.digitaltwin.basyx.submodelrepository.backend.SubmodelBackendProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; /** @@ -43,7 +43,7 @@ public class SubmodelInMemoryBackendProvider implements SubmodelBackendProvider { @Override - public CrudRepository getCrudRepository() { + public BaSyxCrudRepository getCrudRepository() { return new InMemoryCrudRepository(Submodel::getId); } diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelMongoDBBackendProvider.java b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelMongoDBBackendProvider.java index cd414bb77..c1b077800 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelMongoDBBackendProvider.java +++ b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelMongoDBBackendProvider.java @@ -27,6 +27,8 @@ import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.basyx.common.mongocore.BasyxMongoMappingContext; +import org.eclipse.digitaltwin.basyx.common.mongocore.MongoDBCrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.eclipse.digitaltwin.basyx.submodelrepository.backend.SubmodelBackendProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -34,8 +36,6 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation; -import org.springframework.data.mongodb.repository.support.SimpleMongoRepository; -import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; /** @@ -62,11 +62,11 @@ public SubmodelMongoDBBackendProvider(BasyxMongoMappingContext mappingContext, @ } @Override - public CrudRepository getCrudRepository() { + public BaSyxCrudRepository getCrudRepository() { @SuppressWarnings("unchecked") MongoPersistentEntity entity = (MongoPersistentEntity) mappingContext.getPersistentEntity(Submodel.class); - return new SimpleMongoRepository<>(new MappingMongoEntityInformation<>(entity), template); + return new MongoDBCrudRepository(new MappingMongoEntityInformation<>(entity), template, Submodel.class); } } diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java b/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java index 6fc3bbfe3..f7e9f03c7 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java +++ b/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java @@ -26,7 +26,6 @@ package org.eclipse.digitaltwin.basyx.submodelrepository.backend; import java.io.InputStream; -import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -40,10 +39,9 @@ import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.JsonDeserializer; import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.JsonSerializer; import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable; -import org.eclipse.digitaltwin.aas4j.v3.model.Reference; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; -import org.eclipse.digitaltwin.basyx.client.internal.ApiException; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException; @@ -53,16 +51,11 @@ import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport; -import org.eclipse.digitaltwin.basyx.http.Base64UrlEncoder; import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository; import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService; import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelServiceFactory; import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue; import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelValueOnly; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.repository.CrudRepository; -import org.springframework.http.HttpStatus; /** * Default Implementation for the {@link SubmodelRepository} based on Spring @@ -73,8 +66,7 @@ */ public class CrudSubmodelRepository implements SubmodelRepository { - private Logger logger = LoggerFactory.getLogger(CrudSubmodelRepository.class); - private CrudRepository submodelBackend; + private BaSyxCrudRepository submodelBackend; private SubmodelServiceFactory submodelServiceFactory; diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/SubmodelBackendProvider.java b/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/SubmodelBackendProvider.java index ae3edc9db..137ae661f 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/SubmodelBackendProvider.java +++ b/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/SubmodelBackendProvider.java @@ -26,7 +26,7 @@ package org.eclipse.digitaltwin.basyx.submodelrepository.backend; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; -import org.springframework.data.repository.CrudRepository; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; /** * Backend provider for the {@link Submodel} @@ -35,6 +35,6 @@ */ public interface SubmodelBackendProvider { - public CrudRepository getCrudRepository(); + public BaSyxCrudRepository getCrudRepository(); } diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepositoryTest.java b/basyx.submodelrepository/basyx.submodelrepository-backend/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepositoryTest.java index 9f3c658dd..cc6221c24 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-backend/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepositoryTest.java +++ b/basyx.submodelrepository/basyx.submodelrepository-backend/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepositoryTest.java @@ -28,9 +28,9 @@ import static org.junit.Assert.assertEquals; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; +import org.eclipse.digitaltwin.basyx.core.BaSyxCrudRepository; import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository; import org.junit.Test; -import org.springframework.data.repository.CrudRepository; /** * Tests {@link CrudSubmodelRepository} @@ -52,7 +52,7 @@ private SubmodelBackendProvider createSubmodelProvider() { return new SubmodelBackendProvider() { @Override - public CrudRepository getCrudRepository() { + public BaSyxCrudRepository getCrudRepository() { return null; } From 68217b94581d0b81c61dd84a4e296b65bba89156 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Tue, 5 Nov 2024 14:24:47 +0100 Subject: [PATCH 5/9] Resets CI files Signed-off-by: Mohammad Ghazanfar Ali Danish --- .github/workflows/basyx_test.yml | 2 -- .github/workflows/docker_test.yml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/basyx_test.yml b/.github/workflows/basyx_test.yml index 04118297c..1187244a2 100644 --- a/.github/workflows/basyx_test.yml +++ b/.github/workflows/basyx_test.yml @@ -1,8 +1,6 @@ name: Build and Test BaSyx on: - push: - branches: [ feature/filter-at-backend ] pull_request: branches: [ main ] paths-ignore: diff --git a/.github/workflows/docker_test.yml b/.github/workflows/docker_test.yml index a37eafffd..d10df98fa 100644 --- a/.github/workflows/docker_test.yml +++ b/.github/workflows/docker_test.yml @@ -4,8 +4,6 @@ name: Build and Start Docker Images on: - push: - branches: [ feature/filter-at-backend ] pull_request: branches: [ main ] paths-ignore: From c231307f3f6e754a82aef0c57202e9d4e9add402 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Tue, 5 Nov 2024 14:36:49 +0100 Subject: [PATCH 6/9] Refactors codes and add license headers Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../mongodb/AasMongoDBBackendProvider.java | 2 +- .../TestAasMongoDBFilterResolution.java | 30 +++++++++++++++++++ .../basyx.aasrepository-backend/pom.xml | 4 --- .../mongocore/MongoDBCrudRepository.java | 25 ++++++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBBackendProvider.java b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBBackendProvider.java index b055f4e6e..986df6549 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBBackendProvider.java +++ b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/AasMongoDBBackendProvider.java @@ -61,7 +61,7 @@ public AasMongoDBBackendProvider(BasyxMongoMappingContext mappingContext, @Value this.mappingContext = mappingContext; this.template = template; -// configureIndices(this.template); + configureIndices(this.template); mappingContext.addEntityMapping(AssetAdministrationShell.class, collectionName); } diff --git a/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/TestAasMongoDBFilterResolution.java b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/TestAasMongoDBFilterResolution.java index 8c2b9e90b..f98078263 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/TestAasMongoDBFilterResolution.java +++ b/basyx.aasrepository/basyx.aasrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/aasrepository/backend/mongodb/TestAasMongoDBFilterResolution.java @@ -1,3 +1,28 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + package org.eclipse.digitaltwin.basyx.aasrepository.backend.mongodb; import static org.junit.Assert.*; @@ -18,6 +43,11 @@ import org.springframework.data.mongodb.core.aggregation.AggregationOperation; import org.springframework.data.mongodb.core.aggregation.MatchOperation; +/** + * Tests {@link AasMongoDBFilterResolution} + * + * @author danish + */ public class TestAasMongoDBFilterResolution { private AasMongoDBFilterResolution filterResolution; diff --git a/basyx.aasrepository/basyx.aasrepository-backend/pom.xml b/basyx.aasrepository/basyx.aasrepository-backend/pom.xml index 598ee779a..5936dd14a 100644 --- a/basyx.aasrepository/basyx.aasrepository-backend/pom.xml +++ b/basyx.aasrepository/basyx.aasrepository-backend/pom.xml @@ -19,10 +19,6 @@ org.eclipse.digitaltwin.basyx basyx.aasrepository-core - - org.eclipse.digitaltwin.basyx - basyx.mongodbcore - org.springframework.data spring-data-commons diff --git a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java index f25d4ccb1..c04b8203a 100644 --- a/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java +++ b/basyx.common/basyx.mongocore/src/main/java/org/eclipse/digitaltwin/basyx/common/mongocore/MongoDBCrudRepository.java @@ -1,3 +1,28 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + package org.eclipse.digitaltwin.basyx.common.mongocore; import java.util.LinkedList; From 06c9bbcd479cefbd16ca1d96b6c20b78c5b3106e Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Tue, 5 Nov 2024 14:41:30 +0100 Subject: [PATCH 7/9] Fixes CI Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../basyx/submodelrepository/core/SubmodelRepositorySuite.java | 1 + 1 file changed, 1 insertion(+) diff --git a/basyx.submodelrepository/basyx.submodelrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/core/SubmodelRepositorySuite.java b/basyx.submodelrepository/basyx.submodelrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/core/SubmodelRepositorySuite.java index d0eeb1dd0..e094bfdb8 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/core/SubmodelRepositorySuite.java +++ b/basyx.submodelrepository/basyx.submodelrepository-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/core/SubmodelRepositorySuite.java @@ -48,6 +48,7 @@ import org.eclipse.digitaltwin.basyx.core.exceptions.NotInvokableException; import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; +import org.eclipse.digitaltwin.basyx.serialization.SubmodelMetadataUtil; import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository; import org.eclipse.digitaltwin.basyx.submodelservice.DummySubmodelFactory; import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService; From c4042660bceb22244c20a5c010f5318495b81e73 Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Tue, 5 Nov 2024 14:49:16 +0100 Subject: [PATCH 8/9] Adds missing import Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../component/TestEnvironmentWithRegistryIntegration.java | 3 ++- .../submodelrepository/backend/CrudSubmodelRepository.java | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/basyx.aasenvironment/basyx.aasenvironment.component/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/component/TestEnvironmentWithRegistryIntegration.java b/basyx.aasenvironment/basyx.aasenvironment.component/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/component/TestEnvironmentWithRegistryIntegration.java index ca223dbeb..01849c44c 100644 --- a/basyx.aasenvironment/basyx.aasenvironment.component/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/component/TestEnvironmentWithRegistryIntegration.java +++ b/basyx.aasenvironment/basyx.aasenvironment.component/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/component/TestEnvironmentWithRegistryIntegration.java @@ -38,6 +38,7 @@ import org.eclipse.digitaltwin.basyx.aasenvironment.environmentloader.CompleteEnvironment.EnvironmentType; import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException; import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor; +import org.eclipse.digitaltwin.basyx.aasrepository.AasFilter; import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository; import org.eclipse.digitaltwin.basyx.aasrepository.feature.registry.integration.AasRepositoryRegistryLink; import org.eclipse.digitaltwin.basyx.core.exceptions.RepositoryRegistryLinkException; @@ -117,7 +118,7 @@ private static InputStream getIsFromClasspath(String fileName) throws IOExceptio } private static void assertRepositoriesAreEmpty() { - assertTrue(aasRepository.getAllAas(PaginationInfo.NO_LIMIT).getResult().isEmpty()); + assertTrue(aasRepository.getAllAas(PaginationInfo.NO_LIMIT, new AasFilter()).getResult().isEmpty()); assertTrue(smRepository.getAllSubmodels(PaginationInfo.NO_LIMIT).getResult().isEmpty()); } diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java b/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java index 60a3d5f4e..2762c1672 100644 --- a/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java +++ b/basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java @@ -47,6 +47,7 @@ import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo; import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport; +import org.eclipse.digitaltwin.basyx.serialization.SubmodelMetadataUtil; import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository; import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService; import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelServiceFactory; From 2c7776eff0f7c28afa8e645b517e497b12e67ebd Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish Date: Tue, 5 Nov 2024 15:26:24 +0100 Subject: [PATCH 9/9] Adds Javadoc and license headers to PaginationUtilities Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../core/pagination/PaginationUtilities.java | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/PaginationUtilities.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/PaginationUtilities.java index 8580df216..361def549 100644 --- a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/PaginationUtilities.java +++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/pagination/PaginationUtilities.java @@ -1,20 +1,50 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + package org.eclipse.digitaltwin.basyx.core.pagination; import java.util.List; import java.util.function.Function; +/** + * An utility class for Pagination + * + * @author danish + */ public class PaginationUtilities { - public static String resolveCursor(PaginationInfo pRequest, List foundDescriptors) { - return resolveCursor(pRequest, foundDescriptors, Function.identity()); + public static String resolveCursor(PaginationInfo pRequest, List data) { + return resolveCursor(pRequest, data, Function.identity()); } - public static String resolveCursor(PaginationInfo pRequest, List foundDescriptors, Function idResolver) { + public static String resolveCursor(PaginationInfo pRequest, List data, Function idResolver) { - if (foundDescriptors.isEmpty() || !pRequest.isPaged()) + if (data.isEmpty() || !pRequest.isPaged()) return null; - T last = foundDescriptors.get(foundDescriptors.size() - 1); + T last = data.get(data.size() - 1); return idResolver.apply(last); }