Merge branch 'dev'

Change-Id: Ic89bdfb1e7c353ef4f72816419eea4a120e0db6f
diff --git a/NOTICE.txt b/NOTICE.txt
index 8bbd2e1..0dc71e0 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -17,13 +17,13 @@
 source code repository logs.
 
 Copyright (c) 2016-2018 Gigatronik Ingolstadt GmbH
-Copyright (c) 2016-2018 Peak Solution GmbH
+Copyright (c) 2016-2019 Peak Solution GmbH
 Copyright (c) 2017-2018 science + computing AG Tuebingen (ATOS SE)
 Copyright (c) 2017-2018 Canoo Engineering AG
 Copyright (c) 2017 Florian Schmitt
-Copyright (c) 2017-2018 Angelika Wittek
+Copyright (c) 2017-2019 Angelika Wittek
 Copyright (c) 2018 Elektronische Fahrwerksysteme GMBH
-Copyright (c) 2018 Karakun AG
+Copyright (c) 2018-2019 Karakun AG
 
 ## Declared Project Licenses
 
@@ -61,7 +61,13 @@
 commons-httpclient-3.1.jar  (3.1)
     * License: Apache License, 2.0
 
-commons-lang3-3.4.jar (3.4)
+commons-lang3-3.8.1.jar (3.8.1)
+    * License: Apache License, 2.0
+
+commons-text-1.6.jar (1.6)
+    * License: Apache License, 2.0
+
+commons-math-2.2.jar (2.2)
     * License: Apache License, 2.0
 
 gson-2.7.jar (2.7)
@@ -71,7 +77,7 @@
     * License: Apache License, 2.0
     
 Gradle Wrapper (4.10.2)
-    * License: Apache License, 2.0    
+    * License: Apache License, 2.0
 
 hk2-api-2.5.0-b05.jar (2.5.0-b05)
     * License: CDDL-1.1
@@ -130,6 +136,9 @@
 jersey-media-sse-2.23.2.jar (2.23.2)
     * License: CDDL
 
+jersey-media-multipart-2.23.2.jar (2.23.2)
+    * License: CDDL
+
 jersey-server-2.23.2.jar (2.23.2)
     * License: Apache-2.0
 
@@ -317,10 +326,10 @@
 From Dr. Ralph Noerenberg
 Date: 08/15/2016
 "Herewith, we release the generated Client-Source-Code generated from our CORBA IDLs, namely
-* CORBANotification Service (generated from „AvalonEvent.idl”)
-* CORBAFileServer (generated from „CorbaFileServer.idl“),
-Under the Eclipse Public License (EPL). This agreement does not include the „AvalonEvent.idl“ and
-„CorbaFileServer.idl“ itself, which remain protected property of HighQSoft. "
+* CORBANotification Service (generated from „AvalonEvent.idl”)
+* CORBAFileServer (generated from „CorbaFileServer.idl“),
+Under the Eclipse Public License (EPL). This agreement does not include the „AvalonEvent.idl“ and
+„CorbaFileServer.idl“ itself, which remain protected property of HighQSoft. "
 
 OMG Notification Service Specification Version: 1.1
 The terms of use are defined in section "Freely Available And Available
diff --git a/build.gradle b/build.gradle
index df409b3..52090f2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -14,27 +14,36 @@
 
 description = 'MDM API - Default Model'
 group = 'org.eclipse.mdm'
