Skip to content

Commit d2b4431

Browse files
aaronziFriedJannik
andauthored
Revert "Revert "Provide a generic submodel service component"" (eclipse-basyx#641)
* Revert "Revert "Provide a generic submodel service component (eclipse-basyx#446)" (eclipse-basyx#640)" This reverts commit 6d55f30. * Update basyx.submodelservice/basyx.submodelservice-feature-operation-dispatching/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/feature/operationdispatching/AbstractSubmodelServiceDecorator.java Co-authored-by: Jannik Fried <Jannik.Fried@iese.fraunhofer.de> * Update basyx.submodelservice/basyx.submodelservice-feature-operation-dispatching/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/feature/operationdispatching/AbstractSubmodelServiceDecorator.java Co-authored-by: Jannik Fried <Jannik.Fried@iese.fraunhofer.de> * Update basyx.submodelservice/basyx.submodelservice-feature-operation-dispatching/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/feature/operationdispatching/AbstractSubmodelServiceDecorator.java Co-authored-by: Jannik Fried <Jannik.Fried@iese.fraunhofer.de> * Update basyx.submodelservice/basyx.submodelservice-feature-operation-dispatching/src/main/java/org/eclipse/digitaltwin/basyx/submodelservice/feature/operationdispatching/AbstractSubmodelServiceDecorator.java Co-authored-by: Jannik Fried <Jannik.Fried@iese.fraunhofer.de> --------- Co-authored-by: Jannik Fried <Jannik.Fried@iese.fraunhofer.de>
1 parent 6d55f30 commit d2b4431

File tree

67 files changed

+3473
-17
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+3473
-17
lines changed

basyx.submodelrepository/basyx.submodelrepository-backend/src/main/java/org/eclipse/digitaltwin/basyx/submodelrepository/backend/CrudSubmodelRepository.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
package org.eclipse.digitaltwin.basyx.submodelrepository.backend;
2727

2828
import java.io.InputStream;
29-
import java.util.ArrayList;
3029
import java.util.Collection;
3130
import java.util.HashSet;
3231
import java.util.List;
@@ -36,10 +35,8 @@
3635
import java.util.stream.StreamSupport;
3736

3837
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
39-
import org.eclipse.digitaltwin.aas4j.v3.model.Reference;
4038
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
4139
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
42-
import org.eclipse.digitaltwin.basyx.client.internal.ApiException;
4340
import org.eclipse.digitaltwin.basyx.core.exceptions.CollidingIdentifierException;
4441
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
4542
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException;
@@ -49,7 +46,6 @@
4946
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
5047
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
5148
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationSupport;
52-
import org.eclipse.digitaltwin.basyx.http.Base64UrlEncoder;
5349
import org.eclipse.digitaltwin.basyx.serialization.SubmodelMetadataUtil;
5450
import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository;
5551
import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService;
@@ -59,7 +55,6 @@
5955
import org.slf4j.Logger;
6056
import org.slf4j.LoggerFactory;
6157
import org.springframework.data.repository.CrudRepository;
62-
import org.springframework.http.HttpStatus;
6358

6459
/**
6560
* Default Implementation for the {@link SubmodelRepository} based on Spring
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Submodel Service - Feature: Operation Dispatching
2+
3+
This feature enables the dispatching of operation calls to registered Java classes. Requests are delegated to the specified classes, allowing for flexible execution of operations.
4+
5+
Additionally, runtime Java code compilation is supported. If a source directory is provided, Java classes can be compiled on the fly. These compiled classes can then be utilized by assigning an `idShort` to a corresponding Java class.
6+
7+
The following configuration properties are available:
8+
9+
| Property | Example | Description |
10+
|---------------------------------------------------------------------------------------------|--------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
11+
| `basyx.submodelservice.feature.operation.dispatcher.enabled` | `true` | Determines whether the feature is enabled or not. |
12+
| `basyx.submodelservice.feature.operation.dispatcher.mappings[SquareOperation]` | `org.example.SquareOp` | Maps the `idShortPath` of an operation to the class `org.example.SquareOp`. |
13+
| `basyx.submodelservice.feature.operation.dispatcher.mappings[BasicOperations.AddOperation]` | `org.basic.AddOperation` | Another example of mapping an operation to a Java class. |
14+
| `basyx.submodelservice.feature.operation.dispatcher.defaultMapping` | `org.example.MyOperation` | Specifies the default operation to be called if no specific mapping is found. |
15+
| `basyx.submodelservice.feature.operation.dispatcher.java.sources` | `sources` | Directory containing the Java source files to be compiled. These classes can be dynamically loaded and executed at runtime. |
16+
| `basyx.submodelservice.feature.operation.dispatcher.java.classes` | `classes` | Directory for storing compiled classes. This is used in the classpath when loading classes. |
17+
| `basyx.submodelservice.feature.operation.dispatcher.java.additionalClasspath` | `jars/HelloWorld.jar,jars/test.jar` | Comma-separated list of additional libraries used during source compilation and class loading. |
18+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<modelVersion>4.0.0</modelVersion>
3+
<parent>
4+
<groupId>org.eclipse.digitaltwin.basyx</groupId>
5+
<artifactId>basyx.submodelservice</artifactId>
6+
<version>${revision}</version>
7+
</parent>
8+
<artifactId>basyx.submodelservice-feature-operation-dispatching</artifactId>
9+
<name>BaSyx submodelservice-feature-operation-dispatching</name>
10+
<description>BaSyx submodelservice-feature-operation-dispatching</description>
11+
12+
<dependencies>
13+
<dependency>
14+
<groupId>org.eclipse.digitaltwin.basyx</groupId>
15+
<artifactId>basyx.submodelservice-core</artifactId>
16+
</dependency>
17+
<dependency>
18+
<groupId>org.eclipse.digitaltwin.basyx</groupId>
19+
<artifactId>basyx.submodelservice-core</artifactId>
20+
<classifier>tests</classifier>
21+
<scope>test</scope>
22+
</dependency>
23+
<dependency>
24+
<groupId>org.eclipse.digitaltwin.basyx</groupId>
25+
<artifactId>basyx.submodelservice-backend-inmemory</artifactId>
26+
<scope>test</scope>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter</artifactId>
31+
</dependency>
32+
<dependency>
33+
<groupId>org.springframework.boot</groupId>
34+
<artifactId>spring-boot-starter-test</artifactId>
35+
<scope>test</scope>
36+
</dependency>
37+
</dependencies>
38+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*******************************************************************************
2+
* Copyright (C) 2024 DFKI GmbH (https://www.dfki.de/en/web)
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining
5+
* a copy of this software and associated documentation files (the
6+
* "Software"), to deal in the Software without restriction, including
7+
* without limitation the rights to use, copy, modify, merge, publish,
8+
* distribute, sublicense, and/or sell copies of the Software, and to
9+
* permit persons to whom the Software is furnished to do so, subject to
10+
* the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be
13+
* included in all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*
23+
* SPDX-License-Identifier: MIT
24+
*
25+
******************************************************************************/
26+
package org.eclipse.digitaltwin.basyx.submodelservice.feature.operationdispatching;
27+
28+
import java.io.File;
29+
import java.io.InputStream;
30+
import java.util.List;
31+
32+
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
33+
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
34+
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
35+
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
36+
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementNotAFileException;
37+
import org.eclipse.digitaltwin.basyx.core.exceptions.FileDoesNotExistException;
38+
import org.eclipse.digitaltwin.basyx.core.pagination.CursorResult;
39+
import org.eclipse.digitaltwin.basyx.core.pagination.PaginationInfo;
40+
import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService;
41+
import org.eclipse.digitaltwin.basyx.submodelservice.value.SubmodelElementValue;
42+
/**
43+
* @author Gerhard Sonnenberg DFKI GmbH
44+
*/
45+
public class AbstractSubmodelServiceDecorator implements SubmodelService {
46+
47+
private final SubmodelService decorated;
48+
49+
public AbstractSubmodelServiceDecorator(SubmodelService decorated) {
50+
this.decorated = decorated;
51+
}
52+
53+
@Override
54+
public Submodel getSubmodel() {
55+
return decorated.getSubmodel();
56+
}
57+
58+
@Override
59+
public CursorResult<List<SubmodelElement>> getSubmodelElements(PaginationInfo pInfo) {
60+
return decorated.getSubmodelElements(pInfo);
61+
}
62+
63+
@Override
64+
public SubmodelElement getSubmodelElement(String idShortPath) throws ElementDoesNotExistException {
65+
return decorated.getSubmodelElement(idShortPath);
66+
}
67+
68+
@Override
69+
public SubmodelElementValue getSubmodelElementValue(String idShortPath) throws ElementDoesNotExistException {
70+
return decorated.getSubmodelElementValue(idShortPath);
71+
}
72+
73+
@Override
74+
public void setSubmodelElementValue(String idShortPath, SubmodelElementValue value)
75+
throws ElementDoesNotExistException {
76+
decorated.setSubmodelElementValue(idShortPath, value);
77+
}
78+
79+
@Override
80+
public void createSubmodelElement(SubmodelElement submodelElement) {
81+
decorated.createSubmodelElement(submodelElement);
82+
}
83+
84+
@Override
85+
public void createSubmodelElement(String idShortPath, SubmodelElement submodelElement)
86+
throws ElementDoesNotExistException {
87+
decorated.createSubmodelElement(idShortPath, submodelElement);
88+
}
89+
90+
@Override
91+
public void updateSubmodelElement(String idShortPath, SubmodelElement submodelElement)
92+
throws ElementDoesNotExistException {
93+
decorated.updateSubmodelElement(idShortPath, submodelElement);
94+
}
95+
96+
@Override
97+
public void deleteSubmodelElement(String idShortPath) throws ElementDoesNotExistException {
98+
decorated.deleteSubmodelElement(idShortPath);
99+
}
100+
101+
@Override
102+
public void patchSubmodelElements(List<SubmodelElement> submodelElementList) {
103+
decorated.patchSubmodelElements(submodelElementList);
104+
}
105+
106+
@Override
107+
public OperationVariable[] invokeOperation(String idShortPath, OperationVariable[] input)
108+
throws ElementDoesNotExistException {
109+
return decorated.invokeOperation(idShortPath, input);
110+
}
111+
112+
@Override
113+
public File getFileByPath(String idShortPath)
114+
throws ElementDoesNotExistException, ElementNotAFileException, FileDoesNotExistException {
115+
return decorated.getFileByPath(idShortPath);
116+
}
117+
118+
@Override
119+
public void setFileValue(String idShortPath, String fileName, InputStream inputStream)
120+
throws ElementDoesNotExistException, ElementNotAFileException {
121+
decorated.setFileValue(idShortPath, fileName, inputStream);
122+
}
123+
124+
@Override
125+
public void deleteFileValue(String idShortPath)
126+
throws ElementDoesNotExistException, ElementNotAFileException, FileDoesNotExistException {
127+
decorated.deleteFileValue(idShortPath);
128+
}
129+
130+
@Override
131+
public InputStream getFileByFilePath(String filePath) {
132+
return decorated.getFileByFilePath(filePath);
133+
}
134+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*******************************************************************************
2+
* Copyright (C) 2024 DFKI GmbH (https://www.dfki.de/en/web)
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining
5+
* a copy of this software and associated documentation files (the
6+
* "Software"), to deal in the Software without restriction, including
7+
* without limitation the rights to use, copy, modify, merge, publish,
8+
* distribute, sublicense, and/or sell copies of the Software, and to
9+
* permit persons to whom the Software is furnished to do so, subject to
10+
* the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be
13+
* included in all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*
23+
* SPDX-License-Identifier: MIT
24+
*
25+
******************************************************************************/
26+
package org.eclipse.digitaltwin.basyx.submodelservice.feature.operationdispatching;
27+
28+
import java.util.Collections;
29+
import java.util.Map;
30+
31+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
32+
import org.springframework.boot.context.properties.ConfigurationProperties;
33+
import org.springframework.stereotype.Component;
34+
/**
35+
* @author Gerhard Sonnenberg DFKI GmbH
36+
*/
37+
@Component
38+
@ConfigurationProperties(prefix = OperationDispatchingSubmodelServiceFeature.FEATURENAME)
39+
@ConditionalOnProperty(name = OperationDispatchingSubmodelServiceFeature.FEATURENAME +".enabled", havingValue = "true")
40+
public class OperationDispatcherMapping {
41+
42+
private String defaultMapping;
43+
44+
private Map<String, String> mappings = Collections.emptyMap();
45+
46+
public void setDefaultMapping(String defaultMapping) {
47+
this.defaultMapping = defaultMapping;
48+
}
49+
50+
public String getDefaultMapping() {
51+
return defaultMapping;
52+
}
53+
54+
public void setMappings(Map<String, String> mappings) {
55+
this.mappings = mappings;
56+
}
57+
58+
public Map<String, String> getMappings() {
59+
return mappings;
60+
}
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*******************************************************************************
2+
* Copyright (C) 2024 DFKI GmbH (https://www.dfki.de/en/web)
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining
5+
* a copy of this software and associated documentation files (the
6+
* "Software"), to deal in the Software without restriction, including
7+
* without limitation the rights to use, copy, modify, merge, publish,
8+
* distribute, sublicense, and/or sell copies of the Software, and to
9+
* permit persons to whom the Software is furnished to do so, subject to
10+
* the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be
13+
* included in all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
*
23+
* SPDX-License-Identifier: MIT
24+
*
25+
******************************************************************************/
26+
27+
package org.eclipse.digitaltwin.basyx.submodelservice.feature.operationdispatching;
28+
29+
import org.eclipse.digitaltwin.aas4j.v3.model.Operation;
30+
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
31+
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
32+
import org.eclipse.digitaltwin.basyx.core.exceptions.ElementDoesNotExistException;
33+
import org.eclipse.digitaltwin.basyx.submodelservice.SubmodelService;
34+
import org.eclipse.digitaltwin.basyx.submodelservice.feature.operationdispatching.execution.OperationExecutor;
35+
import org.eclipse.digitaltwin.basyx.submodelservice.feature.operationdispatching.execution.OperationExecutorProvider;
36+
import org.springframework.http.HttpStatusCode;
37+
import org.springframework.web.server.ResponseStatusException;
38+
39+
/**
40+
* @author Gerhard Sonnenberg DFKI GmbH
41+
*/
42+
public class OperationDispatcherSubmodelService extends AbstractSubmodelServiceDecorator {
43+
44+
private final OperationExecutorProvider provider;
45+
46+
public OperationDispatcherSubmodelService(SubmodelService decorated, OperationExecutorProvider provider) {
47+
super(decorated);
48+
this.provider = provider;
49+
}
50+
51+
@Override
52+
public OperationVariable[] invokeOperation(String idShortPath, OperationVariable[] input)
53+
throws ElementDoesNotExistException {
54+
SubmodelElement elem = getSubmodelElement(idShortPath);
55+
if (!(elem instanceof Operation)) {
56+
throw new ResponseStatusException(HttpStatusCode.valueOf(404));
57+
}
58+
OperationExecutor executor = provider.getOperationExecutor(idShortPath);
59+
return executor.invoke(idShortPath, (Operation)elem, input);
60+
}
61+
}

0 commit comments

Comments
 (0)