Skip to content

Commit

Permalink
Finalizes AASX File Server (eclipse-basyx#334)
Browse files Browse the repository at this point in the history
* Adds AASX File Server API

Signed-off-by: FriedJannik <[email protected]>
Co-authored-by: Aaron Zielstorff <[email protected]>

* Adds MongoDB Backend for AASXFileServer
Adapts HTTP Test

Co-authored-by: Aaron Zielstorff <[email protected]>

* Applies Refactoring
Co-authored-by: Aaron Zielstorff <[email protected]>

* Fixes test and adds dependency to pom

* Adds missing dependency

* Makes use of AAS4J Package Description

* Adds missing dependency

* Adapts Parsing in test

* Code Review

* Adds missing Test cases

---------

Signed-off-by: FriedJannik <[email protected]>
Co-authored-by: Aaron Zielstorff <[email protected]>
  • Loading branch information
FriedJannik and aaronzi authored Aug 1, 2024
1 parent 1ac413e commit 9ca510f
Show file tree
Hide file tree
Showing 29 changed files with 1,372 additions and 179 deletions.
50 changes: 50 additions & 0 deletions basyx.aasxfileserver/basyx.aasxfileserver-backend-mongodb/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.digitaltwin.basyx</groupId>
<artifactId>basyx.aasxfileserver</artifactId>
<version>${revision}</version>
</parent>

<artifactId>basyx.aasxfileserver-backend-mongodb</artifactId>
<dependencies>
<dependency>
<groupId>org.eclipse.digitaltwin.basyx</groupId>
<artifactId>basyx.aasxfileserver-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.digitaltwin.basyx</groupId>
<artifactId>basyx.aasxfileserver-core</artifactId>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.digitaltwin.basyx</groupId>
<artifactId>basyx.aasxfileserver-backend</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.digitaltwin.basyx</groupId>
<artifactId>basyx.mongodbcore</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*******************************************************************************
* 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.aasxfileserver;

import org.eclipse.digitaltwin.basyx.aasxfileserver.backend.AASXFileServerBackendProvider;
import org.eclipse.digitaltwin.basyx.aasxfileserver.model.Package;
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.repository.CrudRepository;
import org.springframework.stereotype.Component;

/**
* Implementation of {@link AASXFileServerBackendProvider} for MongoDB Backend
*
* @author zielstor, fried
*
*/
@ConditionalOnExpression("'${basyx.backend}'.equals('MongoDB')")
@Component
public class AASXFileServerMongoDBBackendProvider implements AASXFileServerBackendProvider {

private AASXFileServerMongoDBCrudRepository repository;

@Autowired
public AASXFileServerMongoDBBackendProvider(MongoTemplate template, @Value("${basyx.aasx-fileserver.mongodb.collectionName:aasx-fileserver}") String collectionName, @Value("${basyx.aasx-fileserver.mongodb.collectionName:aasx-fileserver}") String gridFsBucketName) {
this.repository = new AASXFileServerMongoDBCrudRepository(template,collectionName,gridFsBucketName);
}

@Override
public CrudRepository<Package, String> getCrudRepository() {
return repository;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*******************************************************************************
* 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.aasxfileserver;
import com.mongodb.client.*;
import com.mongodb.client.gridfs.*;
import com.mongodb.client.gridfs.model.*;
import com.mongodb.client.model.Filters;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.eclipse.digitaltwin.aas4j.v3.model.PackageDescription;
import org.eclipse.digitaltwin.basyx.aasxfileserver.model.Package;
import org.eclipse.digitaltwin.basyx.aasxfileserver.model.PackagesBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.CrudRepository;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
* Implementation of {@link CrudRepository} for MongoDB Backend
*
* @author zielstor, fried
*/
public class AASXFileServerMongoDBCrudRepository implements CrudRepository<Package, String> {

private final MongoTemplate mongoTemplate;
private final String collectionName;
private final GridFSBucket gridFSBucket;

public AASXFileServerMongoDBCrudRepository(MongoTemplate mongoTemplate, String collectionName, String gridfsBucketName) {
this.mongoTemplate = mongoTemplate;
this.collectionName = collectionName;
this.gridFSBucket = GridFSBuckets.create(mongoTemplate.getDb(), gridfsBucketName);
}

@Override
public <S extends Package> S save(S entity) {
if (entity.getPackagesBody().getFile() != null) {
GridFSUploadOptions options = new GridFSUploadOptions();
ObjectId fileId = gridFSBucket.uploadFromStream(entity.getPackagesBody().getFileName(), entity.getPackagesBody().getFile(), options);
entity.getPackagesBody().setFile(null);
entity.getPackagesBody().setPackageId(fileId.toString());
}
mongoTemplate.save(entity, collectionName);
return entity;
}

@Override
public <S extends Package> Iterable<S> saveAll(Iterable<S> entities) {
List<S> result = new ArrayList<>();
for (S entity : entities) {
result.add(save(entity));
}
return result;
}

@Override
public Optional<Package> findById(String id) {
Package pkg = mongoTemplate.findById(id, Package.class, collectionName);
if (pkg != null && pkg.getPackagesBody().getPackageId() != null) {
InputStream file = gridFSBucket.openDownloadStream(new ObjectId(pkg.getPackagesBody().getPackageId()));
pkg.getPackagesBody().setFile(file);
}
return Optional.ofNullable(pkg);
}

@Override
public boolean existsById(String id) {
Query query = new Query(Criteria.where("packageId").is(id));
return mongoTemplate.exists(query, Package.class, collectionName);
}

@Override
public Iterable<Package> findAll() {
return mongoTemplate.findAll(Package.class, collectionName);
}

@Override
public Iterable<Package> findAllById(Iterable<String> ids) {
Query query = new Query(Criteria.where("packageId").in(ids));
return mongoTemplate.find(query, Package.class, collectionName);
}

@Override
public long count() {
return mongoTemplate.count(new Query(), Package.class, collectionName);
}

@Override
public void deleteById(String id) {
Package pkg = mongoTemplate.findAndRemove(new Query(Criteria.where("packageId").is(id)), Package.class, collectionName);
if (pkg != null && pkg.getPackagesBody().getPackageId() != null) {
gridFSBucket.delete(new ObjectId(pkg.getPackagesBody().getPackageId()));
}
}

@Override
public void delete(Package entity) {
deleteById(entity.getPackageId());
}

@Override
public void deleteAllById(Iterable<? extends String> ids) {
for (String id : ids) {
deleteById(id);
}
}

@Override
public void deleteAll(Iterable<? extends Package> entities) {
for (Package entity : entities) {
deleteById(entity.getPackageId());
}
}

@Override
public void deleteAll() {
mongoTemplate.dropCollection(collectionName);
gridFSBucket.drop();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (C) 2024 the Eclipse BaSyx Authors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* SPDX-License-Identifier: MIT
******************************************************************************/

package org.eclipse.digitaltwin.basyx.aasxfileserver;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.eclipse.digitaltwin.basyx.aasxfileserver.backend.SimpleAASXFileServerFactory;
import org.eclipse.digitaltwin.basyx.aasxfileserver.core.AASXFileServerSuite;
import org.eclipse.digitaltwin.basyx.common.mongocore.MongoDBUtilities;
import org.junit.Test;
import org.springframework.data.mongodb.core.MongoTemplate;

import static org.junit.Assert.assertEquals;

/**
* Tests the {@link AASXFileServerMongoDBBackendProvider}
*
* @author zielstor,fried
*
*/
public class TestMongoDBAASXFileServer extends AASXFileServerSuite {

private static final String CONFIGURED_AASX_SERVER_NAME = "configured-aasx-server-name";
private final String CONNECTION_URL = "mongodb://mongoAdmin:mongoPassword@localhost:27017";
private final MongoClient CLIENT = MongoClients.create(CONNECTION_URL);
private final MongoTemplate TEMPLATE = new MongoTemplate(CLIENT, "BaSyxTestDb");

@Override
protected AASXFileServer getAASXFileServer() {
MongoDBUtilities.clearCollection(TEMPLATE, "BaSyxAASXFileServerTest");
MongoDBUtilities.clearCollection(TEMPLATE, "BaSyxAASXFileServerTestFileBucket.chunks");
MongoDBUtilities.clearCollection(TEMPLATE, "BaSyxAASXFileServerTestFileBucket.files");
return new SimpleAASXFileServerFactory(new AASXFileServerMongoDBBackendProvider(TEMPLATE,"BaSyxAASXFileServerTest","BaSyxAASXFileServerTestFileBucket")).create();
}

@Test
public void getConfiguredInMemoryAASXFileServer() {
AASXFileServer server = new SimpleAASXFileServerFactory(new AASXFileServerMongoDBBackendProvider(TEMPLATE,"BaSyxAASXFileServerTest","BaSyxAASXFileServerTestFileBucket"),CONFIGURED_AASX_SERVER_NAME).create();

assertEquals(CONFIGURED_AASX_SERVER_NAME, server.getName());
}

}
Loading

0 comments on commit 9ca510f

Please sign in to comment.