From 5d66131459f4f098896cb7cfcba2648dc9ed31fa Mon Sep 17 00:00:00 2001 From: Mohammad Ghazanfar Ali Danish <62088117+mdanish98@users.noreply.github.com> Date: Thu, 11 Apr 2024 09:38:57 +0200 Subject: [PATCH] Fixes AASX upload/preconfig ignoring thumbnail (#259) * Fixes AASX upload/preconfig ignoring thumbnail Signed-off-by: Mohammad Ghazanfar Ali Danish * Updates RBAC rules for thumbnails Signed-off-by: Mohammad Ghazanfar Ali Danish * Addresses review remarks Signed-off-by: Mohammad Ghazanfar Ali Danish --------- Signed-off-by: Mohammad Ghazanfar Ali Danish --- .../base/DefaultAASEnvironment.java | 46 ++++++++++++++++++- .../src/test/resources/rbac_rules.json | 16 +++++++ .../component/TestPreconfiguration.java | 11 +++++ .../http/AasRepositoryApiHTTPController.java | 13 ++---- 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/basyx.aasenvironment/basyx.aasenvironment-core/src/main/java/org/eclipse/digitaltwin/basyx/aasenvironment/base/DefaultAASEnvironment.java b/basyx.aasenvironment/basyx.aasenvironment-core/src/main/java/org/eclipse/digitaltwin/basyx/aasenvironment/base/DefaultAASEnvironment.java index f80b3a932..ff4c99ae5 100644 --- a/basyx.aasenvironment/basyx.aasenvironment-core/src/main/java/org/eclipse/digitaltwin/basyx/aasenvironment/base/DefaultAASEnvironment.java +++ b/basyx.aasenvironment/basyx.aasenvironment-core/src/main/java/org/eclipse/digitaltwin/basyx/aasenvironment/base/DefaultAASEnvironment.java @@ -45,6 +45,7 @@ import org.eclipse.digitaltwin.aas4j.v3.model.Environment; import org.eclipse.digitaltwin.aas4j.v3.model.Submodel; import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; +import org.eclipse.digitaltwin.aas4j.v3.model.Resource; import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultEnvironment; import org.eclipse.digitaltwin.basyx.aasenvironment.AasEnvironment; import org.eclipse.digitaltwin.basyx.aasenvironment.ConceptDescriptionIdCollector; @@ -113,13 +114,14 @@ public byte[] createAASXAASEnvironmentSerialization(@Valid List aasIds, public void loadEnvironment(CompleteEnvironment completeEnvironment) { Environment environment = completeEnvironment.getEnvironment(); + List relatedFiles = completeEnvironment.getRelatedFiles(); if (environment == null) return; checker.assertNoDuplicateIds(environment); - createShellsOnRepositoryFromEnvironment(environment); + createShellsOnRepositoryFromEnvironment(environment, relatedFiles); createSubmodelsOnRepositoryFromEnvironment(environment, completeEnvironment.getRelatedFiles()); createConceptDescriptionsOnRepositoryFromEnvironment(environment); } @@ -179,15 +181,55 @@ private InMemoryFile getAssociatedInMemoryFile(List relatedFiles, return inMemoryFile.get(); } - private void createShellsOnRepositoryFromEnvironment(Environment environment) { + private void createShellsOnRepositoryFromEnvironment(Environment environment, List relatedFiles) { IdentifiableRepository repo = new DelegatingIdentifiableRepository(aasRepository::getAas, aasRepository::updateAas, aasRepository::createAas); IdentifiableUploader uploader = new IdentifiableUploader<>(repo); for (AssetAdministrationShell shell : environment.getAssetAdministrationShells()) { boolean success = uploader.upload(shell); + setThumbnail(shell.getId(), relatedFiles); logSuccess("shell", shell.getId(), success); } } + private void setThumbnail(String shellId, List relatedFiles) { + if (relatedFiles == null || relatedFiles.isEmpty()) + return; + + Resource thumbnailResource = aasRepository.getAssetInformation(shellId).getDefaultThumbnail(); + + if (thumbnailResource == null || !isValidPath(thumbnailResource.getPath()) || !isValidContentType(thumbnailResource.getContentType())) { + logger.info("Could not find thumbnail resource for aas {}", shellId); + return; + } + + String thumbnailPath = thumbnailResource.getPath(); + String thumbnailContentType = thumbnailResource.getContentType(); + + Optional optionalInMemoryFile = relatedFiles.stream().filter(file -> file.getPath().equals(thumbnailPath)).findAny(); + + if (optionalInMemoryFile.isEmpty()) { + logger.info("Thumbnail file specified at path {} for aas {} could not be found.", thumbnailPath, shellId); + return; + } + + byte[] thumbnailContent = optionalInMemoryFile.get().getFileContent(); + + if (thumbnailContent.length == 0) { + logger.info("Thumbnail content for aas {} is empty.", thumbnailPath); + return; + } + + aasRepository.setThumbnail(shellId, getFileName(thumbnailPath), thumbnailContentType, new ByteArrayInputStream(thumbnailContent)); + } + + private boolean isValidContentType(String contentType) { + return contentType != null && !contentType.isBlank(); + } + + private boolean isValidPath(String path) { + return path != null && !path.isBlank(); + } + private void createSubmodelsOnRepository(List submodels) { IdentifiableRepository repo = new DelegatingIdentifiableRepository(submodelRepository::getSubmodel, submodelRepository::updateSubmodel, submodelRepository::createSubmodel); IdentifiableUploader uploader = new IdentifiableUploader<>(repo); diff --git a/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/resources/rbac_rules.json b/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/resources/rbac_rules.json index 8a0a6b205..bb2e396fb 100644 --- a/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/resources/rbac_rules.json +++ b/basyx.aasenvironment/basyx.aasenvironment-feature-authorization/src/test/resources/rbac_rules.json @@ -425,6 +425,14 @@ "aasId": "*" } }, + { + "role": "basyx-uploader", + "action": "UPDATE", + "targetInformation": { + "@type": "aas", + "aasId": "*" + } + }, { "role": "basyx-uploader", "action": "READ", @@ -493,6 +501,14 @@ "aasId": "http://customer.com/aas/9175_7013_7091_9168" } }, + { + "role": "basyx-uploader-two", + "action": "UPDATE", + "targetInformation": { + "@type": "aas", + "aasId": "http://customer.com/aas/9175_7013_7091_9168" + } + }, { "role": "basyx-uploader-two", "action": "READ", diff --git a/basyx.aasenvironment/basyx.aasenvironment.component/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/component/TestPreconfiguration.java b/basyx.aasenvironment/basyx.aasenvironment.component/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/component/TestPreconfiguration.java index 9b7c65b55..dda65705e 100644 --- a/basyx.aasenvironment/basyx.aasenvironment.component/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/component/TestPreconfiguration.java +++ b/basyx.aasenvironment/basyx.aasenvironment.component/src/test/java/org/eclipse/digitaltwin/basyx/aasenvironment/component/TestPreconfiguration.java @@ -33,6 +33,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.FileInputStream; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; @@ -141,6 +142,16 @@ public void aasxFromDirectoryLoadedSubmodelsInRepository() { assertNotNull(submodel2); } + @Test + public void getThumbnail() throws IOException { + File file = aasRepo.getThumbnail("http://customer.com/aas/9175_7013_7091_9168"); + + InputStream expectedContent = getClass().getClassLoader().getResourceAsStream("testFiles/verwaltungsschale-detail-part1.png"); + InputStream actualContent = new FileInputStream(file); + + assertTrue(IOUtils.contentEquals(expectedContent, actualContent)); + } + @Test public void jsonFromDirectoryLoadedShellsInRepository() { AssetAdministrationShell shell1 = aasRepo.getAas("technical-data-shell-id-json"); diff --git a/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryApiHTTPController.java b/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryApiHTTPController.java index 8bcb43f45..6c0be88c3 100644 --- a/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryApiHTTPController.java +++ b/basyx.aasrepository/basyx.aasrepository-http/src/main/java/org/eclipse/digitaltwin/basyx/aasrepository/http/AasRepositoryApiHTTPController.java @@ -45,6 +45,7 @@ import org.eclipse.digitaltwin.basyx.http.pagination.PagedResult; import org.eclipse.digitaltwin.basyx.http.pagination.PagedResultPagingMetadata; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; @@ -186,14 +187,10 @@ public ResponseEntity deleteThumbnailAasRepository(Base64UrlEncodedIdentif @Override public ResponseEntity getThumbnailAasRepository(Base64UrlEncodedIdentifier aasIdentifier) { - try { - FileInputStream fileInputStream = new FileInputStream(aasRepository.getThumbnail(aasIdentifier.getIdentifier())); - Resource resource = new InputStreamResource(fileInputStream); - return new ResponseEntity(resource, HttpStatus.OK); - } catch (FileNotFoundException e) { - return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); - } - } + Resource resource = new FileSystemResource(aasRepository.getThumbnail(aasIdentifier.getIdentifier())); + + return new ResponseEntity<>(resource, HttpStatus.OK); + } @Override public ResponseEntity putThumbnailAasRepository(Base64UrlEncodedIdentifier aasIdentifier, String fileName, @Valid MultipartFile file) {