Skip to content

Commit 5956f4b

Browse files
Merge pull request #66 from carlos-schmidt/config/submodel-only
Configuration: Only offer submodels
2 parents de86db6 + faf6f99 commit 5956f4b

18 files changed

+137
-96
lines changed

edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/aas/AasAgent.java

Lines changed: 70 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,30 @@
1515
*/
1616
package de.fraunhofer.iosb.app.aas;
1717

18+
import static java.lang.String.format;
19+
20+
import java.io.IOException;
21+
import java.net.URISyntaxException;
22+
import java.net.URL;
23+
import java.util.ArrayList;
24+
import java.util.Arrays;
25+
import java.util.Collection;
26+
import java.util.List;
27+
import java.util.Objects;
28+
29+
import org.eclipse.edc.spi.EdcException;
30+
1831
import com.fasterxml.jackson.databind.DeserializationFeature;
1932
import com.fasterxml.jackson.databind.ObjectMapper;
33+
2034
import de.fraunhofer.iosb.app.Logger;
21-
import de.fraunhofer.iosb.app.model.aas.*;
35+
import de.fraunhofer.iosb.app.model.aas.CustomAssetAdministrationShell;
36+
import de.fraunhofer.iosb.app.model.aas.CustomAssetAdministrationShellEnvironment;
37+
import de.fraunhofer.iosb.app.model.aas.CustomConceptDescription;
38+
import de.fraunhofer.iosb.app.model.aas.CustomSubmodel;
39+
import de.fraunhofer.iosb.app.model.aas.CustomSubmodelElement;
40+
import de.fraunhofer.iosb.app.model.aas.CustomSubmodelElementCollection;
41+
import de.fraunhofer.iosb.app.model.aas.Identifier;
2242
import de.fraunhofer.iosb.app.util.AASUtil;
2343
import de.fraunhofer.iosb.app.util.Encoder;
2444
import de.fraunhofer.iosb.app.util.HttpRestClient;
@@ -29,14 +49,6 @@
2949
import io.adminshell.aas.v3.model.impl.DefaultSubmodel;
3050
import jakarta.ws.rs.core.Response;
3151
import okhttp3.OkHttpClient;
32-
import org.eclipse.edc.spi.EdcException;
33-
34-
import java.io.IOException;
35-
import java.net.URISyntaxException;
36-
import java.net.URL;
37-
import java.util.*;
38-
39-
import static java.lang.String.format;
4052

