Adds getSubmodelElements to IVABElementContainer

Adds a function to IVABElementContainer to get all SubmodelElements
Adds SubmodelElementFacadeFactory to create the correct facade for each SubmodelElement

Change-Id: I0ed49849f213a9bfa30aa4e5a9ff0171ad6bd955
Signed-off-by: Maximilian Conradi <maximilian.conradi@iese.fraunhofer.de>
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/ConnectedSubModel.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/ConnectedSubModel.java
index 55055a0..fcc57a9 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/ConnectedSubModel.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/ConnectedSubModel.java
@@ -110,4 +110,9 @@
 	public Map<String, IOperation> getOperations() {
 		return facade.getOperations();
 	}
+	
+	@Override
+	public Map<String, ISubmodelElement> getSubmodelElements() {
+		return facade.getSubmodelElements();
+	}
 }
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/facades/ConnectedVABElementContainerFacade.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/facades/ConnectedVABElementContainerFacade.java
index 9dc0e1f..3518ba4 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/facades/ConnectedVABElementContainerFacade.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/facades/ConnectedVABElementContainerFacade.java
@@ -8,11 +8,16 @@
 import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
 import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation;
 import org.eclipse.basyx.submodel.metamodel.connected.ConnectedVABModelMap;
+import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.ConnectedRelationshipElement;
+import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.ConnectedSubmodelElementCollection;
 import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.operation.ConnectedOperation;
 import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.property.ConnectedPropertyFactory;
 import org.eclipse.basyx.submodel.metamodel.map.IVABElementContainer;
 import org.eclipse.basyx.submodel.metamodel.map.SubModel;
+import org.eclipse.basyx.submodel.metamodel.map.modeltype.ModelType;
 import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.RelationshipElement;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
 import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
 import org.eclipse.basyx.vab.modelprovider.VABPathTools;
 
@@ -87,5 +92,73 @@
 		// Return result
 		return ret;
 	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public Map<String, ISubmodelElement> getSubmodelElements() {
+
+		// Create return value
+		Map<String, ISubmodelElement> ret = new HashMap<>();
+
+		// Sub model operation list
+		Object opList = getProxy().getModelPropertyValue(SubModel.OPERATIONS);
+		// Read values
+		Collection<Map<String, Object>> opNodes = (Collection<Map<String, Object>>) opList;
+		
+		// Sub model dataElement list
+		Object deList = getProxy().getModelPropertyValue(SubModel.PROPERTIES);
+		// Read values
+		Collection<Map<String, Object>> deNodes = (Collection<Map<String, Object>>) deList;
+		
+
+		// submodel element list; this list will contain all submodelElements
+		Object smElemList = getProxy().getModelPropertyValue(SubModel.SUBMODELELEMENT);
+		// Read values
+		Collection<Map<String, Object>> smElemNodes = (Collection<Map<String, Object>>) smElemList;
+		//remove all submodelElements already contained in on of the other lists
+		smElemNodes.removeAll(opNodes);
+		smElemNodes.removeAll(deNodes);
+		
+
+		// Convert to IOperation
+		for (Map<String, Object> opNode : opNodes) {
+			String id = (String) opNode.get(Referable.IDSHORT);
+
+			ConnectedOperation conOp = new ConnectedOperation(
+					getProxy().getDeepProxy(VABPathTools.concatenatePaths(SubModel.OPERATIONS, id)));
+			// Cache operation properties
+			conOp.putAllLocal(opNode);
+			ret.put(id, conOp);
+		}
+		
+		// Convert to IProperty
+		for (Map<String, Object> deNode : deNodes) {
+			String id = (String) deNode.get(Referable.IDSHORT);
+			ret.put(id, factory
+					.createProperty(getProxy().getDeepProxy(VABPathTools.concatenatePaths(SubModel.PROPERTIES, id))));
+		}
+		
+		// Convert to ISubmodelElement
+		for (Map<String, Object> smElemNode : smElemNodes) {
+			String id = (String) smElemNode.get(Referable.IDSHORT);
+			String modelType = ((String)((Map<String, Object>)(getProxy().getDeepProxy(
+							VABPathTools.concatenatePaths(ModelType.MODELTYPE, id)))).get(ModelType.NAME));
+			
+			//convert ISubmodelElementCollection
+			if(modelType.equals(SubmodelElementCollection.MODELTYPE)) {
+				ret.put(id, new ConnectedSubmodelElementCollection(
+						getProxy().getDeepProxy(VABPathTools.concatenatePaths(SubModel.SUBMODELELEMENT, id))));
+			}
+
+			//convert IRelationshipElement
+			if(modelType.equals(RelationshipElement.MODELTYPE)) {
+				ret.put(id, new ConnectedRelationshipElement(
+						getProxy().getDeepProxy(VABPathTools.concatenatePaths(SubModel.SUBMODELELEMENT, id))));
+			}
+		}
+
+		// Return result
+		return ret;
+	}
 
 }
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/property/ConnectedContainerProperty.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/property/ConnectedContainerProperty.java
index c308c94..9a4fe8b 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/property/ConnectedContainerProperty.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/connected/submodelelement/property/ConnectedContainerProperty.java
@@ -41,5 +41,9 @@
 	public Map<String, IOperation> getOperations() {
 		return facade.getOperations();
 	}
-
+	
+	@Override
+	public Map<String, ISubmodelElement> getSubmodelElements() {
+		return facade.getSubmodelElements();
+	}
 }
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/SubmodelFacade.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/SubmodelFacade.java
index ede562a..5723800 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/SubmodelFacade.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/SubmodelFacade.java
@@ -271,5 +271,9 @@
 	public Map<String, IOperation> getOperations() {
 		return containerFacade.getOperations();
 	}
