From f3b586dca7be5cc2fdd48cc471a73e35596785ad Mon Sep 17 00:00:00 2001 From: Mateus Molina Date: Mon, 9 Dec 2024 12:01:19 +0100 Subject: [PATCH] Bump aas4j-version from 1.0.2 to 1.0.3 (#565) * bump: Aas4j to version 1.0.3 * refactor: extract OperationRequest handling to own class * test: add success fields to test results * chore: bump license header year * chore: add todo for async op execution support * fix: todo rel. to aas4j issue in ConnectedAasManager --- .../client/ConnectedAasManager.java | 5 +- .../SubmodelRepositoryApiHTTPController.java | 26 ++----- .../operation/OperationRequestExecutor.java | 78 +++++++++++++++++++ .../SubmodelServiceHTTPApiController.java | 31 +------- .../resources/operation/result-inout.json | 1 + .../src/test/resources/operation/result.json | 1 + pom.xml | 2 +- 7 files changed, 92 insertions(+), 52 deletions(-) create mode 100644 basyx.submodelservice/basyx.submodelservice-core/src/main/java/org/eclipse/digitaltwin/basyx/operation/OperationRequestExecutor.java diff --git a/basyx.aasenvironment/basyx.aasenvironment-client/src/main/java/org/eclipse/digitaltwin/basyx/aasenvironment/client/ConnectedAasManager.java b/basyx.aasenvironment/basyx.aasenvironment-client/src/main/java/org/eclipse/digitaltwin/basyx/aasenvironment/client/ConnectedAasManager.java index f28480ed7..73ae1cbe1 100644 --- a/basyx.aasenvironment/basyx.aasenvironment-client/src/main/java/org/eclipse/digitaltwin/basyx/aasenvironment/client/ConnectedAasManager.java +++ b/basyx.aasenvironment/basyx.aasenvironment-client/src/main/java/org/eclipse/digitaltwin/basyx/aasenvironment/client/ConnectedAasManager.java @@ -223,10 +223,7 @@ public void createSubmodelInAas(String aasIdentifier, Submodel submodel) { throw new RegistryHttpRequestException(aasIdentifier, e); } - Reference smRef = AasUtils.toReference(AasUtils.toReference(shell), submodel); - - // TODO See https://github.com/eclipse-aas4j/aas4j/issues/308 - smRef.setReferredSemanticId(submodel.getSemanticId()); + Reference smRef = AasUtils.toReference(AasUtils.toReference(shell), submodel, true); aasRepository.addSubmodelReference(aasIdentifier, smRef); } 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 645486669..e7767121a 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 @@ -48,6 +48,8 @@ import org.eclipse.digitaltwin.basyx.http.pagination.Base64UrlEncodedCursor; import org.eclipse.digitaltwin.basyx.http.pagination.PagedResult; import org.eclipse.digitaltwin.basyx.http.pagination.PagedResultPagingMetadata; +import org.eclipse.digitaltwin.basyx.operation.OperationRequestExecutor; +import org.eclipse.digitaltwin.basyx.operation.OperationRequestExecutor.Invokable; import org.eclipse.digitaltwin.basyx.pagination.GetSubmodelElementsResult; import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository; import org.eclipse.digitaltwin.basyx.submodelrepository.http.pagination.GetSubmodelsResult; @@ -283,28 +285,12 @@ private ResponseEntity handleSubmodelElementValueNormalGetReque @Override public ResponseEntity invokeOperationSubmodelRepo(Base64UrlEncodedIdentifier submodelIdentifier, String idShortPath, @Valid OperationRequest body, @Valid Boolean async) { - List inVars = new ArrayList<>(); - inVars.addAll(body.getInputArguments()); - inVars.addAll(body.getInoutputArguments()); - List result = Arrays.asList(repository.invokeOperation(submodelIdentifier.getIdentifier(), idShortPath, inVars.toArray(new OperationVariable[0]))); + // TODO: #566 Add async operation execution support to + // SubmodelRepositoryController - List outVars = new ArrayList<>(result); - List inoutputVars = new ArrayList<>(); - - if (!body.getInoutputArguments().isEmpty()) { - List inoutputVarsIdShorts = body.getInoutputArguments().stream().map(OperationVariable::getValue).map(SubmodelElement::getIdShort).toList(); - - inoutputVars = result.stream().filter(opVar -> inoutputVarsIdShorts.contains(opVar.getValue().getIdShort())).toList(); - - outVars.removeAll(inoutputVars); - } - - return ResponseEntity.ok(createOperationResult(outVars, inoutputVars)); - } - - private OperationResult createOperationResult(List outputVars, List inoutputVars) { - return new DefaultOperationResult.Builder().outputArguments(outputVars).inoutputArguments(inoutputVars).build(); + Invokable invokable = inArgs -> repository.invokeOperation(submodelIdentifier.getIdentifier(), idShortPath, inArgs); + return ResponseEntity.ok(OperationRequestExecutor.executeOperationRequestSynchronously(invokable, body)); } private String getEncodedCursorFromCursorResult(CursorResult cursorResult) { diff --git a/basyx.submodelservice/basyx.submodelservice-core/src/main/java/org/eclipse/digitaltwin/basyx/operation/OperationRequestExecutor.java b/basyx.submodelservice/basyx.submodelservice-core/src/main/java/org/eclipse/digitaltwin/basyx/operation/OperationRequestExecutor.java new file mode 100644 index 000000000..397f55c07 --- /dev/null +++ b/basyx.submodelservice/basyx.submodelservice-core/src/main/java/org/eclipse/digitaltwin/basyx/operation/OperationRequestExecutor.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (C) 2024 the Eclipse BaSyx Authors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * SPDX-License-Identifier: MIT + ******************************************************************************/ + +package org.eclipse.digitaltwin.basyx.operation; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.digitaltwin.aas4j.v3.model.OperationRequest; +import org.eclipse.digitaltwin.aas4j.v3.model.OperationResult; +import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable; +import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement; +import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultOperationResult; + +/** + * Executes an Operation Request + * + * @author mateusmolina + */ +public class OperationRequestExecutor { + + private OperationRequestExecutor() { + } + + public static OperationResult executeOperationRequestSynchronously(Invokable invokable, OperationRequest request) { + List inVars = new ArrayList<>(); + inVars.addAll(request.getInputArguments()); + inVars.addAll(request.getInoutputArguments()); + + List result = Arrays.asList(invokable.invoke(inVars.toArray(new OperationVariable[0]))); + + List outVars = new ArrayList<>(result); + List inoutputVars = new ArrayList<>(); + + if (!request.getInoutputArguments().isEmpty()) { + List inoutputVarsIdShorts = request.getInoutputArguments().stream().map(OperationVariable::getValue).map(SubmodelElement::getIdShort).toList(); + + inoutputVars = result.stream().filter(opVar -> inoutputVarsIdShorts.contains(opVar.getValue().getIdShort())).toList(); + + outVars.removeAll(inoutputVars); + } + + return createSuccessOperationResult(outVars, inoutputVars); + } + + private static OperationResult createSuccessOperationResult(List outputVars, List inoutputVars) { + return new DefaultOperationResult.Builder().success(true).outputArguments(outputVars).inoutputArguments(inoutputVars).build(); + } + + @FunctionalInterface + public interface Invokable { + OperationVariable[] invoke(OperationVariable[] arguments); + } + +} diff --git a/basyx.submodelservice/basyx.submodelservice-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/http/SubmodelServiceHTTPApiController.java b/basyx.submodelservice/basyx.submodelservice-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/http/SubmodelServiceHTTPApiController.java index 66498d924..03ab13a15 100644 --- a/basyx.submodelservice/basyx.submodelservice-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/http/SubmodelServiceHTTPApiController.java +++ b/basyx.submodelservice/basyx.submodelservice-http/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/http/SubmodelServiceHTTPApiController.java @@ -27,16 +27,12 @@ import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.eclipse.digitaltwin.aas4j.v3.model.OperationRequest; import org.eclipse.digitaltwin.aas4j.v3.model.OperationResult; -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.aas4j.v3.model.impl.DefaultOperationResult; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException; import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException; import org.eclipse.digitaltwin.basyx.core.exceptions.FileDoesNotExistException; @@ -45,6 +41,8 @@ import org.eclipse.digitaltwin.basyx.http.pagination.Base64UrlEncodedCursor; import org.eclipse.digitaltwin.basyx.http.pagination.PagedResult; import org.eclipse.digitaltwin.basyx.http.pagination.PagedResultPagingMetadata; +import org.eclipse.digitaltwin.basyx.operation.OperationRequestExecutor; +import org.eclipse.digitaltwin.basyx.operation.OperationRequestExecutor.Invokable; import org.eclipse.digitaltwin.basyx.pagination.GetSubmodelElementsResult; import org.eclipse.digitaltwin.basyx.serialization.SubmodelMetadataUtil; import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService; @@ -236,30 +234,9 @@ public ResponseEntity patchSubmodelValueOnly(@Parameter(in = ParameterIn.D public ResponseEntity invokeOperation( @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 = "Operation request object", required = true, schema = @Schema()) @Valid @RequestBody OperationRequest body) { - List inVars = new ArrayList<>(); - inVars.addAll(body.getInputArguments()); - inVars.addAll(body.getInoutputArguments()); - List result = Arrays.asList(service.invokeOperation(idShortPath, inVars.toArray(new OperationVariable[0]))); - - List outVars = new ArrayList<>(result); - List inoutputVars = new ArrayList<>(); - - if (!body.getInoutputArguments().isEmpty()) { - List inoutputVarsIdShorts = body.getInoutputArguments().stream().map(OperationVariable::getValue).map(SubmodelElement::getIdShort).toList(); - - inoutputVars = result.stream().filter(opVar -> inoutputVarsIdShorts.contains(opVar.getValue().getIdShort())).toList(); - - outVars.removeAll(inoutputVars); - } - - return ResponseEntity.ok(createOperationResult(outVars, inoutputVars)); - } - - private OperationResult createOperationResult(List outputVars, List inoutputVars) { - return new DefaultOperationResult.Builder() - .outputArguments(outputVars).inoutputArguments(inoutputVars) - .build(); + Invokable invokable = inArgs -> service.invokeOperation(idShortPath, inArgs); + return ResponseEntity.ok(OperationRequestExecutor.executeOperationRequestSynchronously(invokable, body)); } private String getEncodedCursorFromCursorResult(CursorResult cursorResult) { diff --git a/basyx.submodelservice/basyx.submodelservice-http/src/test/resources/operation/result-inout.json b/basyx.submodelservice/basyx.submodelservice-http/src/test/resources/operation/result-inout.json index 3aa563302..19b9d9bdc 100644 --- a/basyx.submodelservice/basyx.submodelservice-http/src/test/resources/operation/result-inout.json +++ b/basyx.submodelservice/basyx.submodelservice-http/src/test/resources/operation/result-inout.json @@ -1,4 +1,5 @@ { + "success": true, "inoutputArguments": [ { "value": { diff --git a/basyx.submodelservice/basyx.submodelservice-http/src/test/resources/operation/result.json b/basyx.submodelservice/basyx.submodelservice-http/src/test/resources/operation/result.json index 7a48f8c6a..20cf503ca 100644 --- a/basyx.submodelservice/basyx.submodelservice-http/src/test/resources/operation/result.json +++ b/basyx.submodelservice/basyx.submodelservice-http/src/test/resources/operation/result.json @@ -1,4 +1,5 @@ { + "success": true, "outputArguments": [ { "value": { diff --git a/pom.xml b/pom.xml index 2b32c14eb..c806de04e 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ linux/amd64, linux/arm64, linux/arm/v7 8081 8081 - 1.0.2 + 1.0.3