Merge "519139: Removed final keyword" into dev_0.7
diff --git a/build.gradle b/build.gradle
index b2bef13..ebc44e4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,4 +17,9 @@
 repositories {

     mavenLocal()

     mavenCentral()

+}

+

+dependencies {

+    // testing

+    testCompile 'junit:junit:4.12'

 }
\ No newline at end of file
diff --git a/src/test/java/org/eclipse/mdm/api/base/model/ModelTest.java b/src/test/java/org/eclipse/mdm/api/base/model/ModelTest.java
new file mode 100755
index 0000000..a924c91
--- /dev/null
+++ b/src/test/java/org/eclipse/mdm/api/base/model/ModelTest.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2017 science+computing ag
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.eclipse.mdm.api.base.model;
+
+import static org.junit.Assert.*;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.mdm.api.base.massdata.UnitBuilder;
+import org.eclipse.mdm.api.base.massdata.WriteRequest;
+import org.eclipse.mdm.api.base.massdata.WriteRequestBuilder;
+import org.eclipse.mdm.api.base.model.MeasuredValues.ValueIterator;
+
+/**
+ * 
+ * some unit test to test functionality of org.eclipse.mdm.api.base.model. At
+ * this point, please don't expect anything near complete test coverage.
+ * 
+ * @author Florian Schmitt
+ *
+ */
+public class ModelTest {
+	/**
+	 * 
+	 * Very basic implementation of BaseEntityFactory for testing purposes. We
+	 * deliver a core containing data on initialization to simulate other data
+	 * sources.
+	 * 
+	 * @author Florian Schmitt
+	 *
+	 */
+	private class EntityFactoryImpl extends BaseEntityFactory {
+
+		private Core core;
+
+		EntityFactoryImpl(Core core) {
+			this.core = core;
+		}
+
+		@Override
+		protected Optional<User> getLoggedInUser() {
+			return Optional.ofNullable(null);
+		}
+
+		@Override
+		protected <T extends Entity> Core createCore(Class<T> entityClass) {
+			return core;
+		}
+
+		@Override
+		protected <T extends Entity> Core createCore(Class<T> entityClass, ContextType contextType) {
+			return core;
+		}
+
+		@Override
+		protected <T extends Entity> Core createCore(String name, Class<T> entityClass) {
+			return core;
+		}
+
+	}
+
+	/**
+	 * 
+	 * Very basic implementation of the Core class. The contents is initialized
+	 * via a given map (instead of using a database or some other method)
+	 * 
+	 * @author Florian Schmitt
+	 */
+	private class CoreImpl implements Core {
+
+		private Map<String, Value> values;
+		private EntityStore mutableStore;
+
+		public CoreImpl(Map<String, Value> values) {
+			super();
+			this.values = values;
+			this.mutableStore = new EntityStore();
+		}
+
+		@Override
+		public String getSourceName() {
+			return "UnitTestSource";
+		}
+
+		@Override
+		public String getTypeName() {
+			return "UnitTestType";
+		}
+
+		@Override
+		public Long getID() {
+			return 4711l;
+		}
+
+		@Override
+		public void setID(Long instanceID) {
+
+		}
+
+		@Override
+		public Map<String, Value> getValues() {
+			return values;
+		}
+
+		@Override
+		public void hideValues(Collection<String> names) {
+
+		}
+
+		@Override
+		public Map<String, Value> getAllValues() {
+			return values;
+		}
+
+		@Override
+		public EntityStore getMutableStore() {
+			return mutableStore;
+		}
+
+		@Override
+		public EntityStore getPermanentStore() {
+			return new EntityStore();
+		}
+
+		@Override
+		public ChildrenStore getChildrenStore() {
+			return new ChildrenStore();
+		}
+
+	}
+
+	/**
+	 * Quick and dirty comparison of two numbers for approximate equality
+	 * 
+	 * @param a
+	 * @param b
+	 * @return
+	 */
+	private <T extends Number> boolean fpEquals(T a, T b) {
+		double eps = 0.00005d;
+		double ad = a.doubleValue();
+		double bd = b.doubleValue();
+		return (Math.abs(ad - bd) < eps * Math.abs(Math.max(ad, bd)));
+	}
+
+	/**
+	 * basic test for reading the value of a parameter.The intialization via
+	 * maps is needed to simulate the data store.
+	 */
+	@org.junit.Test
+	public void parameterValue() {
+		Map<String, Value> map = new HashMap<String, Value>();
+		map.put("DataType", new Value(ValueType.STRING, "DataType", null, true, ScalarType.FLOAT, ScalarType.class,
+				ScalarType.FLOAT));
+		map.put("Value", ValueType.STRING.create("Value", null, true, "5.7"));
+		map.put("Name", ValueType.STRING.create("Name", null, true, "paramname"));
+		Core core = new CoreImpl(map);
+		Parameter tp = new Parameter(core);
+		Value vv = tp.getVirtualValue();
+		Float extracted = vv.<Float>extract();
+		assertTrue(fpEquals(new Float(5.7f), extracted));
+	}
+
+	/**
+	 * basic test for reading measured float values
+	 */
+	@org.junit.Test
+	public void measuredValueFloat() {
+		Float[] vals = { 1.0f, 2.0f, 3.7f, 2.1f };
+		boolean[] flags = { true, true, false, true };
+		MeasuredValues mv = new MeasuredValues(ScalarType.FLOAT, "Value1", "lightyears", vals, flags);
+		ValueIterator<Float> valueIterator = mv.iterator();
+		int i = 0;
+		while (valueIterator.hasNext()) {
+			boolean isCurrentValid = valueIterator.isValid();
+			Float currentValue = valueIterator.next();
+			assertTrue(fpEquals(vals[i], currentValue));
+			assertEquals(flags[i], isCurrentValid);
+			i++;
+		}
+		assertEquals(i, vals.length);
+	}
+
+	/**
+	 * basic test for reading measured double values
+	 */
+	@org.junit.Test
+	public void measuredValueDouble() {
+		Double[] vals = { 1.0d, 2.0d, 3.7d, 2.1d };
+		boolean[] flags = { true, true, false, true };
+		MeasuredValues mv = new MeasuredValues(ScalarType.DOUBLE, "Value1", "lightyears", vals, flags);
+		ValueIterator<Double> valueIterator = mv.iterator();
+		int i = 0;
+		while (valueIterator.hasNext()) {
+			boolean isCurrentValid = valueIterator.isValid();
+			Double currentValue = valueIterator.next();
+			assertTrue(fpEquals(vals[i], currentValue));
+			assertEquals(flags[i], isCurrentValid);
+			i++;
+		}
+		assertEquals(i, vals.length);
+	}
+
+	/**
+	 * basic test for reading measured string values
+	 */
+	@org.junit.Test
+	public void measuredValueString() {
+		String[] vals = { "str1", "str2", "str3", "str4" };
+		boolean[] flags = { true, true, false, true };
+		MeasuredValues mv = new MeasuredValues(ScalarType.STRING, "Value1", "lightyears", vals, flags);
+		ValueIterator<String> valueIterator = mv.iterator();
+		int i = 0;
+		while (valueIterator.hasNext()) {
+			boolean isCurrentValid = valueIterator.isValid();
+			String currentValue = valueIterator.next();
+			assertEquals(vals[i], currentValue);
+			assertEquals(flags[i], isCurrentValid);
+			i++;
+		}
+		assertEquals(i, vals.length);
+	}
+
+	/**
+	 * basic test for reading attributes of the channel.The intialization via
+	 * maps is needed to simulate the data store.
+	 */
+	@org.junit.Test
+	public void getChannelAttrs() {
+		Map<String, Value> map = new HashMap<String, Value>();
+		float min_src = 5.7f;
+		float max_src = 10.23f;
+		map.put("Minimum", ValueType.DOUBLE.create("Minimum", "m/s", true, new Double(min_src)));
+		map.put("Maximum", ValueType.DOUBLE.create("Maximum", "m/s", true, new Double(max_src)));
+		Core core = new CoreImpl(map);
+		Channel ch = new Channel(core);
+		Double min = ch.getMinimum();
+		Double max = ch.getMaximum();
+		assertTrue(fpEquals(min, min_src));
+		assertTrue(fpEquals(max, max_src));
+	}
+
+	/**
+	 * basic test to read the default scalar type of a quantity. The
+	 * intialization via maps is needed to simulate the data store.
+	 */
+	@org.junit.Test
+	public void getQuantity() {
+		Map<String, Value> map = new HashMap<String, Value>();
+		map.put("DefDataType", new Value(ValueType.ENUMERATION, "name", "unit", true, ScalarType.FLOAT,
+				ScalarType.class, ScalarType.FLOAT));
+		Core core = new CoreImpl(map);
+		Quantity quantity = new Quantity(core);
+		ScalarType defaultScalarType = quantity.getDefaultScalarType();
+		assertTrue(defaultScalarType.isFloat());
+	}
+
+	/**
+	 * basic test for building a write request
+	 */
+	@org.junit.Test
+	public void writeRequest() {
+		AxisType axisType = AxisType.X_AXIS;
+		Map<String, Value> map = new HashMap<String, Value>();
+		Core core = new CoreImpl(map);
+		ChannelGroup channelGroup = new ChannelGroup(core);
+		Channel channel = new Channel(core);
+		WriteRequestBuilder wrb = WriteRequest.create(channelGroup, channel, axisType);
+		UnitBuilder ub = wrb.implicitConstant(ScalarType.DOUBLE, 0.7d);
+		WriteRequest wr = ub.build();
+		SequenceRepresentation sequenceRepresentation = wr.getSequenceRepresentation();
+		assertTrue(sequenceRepresentation.isConstant());
+		assertEquals(AxisType.X_AXIS, wr.getAxisType());
+	}
+
+	/**
+	 * basic test for getting a measurement channel and all necessary related
+	 * objects (measurment, and so on) via factory methods. The intialization
+	 * via maps is needed to simulate the data store.
+	 */
+	@org.junit.Test
+	public void entityFactory() {
+		Map<String, Value> map = new HashMap<String, Value>();
+		map.put("Name", ValueType.STRING.create("Name", null, true, "pdnameabc"));
+		map.put("Length", ValueType.INTEGER.create("Length", null, true, 13));
+		map.put("Mass", ValueType.INTEGER.create("Length", null, true, 0));
+		map.put("Time", ValueType.INTEGER.create("Length", null, true, 0));
+		map.put("Temperature", ValueType.INTEGER.create("Length", null, true, 0));
+		map.put("Current", ValueType.INTEGER.create("Length", null, true, 0));
+		map.put("MolarAmount", ValueType.INTEGER.create("Length", null, true, 0));
+		map.put("LuminousIntensity", ValueType.INTEGER.create("Length", null, true, 0));
+		// TODO: check if angle in lower case is correct
+		map.put("angle", ValueType.INTEGER.create("Length", null, true, 0));
+		Core core = new CoreImpl(map);
+		EntityFactoryImpl ef = new EntityFactoryImpl(core);
+		PhysicalDimension physicalDimension = ef.createPhysicalDimension("physdim");
+
+		map = new HashMap<String, Value>();
+		map.put("Offset", ValueType.DOUBLE.create("Length", null, true, 0d));
+		map.put("Factor", ValueType.DOUBLE.create("Length", null, true, 0d));
+		map.put("Name", ValueType.STRING.create("Name", null, true, "unitname"));
+		core = new CoreImpl(map);
+		ef = new EntityFactoryImpl(core);
+		Unit unit = ef.createUnit("unit", physicalDimension);
+
+		map = new HashMap<String, Value>();
+		map.put("Name", ValueType.STRING.create("Name", null, true, "quantname"));
+		map.put("Version", ValueType.STRING.create("Version", null, true, "4711"));
+		map.put("DateCreated", ValueType.DATE.create("DateCreated", null, true, null));
+		map.put("DefaultRank", ValueType.INTEGER.create("DefaultRank", null, true, 5));
+		map.put("DefDimension", ValueType.INTEGER_SEQUENCE.create("DefDimension", null, true, new int[] { 5 }));
+		map.put("DefTypeSize", ValueType.INTEGER.create("DefTypeSize", null, true, 8));
+		map.put("DefMQName", ValueType.STRING.create("DefMQName", null, true, "mqname"));
+		map.put("DefDataType", new Value(ValueType.ENUMERATION, "DefDataType", "", true, ScalarType.DOUBLE,
+				ScalarType.class, ScalarType.DOUBLE));
+		map.put("ValidFlag", new Value(ValueType.ENUMERATION, "ValidFlag", "", false, VersionState.ARCHIVED,
+				VersionState.class, null));
+		map.put("Description", ValueType.STRING.create("Description", null, true, null));
+		core = new CoreImpl(map);
+		ef = new EntityFactoryImpl(core);
+		Quantity quantity = ef.createQuantity("quantity", unit);
+		// Note that default values are set in createQuantity and thus should
+		// differ from above.
+		assertEquals(ScalarType.FLOAT, quantity.getDefaultScalarType());
+		assertEquals((Integer) 1, quantity.getDefaultRank());
+		assertEquals("quantity", quantity.getName());
+		assertEquals(unit, quantity.getDefaultUnit());
+
+		map = new HashMap<String, Value>();
+		map.put("Name", ValueType.STRING.create("Name", null, true, null));
+		map.put("DateCreated", ValueType.DATE.create("DateCreated", null, true, null));
+		core = new CoreImpl(map);
+		ef = new EntityFactoryImpl(core);
+		Test test = ef.createTest("mytest");
+
+		map = new HashMap<String, Value>();
+		map.put("Name", ValueType.STRING.create("Name", null, true, null));
+		map.put("DateCreated", ValueType.DATE.create("DateCreated", null, true, null));
+		map.put("Optional", ValueType.BOOLEAN.create("Optional", null, true, null));
+		map.put("Sortindex", ValueType.INTEGER.create("Sortindex", null, true, null));
+		core = new CoreImpl(map);
+		ef = new EntityFactoryImpl(core);
+		TestStep testStep = ef.createTestStep("teststep", test);
+
+		map = new HashMap<String, Value>();
+		map.put("Name", ValueType.STRING.create("Name", null, true, null));
+		map.put("DateCreated", ValueType.DATE.create("DateCreated", null, true, null));
+		core = new CoreImpl(map);
+		ef = new EntityFactoryImpl(core);
+		Measurement measurement = ef.createMeasurement("measurement", testStep);
+
+		map = new HashMap<String, Value>();
+		map.put("Name", ValueType.STRING.create("Name", null, true, null));
+		map.put("Description", ValueType.STRING.create("Description", null, true, null));
+		map.put("Interpolation",
+				new Value(ValueType.ENUMERATION, "Interpolation", "", true, null, Interpolation.class, null));
+		map.put("DataType", new Value(ValueType.ENUMERATION, "DataType", "", true, null, ScalarType.class, null));
+		map.put("TypeSize", ValueType.INTEGER.create("TypeSize", null, true, null));
+		map.put("Rank", ValueType.INTEGER.create("Rank", null, true, null));
+		core = new CoreImpl(map);
+		ef = new EntityFactoryImpl(core);
+		Channel channel = ef.createChannel("channel", measurement, quantity);
+		assertEquals(Interpolation.NONE, channel.getInterpolation());
+	}
+
+	/**
+	 * basic test of some ValuType methods.
+	 */
+	@org.junit.Test
+	public void valueType() {
+		assertEquals(ValueType.SHORT_SEQUENCE.toSingleType(), ValueType.SHORT);
+		assertEquals(ValueType.DATE.toSequenceType(), ValueType.DATE_SEQUENCE);
+		assertEquals(Float.class, ValueType.FLOAT.getValueClass());
+		assertEquals(true, ValueType.DOUBLE.isAnyFloatType());
+		assertEquals(true, ValueType.DOUBLE.isDouble());
+		assertEquals(false, ValueType.DOUBLE.isFloat());
+		assertEquals(true, ValueType.FLOAT.isAnyFloatType());
+		assertEquals(false, ValueType.INTEGER.isAnyFloatType());
+		assertEquals(true, ValueType.INTEGER.isInteger());
+		assertEquals(false, ValueType.FLOAT.isInteger());
+		assertEquals(true, ValueType.FLOAT.isFloat());
+	}
+
+	/**
+	 * basic tests of some ScalarType methods
+	 */
+	@org.junit.Test
+	public void scalarType() {
+		assertEquals(ValueType.BYTE_SEQUENCE, ScalarType.BYTE.toValueType());
+		assertEquals(true, ScalarType.LONG.isLong());
+		assertEquals(false, ScalarType.DOUBLE_COMPLEX.isLong());
+	}
+
+	/**
+	 * basic test of some SequenceReprestentaion methods
+	 */
+	@org.junit.Test
+	public void sequenceRepresentation() {
+		assertNotEquals(SequenceRepresentation.EXPLICIT, SequenceRepresentation.IMPLICIT_CONSTANT);
+		assertTrue(SequenceRepresentation.EXPLICIT.isExplicit());
+		assertTrue(SequenceRepresentation.EXPLICIT_EXTERNAL.isExplicit());
+		assertTrue(SequenceRepresentation.EXPLICIT_EXTERNAL.isExternal());
+		assertFalse(SequenceRepresentation.EXPLICIT_EXTERNAL.isImplicit());
+	}
+
+	/**
+	 * basic tests of TypeSpecification
+	 */
+	@org.junit.Test
+	public void typeSpecification() {
+		assertNotEquals(TypeSpecification.BIT_INTEGER, TypeSpecification.BIT_FLOAT_BEO);
+		assertEquals(TypeSpecification.BOOLEAN, TypeSpecification.BOOLEAN);
+	}
+
+	/**
+	 * basic tests of AxisTzpe methods
+	 */
+	@org.junit.Test
+	public void axisType() {
+		assertTrue(AxisType.X_AXIS.isXAxis());
+		assertTrue(AxisType.Y_AXIS.isYAxis());
+		assertTrue(AxisType.XY_AXIS.isXYAxis());
+		assertFalse(AxisType.X_AXIS.isYAxis());
+		assertFalse(AxisType.Y_AXIS.isXYAxis());
+		assertFalse(AxisType.XY_AXIS.isXAxis());
+	}
+
+	/**
+	 * basic tests of VersionState enumeration
+	 */
+	@org.junit.Test
+	public void versionState() {
+		assertFalse(VersionState.ARCHIVED.isEditable());
+		assertTrue(VersionState.ARCHIVED.isArchived());
+		assertFalse(VersionState.ARCHIVED.isValid());
+		assertTrue(VersionState.EDITABLE.isEditable());
+		assertFalse(VersionState.EDITABLE.isArchived());
+		assertFalse(VersionState.EDITABLE.isValid());
+		assertFalse(VersionState.VALID.isEditable());
+		assertFalse(VersionState.VALID.isArchived());
+		assertTrue(VersionState.VALID.isValid());
+	}
+
+	/**
+	 * basic tests of interpolation enumeration
+	 */
+	@org.junit.Test
+	public void interpolation() {
+		assertTrue(Interpolation.LINEAR.isLinear());
+		assertFalse(Interpolation.NONE.isSpecific());
+	}
+}