Skip to content

Commit

Permalink
Merge pull request #374 from FriedJannik/development_api_fix
Browse files Browse the repository at this point in the history
Simplifies StorageSubmodelAPI
  • Loading branch information
FrankSchnicke authored Aug 10, 2023
2 parents b6d9f57 + 70a4bb6 commit 54fdade
Showing 1 changed file with 19 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,17 @@
import java.util.Map;

import org.eclipse.basyx.extensions.internal.storage.BaSyxStorageAPI;
import org.eclipse.basyx.submodel.metamodel.api.ISubmodel;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation;
import org.eclipse.basyx.submodel.metamodel.facade.SubmodelElementMapCollectionConverter;
import org.eclipse.basyx.submodel.metamodel.facade.submodelelement.SubmodelElementFacadeFactory;
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElement;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
import org.eclipse.basyx.submodel.restapi.SubmodelElementProvider;
import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI;
import org.eclipse.basyx.submodel.restapi.operation.DelegatedInvocationManager;
import org.eclipse.basyx.submodel.restapi.vab.VABSubmodelAPI;
import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;
import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
import org.eclipse.basyx.vab.modelprovider.lambda.VABLambdaProvider;
import org.eclipse.basyx.vab.modelprovider.map.VABMapProvider;

/**
* Abstract submodel api for storage backends.
Expand Down Expand Up @@ -98,7 +89,7 @@ public void setSubmodel(Submodel submodel) {
}

@Override
public ISubmodel getSubmodel() {
public Submodel getSubmodel() {
return storageApi.retrieve(identificationId);
}

Expand All @@ -111,115 +102,25 @@ public void addSubmodelElement(ISubmodelElement elem) {

@Override
public void addSubmodelElement(String idShortPath, ISubmodelElement elem) {
List<String> idShorts = idShortsPathAsList(idShortPath);
addNestedSubmodelElement(idShorts, elem);
}

private void addNestedSubmodelElement(List<String> idShorts, ISubmodelElement element) {
Submodel submodel = (Submodel) getSubmodel();
if (idShorts.size() > 1) {
idShorts = removeLastElement(idShorts);
ISubmodelElement parentElement = getNestedSubmodelElement(submodel, idShorts);
if (parentElement instanceof SubmodelElementCollection) {
addToSubmodelElementCollection(element, submodel, parentElement);
}
} else {
submodel.addSubmodelElement(element);
storageApi.update(submodel, identificationId);
}
}

private <T> List<T> removeLastElement(List<T> list) {
return list.subList(0, list.size() - 1);
}

private void addToSubmodelElementCollection(ISubmodelElement element, Submodel submodel, ISubmodelElement parentElement) {
((SubmodelElementCollection) parentElement).addSubmodelElement(element);
submodel.addSubmodelElement(parentElement);
storageApi.update(submodel, identificationId);
}

private ISubmodelElement getNestedSubmodelElement(Submodel submodel, List<String> idShorts) {
Map<String, ISubmodelElement> elementMap = submodel.getSubmodelElements();
Map<String, ISubmodelElement> resolvedElementMap = resolveElementPath(idShorts, elementMap);

String lastIdShort = idShorts.get(idShorts.size() - 1);
if (!resolvedElementMap.containsKey(lastIdShort)) {
throwPathCouldNotBeResolvedException(lastIdShort);
}

return resolvedElementMap.get(lastIdShort);
VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel()));
api.addSubmodelElement(idShortPath, elem);
storageApi.update(api.getSubmodel(), identificationId);
}

private Map<String, ISubmodelElement> resolveElementPath(List<String> idShorts, Map<String, ISubmodelElement> elementMap) {
var elementMapWrapper = new Object() {
Map<String, ISubmodelElement> wrappedElementMap = elementMap;
};

String lastIdShort = idShorts.get(idShorts.size() - 1);
idShorts.stream().takeWhile(idShort -> !lastIdShort.equals(idShort)).forEachOrdered(idShort -> {
ISubmodelElement element = elementMapWrapper.wrappedElementMap.get(idShort);
if (element instanceof SubmodelElementCollection) {
elementMapWrapper.wrappedElementMap = ((SubmodelElementCollection) element).getSubmodelElements();
} else {
throwPathCouldNotBeResolvedException(idShort);
}
});
return elementMapWrapper.wrappedElementMap;
}

private void throwPathCouldNotBeResolvedException(String idShort) {
throw new ResourceNotFoundException(idShort + " in the nested submodel element path could not be resolved.");
}

@Override
public ISubmodelElement getSubmodelElement(String idShortPath) {
List<String> idShorts = idShortsPathAsList(idShortPath);
ISubmodelElement submodelElement = getNestedSubmodelElement(idShorts);
return convertSubmodelElement(submodelElement);
}

private ISubmodelElement getNestedSubmodelElement(List<String> idShorts) {
Submodel submodel = (Submodel) getSubmodel();
return getNestedSubmodelElement(submodel, idShorts);
}

@SuppressWarnings("unchecked")
private ISubmodelElement convertSubmodelElement(ISubmodelElement element) {
Map<String, Object> convertedCollectionMap = SubmodelElementMapCollectionConverter.smElementToMap((Map<String, Object>) element);
return SubmodelElement.createAsFacade(convertedCollectionMap);
VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel()));
return api.getSubmodelElement(idShortPath);
}

@Override
public void deleteSubmodelElement(String idShortPath) {
if (idShortPath.contains("/")) {
List<String> idShorts = idShortsPathAsList(idShortPath);
deleteNestedSubmodelElement(idShorts);
} else {
deleteTopLevelSubmodelElement(idShortPath);
}

VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel()));
api.deleteSubmodelElement(idShortPath);
storageApi.update(api.getSubmodel(), identificationId);
}

private void deleteNestedSubmodelElement(List<String> idShorts) {
if (idShorts.size() == 1) {
deleteSubmodelElement(idShorts.get(0));
return;
}
Submodel submodel = (Submodel) getSubmodel();
List<String> parentIdShorts = removeLastElement(idShorts);
ISubmodelElement parentElement = getNestedSubmodelElement(submodel, parentIdShorts);
SubmodelElementCollection elementCollection = (SubmodelElementCollection) parentElement;
elementCollection.deleteSubmodelElement(idShorts.get(idShorts.size() - 1));
storageApi.update(submodel, identificationId);
}

private void deleteTopLevelSubmodelElement(String idShort) {
Submodel submodel = (Submodel) getSubmodel();
storageApi.deleteFile(submodel, idShort);
submodel.getSubmodelElements().remove(idShort);
storageApi.update(submodel, identificationId);
}

@Override
public Collection<IOperation> getOperations() {
Expand All @@ -235,56 +136,19 @@ public Collection<ISubmodelElement> getSubmodelElements() {

@Override
public void updateSubmodelElement(String idShortPath, Object newValue) {
List<String> idShorts = idShortsPathAsList(idShortPath);
updateSubmodelElement(idShorts, newValue);
VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel()));
api.updateSubmodelElement(idShortPath, newValue);
storageApi.update(api.getSubmodel(), identificationId);
}

@SuppressWarnings("unchecked")
private void updateSubmodelElement(List<String> idShorts, Object newValue) {
Submodel submodel = (Submodel) getSubmodel();
ISubmodelElement element = getNestedSubmodelElement(submodel, idShorts);

IModelProvider mapProvider = new VABLambdaProvider((Map<String, Object>) element);
IModelProvider smeProvider = new SubmodelElementProvider(mapProvider);

smeProvider.setValue(Property.VALUE, newValue);
ISubmodelElement updatedLastLevelElement = SubmodelElementFacadeFactory.createSubmodelElement((Map<String, Object>) smeProvider.getValue(""));
ISubmodelElement updatedNestedElement = createUpdatedNestedSubmodelElement(submodel, updatedLastLevelElement, idShorts);

submodel.addSubmodelElement(updatedNestedElement);

storageApi.update(submodel, identificationId);
}

@Override
public Object getSubmodelElementValue(String idShortPath) {
if (idShortPath.contains("/")) {
List<String> idShorts = idShortsPathAsList(idShortPath);
return getNestedSubmodelElementValue(idShorts);
} else {
return getTopLevelSubmodelElementValue(idShortPath);
}
}

private Object getTopLevelSubmodelElementValue(String idShort) {
Submodel submodel = (Submodel) getSubmodel();
return getElementProvider(submodel, idShort).getValue("/value");
}

@SuppressWarnings("unchecked")
private IModelProvider getElementProvider(Submodel submodel, String idShortPath) {
ISubmodelElement elem = submodel.getSubmodelElement(idShortPath);
IModelProvider mapProvider = new VABMapProvider((Map<String, Object>) elem);
return new SubmodelElementProvider(mapProvider);
}

@SuppressWarnings("unchecked")
private Object getNestedSubmodelElementValue(List<String> idShorts) {
ISubmodelElement lastElement = getNestedSubmodelElement(idShorts);
IModelProvider mapProvider = new VABMapProvider((Map<String, Object>) lastElement);
return new SubmodelElementProvider(mapProvider).getValue("/value");
VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel()));
return api.getSubmodelElementValue(idShortPath);
}

@Deprecated
@SuppressWarnings("unchecked")
protected Object unwrapParameter(Object parameter) {
if (parameter instanceof Map<?, ?>) {
Expand Down Expand Up @@ -329,18 +193,6 @@ public Object getOperationResult(String idShort, String requestId) {
throw new MalformedRequestException("Invoke not supported by this backend");
}

private ISubmodelElement createUpdatedNestedSubmodelElement(Submodel sm, ISubmodelElement updatedLastLevelElement, List<String> idShorts) {
ISubmodelElement updatedNestedElement = updatedLastLevelElement;
for (int i = idShorts.size() - 1; i > 0; i--) {
idShorts = idShorts.subList(0, i);
ISubmodelElementCollection nextLevelElementCollection = (ISubmodelElementCollection) getNestedSubmodelElement(sm, idShorts);
nextLevelElementCollection.addSubmodelElement(updatedNestedElement);
updatedNestedElement = nextLevelElementCollection;
}

return updatedNestedElement;
}

@SuppressWarnings("unchecked")
@Override
public java.io.File getSubmodelElementFile(String idShortPath) {
Expand All @@ -351,12 +203,10 @@ public java.io.File getSubmodelElementFile(String idShortPath) {

@Override
public void uploadSubmodelElementFile(String idShortPath, InputStream fileStream) {
String[] splitted = VABPathTools.splitPath(idShortPath);
List<String> idShorts = Arrays.asList(splitted);
Submodel sm = (Submodel) getSubmodel();
ISubmodelElement element = getNestedSubmodelElement(sm, idShorts);
VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel()));
ISubmodelElement element = api.getSubmodelElement(idShortPath);
String fileName = storageApi.writeFile(idShortPath, getSubmodel().getIdentification().getId(), fileStream, element);
updateSubmodelElement(idShorts, fileName);
updateSubmodelElement(idShortPath, fileName);
}

}

0 comments on commit 54fdade

Please sign in to comment.