-version = '5.1.0M1'
+version = '5.1.0M2-SNAPSHOT'
 
 apply plugin: 'java'
 apply plugin: 'maven'
 apply plugin: 'eclipse'
 
 repositories {
-    mavenLocal()
-    mavenCentral()
+	mavenLocal()
+	mavenCentral()
 }
 
 dependencies {
 	compile "org.eclipse.mdm:org.eclipse.mdm.api.base:${version}"
-	
+
 	// testing
-    testCompile 'junit:junit:4.12'
-    testCompile 'org.mockito:mockito-core:2.13.0'
-    testCompile 'org.assertj:assertj-core:3.6.2'
+	testCompile 'junit:junit:4.12'
+	testCompile 'org.mockito:mockito-core:2.13.0'
+	testCompile 'org.assertj:assertj-core:3.6.2'
 }
 
 jar {
 	metaInf { from 'NOTICE.txt' }
 	metaInf { from 'LICENSE.txt' }
+}
+
+task sourcesJar(type: Jar, dependsOn: classes) {
+	classifier = 'sources'
+	from sourceSets.main.allSource
+}
+
+artifacts {
+	archives sourcesJar
 }
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/mdm/api/dflt/model/EntityFactory.java b/src/main/java/org/eclipse/mdm/api/dflt/model/EntityFactory.java
index 0137401..5e07cf1 100644
--- a/src/main/java/org/eclipse/mdm/api/dflt/model/EntityFactory.java
+++ b/src/main/java/org/eclipse/mdm/api/dflt/model/EntityFactory.java
@@ -55,6 +55,22 @@
 	// ======================================================================
 
 	/**
+	 * Creates a new {@link Role}.
+	 *
+	 * @param name
+	 *            Name of the created {@code Role}.
+	 * @return The created {@code Role} is returned.
+	 */
+	public Role createRole(String name) {
+		Role role = new Role(createCore(Role.class));
+
+		// properties
+		role.setName(name);
+
+		return role;
+	}
+	
+	/**
 	 * Always throws an UnsupportedOperationException since in a default model
 	 * each {@link Test} has a parent {@link Pool}.
 	 *
@@ -105,6 +121,19 @@
 	}
 
 	/**
+	 * Creates a new {@link Test} for given {@link Pool}.
+	 *
+	 * @param name
+	 *            Name of the created {@code Test}.
+	 * @param pool
+	 *            The parent {@code Pool}.
+	 * @return The created {@code Test} is returned.
+	 */
+	public Test createTest(String name, Pool pool) {
+		return createTest(name, pool, (Status) null);
+	}
+	
+	/**
 	 * Creates a new {@link Test} for given {@link Pool} using given
 	 * {@link TemplateTest}.
 	 *
@@ -153,10 +182,29 @@
 	 * @return The created {@code ContextRoot} is returned.
 	 */
 	public ContextRoot createContextRoot(Measurement measurement, TemplateRoot templateRoot) {
+		return createContextRoot(Arrays.asList(measurement), templateRoot);
+	}
+	
+	/**
+	 * Creates a new {@link ContextRoot} for given {@link List} if {@link Measurement}s using
+	 * given {@link TemplateRoot}. If List is null or empty context root is created with no
+	 * relations.
+	 *
+	 * @param measurements
+	 *            The parent {@code Measurement}.
+	 * @param templateRoot
+	 *            The template the returned {@code ContextRoot} will be derived
+	 *            from.
+	 * @return The created {@code ContextRoot} is returned.
+	 */
+	public ContextRoot createContextRoot(List<Measurement> measurements, TemplateRoot templateRoot) {
 		ContextRoot contextRoot = createContextRoot(templateRoot);
 
 		// relations
-		getCore(measurement).getMutableStore().set(contextRoot, templateRoot.getContextType());
+		if(measurements != null && !measurements.isEmpty()) {
+			measurements.forEach(m ->
+				getCore(m).getMutableStore().set(contextRoot, templateRoot.getContextType()));
+		}
 
 		return contextRoot;
 	}
@@ -919,7 +967,7 @@
 	 *            from.
 	 * @return The created {@code TestStep} is returned.
 	 */
-	protected TestStep createTestStep(Test test, TemplateTestStep templateTestStep) {
+	public TestStep createTestStep(Test test, TemplateTestStep templateTestStep) {
 		return createTestStep(test, null, templateTestStep);
 	}
 
@@ -941,7 +989,7 @@
 		TemplateTest templateTest = TemplateTest.of(test)
 				.orElseThrow(() -> new IllegalArgumentException("Template test is not available."));
 		if (!templateTest.contains(templateTestStep)) {
-			throw new IllegalArgumentException("Template test step is part of the test template.");
+			throw new IllegalArgumentException("Template test step is not part of the test template.");
 		}
 
 		TestStep testStep = createTestStep(templateTestStep.getName(), test, status);
diff --git a/src/main/java/org/eclipse/mdm/api/dflt/model/Role.java b/src/main/java/org/eclipse/mdm/api/dflt/model/Role.java
new file mode 100644
index 0000000..c15a9a1
--- /dev/null
+++ b/src/main/java/org/eclipse/mdm/api/dflt/model/Role.java
@@ -0,0 +1,57 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+package org.eclipse.mdm.api.dflt.model;
+
+import org.eclipse.mdm.api.base.adapter.Core;
+import org.eclipse.mdm.api.base.model.BaseEntity;
+import org.eclipse.mdm.api.base.model.Deletable;
+import org.eclipse.mdm.api.base.model.Describable;
+import org.eclipse.mdm.api.base.model.User;
+
+/**
+ * Implementation of the role entity type. Each role can contain multiple {@link User}
+ * and each {@link User} can be assigned multiple {@link Role}s.
+ */
+public class Role extends BaseEntity implements Deletable, Describable {
+
+	public static final String ATTR_SUPERUSER_FLAG = "SuperuserFlag";
+	public static final String REL_GROUPS2USERS = "groups2users";
+
+	/**
+	 * Constructor.
+	 *
+	 * @param core
+	 *            The {@link Core}.
+	 */
+	Role(Core core) {
+		super(core);
+		getValue(ATTR_SUPERUSER_FLAG).set((short) 0);
+	}
+
+	/**
+	 * @param user User to add
+	 */
+	public void addUser(User user) {
+		getCore().getNtoMStore().add(REL_GROUPS2USERS, user);
+	}
+
+
+	/**
+	 * @param user {@link User} to remove
+	 */
+	public void removeUser(User user) {
+		getCore().getNtoMStore().remove(REL_GROUPS2USERS, user);
+	}
+}