diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/ElementNotAFileException.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/ElementNotAFileException.java
new file mode 100644
index 000000000..59fed0ddd
--- /dev/null
+++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/ElementNotAFileException.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.core.exceptions;
+
+/**
+ * Indicates that the requested submodel element is not a File SubmodelElement
+ *
+ * @author danish
+ *
+ */
+@SuppressWarnings("serial")
+public class ElementNotAFileException extends RuntimeException {
+ public ElementNotAFileException() {
+ }
+
+ public ElementNotAFileException(String elementId) {
+ super(getMsg(elementId));
+ }
+
+ private static String getMsg(String elementId) {
+ return "SubmodelElement with Id " + elementId + " is not a File";
+ }
+}
diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FeatureNotImplementedException.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FeatureNotImplementedException.java
new file mode 100644
index 000000000..1d13ab9b3
--- /dev/null
+++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FeatureNotImplementedException.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.core.exceptions;
+
+/**
+ * This exception is used for features where certain functionalities are not implemented yet.
+ *
+ * @author zhangzai
+ *
+ */
+@SuppressWarnings("serial")
+public class FeatureNotImplementedException extends RuntimeException {
+
+ public FeatureNotImplementedException() {
+ super();
+ }
+
+ public FeatureNotImplementedException(String featureName) {
+ super(getMessage(featureName));
+ }
+
+ private static String getMessage(String featureName) {
+ return "Feature " + featureName + " is not implemented yet";
+ }
+}
diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FileDoesNotExistException.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FileDoesNotExistException.java
new file mode 100644
index 000000000..bc1ae701f
--- /dev/null
+++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FileDoesNotExistException.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.core.exceptions;
+
+/**
+ * Indicates that the requested file does not exist
+ *
+ * @author danish
+ *
+ */
+@SuppressWarnings("serial")
+public class FileDoesNotExistException extends RuntimeException {
+ public FileDoesNotExistException() {
+ }
+
+ public FileDoesNotExistException(String elementId) {
+ super(getMsg(elementId));
+ }
+
+ private static String getMsg(String elementId) {
+ return "Requested File inside File SubmodelElement with ID : " + elementId + " does not exist";
+ }
+
+}
diff --git a/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FileHandlingException.java b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FileHandlingException.java
new file mode 100644
index 000000000..8d7b9c11b
--- /dev/null
+++ b/basyx.common/basyx.core/src/main/java/org/eclipse/digitaltwin/basyx/core/exceptions/FileHandlingException.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.core.exceptions;
+
+/**
+ * Indicates that the provided file could not be handled
+ *
+ * @author zhangzai
+ *
+ */
+@SuppressWarnings("serial")
+public class FileHandlingException extends RuntimeException {
+
+ public FileHandlingException() {
+ super();
+ }
+
+ public FileHandlingException(String fileName) {
+ super(getMessage(fileName));
+ }
+
+ private static String getMessage(String fileName) {
+ return "Exception occurred while handling the file: " + fileName;
+ }
+
+}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/pom.xml b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/pom.xml
index 2e0148c9e..170fe105e 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/pom.xml
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/pom.xml
@@ -45,5 +45,13 @@
org.springframework.boot
spring-boot-starter
+
+ org.apache.tika
+ tika-core
+
+
+ commons-io
+ commons-io
+
\ No newline at end of file
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/InMemorySubmodelRepository.java b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/InMemorySubmodelRepository.java
index e22bbc98e..165ac560b 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/InMemorySubmodelRepository.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/InMemorySubmodelRepository.java
@@ -25,6 +25,12 @@
package org.eclipse.digitaltwin.basyx.submodelrepository;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -39,23 +45,30 @@
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.apache.commons.io.IOUtils;
+import org.apache.tika.utils.StringUtils;
+import org.eclipse.digitaltwin.aas4j.v3.model.File;
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException;
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.FileDoesNotExistException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.FileHandlingException;
import org.eclipse.digitaltwin.basyx.core.exceptions.IdentificationMismatchException;
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.submodelservice.SubmodelService;
import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelServiceFactory;
+import org.eclipse.digitaltwin.basyx.submodelservice.value.FileBlobValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelValueOnly;
/**
* In-memory implementation of the SubmodelRepository
*
- * @author schnicke, danish, kammognie
+ * @author schnicke, danish, kammognie, zhangzai
*
*/
public class InMemorySubmodelRepository implements SubmodelRepository {
@@ -64,6 +77,7 @@ public class InMemorySubmodelRepository implements SubmodelRepository {
private Map submodelServices = new LinkedHashMap<>();
private SubmodelServiceFactory submodelServiceFactory;
private String smRepositoryName;
+ private String tmpDirectory = getTemporaryDirectoryPath();
/**
* Creates the InMemorySubmodelRepository utilizing the passed
@@ -74,13 +88,14 @@ public class InMemorySubmodelRepository implements SubmodelRepository {
public InMemorySubmodelRepository(SubmodelServiceFactory submodelServiceFactory) {
this.submodelServiceFactory = submodelServiceFactory;
}
-
+
/**
* Creates the InMemorySubmodelRepository utilizing the passed
* SubmodelServiceFactory for creating new SubmodelServices
*
- * @param submodelServiceFactory
- * @param smRepositoryName Name of the SubmodelRepository
+ * @param submodelServiceFactory
+ * @param smRepositoryName
+ * Name of the SubmodelRepository
*/
public InMemorySubmodelRepository(SubmodelServiceFactory submodelServiceFactory, String smRepositoryName) {
this(submodelServiceFactory);
@@ -101,15 +116,16 @@ public InMemorySubmodelRepository(SubmodelServiceFactory submodelServiceFactory,
submodelServices = createServices(submodels);
}
-
+
/**
* Creates the InMemorySubmodelRepository utilizing the passed
* SubmodelServiceFactory for creating new SubmodelServices and preconfiguring
* it with the passed Submodels
*
- * @param submodelServiceFactory
- * @param submodels
- * @param smRepositoryName Name of the SubmodelRepository
+ * @param submodelServiceFactory
+ * @param submodels
+ * @param smRepositoryName
+ * Name of the SubmodelRepository
*/
public InMemorySubmodelRepository(SubmodelServiceFactory submodelServiceFactory, Collection submodels, String smRepositoryName) {
this(submodelServiceFactory, submodels);
@@ -119,13 +135,9 @@ public InMemorySubmodelRepository(SubmodelServiceFactory submodelServiceFactory,
private void throwIfHasCollidingIds(Collection submodelsToCheck) {
Set ids = new HashSet<>();
- submodelsToCheck.stream()
- .map(submodel -> submodel.getId())
- .filter(id -> !ids.add(id))
- .findAny()
- .ifPresent(id -> {
- throw new CollidingIdentifierException(id);
- });
+ submodelsToCheck.stream().map(submodel -> submodel.getId()).filter(id -> !ids.add(id)).findAny().ifPresent(id -> {
+ throw new CollidingIdentifierException(id);
+ });
}
private Map createServices(Collection submodels) {
@@ -137,13 +149,9 @@ private Map createServices(Collection submode
@Override
public CursorResult> getAllSubmodels(PaginationInfo pInfo) {
- List allSubmodels = submodelServices.values()
- .stream()
- .map(service -> service.getSubmodel())
- .collect(Collectors.toList());
+ List allSubmodels = submodelServices.values().stream().map(service -> service.getSubmodel()).collect(Collectors.toList());
- TreeMap submodelMap = allSubmodels.stream()
- .collect(Collectors.toMap(Submodel::getId, aas -> aas, (a, b) -> a, TreeMap::new));
+ TreeMap submodelMap = allSubmodels.stream().collect(Collectors.toMap(Submodel::getId, aas -> aas, (a, b) -> a, TreeMap::new));
PaginationSupport paginationSupport = new PaginationSupport<>(submodelMap, Submodel::getId);
CursorResult> paginatedSubmodels = paginationSupport.getPaged(pInfo);
@@ -202,8 +210,7 @@ public void deleteSubmodel(String submodelId) throws ElementDoesNotExistExceptio
public void createSubmodelElement(String submodelId, SubmodelElement smElement) {
throwIfSubmodelDoesNotExist(submodelId);
- submodelServices.get(submodelId)
- .createSubmodelElement(smElement);
+ submodelServices.get(submodelId).createSubmodelElement(smElement);
}
@Override
@@ -235,7 +242,7 @@ public Submodel getSubmodelByIdMetadata(String submodelId) {
throw new RuntimeException("Unable to serialize the Submodel", e);
}
}
-
+
@Override
public String getName() {
return smRepositoryName == null ? SubmodelRepository.super.getName() : smRepositoryName;
@@ -246,6 +253,68 @@ public OperationVariable[] invokeOperation(String submodelId, String idShortPath
return getSubmodelService(submodelId).invokeOperation(idShortPath, input);
}
+ @Override
+ public java.io.File getFileByPathSubmodel(String submodelId, String idShortPath) {
+ throwIfSubmodelDoesNotExist(submodelId);
+
+ SubmodelElement submodelElement = submodelServices.get(submodelId).getSubmodelElement(idShortPath);
+
+ throwIfSmElementIsNotAFile(submodelElement);
+
+ String filePath = getFilePath(submodelElement);
+
+ throwIfFileDoesNotExist((File) submodelElement, filePath);
+
+ return new java.io.File(filePath);
+ }
+
+ @Override
+ public void setFileValue(String submodelId, String idShortPath, String fileName, InputStream inputStream) {
+ throwIfSubmodelDoesNotExist(submodelId);
+
+ SubmodelElement submodelElement = submodelServices.get(submodelId).getSubmodelElement(idShortPath);
+ throwIfSmElementIsNotAFile(submodelElement);
+
+ File fileSmElement = (File) submodelElement;
+ deleteExistingFile(fileSmElement);
+ String filePath = createFilePath(submodelId, idShortPath, fileName);
+
+ createFileAtSpecifiedPath(fileName, inputStream, filePath);
+
+ FileBlobValue fileValue = new FileBlobValue(fileSmElement.getContentType(), filePath);
+
+ setSubmodelElementValue(submodelId, idShortPath, fileValue);
+ }
+
+ @Override
+ public void deleteFileValue(String submodelId, String idShortPath) {
+ throwIfSubmodelDoesNotExist(submodelId);
+
+ SubmodelElement submodelElement = submodelServices.get(submodelId).getSubmodelElement(idShortPath);
+
+ throwIfSmElementIsNotAFile(submodelElement);
+
+ File fileSubmodelElement = (File) submodelElement;
+ String filePath = fileSubmodelElement.getValue();
+
+ throwIfFileDoesNotExist(fileSubmodelElement, filePath);
+
+ java.io.File tmpFile = new java.io.File(filePath);
+ tmpFile.delete();
+
+ FileBlobValue fileValue = new FileBlobValue(StringUtils.EMPTY, StringUtils.EMPTY);
+
+ setSubmodelElementValue(submodelId, idShortPath, fileValue);
+ }
+
+ private String createFilePath(String submodelId, String idShortPath, String fileName) {
+ return tmpDirectory + "/" + submodelId + "-" + idShortPath.replace("/", "-") + "-" + fileName;
+ }
+
+ private void throwIfSmElementIsNotAFile(SubmodelElement submodelElement) {
+ if (!(submodelElement instanceof File))
+ throw new ElementNotAFileException(submodelElement.getIdShort());
+ }
private void throwIfMismatchingIds(String smId, Submodel newSubmodel) {
String newSubmodelId = newSubmodel.getId();
@@ -254,7 +323,6 @@ private void throwIfMismatchingIds(String smId, Submodel newSubmodel) {
throw new IdentificationMismatchException();
}
-
private SubmodelService getSubmodelService(String submodelId) {
throwIfSubmodelDoesNotExist(submodelId);
@@ -271,4 +339,53 @@ private void throwIfSubmodelDoesNotExist(String id) {
throw new ElementDoesNotExistException(id);
}
+ private void throwIfFileDoesNotExist(File fileSmElement, String filePath) {
+ if (fileSmElement.getValue().isBlank() || !isFilePathValid(filePath))
+ throw new FileDoesNotExistException(fileSmElement.getIdShort());
+ }
+
+ private boolean isFilePathValid(String filePath) {
+ try {
+ Paths.get(filePath);
+ } catch (InvalidPathException | NullPointerException ex) {
+ return false;
+ }
+ return true;
+ }
+
+ private String getTemporaryDirectoryPath() {
+ String tempDirectoryPath = "";
+ try {
+ tempDirectoryPath = Files.createTempDirectory("basyx-temp").toAbsolutePath().toString();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return tempDirectoryPath;
+ }
+
+ private String getFilePath(SubmodelElement submodelElement) {
+ return ((File) submodelElement).getValue();
+ }
+
+ private void deleteExistingFile(File fileSmElement) {
+ String filePath = fileSmElement.getValue();
+ if(filePath.isEmpty()) return;
+
+ try {
+ Files.deleteIfExists(Paths.get(filePath, ""));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void createFileAtSpecifiedPath(String fileName, InputStream inputStream, String filePath) {
+ java.io.File targetFile = new java.io.File(filePath);
+
+ try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
+ IOUtils.copy(inputStream, outStream);
+ } catch (IOException e) {
+ throw new FileHandlingException(fileName);
+ }
+ }
+
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/TestInMemorySubmodelRepository.java b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/TestInMemorySubmodelRepository.java
index 1d9cf5a3d..4fc12db12 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/TestInMemorySubmodelRepository.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/TestInMemorySubmodelRepository.java
@@ -44,7 +44,7 @@
*
*/
public class TestInMemorySubmodelRepository extends SubmodelRepositorySuite {
-
+
private static final String CONFIGURED_SM_REPO_NAME = "configured-sm-repo-name";
@Override
@@ -58,12 +58,12 @@ protected SubmodelRepository getSubmodelRepository(Collection submodel
}
@Test
- public void getConfiguredInMemorySmRepositoryName() {
+ public void getConfiguredInMemorySmRepositoryName() {
SubmodelRepository repo = new InMemorySubmodelRepository(new InMemorySubmodelServiceFactory(), CONFIGURED_SM_REPO_NAME);
-
+
assertEquals(CONFIGURED_SM_REPO_NAME, repo.getName());
}
-
+
@Test(expected = CollidingIdentifierException.class)
public void idCollisionDuringConstruction() {
Collection submodelsWithCollidingIds = createSubmodelCollectionWithCollidingIds();
@@ -83,4 +83,5 @@ private Collection createSubmodelCollectionWithCollidingIds() {
private Collection createSubmodelCollectionWithUniqueIds() {
return Arrays.asList(DummySubmodelFactory.createSimpleDataSubmodel(), DummySubmodelFactory.createTechnicalDataSubmodel());
}
+
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/test/resources/SampleJsonFile.json b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/test/resources/SampleJsonFile.json
new file mode 100644
index 000000000..f1ce92ea3
--- /dev/null
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-inmemory/src/test/resources/SampleJsonFile.json
@@ -0,0 +1,5 @@
+{
+ "name": "SampleJsonFile",
+ "description": "A JSON file for verification",
+ "version": 123
+}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/pom.xml b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/pom.xml
index afc17f693..2d38ea0cd 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/pom.xml
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/pom.xml
@@ -37,5 +37,9 @@
org.eclipse.digitaltwin.basyx
basyx.submodelservice-core
+
+ org.apache.tika
+ tika-core
+
\ No newline at end of file
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/MongoDBSubmodelRepository.java b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/MongoDBSubmodelRepository.java
index de3b22829..5b490a62d 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/MongoDBSubmodelRepository.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/MongoDBSubmodelRepository.java
@@ -24,21 +24,35 @@
******************************************************************************/
package org.eclipse.digitaltwin.basyx.submodelrepository;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
+import org.apache.commons.io.FileUtils;
+import org.apache.tika.mime.MimeType;
+import org.apache.tika.mime.MimeTypeException;
+import org.apache.tika.mime.MimeTypes;
+import org.apache.tika.utils.StringUtils;
+import org.bson.types.ObjectId;
+import org.eclipse.digitaltwin.aas4j.v3.model.File;
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException;
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
import org.eclipse.digitaltwin.basyx.core.exceptions.FeatureNotSupportedException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.FileDoesNotExistException;
import org.eclipse.digitaltwin.basyx.core.exceptions.IdentificationMismatchException;
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService;
import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelServiceFactory;
+import org.eclipse.digitaltwin.basyx.submodelservice.value.FileBlobValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelValueOnly;
import org.springframework.data.domain.Sort;
@@ -47,25 +61,30 @@
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
-
+import org.springframework.data.mongodb.gridfs.GridFsTemplate;
+import com.mongodb.client.gridfs.model.GridFSFile;
import com.mongodb.client.result.DeleteResult;
/**
* MongoDB implementation of the SubmodelRepository
*
- * @author jungjan, kammognie
+ * @author jungjan, kammognie, zhangzai, danish
*
*/
public class MongoDBSubmodelRepository implements SubmodelRepository {
private static final PaginationInfo NO_LIMIT_PAGINATION_INFO = new PaginationInfo(0, null);
- private static final String ID = "_id";
- private static String ID_JSON_PATH = "id";
+ private static final String MONGO_ID = "_id";
+ private static final String TEMP_DIR_PREFIX = "basyx-temp";
+ private static final String GRIDFS_ID_DELIMITER = "#";
+ private static final String ID_JSON_PATH = "id";
private MongoTemplate mongoTemplate;
private String collectionName;
private SubmodelServiceFactory submodelServiceFactory;
private String smRepositoryName;
+ private GridFsTemplate gridFsTemplate;
+
/**
* Creates the MongoDBSubmodelRepository utilizing the passed
* SubmodelServiceFactory for creating new SubmodelServices and uses a
@@ -75,12 +94,13 @@ public class MongoDBSubmodelRepository implements SubmodelRepository {
* @param collectionName
* @param submodelServiceFactory
*/
- public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionName,
- SubmodelServiceFactory submodelServiceFactory) {
+ public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionName, SubmodelServiceFactory submodelServiceFactory) {
this.mongoTemplate = mongoTemplate;
this.collectionName = collectionName;
this.submodelServiceFactory = submodelServiceFactory;
configureIndexForSubmodelId(mongoTemplate);
+
+ configureDefaultGridFsTemplate(this.mongoTemplate);
}
/**
@@ -88,15 +108,21 @@ public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionN
* SubmodelServiceFactory for creating new SubmodelServices and uses a
* collectionName and a mongoTemplate for operating MongoDB
*
- * @param mongoTemplate
- * @param collectionName
- * @param submodelServiceFactory
- * @param smRepositoryName Name of the SubmodelRepository
+ * @param mongoTemplate
+ * @param collectionName
+ * @param submodelServiceFactory
+ * @param smRepositoryName
+ * Name of the SubmodelRepository
*/
- public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionName,
- SubmodelServiceFactory submodelServiceFactory, String smRepositoryName) {
+ public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionName, SubmodelServiceFactory submodelServiceFactory, String smRepositoryName, GridFsTemplate gridFsTemplate) {
this(mongoTemplate, collectionName, submodelServiceFactory);
this.smRepositoryName = smRepositoryName;
+ this.gridFsTemplate = gridFsTemplate;
+
+ if (this.gridFsTemplate == null)
+ configureDefaultGridFsTemplate(mongoTemplate);
+
+ configureIndexForSubmodelId(mongoTemplate);
}
/**
@@ -108,30 +134,35 @@ public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionN
* @param submodelServiceFactory
* @param submodels
*/
- public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionName,
- SubmodelServiceFactory submodelServiceFactory, Collection submodels) {
+ public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionName, SubmodelServiceFactory submodelServiceFactory, Collection submodels) {
this(mongoTemplate, collectionName, submodelServiceFactory);
initializeRemoteCollection(submodels);
+
+ configureDefaultGridFsTemplate(this.mongoTemplate);
}
/**
* Creates the MongoDBSubmodelRepository utilizing the passed
* SubmodelServiceFactory for creating new SubmodelServices and uses a
* collectionName and a mongoTemplate for operating MongoDB. Additionally
- * initializes the MongoDB collection with a collection of submodels.
- * And configures the SubmodelRepository name.
+ * initializes the MongoDB collection with a collection of submodels. And
+ * configures the SubmodelRepository name.
*
* @param mongoTemplate
* @param collectionName
* @param submodelServiceFactory
* @param submodels
- * @param smRepositoryName Name of the SubmodelRepository
+ * @param smRepositoryName
+ * Name of the SubmodelRepository
*/
- public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionName,
- SubmodelServiceFactory submodelServiceFactory, Collection submodels, String smRepositoryName) {
+ public MongoDBSubmodelRepository(MongoTemplate mongoTemplate, String collectionName, SubmodelServiceFactory submodelServiceFactory, Collection submodels, String smRepositoryName, GridFsTemplate gridFsTemplate) {
this(mongoTemplate, collectionName, submodelServiceFactory, submodels);
-
+
this.smRepositoryName = smRepositoryName;
+ this.gridFsTemplate = gridFsTemplate;
+
+ if (this.gridFsTemplate == null)
+ configureDefaultGridFsTemplate(mongoTemplate);
}
private void initializeRemoteCollection(Collection submodels) {
@@ -143,8 +174,7 @@ private void initializeRemoteCollection(Collection submodels) {
private void configureIndexForSubmodelId(MongoTemplate mongoTemplate) {
Index idIndex = new Index().on(ID_JSON_PATH, Direction.ASC);
- mongoTemplate.indexOps(Submodel.class)
- .ensureIndex(idIndex);
+ mongoTemplate.indexOps(Submodel.class).ensureIndex(idIndex);
}
@Override
@@ -160,8 +190,7 @@ public CursorResult> getAllSubmodels(PaginationInfo pInfo) {
@Override
public Submodel getSubmodel(String submodelId) throws ElementDoesNotExistException {
- Submodel submodel = mongoTemplate.findOne(new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodelId)),
- Submodel.class, collectionName);
+ Submodel submodel = mongoTemplate.findOne(new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodelId)), Submodel.class, collectionName);
if (submodel == null) {
throw new ElementDoesNotExistException(submodelId);
}
@@ -200,8 +229,7 @@ public void createSubmodel(Submodel submodel) throws CollidingIdentifierExceptio
}
private void throwIfCollidesWithRemoteId(Submodel submodel) {
- if (mongoTemplate.exists(new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodel.getId())),
- Submodel.class, collectionName)) {
+ if (mongoTemplate.exists(new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodel.getId())), Submodel.class, collectionName)) {
throw new CollidingIdentifierException(submodel.getId());
}
}
@@ -211,26 +239,22 @@ private SubmodelService getSubmodelService(String submodelId) {
}
@Override
- public CursorResult> getSubmodelElements(String submodelId, PaginationInfo pInfo)
- throws ElementDoesNotExistException {
+ public CursorResult> getSubmodelElements(String submodelId, PaginationInfo pInfo) throws ElementDoesNotExistException {
return getSubmodelService(submodelId).getSubmodelElements(pInfo);
}
@Override
- public SubmodelElement getSubmodelElement(String submodelId, String submodelElementIdShort)
- throws ElementDoesNotExistException {
+ public SubmodelElement getSubmodelElement(String submodelId, String submodelElementIdShort) throws ElementDoesNotExistException {
return getSubmodelService(submodelId).getSubmodelElement(submodelElementIdShort);
}
@Override
- public SubmodelElementValue getSubmodelElementValue(String submodelId, String submodelElementIdShort)
- throws ElementDoesNotExistException {
+ public SubmodelElementValue getSubmodelElementValue(String submodelId, String submodelElementIdShort) throws ElementDoesNotExistException {
return getSubmodelService(submodelId).getSubmodelElementValue(submodelElementIdShort);
}
@Override
- public void setSubmodelElementValue(String submodelId, String submodelElementIdShort, SubmodelElementValue value)
- throws ElementDoesNotExistException {
+ public void setSubmodelElementValue(String submodelId, String submodelElementIdShort, SubmodelElementValue value) throws ElementDoesNotExistException {
SubmodelService submodelService = getSubmodelService(submodelId);
submodelService.setSubmodelElementValue(submodelElementIdShort, value);
@@ -239,8 +263,7 @@ public void setSubmodelElementValue(String submodelId, String submodelElementIdS
@Override
public void deleteSubmodel(String submodelId) throws ElementDoesNotExistException {
- DeleteResult result = mongoTemplate.remove(new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodelId)),
- Submodel.class, collectionName);
+ DeleteResult result = mongoTemplate.remove(new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodelId)), Submodel.class, collectionName);
if (result.getDeletedCount() == 0) {
throw new ElementDoesNotExistException(submodelId);
@@ -257,8 +280,7 @@ public void createSubmodelElement(String submodelId, SubmodelElement submodelEle
}
@Override
- public void createSubmodelElement(String submodelId, String idShortPath, SubmodelElement submodelElement)
- throws ElementDoesNotExistException {
+ public void createSubmodelElement(String submodelId, String idShortPath, SubmodelElement submodelElement) throws ElementDoesNotExistException {
SubmodelService submodelService = getSubmodelService(submodelId);
submodelService.createSubmodelElement(idShortPath, submodelElement);
@@ -288,10 +310,9 @@ public Submodel getSubmodelByIdMetadata(String submodelId) throws ElementDoesNot
@Override
public String getName() {
return smRepositoryName == null ? SubmodelRepository.super.getName() : smRepositoryName;
- }
-
- private String resolveCursor(PaginationInfo pRequest, List foundDescriptors,
- Function idResolver) {
+ }
+
+ private String resolveCursor(PaginationInfo pRequest, List foundDescriptors, Function idResolver) {
if (foundDescriptors.isEmpty() || !pRequest.isPaged()) {
return null;
}
@@ -300,12 +321,12 @@ private String resolveCursor(PaginationInfo pRequest, List foundDescripto
}
private void applySorting(Query query, PaginationInfo pInfo) {
- query.with(Sort.by(Direction.ASC, ID));
+ query.with(Sort.by(Direction.ASC, MONGO_ID));
}
private void applyPagination(Query query, PaginationInfo pInfo) {
if (pInfo.getCursor() != null) {
- query.addCriteria(Criteria.where(ID).gt(pInfo.getCursor()));
+ query.addCriteria(Criteria.where(MONGO_ID).gt(pInfo.getCursor()));
}
if (pInfo.getLimit() != null) {
query.limit(pInfo.getLimit());
@@ -317,4 +338,151 @@ public OperationVariable[] invokeOperation(String submodelId, String idShortPath
throw new FeatureNotSupportedException("Operation Invocation");
}
+ @Override
+ public java.io.File getFileByPathSubmodel(String submodelId, String idShortPath) {
+ Query query = new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodelId));
+
+ throwIfSubmodelDoesNotExist(query, submodelId);
+
+ SubmodelElement submodelElement = getSubmodelService(submodelId).getSubmodelElement(idShortPath);
+
+ throwIfSmElementIsNotAFile(submodelElement);
+
+ File fileSmElement = (File) submodelElement;
+
+ throwIfFileDoesNotExist(fileSmElement);
+
+ String fileId = getFileId(fileSmElement.getValue());
+
+ GridFSFile file = gridFsTemplate.findOne(new Query(Criteria.where(MONGO_ID).is(fileId)));
+
+ InputStream fileIs = getGridFsFileAsInputStream(file);
+
+ return createFileInTempDirectory(idShortPath, fileSmElement, fileIs);
+ }
+
+ @Override
+ public void deleteFileValue(String submodelId, String idShortPath) {
+ Query query = new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodelId));
+
+ throwIfSubmodelDoesNotExist(query, submodelId);
+
+ SubmodelElement submodelElement = getSubmodelService(submodelId).getSubmodelElement(idShortPath);
+
+ throwIfSmElementIsNotAFile(submodelElement);
+
+ File fileSmElement = (File) submodelElement;
+
+ throwIfFileDoesNotExist(fileSmElement);
+
+ String fileId = getFileId(fileSmElement.getValue());
+
+ gridFsTemplate.delete(new Query(Criteria.where(MONGO_ID).is(fileId)));
+
+ FileBlobValue fileValue = new FileBlobValue(StringUtils.EMPTY, StringUtils.EMPTY);
+
+ setSubmodelElementValue(submodelId, idShortPath, fileValue);
+ }
+
+ @Override
+ public void setFileValue(String submodelId, String idShortPath, String fileName, InputStream inputStream) {
+ Query query = new Query().addCriteria(Criteria.where(ID_JSON_PATH).is(submodelId));
+
+ throwIfSubmodelDoesNotExist(query, submodelId);
+
+ SubmodelElement submodelElement = getSubmodelService(submodelId).getSubmodelElement(idShortPath);
+
+ throwIfSmElementIsNotAFile(submodelElement);
+
+ File fileSmElement = (File) submodelElement;
+
+ ObjectId id = gridFsTemplate.store(inputStream, fileSmElement.getValue(), fileSmElement.getContentType());
+
+ FileBlobValue fileValue = new FileBlobValue(fileSmElement.getContentType(), appendFsIdToFileValue(fileSmElement, id));
+
+ setSubmodelElementValue(submodelId, idShortPath, fileValue);
+ }
+
+ private void configureDefaultGridFsTemplate(MongoTemplate mongoTemplate) {
+ this.gridFsTemplate = new GridFsTemplate(mongoTemplate.getMongoDatabaseFactory(), mongoTemplate.getConverter());
+ }
+
+ private String appendFsIdToFileValue(File fileSmElement, ObjectId id) {
+ return id.toString() + GRIDFS_ID_DELIMITER + fileSmElement.getValue();
+ }
+
+ private java.io.File createFileInTempDirectory(String idShortPath, File fileSmElement, InputStream fileIs) {
+
+ Path tempDir = createTempDirectory(TEMP_DIR_PREFIX);
+
+ String absolutePath = tempDir.toAbsolutePath().toString();
+
+ String filePath = getFilePath(absolutePath, idShortPath, fileSmElement.getContentType());
+
+ java.io.File targetFile = new java.io.File(filePath);
+
+ try {
+ FileUtils.copyInputStreamToFile(fileIs, targetFile);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return targetFile;
+ }
+
+ private Path createTempDirectory(String prefix) {
+ Path tempDir = null;
+ try {
+ tempDir = Files.createTempDirectory(prefix);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return tempDir;
+ }
+
+ private InputStream getGridFsFileAsInputStream(GridFSFile file) {
+ InputStream fileIs = null;
+
+ try {
+ fileIs = gridFsTemplate.getResource(file).getInputStream();
+ } catch (IllegalStateException | IOException e1) {
+ e1.printStackTrace();
+ }
+ return fileIs;
+ }
+
+ private String getFileId(String value) {
+ return value.substring(0, value.indexOf(GRIDFS_ID_DELIMITER));
+ }
+
+ private void throwIfFileDoesNotExist(File fileSmElement) {
+ if (fileSmElement.getValue().isBlank() || fileSmElement.getValue().indexOf(GRIDFS_ID_DELIMITER) == -1)
+ throw new FileDoesNotExistException(fileSmElement.getIdShort());
+ }
+
+ private void throwIfSmElementIsNotAFile(SubmodelElement submodelElement) {
+
+ if (!(submodelElement instanceof File))
+ throw new ElementNotAFileException(submodelElement.getIdShort());
+ }
+
+ private String getFilePath(String tmpDirectory, String idShortPath, String contentType) {
+ String fileName = idShortPath.replace("/", "-");
+
+ String extension = getFileExtension(contentType);
+
+ return tmpDirectory + "/" + fileName + extension;
+ }
+
+ private String getFileExtension(String contentType) {
+ MimeTypes allTypes = MimeTypes.getDefaultMimeTypes();
+ try {
+ MimeType mimeType = allTypes.forName(contentType);
+ return mimeType.getExtension();
+ } catch (MimeTypeException e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/MongoDBSubmodelRepositoryFactory.java b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/MongoDBSubmodelRepositoryFactory.java
index c3659566c..542282db6 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/MongoDBSubmodelRepositoryFactory.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/MongoDBSubmodelRepositoryFactory.java
@@ -32,12 +32,13 @@
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.gridfs.GridFsTemplate;
import org.springframework.stereotype.Component;
/**
* SubmodelRepository factory returning a MongoDb backend SubmodelRepository
*
- * @author jungjan
+ * @author jungjan, zhangzai
*
*/
@Component
@@ -48,46 +49,52 @@ public class MongoDBSubmodelRepositoryFactory implements SubmodelRepositoryFacto
private String collectionName;
private SubmodelServiceFactory submodelServiceFactory;
private Collection submodels;
-
+
private String smRepositoryName;
+ private GridFsTemplate gridFsTemplate;
@Autowired(required = false)
- public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate,
- @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName,
- SubmodelServiceFactory submodelServiceFactory) {
+ public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate, @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName, SubmodelServiceFactory submodelServiceFactory) {
this.mongoTemplate = mongoTemplate;
this.collectionName = collectionName;
this.submodelServiceFactory = submodelServiceFactory;
}
- public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate,
- @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName,
- SubmodelServiceFactory submodelServiceFactory, @Value("${basyx.smrepo.name:sm-repo}") String smRepositoryName) {
+ @Autowired(required = false)
+ public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate, @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName, SubmodelServiceFactory submodelServiceFactory,
+ GridFsTemplate gridFsTemplate) {
this(mongoTemplate, collectionName, submodelServiceFactory);
+ this.gridFsTemplate = gridFsTemplate;
+ }
+
+ @Autowired(required = false)
+ public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate, @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName, SubmodelServiceFactory submodelServiceFactory,
+ GridFsTemplate gridFsTemplate, @Value("${basyx.smrepo.name:sm-repo}") String smRepositoryName) {
+ this(mongoTemplate, collectionName, submodelServiceFactory, gridFsTemplate);
this.smRepositoryName = smRepositoryName;
}
@Autowired(required = false)
- public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate,
- @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName,
- SubmodelServiceFactory submodelServiceFactory, Collection submodels) {
+ public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate, @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName, SubmodelServiceFactory submodelServiceFactory,
+ Collection submodels) {
this(mongoTemplate, collectionName, submodelServiceFactory);
this.submodels = submodels;
}
-
- public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate,
- @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName,
- SubmodelServiceFactory submodelServiceFactory, Collection submodels, @Value("${basyx.smrepo.name:sm-repo}") String smRepositoryName) {
+
+ @Autowired(required = false)
+ public MongoDBSubmodelRepositoryFactory(MongoTemplate mongoTemplate, @Value("${basyx.submodelrepository.mongodb.collectionName:submodel-repo}") String collectionName, SubmodelServiceFactory submodelServiceFactory,
+ Collection submodels, @Value("${basyx.smrepo.name:sm-repo}") String smRepositoryName, GridFsTemplate gridFsTemplate) {
this(mongoTemplate, collectionName, submodelServiceFactory, submodels);
this.smRepositoryName = smRepositoryName;
+ this.gridFsTemplate = gridFsTemplate;
}
@Override
public SubmodelRepository create() {
if (this.submodels == null || this.submodels.isEmpty()) {
- return new MongoDBSubmodelRepository(mongoTemplate, collectionName, submodelServiceFactory, smRepositoryName);
+ return new MongoDBSubmodelRepository(mongoTemplate, collectionName, submodelServiceFactory, smRepositoryName, gridFsTemplate);
}
- return new MongoDBSubmodelRepository(mongoTemplate, collectionName, submodelServiceFactory, submodels, smRepositoryName);
+ return new MongoDBSubmodelRepository(mongoTemplate, collectionName, submodelServiceFactory, submodels, smRepositoryName, gridFsTemplate);
}
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/TestMongoDBSubmodelRepository.java b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/TestMongoDBSubmodelRepository.java
index 27f0d29be..3fb882337 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/TestMongoDBSubmodelRepository.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/TestMongoDBSubmodelRepository.java
@@ -36,7 +36,8 @@
import org.eclipse.digitaltwin.basyx.submodelservice.InMemorySubmodelServiceFactory;
import org.junit.Test;
import org.springframework.data.mongodb.core.MongoTemplate;
-import org.junit.Test;
+import org.springframework.data.mongodb.gridfs.GridFsTemplate;
+
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
@@ -45,6 +46,7 @@ public class TestMongoDBSubmodelRepository extends SubmodelRepositorySuite {
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");
+ private final GridFsTemplate GRIDFS_TEMPLATE = new GridFsTemplate(TEMPLATE.getMongoDatabaseFactory(), TEMPLATE.getConverter(), "TestSMEFiles");
private final InMemorySubmodelServiceFactory SUBMODEL_SERVICE_FACTORY = new InMemorySubmodelServiceFactory();
private static final String CONFIGURED_SM_REPO_NAME = "configured-sm-repo-name";
@@ -52,7 +54,7 @@ public class TestMongoDBSubmodelRepository extends SubmodelRepositorySuite {
protected SubmodelRepository getSubmodelRepository() {
MongoDBUtilities.clearCollection(TEMPLATE, COLLECTION);
- return new MongoDBSubmodelRepositoryFactory(TEMPLATE, COLLECTION, SUBMODEL_SERVICE_FACTORY).create();
+ return new MongoDBSubmodelRepositoryFactory(TEMPLATE, COLLECTION, SUBMODEL_SERVICE_FACTORY, GRIDFS_TEMPLATE).create();
}
@Override
@@ -62,13 +64,13 @@ protected SubmodelRepository getSubmodelRepository(Collection submodel
// TODO: Remove this after MongoDB uses AAS4J serializer
submodels.forEach(this::removeInvokableFromInvokableOperation);
- return new MongoDBSubmodelRepositoryFactory(TEMPLATE, COLLECTION, SUBMODEL_SERVICE_FACTORY, submodels).create();
+ return new MongoDBSubmodelRepositoryFactory(TEMPLATE, COLLECTION, SUBMODEL_SERVICE_FACTORY, submodels, CONFIGURED_SM_REPO_NAME, GRIDFS_TEMPLATE).create();
}
-
+
@Test
public void getConfiguredMongoDBSmRepositoryName() {
- SubmodelRepository repo = new MongoDBSubmodelRepository(TEMPLATE, COLLECTION, SUBMODEL_SERVICE_FACTORY, CONFIGURED_SM_REPO_NAME);
-
+ SubmodelRepository repo = new MongoDBSubmodelRepository(TEMPLATE, COLLECTION, SUBMODEL_SERVICE_FACTORY, CONFIGURED_SM_REPO_NAME, GRIDFS_TEMPLATE);
+
assertEquals(CONFIGURED_SM_REPO_NAME, repo.getName());
}
@@ -85,10 +87,7 @@ public void invokeNonOperation() {
}
private void removeInvokableFromInvokableOperation(Submodel sm) {
- sm.getSubmodelElements().stream()
- .filter(InvokableOperation.class::isInstance)
- .map(InvokableOperation.class::cast)
- .forEach(o -> o.setInvokable(null));
+ sm.getSubmodelElements().stream().filter(InvokableOperation.class::isInstance).map(InvokableOperation.class::cast).forEach(o -> o.setInvokable(null));
}
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/test/resources/SampleJsonFile.json b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/test/resources/SampleJsonFile.json
new file mode 100644
index 000000000..f1ce92ea3
--- /dev/null
+++ b/basyx.submodelrepository/basyx.submodelrepository-backend-mongodb/src/test/resources/SampleJsonFile.json
@@ -0,0 +1,5 @@
+{
+ "name": "SampleJsonFile",
+ "description": "A JSON file for verification",
+ "version": 123
+}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-core/pom.xml b/basyx.submodelrepository/basyx.submodelrepository-core/pom.xml
index a704f5c1c..1fa44a1ee 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-core/pom.xml
+++ b/basyx.submodelrepository/basyx.submodelrepository-core/pom.xml
@@ -25,10 +25,14 @@
tests
test
-
org.eclipse.digitaltwin.aas4j
model
+
+ commons-io
+ commons-io
+ test
+
\ No newline at end of file
diff --git a/basyx.submodelrepository/basyx.submodelrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelRepository.java b/basyx.submodelrepository/basyx.submodelrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelRepository.java
index 5d2fa71ba..bf0d1947f 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelRepository.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-core/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/SubmodelRepository.java
@@ -26,12 +26,15 @@
package org.eclipse.digitaltwin.basyx.submodelrepository;
import java.util.List;
+import java.io.InputStream;
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException;
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.FileDoesNotExistException;
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue;
@@ -208,4 +211,48 @@ public default String getName() {
* @throws ElementDoesNotExistException
*/
public Submodel getSubmodelByIdMetadata(String submodelId) throws ElementDoesNotExistException;
+
+ /**
+ * Retrieves the file of a file submodelelement
+ *
+ * @param submodelId
+ * the Submodel id
+ * @param idShortPath
+ * the IdShort path of the file element
+ * @return
+ *
+ * @throws ElementDoesNotExistException
+ * @throws ElementNotAFileException
+ * @throws FileDoesNotExistException
+ */
+ public java.io.File getFileByPathSubmodel(String submodelId, String idShortPath) throws ElementDoesNotExistException, ElementNotAFileException, FileDoesNotExistException;
+
+ /**
+ * Uploads a file to a file submodelelement
+ *
+ * @param submodelId
+ * the Submodel id
+ * @param idShortPath
+ * the IdShort path of the file element
+ * @param file
+ * the file object to upload
+ *
+ * @throws ElementDoesNotExistException
+ * @throws ElementNotAFileException
+ */
+ public void setFileValue(String submodelId, String idShortPath, String fileName, InputStream inputStream) throws ElementDoesNotExistException, ElementNotAFileException;
+
+ /**
+ * Deletes the file of a file submodelelement
+ *
+ * @param submodelId
+ * the Submodel id
+ * @param idShortPath
+ * the IdShort path of the file element
+ *
+ * @throws ElementDoesNotExistException
+ * @throws ElementNotAFileException
+ * @throws FileDoesNotExistException
+ */
+ public void deleteFileValue(String submodelId, String idShortPath) throws ElementDoesNotExistException, ElementNotAFileException, FileDoesNotExistException;
}
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 37ba5d562..3a1503dea 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
@@ -29,9 +29,17 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.Collection;
import java.util.List;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
import org.eclipse.digitaltwin.aas4j.v3.model.DataTypeDefXSD;
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
import org.eclipse.digitaltwin.aas4j.v3.model.Property;
@@ -41,6 +49,8 @@
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel;
import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException;
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.FileDoesNotExistException;
import org.eclipse.digitaltwin.basyx.core.exceptions.IdentificationMismatchException;
import org.eclipse.digitaltwin.basyx.core.exceptions.NotInvokableException;
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
@@ -50,15 +60,17 @@
import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelServiceHelper;
import org.eclipse.digitaltwin.basyx.submodelservice.value.PropertyValue;
import org.junit.Test;
+import org.springframework.core.io.ClassPathResource;
/**
* Testsuite for implementations of the SubmodelRepository interface
*
- * @author schnicke, danish, kammognie
+ * @author schnicke, danish, kammognie, zhangzai
*
*/
public abstract class SubmodelRepositorySuite {
private static final PaginationInfo NO_LIMIT_PAGINATION_INFO = new PaginationInfo(0, null);
+ private static final String DUMMY_FILE_CONTENT = "this is a file";
protected abstract SubmodelRepository getSubmodelRepository();
@@ -185,7 +197,6 @@ public void getSubmodelElements() {
public void getSubmodelElementsOfNonExistingSubmodel() {
SubmodelRepository repo = getSubmodelRepositoryWithDummySubmodels();
repo.getSubmodelElements("notExisting", NO_LIMIT_PAGINATION_INFO).getResult();
-
}
@Test
@@ -242,6 +253,111 @@ public void setPropertyValue() {
assertEquals(expected, retrievedValue.getValue());
}
+
+ @Test
+ public void updateFile() {
+ SubmodelRepository repo = getSubmodelRepositoryWithDummySubmodels();
+
+ // Set the value of the file-submodelelement for the first time
+ try {
+ repo.setFileValue(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT, "SampleJsonFile.json", getInputStreamOfFileFromClasspath("SampleJsonFile.json"));
+ } catch (IOException e1) {
+ fail();
+ e1.printStackTrace();
+ }
+
+ // Set the value of the file-submodel element again with a dummy text file
+ try {
+ repo.setFileValue(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT, "newFile.txt", getInputStreamOfDummyFile());
+ } catch (IOException e1) {
+ fail();
+ e1.printStackTrace();
+ }
+
+ // Get the file from the file submodel element
+ File retrievedValue = repo.getFileByPathSubmodel(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+
+ try {
+ String actual = new String(FileUtils.openInputStream(retrievedValue).readAllBytes());
+ assertEquals(DUMMY_FILE_CONTENT, actual);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void getFile(){
+ SubmodelRepository repo = getSubmodelRepositoryWithDummySubmodels();
+ String expectedFileExtension = "json";
+
+ InputStream expectedFile = null;
+ try {
+ expectedFile = getInputStreamOfFileFromClasspath("SampleJsonFile.json");
+ } catch (IOException e1) {
+ e1.printStackTrace();
+ }
+
+ try {
+ repo.setFileValue(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT, "SampleJsonFile.json", getInputStreamOfFileFromClasspath("SampleJsonFile.json"));
+ } catch (IOException e) {
+ fail();
+ e.printStackTrace();
+ }
+
+ File retrievedValue = repo.getFileByPathSubmodel(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+
+ assertEquals(expectedFileExtension, getExtension(retrievedValue.getName()));
+
+ try {
+ assertTrue(IOUtils.contentEquals(expectedFile, FileUtils.openInputStream(retrievedValue)));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test(expected = FileDoesNotExistException.class)
+ public void getNonExistingFile(){
+ SubmodelRepository repo = getSubmodelRepositoryWithDummySubmodels();
+ deleteFileIfExisted(repo);
+
+ repo.getFileByPathSubmodel(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+ }
+
+
+ @Test(expected = ElementNotAFileException.class)
+ public void getFileFromNonFileSME(){
+ SubmodelRepository repo = getSubmodelRepositoryWithDummySubmodels();
+
+ repo.getFileByPathSubmodel(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_MULTI_LANG_PROP_ID_SHORT);
+ }
+
+ @Test
+ public void deleteFile() {
+ SubmodelRepository repo = getSubmodelRepositoryWithDummySubmodels();
+
+ try {
+ repo.setFileValue(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT, "SampleJsonFile.json", getInputStreamOfFileFromClasspath("SampleJsonFile.json"));
+ } catch (IOException e1) {
+ fail();
+ e1.printStackTrace();
+ }
+
+ repo.deleteFileValue(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+
+ try {
+ repo.getFileByPathSubmodel(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+ fail();
+ } catch (Exception e) {
+ }
+ }
+
+ @Test(expected = FileDoesNotExistException.class)
+ public void deleteNonExistingFile() throws IOException {
+ SubmodelRepository repo = getSubmodelRepositoryWithDummySubmodels();
+ deleteFileIfExisted(repo);
+
+ repo.deleteFileValue(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+ }
@Test(expected = ElementDoesNotExistException.class)
public void setNonExistingSubmodelElementValue() {
@@ -386,7 +502,16 @@ public void invokeNonOperation() {
submodelRepo.invokeOperation(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ANNOTATED_RELATIONSHIP_ELEMENT_ID_SHORT, new OperationVariable[0]);
}
-
+
+ private void deleteFileIfExisted(SubmodelRepository repo) {
+ try {
+ repo.getFileByPathSubmodel(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+ repo.deleteFileValue(DummySubmodelFactory.SUBMODEL_TECHNICAL_DATA_ID, SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+ }catch(FileDoesNotExistException e) {
+ return;
+ }
+
+ }
private SubmodelElement getExpectedSubmodelElement() {
return DummySubmodelFactory.createOperationalDataSubmodel()
@@ -420,5 +545,19 @@ private void assertIsEmpty(Collection submodels) {
private String generateIdShortPath() {
return DummySubmodelFactory.SUBMODEL_OPERATIONAL_DATA_ELEMENT_COLLECTION_ID_SHORT + "." + DummySubmodelFactory.SUBMODEL_OPERATIONAL_DATA_ELEMENT_LIST_ID_SHORT + "[0]";
}
+
+ private InputStream getInputStreamOfFileFromClasspath(String fileName) throws FileNotFoundException, IOException {
+ ClassPathResource classPathResource = new ClassPathResource(fileName);
+
+ return classPathResource.getInputStream();
+ }
+
+ private InputStream getInputStreamOfDummyFile() throws FileNotFoundException, IOException {
+ return new ByteArrayInputStream(DUMMY_FILE_CONTENT.getBytes());
+ }
+
+ private String getExtension(String filename) {
+ return FilenameUtils.getExtension(filename);
+ }
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-feature-mqtt/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/feature/mqtt/MqttSubmodelRepository.java b/basyx.submodelrepository/basyx.submodelrepository-feature-mqtt/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/feature/mqtt/MqttSubmodelRepository.java
index fa06bcf22..d44fcd465 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-feature-mqtt/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/feature/mqtt/MqttSubmodelRepository.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-feature-mqtt/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/feature/mqtt/MqttSubmodelRepository.java
@@ -1,6 +1,7 @@
package org.eclipse.digitaltwin.basyx.submodelrepository.feature.mqtt;
import java.util.List;
+import java.io.InputStream;
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
@@ -9,6 +10,7 @@
import org.eclipse.digitaltwin.basyx.common.mqttcore.serializer.SubmodelSerializer;
import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException;
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.FeatureNotImplementedException;
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository;
@@ -186,4 +188,19 @@ public OperationVariable[] invokeOperation(String submodelId, String idShortPath
return decorated.invokeOperation(submodelId, idShortPath, input);
}
+ @Override
+ public java.io.File getFileByPathSubmodel(String submodelId, String idShortPath) {
+ throw new FeatureNotImplementedException();
+ }
+
+ @Override
+ public void deleteFileValue(String identifier, String idShortPath) {
+ throw new FeatureNotImplementedException();
+ }
+
+ @Override
+ public void setFileValue(String submodelId, String idShortPath, String fileName, InputStream inputStream){
+ throw new FeatureNotImplementedException();
+ }
+
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositoryApiHTTPController.java b/basyx.submodelrepository/basyx.submodelrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositoryApiHTTPController.java
index 90249c9de..7cde8a23e 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositoryApiHTTPController.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositoryApiHTTPController.java
@@ -25,6 +25,10 @@
package org.eclipse.digitaltwin.basyx.submodelrepository.http;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -38,6 +42,9 @@
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
+import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException;
+import org.eclipse.digitaltwin.basyx.core.exceptions.FileDoesNotExistException;
import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier;
import org.eclipse.digitaltwin.basyx.http.model.OperationRequest;
import org.eclipse.digitaltwin.basyx.http.model.OperationResult;
@@ -49,11 +56,14 @@
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelValueOnly;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
@@ -90,7 +100,6 @@ public ResponseEntity deleteSubmodelElementByPathSubmodelRepo(
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
-
@Override
public ResponseEntity getAllSubmodels(@Size(min = 1, max = 3072) @Valid Base64UrlEncodedIdentifier semanticId, @Valid String idShort, @Min(1) @Valid Integer limit, @Valid String cursor, @Valid String level,
@Valid String extent) {
@@ -128,7 +137,7 @@ public ResponseEntity getAllSubmodelElements(Base64UrlEncodedIdenti
PaginationInfo pInfo = new PaginationInfo(limit, cursor);
CursorResult> submodelElements = repository
.getSubmodelElements(submodelIdentifier.getIdentifier(), pInfo);
-
+
GetSubmodelElementsResult paginatedSubmodelElement = new GetSubmodelElementsResult();
paginatedSubmodelElement.setResult(submodelElements.getResult());
paginatedSubmodelElement
@@ -139,7 +148,7 @@ public ResponseEntity getAllSubmodelElements(Base64UrlEncodedIdenti
@Override
public ResponseEntity getSubmodelElementByPathSubmodelRepo(Base64UrlEncodedIdentifier submodelIdentifier, String idShortPath, @Valid String level, @Valid String extent) {
- return handleSubmodelElementValueNormalGetRequest(submodelIdentifier.getIdentifier(), idShortPath);
+ return handleSubmodelElementValueNormalGetRequest(submodelIdentifier.getIdentifier(), idShortPath);
}
@Override
@@ -174,6 +183,53 @@ public ResponseEntity getSubmodelByIdMetadata(Base64UrlEncodedIdentifi
return new ResponseEntity(repository.getSubmodelByIdMetadata(submodelIdentifier.getIdentifier()), HttpStatus.OK);
}
+ @Override
+ public ResponseEntity getFileByPath(Base64UrlEncodedIdentifier submodelIdentifier, String idShortPath) {
+ try {
+ FileInputStream fileInputStream = new FileInputStream(repository.getFileByPathSubmodel(submodelIdentifier.getIdentifier(), idShortPath));
+ Resource resource = new InputStreamResource(fileInputStream);
+ return new ResponseEntity(resource, HttpStatus.OK);
+ } catch (FileDoesNotExistException | ElementDoesNotExistException e) {
+ return new ResponseEntity(HttpStatus.NOT_FOUND);
+ } catch (ElementNotAFileException e) {
+ return new ResponseEntity(HttpStatus.PRECONDITION_FAILED);
+ } catch(FileNotFoundException e) {
+ return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ @Override
+ public ResponseEntity putFileByPath(Base64UrlEncodedIdentifier submodelIdentifier, String idShortPath, String fileName, @Valid MultipartFile file) {
+ InputStream fileInputstream = null;
+ try {
+ fileInputstream = file.getInputStream();
+ repository.setFileValue(submodelIdentifier.getIdentifier(), idShortPath, fileName, fileInputstream);
+ closeInputStream(fileInputstream);
+ return new ResponseEntity(HttpStatus.OK);
+ } catch (ElementDoesNotExistException e) {
+ closeInputStream(fileInputstream);
+ return new ResponseEntity(HttpStatus.NOT_FOUND);
+ } catch (ElementNotAFileException e) {
+ closeInputStream(fileInputstream);
+ return new ResponseEntity(HttpStatus.PRECONDITION_FAILED);
+ } catch (IOException e) {
+ closeInputStream(fileInputstream);
+ return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ @Override
+ public ResponseEntity deleteFileByPath(Base64UrlEncodedIdentifier submodelIdentifier, String idShortPath) {
+ try {
+ repository.deleteFileValue(submodelIdentifier.getIdentifier(), idShortPath);
+ return new ResponseEntity(HttpStatus.OK);
+ } catch (FileDoesNotExistException | ElementDoesNotExistException e) {
+ return new ResponseEntity(HttpStatus.NOT_FOUND);
+ } catch (ElementNotAFileException e) {
+ return new ResponseEntity(HttpStatus.PRECONDITION_FAILED);
+ }
+ }
+
private ResponseEntity handleSubmodelElementValueSetRequest(Base64UrlEncodedIdentifier submodelIdentifier, String idShortPath, SubmodelElementValue body) {
repository.setSubmodelElementValue(submodelIdentifier.getIdentifier(), idShortPath, body);
return new ResponseEntity(HttpStatus.NO_CONTENT);
@@ -202,4 +258,15 @@ private OperationResult createOperationResult(OperationVariable[] result) {
operationResult.setOutputArguments(Arrays.asList(result));
return operationResult;
}
+
+ private void closeInputStream(InputStream fileInputstream) {
+ if (fileInputstream == null)
+ return;
+
+ try {
+ fileInputstream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositoryHTTPApi.java b/basyx.submodelrepository/basyx.submodelrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositoryHTTPApi.java
index 29e96a93e..0c93517b6 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositoryHTTPApi.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositoryHTTPApi.java
@@ -46,6 +46,7 @@
import org.eclipse.digitaltwin.basyx.submodelrepository.http.pagination.GetSubmodelsResult;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue;
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelValueOnly;
+import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
@@ -53,6 +54,8 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -372,6 +375,68 @@ ResponseEntity postSubmodelElementSubmodelRepo(
ResponseEntity deleteSubmodelElementByPathSubmodelRepo(
@Parameter(in = ParameterIn.PATH, description = "The Submodel’s unique id (UTF8-BASE64-URL-encoded)", required = true, schema = @Schema()) @PathVariable("submodelIdentifier") Base64UrlEncodedIdentifier submodelIdentifier,
@Parameter(in = ParameterIn.PATH, description = "IdShort path to the submodel element (dot-separated)", required = true, schema = @Schema()) @PathVariable("idShortPath") String idShortPath);
+
+ @Operation(summary = "Downloads file content from a specific submodel element from the Submodel at a specified path", description = "", tags={ "Asset Administration Shell API" })
+ @ApiResponses(value = {
+ @ApiResponse(responseCode = "200", description = "Requested file", content = @Content(mediaType = "application/octet-stream", schema = @Schema(implementation = Resource.class))),
+
+ @ApiResponse(responseCode = "400", description = "Bad Request, e.g. the request parameters of the format of the request body is wrong.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "401", description = "Unauthorized, e.g. the server refused the authorization attempt.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "500", description = "Internal Server Error", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "200", description = "Default error handling for unmentioned status codes", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))) })
+ @RequestMapping(value = "/submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/attachment",
+ produces = { "application/octet-stream", "application/json" },
+ method = RequestMethod.GET)
+ ResponseEntity getFileByPath(@Parameter(in = ParameterIn.PATH, description = "The Submodel’s unique id (UTF8-BASE64-URL-encoded)", required=true, schema=@Schema()) @PathVariable("submodelIdentifier") Base64UrlEncodedIdentifier submodelIdentifier, @Parameter(in = ParameterIn.PATH, description = "IdShort path to the submodel element (dot-separated)", required=true, schema=@Schema()) @PathVariable("idShortPath") String idShortPath);
+
+ @Operation(summary = "Uploads file content to an existing submodel element at a specified path within submodel elements hierarchy", description = "", tags={ "Asset Administration Shell API" })
+ @ApiResponses(value = {
+ @ApiResponse(responseCode = "204", description = "Submodel element updated successfully"),
+
+ @ApiResponse(responseCode = "400", description = "Bad Request, e.g. the request parameters of the format of the request body is wrong.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "401", description = "Unauthorized, e.g. the server refused the authorization attempt.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "500", description = "Internal Server Error", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "200", description = "Default error handling for unmentioned status codes", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))) })
+ @RequestMapping(value = "/submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/attachment",
+ produces = { "application/json" },
+ consumes = { "multipart/form-data" },
+ method = RequestMethod.PUT)
+ ResponseEntity putFileByPath(@Parameter(in = ParameterIn.PATH, description = "The Submodel’s unique id (UTF8-BASE64-URL-encoded)", required=true, schema=@Schema()) @PathVariable("submodelIdentifier") Base64UrlEncodedIdentifier submodelIdentifier, @Parameter(in = ParameterIn.PATH, description = "IdShort path to the submodel element (dot-separated)", required=true, schema=@Schema()) @PathVariable("idShortPath") String idShortPath, @Parameter(in = ParameterIn.DEFAULT, description = "", required=true,schema=@Schema()) @RequestParam(value="fileName", required=true) String fileName, @Parameter(description = "file detail") @Valid @RequestPart("file") MultipartFile file);
+
+ @Operation(summary = "Deletes file content of an existing submodel element at a specified path within submodel elements hierarchy", description = "", tags={ "Asset Administration Shell API" })
+ @ApiResponses(value = {
+ @ApiResponse(responseCode = "200", description = "Submodel element updated successfully"),
+
+ @ApiResponse(responseCode = "400", description = "Bad Request, e.g. the request parameters of the format of the request body is wrong.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "401", description = "Unauthorized, e.g. the server refused the authorization attempt.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "500", description = "Internal Server Error", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))),
+
+ @ApiResponse(responseCode = "200", description = "Default error handling for unmentioned status codes", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class))) })
+ @RequestMapping(value = "/submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/attachment",
+ produces = { "application/json" },
+ method = RequestMethod.DELETE)
+ ResponseEntity deleteFileByPath(@Parameter(in = ParameterIn.PATH, description = "The Submodel’s unique id (UTF8-BASE64-URL-encoded)", required=true, schema=@Schema()) @PathVariable("submodelIdentifier") Base64UrlEncodedIdentifier submodelIdentifier, @Parameter(in = ParameterIn.PATH, description = "IdShort path to the submodel element (dot-separated)", required=true, schema=@Schema()) @PathVariable("idShortPath") String idShortPath);
+
@Operation(summary = "Synchronously or asynchronously invokes an Operation at a specified path", description = "", tags = { "Submodel Repository API" })
@ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Operation result object", content = @Content(mediaType = "application/json", schema = @Schema(implementation = OperationResult.class))),
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/DummySubmodelRepositoryComponent.java b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/DummySubmodelRepositoryComponent.java
index 271786dff..9bc325618 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/DummySubmodelRepositoryComponent.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/DummySubmodelRepositoryComponent.java
@@ -28,8 +28,6 @@
import org.springframework.boot.SpringApplication;
-import org.eclipse.digitaltwin.basyx.submodelrepository.InMemorySubmodelRepository;
-import org.eclipse.digitaltwin.basyx.submodelservice.InMemorySubmodelServiceFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositorySubmodelHTTPTestSuite.java b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositorySubmodelHTTPTestSuite.java
index d92c062d6..4ba0991a0 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositorySubmodelHTTPTestSuite.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/SubmodelRepositorySubmodelHTTPTestSuite.java
@@ -29,11 +29,24 @@
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
+import org.apache.hc.client5.http.ClientProtocolException;
+import org.apache.hc.client5.http.classic.methods.HttpPut;
+import org.apache.hc.client5.http.entity.mime.FileBody;
+import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier;
import org.eclipse.digitaltwin.basyx.http.serialization.BaSyxHttpTestUtils;
@@ -42,6 +55,7 @@
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.HttpStatus;
+import org.springframework.util.ResourceUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
@@ -70,8 +84,7 @@ public void getAllSubmodelsPreconfigured() throws IOException, ParseException {
@Test
public void getSpecificSubmodel() throws ParseException, IOException {
- String submodelJSON = requestSpecificSubmodelJSON(DummySubmodelFactory.createTechnicalDataSubmodel()
- .getId());
+ String submodelJSON = requestSpecificSubmodelJSON(DummySubmodelFactory.createTechnicalDataSubmodel().getId());
String expectedSubmodelJSON = getSingleSubmodelJSON();
BaSyxHttpTestUtils.assertSameJSONContent(expectedSubmodelJSON, submodelJSON);
@@ -81,8 +94,7 @@ public void getSpecificSubmodel() throws ParseException, IOException {
public void getSpecificSubmodelMetadata() throws ParseException, IOException {
String expectedSubmodelJSON = getSingleSubmodelMetadataJSON();
- CloseableHttpResponse response = BaSyxHttpTestUtils.executeGetOnURL(createSubmodelMetadataURL(DummySubmodelFactory.createTechnicalDataSubmodel()
- .getId()));
+ CloseableHttpResponse response = BaSyxHttpTestUtils.executeGetOnURL(createSubmodelMetadataURL(DummySubmodelFactory.createTechnicalDataSubmodel().getId()));
assertEquals(HttpStatus.OK.value(), response.getCode());
BaSyxHttpTestUtils.assertSameJSONContent(expectedSubmodelJSON, BaSyxHttpTestUtils.getResponseAsString(response));
@@ -149,8 +161,7 @@ public void createSubmodelCollidingId() throws IOException {
@Test
public void deleteSubmodel() throws IOException {
- String existingSubmodelId = DummySubmodelFactory.createTechnicalDataSubmodel()
- .getId();
+ String existingSubmodelId = DummySubmodelFactory.createTechnicalDataSubmodel().getId();
CloseableHttpResponse deletionResponse = deleteSubmodelById(existingSubmodelId);
assertEquals(HttpStatus.NO_CONTENT.value(), deletionResponse.getCode());
@@ -168,16 +179,145 @@ public void deleteNonExistingSubmodel() throws IOException {
@Test
public void getPaginatedSubmodel() throws ParseException, IOException {
- String submodelsJSON = BaSyxSubmodelHttpTestUtils
- .requestAllSubmodels(getURL() + "?limit=1&cursor=7A7104BDAB57E184");
- String expected = getSingleSubmodelPaginatedJson();
+ String submodelsJSON = BaSyxSubmodelHttpTestUtils.requestAllSubmodels(getURL() + "?limit=1&cursor=7A7104BDAB57E184");
+ String expected = getSubmodelsPaginatedJson();
BaSyxHttpTestUtils.assertSameJSONContent(expected, submodelsJSON);
}
+ @Test
+ public void uploadFileToFileSubmodelElement() throws IOException {
+ CloseableHttpResponse submodelElementFileUploadResponse = uploadFileToSubmodelElement(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_FILE_ID_SHORT);
+
+ assertEquals(HttpStatus.OK.value(), submodelElementFileUploadResponse.getCode());
+ }
+
+ @Test
+ public void uploadFileToNonFileSubmodelElement() throws FileNotFoundException, UnsupportedEncodingException, ClientProtocolException, IOException {
+ CloseableHttpResponse submodelElementFileUploadResponse = uploadFileToSubmodelElement(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_NON_FILE_ID_SHORT);
+
+ assertEquals(HttpStatus.PRECONDITION_FAILED.value(), submodelElementFileUploadResponse.getCode());
+ }
+
+ @Test
+ public void uploadFileToNotExistElement() throws FileNotFoundException, UnsupportedEncodingException, ClientProtocolException, IOException {
+ CloseableHttpResponse submodelElementFileUploadResponse = uploadFileToSubmodelElement(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, "ElementNotExist");
+
+ assertEquals(HttpStatus.NOT_FOUND.value(), submodelElementFileUploadResponse.getCode());
+ }
+
+ @Test
+ public void deleteFile() throws FileNotFoundException, IOException {
+ uploadFileToSubmodelElement(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_FILE_ID_SHORT);
+
+ CloseableHttpResponse response = BaSyxHttpTestUtils.executeDeleteOnURL(createSMEFileDeleteURL(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_FILE_ID_SHORT));
+ assertEquals(HttpStatus.OK.value(), response.getCode());
+
+ response = BaSyxHttpTestUtils.executeGetOnURL(createSMEFileGetURL(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_FILE_ID_SHORT));
+ assertEquals(HttpStatus.NOT_FOUND.value(), response.getCode());
+ }
+
+ @Test
+ public void deleteFileToNonFileSubmodelElement() throws FileNotFoundException, UnsupportedEncodingException, ClientProtocolException, IOException {
+ uploadFileToSubmodelElement(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_FILE_ID_SHORT);
+
+ CloseableHttpResponse response = BaSyxHttpTestUtils.executeDeleteOnURL(createSMEFileGetURL(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_NON_FILE_ID_SHORT));
+
+ assertEquals(HttpStatus.PRECONDITION_FAILED.value(), response.getCode());
+ }
+
+ @Test
+ public void deleteFileFromNotExistElement() throws FileNotFoundException, UnsupportedEncodingException, ClientProtocolException, IOException {
+ CloseableHttpResponse response = BaSyxHttpTestUtils.executeDeleteOnURL(createSMEFileGetURL(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, "ElementNotExist"));
+
+ assertEquals(HttpStatus.NOT_FOUND.value(), response.getCode());
+ }
+
+ @Test
+ public void getFile() throws FileNotFoundException, IOException, ParseException {
+ uploadFileToSubmodelElement(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_FILE_ID_SHORT);
+
+ CloseableHttpResponse response = BaSyxHttpTestUtils.executeGetOnURL(createSMEFileGetURL(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_FILE_ID_SHORT));
+ assertEquals(HttpStatus.OK.value(), response.getCode());
+
+ String received = BaSyxHttpTestUtils.getResponseAsString(response);
+
+ String fileName = "BaSyx-Logo.png";
+
+ assertEquals(readFile("src/test/resources/" + fileName, Charset.defaultCharset()), new String(received.getBytes(), Charset.defaultCharset()));
+ }
+
+ @Test
+ public void getFileFromNonFileSubmodelElement() throws FileNotFoundException, UnsupportedEncodingException, ClientProtocolException, IOException {
+ CloseableHttpResponse response = BaSyxHttpTestUtils.executeGetOnURL(createSMEFileGetURL(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, DummySubmodelFactory.SUBMODEL_ELEMENT_NON_FILE_ID_SHORT));
+
+ assertEquals(HttpStatus.PRECONDITION_FAILED.value(), response.getCode());
+ }
+
+ @Test
+ public void getFileFromNotExistElement() throws FileNotFoundException, UnsupportedEncodingException, ClientProtocolException, IOException {
+ CloseableHttpResponse response = BaSyxHttpTestUtils.executeGetOnURL(createSMEFileGetURL(DummySubmodelFactory.SUBMODEL_FOR_FILE_TEST, "ElementNotExist"));
+
+ assertEquals(HttpStatus.NOT_FOUND.value(), response.getCode());
+ }
+
+ private String createSMEFileDeleteURL(String submodelId, String submodelElementIdShort) {
+ return BaSyxSubmodelHttpTestUtils.getSpecificSubmodelAccessPath(getURL(), submodelId) + "/submodel-elements/" + submodelElementIdShort + "/attachment";
+ }
+
+ private String createSMEFileGetURL(String submodelId, String submodelElementIdShort) {
+ return BaSyxSubmodelHttpTestUtils.getSpecificSubmodelAccessPath(getURL(), submodelId) + "/submodel-elements/" + submodelElementIdShort + "/attachment";
+ }
+
+ private CloseableHttpResponse uploadFileToSubmodelElement(String submodelId, String submodelElementIdShort) throws IOException {
+ CloseableHttpClient client = HttpClients.createDefault();
+
+ String fileName = "BaSyx-Logo.png";
+
+ java.io.File file = ResourceUtils.getFile("src/test/resources/" + fileName);
+
+ HttpPut putRequest = createPutRequestWithFile(submodelId, submodelElementIdShort, fileName, file);
+
+ return executePutRequest(client, putRequest);
+ }
+
+ private CloseableHttpResponse executePutRequest(CloseableHttpClient client, HttpPut putRequest) throws IOException {
+ CloseableHttpResponse response = client.execute(putRequest);
+
+ HttpEntity responseEntity = response.getEntity();
+
+ EntityUtils.consume(responseEntity);
+ return response;
+ }
+
+ private HttpPut createPutRequestWithFile(String submodelId, String submodelElementIdShort, String fileName, java.io.File file) {
+ HttpPut putRequest = new HttpPut(createSMEFileUploadURL(submodelId, submodelElementIdShort, fileName));
+
+ MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+
+ builder.addPart("file", new FileBody(file));
+ builder.setContentType(ContentType.MULTIPART_FORM_DATA);
+
+ HttpEntity multipart = builder.build();
+ putRequest.setEntity(multipart);
+ return putRequest;
+ }
+
+ private String createSMEFileUploadURL(String submodelId, String submodelElementIdShort, String fileName) {
+ return BaSyxSubmodelHttpTestUtils.getSpecificSubmodelAccessPath(getURL(), submodelId) + "/submodel-elements/" + submodelElementIdShort + "/attachment?fileName=" + fileName;
+ }
+
+ private static String readFile(String path, Charset encoding) throws IOException {
+ byte[] encoded = Files.readAllBytes(Paths.get(path));
+
+ return new String(encoded, encoding);
+ }
+
private void assertSubmodelCreationReponse(String submodelJSON, CloseableHttpResponse creationResponse) throws IOException, ParseException, JsonProcessingException, JsonMappingException {
assertEquals(HttpStatus.CREATED.value(), creationResponse.getCode());
+
String response = BaSyxHttpTestUtils.getResponseAsString(creationResponse);
+
BaSyxHttpTestUtils.assertSameJSONContent(submodelJSON, response);
}
@@ -227,8 +367,8 @@ private String getAllSubmodelJSON() throws IOException {
return BaSyxHttpTestUtils.readJSONStringFromClasspath("MultipleSubmodels.json");
}
- private String getSingleSubmodelPaginatedJson() throws FileNotFoundException, IOException {
- return BaSyxHttpTestUtils.readJSONStringFromClasspath("SingleSubmodelPaginated.json");
+ private String getSubmodelsPaginatedJson() throws FileNotFoundException, IOException {
+ return BaSyxHttpTestUtils.readJSONStringFromClasspath("SubmodelsPaginated.json");
}
protected List createSubmodels() {
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/TestSubmodelRepositorySubmodelElementsHTTP.java b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/TestSubmodelRepositorySubmodelElementsHTTP.java
index eee08a9d4..2d3e9f00c 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/TestSubmodelRepositorySubmodelElementsHTTP.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/TestSubmodelRepositorySubmodelElementsHTTP.java
@@ -26,6 +26,7 @@
package org.eclipse.digitaltwin.basyx.submodelrepository.http;
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
+
import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository;
import org.eclipse.digitaltwin.basyx.submodelservice.http.SubmodelServiceSubmodelElementsTestSuiteHTTP;
import org.junit.After;
@@ -60,8 +61,7 @@ public void createSubmodelOnRepo() {
@After
public void removeSubmodelFromRepo() {
SubmodelRepository repo = appContext.getBean(SubmodelRepository.class);
- repo.getAllSubmodels(NO_LIMIT_PAGINATION_INFO).getResult().stream().map(s -> s.getId())
- .forEach(repo::deleteSubmodel);
+ repo.getAllSubmodels(NO_LIMIT_PAGINATION_INFO).getResult().stream().map(s -> s.getId()).forEach(repo::deleteSubmodel);
}
@AfterClass
@@ -72,8 +72,7 @@ public static void shutdownAASRepo() {
@Override
protected String getURL() {
- return BaSyxSubmodelHttpTestUtils.getSpecificSubmodelAccessPath("http://localhost:8080/submodels",
- createSubmodel().getId());
+ return BaSyxSubmodelHttpTestUtils.getSpecificSubmodelAccessPath("http://localhost:8080/submodels", createSubmodel().getId());
}
}
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/TestSubmodelRepositorySubmodelHTTP.java b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/TestSubmodelRepositorySubmodelHTTP.java
index b7c267719..a60d8deda 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/TestSubmodelRepositorySubmodelHTTP.java
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelrepository/http/TestSubmodelRepositorySubmodelHTTP.java
@@ -25,10 +25,13 @@
package org.eclipse.digitaltwin.basyx.submodelrepository.http;
+import java.io.FileNotFoundException;
+import java.io.IOException;
import java.util.Collection;
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
+import org.eclipse.digitaltwin.basyx.http.serialization.BaSyxHttpTestUtils;
import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -43,6 +46,7 @@
*/
public class TestSubmodelRepositorySubmodelHTTP extends SubmodelRepositorySubmodelHTTPTestSuite {
private static final PaginationInfo NO_LIMIT_PAGINATION_INFO = new PaginationInfo(0, null);
+ private static final String SUBMODEL_JSON = "SingleSubmodel4FileTest.json";
private static ConfigurableApplicationContext appContext;
@BeforeClass
@@ -53,8 +57,7 @@ public static void startAASRepo() throws Exception {
@Override
public void resetRepository() {
SubmodelRepository repo = appContext.getBean(SubmodelRepository.class);
- repo.getAllSubmodels(NO_LIMIT_PAGINATION_INFO).getResult().stream().map(s -> s.getId())
- .forEach(repo::deleteSubmodel);
+ repo.getAllSubmodels(NO_LIMIT_PAGINATION_INFO).getResult().stream().map(s -> s.getId()).forEach(repo::deleteSubmodel);
}
@Override
@@ -62,6 +65,12 @@ public void populateRepository() {
SubmodelRepository repo = appContext.getBean(SubmodelRepository.class);
Collection submodels = createSubmodels();
submodels.forEach(repo::createSubmodel);
+ try {
+ createSubmodel4FileTest();
+ } catch (IOException e) {
+ System.out.println("Cannot load " + SUBMODEL_JSON + " for testing file-upload feature.");
+ e.printStackTrace();
+ }
}
@AfterClass
@@ -73,4 +82,11 @@ public static void shutdownAASRepo() {
protected String getURL() {
return "http://localhost:8080/submodels";
}
+
+ private void createSubmodel4FileTest() throws FileNotFoundException, IOException {
+ String submodelJSON = BaSyxHttpTestUtils.readJSONStringFromClasspath(SUBMODEL_JSON);
+
+ BaSyxSubmodelHttpTestUtils.createSubmodel(getURL(), submodelJSON);
+ }
+
}
\ No newline at end of file
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/BaSyx-Logo.png b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/BaSyx-Logo.png
new file mode 100644
index 000000000..da613e94c
Binary files /dev/null and b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/BaSyx-Logo.png differ
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/MultipleSubmodels.json b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/MultipleSubmodels.json
index 482e499ec..3c1f6b33a 100644
--- a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/MultipleSubmodels.json
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/MultipleSubmodels.json
@@ -406,6 +406,49 @@
}
},
{
+ "id": "8A6344BDAB57E184",
+ "idShort": "FileTests",
+ "modelType": "Submodel",
+ "semanticId": {
+ "keys": [{
+ "type": "GlobalReference",
+ "value": "0173-1#01-AFZ615#016"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "submodelElements": [{
+ "category": "PARAMETER",
+ "contentType": "application/json",
+ "idShort": "FileData",
+ "modelType": "File",
+ "semanticId": {
+ "keys": [{
+ "type": "ConceptDescription",
+ "value": "0173-1#02-BAA120#008"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "value": "BaSyx-Logo.png"
+ }, {
+ "category": "PARAMETER",
+ "idShort": "NonFileParameter",
+ "modelType": "Property",
+ "semanticId": {
+ "keys": [{
+ "type": "ConceptDescription",
+ "value": "0173-1#02-BAA120#008"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "value": "5000",
+ "valueType": "xs:integer"
+ }
+ ]
+ },
+ {
"modelType": "Submodel",
"id": "AC69B1CB44F07935",
"idShort": "OperationalData",
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SingleSubmodel4FileTest.json b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SingleSubmodel4FileTest.json
new file mode 100644
index 000000000..9b0585616
--- /dev/null
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SingleSubmodel4FileTest.json
@@ -0,0 +1,48 @@
+{
+ "modelType": "Submodel",
+ "semanticId": {
+ "keys": [
+ {
+ "type": "GlobalReference",
+ "value": "0173-1#01-AFZ615#016"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "id": "8A6344BDAB57E184",
+ "idShort": "FileTests",
+ "submodelElements": [
+ {
+ "modelType": "File",
+ "contentType": "application/json",
+ "value": "BaSyx-Logo.png",
+ "semanticId": {
+ "keys": [
+ {
+ "type": "ConceptDescription",
+ "value": "0173-1#02-BAA120#008"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "category": "PARAMETER",
+ "idShort": "FileData"
+ },
+ {
+ "modelType": "Property",
+ "semanticId": {
+ "keys": [
+ {
+ "type": "ConceptDescription",
+ "value": "0173-1#02-BAA120#008"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "value": "5000",
+ "valueType": "xs:integer",
+ "category": "PARAMETER",
+ "idShort": "NonFileParameter"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SingleSubmodelPaginated.json b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SingleSubmodelPaginated.json
deleted file mode 100644
index 342f34006..000000000
--- a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SingleSubmodelPaginated.json
+++ /dev/null
@@ -1 +0,0 @@
-{"paging_metadata":{"cursor":"AC69B1CB44F07935"},"result":[{"modelType":"Submodel","id":"AC69B1CB44F07935","idShort":"OperationalData","submodelElements":[{"modelType":"Property","value":"4370","valueType":"xs:integer","category":"VARIABLE","idShort":"RotationSpeed","semanticId":{"keys":[{"type":"ConceptDescription","value":"http://customer.com/cd/1/1/18EBD56F6B43D895"}],"type":"ExternalReference"}}]}]}
\ No newline at end of file
diff --git a/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SubmodelsPaginated.json b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SubmodelsPaginated.json
new file mode 100644
index 000000000..af1ffc054
--- /dev/null
+++ b/basyx.submodelrepository/basyx.submodelrepository-http/src/test/resources/SubmodelsPaginated.json
@@ -0,0 +1,49 @@
+{
+ "paging_metadata": {
+ "cursor": "8A6344BDAB57E184"
+ },
+ "result": [{
+ "id": "8A6344BDAB57E184",
+ "idShort": "FileTests",
+ "modelType": "Submodel",
+ "semanticId": {
+ "keys": [{
+ "type": "GlobalReference",
+ "value": "0173-1#01-AFZ615#016"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "submodelElements": [{
+ "category": "PARAMETER",
+ "contentType": "application/json",
+ "idShort": "FileData",
+ "modelType": "File",
+ "semanticId": {
+ "keys": [{
+ "type": "ConceptDescription",
+ "value": "0173-1#02-BAA120#008"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "value": "BaSyx-Logo.png"
+ }, {
+ "category": "PARAMETER",
+ "idShort": "NonFileParameter",
+ "modelType": "Property",
+ "semanticId": {
+ "keys": [{
+ "type": "ConceptDescription",
+ "value": "0173-1#02-BAA120#008"
+ }
+ ],
+ "type": "ExternalReference"
+ },
+ "value": "5000",
+ "valueType": "xs:integer"
+ }
+ ]
+ }
+ ]
+}
diff --git a/basyx.submodelservice/basyx.submodelservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/InMemorySubmodelService.java b/basyx.submodelservice/basyx.submodelservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/InMemorySubmodelService.java
index 65e7929a4..87af62974 100644
--- a/basyx.submodelservice/basyx.submodelservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/InMemorySubmodelService.java
+++ b/basyx.submodelservice/basyx.submodelservice-backend-inmemory/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/InMemorySubmodelService.java
@@ -101,6 +101,7 @@ public SubmodelElementValue getSubmodelElementValue(String idShort) throws Eleme
return submodelElementValueFactory.create(getSubmodelElement(idShort)).getValue();
}
+ @SuppressWarnings("unchecked")
@Override
public void setSubmodelElementValue(String idShort, SubmodelElementValue value) throws ElementDoesNotExistException {
SubmodelElementValueMapperFactory submodelElementValueFactory = new SubmodelElementValueMapperFactory();
diff --git a/basyx.submodelservice/basyx.submodelservice-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelservice/DummySubmodelFactory.java b/basyx.submodelservice/basyx.submodelservice-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelservice/DummySubmodelFactory.java
index 21eae1308..a2f38af38 100644
--- a/basyx.submodelservice/basyx.submodelservice-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelservice/DummySubmodelFactory.java
+++ b/basyx.submodelservice/basyx.submodelservice-core/src/test/java/org/eclipse/digitaltwin/basyx/submodelservice/DummySubmodelFactory.java
@@ -97,6 +97,11 @@ public class DummySubmodelFactory {
public static final String SUBMODEL_SIMPLE_DATA_ID_SHORT = "simpleSubmodel001";
public static final String SUBMODEL_SIMPLE_DATA_ID = "simpleSubmodel001";
public static final String SUBMODEL_ELEMENT_SIMPLE_DATA_ID_SHORT = "elementToDelete";
+
+ //SUBMODEL_FOR_FILE_TEST
+ public static final String SUBMODEL_FOR_FILE_TEST = "8A6344BDAB57E184";
+ public static final String SUBMODEL_ELEMENT_FILE_ID_SHORT = "FileData";
+ public static final String SUBMODEL_ELEMENT_NON_FILE_ID_SHORT = "NonFileParameter";
public static Collection getSubmodels() {
return Arrays.asList(createTechnicalDataSubmodel(), createOperationalDataSubmodel(), createSimpleDataSubmodel());
diff --git a/basyx.submodelservice/basyx.submodelservice-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelservice/http/SubmodelServiceSubmodelElementsTestSuiteHTTP.java b/basyx.submodelservice/basyx.submodelservice-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelservice/http/SubmodelServiceSubmodelElementsTestSuiteHTTP.java
index 7dace4e10..5e81bf028 100644
--- a/basyx.submodelservice/basyx.submodelservice-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelservice/http/SubmodelServiceSubmodelElementsTestSuiteHTTP.java
+++ b/basyx.submodelservice/basyx.submodelservice-http/src/test/java/org/eclipse/digitaltwin/basyx/submodelservice/http/SubmodelServiceSubmodelElementsTestSuiteHTTP.java
@@ -68,8 +68,7 @@ public void getSubmodelElements() throws FileNotFoundException, IOException, Par
@Test
public void getSubmodelElement() throws FileNotFoundException, IOException, ParseException {
String expectedElement = getSubmodelElementJSON();
- CloseableHttpResponse response = requestSubmodelElement(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_PROPERTY_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElement(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_PROPERTY_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
BaSyxHttpTestUtils.assertSameJSONContent(expectedElement, BaSyxHttpTestUtils.getResponseAsString(response));
@@ -79,8 +78,7 @@ public void getSubmodelElement() throws FileNotFoundException, IOException, Pars
public void getPropertyValue() throws IOException, ParseException {
String expectedValue = wrapStringValue("5000");
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_PROPERTY_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_PROPERTY_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -98,20 +96,17 @@ public void getNonExistingSubmodelElementValue() throws IOException {
public void setPropertyValue() throws IOException, ParseException {
String expectedValue = wrapStringValue("2567");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_PROPERTY_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_PROPERTY_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_PROPERTY_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_PROPERTY_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getMultiLanguagePropertyValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_MULTI_LANG_PROP_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_MULTI_LANG_PROP_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -124,20 +119,17 @@ public void getMultiLanguagePropertyValue() throws IOException, ParseException {
public void setMultiLanguagePropertyValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setMultiLanguagePropertyValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_MULTI_LANG_PROP_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_MULTI_LANG_PROP_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_MULTI_LANG_PROP_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_MULTI_LANG_PROP_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getRangeValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RANGE_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RANGE_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -150,20 +142,17 @@ public void getRangeValue() throws IOException, ParseException {
public void setRangeValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setRangeValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RANGE_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RANGE_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RANGE_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RANGE_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getFileValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -176,20 +165,16 @@ public void getFileValue() throws IOException, ParseException {
public void setFileValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setFileValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
-
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_FILE_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getBlobValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_BLOB_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_BLOB_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -202,20 +187,17 @@ public void getBlobValue() throws IOException, ParseException {
public void setBlobValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setBlobValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_BLOB_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_BLOB_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_BLOB_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_BLOB_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getEntityValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -228,12 +210,10 @@ public void getEntityValue() throws IOException, ParseException {
public void setEntityValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setEntityValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@@ -243,20 +223,17 @@ public void setEntityValueMRP() throws IOException, ParseException {
String minimumRequestPayloadValue = getJSONValueAsString("value/setEntityValueMRP.json");
String expectedValue = getJSONValueAsString("value/expectedUpdatedMRPEntityValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT, minimumRequestPayloadValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT, minimumRequestPayloadValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ENTITY_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getReferenceElementValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_REFERENCE_ELEMENT_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_REFERENCE_ELEMENT_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -269,20 +246,17 @@ public void getReferenceElementValue() throws IOException, ParseException {
public void setReferenceElementValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setReferenceElementValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_REFERENCE_ELEMENT_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_REFERENCE_ELEMENT_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_REFERENCE_ELEMENT_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_REFERENCE_ELEMENT_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getRelationshipElementValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RELATIONSHIP_ELEMENT_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RELATIONSHIP_ELEMENT_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -295,20 +269,17 @@ public void getRelationshipElementValue() throws IOException, ParseException {
public void setRelationshipElementValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setRelationshipElementValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RELATIONSHIP_ELEMENT_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RELATIONSHIP_ELEMENT_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RELATIONSHIP_ELEMENT_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_RELATIONSHIP_ELEMENT_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getAnnotatedRelationshipElementValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ANNOTATED_RELATIONSHIP_ELEMENT_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ANNOTATED_RELATIONSHIP_ELEMENT_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -321,20 +292,17 @@ public void getAnnotatedRelationshipElementValue() throws IOException, ParseExce
public void setAnnotatedRelationshipElementValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setAnnotatedRelationshipElementValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ANNOTATED_RELATIONSHIP_ELEMENT_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ANNOTATED_RELATIONSHIP_ELEMENT_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ANNOTATED_RELATIONSHIP_ELEMENT_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_ANNOTATED_RELATIONSHIP_ELEMENT_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getSubmodelElementCollectionValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_COLLECTION_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_COLLECTION_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -347,20 +315,17 @@ public void getSubmodelElementCollectionValue() throws IOException, ParseExcepti
public void setSubmodelElementCollectionValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setSubmodelElementCollectionValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_COLLECTION_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_COLLECTION_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_COLLECTION_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_COLLECTION_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@Test
public void getSubmodelElementListValue() throws IOException, ParseException {
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_LIST_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_LIST_ID_SHORT);
assertEquals(HttpStatus.OK.value(), response.getCode());
@@ -373,12 +338,10 @@ public void getSubmodelElementListValue() throws IOException, ParseException {
public void setSubmodelElementListValue() throws IOException, ParseException {
String expectedValue = getJSONValueAsString("value/setSubmodelElementListValue.json");
- CloseableHttpResponse writeResponse = writeSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_LIST_ID_SHORT, expectedValue);
+ CloseableHttpResponse writeResponse = writeSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_LIST_ID_SHORT, expectedValue);
assertEquals(HttpStatus.NO_CONTENT.value(), writeResponse.getCode());
- CloseableHttpResponse response = requestSubmodelElementValue(
- SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_LIST_ID_SHORT);
+ CloseableHttpResponse response = requestSubmodelElementValue(SubmodelServiceHelper.SUBMODEL_TECHNICAL_DATA_SUBMODEL_ELEMENT_LIST_ID_SHORT);
BaSyxHttpTestUtils.assertSameJSONContent(expectedValue, BaSyxHttpTestUtils.getResponseAsString(response));
}
@@ -386,8 +349,7 @@ public void setSubmodelElementListValue() throws IOException, ParseException {
@Test
public void createSubmodelElementCollidingId() throws IOException {
String element = getJSONValueAsString("SubmodelElement.json");
- CloseableHttpResponse createdResponse = BaSyxHttpTestUtils.executePostOnURL(createSubmodelElementsURL(),
- element);
+ CloseableHttpResponse createdResponse = BaSyxHttpTestUtils.executePostOnURL(createSubmodelElementsURL(), element);
assertEquals(HttpStatus.CONFLICT.value(), createdResponse.getCode());
}
@@ -395,59 +357,45 @@ public void createSubmodelElementCollidingId() throws IOException {
@Test
public void createSubmodelElement() throws FileNotFoundException, IOException, ParseException {
String element = getJSONValueAsString("SubmodelElementNew.json");
- CloseableHttpResponse createdResponse = BaSyxHttpTestUtils.executePostOnURL(createSubmodelElementsURL(),
- element);
+ CloseableHttpResponse createdResponse = BaSyxHttpTestUtils.executePostOnURL(createSubmodelElementsURL(), element);
- CloseableHttpResponse fetchedResponse = requestSubmodelElement(
- "MaxRotationSpeedNew");
+ CloseableHttpResponse fetchedResponse = requestSubmodelElement("MaxRotationSpeedNew");
assertEquals(HttpStatus.CREATED.value(), createdResponse.getCode());
BaSyxHttpTestUtils.assertSameJSONContent(element, BaSyxHttpTestUtils.getResponseAsString(fetchedResponse));
}
@Test
public void deleteSubmodelElement() throws FileNotFoundException, IOException, ParseException {
- CloseableHttpResponse deleteResponse = BaSyxHttpTestUtils.executeDeleteOnURL(
- createSpecificSubmodelElementURL(DummySubmodelFactory.SUBMODEL_ELEMENT_SIMPLE_DATA_ID_SHORT));
+ CloseableHttpResponse deleteResponse = BaSyxHttpTestUtils.executeDeleteOnURL(createSpecificSubmodelElementURL(DummySubmodelFactory.SUBMODEL_ELEMENT_SIMPLE_DATA_ID_SHORT));
assertEquals(HttpStatus.NO_CONTENT.value(), deleteResponse.getCode());
- CloseableHttpResponse fetchedResponse = requestSubmodelElement(
- DummySubmodelFactory.SUBMODEL_ELEMENT_SIMPLE_DATA_ID_SHORT);
+ CloseableHttpResponse fetchedResponse = requestSubmodelElement(DummySubmodelFactory.SUBMODEL_ELEMENT_SIMPLE_DATA_ID_SHORT);
assertEquals(HttpStatus.NOT_FOUND.value(), fetchedResponse.getCode());
}
@Test
- public void createNestedSubmodelElementInSubmodelElementCollection()
- throws FileNotFoundException, IOException, ParseException {
+ public void createNestedSubmodelElementInSubmodelElementCollection() throws FileNotFoundException, IOException, ParseException {
String element = getJSONValueAsString("SubmodelElementNew.json");
- CloseableHttpResponse createdInCollectionResponse = BaSyxHttpTestUtils.executePostOnURL(
- createSpecificSubmodelElementURL(DummySubmodelFactory.SUBMODEL_ELEMENT_COLLECTION_SIMPLE), element);
+ CloseableHttpResponse createdInCollectionResponse = BaSyxHttpTestUtils.executePostOnURL(createSpecificSubmodelElementURL(DummySubmodelFactory.SUBMODEL_ELEMENT_COLLECTION_SIMPLE), element);
assertEquals(HttpStatus.CREATED.value(), createdInCollectionResponse.getCode());
- CloseableHttpResponse fetchedNestedInCollectionResponse = requestSubmodelElement(
- createCollectionNestedIdShortPath("MaxRotationSpeedNew"));
- BaSyxHttpTestUtils.assertSameJSONContent(element,
- BaSyxHttpTestUtils.getResponseAsString(fetchedNestedInCollectionResponse));
+ CloseableHttpResponse fetchedNestedInCollectionResponse = requestSubmodelElement(createCollectionNestedIdShortPath("MaxRotationSpeedNew"));
+ BaSyxHttpTestUtils.assertSameJSONContent(element, BaSyxHttpTestUtils.getResponseAsString(fetchedNestedInCollectionResponse));
}
@Test
- public void createNestedSubmodelElementInSubmodelElementList()
- throws IOException, JsonProcessingException, JsonMappingException, ParseException {
+ public void createNestedSubmodelElementInSubmodelElementList() throws IOException, JsonProcessingException, JsonMappingException, ParseException {
String element = getJSONValueAsString("SubmodelElementNew.json");
- CloseableHttpResponse createdInListResponse = BaSyxHttpTestUtils.executePostOnURL(
- createSpecificSubmodelElementURL(DummySubmodelFactory.SUBMODEL_ELEMENT_LIST_SIMPLE), element);
+ CloseableHttpResponse createdInListResponse = BaSyxHttpTestUtils.executePostOnURL(createSpecificSubmodelElementURL(DummySubmodelFactory.SUBMODEL_ELEMENT_LIST_SIMPLE), element);
assertEquals(HttpStatus.CREATED.value(), createdInListResponse.getCode());
CloseableHttpResponse fetchedNestedInListResponse = requestSubmodelElement(createListNestedIdShortPath(1));
- BaSyxHttpTestUtils.assertSameJSONContent(element,
- BaSyxHttpTestUtils.getResponseAsString(fetchedNestedInListResponse));
+ BaSyxHttpTestUtils.assertSameJSONContent(element, BaSyxHttpTestUtils.getResponseAsString(fetchedNestedInListResponse));
}
@Test
- public void deleteNestedSubmodelElementFromSubmodelElementCollection()
- throws FileNotFoundException, IOException, ParseException {
- String nestedIdShortPathInCollection = createCollectionNestedIdShortPath(
- DummySubmodelFactory.SUBMODEL_ELEMENT_FIRST_ID_SHORT);
- CloseableHttpResponse deleteResponse = BaSyxHttpTestUtils
- .executeDeleteOnURL(createSpecificSubmodelElementURL(nestedIdShortPathInCollection));
+ public void deleteNestedSubmodelElementFromSubmodelElementCollection() throws FileNotFoundException, IOException, ParseException {
+ String nestedIdShortPathInCollection = createCollectionNestedIdShortPath(DummySubmodelFactory.SUBMODEL_ELEMENT_FIRST_ID_SHORT);
+ CloseableHttpResponse deleteResponse = BaSyxHttpTestUtils.executeDeleteOnURL(createSpecificSubmodelElementURL(nestedIdShortPathInCollection));
assertEquals(HttpStatus.NO_CONTENT.value(), deleteResponse.getCode());
CloseableHttpResponse fetchedNestedInCollectionResponse = requestSubmodelElement(nestedIdShortPathInCollection);
@@ -455,11 +403,9 @@ public void deleteNestedSubmodelElementFromSubmodelElementCollection()
}
@Test
- public void deleteNestedSubmodelElementFromSubmodelElementList()
- throws IOException {
+ public void deleteNestedSubmodelElementFromSubmodelElementList() throws IOException {
String nestedIdShortSmeList = createListNestedIdShortPath(0);
- CloseableHttpResponse deleteResponse = BaSyxHttpTestUtils
- .executeDeleteOnURL(createSpecificSubmodelElementURL(nestedIdShortSmeList));
+ CloseableHttpResponse deleteResponse = BaSyxHttpTestUtils.executeDeleteOnURL(createSpecificSubmodelElementURL(nestedIdShortSmeList));
assertEquals(HttpStatus.NO_CONTENT.value(), deleteResponse.getCode());
CloseableHttpResponse fetchedNestedInListResponse = requestSubmodelElement(createListNestedIdShortPath(1));
diff --git a/pom.xml b/pom.xml
index 51fcae462..0c20a12b6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,4 +1,6 @@
-
+
4.0.0
org.springframework.boot
@@ -245,6 +247,17 @@
+
+ org.apache.tika
+ tika-core
+ 2.8.0
+
+
+
+ commons-io
+ commons-io
+ 2.13.0
+
org.eclipse.digitaltwin.basyx