Adds new snippets

- Snippet hosting a preconfigured submodel
- Snippet creating a dynamic property

Change-Id: Idcef7e226a74a4d73353be3a8fa17f593f1a8859
Signed-off-by: Frank Schnicke <frank.schnicke@iese.fraunhofer.de>
diff --git a/examples/basys.examples/src/main/java/org/eclipse/basyx/examples/snippets/property/CreateLambdaProperty.java b/examples/basys.examples/src/main/java/org/eclipse/basyx/examples/snippets/property/CreateLambdaProperty.java
new file mode 100644
index 0000000..5259713
--- /dev/null
+++ b/examples/basys.examples/src/main/java/org/eclipse/basyx/examples/snippets/property/CreateLambdaProperty.java
@@ -0,0 +1,49 @@
+package org.eclipse.basyx.examples.snippets.property;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.AASLambdaPropertyHelper;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetypedef.PropertyValueTypeDef;
+
+/**
+ * This snippet showcases how create a lambda Property, i.e. a property that
+ * retrieves its value at runtime from an arbitrary backend. <br>
+ * This is for example useful if a sensor or a edge device has to be connected.
+ * It is valid to only provide a getter, i.e. in case of a sensor. <br>
+ * The lambda property will only work if it is included in a submodel and being
+ * hosted} <br>
+ * <br>
+ * Please note, that a submodel containing a dynamic property can not be pushed
+ * to another server. Instead, it has to be hosted on its own server (see
+ * {@link org.eclipse.basyx.examples.snippets.submodel.HostPreconfiguredSubmodel
+ * Host Preconfigured Submodel}).
+ * 
+ * @author schnicke
+ *
+ */
+public class CreateLambdaProperty {
+
+	/**
+	 * Configures the passed property so that calls to its setValue/getValue are
+	 * delegated
+	 * 
+	 * @param propertyIdShort
+	 *            id of the lambda property
+	 * @param type
+	 *            type of the lambda property
+	 * @param get
+	 *            getter to be used
+	 * @param set
+	 *            setter to be used
+	 * @return the created lambda property
+	 */
+	public static Property createLambdaProperty(String propertyIdShort, PropertyValueTypeDef type, Supplier<Object> get, Consumer<Object> set) {
+		Property prop = new Property(propertyIdShort, type);
+
+		AASLambdaPropertyHelper.setLambdaValue(prop, get, set);
+
+		return prop;
+	}
+}
diff --git a/examples/basys.examples/src/main/java/org/eclipse/basyx/examples/snippets/submodel/HostPreconfiguredSubmodel.java b/examples/basys.examples/src/main/java/org/eclipse/basyx/examples/snippets/submodel/HostPreconfiguredSubmodel.java
new file mode 100644
index 0000000..bce8686
--- /dev/null
+++ b/examples/basys.examples/src/main/java/org/eclipse/basyx/examples/snippets/submodel/HostPreconfiguredSubmodel.java
@@ -0,0 +1,51 @@
+package org.eclipse.basyx.examples.snippets.submodel;
+
+import org.eclipse.basyx.components.configuration.BaSyxContextConfiguration;
+import org.eclipse.basyx.components.servlet.submodel.SubmodelServlet;
+import org.eclipse.basyx.submodel.metamodel.map.SubModel;
+import org.eclipse.basyx.vab.protocol.http.server.AASHTTPServer;
+import org.eclipse.basyx.vab.protocol.http.server.BaSyxContext;
+
+/**
+ * This snippet showcases how host a submodel on a standalone server, i.e. a
+ * server that is preconfigured with a submodel and does not allow upload of
+ * additional AAS/Submodels<br>
+ * For instance, this can be used by a device manufacturer to provide a submodel
+ * containing live sensor data in combination with a dynamic property (cf.
+ * {@link org.eclipse.basyx.examples.snippets.property.CreateLambdaProperty
+ * CreateDynamicProperty}). <br>
+ * 
+ * @author schnicke
+ *
+ */
+public class HostPreconfiguredSubmodel {
+
+	/**
+	 * Creates, configures and starts an HTTP Server providing a preconfigured
+	 * submodel
+	 * 
+	 * @param serverContext
+	 *            the context configuration of the server
+	 * @param sm
+	 *            the submodel to be hosted
+	 * @return the started server
+	 */
+	public static AASHTTPServer hostPreconfiguredSubmodel(BaSyxContextConfiguration serverContext, SubModel sm) {
+		// Create the BaSyx context from the context configuration
+		BaSyxContext context = serverContext.createBaSyxContext();
+
+		// Create a new SubmodelServlet containing the passed submodel
+		SubmodelServlet smServlet = new SubmodelServlet(sm);
+
+		// Add the SubmodelServlet mapping to the context at the path "$SmIdShort"
+		// Here, it possible to add further submodels using the same pattern
+		context.addServletMapping("/" + sm.getIdShort() + "/*", smServlet);
+
+		// Create and start a HTTP server with the context created above
+		AASHTTPServer preconfiguredSmServer = new AASHTTPServer(context);
+		preconfiguredSmServer.start();
+
+		return preconfiguredSmServer;
+	}
+
+}
diff --git a/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/property/TestCreateLambdaProperty.java b/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/property/TestCreateLambdaProperty.java
new file mode 100644
index 0000000..a808663
--- /dev/null
+++ b/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/property/TestCreateLambdaProperty.java
@@ -0,0 +1,71 @@
+package org.eclipse.basyx.examples.snippets.property;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.basyx.aas.metamodel.map.descriptor.CustomId;
+import org.eclipse.basyx.components.configuration.BaSyxContextConfiguration;
+import org.eclipse.basyx.examples.snippets.submodel.HostPreconfiguredSubmodel;
+import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IProperty;
+import org.eclipse.basyx.submodel.metamodel.connected.ConnectedSubModel;
+import org.eclipse.basyx.submodel.metamodel.map.SubModel;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.Property;
+import org.eclipse.basyx.submodel.metamodel.map.submodelelement.dataelement.property.valuetypedef.PropertyValueTypeDef;
+import org.eclipse.basyx.vab.coder.json.connector.JSONConnector;
+import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
+import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnector;
+import org.eclipse.basyx.vab.protocol.http.server.AASHTTPServer;
+import org.junit.After;
+import org.junit.Test;
+
+/**
+ * Test for the CreateLambdaProperty snippet
+ * 
+ * @author schnicke
+ *
+ */
+public class TestCreateLambdaProperty {
+
+	// Value to be facaded by the lambda property
+	private int testValue = 15;
+
+	// Used for test case tear down
+	private AASHTTPServer server;
+
+	@Test
+	public void testCreateLambdaProperty() {
+		// The type cast in the setter is necessary due to the Consumer<Object> definition
+		Property lambdaProp = CreateLambdaProperty.createLambdaProperty("lambdaProp", PropertyValueTypeDef.Integer, () -> testValue, (v) -> testValue = (int) v);
+
+		// Package it in a test submodel and host it
+		SubModel sm = new SubModel("testSubmodelIdShort", new CustomId("testSubmodelId"));
+		sm.addSubModelElement(lambdaProp);
+		
+		// Create the context configuration and host the submodel containg the lambda property
+		BaSyxContextConfiguration config = new BaSyxContextConfiguration(4040, "");
+		server = HostPreconfiguredSubmodel.hostPreconfiguredSubmodel(config, sm);
+
+		// Here, for simplicity reason of the test, the ConnectedSubmodel is created by hand.
+		// In a real-world application, the AASManager would be used instead.
+		String smPath = "http://localhost:4040/" + sm.getIdShort() + "/submodel";
+
+		ConnectedSubModel cSm = new ConnectedSubModel(new VABElementProxy("", new JSONConnector(new HTTPConnector(smPath))));
+		IProperty cLambdaProp = (IProperty) cSm.getSubmodelElement(lambdaProp.getIdShort());
+
+		// Test getting
+		assertEquals(testValue, cLambdaProp.getValue());
+
+		// Test setting
+		int newVal = 100;
+		cLambdaProp.setValue(newVal);
+		assertEquals(newVal, cLambdaProp.getValue());
+		assertEquals(newVal, testValue);
+	}
+
+	// Ensures that the started server is shut down regardless of test result
+	@After
+	public void tearDown() {
+		if (server != null) {
+			server.shutdown();
+		}
+	}
+}
diff --git a/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/submodel/TestHostPreconfiguredSubmodel.java b/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/submodel/TestHostPreconfiguredSubmodel.java
new file mode 100644
index 0000000..9b5a33a
--- /dev/null
+++ b/examples/basys.examples/src/test/java/org/eclipse/basyx/examples/snippets/submodel/TestHostPreconfiguredSubmodel.java
@@ -0,0 +1,48 @@
+package org.eclipse.basyx.examples.snippets.submodel;
+
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.basyx.aas.metamodel.map.descriptor.CustomId;
+import org.eclipse.basyx.components.configuration.BaSyxContextConfiguration;
+import org.eclipse.basyx.submodel.metamodel.connected.ConnectedSubModel;
+import org.eclipse.basyx.submodel.metamodel.map.SubModel;
+import org.eclipse.basyx.vab.coder.json.connector.JSONConnector;
+import org.eclipse.basyx.vab.modelprovider.VABElementProxy;
+import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnector;
+import org.eclipse.basyx.vab.protocol.http.server.AASHTTPServer;
+import org.junit.After;
+import org.junit.Test;
+
+/**
+ * Test for the HostPreconfiguredSubmodel snippet
+ * 
+ * @author schnicke
+ *
+ */
+public class TestHostPreconfiguredSubmodel {
+
+	// Used for test case tear down
+	private AASHTTPServer server;
+
+	@Test
+	public void testHostPreconfiguredSubmodel() {
+		SubModel sm = new SubModel("testSubmodelIdShort", new CustomId("testSubmodel"));
+		BaSyxContextConfiguration contextConfig = new BaSyxContextConfiguration(4040, "");
+		server = HostPreconfiguredSubmodel.hostPreconfiguredSubmodel(contextConfig, sm);
+		String smPath = "http://localhost:4040/" + sm.getIdShort() + "/submodel";
+
+		// Here, for simplicity reason of the test, the ConnectedSubmodel is created by hand. 
+		// In a real-world application, the AASManager would be used instead.
+		ConnectedSubModel cSm = new ConnectedSubModel(new VABElementProxy("", new JSONConnector(new HTTPConnector(smPath))));
+		assertEquals(sm.getIdentification(), cSm.getIdentification());
+	}
+
+	// Ensures that the started server is shut down regardless of test result
+	@After
+	public void tearDown() {
+		if (server != null) {
+			server.shutdown();
+		}
+	}
+}