Skip to content

Commit 008c7f4

Browse files
Fixes MongoDBSubmodelAPI value retrieval bug (#243)
* Fixes MongoDBSubmodelAPI value retrieval bug Signed-off-by: Frank Schnicke <[email protected]>
1 parent 09ba32e commit 008c7f4

File tree

2 files changed

+107
-51
lines changed

2 files changed

+107
-51
lines changed

basyx.components/basyx.components.docker/basyx.components.AASServer/src/main/java/org/eclipse/basyx/components/aas/mongodb/MongoDBSubmodelAPI.java

Lines changed: 35 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
5454
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
5555
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
56+
import org.eclipse.basyx.vab.modelprovider.lambda.VABLambdaProvider;
5657
import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider;
5758
import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory;
5859
import org.springframework.data.mongodb.core.MongoOperations;
@@ -205,8 +206,7 @@ public void setSubmodel(Submodel sm) {
205206
String id = sm.getIdentification().getId();
206207
this.setSubmodelId(id);
207208

208-
Query hasId = query(where(SMIDPATH).is(smId));
209-
Object replaced = mongoOps.findAndReplace(hasId, sm, collection);
209+
Submodel replaced = writeSubmodelInDB(sm);
210210
if (replaced == null) {
211211
mongoOps.insert(sm, collection);
212212
}
@@ -250,9 +250,7 @@ public void addSubmodelElement(ISubmodelElement elem) {
250250
Submodel sm = (Submodel) getSubmodel();
251251
// Add element
252252
sm.addSubmodelElement(elem);
253-
// Replace db entry
254-
Query hasId = query(where(SMIDPATH).is(smId));
255-
mongoOps.findAndReplace(hasId, sm, collection);
253+
writeSubmodelInDB(sm);
256254
}
257255

258256
private ISubmodelElement getTopLevelSubmodelElement(String idShort) {
@@ -279,9 +277,7 @@ private void deleteTopLevelSubmodelElement(String idShort) {
279277
Submodel sm = (Submodel) getSubmodel();
280278
// Remove element
281279
sm.getSubmodelElements().remove(idShort);
282-
// Replace db entry
283-
Query hasId = query(where(SMIDPATH).is(smId));
284-
mongoOps.findAndReplace(hasId, sm, collection);
280+
writeSubmodelInDB(sm);
285281
}
286282

287283
@Override
@@ -299,16 +295,12 @@ private void addNestedSubmodelElement(List<String> idShorts, ISubmodelElement el
299295
ISubmodelElement parentElement = getNestedSubmodelElement(sm, idShorts);
300296
if (parentElement instanceof SubmodelElementCollection) {
301297
((SubmodelElementCollection) parentElement).addSubmodelElement(elem);
302-
// Replace db entry
303-
Query hasId = query(where(SMIDPATH).is(smId));
304-
mongoOps.findAndReplace(hasId, sm, collection);
298+
writeSubmodelInDB(sm);
305299
}
306300
} else {
307301
// else => directly add it to the submodel
308302
sm.addSubmodelElement(elem);
309-
// Replace db entry
310-
Query hasId = query(where(SMIDPATH).is(smId));
311-
mongoOps.findAndReplace(hasId, sm, collection);
303+
writeSubmodelInDB(sm);
312304
}
313305
}
314306

@@ -318,33 +310,20 @@ public Collection<ISubmodelElement> getSubmodelElements() {
318310
return sm.getSubmodelElements().values();
319311
}
320312

321-
private void updateTopLevelSubmodelElement(String idShort, Object newValue) {
322-
// Get sm from db
323-
Submodel sm = (Submodel) getSubmodel();
324-
// Unwrap value
325-
newValue = unwrapParameter(newValue);
326-
// Get and update property value
327-
getElementProvider(sm, idShort).setValue(Property.VALUE, newValue);
328-
// Replace db entry
329-
Query hasId = query(where(SMIDPATH).is(smId));
330-
mongoOps.findAndReplace(hasId, sm, collection);
331-
}
332-
333313
@SuppressWarnings("unchecked")
334-
private void updateNestedSubmodelElement(List<String> idShorts, Object newValue) {
314+
private void updateSubmodelElementInDB(List<String> idShorts, Object newValue) {
335315
Submodel sm = (Submodel) getSubmodel();
336-
337-
// Get parent SM element
338316
ISubmodelElement element = getNestedSubmodelElement(sm, idShorts);
339317

340-
// Update value
341-
IModelProvider mapProvider = new VABMapProvider((Map<String, Object>) element);
342-
IModelProvider elemProvider = SubmodelElementProvider.getElementProvider(mapProvider);
343-
elemProvider.setValue(Property.VALUE, newValue);
318+
IModelProvider mapProvider = new VABLambdaProvider((Map<String, Object>) element);
319+
SubmodelElementProvider smeProvider = new SubmodelElementProvider(mapProvider);
344320

345-
// Replace db entry
346-
Query hasId = query(where(SMIDPATH).is(smId));
347-
mongoOps.findAndReplace(hasId, sm, collection);
321+
smeProvider.setValue(Property.VALUE, newValue);
322+
ISubmodelElement updatedElement = SubmodelElementFacadeFactory.createSubmodelElement((Map<String, Object>) smeProvider.getValue(""));
323+
324+
sm.addSubmodelElement(updatedElement);
325+
326+
writeSubmodelInDB(sm);
348327
}
349328

350329
private Object getTopLevelSubmodelElementValue(String idShort) {
@@ -355,8 +334,8 @@ private Object getTopLevelSubmodelElementValue(String idShort) {
355334
@SuppressWarnings("unchecked")
356335
private Object getNestedSubmodelElementValue(List<String> idShorts) {
357336
ISubmodelElement lastElement = getNestedSubmodelElement(idShorts);
358-
IModelProvider mapProvider = new VABMapProvider((Map<String, Object>) lastElement);
359-
return SubmodelElementProvider.getElementProvider(mapProvider).getValue("/value");
337+
IModelProvider mapProvider = new VABLambdaProvider((Map<String, Object>) lastElement);
338+
return new SubmodelElementProvider(mapProvider).getValue("/value");
360339
}
361340

362341
@SuppressWarnings("unchecked")
@@ -374,10 +353,10 @@ protected Object unwrapParameter(Object parameter) {
374353
}
375354

376355
@SuppressWarnings("unchecked")
377-
private IModelProvider getElementProvider(Submodel sm, String idShortPath) {
378-
ISubmodelElement elem = sm.getSubmodelElement(idShortPath);
356+
private static SubmodelElementProvider getElementProvider(Submodel sm, String idShort) {
357+
ISubmodelElement elem = sm.getSubmodelElement(idShort);
379358
IModelProvider mapProvider = new VABMapProvider((Map<String, Object>) elem);
380-
return SubmodelElementProvider.getElementProvider(mapProvider);
359+
return new SubmodelElementProvider(mapProvider);
381360
}
382361

383362
private ISubmodelElement getNestedSubmodelElement(Submodel sm, List<String> idShorts) {
@@ -420,9 +399,7 @@ private void deleteNestedSubmodelElement(List<String> idShorts) {
420399
// Remove element
421400
SubmodelElementCollection coll = (SubmodelElementCollection) parentElement;
422401
coll.deleteSubmodelElement(idShorts.get(idShorts.size() - 1));
423-
// Replace db entry
424-
Query hasId = query(where(SMIDPATH).is(smId));
425-
mongoOps.findAndReplace(hasId, sm, collection);
402+
writeSubmodelInDB(sm);
426403
}
427404

428405
private Object invokeNestedOperationAsync(List<String> idShorts, Object... params) {
@@ -460,13 +437,20 @@ public void deleteSubmodelElement(String idShortPath) {
460437

461438
@Override
462439
public void updateSubmodelElement(String idShortPath, Object newValue) {
463-
if (idShortPath.contains("/")) {
464-
String[] splitted = VABPathTools.splitPath(idShortPath);
465-
List<String> idShorts = Arrays.asList(splitted);
466-
updateNestedSubmodelElement(idShorts, newValue);
467-
} else {
468-
updateTopLevelSubmodelElement(idShortPath, newValue);
469-
}
440+
String[] splitted = VABPathTools.splitPath(idShortPath);
441+
List<String> idShorts = Arrays.asList(splitted);
442+
updateSubmodelElementInDB(idShorts, newValue);
443+
}
444+
445+
/**
446+
* Returns the updated Submodel or null if not found
447+
*
448+
* @param sm
449+
* @return
450+
*/
451+
private Submodel writeSubmodelInDB(Submodel sm) {
452+
Query hasId = query(where(SMIDPATH).is(smId));
453+
return mongoOps.findAndReplace(hasId, sm, collection);
470454
}
471455

472456
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*******************************************************************************
2+
* Copyright (C) 2023 the Eclipse BaSyx Authors
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.basyx.regression.AASServer.mongodb;
27+
28+
import static org.junit.Assert.assertEquals;
29+
30+
import org.eclipse.basyx.aas.metamodel.map.descriptor.CustomId;
31+
import org.eclipse.basyx.components.aas.mongodb.MongoDBSubmodelAPI;
32+
import org.eclipse.basyx.components.configuration.BaSyxMongoDBConfiguration;
33+
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
34+
import org.eclipse.basyx.submodel.metamodel.map.qualifier.LangStrings;
35+
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.MultiLanguageProperty;
36+
import org.junit.Test;
37+
38+
import com.mongodb.client.MongoClient;
39+
import com.mongodb.client.MongoClients;
40+
41+
/**
42+
* Tests the ISubmodelAPI implementation of the MongoDB backend
43+
*
44+
* @author schnicke
45+
*/
46+
public class TestMongoDBSubmodelAPI {
47+
48+
@Test
49+
public void writeAndReadMultiLanguageProperty() {
50+
MongoDBSubmodelAPI submodelAPI = createAPIWithPreconfiguredSubmodel();
51+
52+
MultiLanguageProperty mlprop = new MultiLanguageProperty("myMLP");
53+
submodelAPI.addSubmodelElement(mlprop);
54+
55+
LangStrings expected = new LangStrings("de", "Hallo!");
56+
submodelAPI.updateSubmodelElement(mlprop.getIdShort(), expected);
57+
58+
Object value = submodelAPI.getSubmodelElementValue(mlprop.getIdShort());
59+
60+
assertEquals(expected, value);
61+
}
62+
63+
private MongoDBSubmodelAPI createAPIWithPreconfiguredSubmodel() {
64+
MongoClient client = MongoClients.create(new BaSyxMongoDBConfiguration().getConnectionUrl());
65+
MongoDBSubmodelAPI submodelAPI = new MongoDBSubmodelAPI("", client);
66+
67+
Submodel mySM = new Submodel("mySubmodel", new CustomId("mySubmodelId"));
68+
69+
submodelAPI.setSubmodel(mySM);
70+
return submodelAPI;
71+
}
72+
}

0 commit comments

Comments
 (0)