-
+	
+	@Override
+	public Map<String, ISubmodelElement> getSubmodelElements() {
+		return containerFacade.getSubmodelElements();
+	}
 }
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/VABElementContainerFacade.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/VABElementContainerFacade.java
index 0579e79..d455a90 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/VABElementContainerFacade.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/VABElementContainerFacade.java
@@ -1,12 +1,16 @@
 package org.eclipse.basyx.submodel.metamodel.facade;
 
+import java.util.Collection;
+import java.util.HashMap;
 import java.util.Map;
 
 import org.eclipse.basyx.submodel.metamodel.api.submodelelement.IDataElement;
 import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
 import org.eclipse.basyx.submodel.metamodel.api.submodelelement.operation.IOperation;
+import org.eclipse.basyx.submodel.metamodel.facade.submodelelement.SubmodelElementFacadeFactory;
 import org.eclipse.basyx.submodel.metamodel.map.IVABElementContainer;
 import org.eclipse.basyx.submodel.metamodel.map.SubModel;
+import org.eclipse.basyx.submodel.metamodel.map.qualifier.Referable;
 
 /**
  * Facade providing access to attributes of entities implementing
@@ -56,4 +60,16 @@
 	public Map<String, IOperation> getOperations() {
 		return (Map<String, IOperation>) map.get(SubModel.OPERATIONS);
 	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public Map<String, ISubmodelElement> getSubmodelElements() {
+		Map<String, ISubmodelElement> ret = new HashMap<>();
+		Collection<Object> smElems = ((Map<String, Object>) map.get(SubModel.SUBMODELELEMENT)).values();
+		for(Object smElemO: smElems) {
+			Map<String, Object> smElem = (Map<String, Object>) smElemO;
+			ret.put((String) smElem.get(Referable.IDSHORT), SubmodelElementFacadeFactory.createSubmodelElement(smElem));
+		}
+		return ret;
+	}
 }
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/submodelelement/SubmodelElementFacadeFactory.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/submodelelement/SubmodelElementFacadeFactory.java
new file mode 100644
index 0000000..8f8dd64
--- /dev/null
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/facade/submodelelement/SubmodelElementFacadeFactory.java
@@ -0,0 +1,58 @@
+package org.eclipse.basyx.submodel.metamodel.facade.submodelelement;
+
+import java.util.Map;
+
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
+import org.eclipse.basyx.submodel.metamodel.facade.modeltype.ModelTypeFacade;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.ReferenceElement;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.RelationshipElement;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.OperationVariable;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.property.Event;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.property.Property;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.property.blob.Blob;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.property.file.File;
+
+/**
+ * Facade factory for SubmodelElement
+ * 
+ * @author conradi
+ * 
+ */
+public class SubmodelElementFacadeFactory {
+
+	/**
+	 * Takes a Map and creates the corresponding SubmodelElement as facade
+	 * 
+	 * @param smElement a Map containing the information of a SubmodelElement
+	 * @return the actual of the given SubmodelElement map created as facade
+	 */
+	public static ISubmodelElement createSubmodelElement(Map<String, Object> submodelElement) {
+		String type = ModelTypeFacade.getModelTypeName(submodelElement);
+		
+		switch (type) {
+			case Event.MODELTYPE:
+				return Event.createAsFacade(submodelElement);
+			case Property.MODELTYPE:
+				return Property.createAsFacade(submodelElement);
+			case File.MODELTYPE:
+				return File.createAsFacade(submodelElement);
+			case Blob.MODELTYPE:
+				return Blob.createAsFacade(submodelElement);
+			case ReferenceElement.MODELTYPE:
+				return ReferenceElement.createAsFacade(submodelElement);
+			case SubmodelElementCollection.MODELTYPE:
+				return SubmodelElementCollection.createAsFacade(submodelElement);
+			case RelationshipElement.MODELTYPE:
+				return RelationshipElement.createAsFacade(submodelElement);
+			case OperationVariable.MODELTYPE:
+				return OperationVariable.createAsFacade(submodelElement);
+			case Operation.MODELTYPE:
+				return Operation.createAsFacade(submodelElement);
+			default:
+				return null;
+		}
+	}
+	
+}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/IVABElementContainer.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/IVABElementContainer.java
index ba29517..2f8caa4 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/IVABElementContainer.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/IVABElementContainer.java
@@ -12,4 +12,6 @@
 	public Map<String, IDataElement> getDataElements();
 
 	public Map<String, IOperation> getOperations();
+	
+	public Map<String, ISubmodelElement> getSubmodelElements();
 }
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/SubModel.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/SubModel.java
index 3826240..9fbf8d6 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/SubModel.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/SubModel.java
@@ -214,4 +214,9 @@
 	public void addSubModelElement(ISubmodelElement element) {
 		new SubmodelFacade(this).addSubModelElement(element);
 	}
+	
+	@Override
+	public Map<String, ISubmodelElement> getSubmodelElements() {
+		return new SubmodelFacade(this).getSubmodelElements();
+	}
 }
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/property/ContainerProperty.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/property/ContainerProperty.java
index a7e1678..1730f3e 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/property/ContainerProperty.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/submodel/metamodel/map/submodelelement/property/ContainerProperty.java
@@ -47,4 +47,9 @@
 	public Map<String, IOperation> getOperations() {
 		return containerFacade.getOperations();
 	}
+	
+	@Override
+	public Map<String, ISubmodelElement> getSubmodelElements() {
+		return containerFacade.getSubmodelElements();
+	}
 }