From a48f9f7c928950ed5d798f0abdf9284a5050e735 Mon Sep 17 00:00:00 2001 From: Daespen Date: Mon, 31 Jul 2023 10:02:22 +0200 Subject: [PATCH] Fixes File idShort collisions (#324) Signed-off-by: Daniel Espen --- .../submodel/restapi/SubmodelProvider.java | 11 +- .../restapi/SubmodelProviderTest.java | 111 ++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/eclipse/basyx/submodel/restapi/SubmodelProvider.java b/src/main/java/org/eclipse/basyx/submodel/restapi/SubmodelProvider.java index 8aa8dc3d..750a1f5f 100644 --- a/src/main/java/org/eclipse/basyx/submodel/restapi/SubmodelProvider.java +++ b/src/main/java/org/eclipse/basyx/submodel/restapi/SubmodelProvider.java @@ -39,6 +39,7 @@ 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.SubmodelElementCollection; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueTypeHelper; @@ -379,9 +380,17 @@ private String getIdShortFromSplittedPath(String[] splitted) { @SuppressWarnings("unchecked") private Object handleFile(String[] splitted) { String idShortPath = getFileIdShortFromSplittedPath4FileDownload(splitted); + + if (idShortPath.isEmpty()) { + return submodelAPI.getSubmodelElement(FILE); + } + Map submodelElement = (Map) submodelAPI.getSubmodelElement(idShortPath); - if (!File.isFile(submodelElement)) { + if (SubmodelElementCollection.isSubmodelElementCollection(submodelElement)) { + SubmodelElementCollection smeCollection = SubmodelElementCollection.createAsFacade(submodelElement); + return smeCollection.getSubmodelElement(FILE); + } else if (!File.isFile(submodelElement)) { throw new MalformedRequestException("/File is only allowed for File Submodel Elements"); } diff --git a/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SubmodelProviderTest.java b/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SubmodelProviderTest.java index bf0fa004..9afc9b5f 100644 --- a/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SubmodelProviderTest.java +++ b/src/test/java/org/eclipse/basyx/testsuite/regression/submodel/restapi/SubmodelProviderTest.java @@ -42,6 +42,7 @@ import org.eclipse.basyx.submodel.metamodel.map.qualifier.Identifiable; import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection; +import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.File; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueType; import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetype.ValueTypeHelper; @@ -67,6 +68,8 @@ public class SubmodelProviderTest { private VABConnectionManager connManager; protected static final String submodelAddr = "urn:fhg:es.iese:aas:1:1:submodel"; protected static final String SMPROVIDER_PATH_PREFIX = "/" + SubmodelProvider.SUBMODEL + "/"; + protected static final String SIMPLE_FILE_VALUE = "simpleFile.xml"; + protected static final String SIMPLE_PROPERTY_VALUE = "simpleProperty"; protected VABConnectionManager getConnectionManager() { if (connManager == null) { @@ -391,6 +394,114 @@ public void testUpdateElementInSmElementCollection() { assertEquals(321, value.intValue()); } + @SuppressWarnings("unchecked") + @Test + public void collectionIdShortFileCollision() { + VABElementProxy submodelProxy = getConnectionManager().connectToVABElement(submodelAddr); + + String colIdShort = "Files"; + String fileIdShort = "File"; + + SubmodelElementCollection fileCollection = new SubmodelElementCollection(colIdShort); + File fileSubmodelElement = new File("application/xml"); + String fileValue = "simpleFile.xml"; + fileSubmodelElement.setValue(fileValue); + fileSubmodelElement.setIdShort(fileIdShort); + fileCollection.addSubmodelElement(fileSubmodelElement); + + String smeCollectionPath = VABPathTools.concatenatePaths(SMPROVIDER_PATH_PREFIX, MultiSubmodelElementProvider.ELEMENTS, colIdShort); + submodelProxy.setValue(smeCollectionPath, fileCollection); + + String fileValuePath = VABPathTools.concatenatePaths(smeCollectionPath, fileIdShort); + Map resultingFileMap = (Map) submodelProxy.getValue(fileValuePath); + File resultingFile = File.createAsFacade(resultingFileMap); + assertEquals(fileValue, resultingFile.getValue()); + } + + /** + * Test getting a File with "File" as IdShort + */ + @Test + public void getFileSubmodelElement() { + VABElementProxy submodelProxy = getConnectionManager().connectToVABElement(submodelAddr); + String fileIdShort = "MySimpleFile"; + createSimpleFile(submodelProxy, fileIdShort); + assertSimpleFileValue(submodelProxy, fileIdShort); + } + + @Test + public void getIdShortCollision() { + VABElementProxy submodelProxy = getConnectionManager().connectToVABElement(submodelAddr); + String fileIdShort = "File"; + + Property fileProperty = new Property(fileIdShort, SIMPLE_PROPERTY_VALUE); + String propertyAccessPath = VABPathTools.concatenatePaths(SMPROVIDER_PATH_PREFIX, MultiSubmodelElementProvider.ELEMENTS, fileIdShort); + submodelProxy.setValue(propertyAccessPath, fileProperty); + + assertSimplePropertyValue(submodelProxy, fileIdShort); + } + + @Test + public void getFileIdShortCollision() { + VABElementProxy submodelProxy = getConnectionManager().connectToVABElement(submodelAddr); + String fileIdShort = "File"; + createSimpleFile(submodelProxy, fileIdShort); + assertSimpleFileValue(submodelProxy, fileIdShort); + } + + private void createSimpleFile(VABElementProxy submodelProxy, String fileIdShort) { + File fileSubmodelElement = new File("application/xml"); + fileSubmodelElement.setValue(SIMPLE_FILE_VALUE); + fileSubmodelElement.setIdShort(fileIdShort); + + String fileAccessPath = VABPathTools.concatenatePaths(SMPROVIDER_PATH_PREFIX, MultiSubmodelElementProvider.ELEMENTS, fileIdShort); + submodelProxy.setValue(fileAccessPath, fileSubmodelElement); + } + + @SuppressWarnings("unchecked") + private void assertSimpleFileValue(VABElementProxy submodelProxy, String fileIdShort) { + String fileAccessPath = VABPathTools.concatenatePaths(SMPROVIDER_PATH_PREFIX, MultiSubmodelElementProvider.ELEMENTS, fileIdShort); + Map resultingFileMap = (Map) submodelProxy.getValue(fileAccessPath); + File resultingFile = File.createAsFacade(resultingFileMap); + assertEquals(SIMPLE_FILE_VALUE, resultingFile.getValue()); + } + + @SuppressWarnings("unchecked") + private void assertSimplePropertyValue(VABElementProxy submodelProxy, String propertyIdShort) { + String accessPath = VABPathTools.concatenatePaths(SMPROVIDER_PATH_PREFIX, MultiSubmodelElementProvider.ELEMENTS, propertyIdShort); + Map resultingPropertyMap = (Map) submodelProxy.getValue(accessPath); + Property resultingProperty = Property.createAsFacade(resultingPropertyMap); + assertEquals(SIMPLE_PROPERTY_VALUE, resultingProperty.getValue()); + } + + @SuppressWarnings("unchecked") + @Test + public void nestedCollectionIdShortFileCollision() { + VABElementProxy submodelProxy = getConnectionManager().connectToVABElement(submodelAddr); + + String fileIdShort = "File"; + File fileSubmodelElement = new File("application/xml"); + String fileValue = "simpleFile.xml"; + fileSubmodelElement.setValue(fileValue); + fileSubmodelElement.setIdShort(fileIdShort); + + String innerColIdShort = "Files"; + SubmodelElementCollection innerCollection = new SubmodelElementCollection(innerColIdShort); + innerCollection.addSubmodelElement(fileSubmodelElement); + + String outerColIdShort = "Files"; + SubmodelElementCollection outerCollection = new SubmodelElementCollection(outerColIdShort); + outerCollection.addSubmodelElement(innerCollection); + + String outerCollectionPath = VABPathTools.concatenatePaths(SMPROVIDER_PATH_PREFIX, MultiSubmodelElementProvider.ELEMENTS, outerColIdShort); + submodelProxy.setValue(outerCollectionPath, outerCollection); + + String fileValuePath = VABPathTools.concatenatePaths(outerCollectionPath, innerColIdShort, fileIdShort); + Map resultingFileMap = (Map) submodelProxy.getValue(fileValuePath); + File resultingFile = File.createAsFacade(resultingFileMap); + assertEquals(fileValue, resultingFile.getValue()); + } + /** * Test reading a single operation */