4153
/**
4254
* Communicating with AAS service
@@ -123,11 +135,11 @@ public Response deleteModel(URL aasServiceUrl, String element) {
123135
* @return AAS model enriched with each elements access URL as string in assetId
124136
* field.
125137
*/
126-
public CustomAssetAdministrationShellEnvironment getAasEnvWithUrls(URL aasServiceUrl)
138+
public CustomAssetAdministrationShellEnvironment getAasEnvWithUrls(URL aasServiceUrl, boolean onlySubmodels)
127139
throws IOException, DeserializationException {
128140
var aasServiceUrlString = aasServiceUrl.toString();
129141

130-
var model = readModel(aasServiceUrl);
142+
var model = readModel(aasServiceUrl, onlySubmodels);
131143
// Add urls to all shells
132144
model.getAssetAdministrationShells().forEach(shell -> shell.setSourceUrl(
133145
format("%s/shells/%s", aasServiceUrlString,
@@ -139,9 +151,9 @@ public CustomAssetAdministrationShellEnvironment getAasEnvWithUrls(URL aasServic
139151
Encoder.encodeBase64(submodel.getIdentification().getId())));
140152
submodel.getSubmodelElements()
141153
.forEach(elem -> putUrlRec(
142-
format("%s/submodels/%s/submodel/submodel-elements", aasServiceUrlString,
143-
Encoder.encodeBase64(submodel.getIdentification().getId())),
144-
elem));
154+
format("%s/submodels/%s/submodel/submodel-elements", aasServiceUrlString,
155+
Encoder.encodeBase64(submodel.getIdentification().getId())),
156+
elem));
145157
});
146158
model.getSubmodels().forEach(submodel -> AASUtil.getAllSubmodelElements(submodel)
147159
.forEach(element -> element.setSourceUrl(
@@ -158,36 +170,53 @@ public CustomAssetAdministrationShellEnvironment getAasEnvWithUrls(URL aasServic
158170
/**
159171
* Returns the AAS model.
160172
*/
161-
private CustomAssetAdministrationShellEnvironment readModel(URL aasServiceUrl)
173+
private CustomAssetAdministrationShellEnvironment readModel(URL aasServiceUrl, boolean onlySubmodels)
162174
throws IOException, DeserializationException {
175+
var aasEnv = new CustomAssetAdministrationShellEnvironment();
163176

164-
String shellResponse;
165-
String conceptResponse;
166-
String submodelResponse;
177+
URL shellsUrl;
178+
URL conceptDescriptionsUrl;
179+
URL submodelUrl;
167180
try {
168-
shellResponse =
169-
Objects.requireNonNull(httpRestClient.get(aasServiceUrl.toURI().resolve("/shells").toURL()).body()).string();
170-
submodelResponse =
171-
Objects.requireNonNull(httpRestClient.get(aasServiceUrl.toURI().resolve("/submodels").toURL()).body()).string();
172-
conceptResponse = Objects.requireNonNull(httpRestClient.get(aasServiceUrl.toURI().resolve("/concept" +
173-
"-descriptions").toURL()).body())
174-
.string();
175-
} catch (URISyntaxException e) {
176-
throw new EdcException(e.getMessage());
181+
submodelUrl = aasServiceUrl.toURI().resolve("/submodels").toURL();
182+
shellsUrl = aasServiceUrl.toURI().resolve("/shells").toURL();
183+
conceptDescriptionsUrl = aasServiceUrl.toURI().resolve("/concept-descriptions").toURL();
184+
} catch (URISyntaxException resolveUriException) {
185+
throw new EdcException(
186+
format("Error while building URLs for reading from the AAS Service at %s", aasServiceUrl),
187+
resolveUriException);
177188
}
178189

179-
CustomAssetAdministrationShell[] shells = objectMapper.readValue(shellResponse,
180-
CustomAssetAdministrationShell[].class);
181-
CustomConceptDescription[] conceptDescriptions = objectMapper.readValue(conceptResponse,
182-
CustomConceptDescription[].class);
190+
aasEnv.setSubmodels(readSubmodels(submodelUrl, onlySubmodels));
191+
if (!onlySubmodels) {
192+
aasEnv.setAssetAdministrationShells(readShells(shellsUrl));
193+
aasEnv.setConceptDescriptions(readConceptDescriptions(conceptDescriptionsUrl));
194+
}
195+
return aasEnv;
196+
}
197+
198+
private List<CustomConceptDescription> readConceptDescriptions(URL conceptDescriptionsUrl) throws IOException {
183199

184-
// Because of SMCs "value" field, submodels have to be parsed manually
200+
var conceptResponse = Objects.requireNonNull(httpRestClient.get(conceptDescriptionsUrl).body()).string();
201+
202+
return Arrays.asList(objectMapper.readValue(conceptResponse, CustomConceptDescription[].class));
203+
}
185204

186-
// First, parse into full admin-shell.io submodels:
205+
private List<CustomAssetAdministrationShell> readShells(URL shellsUrl) throws IOException {
206+
var shellHttpResponse = Objects.requireNonNull(httpRestClient.get(shellsUrl).body()).string();
207+
208+
return Arrays.asList(objectMapper.readValue(shellHttpResponse, CustomAssetAdministrationShell[].class));
209+
}
210+
211+
private List<CustomSubmodel> readSubmodels(URL submodelUrl, boolean onlySubmodels)
212+
throws IOException, DeserializationException {
213+
var submodelHttpResponse = Objects.requireNonNull(httpRestClient.get(submodelUrl).body()).string();
214+
215+
// First, parse into "full" admin-shell.io submodels:
187216
JsonDeserializer jsonDeserializer = new JsonDeserializer();
188-
List<DefaultSubmodel> submodels = jsonDeserializer.readReferables(submodelResponse, DefaultSubmodel.class);
217+
List<DefaultSubmodel> submodels = jsonDeserializer.readReferables(submodelHttpResponse, DefaultSubmodel.class);
189218

190-
// Now, create custom submodels from the data of the full submodels
219+
// Now, create customSubmodels from the "full" submodels
191220
List<CustomSubmodel> customSubmodels = new ArrayList<>();
192221
for (Submodel submodel : submodels) {
193222
var customSubmodel = new CustomSubmodel();
@@ -197,20 +226,14 @@ private CustomAssetAdministrationShellEnvironment readModel(URL aasServiceUrl)
197226
customSubmodel.setIdentification(customIdentification);
198227

199228
customSubmodel.setIdShort(submodel.getIdShort());
200-
201-
// Recursively add submodelElements
202-
var customElements = AASUtil.getCustomSubmodelElementStructureFromSubmodel(submodel);
203-
customSubmodel.setSubmodelElements((List<CustomSubmodelElement>) customElements);
204-
229+
if (!onlySubmodels) {
230+
// Recursively add submodelElements
231+
var customElements = AASUtil.getCustomSubmodelElementStructureFromSubmodel(submodel);
232+
customSubmodel.setSubmodelElements((List<CustomSubmodelElement>) customElements);
233+
}
205234
customSubmodels.add(customSubmodel);
206235
}
207-
var aasEnv = new CustomAssetAdministrationShellEnvironment();
208-
209-
aasEnv.setAssetAdministrationShells(Arrays.asList(shells));
210-
aasEnv.setSubmodels(customSubmodels);
211-
aasEnv.setConceptDescriptions(Arrays.asList(conceptDescriptions));
212-
213-
return aasEnv;
236+
return customSubmodels;
214237
}
215238

216239
/**

edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/controller/AasController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ public Response handleRequest(RequestType requestType, URL url, String... reques
7070
* @throws DeserializationException AAS from service could not be deserialized
7171
* @throws IOException Communication with AAS service failed
7272
*/
73-
public CustomAssetAdministrationShellEnvironment getAasModelWithUrls(URL aasServiceUrl)
73+
public CustomAssetAdministrationShellEnvironment getAasModelWithUrls(URL aasServiceUrl, boolean onlySubmodels)
7474
throws IOException, DeserializationException {
7575
Objects.requireNonNull(aasServiceUrl);
76-
return aasAgent.getAasEnvWithUrls(aasServiceUrl);
76+
return aasAgent.getAasEnvWithUrls(aasServiceUrl, onlySubmodels);
7777
}
7878

7979
/**

edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/model/aas/CustomAssetAdministrationShellEnvironment.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616
package de.fraunhofer.iosb.app.model.aas;
1717

1818
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
19+
import com.fasterxml.jackson.annotation.JsonInclude;
1920

21+
import java.util.ArrayList;
2022
import java.util.List;
2123

24+
@JsonInclude(JsonInclude.Include.NON_EMPTY)
2225
@JsonIgnoreProperties(ignoreUnknown = true)
2326
public class CustomAssetAdministrationShellEnvironment {
2427

25-
protected List<CustomAssetAdministrationShell> assetAdministrationShells;
28+
protected List<CustomAssetAdministrationShell> assetAdministrationShells = new ArrayList<>();
2629

27-
protected List<CustomSubmodel> submodels;
30+
protected List<CustomSubmodel> submodels= new ArrayList<>();
2831

29-
protected List<CustomConceptDescription> conceptDescriptions;
32+
protected List<CustomConceptDescription> conceptDescriptions= new ArrayList<>();
3033

3134
public List<CustomAssetAdministrationShell> getAssetAdministrationShells() {
3235
return assetAdministrationShells;

edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/model/aas/CustomSubmodel.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717

1818
import com.fasterxml.jackson.annotation.JsonAutoDetect;
1919
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
20+
import com.fasterxml.jackson.annotation.JsonInclude;
2021

2122
import java.util.ArrayList;
2223
import java.util.List;
2324

25+
@JsonInclude(JsonInclude.Include.NON_EMPTY)
2426
@JsonIgnoreProperties(ignoreUnknown = true)
2527
@JsonAutoDetect
2628
public class CustomSubmodel extends AASElement {

edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/model/configuration/Configuration.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ public class Configuration {
4343

4444
@JsonProperty(SETTINGS_PREFIX + "syncPeriod")
4545
private int syncPeriod = 5; // Seconds
46+
47+
@JsonProperty(SETTINGS_PREFIX + "onlySubmodels")
48+
private boolean onlySubmodels = false;
4649

4750
@JsonProperty(SETTINGS_PREFIX + "exposeSelfDescription")
4851
private boolean exposeSelfDescription = true;
@@ -80,6 +83,14 @@ public int getSyncPeriod() {
8083
return syncPeriod;
8184
}
8285

86+
public boolean isOnlySubmodels() {
87+
return onlySubmodels;
88+
}
89+
90+
public void setOnlySubmodels(boolean onlySubmodels) {
91+
this.onlySubmodels = onlySubmodels;
92+
}
93+
8394
public boolean isExposeSelfDescription() {
8495
return exposeSelfDescription;
8596
}

edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/sync/Synchronizer.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import de.fraunhofer.iosb.app.controller.AasController;
1919
import de.fraunhofer.iosb.app.controller.ResourceController;
2020
import de.fraunhofer.iosb.app.model.aas.*;
21+
import de.fraunhofer.iosb.app.model.configuration.Configuration;
2122
import de.fraunhofer.iosb.app.model.ids.SelfDescription;
2223
import de.fraunhofer.iosb.app.model.ids.SelfDescriptionChangeListener;
2324
import de.fraunhofer.iosb.app.model.ids.SelfDescriptionRepository;
@@ -43,12 +44,14 @@ public class Synchronizer implements SelfDescriptionChangeListener {
4344
private final SelfDescriptionRepository selfDescriptionRepository;
4445
private final AasController aasController;
4546
private final ResourceController resourceController;
47+
private final Configuration configuration;
4648

4749
public Synchronizer(SelfDescriptionRepository selfDescriptionRepository,
4850
AasController aasController, ResourceController resourceController) {
4951
this.selfDescriptionRepository = selfDescriptionRepository;
5052
this.aasController = aasController;
5153
this.resourceController = resourceController;
54+
this.configuration = Configuration.getInstance();
5255
}
5356

5457
/**
@@ -62,10 +65,12 @@ public void synchronize() {
6265
}
6366

6467
private void synchronize(URL aasServiceUrl) {
68+
var onlySubmodels = this.configuration.isOnlySubmodels();
69+
6570
var oldSelfDescription = selfDescriptionRepository.getSelfDescription(aasServiceUrl);
66-
CustomAssetAdministrationShellEnvironment newEnvironment;
71+
var newEnvironment = fetchCurrentAasModel(aasServiceUrl, onlySubmodels);
6772

68-
newEnvironment = fetchCurrentAasModel(aasServiceUrl);
73+
// Only load submodels or shells, conceptDescriptions, submodelElements as well?
6974

7075
if (Objects.nonNull(oldSelfDescription)) {
7176
var oldEnvironment = oldSelfDescription.getEnvironment();
@@ -77,9 +82,10 @@ private void synchronize(URL aasServiceUrl) {
7782
// If the element exists in oldEnvironment, copy the old elements into
7883
// newEnvironment, already having an idsContractId/idsAssetId
7984
syncShell(newEnvironment, oldEnvironment);
80-
syncSubmodel(newEnvironment, oldEnvironment);
8185
syncConceptDescription(newEnvironment, oldEnvironment);
8286

87+
syncSubmodel(newEnvironment, oldEnvironment);
88+
8389
removeOldElements(newEnvironment, oldEnvironment);
8490

8591
// Finally, update the self description
@@ -88,11 +94,11 @@ private void synchronize(URL aasServiceUrl) {
8894
selfDescriptionRepository.updateSelfDescription(aasServiceUrl, newEnvironment);
8995
}
9096

91-
private CustomAssetAdministrationShellEnvironment fetchCurrentAasModel(URL aasServiceUrl) {
97+
private CustomAssetAdministrationShellEnvironment fetchCurrentAasModel(URL aasServiceUrl, boolean onlySubmodels) {
9298
CustomAssetAdministrationShellEnvironment newEnvironment;
9399

94100
try { // Fetch current AAS model from AAS service
95-
newEnvironment = aasController.getAasModelWithUrls(aasServiceUrl);
101+
newEnvironment = aasController.getAasModelWithUrls(aasServiceUrl, onlySubmodels);
96102
} catch (IOException aasServiceUnreachableException) {
97103
throw new EdcException(format("Could not reach AAS service (%s): %s", aasServiceUrl,
98104
aasServiceUnreachableException.getMessage()));
@@ -105,7 +111,8 @@ private CustomAssetAdministrationShellEnvironment fetchCurrentAasModel(URL aasSe
105111

106112
private void addNewElements(CustomAssetAdministrationShellEnvironment newEnvironment) {
107113
var envElements = AASUtil.getAllElements(newEnvironment);
108-
addAssetsContracts(envElements.stream().filter(element -> Objects.isNull(element.getIdsAssetId()) || Objects.isNull(element.getIdsContractId()))
114+
addAssetsContracts(envElements.stream().filter(
115+
element -> Objects.isNull(element.getIdsAssetId()) || Objects.isNull(element.getIdsContractId()))
109116
.toList());
110117
}
111118

edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/aas/AasAgentTest.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ public void initializeAasAgent() {
5959
aasAgent = new AasAgent(new OkHttpClient());
6060
}
6161

62-
@Test // Can't really test this anymore with new variable "sourceUrl" that is not
63-
// serialized
62+
@Test
6463
public void testGetAasEnvWithUrls() throws IOException, DeserializationException {
6564
var shells = FileManager.loadResource("shells.json");
6665
var submodels = FileManager.loadResource("submodels.json");
@@ -74,7 +73,27 @@ public void testGetAasEnvWithUrls() throws IOException, DeserializationException
7473
var shouldBeResult = FileManager.loadResource("selfDescriptionWithAccessURLS.json");
7574

7675
var result = new ObjectMapper().writeValueAsString(
77-
aasAgent.getAasEnvWithUrls(new URL(HTTP_LOCALHOST_8080)));
76+
aasAgent.getAasEnvWithUrls(new URL(HTTP_LOCALHOST_8080), false));
77+
result = result.replace("\n", "").replace(" ", "");
78+
79+
assertEquals(shouldBeResult, result);
80+
}
81+
82+
@Test
83+
public void testGetAasEnvWithUrlsOnlySubmodels() throws IOException, DeserializationException {
84+
var shells = FileManager.loadResource("shells.json");
85+
var submodels = FileManager.loadResource("submodels.json");
86+
var conceptDescriptions = FileManager.loadResource("conceptDescriptions.json");
87+
88+
mockServer.when(request().withMethod("GET").withPath("/shells")).respond(response().withBody(shells));
89+
mockServer.when(request().withMethod("GET").withPath("/submodels")).respond(response().withBody(submodels));
90+
mockServer.when(request().withMethod("GET").withPath("/concept-descriptions"))
91+
.respond(response().withBody(conceptDescriptions));
92+
93+
var shouldBeResult = FileManager.loadResource("selfDescriptionWithAccessURLsSubmodelsOnly.json");
94+
95+
var result = new ObjectMapper().writeValueAsString(
96+
aasAgent.getAasEnvWithUrls(new URL(HTTP_LOCALHOST_8080), true));
7897
result = result.replace("\n", "").replace(" ", "");
7998

8099
assertEquals(shouldBeResult, result);

edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/model/ids/SelfDescriptionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class SelfDescriptionTest {
2525
@Test
2626
public void emptyEnvironmentTest() {
2727
SelfDescription selfDescription = new SelfDescription(new CustomAssetAdministrationShellEnvironment());
28-
assertEquals("{\"assetAdministrationShells\":null,\"submodels\":null,\"conceptDescriptions\":null}",
28+
assertEquals("{}",
2929
selfDescription.toString());
3030
}
3131
}

edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/sync/SynchronizerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public void synchronizationInitializeTest() {
102102
}
103103

104104
@Test
105-
public void synchronizationRemoveSubmodelElementTest() {
105+
public void synchronizationRemoveAllSubmodelElementsTest() {
106106
startMockServer(port);
107107

108108
prepareDefaultMockedResponse();
@@ -142,7 +142,7 @@ public void synchronizationRemoveAllTest() {
142142

143143
prepareEmptyMockedResponse();
144144
synchronizer.synchronize();
145-
assertEquals("{\"assetAdministrationShells\":[],\"submodels\":[],\"conceptDescriptions\":[]}",
145+
assertEquals("{}",
146146
selfDescriptionRepo.getSelfDescription(url).toString());
147147
}
148148

0 commit comments

Comments
 (0)