Merge branch 'dev' into aofile

Conflicts:
	api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXEntityConfigRepositoryLoader.java
	api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
	nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/control/ImportTask.java
	nucleus/webclient/src/main/webapp/src/assets/i18n/de.json
	nucleus/webclient/src/main/webapp/src/assets/i18n/en.json

Change-Id: Ie54a1230c6628fbeb99347025cb24fa575e82fdd
Signed-off-by: Matthias Koller <m.koller@peak-solution.de>
diff --git a/README.md b/README.md
index fe0728c..06277b9 100644
--- a/README.md
+++ b/README.md
@@ -364,7 +364,9 @@
 ## Connector and service.xml
 
 The `service.xml` contains all information necessary for the Connector-Service to connect to the available datasources/adapter instances.
-Since this information includes secret information like passwords, it is possible to provide lookups, which gives you the possibility to specify tokens as references to properties defined elsewhere.
+The `service.xml` changed in version 5.2.0M5 and since then the `service` tag needs the mandatory attribute `sourceName` which is used to distinguish the datasource and is used to select datasource in the webclient.
+
+Since the information in `service.xml` includes secret information like passwords, it is possible to provide lookups, which gives you the possibility to specify tokens as references to properties defined elsewhere.
 
 There are different lookups available
 * `sys`: Looks up variables defined as system properties
diff --git a/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContext.java b/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContext.java
index fc0b388..bd9488d 100644
--- a/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContext.java
+++ b/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContext.java
@@ -66,7 +66,7 @@
 	 * @param extSystemAttrList
 	 * @throws AoException
 	 */
-	public ATFXContext(ORB orb, AoSession aoSession, Map<String, String> parameters,
+	public ATFXContext(String sourceName, ORB orb, AoSession aoSession, Map<String, String> parameters,
 			List<ExtSystemAttribute> extSystemAttrList, File atfxFile) throws AoException {
 		this.parameters = parameters;
 
@@ -76,7 +76,8 @@
 
 		boolean includeCatalog = Boolean.valueOf(parameters.getOrDefault(INCLUDE_CATALOG, "false"));
 
-		this.modelManager = new ODSModelManager(orb, aoSession, new ATFXEntityConfigRepositoryLoader(includeCatalog));
+		this.modelManager = new ODSModelManager(sourceName, orb, aoSession,
+				new ATFXEntityConfigRepositoryLoader(includeCatalog));
 		this.entityManager = new ATFXEntityManager(this, extSystemAttrList);
 		this.atfxFile = atfxFile;
 
diff --git a/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContextFactory.java b/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContextFactory.java
index 0187ba0..f5ca660 100644
--- a/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContextFactory.java
+++ b/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContextFactory.java
@@ -45,12 +45,12 @@
 	private static final String PROP_EXTSYSTEMNAME = "extSystemName";
 
 	@Override
-	public ApplicationContext connect(Map<String, String> parameters) throws ConnectionException {
-		return initApplicationContext(parameters, null);
+	public ApplicationContext connect(String sourceName, Map<String, String> parameters) throws ConnectionException {
+		return initApplicationContext(sourceName, parameters, null);
 	}
 
-	public ApplicationContext connect(Map<String, String> parameters, ApplicationContext targetContext)
-			throws ConnectionException {
+	public ApplicationContext connect(String sourceName, Map<String, String> parameters,
+			ApplicationContext targetContext) throws ConnectionException {
 
 		EntityManager entityManager = targetContext.getEntityManager()
 				.orElseThrow(() -> new ConnectionException("TargetEntity manager not present!"));
@@ -73,10 +73,10 @@
 			}
 		}
 
-		return initApplicationContext(parameters, extSystemAttrList);
+		return initApplicationContext(sourceName, parameters, extSystemAttrList);
 	}
 
-	private ApplicationContext initApplicationContext(Map<String, String> parameters,
+	private ApplicationContext initApplicationContext(String sourceName, Map<String, String> parameters,
 			List<ExtSystemAttribute> extSystemAttrList) throws ConnectionException {
 		File atfxFile = new File(parameters.get("atfxfile"));
 
@@ -88,7 +88,7 @@
 				throw new ConnectionException(
 						"Cannot open session on a not existing or empty ATFX file: " + atfxFile.getAbsolutePath());
 			}
-			return new ATFXContext(orb, aoSession, parameters, extSystemAttrList, atfxFile);
+			return new ATFXContext(sourceName, orb, aoSession, parameters, extSystemAttrList, atfxFile);
 		} catch (AoException e) {
 			throw new ConnectionException("Error " + e.reason, e);
 		} catch (IOException e) {
diff --git a/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXEntityConfigRepositoryLoader.java b/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXEntityConfigRepositoryLoader.java
index 471c3cd..a98ee58 100644
--- a/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXEntityConfigRepositoryLoader.java
+++ b/api/atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXEntityConfigRepositoryLoader.java
@@ -30,6 +30,7 @@
 import org.eclipse.mdm.api.base.model.ExtCompFile;
 import org.eclipse.mdm.api.base.model.ExternalComponent;
 import org.eclipse.mdm.api.base.model.MeaResultFile;
+import org.eclipse.mdm.api.base.model.LocalColumn;
 import org.eclipse.mdm.api.base.model.Measurement;
 import org.eclipse.mdm.api.base.model.Parameter;
 import org.eclipse.mdm.api.base.model.ParameterSet;
@@ -110,6 +111,10 @@
 		channelConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Unit.class)));
 		channelConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Quantity.class)));
 		entityConfigRepository.register(channelConfig);
+		
+		// LocalColumn
+		EntityConfig<LocalColumn> localColumnConfig = create(modelManager, new Key<>(LocalColumn.class), "LocalColumn", false);
+		entityConfigRepository.register(localColumnConfig);
 
 		// ParameterSet
 		EntityConfig<Parameter> parameterConfig = create(modelManager, new Key<>(Parameter.class), "ResultParameter",
diff --git a/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterExtCompTest.java b/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterExtCompTest.java
index 255cebd..1853702 100644
--- a/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterExtCompTest.java
+++ b/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterExtCompTest.java
@@ -41,7 +41,7 @@
 	public static void init() throws ConnectionException {
 		Map<String, String> map = ImmutableMap.of("atfxfile", ATFX_FILE, "freetext.active", "false");
 
-		context = new ATFXContextFactory().connect(map);
+		context = new ATFXContextFactory().connect("ATFX", map);
 	}
 
 	@AfterClass
diff --git a/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterTest.java b/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterTest.java
index 1184f7a..32831f9 100644
--- a/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterTest.java
+++ b/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterTest.java
@@ -53,7 +53,7 @@
 	public static void init() throws ConnectionException {
 		Map<String, String> map = ImmutableMap.of("atfxfile", ATFX_FILE, "freetext.active", "false");
 
-		context = new ATFXContextFactory().connect(map);
+		context = new ATFXContextFactory().connect("ATFX", map);
 	}
 
 	@AfterClass
diff --git a/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterWriteTest.java b/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterWriteTest.java
index f171742..ae6e40f 100644
--- a/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterWriteTest.java
+++ b/api/atfxadapter/src/test/java/org/eclipse/mdm/api/atfxadapter/AtfxAdapterWriteTest.java
@@ -49,7 +49,7 @@
 		Map<String, String> map = ImmutableMap.of("atfxfile", f.getAbsolutePath(), "freetext.active", "false",
 				"includeCatalog", "true");
 
-		context = new ATFXContextFactory().connect(map);
+		context = new ATFXContextFactory().connect("ATFX", map);
 	}
 
 	@AfterClass
diff --git a/api/base/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContextFactory.java b/api/base/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContextFactory.java
index 4059c10..aea8b7f 100644
--- a/api/base/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContextFactory.java
+++ b/api/base/src/main/java/org/eclipse/mdm/api/base/BaseApplicationContextFactory.java
@@ -31,9 +31,10 @@
 	 * Takes given connection parameters and creates a new context, which is
 	 * permanently connected with configured data source.
 	 *
+	 * @param sourceName           name of the datasource
 	 * @param connectionParameters The connection parameters.
 	 * @return The connected context is returned.
 	 * @throws ConnectionException Thrown if unable to connect to a data source.
 	 */
-	T connect(Map<String, String> connectionParameters) throws ConnectionException;
+	T connect(String sourceName, Map<String, String> connectionParameters) throws ConnectionException;
 }
\ No newline at end of file
diff --git a/api/base/src/main/java/org/eclipse/mdm/api/base/model/BaseParameter.java b/api/base/src/main/java/org/eclipse/mdm/api/base/model/BaseParameter.java
index 22ae210..82d12fb 100644
--- a/api/base/src/main/java/org/eclipse/mdm/api/base/model/BaseParameter.java
+++ b/api/base/src/main/java/org/eclipse/mdm/api/base/model/BaseParameter.java
@@ -15,6 +15,8 @@
 package org.eclipse.mdm.api.base.model;
 
 import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
@@ -194,6 +196,8 @@
 			setFloatComplexValue((FloatComplex) value, unit);
 		} else if (value instanceof DoubleComplex) {
 			setDoubleComplexValue((DoubleComplex) value, unit);
+		} else if (value instanceof Date) {
+			setDateValue(((Date) value).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
 		} else {
 			throw new IllegalArgumentException(
 					"Value '" + value + "' of type '" + value.getClass().getSimpleName() + "' is not supported.");
diff --git a/api/base/src/main/java/org/eclipse/mdm/api/base/model/LocalColumn.java b/api/base/src/main/java/org/eclipse/mdm/api/base/model/LocalColumn.java
new file mode 100644
index 0000000..78fcc07
--- /dev/null
+++ b/api/base/src/main/java/org/eclipse/mdm/api/base/model/LocalColumn.java
@@ -0,0 +1,40 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 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.base.model;
+
+import org.eclipse.mdm.api.base.adapter.Core;
+
+/**
+ * Implementation of the local column entity type. 
+ * <p>
+ * Introduced for use as the result type in {@link QueryRequest}s where the result set should be aggregated by LocalColumn IDs.
+ * <p>
+ * Avoid using this Entity in situations where all attribute values of an entity instance are retrieved from the data source 
+ * (for example the load methods of {@link EntityManager}) as this would include the (potentially large) data sets for the 
+ * Values and Flags values.
+ *
+ * @author Martin Fleischer, Peak Solution GmbH
+ */
+public class LocalColumn extends BaseEntity {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param core The {@link Core}.
+	 */
+	LocalColumn(Core core) {
+		super(core);
+	}
+}
diff --git a/api/base/src/test/java/org/eclipse/mdm/api/base/WriteRequestBuilderTest.java b/api/base/src/test/java/org/eclipse/mdm/api/base/WriteRequestBuilderTest.java
index 26513aa..8fda594 100644
--- a/api/base/src/test/java/org/eclipse/mdm/api/base/WriteRequestBuilderTest.java
+++ b/api/base/src/test/java/org/eclipse/mdm/api/base/WriteRequestBuilderTest.java
@@ -36,16 +36,20 @@
 	private final AxisType axisType = mock(AxisType.class);

 

 	private final ExternalComponentData externalComponent1 = new ExternalComponentData()

-			.setTypeSpecification(TypeSpecification.BIT_INTEGER).setStartOffset(100).setBlocksize(1)

-			.setValuesPerBlock(100).setLength(100).setFileLink(FileLink.newRemote("extComp1.btf", new MimeType(""), "", -1L, null, FileServiceType.EXTREF))

-			.setFlagsFileLink(FileLink.newRemote("extCompFlags.btf", new MimeType(""), "", -1L, null, FileServiceType.EXTREF)).setFlagsStartOffset(0L)

-			.setBitCount((short) 24).setBitOffset((short) 0);

+			.setTypeSpecification(TypeSpecification.BIT_INTEGER).setStartOffset(100L).setBlocksize(1)

+			.setValuesPerBlock(100).setLength(100)

+			.setFileLink(FileLink.newRemote("extComp1.btf", new MimeType(""), "", -1L, null, FileServiceType.EXTREF))

+			.setFlagsFileLink(

+					FileLink.newRemote("extCompFlags.btf", new MimeType(""), "", -1L, null, FileServiceType.EXTREF))

+			.setFlagsStartOffset(0L).setBitCount((short) 24).setBitOffset((short) 0);

 

 	private final ExternalComponentData externalComponent2 = new ExternalComponentData()

-			.setTypeSpecification(TypeSpecification.BIT_INTEGER).setStartOffset(10).setBlocksize(1)

-			.setValuesPerBlock(50).setLength(200).setFileLink(FileLink.newRemote("extComp2.btf", new MimeType(""), "", -1L, null, FileServiceType.EXTREF))

-			.setFlagsFileLink(FileLink.newRemote("extCompFlags.btf", new MimeType(""), "", -1L, null, FileServiceType.EXTREF)).setFlagsStartOffset(200L)

-			.setBitCount((short) 24).setBitOffset((short) 0);

+			.setTypeSpecification(TypeSpecification.BIT_INTEGER).setStartOffset(10L).setBlocksize(1)

+			.setValuesPerBlock(50).setLength(200)

+			.setFileLink(FileLink.newRemote("extComp2.btf", new MimeType(""), "", -1L, null, FileServiceType.EXTREF))

+			.setFlagsFileLink(

+					FileLink.newRemote("extCompFlags.btf", new MimeType(""), "", -1L, null, FileServiceType.EXTREF))

+			.setFlagsStartOffset(200L).setBitCount((short) 24).setBitOffset((short) 0);

 

 	@Test

 	public void testOneExternalComponent() {

diff --git a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java
index 249de9f..b66f7b1 100644
--- a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java
+++ b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContext.java
@@ -76,15 +76,15 @@
 	 * @param parameters
 	 * @throws AoException
 	 */
-	public ODSContext(ORB orb, AoSession aoSession, CORBAFileServerIF fileServer, Map<String, String> parameters)
-			throws AoException {
-		this(orb, aoSession, fileServer, parameters, null);
+	public ODSContext(String sourceName, ORB orb, AoSession aoSession, CORBAFileServerIF fileServer,
+			Map<String, String> parameters) throws AoException {
+		this(sourceName, orb, aoSession, fileServer, parameters, null);
 	}
 
 	/**
 	 * Creates a new ODS application context.
 	 *
-	 * @param orb        the CORBA ORB used to connect to the ODS API
+	 * @param orb              the CORBA ORB used to connect to the ODS API
 	 * @param aoSession
 	 * @param fileServer
 	 * @param parameters
@@ -93,16 +93,16 @@
 	 *
 	 * @since 5.2.0
 	 */
-	public ODSContext(ORB orb, AoSession aoSession, CORBAFileServerIF fileServer, Map<String, String> parameters, EntityConfigRepositoryLoader repositoryLoader)
-			throws AoException {
+	public ODSContext(String sourceName, ORB orb, AoSession aoSession, CORBAFileServerIF fileServer,
+			Map<String, String> parameters, EntityConfigRepositoryLoader repositoryLoader) throws AoException {
 		this.fileServer = fileServer;
 		this.parameters = parameters;
 
 		this.repositoryLoader = repositoryLoader;
 		if (repositoryLoader == null) {
-			this.modelManager = new ODSModelManager(orb, aoSession);
+			this.modelManager = new ODSModelManager(sourceName, orb, aoSession);
 		} else {
-			this.modelManager = new ODSModelManager(orb, aoSession, repositoryLoader);
+			this.modelManager = new ODSModelManager(sourceName, orb, aoSession, repositoryLoader);
 		}
 		this.queryService = new ODSQueryService(this.modelManager);
 		this.entityManager = new ODSEntityManager(this);
@@ -260,6 +260,7 @@
 	 * @throws AoException Thrown on errors.
 	 */
 	public ODSContext newContext() throws AoException {
-		return new ODSContext(modelManager.getORB(), getAoSession().createCoSession(), fileServer, parameters, repositoryLoader);
+		return new ODSContext(modelManager.getSourceName(), modelManager.getORB(), getAoSession().createCoSession(),
+				fileServer, parameters, repositoryLoader);
 	}
 }
diff --git a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java
index 33a2e1b..e418c01 100644
--- a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java
+++ b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/ODSContextFactory.java
@@ -59,7 +59,7 @@
 	public static final String PARAM_PASSWORD = "password";
 
 	public static final String PARAM_FOR_USER = "for_user";
-	
+
 	public static final String PARAM_ENTITY_CONFIG_REPO_LOADER = "entity_config_repo_loader";
 
 	private static final Logger LOGGER = LoggerFactory.getLogger(ODSContextFactory.class);
@@ -92,7 +92,7 @@
 	 * Listed names are available via public fields of this class.
 	 */
 	@Override
-	public ApplicationContext connect(Map<String, String> parameters) throws ConnectionException {
+	public ApplicationContext connect(String sourceName, Map<String, String> parameters) throws ConnectionException {
 		AoSession aoSession = null;
 		try (ServiceLocator serviceLocator = new ServiceLocator(orb, getParameter(parameters, PARAM_NAMESERVICE))) {
 			String nameOfService = getParameter(parameters, PARAM_SERVICENAME).replace(".ASAM-ODS", "");
@@ -119,10 +119,10 @@
 
 			CORBAFileServerIF fileServer = serviceLocator.resolveFileServer(nameOfService);
 
-			EntityConfigRepositoryLoader repositoryLoader =
-					getEntityConfigRepositoryLoader(parametersWithoutPassword.get(PARAM_ENTITY_CONFIG_REPO_LOADER));
+			EntityConfigRepositoryLoader repositoryLoader = getEntityConfigRepositoryLoader(
+					parametersWithoutPassword.get(PARAM_ENTITY_CONFIG_REPO_LOADER));
 
-			return new ODSContext(orb, aoSession, fileServer, parametersWithoutPassword, repositoryLoader);
+			return new ODSContext(sourceName, orb, aoSession, fileServer, parametersWithoutPassword, repositoryLoader);
 		} catch (AoException e) {
 			closeSession(aoSession);
 			throw new ConnectionException("Unable to connect to ODS server due to: " + e.reason, e);
diff --git a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
index 7f12b37..fc839e1 100644
--- a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
+++ b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
@@ -30,6 +30,7 @@
 import org.eclipse.mdm.api.base.model.Environment;
 import org.eclipse.mdm.api.base.model.ExtCompFile;
 import org.eclipse.mdm.api.base.model.ExternalComponent;
+import org.eclipse.mdm.api.base.model.LocalColumn;
 import org.eclipse.mdm.api.base.model.MDMLocalization;
 import org.eclipse.mdm.api.base.model.MeaResultFile;
 import org.eclipse.mdm.api.base.model.Measurement;
@@ -133,6 +134,10 @@
 		channelConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Unit.class)));
 		channelConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Quantity.class)));
 		entityConfigRepository.register(channelConfig);
+		
+		// LocalColumn
+		EntityConfig<LocalColumn> localColumnConfig = create(modelManager, new Key<>(LocalColumn.class), "LocalColumn", false);
+		entityConfigRepository.register(localColumnConfig);
 
 		// ValueList
 		EntityConfig<ValueListValue> valueListValueConfig = create(modelManager, new Key<>(ValueListValue.class),
diff --git a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java
index d1c9084..b437ed7 100644
--- a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java
+++ b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java
@@ -95,8 +95,8 @@
 	 * @param aoSession The underlying ODS session.
 	 * @throws AoException Thrown on errors.
 	 */
-	public ODSModelManager(ORB orb, AoSession aoSession) throws AoException {
-		this(orb, aoSession, new DefaultEntityConfigRepositoryLoader());
+	public ODSModelManager(String sourceName, ORB orb, AoSession aoSession) throws AoException {
+		this(sourceName, orb, aoSession, new DefaultEntityConfigRepositoryLoader());
 	}
 
 	/**
@@ -106,11 +106,11 @@
 	 * @param aoSession The underlying ODS session.
 	 * @throws AoException Thrown on errors.
 	 */
-	public ODSModelManager(ORB orb, AoSession aoSession, EntityConfigRepositoryLoader entityConfigRepositoryLoader)
-			throws AoException {
+	public ODSModelManager(String sourceName, ORB orb, AoSession aoSession,
+			EntityConfigRepositoryLoader entityConfigRepositoryLoader) throws AoException {
 		this.aoSession = aoSession;
 		this.orb = orb;
-		sourceName = aoSession.getName();
+		this.sourceName = sourceName;
 		applElemAccess = aoSession.getApplElemAccess();
 		this.entityConfigRepositoryLoader = entityConfigRepositoryLoader;
 
diff --git a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/LocalColumnSearchQuery.java b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/LocalColumnSearchQuery.java
new file mode 100644
index 0000000..64298c9
--- /dev/null
+++ b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/LocalColumnSearchQuery.java
@@ -0,0 +1,61 @@
+/********************************************************************************
+ * Copyright (c) 2015-2020 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.odsadapter.search;
+
+import org.eclipse.mdm.api.base.adapter.EntityType;
+import org.eclipse.mdm.api.base.model.Channel;
+import org.eclipse.mdm.api.base.model.ChannelGroup;
+import org.eclipse.mdm.api.base.model.LocalColumn;
+import org.eclipse.mdm.api.base.model.Measurement;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
+import org.eclipse.mdm.api.base.query.QueryService;
+import org.eclipse.mdm.api.base.search.ContextState;
+import org.eclipse.mdm.api.base.search.SearchQuery;
+import org.eclipse.mdm.api.dflt.model.Pool;
+import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
+import org.eclipse.mdm.api.odsadapter.search.JoinTree.JoinConfig;
+
+/**
+ * {@link SearchQuery} implementation for {@link LocalColumn} as the source entity type.
+ *
+ * @author Martin Fleischer, Peak Solution GmbH
+ */
+final class LocalColumnSearchQuery extends BaseEntitySearchQuery {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param modelManager Used to load {@link EntityType}s.
+	 * @param contextState The {@link ContextState}.
+	 */
+	LocalColumnSearchQuery(ODSModelManager modelManager, QueryService queryService, ContextState contextState) {
+		super(modelManager, queryService, LocalColumn.class, Project.class);
+
+		// layers
+		addJoinConfig(JoinConfig.up(Pool.class, Project.class));
+		addJoinConfig(JoinConfig.up(Test.class, Pool.class));
+		addJoinConfig(JoinConfig.up(TestStep.class, Test.class));
+		addJoinConfig(JoinConfig.up(Measurement.class, TestStep.class));
+		addJoinConfig(JoinConfig.up(ChannelGroup.class, Measurement.class));
+		addJoinConfig(JoinConfig.up(LocalColumn.class, ChannelGroup.class));
+		addJoinConfig(JoinConfig.down(Measurement.class, Channel.class));
+
+		// context
+		addJoinConfig(contextState);
+	}
+
+}
diff --git a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchService.java b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchService.java
index 1b00a2d..222d1b9 100644
--- a/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchService.java
+++ b/api/odsadapter/src/main/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchService.java
@@ -27,6 +27,7 @@
 import org.eclipse.mdm.api.base.model.ChannelGroup;
 import org.eclipse.mdm.api.base.model.Entity;
 import org.eclipse.mdm.api.base.model.Environment;
+import org.eclipse.mdm.api.base.model.LocalColumn;
 import org.eclipse.mdm.api.base.model.Measurement;
 import org.eclipse.mdm.api.base.model.Parameter;
 import org.eclipse.mdm.api.base.model.ParameterSet;
@@ -103,6 +104,8 @@
 				c -> new ChannelGroupSearchQuery(context.getODSModelManager(), queryService, c));
 		registerMergedSearchQuery(Channel.class,
 				c -> new ChannelSearchQuery(context.getODSModelManager(), queryService, c));
+		registerMergedSearchQuery(LocalColumn.class,
+				c -> new LocalColumnSearchQuery(context.getODSModelManager(), queryService, c));
 		registerMergedSearchQuery(ParameterSet.class,
 				c -> new ParameterSetSearchQuery(context.getODSModelManager(), queryService, c));
 		registerMergedSearchQuery(Parameter.class,
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/AggregationTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/AggregationTest.java
index 82a7b3f..f563901 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/AggregationTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/AggregationTest.java
@@ -82,7 +82,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 	}
 
 	@AfterClass
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/JoinTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/JoinTest.java
index 108d4c0..90bba19 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/JoinTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/JoinTest.java
@@ -87,7 +87,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 	}
 
 	@AfterClass
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterExtCompTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterExtCompTest.java
index 8effd78..9312970 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterExtCompTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterExtCompTest.java
@@ -144,7 +144,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 		entityManager = context.getEntityManager()
 				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
 		entityFactory = context.getEntityFactory()
@@ -401,10 +401,10 @@
 			wrb = WriteRequest.create(channelGroup, channels.get(3), AxisType.Y_AXIS);
 			writeRequests.add(wrb.explicitExternal().externalComponents(ScalarType.BYTE, Lists.newArrayList(
 					(new ExternalComponentData()).setTypeSpecification(TypeSpecification.BYTE).setLength(5)
-							.setStartOffset(0).setBlocksize(5).setValuesPerBlock(5).setValueOffset(0)
+							.setStartOffset(0L).setBlocksize(5).setValuesPerBlock(5).setValueOffset(0)
 							.setFileLink(fileLinkValues1).setFlagsStartOffset(0L).setFlagsFileLink(fileLinkFlags1),
 					(new ExternalComponentData()).setTypeSpecification(TypeSpecification.BYTE).setLength(5)
-							.setStartOffset(0).setBlocksize(5).setValuesPerBlock(5).setValueOffset(0)
+							.setStartOffset(0L).setBlocksize(5).setValuesPerBlock(5).setValueOffset(0)
 							.setFileLink(fileLinkValues2).setFlagsStartOffset(0L).setFlagsFileLink(fileLinkFlags2)))
 					.build());
 
@@ -413,10 +413,10 @@
 					.add(wrb.explicitExternal()
 							.externalComponents(ScalarType.INTEGER, Lists.newArrayList(
 									(new ExternalComponentData()).setTypeSpecification(TypeSpecification.INTEGER)
-											.setLength(5).setStartOffset(5).setBlocksize(20).setValuesPerBlock(5)
+											.setLength(5).setStartOffset(5L).setBlocksize(20).setValuesPerBlock(5)
 											.setValueOffset(0).setFileLink(fileLinkValues1),
 									(new ExternalComponentData()).setTypeSpecification(TypeSpecification.INTEGER)
-											.setLength(5).setStartOffset(5).setBlocksize(20).setValuesPerBlock(5)
+											.setLength(5).setStartOffset(5L).setBlocksize(20).setValuesPerBlock(5)
 											.setValueOffset(0).setFileLink(fileLinkValues2)))
 							.build());
 		} catch (IOException exc) {
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterTest.java
index 59cbce6..87264ac 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSAdapterTest.java
@@ -132,7 +132,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 		entityManager = context.getEntityManager()
 				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
 		entityFactory = context.getEntityFactory()
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSContextTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSContextTest.java
index 778051f..5a47f53 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSContextTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSContextTest.java
@@ -89,7 +89,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 		entityManager = context.getEntityManager()
 				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
 	}
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java
index b810477..a5dd7e4 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java
@@ -89,7 +89,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 		em = context.getEntityManager().orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
 		entityFactory = context.getEntityFactory()
 				.orElseThrow(() -> new IllegalStateException("Entity manager factory not available."));
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/RelationTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/RelationTest.java
index 2d72169..558daff 100755
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/RelationTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/RelationTest.java
@@ -97,7 +97,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 		entityManager = context.getEntityManager()
 				.orElseThrow(() -> new ServiceNotProvidedException(EntityManager.class));
 		modelManager = context.getModelManager().orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationTest.java
index e86d55e..de0823a 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationTest.java
@@ -117,7 +117,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect("MDMNVH", connectionParameters);
 
 		Map<String, String> notificationParameters = new HashMap<>();
 		notificationParameters.put(ODSNotificationServiceFactory.PARAM_SERVER_TYPE,
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceIT.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceIT.java
index ae44358..b0e698a 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceIT.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceIT.java
@@ -106,7 +106,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 		modelManager = context.getModelManager().orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
 		searchService = context.getSearchService()
 				.orElseThrow(() -> new IllegalStateException("Search service not available."));
diff --git a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceStatusTest.java b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceStatusTest.java
index d0cfc38..c9f461c 100644
--- a/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceStatusTest.java
+++ b/api/odsadapter/src/test/java/org/eclipse/mdm/api/odsadapter/search/ODSSearchServiceStatusTest.java
@@ -98,7 +98,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 		modelManager = context.getModelManager().orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
 		searchService = context.getSearchService()
 				.orElseThrow(() -> new IllegalStateException("Search service not available."));
@@ -138,7 +138,7 @@
 		ODSSearchService service = Mockito.spy((ODSSearchService) searchService);
 
 		EntityType test = modelManager.getEntityType(Test.class);
-		
+
 		Filter filter = Filter.and().add(ComparisonOperator.EQUAL.create(test.getAttribute("Status"), "Active"));
 		List<Attribute> attributesList = getAttributeListFromFilter(filter);
 
diff --git a/doc/GettingStartedGuide/src/070_installApplication.adoc b/doc/GettingStartedGuide/src/070_installApplication.adoc
index c006c1e..db2f685 100644
--- a/doc/GettingStartedGuide/src/070_installApplication.adoc
+++ b/doc/GettingStartedGuide/src/070_installApplication.adoc
@@ -38,6 +38,7 @@
 `org.eclipse.mdm/nucleus/connector/src/main/configuration/service.xml` 
 
 * configure the data sources, for ODS Servers look into your ODS Server log file to determine the corba URL
+* the sourceName is the name of the datasource within openMDM 5. It must be unique among all services and should only contain alphanumeric characters and underscores.
 * To use the freetext search configure for each datasource separately:
 ** specific parameters for the NotificationService and the freetext search
 ** set the freetext.active parameter to true (Example2)
@@ -49,12 +50,12 @@
 
  <services>
  <!-- Example1: ODS Server without freetext.* parameters -> freetext search is not active -->
- <service entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
+ <service sourceName="YOUR_SERVICE1" entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
 	    <param name="nameservice">corbaloc::1.2@YOUR_HOST1:2809/NameService</param>
 	    <param name="servicename">YOUR_SERVICE1.ASAM-ODS</param>
  </service>
  <!-- Example2: Peak ODS-Sever with active freetext search -->
- <service entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
+ <service sourceName="YOUR_SERVICE2" entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
     	<param name="nameservice">corbaloc::1.2@YOUR_HOST2:2809/NameService</param>
 	    <param name="servicename">YOUR_SERVICE2.ASAM-ODS</param>
 	    <!--The indexing requires a user to get the DataItems from the ODS Server. Those are the credentials for the user -->
@@ -66,7 +67,7 @@
  </service>
 
  <!-- Example3:  Avalon ODS-Sever -> freetext search is not active-->
- <service entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
+ <service sourceName="YOUR_SERVICE3" entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
 	    <param name="nameservice">corbaloc::1.2@YOUR_HOST3:2809/NameService</param>
 	    <param name="servicename">YOUR_SERVICE3.ASAM-ODS</param>
 	    <!--The indexing requires a user to get the DataItems from the ODS Server. Those are the credentials for the user -->
diff --git a/doc/UserGuide/src/200_GeneralFunctions.adoc b/doc/UserGuide/src/200_GeneralFunctions.adoc
index 2ca1f4f..2b81427 100644
--- a/doc/UserGuide/src/200_GeneralFunctions.adoc
+++ b/doc/UserGuide/src/200_GeneralFunctions.adoc
@@ -54,6 +54,12 @@
 
 Logging out will end all of your ASAM ODS user sessions / connections.
 
+=== Datasources
+
+Select one or more datasources to work with. 
+Furthermore you can specify to which datasources the client should connect to after login, by clicking the `Default datasources` button.
+
+
 === Language
 
 Select a language for text and labels. Currently available languages are English and German (Deutsch).
diff --git a/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/boundary/ExportService.java b/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/boundary/ExportService.java
index 77ff416..ab33d87 100644
--- a/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/boundary/ExportService.java
+++ b/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/boundary/ExportService.java
@@ -183,7 +183,7 @@
 					.asSubclass(ApplicationContextFactory.class);
 
 			ApplicationContextFactory contextFactory = contextFactoryClass.newInstance();
-			return contextFactory.connect(parameters);
+			return contextFactory.connect("ATFX", parameters);
 		} catch (Exception e) {
 			throw new ConnectionException(
 					"failed to initialize entity manager using factory '" + contextFactoryClassname + "'", e);
diff --git a/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/boundary/ImportService.java b/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/boundary/ImportService.java
index 4e488bf..e53e11c 100644
--- a/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/boundary/ImportService.java
+++ b/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/boundary/ImportService.java
@@ -157,7 +157,7 @@
 					.asSubclass(ApplicationContextFactory.class);
 
 			ApplicationContextFactory contextFactory = contextFactoryClass.newInstance();
-			return contextFactory.connect(parameters);
+			return contextFactory.connect("ATFX", parameters);
 		} catch (Exception e) {
 			throw new ConnectionException(
 					"failed to initialize entity manager using factory '" + contextFactoryClassname + "'", e);
diff --git a/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/control/ImportTask.java b/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/control/ImportTask.java
index ef86863..c85c1d9 100644
--- a/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/control/ImportTask.java
+++ b/nucleus/apicopy/src/main/java/org/eclipse/mdm/apicopy/control/ImportTask.java
@@ -897,11 +897,16 @@
 
 						List<Unit> sourceUnits = entityManagerDst.loadAll(Unit.class, escapeWildcards(sourceUnitName));
 
-						if (sourceUnits == null || sourceUnits.isEmpty()) {
+						if (!sourceUnitName.isEmpty() && (sourceUnits == null || sourceUnits.isEmpty())) {
 							throw new ApiCopyException(
 									String.format("Unit with name '%s' not found in target!", sourceUnitName));
 						}
 
+						Unit sourceUnit = null;
+
+						if (sourceUnits != null && !sourceUnits.isEmpty()) {
+							sourceUnit = sourceUnits.get(0);
+						}
 						if (append) {
 
 							Channel channelSrc = mapChannelsSrc.get(channelDst.getName());
@@ -924,9 +929,8 @@
 
 						}
 
-						listWriteRequests.add(createWriteRequest(entityManagerSrc, channelGroupDst, channelDst, measuredValues,
-								sourceUnits.get(0), mapChannelsSrc.get(channelDst.getName()), transaction));
-
+						listWriteRequests.add(createWriteRequest(channelGroupDst, channelDst, measuredValues,
+								sourceUnit, mapChannelsSrc.get(channelDst.getName())));
 					}
 
 				}
@@ -1023,23 +1027,25 @@
 
 		LOG.trace("Preloading Units.");
 
-		// Load quantity names in dst by name
-		Set<String> unitNames = srcChannels.stream().map(c -> c.getUnit().getName())
+		// Load unit names in dst by name
+		Set<String> unitNames = srcChannels.stream().filter(c -> c.getUnit() != null).map(c -> c.getUnit().getName())
 				.map(n -> unitMapping.getOrDefault(n, n)).collect(Collectors.toSet());
 
 		List<Unit> results = entityManagerDst.loadAll(Unit.class, unitNames);
 
-		Map<String, Unit> map = new HashMap<>();
+		Map<String, Unit> mapping = new HashMap<>();
 		for (Unit u : results) {
-			map.put(u.getName(), u);
-		}
-		// Add units for aliased unit names
-		for (Map.Entry<String, String> entry : unitMapping.entrySet()) {
-			map.put(entry.getKey(), map.get(entry.getValue()));
-			LOG.debug("Mapping {} to {}", entry.getKey(), map.get(entry.getKey()));
+			mapping.put(u.getName(), u);
 		}
 
-		return map;
+		// Add units for aliased unit names
+		for (Map.Entry<String, String> entry : unitMapping.entrySet()) {
+			Unit mappedUnit = mapping.get(entry.getValue());
+			mapping.put(entry.getKey(), mappedUnit);
+			LOG.debug("Mapping {} to {}", entry.getKey(), mappedUnit);
+		}
+
+		return mapping;
 	}
 
 	private Optional<ChannelGroup> fetchOneChannelGroup(EntityManager entityManager, ChannelGroup channelGroupSrc) {
diff --git a/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ExportTaskTest.java b/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ExportTaskTest.java
index fcb2796..98e6379 100644
--- a/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ExportTaskTest.java
+++ b/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ExportTaskTest.java
@@ -30,7 +30,6 @@
 import org.eclipse.mdm.api.dflt.ApplicationContext;
 import org.eclipse.mdm.api.dflt.model.Project;
 import org.eclipse.mdm.api.odsadapter.ODSContextFactory;
-import org.eclipse.mdm.apicopy.control.ExportTask;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -87,7 +86,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		contextSrc = new ODSContextFactory().connect(connectionParameters);
+		contextSrc = new ODSContextFactory().connect(serviceName, connectionParameters);
 
 		// target context
 		f = tmpFolder.newFile("open.atfx");
@@ -96,7 +95,7 @@
 		Map<String, String> map = ImmutableMap.of("atfxfile", f.getAbsolutePath(), "freetext.active", "false",
 				"includeCatalog", "true");
 
-		contextDst = new ATFXContextFactory().connect(map);
+		contextDst = new ATFXContextFactory().connect("ATFX", map);
 	}
 
 	@AfterClass
@@ -112,7 +111,7 @@
 		contextDst.close();
 
 		Map<String, String> map = ImmutableMap.of("atfxfile", f.getAbsolutePath(), "freetext.active", "false");
-		contextDst = new ATFXContextFactory().connect(map);
+		contextDst = new ATFXContextFactory().connect("ATFX", map);
 
 		task = new ExportTask(contextSrc, contextDst);
 		task.copy(Arrays.asList(contextSrc.getEntityManager().get().load(Project.class, "1")));
diff --git a/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ImportExtCompTaskTest.java b/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ImportExtCompTaskTest.java
index 743a309..d1803d4 100644
--- a/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ImportExtCompTaskTest.java
+++ b/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ImportExtCompTaskTest.java
@@ -9,7 +9,7 @@
  * http://www.eclipse.org/legal/epl-2.0.

  *

  * SPDX-License-Identifier: EPL-2.0

- *******************************************************************************/
+ *******************************************************************************/

 package org.eclipse.mdm.apicopy.control;

 

 import static org.assertj.core.api.Assertions.assertThat;

@@ -99,14 +99,14 @@
 		connectionParameters.put(PARAM_USER, USER);

 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);

 

-		contextDst = new ODSContextFactory().connect(connectionParameters);

+		contextDst = new ODSContextFactory().connect(serviceName, connectionParameters);

 

 		// source context

 		File f = new File(ATFX_FILE);

 

 		Map<String, String> map = ImmutableMap.of("atfxfile", f.getAbsolutePath(), "freetext.active", "false");

 

-		contextSrc = new ATFXContextFactory().connect(map);

+		contextSrc = new ATFXContextFactory().connect("ATFX", map);

 

 	}

 

@@ -156,7 +156,7 @@
 		Map<String, String> map = ImmutableMap.of("atfxfile", f.getAbsolutePath(), "freetext.active", "false",

 				"includeCatalog", "true");

 

-		ApplicationContext contextExp = new ATFXContextFactory().connect(map);

+		ApplicationContext contextExp = new ATFXContextFactory().connect("ATFX", map);

 

 		/*

 		 * Copy the catalog (which involves creating the ContextComponts).

@@ -171,7 +171,7 @@
 		 * support co-sessions. Thus we have to create a new session by creating a new

 		 * application context.

 		 */

-		contextExp = new ATFXContextFactory().connect(map);

+		contextExp = new ATFXContextFactory().connect("ATFX", map);

 		task = new ExportTask(contextDst, contextExp);

 		task.copy(contextDst.getEntityManager().get().loadAll(TestStep.class, "ImportTaskTest"));

 		contextExp.close();

diff --git a/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ImportTaskTest.java b/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ImportTaskTest.java
index b16657f..11b6138 100644
--- a/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ImportTaskTest.java
+++ b/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/ImportTaskTest.java
@@ -9,7 +9,7 @@
  * http://www.eclipse.org/legal/epl-2.0.

  *

  * SPDX-License-Identifier: EPL-2.0

- *******************************************************************************/
+ *******************************************************************************/

 package org.eclipse.mdm.apicopy.control;

 

 import static org.eclipse.mdm.api.odsadapter.ODSContextFactory.PARAM_NAMESERVICE;

@@ -77,14 +77,14 @@
 		connectionParameters.put(PARAM_USER, USER);

 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);

 

-		contextDst = new ODSContextFactory().connect(connectionParameters);

+		contextDst = new ODSContextFactory().connect(serviceName, connectionParameters);

 

 		// source context

 		File f = new File(ATFX_FILE);

 

 		Map<String, String> map = ImmutableMap.of("atfxfile", f.getAbsolutePath(), "freetext.active", "false");

 

-		contextSrc = new ATFXContextFactory().connect(map);

+		contextSrc = new ATFXContextFactory().connect("ATFX", map);

 	}

 

 	@AfterClass

diff --git a/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/RoundTripTest.java b/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/RoundTripTest.java
index 5e6eb3c..51e293e 100644
--- a/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/RoundTripTest.java
+++ b/nucleus/apicopy/src/test/java/org/eclipse/mdm/apicopy/control/RoundTripTest.java
@@ -93,7 +93,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		contextODSServer = new ODSContextFactory().connect(connectionParameters);
+		contextODSServer = new ODSContextFactory().connect(serviceName, connectionParameters);
 	}
 
 	@AfterClass
@@ -121,12 +121,12 @@
 				.put("freetext.active", "false").put("includeCatalog", "true").put("WRITE_EXTERNALCOMPONENTS", "true")
 				.put("write_mode", "file").build();
 
-		try (ApplicationContext contextDst = new ATFXContextFactory().connect(map)) {
+		try (ApplicationContext contextDst = new ATFXContextFactory().connect("ATFX", map)) {
 			ExportTask task = new ExportTask(contextODSServer, contextDst);
 			task.copyCatalog();
 		}
 
-		try (ApplicationContext contextDst = new ATFXContextFactory().connect(map)) {
+		try (ApplicationContext contextDst = new ATFXContextFactory().connect("ATFX", map)) {
 			ExportTask task = new ExportTask(contextODSServer, contextDst);
 			task.copy(Arrays.asList(
 					contextODSServer.getEntityManager().get().load(org.eclipse.mdm.api.base.model.Test.class, "2017")));
@@ -193,7 +193,7 @@
 				.put("includeCatalog", "true").put("WRITE_EXTERNALCOMPONENTS", "true").put("write_mode", "file")
 				.build();
 
-		try (ApplicationContext contextImportSrc = new ATFXContextFactory().connect(mapContextImportSrc)) {
+		try (ApplicationContext contextImportSrc = new ATFXContextFactory().connect("ATFX", mapContextImportSrc)) {
 
 			ImportTask importTask = new ImportTask(contextImportSrc, contextODSServer, new DefaultTemplateManager());
 
diff --git a/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/boundary/DatasourceResource.java b/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/boundary/DatasourceResource.java
new file mode 100644
index 0000000..b135466
--- /dev/null
+++ b/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/boundary/DatasourceResource.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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.datasource.boundary;
+
+import static org.eclipse.mdm.businessobjects.boundary.ResourceConstants.REQUESTPARAM_SOURCENAME;
+
+import java.util.List;
+
+import javax.ejb.EJB;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.eclipse.mdm.api.base.model.Environment;
+import org.eclipse.mdm.businessobjects.entity.MDMEntityResponse;
+import org.eclipse.mdm.businessobjects.utils.ServiceUtils;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+/**
+ * {@link Environment} resource
+ * 
+ * @author Joachim Zeyn, Peak Solution GmbH
+ *
+ */
+@Tag(name = "Datasource")
+@Path("/datasources")
+public class DatasourceResource {
+
+	@EJB
+	private DatasourceService datasourceService;
+
+	@GET
+	@Operation(summary = "Get the available datasources", description = "Get the available services/datasources", responses = {
+			@ApiResponse(description = "The datasources", content = @Content(schema = @Schema(implementation = MDMEntityResponse.class))),
+			@ApiResponse(responseCode = "500", description = "Error") })
+	@Produces(MediaType.APPLICATION_JSON)
+	public Response getDatasources() {
+		return ServiceUtils.toResponse(datasourceService.readServiceNames(), Status.OK);
+	}
+
+	@PUT
+	@Operation(summary = "Set the selected datasources", description = "Set the active services/datasources", responses = {
+			@ApiResponse(description = "List of service names currently active.", content = @Content(schema = @Schema(implementation = List.class))),
+			@ApiResponse(responseCode = "500", description = "Error") })
+	public Response setDatasources(
+			@Parameter(description = "Names of the MDM datasources", required = true) @PathParam(REQUESTPARAM_SOURCENAME) String sourceName,
+			List<String> activeServices) {
+
+		this.datasourceService.setActiveServices(activeServices);
+		return ServiceUtils.toResponse(datasourceService.readServiceNames(), Status.OK);
+	}
+}
diff --git a/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/boundary/DatasourceService.java b/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/boundary/DatasourceService.java
new file mode 100644
index 0000000..b815ea1
--- /dev/null
+++ b/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/boundary/DatasourceService.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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.datasource.boundary;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.ejb.Stateless;
+import javax.inject.Inject;
+
+import org.eclipse.mdm.connector.boundary.ConnectorService;
+import org.eclipse.mdm.connector.control.ServiceConfigurationActivity;
+
+/**
+ * Bean implementation with available Services
+ * 
+ * @author Joachim Zeyn, Peak Solution GmbH
+ *
+ */
+@Stateless
+public class DatasourceService {
+
+	@Inject
+	private ConnectorService connectorService;
+
+	@Inject
+	ServiceConfigurationActivity serviceConfigurationActivity;
+
+	/**
+	 * Default no-arg constructor for EJB
+	 */
+	public DatasourceService() {
+	}
+
+	public List<String> readServiceNames() {
+		return serviceConfigurationActivity.readServiceConfigurations().stream().map(s -> s.getName())
+				.collect(Collectors.toList());
+	}
+
+	public void setActiveServices(List<String> activeServices) {
+		this.connectorService.setActiveSourceNames(activeServices);
+	}
+}
diff --git a/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/entity/AvailableDatasourceResponse.java b/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/entity/AvailableDatasourceResponse.java
new file mode 100644
index 0000000..eda34da
--- /dev/null
+++ b/nucleus/businessobjects/src/main/java/org/eclipse/mdm/datasource/entity/AvailableDatasourceResponse.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2021 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
+ *******************************************************************************/
+
+/**
+ * SearchDefinitionResponse (Container for {@link SearchAttribute}s)
+ * 
+ * @author Sebastian Dirsch, Gigatronik Ingolstadt GmbH
+ *
+ */
+package org.eclipse.mdm.datasource.entity;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.eclipse.mdm.connector.entity.ServiceConfiguration;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AvailableDatasourceResponse {
+
+
+	/** transferable data content */
+	private List<ServiceConfiguration> data;
+
+	/**
+	 * Constructor
+	 * 
+	 * @param searchAttributes list of {@link SearchAttribute}s to transfer
+	 */
+	public AvailableDatasourceResponse(List<ServiceConfiguration> serviceConfiguration) {
+		data = new ArrayList<>(serviceConfiguration);
+	}
+
+	/**
+	 * Constructor
+	 */
+	public AvailableDatasourceResponse() {
+		data = new ArrayList<>();
+	}
+
+	public List<ServiceConfiguration> getData() {
+		return Collections.unmodifiableList(this.data);
+	}
+}
diff --git a/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/boundary/NodeProviderServiceTest.java b/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/boundary/NodeProviderServiceTest.java
index dc1254f..cac62e0 100644
--- a/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/boundary/NodeProviderServiceTest.java
+++ b/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/boundary/NodeProviderServiceTest.java
@@ -111,7 +111,7 @@
 		connectionParameters.put(PARAM_USER, USER);

 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);

 

-		context = new ODSContextFactory().connect(connectionParameters);

+		context = new ODSContextFactory().connect(serviceName, connectionParameters);

 

 		Map<String, String> connectionParameters2 = new HashMap<>();

 		connectionParameters2.put(PARAM_NAMESERVICE, String.format(NAME_SERVICE, nameServiceHost, 2807));

@@ -119,7 +119,7 @@
 		connectionParameters2.put(PARAM_USER, USER);

 		connectionParameters2.put(PARAM_PASSWORD, PASSWORD);

 

-		context2 = new ODSContextFactory().connect(connectionParameters2);

+		context2 = new ODSContextFactory().connect("CRASHDEMO", connectionParameters2);

 	}

 

 	@AfterClass

diff --git a/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/control/GenericNodeProviderTest.java b/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/control/GenericNodeProviderTest.java
index d480d19..b1a69e9 100644
--- a/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/control/GenericNodeProviderTest.java
+++ b/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/control/GenericNodeProviderTest.java
@@ -97,7 +97,7 @@
 		connectionParameters.put(PARAM_USER, USER);

 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);

 

-		context = new ODSContextFactory().connect(connectionParameters);

+		context = new ODSContextFactory().connect(serviceName, connectionParameters);

 	}

 

 	@AfterClass

@@ -122,7 +122,7 @@
 		ConnectorService connectorService = Mockito.mock(ConnectorService.class);

 		Mockito.when(connectorService.getContexts()).thenReturn(Arrays.asList(context));

 		Mockito.when(connectorService.getContextByName(any())).thenReturn(context);

-		

+

 		MDMExpressionLanguageService elService = Mockito.mock(MDMExpressionLanguageService.class);

 

 		return new GenericNodeProvider(connectorService, npr, elService);

@@ -336,28 +336,34 @@
 		env.getOrderAttributes().addAll(env.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

 

 		NodeLevel project = new NodeLevel(modelManager.getEntityType(Project.class));

-		project.getOrderAttributes().addAll(project.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

+		project.getOrderAttributes()

+				.addAll(project.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

 

 		EntityType vehicle = modelManager.getEntityType("vehicle");

 		NodeLevel vehicleModel = new NodeLevel(vehicle, vehicle.getAttribute("model"), vehicle.getAttribute("model"));

 		vehicleModel.setVirtual(true);

 		vehicleModel.setContextState(contextState);

-		vehicleModel.getOrderAttributes().addAll(vehicleModel.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

+		vehicleModel.getOrderAttributes()

+				.addAll(vehicleModel.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

 

 		NodeLevel test = new NodeLevel(modelManager.getEntityType(org.eclipse.mdm.api.base.model.Test.class));

 		test.getOrderAttributes().addAll(test.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

 

 		NodeLevel testStep = new NodeLevel(modelManager.getEntityType(TestStep.class));

-		testStep.getOrderAttributes().addAll(testStep.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

+		testStep.getOrderAttributes()

+				.addAll(testStep.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

 

 		NodeLevel measurement = new NodeLevel(modelManager.getEntityType(Measurement.class));

-		measurement.getOrderAttributes().addAll(measurement.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

+		measurement.getOrderAttributes()

+				.addAll(measurement.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

 

 		NodeLevel channelGroup = new NodeLevel(modelManager.getEntityType(ChannelGroup.class));

-		channelGroup.getOrderAttributes().addAll(channelGroup.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

+		channelGroup.getOrderAttributes()

+				.addAll(channelGroup.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

 

 		NodeLevel channel = new NodeLevel(modelManager.getEntityType(Channel.class));

-		channel.getOrderAttributes().addAll(channel.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

+		channel.getOrderAttributes()

+				.addAll(channel.getLabelAttributes().stream().map(SortAttribute::new).collect(toList()));

 

 		env.setChild(project);

 		project.setChild(vehicleModel);

diff --git a/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/entity/NodeProviderRootTest.java b/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/entity/NodeProviderRootTest.java
index 57ddc01..8cc430e 100644
--- a/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/entity/NodeProviderRootTest.java
+++ b/nucleus/businessobjects/src/test/java/org/eclipse/mdm/nodeprovider/entity/NodeProviderRootTest.java
@@ -45,7 +45,7 @@
 		Map<String, String> map = ImmutableMap.of("atfxfile", "../../api/atfxadapter/src/test/resources/Right_Acc.atfx",

 				"freetext.active", "false");

 

-		context = new ATFXContextFactory().connect(map);

+		context = new ATFXContextFactory().connect("ATFX", map);

 	}

 

 	@After

diff --git a/nucleus/businessobjects/src/test/java/org/eclipse/mdm/query/boundary/QueryTest.java b/nucleus/businessobjects/src/test/java/org/eclipse/mdm/query/boundary/QueryTest.java
index 0a63b84..9d751a7 100644
--- a/nucleus/businessobjects/src/test/java/org/eclipse/mdm/query/boundary/QueryTest.java
+++ b/nucleus/businessobjects/src/test/java/org/eclipse/mdm/query/boundary/QueryTest.java
@@ -92,7 +92,7 @@
 		connectionParameters.put(PARAM_USER, USER);
 		connectionParameters.put(PARAM_PASSWORD, PASSWORD);
 
-		context = new ODSContextFactory().connect(connectionParameters);
+		context = new ODSContextFactory().connect(serviceName, connectionParameters);
 		modelManager = context.getModelManager().orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
 		queryService = context.getQueryService().orElseThrow(() -> new ServiceNotProvidedException(QueryService.class));
 	}
diff --git a/nucleus/connector/src/main/configuration/service.xml b/nucleus/connector/src/main/configuration/service.xml
index a63cb2e..4066f21 100644
--- a/nucleus/connector/src/main/configuration/service.xml
+++ b/nucleus/connector/src/main/configuration/service.xml
@@ -12,11 +12,12 @@
  -->
 
 <services>
-	<service entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
+
+	<service sourceName="YOUR_SERVICE1" entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
 		<param name="nameservice">corbaloc::1.2@YOUR_HOST1:2809/NameService</param>
 		<param name="servicename">YOUR_SERVICE1.ASAM-ODS</param>
 	</service>
-	<service entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
+	<service sourceName="YOUR_SERVICE2" entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
 		<param name="nameservice">corbaloc::1.2@YOUR_HOST2:2809/NameService</param>
 		<param name="servicename">YOUR_SERVICE2.ASAM-ODS</param>
 		
@@ -30,7 +31,7 @@
 		<param name="freetext.notificationType">peak</param>
 		<param name="freetext.notificationUrl">http://YOUR_HOST2:8089/api</param>
 	</service>
-	<service entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
+	<service sourceName="YOUR_SERVICE3" entityManagerFactoryClass="org.eclipse.mdm.api.odsadapter.ODSContextFactory">
 		<param name="nameservice">corbaloc::1.2@YOUR_HOST3:2809/NameService</param>
 		<param name="servicename">YOUR_SERVICE3.ASAM-ODS</param>
 		
diff --git a/nucleus/connector/src/main/java/org/eclipse/mdm/connector/boundary/ConnectorService.java b/nucleus/connector/src/main/java/org/eclipse/mdm/connector/boundary/ConnectorService.java
index dbc786a..b42651b 100644
--- a/nucleus/connector/src/main/java/org/eclipse/mdm/connector/boundary/ConnectorService.java
+++ b/nucleus/connector/src/main/java/org/eclipse/mdm/connector/boundary/ConnectorService.java
@@ -99,6 +99,49 @@
 	}
 
 	/**
+	 * Read the service configurations after bean construction
+	 */
+	@PostConstruct
+	public void init() {
+		LOG.info("Initialized connector service for user with name '" + principal.getName() + "'.");
+	}
+
+	/**
+	 * disconnect from all connected data sources This method is call from a
+	 * {@link LoginModule} at logout
+	 *
+	 * This method is call from a {@link LoginModule}
+	 *
+	 */
+	@PreDestroy
+	public void disconnect() {
+		for (ApplicationContext context : getContexts()) {
+			disconnectContext(context);
+		}
+		LOG.info("user with name '" + principal.getName() + "' has been disconnected!");
+	}
+
+	/**
+	 * @return list with names of configured source names.
+	 */
+	public List<String> getSourceNames() {
+		return serviceConfigurationActivity.readServiceConfigurations().stream().map(ServiceConfiguration::getName)
+				.collect(Collectors.toList());
+	}
+
+	/**
+	 * Disconnects all currently connected source and connects to the given list of
+	 * sources.
+	 * 
+	 * @param sourceNames list of source names to connect to.
+	 */
+	public void setActiveSourceNames(List<String> sourceNames) {
+		this.disconnect();
+		serviceConfigurationActivity.readServiceConfigurations().stream()
+				.filter(val -> sourceNames.contains(val.getName())).forEach(this::connectContexts);
+	}
+
+	/**
 	 * returns all available {@link ApplicationContext}s
 	 *
 	 * @return list of available {@link ApplicationContext}s
@@ -118,40 +161,27 @@
 			ApplicationContext context = contexts.get(name);
 
 			if (context == null) {
-				String errorMessage = "no data source with environment name '" + name + "' connected!";
-				throw new ConnectorServiceException(errorMessage);
+				// try to open context on the fly
+				ServiceConfiguration s = serviceConfigurationActivity.readServiceConfigurations().stream()
+						.filter(val -> name.contains(val.getName())).findFirst()
+						.orElseThrow(() -> new ConnectorServiceException(
+								"no data source with service name '" + name + "' configured!"));
+
+				return this.connectContexts(s).orElseThrow(
+						() -> new ConnectorServiceException("Could not connect to service name '" + name + "'."));
 			}
 
 			return context;
 		} catch (DataAccessException e) {
 			throw new ConnectorServiceException(e.getMessage(), e);
 		}
-
 	}
 
 	/**
-	 * Read the service configurations after bean construction
+	 * Connects all configured application contexts
 	 */
-	@PostConstruct
 	public void connect() {
-		System.out.println("Init ConnectorService");
-		LOG.info("connecting user with name '" + principal.getName() + "'");
-		serviceConfigurationActivity.readServiceConfigurations().stream().forEach(this::connectContexts);
-	}
-
-	/**
-	 * disconnect from all connected data sources This method is call from a
-	 * {@link LoginModule} at logout
-	 *
-	 * This method is call from a {@link LoginModule}
-	 *
-	 */
-	@PreDestroy
-	public void disconnect() {
-		for (ApplicationContext context : getContexts()) {
-			disconnectContext(context);
-		}
-		LOG.info("user with name '" + principal.getName() + "' has been disconnected!");
+		setActiveSourceNames(getSourceNames());
 	}
 
 	/**
@@ -199,11 +229,11 @@
 			}
 		}
 		ServiceConfiguration serviceConfig = serviceConfigs.remove(context);
-		
+
 		if (contexts.remove(name) != null) {
 			LOG.debug("Context '{}' removed from contexts map", name);
 		}
-		
+
 		if (serviceConfig == null) {
 			LOG.warn("Could not reconnect ApplicationContext, because service configuration is null!");
 			return Optional.empty();
@@ -234,7 +264,7 @@
 			connectionParameters.putAll(processLookups(source.getConnectionParameters()));
 			connectionParameters.put(CONNECTION_PARAM_FOR_USER, principal.getName());
 
-			ApplicationContext context = contextFactory.connect(connectionParameters);
+			ApplicationContext context = contextFactory.connect(source.getName(), connectionParameters);
 
 			serviceConfigs.put(context, source);
 			contexts.put(context.getSourceName(), context);
diff --git a/nucleus/connector/src/main/java/org/eclipse/mdm/connector/control/ServiceConfigurationActivity.java b/nucleus/connector/src/main/java/org/eclipse/mdm/connector/control/ServiceConfigurationActivity.java
index 742277c..17b3250 100644
--- a/nucleus/connector/src/main/java/org/eclipse/mdm/connector/control/ServiceConfigurationActivity.java
+++ b/nucleus/connector/src/main/java/org/eclipse/mdm/connector/control/ServiceConfigurationActivity.java
@@ -37,6 +37,8 @@
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
+import com.google.common.base.Strings;
+
 /**
  * ServiceConfigurationReader to read MDM Service configurations from a
  * service.xml file
@@ -56,6 +58,8 @@
 
 	private static final String ROOT_ELEMENT_NAME = "services";
 	private static final String SERVICE_ELEMENT_NAME = "service";
+	private static final String SERVICE_NAME_NAME = "name";
+
 	private static final String PARAM_ELEMENT_NAME = "param";
 	private static final String EMFACTORYCLASS_ATTRIBUTE_NAME = "entityManagerFactoryClass";
 	private static final String NAME_ATTRIBUTE_NAME = "name";
@@ -106,7 +110,23 @@
 				connectionParameters.put(paramName, paramValue);
 			}
 		}
-		return new ServiceConfiguration(entityManagerFactoryClass, connectionParameters);
+		String name = serviceElement.getAttribute(SERVICE_NAME_NAME);
+		if (Strings.isNullOrEmpty(name)) {
+			LOG.warn(
+					"Attribute 'sourceName' at element 'service' not found. Falling back to parameter with name 'servicename' ");
+			// fallback to servicename parameter
+			name = connectionParameters.get("servicename");
+
+			if (name != null) {
+				name = name.replace(".ASAM-ODS", "");
+			}
+
+			if (Strings.isNullOrEmpty(name)) {
+				throw new ConnectorServiceException(
+						"For one of the services in the services.xml, neither the name attribute nor servicename parameter are set. Please make sure every service as a name set.");
+			}
+		}
+		return new ServiceConfiguration(name, entityManagerFactoryClass, connectionParameters);
 	}
 
 	private static String readElementAttribute(Element element, String attrName) {
diff --git a/nucleus/connector/src/main/java/org/eclipse/mdm/connector/entity/ServiceConfiguration.java b/nucleus/connector/src/main/java/org/eclipse/mdm/connector/entity/ServiceConfiguration.java
index e76d14d..02e52c5 100644
--- a/nucleus/connector/src/main/java/org/eclipse/mdm/connector/entity/ServiceConfiguration.java
+++ b/nucleus/connector/src/main/java/org/eclipse/mdm/connector/entity/ServiceConfiguration.java
@@ -30,6 +30,11 @@
 public class ServiceConfiguration {
 
 	/**
+	 * The name of this service.
+	 */
+	private final String name;
+
+	/**
 	 * The fully qualified class name of the entity manager factory for this
 	 * backend, never null.
 	 */
@@ -46,6 +51,7 @@
 	 * parameter map is copied by this constructor and no reference to the original
 	 * is retained.
 	 * 
+	 * @param name                      the name of the service
 	 * @param entityManagerFactoryClass the fully qualified class name of the entity
 	 *                                  manager factory for this backend, must not
 	 *                                  be null
@@ -53,7 +59,8 @@
 	 *                                  this backend, or null to use an empty map
 	 *                                  instead
 	 */
-	public ServiceConfiguration(String contextFactoryClass, Map<String, String> connectionParameters) {
+	public ServiceConfiguration(String name, String contextFactoryClass, Map<String, String> connectionParameters) {
+		this.name = Objects.requireNonNull(name, "Null \"name\" argument passed to ServiceConfiguration constructor");
 		this.contextFactoryClass = Objects.requireNonNull(contextFactoryClass,
 				"Null \"contextFactoryClass\" argument passed to ServiceConfiguration constructor");
 		this.connectionParameters = (connectionParameters == null ? Collections.emptyMap()
@@ -61,6 +68,13 @@
 	}
 
 	/**
+	 * @return the name of the service
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
 	 * Returns the fully qualified class name of the entity manager factory for this
 	 * backend. The result is never null.
 	 * 
diff --git a/nucleus/connector/src/test/java/org/eclipse/mdm/connector/boundary/ConnectorServiceTest.java b/nucleus/connector/src/test/java/org/eclipse/mdm/connector/boundary/ConnectorServiceTest.java
index b89fdf5..6058cd1 100644
--- a/nucleus/connector/src/test/java/org/eclipse/mdm/connector/boundary/ConnectorServiceTest.java
+++ b/nucleus/connector/src/test/java/org/eclipse/mdm/connector/boundary/ConnectorServiceTest.java
@@ -55,6 +55,7 @@
 	public void testGetEntityManagers_happyFlow() throws Exception {
 		ConnectorService connectorService = createConnectorService(testUser);
 		connectorService.connect();
+
 		assertThat(connectorService.getContexts().size(), is(1));
 	}
 
@@ -112,8 +113,8 @@
 		SessionContext sessionContextMock = mock(SessionContext.class);
 		when(sessionContextMock.getCallerPrincipal()).thenReturn(user);
 
-		ServiceConfiguration serviceConfiguration = new ServiceConfiguration(TestContextFactory.class.getName(),
-				Collections.emptyMap());
+		ServiceConfiguration serviceConfiguration = new ServiceConfiguration(testSourceName,
+				TestContextFactory.class.getName(), Collections.emptyMap());
 
 		ConnectorService connectorService = new ConnectorService();
 
@@ -130,8 +131,9 @@
 	public static final class TestContextFactory implements ApplicationContextFactory {
 
 		@Override
-		public ApplicationContext connect(Map<String, String> connectionParameters) throws ConnectionException {
-			return createContext(testSourceName);
+		public ApplicationContext connect(String sourceName, Map<String, String> connectionParameters)
+				throws ConnectionException {
+			return createContext(sourceName);
 		}
 	}
 
diff --git a/nucleus/freetextindexer/src/test/java/org/eclipse/mdm/freetextindexer/boundary/ElasticsearchBoundaryTest.java b/nucleus/freetextindexer/src/test/java/org/eclipse/mdm/freetextindexer/boundary/ElasticsearchBoundaryTest.java
index 00e2ba8..688cbfe 100644
--- a/nucleus/freetextindexer/src/test/java/org/eclipse/mdm/freetextindexer/boundary/ElasticsearchBoundaryTest.java
+++ b/nucleus/freetextindexer/src/test/java/org/eclipse/mdm/freetextindexer/boundary/ElasticsearchBoundaryTest.java
@@ -64,7 +64,7 @@
 
 	@BeforeClass
 	public static void setup() throws ConnectionException {
-		context = new ATFXContextFactory().connect(ImmutableMap.of("atfxfile", atfxFilePath + atfxFile));
+		context = new ATFXContextFactory().connect("ATFX", ImmutableMap.of("atfxfile", atfxFilePath + atfxFile));
 		Environment env = context.getEntityManager().get().loadAll(Environment.class).get(0);
 		sourceName = env.getSourceName().toLowerCase();
 
diff --git a/nucleus/preferences/src/main/java/org/eclipse/mdm/preferences/controller/PreferenceService.java b/nucleus/preferences/src/main/java/org/eclipse/mdm/preferences/controller/PreferenceService.java
index 947f35c..1d0a0cd 100644
--- a/nucleus/preferences/src/main/java/org/eclipse/mdm/preferences/controller/PreferenceService.java
+++ b/nucleus/preferences/src/main/java/org/eclipse/mdm/preferences/controller/PreferenceService.java
@@ -59,12 +59,11 @@
 	}
 
 	/**
-	 * Constructor for unit tests
-	 * 
+	 *  
 	 * @param em             EntityManager to use
 	 * @param sessionContext sessionManager to use
 	 */
-	PreferenceService(EntityManager em, SessionContext sessionContext) {
+	public PreferenceService(EntityManager em, SessionContext sessionContext) {
 		this.em = em;
 		this.sessionContext = sessionContext;
 	}
@@ -78,7 +77,8 @@
 					Preference.class).setParameter("user", sessionContext.getCallerPrincipal().getName())
 					.setParameter("key", key.toLowerCase() + "%");
 		} else {
-			String user = sessionContext.isCallerInRole(ADMIN_ROLE) ? null : sessionContext.getCallerPrincipal().getName();
+			String user = sessionContext.isCallerInRole(ADMIN_ROLE) ? null
+					: sessionContext.getCallerPrincipal().getName();
 			query = em.createQuery(buildQuery(scope, key, user), Preference.class);
 
 			if (key != null && !key.trim().isEmpty()) {
diff --git a/nucleus/webclient/src/main/webapp/src/app/app.component.html b/nucleus/webclient/src/main/webapp/src/app/app.component.html
index 43663a4..13eeb39 100644
--- a/nucleus/webclient/src/main/webapp/src/app/app.component.html
+++ b/nucleus/webclient/src/main/webapp/src/app/app.component.html
@@ -20,7 +20,19 @@
       </ul>
       <ul class="navbar-nav ml-md-auto">
         <li class="nav-item">
-          <span class="navbar-text" style="padding: 0 5px; vertical-align: middle;">{{ 'app.language' | translate }}</span>
+          <span class="navbar-text" style="padding: 7px 5px; vertical-align: top">{{ 'app.datasources' | translate }}</span>
+          <p-multiSelect #datasourcemultiselect [options]="datasources" (onChange)="onSelectDatasources()" [(ngModel)]="selectedDatasources" [style]="{ 'margin-top': '2px', 'width': '150px' }" maxSelectedLabels="1"
+            defaultLabel="{{ 'app.dialog-preference-datasources.choose' | translate }}" selectedItemsLabel="{{ 'app.dialog-preference-datasources.x-datasources-selected' | translate }}">
+            <p-footer>
+              <div style="white-space: nowrap;">
+                <button type="button" class="btn btn-mdm" (click)="displayDatasourceDialog = true" title="{{ 'app.dialog-preference-datasources.title' | translate }}">{{ 'app.dialog-preference-datasources.btntitle' | translate }}</button>
+                <button type="button" class="btn btn-mdm" (click)="closeDatasourceDropdown($event)" title="Close dropdown">{{ 'app.dialog-preference-datasources.btnselect' | translate }}</button>
+              </div>
+            </p-footer>
+          </p-multiSelect>
+        </li>
+        <li class="nav-item">
+          <span class="navbar-text" style="padding: 7px 5px; vertical-align: top">{{ 'app.language' | translate }}</span>
           <p-dropdown [options]="languages" (onChange)="onSelectLanguage($event)" [(ngModel)]="selectedLanguage" [style]="{ 'margin-top': '2px', 'min-width': '100px' }"></p-dropdown>
         </li>
         <li class="nav-item"><a class="nav-link" [routerLink]="" (click)="onShowAboutDialog()" href="#">{{ 'app.about' | translate }}</a></li>
@@ -30,9 +42,42 @@
 </nav>
 
 <div>
-  <router-outlet></router-outlet>
+  <router-outlet *ngIf="canShowApplication"></router-outlet>
 </div>
 
+<p-dialog header="{{ 'app.dialog-preference-datasources.title' | translate }}" [(visible)]="displayDatasourceDialog"  [style]="{ 'max-width': '400px', 'max-height': '400px'}">
+  <p-table *ngIf="datasources?.length > 0" [value]="datasources" [(selection)]="selectedPreferenceRow" [paginator]="datasources?.length > 10" [rows]="10">
+    <ng-template pTemplate="header">
+        <tr>
+          <th style="width: 3em">
+            <p-tableHeaderCheckbox></p-tableHeaderCheckbox>
+          </th>
+          <th>
+            {{ 'app.dialog-preference-datasources.column-header' | translate }}
+          </th>
+        </tr>
+    </ng-template>
+    <ng-template pTemplate="body" let-row>
+        <tr>
+          <td>
+            <p-tableCheckbox [value]="row"></p-tableCheckbox>
+          </td>
+          <td>
+            {{row?.label}}
+          </td>
+        </tr>
+    </ng-template>
+  </p-table>
+
+  <p-footer>
+    <button type="button" pButton
+      (click)="saveDatasourcePreference($event)" 
+      [disabled]="selectedPreferenceRow?.length == 0"
+      icon="fa fa-floppy-o"
+      label="{{ 'app.dialog-preference-datasources.btntitle' | translate }}"></button>
+  </p-footer>
+</p-dialog>
+
 <p-dialog header="About" [(visible)]="displayAboutDialog" modal="true" dismissableMask="true" responsive="true">
   <notice></notice>
 </p-dialog>
diff --git a/nucleus/webclient/src/main/webapp/src/app/app.component.ts b/nucleus/webclient/src/main/webapp/src/app/app.component.ts
index 8d2cb5d..d75049b 100644
--- a/nucleus/webclient/src/main/webapp/src/app/app.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/app.component.ts
@@ -12,15 +12,22 @@
  *
  ********************************************************************************/
 
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
 
+import { map } from 'rxjs/operators';
+import { Observable } from 'rxjs';
+
 import { SelectItem } from 'primeng/api';
 import { User, Role } from './authentication/authentication.service';
 import { AuthenticationService } from './authentication/authentication.service';
 import { NodeService } from '@navigator/node.service';
+import { NodeproviderService } from '@navigator/nodeprovider.service';
 import ISO6391 from 'iso-639-1';
 import { MdmLocalizationService } from '@localization/mdm-localization.service';
+import { AvailableDatasourceService } from './available-datasource/available-datasource.service';
+import { Preference, PreferenceService, Scope } from './core/preference.service';
+import { MultiSelect } from 'primeng/primeng';
 
 @Component({
   selector: 'app-root',
@@ -33,6 +40,15 @@
   public languages: SelectItem[] = [];
   public selectedLanguage: string;
 
+  public datasources: SelectItem[] = [];
+  public selectedDatasources: string[] = [];
+  public standardDatasources: String[];
+  private preferenceName: string = 'app.components.standard_datasource';
+  public selectedPreferenceRow: SelectItem[] = [];
+  public displayDatasourceDialog = false;
+
+  public canShowApplication: boolean = false;
+
   public links = [
       { name: 'Administration', path: '/administration', roles: [ Role.Admin ] }
   ];
@@ -40,18 +56,39 @@
   public user: User = null;
   public rolesTooltip: string;
 
+  @ViewChild('datasourcemultiselect')
+  public datasourceMultiselect : MultiSelect;
+
   constructor(private translate: TranslateService,
               private localizationService: MdmLocalizationService,
               private authService: AuthenticationService,
-              private nodeService: NodeService) {}
+              private nodeService: NodeService,
+              private preferenceService: PreferenceService,
+              private nodeproviderService: NodeproviderService,
+              private dsService: AvailableDatasourceService) {}
 
   ngOnInit() {
     this.initLanguageSettings();
 
+    this.initStandarDatasource(this.loadPreference(this.preferenceName)).subscribe(value => {
+      this.standardDatasources = value;
+    })
+
     this.authService.getLoginUser().subscribe(value => {
       this.user = value;
       this.rolesTooltip = value.roles.join(', ');
     });
+
+    this.dsService.getAvailableDatasource().subscribe(value => {
+      this.datasources = value.map(ds => { return { label: ds, value: ds }});
+      if (this.standardDatasources === null || this.standardDatasources.length === 0) {
+        this.displayDatasourceDialog = true
+      } else {
+        this.datasources.filter(sourceName => this.standardDatasources.forEach(sp => (sp === sourceName.label) ? this.selectedDatasources.push(sourceName.value) : null));
+        this.selectedPreferenceRow = this.selectedDatasources.map(sourceName => {return { label: sourceName, value: sourceName }});
+        this.onSelectDatasources();
+      }
+    });
   }
 
   private initLanguageSettings() {
@@ -70,6 +107,44 @@
     });
   }
 
+  public closeDatasourceDropdown(event: any) {
+    this.datasourceMultiselect.close(event);
+  }
+
+  public onSelectDatasources() {
+    this.dsService.setDatasource(this.selectedDatasources).subscribe(value => {
+      this.nodeproviderService.loadNodeproviders().subscribe(np => {
+        this.nodeproviderService.setActiveNodeprovider(np[0].id);
+        if (this.languages === undefined || this.languages.length === 0) {
+          this.initLanguageSettings();
+        }
+        this.nodeService.setActiveDatasource(this.selectedDatasources.join(',')); // TODO
+        this.standardDatasources = [];
+        this.selectedPreferenceRow.forEach(pp => this.standardDatasources.push(pp.label));
+        this.canShowApplication = true;
+      })
+    });
+  }
+
+  saveDatasourcePreference($event) {
+    let werte: string = '';
+    this.selectedPreferenceRow.forEach(pp => werte += pp.label + '\n');
+    this.preferenceService.savePreference(this.datasourceToPreference(werte.substr(0, werte.length - 1))).subscribe(value => {
+      this.selectedDatasources = [];
+      this.selectedPreferenceRow.forEach(pp => this.selectedDatasources.push(pp.value));
+      this.onSelectDatasources();
+      this.displayDatasourceDialog = false;
+    });
+  }
+
+  private datasourceToPreference(datasource: string) {
+    let pref = new Preference();
+    pref.value = datasource;
+    pref.key = this.preferenceName;
+    pref.scope = Scope.USER;
+    return pref;
+  }
+
   public onSelectLanguage($event: any) {
     this.translate.use(this.selectedLanguage);
   }
@@ -77,4 +152,13 @@
   public onShowAboutDialog() {
     this.displayAboutDialog = true;
   }
+
+  private initStandarDatasource(pref: Observable<Preference>): Observable<string[]> {
+    return pref.pipe(map(p => (p === undefined ? null : p.value.split('\n'))));
+  }
+
+  private loadPreference(preferenceName: string): Observable<Preference> {
+    return this.preferenceService.getPreferenceForScope('USER', preferenceName)
+      .pipe(map(p => p[0]));
+  }
 }
diff --git a/nucleus/webclient/src/main/webapp/src/app/available-datasource/available-datasource.service.ts b/nucleus/webclient/src/main/webapp/src/app/available-datasource/available-datasource.service.ts
new file mode 100644
index 0000000..cc92865
--- /dev/null
+++ b/nucleus/webclient/src/main/webapp/src/app/available-datasource/available-datasource.service.ts
@@ -0,0 +1,52 @@
+/********************************************************************************
+ * 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
+ *
+ ********************************************************************************/
+
+ import { Injectable } from '@angular/core';
+ import {Http, Headers, RequestOptions} from '@angular/http';
+import { HttpClient } from '@angular/common/http';
+ import { Router, ResolveStart } from '@angular/router';
+ import { PropertyService } from '../core/property.service';
+ import { Observable } from 'rxjs';
+ import { publishReplay, refCount, map, tap, catchError } from 'rxjs/operators';
+ import {plainToClass} from 'class-transformer';
+ import {HttpErrorHandler} from '../core/http-error-handler';
+ 
+export class ServiceConfiguration {
+  contextFactoryClass: string;
+  connectionParameters: Map<string, string>;
+}
+ 
+@Injectable({
+   providedIn: 'root'
+})
+export class AvailableDatasourceService {
+   readonly loginURL: string;
+   readonly currentURL: string;
+ 
+  constructor(private http: HttpClient,
+     private _prop: PropertyService,
+     private httpErrorHandler: HttpErrorHandler) {
+     this.currentURL = _prop.getUrl('mdm/datasources/');
+   }
+ 
+   getAvailableDatasource() {
+     return this.http.get<string[]>(this.currentURL).pipe(
+      catchError(this.httpErrorHandler.handleError));;
+   }
+
+   setDatasource(activeDatasources: string[]) {
+     return this.http.put<string[]>(this.currentURL, activeDatasources).pipe(
+      catchError(this.httpErrorHandler.handleError));
+   }
+}
diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/chartviewer/chart-viewer.component.ts b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/chartviewer/chart-viewer.component.ts
index 63f13a6..8024c90 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/chartviewer/chart-viewer.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/chartviewer/chart-viewer.component.ts
@@ -139,10 +139,13 @@
 
       } else if (this.selectedChannelRows.length === 0) {
         // either the selected channel or all channels from the map
-        group = this.measurement.getFirstChannelGroup();
-        if (group) {
-          channels = this.measurement.findChannels(group);
-        }
+        //group = this.measurement.getFirstChannelGroup();
+        //if (group) {
+        //  channels = this.measurement.findChannels(group);
+        //}
+        this.data = this.getEmptyData();
+        this.tmpData = this.getEmptyData();
+        group = undefined;
       } else {
         group = this.selectedChannelRows[0].channelGroup;
         channels = this.selectedChannelRows.filter(cr => cr.channelGroup.id === group.id).map(cr => cr.yChannel);
diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/chatviewer-nav-card/chart-viewer-nav-card.component.ts b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/chatviewer-nav-card/chart-viewer-nav-card.component.ts
index 61dd3f1..336cec8 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/chatviewer-nav-card/chart-viewer-nav-card.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/chatviewer-nav-card/chart-viewer-nav-card.component.ts
@@ -27,6 +27,7 @@
 import { filter } from 'rxjs/operators';
 import { ChannelSelectionRow } from '../../model/chartviewer.model';
 import { ChannelGroup } from '../../model/types/channelgroup.class';
+import { Channel } from '../../model/types/channel.class';
 
 @Component({
   selector: 'mdm5-chartViewerNavCard',
@@ -170,7 +171,19 @@
         channelGroup = measurement.findChannelGroupByChannel(channel[0]);
         cGrpID = channel[0].channelGroupId;
       }
-      this.selectedChannelRows = channel.filter(c => cGrpID === undefined || c.channelGroupId === cGrpID)
+
+      let channelsArr: Channel[] = [];
+      channel.forEach(ch => {
+        if (measurement.getNumChannelGroupsForChannel(ch) > 1) {
+          this.notificationService.notifyWarn(
+            this.translateService.instant('chartviewer.chart-viewer-nav-card.channel-linked-to-multiple-channel-groups', {"channelname": ch.name}), null);
+        } else {
+          channelsArr.push(ch);
+        }
+      })
+
+     
+      this.selectedChannelRows = channelsArr.filter(c => cGrpID === undefined || c.channelGroupId === cGrpID)
           .map(c => new ChannelSelectionRow(channelGroup, c));
       this.sortSelectedChannelRows();
     }
diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/datatable/data-table.component.html b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/datatable/data-table.component.html
index 379f382..8b00c52 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/datatable/data-table.component.html
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/datatable/data-table.component.html
@@ -13,7 +13,7 @@
  ********************************************************************************-->
 
 <p-table class="datatable" #datatable [value]="datapoints" [columns]="cols" [lazy]="true" (onLazyLoad)="loadLazy($event)" [paginator]="true" 
-[rows]="recordsPerPage" [totalRecords]="totalRecords" [loading]="tableLoading" [rowsPerPageOptions]="[10, 20, 50, 100, 1000]">
+[rows]="recordsPerPage" [totalRecords]="totalRecords" [loading]="tableLoading" [rowsPerPageOptions]="[10, 20, 50, 100, 1000, 10000]">
     <ng-template pTemplate="header" let-columns>
         <tr>
             <th class="{{columns.length > 16 ? 'widecolumn' : ''}}">Index</th>
diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/datatable/data-table.component.ts b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/datatable/data-table.component.ts
index 7d2b06d..079001b 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/datatable/data-table.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/datatable/data-table.component.ts
@@ -105,15 +105,21 @@
   private groupChannelRowsByChannelGroup(channelRows: ChannelSelectionRow[]) {
     return channelRows.reduce((previous, currentItem) => {
       const group = currentItem.channelGroup.id;
-      if (!previous[group]) {
-        previous[group] = { channelGroup: currentItem.channelGroup, channels: [] };
+
+      if (group != null) {
+        if (!previous[group]) {
+          previous[group] = { channelGroup: currentItem.channelGroup, channels: [] };
+        }
+        if (currentItem.xChannel != undefined
+          && previous[group].channels.findIndex(c => c.id === currentItem.xChannel.id) == -1) {
+          previous[group].channels.push(currentItem.xChannel);
+        }
+        if (currentItem.yChannel != undefined
+          && previous[group].channels.findIndex(c => c.id === currentItem.yChannel.id) == -1) {
+          previous[group].channels.push(currentItem.yChannel);
+        }
       }
-      /*if (previous[group].findIndex(c => c.id === currentItem.xChannel.id) == -1) {
-        previous[group].push(currentItem.xChannel);
-      }*/
-      if (previous[group].channels.findIndex(c => c.id === currentItem.yChannel.id) == -1) {
-        previous[group].channels.push(currentItem.yChannel);
-      }
+
       return previous;
     }, {} as Record<string, {channelGroup: ChannelGroup, channels: Channel[]}>);
   }
diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.ts b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.ts
index fc8ef1c..2ed65d3 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.ts
@@ -39,6 +39,7 @@
 import { NodeService } from '@navigator/node.service';
 import { Preference, PreferenceService, Scope } from '@core/preference.service';
 import { deserialize, serialize } from 'class-transformer';
+import { isNullOrUndefined } from 'util';
 
 /**
  * Internal class only which is used for the user preference of the y-channel table configuration
@@ -852,8 +853,8 @@
   }
 
   private filterYChannelOptions() {
-    this.yChannelOptionsFiltered = this.filter(this.yChannelOptions, this.yChannelFilter);
-    this.totalYChannels = this.yChannelOptions.length;
+    this.yChannelOptionsFiltered = this.filter(this.yChannelOptions, this.yChannelFilter).filter(ch => this.yChannelOptions.filter(c => c.id == ch.id).length < 2);
+    this.totalYChannels = this.yChannelOptionsFiltered.length;
     if (this.virtualYChannelOptionsFiltered.length === 0) {
       // initial load data rows
       this.virtualYChannelOptionsFiltered = this.yChannelOptionsFiltered.slice(0, this.yChannelRows);
diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.html b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.html
index d0370f7..f984186 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.html
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.html
@@ -39,7 +39,11 @@
         
       </p-contextMenu>
 
-      <mdm5-dataTable *ngSwitchCase="'table'" [measurement]="measurement" [selectedChannelRows]="selectedChannelRows"></mdm5-dataTable>
+      <p-tabView *ngSwitchCase="'table'">
+        <p-tabPanel [header]="sel[0]" *ngFor="let sel of groupedSelectedChannelRows; let i = index" [selected]="i == 0">
+          <mdm5-dataTable [measurement]="measurement" [selectedChannelRows]="sel[1]"></mdm5-dataTable>
+        </p-tabPanel>
+      </p-tabView>
       <div *ngSwitchDefault></div>
     </div>
   </div>
diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.ts b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.ts
index 99e2c49..f16514f 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.ts
@@ -64,6 +64,7 @@
   public xyMode: boolean;
 
   public selectedChannelRows: ChannelSelectionRow[] = [];
+  public groupedSelectedChannelRows: [string, ChannelSelectionRow[]][] = [];
 
   modes: SelectItem[] = [];
   selectedMode = 'chart';
@@ -183,6 +184,7 @@
     const selectedGroups: ChannelGroup[] = complex.groups;
     // force change detection
     this.selectedChannelRows = [...rows];
+    this.groupedSelectedChannelRows = this.groupChannelSelectionRowsByChannelGroup(this.selectedChannelRows);
     if (!selectedGroups || selectedGroups.length === 0) {
       this.assignedColors = [];
     }
@@ -351,7 +353,28 @@
     }
   }
 
-  /******* Helping functions */
+  private groupChannelSelectionRowsByChannelGroup(channelRows: ChannelSelectionRow[]) {
+    let arrRet: [string, ChannelSelectionRow[]][] = [];
+
+    if (channelRows != undefined) {
+      let mapChannelSelectionRows = new Map<string, ChannelSelectionRow[]>();
+      let mapChannelGroupIds = new Map<string, string>();
+
+      channelRows.forEach(row => {
+        if (!mapChannelSelectionRows.has(row.channelGroup.id)) {
+          mapChannelSelectionRows.set(row.channelGroup.id, []);
+          mapChannelGroupIds.set(row.channelGroup.id, row.channelGroup.name);
+        }
+        mapChannelSelectionRows.get(row.channelGroup.id).push(row);
+      })
+
+      mapChannelSelectionRows.forEach((v, k) => arrRet.push([mapChannelGroupIds.get(k), v]));
+    }
+
+    return arrRet.sort((a, b) => a[0].toLowerCase().localeCompare(b[0].toLowerCase()));
+  }
+
+  /******* Helper functions */
 
   /**
    * Filter duplicate values and only return distinct values  as array.
diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/model/types/measurement.class.ts b/nucleus/webclient/src/main/webapp/src/app/chartviewer/model/types/measurement.class.ts
index 03dde20..e5b5c01 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/model/types/measurement.class.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/model/types/measurement.class.ts
@@ -77,6 +77,18 @@
         return undefined;

     }

 

+    getNumChannelGroupsForChannel(channel: Channel) {

+        let count: number = 0;

+        for (let entry of Array.from(this.channels.entries())) {

+            let c = entry[1].find(chan => chan.id === channel.id);

+            if (c !== undefined) {

+               ++count;

+            }

+          }

+

+        return count;

+    }

+

     findChannel(channelId: string) {

         for (let entry of Array.from(this.channels.entries())) {

             let c = entry[1].find(channel => channel.id === channelId);

diff --git a/nucleus/webclient/src/main/webapp/src/app/chartviewer/services/chart-viewer-data.service.ts b/nucleus/webclient/src/main/webapp/src/app/chartviewer/services/chart-viewer-data.service.ts
index c2b0671..7a8852c 100644
--- a/nucleus/webclient/src/main/webapp/src/app/chartviewer/services/chart-viewer-data.service.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/chartviewer/services/chart-viewer-data.service.ts
@@ -161,7 +161,7 @@
     query.addFilter(sourceName, 'Measurement.Id eq ' + measurementId);
     query.columns = ['Measurement.Id', 'ChannelGroup.Id', 'ChannelGroup.Name', 'ChannelGroup.SubMatrixNoRows',
       'Channel.Id', 'Channel.Name', 'LocalColumn.axistype', 'LocalColumn.IndependentFlag'];
-    query.resultType = 'Channel';
+    query.resultType = 'LocalColumn';
     query.resultOffset = this.resultOffset;
     query.resultLimit = 0; // request all results
 
@@ -186,7 +186,7 @@
 
   private mapRow(row: Row) {
     let channel = new Channel();
-    channel.id = row.id;
+    channel.id = Row.getColumn(row, 'Channel.Id');
     channel.name = Row.getColumn(row, 'Channel.Name');
     channel.channelGroupId = Row.getColumn(row, 'ChannelGroup.Id');
     channel.axisType = Row.getColumn(row, 'LocalColumn.axistype'),
diff --git a/nucleus/webclient/src/main/webapp/src/app/core/mdm-core.module.ts b/nucleus/webclient/src/main/webapp/src/app/core/mdm-core.module.ts
index e11865b..2631cf9 100644
--- a/nucleus/webclient/src/main/webapp/src/app/core/mdm-core.module.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/core/mdm-core.module.ts
@@ -27,10 +27,12 @@
 import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
 import { BsDropdownModule } from 'ngx-bootstrap';
 
+import { TableModule } from 'primeng/table';
 import { TreeModule, DataTableModule, SharedModule, ContextMenuModule } from 'primeng/primeng';
 import { DropdownModule, MultiSelectModule, CalendarModule } from 'primeng/primeng';
 import { ToastModule } from 'primeng/toast';
 import { MessageService } from 'primeng/api';
+import { TabViewModule } from "primeng/tabview";
 
 import { PropertyService } from './property.service';
 import { PreferenceService } from './preference.service';
@@ -71,6 +73,7 @@
     DatepickerModule.forRoot(),
     TreeModule,
     DataTableModule,
+    TableModule,
     SharedModule,
     ContextMenuModule,
     DropdownModule,
@@ -80,6 +83,7 @@
     BsDropdownModule.forRoot(),
     HttpClientModule,
     TranslateModule.forChild(),
+    TabViewModule,
   ],
   declarations: [
     MDMNotificationComponent,
@@ -99,6 +103,7 @@
     CalendarModule,
     TreeModule,
     DataTableModule,
+    TableModule,
     SharedModule,
     ContextMenuModule,
     ToastModule,
@@ -114,6 +119,7 @@
     OnlyNumberDirective,
     MdmTranslatePipe,
     MimeTypePipe,
+    TabViewModule,
   ],
   providers: [
       PositioningService,
diff --git a/nucleus/webclient/src/main/webapp/src/app/details/components/mdm-detail-descriptive-data/mdm-detail-descriptive-data.component.ts b/nucleus/webclient/src/main/webapp/src/app/details/components/mdm-detail-descriptive-data/mdm-detail-descriptive-data.component.ts
index 98de20a..29f8d36 100644
--- a/nucleus/webclient/src/main/webapp/src/app/details/components/mdm-detail-descriptive-data/mdm-detail-descriptive-data.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/details/components/mdm-detail-descriptive-data/mdm-detail-descriptive-data.component.ts
@@ -348,8 +348,10 @@
       if (attr) {
         if (typeof attr.value === 'string') {
           return attr.value;
-        } else if (Array.isArray(attr.value) && attr.value.length > 0 && typeof attr.value[0] === 'string') {
+        } else if (Array.isArray(attr.value) && attr.value.length == 1 && typeof attr.value[0] === 'string') {
           return attr.value[0];
+        } else if (Array.isArray(attr.value) && attr.value.length > 1 && typeof attr.value[1] === 'string') {
+          return attr.value[1];
         }
       }
     }
diff --git a/nucleus/webclient/src/main/webapp/src/app/localization/mdm-localization.service.ts b/nucleus/webclient/src/main/webapp/src/app/localization/mdm-localization.service.ts
index 5f37b48..d46967d 100644
--- a/nucleus/webclient/src/main/webapp/src/app/localization/mdm-localization.service.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/localization/mdm-localization.service.ts
@@ -15,7 +15,7 @@
 import { Injectable } from '@angular/core';
 
 import { TranslateService } from '@ngx-translate/core';
-import { Observable, ReplaySubject, Subject } from 'rxjs';
+import { Observable, ReplaySubject, Subscription } from 'rxjs';
 import { catchError, filter, flatMap, map, shareReplay, tap } from 'rxjs/operators';
 
 import { HttpErrorHandler } from '@core/http-error-handler';
@@ -39,20 +39,16 @@
 
   private lastEnvironment: string;
 
+  private nodeServiceSubscription: Subscription;
+
   constructor(private http: HttpClient,
     private httpErrorHandler: HttpErrorHandler,
     private prop: PropertyService,
     private translateService: TranslateService,
     private nodeService: NodeService) {
       // initialize translations for each present environment
-      this.replayer = this.nodeService.getNodes().pipe(
-        tap(envs => this.initTranslationIndices(envs)),
-        map(envs => envs.reduce((previous, current) => {
-          previous[current.sourceName] = this.loadTranslationMap(current.sourceName);
-          return previous;
-        }, {})),
-        shareReplay(1)
-      );
+      this.initializeTranslations();
+      this.subscribeToDatasourceChanges();
       
       this.contextUrl = this.prop.getUrl('mdm/environments');
 
@@ -67,6 +63,26 @@
       this.translateService.onLangChange.subscribe(() => this.emitTranslations());
   }
 
+  subscribeToDatasourceChanges() {
+    this.nodeServiceSubscription = this.nodeService.datasourceChanged.subscribe(
+      np =>  this.initializeTranslations()
+    );
+  }
+
+  /*
+   * initialize translations for each present environment
+   */
+  initializeTranslations() {
+    this.replayer = this.nodeService.getNodes().pipe(
+      tap(envs => this.initTranslationIndices(envs)),
+      map(envs => envs.reduce((previous, current) => {
+        previous[current.sourceName] = this.loadTranslationMap(current.sourceName);
+        return previous;
+      }, {})),
+      shareReplay(1)
+    );
+  }
+
   /**
    * Reloads translation map if none is present or present translations refer to other source.
    * Returns an Observable holding the current translations.
@@ -89,12 +105,14 @@
   }
 
   public getLanguages() {
+    return Observable.of(['en', 'de']);
+    /* TODO: cannot accessing the environments before setting the active datasources; thus hardcoding the languages 
     return this.nodeService.getNodes().pipe(
       map(envs => Array.from(new Set(envs.map(env => this.extractLanguageCodes(env))
         .filter(codes => codes != undefined)
         .reduce((prev, current) => prev.concat(current), [])))
       )
-    )
+    )*/
   }
 
   public getDefaultMimeType(type: string, sourceName?: string): Observable<string> {
diff --git a/nucleus/webclient/src/main/webapp/src/app/navigator/mdm-navigator.component.ts b/nucleus/webclient/src/main/webapp/src/app/navigator/mdm-navigator.component.ts
index 5a1c5b5..4afa304 100644
--- a/nucleus/webclient/src/main/webapp/src/app/navigator/mdm-navigator.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/navigator/mdm-navigator.component.ts
@@ -13,7 +13,7 @@
  ********************************************************************************/
 
 
-import { Component, OnInit, ViewChild } from '@angular/core';
+import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
 import { TreeNode, MenuItem, Tree } from 'primeng/primeng';
 
 import { map, tap, startWith, filter, flatMap } from 'rxjs/operators';
@@ -47,7 +47,7 @@
     '>>>.ui-tree .ui-tree-container { overflow: visible; }'
   ]
 })
-export class MDMNavigatorComponent implements OnInit {
+export class MDMNavigatorComponent implements OnInit, OnDestroy {
 
   ICON_UNCHECKED = 'fa fa-square-o';
   ICON_CHECKED = 'fa fa-check-square-o';
@@ -64,6 +64,7 @@
   tagableMenuMap: Map<string, MenuItem[]> = new Map();
   statusMap: Map<string, Node[]> = new Map();
   statusMap4Obj: Map<string, Map<string, string[]>> = new Map();
+  nodeServiceSubscription: Subscription;
 
   loadingNode = <TreeNode>{
     label: 'Loading subordinate items...',
@@ -154,6 +155,34 @@
     });
 
     // make sure navigate parameter is handled after nodes are loaded
+    this.loadNavigateParameter();
+
+    this.subscribeToDatasourceChanged();
+    this.subscribeToNodeProviderChanges();
+
+    this.navigatorService.onOpenInTree
+      .subscribe(
+        items => this.openInTree(items),
+        error => this.notificationService.notifyError(
+          this.translateService.instant('navigator.mdm-navigator.err-cannot-open-node-in-navigation-tree'), error)
+      );      
+  }
+
+  ngOnDestroy() {
+    if (this.nodeServiceSubscription) {
+      this.nodeServiceSubscription.unsubscribe;
+    }
+  }
+
+  subscribeToDatasourceChanged() {
+    this.nodeServiceSubscription = this.nodeService.datasourceChanged.subscribe(
+      np =>  this.loadNavigateParameter(),
+      error => this.notificationService.notifyError(
+        this.translateService.instant('navigator.mdm-navigator.err-cannot-update-navigation-tree'), error)
+    );
+  }
+
+  loadNavigateParameter() {
     this.loadRootNodes().subscribe(
       treeNodes => {
         this.nodes = treeNodes;
@@ -429,6 +458,12 @@
           if (type === 'Measurement' || type === 'ChannelGroup') {
             this.contextMenuItems.push(this.contextMenuItemChart);
           }
+          
+          if (type === 'Test' || type === 'TestStep') {
+            this.addMenuStatus(source, type);
+          } else if (this.contextMenuItems.indexOf(this.contextMenuItemStatus) == (this.contextMenuItems.length - 1)) {
+            this.contextMenuItems.pop();
+          }
         }
       }
     }
diff --git a/nucleus/webclient/src/main/webapp/src/app/navigator/node.service.ts b/nucleus/webclient/src/main/webapp/src/app/navigator/node.service.ts
index 1d933b9..7fe0e37 100644
--- a/nucleus/webclient/src/main/webapp/src/app/navigator/node.service.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/navigator/node.service.ts
@@ -12,7 +12,7 @@
  *
  ********************************************************************************/
 
-import {Injectable} from '@angular/core';
+import {Injectable, EventEmitter} from '@angular/core';
 import {Http, Headers, RequestOptions} from '@angular/http';
 import {Observable, of} from 'rxjs';
 import {catchError, map} from 'rxjs/operators';
@@ -26,6 +26,8 @@
 @Injectable()
 export class NodeService {
 
+  public datasourceChanged: EventEmitter<string> = new EventEmitter<string>();
+
   private _nodeUrl: string;
   private _nodeProviderEndpoint: string;
   private _defNodeProv = 'generic';
@@ -41,6 +43,13 @@
     this._nodeUrl = this._prop.getUrl('mdm/environments');
   }
 
+  /*
+   * The datasource has changed, the components must reload environment data.
+   */
+  setActiveDatasource(datasource: string) {
+    this.datasourceChanged.emit(datasource);
+  }
+
   searchNodes(query, env, type) {
     return this.http.get(this._nodeUrl + '/' + env + '/' + this.typeToUrl(type) + '?' + query).pipe(
               map(res => plainToClass(Node, res.json().data)),
diff --git a/nucleus/webclient/src/main/webapp/src/app/search/mdm-search.component.ts b/nucleus/webclient/src/main/webapp/src/app/search/mdm-search.component.ts
index f34d3b8..9661ef2 100644
--- a/nucleus/webclient/src/main/webapp/src/app/search/mdm-search.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/search/mdm-search.component.ts
@@ -57,6 +57,7 @@
 
   environments: Node[];
   selectedEnvironments: Node[] = [];
+  nodeServiceSubscription: Subscription;
 
   definitions: SearchDefinition[] = [];
   selectedDefinition: string;
@@ -135,17 +136,8 @@
     streamTranslate(this.translateService, TRANSLATE(this.filterService.NO_FILTER_NAME)).subscribe(
             (msg: string) => this.setNoFilterLabel(msg));
 
-    this.nodeService.getNodes().pipe(
-      mergeMap(envs => combineLatest([
-        of(envs),
-        this.searchService.loadSearchAttributesStructured(envs.map(env => env.sourceName)),
-        this.filterService.getFiltersOfCurrentUser().pipe(defaultIfEmpty([this.currentFilter])),
-        this.searchService.getDefinitionsSimple()
-      ]))).subscribe(
-        ([envs, attrs, filters, definitions]) => this.init(envs, attrs, filters, definitions),
-        error => this.notificationService.notifyError(
-          this.translateService.instant('search.mdm-search.err-cannot-load-data-sources'), error)
-      );
+    this.initNodes();
+    this.subscribeToDatasourceChanges();
 
     // event handlers
     this.viewComponent.viewChanged$.subscribe(
@@ -159,6 +151,27 @@
      if (this.linkedToNavigatorSub) {
       this.linkedToNavigatorSub.unsubscribe();
     }
+    if (this.nodeServiceSubscription) {
+      this.nodeServiceSubscription.unsubscribe;
+    }
+  }
+
+  subscribeToDatasourceChanges(){
+    this.nodeServiceSubscription = this.nodeService.datasourceChanged.subscribe(np => this.initNodes())
+  }
+
+  initNodes() {
+    this.nodeService.getNodes().pipe(
+      mergeMap(envs => combineLatest([
+        of(envs),
+        this.searchService.loadSearchAttributesStructured(envs.map(env => env.sourceName)),
+        this.filterService.getFiltersOfCurrentUser().pipe(defaultIfEmpty([this.currentFilter])),
+        this.searchService.getDefinitionsSimple()
+      ]))).subscribe(
+        ([envs, attrs, filters, definitions]) => this.init(envs, attrs, filters, definitions),
+        error => this.notificationService.notifyError(
+          this.translateService.instant('search.mdm-search.err-cannot-load-data-sources'), error)
+      )
   }
 
   init(envs: Node[], attrs: { [type: string]: { [env: string]: SearchAttribute[] }},
diff --git a/nucleus/webclient/src/main/webapp/src/app/search/search.service.ts b/nucleus/webclient/src/main/webapp/src/app/search/search.service.ts
index 17c3b2f..13fe453 100644
--- a/nucleus/webclient/src/main/webapp/src/app/search/search.service.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/search/search.service.ts
@@ -171,7 +171,7 @@
 
   ignoreAttributesPrefs: Preference[] = [];
 
-  private cachedAttributes: Observable<any>;
+  private cachedAttributes = new Map();//Observable<any>;
 
   constructor(private http: Http,
     private httpErrorHandler: HttpErrorHandler,
@@ -218,14 +218,14 @@
   }
 
   loadSearchAttributesStructured(environments: string[]) {
-    if (!this.cachedAttributes) {
-      this.cachedAttributes = this.getDefinitionsSimple().pipe(
+    if (!this.cachedAttributes.has(environments.toString())) {
+      this.cachedAttributes.set(environments.toString(), this.getDefinitionsSimple().pipe(
         map(defs => defs.map(d => d.value)),
         mergeMap(defs => this.loadSearchAttributesForAllDefs(defs, environments)),
         publishReplay(1),
-        refCount());
+        refCount()));
     }
-    return this.cachedAttributes;
+    return this.cachedAttributes.get(environments.toString());
   }
 
   loadSearchAttributesForAllDefs(types: string[], environments: string[]) {
@@ -259,8 +259,10 @@
 
     q.resultType = searchFilter.resultType;
     if (attr && attr['tests']) {
-      q.filters = this.convert(searchFilter.environments, searchFilter.conditions, attr['tests'],
-        searchFilter.fulltextQuery, and); // TODO
+      let envsAttr = this.getEnvFromCachedAttributes();
+      let envs: string[] = [];
+      searchFilter.environments.forEach(env => {envsAttr.forEach(val => {env === val ? envs.push(env): null})});
+      q.filters = this.convert(envs, searchFilter.conditions, attr['tests'], searchFilter.fulltextQuery, true); // TODO
     }
     q.columns = view.columns.map(c => c.type + '.' + c.name);
     console.log('Query', q);
@@ -268,6 +270,21 @@
     return q;
   }
 
+  /*
+   * get the environments from the cached Attributes
+   */
+  getEnvFromCachedAttributes() {
+    let envs: string[] = [];
+    this.cachedAttributes.forEach((value: any, key: string) => {
+      key.split(',').forEach(env => {
+        if (!envs.some(val => env === val)) {
+        envs.push(env)
+        }
+      });
+    });
+    return envs;
+  }
+
   convert(envs: string[], conditions: Condition[], attr: { [env: string]: SearchAttribute[] },
     fullTextQuery: string, and: boolean): Filter[] {
     return envs.map(e => this.convertEnv(e, conditions, attr[e], fullTextQuery, and)).filter(e => e != undefined);
diff --git a/nucleus/webclient/src/main/webapp/src/app/tableview/editview.component.ts b/nucleus/webclient/src/main/webapp/src/app/tableview/editview.component.ts
index c139096..e36d374 100644
--- a/nucleus/webclient/src/main/webapp/src/app/tableview/editview.component.ts
+++ b/nucleus/webclient/src/main/webapp/src/app/tableview/editview.component.ts
@@ -48,6 +48,7 @@
   typeAheadValues: {label: string, group: string, attribute: SearchAttribute }[] = [];
 
   selectedAttribute: SearchAttribute;
+  nodeServiceSubscription: Subscription;
 
   @Output()
   coloumnsSubmitted = new EventEmitter<View>();
@@ -68,7 +69,15 @@
         error => this.notificationService.notifyError(this.translateService.instant('tableview.editview.err-cannot-select-node'), error)
       )
     );
+    this.initNodes();
+    this.subscribeToDatasourceChanges();
+  }
 
+  subscribeToDatasourceChanges(){
+    this.nodeServiceSubscription = this.nodeService.datasourceChanged.subscribe(np => this.initNodes())
+  }
+  
+  initNodes() {
     this.subscription.add(
       this.nodeService.getNodes()
         .subscribe(
@@ -76,7 +85,7 @@
             this.searchService.loadSearchAttributesStructured(envs.map(e => e.sourceName)).pipe(
               map(attrs => attrs['measurements']))
               .subscribe(
-                attrs => this.refreshValues(attrs, envs),
+                attrs => this.refreshValues(attrs, envs), //refreshTypeAheadValues
                 error => this.notificationService.notifyError(
                   this.translateService.instant('tableview.editview.err-cannot-load-search-attributes'), error)
               );
diff --git a/nucleus/webclient/src/main/webapp/src/assets/i18n/de.json b/nucleus/webclient/src/main/webapp/src/assets/i18n/de.json
index fc96855..dd01c94 100644
--- a/nucleus/webclient/src/main/webapp/src/assets/i18n/de.json
+++ b/nucleus/webclient/src/main/webapp/src/assets/i18n/de.json
@@ -15,6 +15,7 @@
 			"btn-cancel": "Abbrechen",
 			"btn-save": "Speichern",
 			"err-cannot-load-data-source": "Datenquelle kann nicht geladen werden.",
+			"err-cannot-load-scope": "Geltungsbereich kann nicht geladen werden.",
 			"lbl-key": "Schlüssel",
 			"lbl-scope": "Geltungsbereich",
 			"lbl-source": "Quelle",
@@ -33,8 +34,10 @@
 			"component-name": "Komponenten-Name",
 			"component-type": "Komponenten-Typ",
 			"description": "Beschreibung",
+			"dialog-ext-system-attr-title": "Externes System Attribute",
 			"dialog-ext-system-delete-text": "Bitte bestätigen Sie das Löschen des Externen Systems",
 			"dialog-ext-system-delete-title": "Externes System löschen",
+			"dialog-ext-system-mdm-attr-title": "MDM Attribute",
 			"dialog-ext-system-title": "Externes System",
 			"dropdown-please-select": "Bitte auswählen",
 			"err-cannot-load-comp-types": "Komponententypen konnten nicht geladen werden",
@@ -45,6 +48,7 @@
 			"ext-system-attributes": "Externes System Attribute",
 			"loading": "Lade Daten...",
 			"loading-attributes": "Lade Attribute...",
+			"loading-short": "Lade",
 			"mdm-attributes": "MDM Attribute",
 			"name": "Name",
 			"select-system": "Datenquelle auswählen",
@@ -67,6 +71,7 @@
 			"btn-cancel": "Abbrechen",
 			"btn-copy": "Kopieren",
 			"btn-del": "Löschen",
+			"btn-edit": "Bearbeiten",
 			"btn-new-version": "Neue Version",
 			"btn-save": "Speichern",
 			"btn-valid": "Gültig setzen",
@@ -88,6 +93,9 @@
 			"select-system": "Datenquelle auswählen",
 			"selected-system": "Gewählte Datenquelle",
 			"status": "Status",
+			"status-lbl-archived": "Archiviert",
+			"status-lbl-editable": "In Bearbeitung",
+			"status-lbl-valid": "Gültig",
 			"txt-copy-of": "Kopie{0}Von",
 			"unit": "Einheit",
 			"version": "Version"
@@ -97,6 +105,7 @@
 			"btn-cancel": "Abbrechen",
 			"btn-copy": "Kopieren",
 			"btn-del": "Entfernen",
+			"btn-edit": "Bearbeiten",
 			"btn-save": "Speichern",
 			"db": "dB",
 			"db-ref-factor": "dB Ref.-Faktor",
@@ -112,6 +121,7 @@
 			"err-cannot-update-unit": "Die Einheit konnte nicht gespeichert werden",
 			"factor": "Faktor",
 			"loading": "Lade Daten...",
+			"loading-short": "Lade",
 			"name": "Name",
 			"offset": "Offset",
 			"phys-dim": "Phys. Dimension",
@@ -122,6 +132,15 @@
 	},
 	"app": {
 		"about": "Über",
+		"datasources": "Datenquellen",
+		"dialog-preference-datasources": {
+			"btnselect": "Übernehmen",
+			"btntitle": "Standard Datenquellen",
+			"choose": "Auswählen",
+			"column-header": "Datenquellen",
+			"title": "Standard Datenquellen auswählen",
+			"x-datasources-selected": "{0} Datenquellen"
+		},
 		"language": "Sprache",
 		"logout": "Logout",
 		"roles": "Rollen"
@@ -163,12 +182,14 @@
 	"chartviewer": {
 		"chart": "Grafik",
 		"chart-viewer-nav-card": {
+			"channel-linked-to-multiple-channel-groups": "Daten für Kanal {{channelname}} können nicht angezeigt werden, da er mehreren Kanalgruppen zugeordnet ist.",
 			"load-missing-channels": "{{limit}} Kanäle nachladen ({{offset}}/{{total}})"
 		},
 		"request-options": {
 			"apply": "Übernehmen",
 			"from": "von",
 			"options": "Optionen",
+			"overall": "Gesamt",
 			"preview-values": "Vorschauwerte",
 			"reset": "Zurücksetzen",
 			"step-size": "Schrittweite",
@@ -183,9 +204,13 @@
 		"table": "Tabelle",
 		"x-axis": "X-Achse",
 		"xy-chart-data-selection-panel": {
+			"all-results": "Alle",
 			"apply": "Übernehmen",
 			"cancel": "Abbrechen",
+			"default-result-limit": "Standard",
 			"filter": "Filter",
+			"manual-result-limit": "Maunell",
+			"measurement": "Messergebnis",
 			"no-x-channel-dialog-header": "Information",
 			"no-x-channel-dialog-message": "Die aktuelle Kanalgruppe hat keine Kanäle die als X-Achse bzw. XY-Achse definiert sind. Wenn Sie auch als Y-Achse definierte Kanäle zulassen möchten, deaktivieren Sie bitte den Filter in der Werkzeugleiste.",
 			"result-limit": "Maximale Anzahl Ergebnisse",
@@ -195,14 +220,27 @@
 			"tooltip-regexp-filter": "Reguläre Ausdrücke als Filtereingabe möglich.\n\nBeispiele:\n?: Der voranstehende Ausdruck ist optional, er kann einmal vorkommen, braucht es aber nicht, das heißt, der Ausdruck kommt null- oder einmal vor\n+: Der voranstehende Ausdruck muss mindestens einmal vorkommen, darf aber auch mehrfach vorkommen.\n*: Der voranstehende Ausdruck darf beliebig oft (auch keinmal) vorkommen.",
 			"y-channel-query-config-editor": "Sucheinstellungen für Y-Kanäle"
 		},
+		"xy-chart-viewer": {},
 		"xy-chart-viewer-nav-card": {
 			"no-node-selected": "Kein Knoten ausgewählt"
 		},
 		"xy-chart-viewer-toolbar": {
 			"absolute-drawing": "Absolut",
+			"activate-xy-mode": "Kanal Auswahloptionen nach Achsentyp filtern",
+			"clear-area": "Fläche unter dem Graph leeren",
+			"deactivate-xy-mode": "Alle Kanäle als Auswahloptionen anzeigen",
+			"fill-area": "Fläche unter dem Graph füllen",
+			"hide-chart-legend": "Legende des Diagramms verbergen",
+			"hide-data-selection-panel": "Datenauswahlpanel verbergen",
+			"hide-datapoints": "Datenpunkte verbergen",
+			"hide-lines": "Verbindungslinien verbergen",
 			"line-width": "Linienstärke",
 			"open-popup": "Popup Öffnen",
 			"relative-drawing": "Relativ",
+			"show-chart-legend": "Legende des Diagramms anzeigen",
+			"show-data-selection-panel": "Datenauswahlpanel anzeigen",
+			"show-datapoints": "Datenpunkte markieren",
+			"show-lines": "Verbindungslinien anzeigen",
 			"tension": "Tension: 0 = Linear, 0.4 = Bezierkurve"
 		},
 		"y-axis": "Y-Achse"
@@ -272,6 +310,14 @@
 			"err-cannot-load-preference-for-attributes-to-ignore": "Einstellung für zu ignorierende Attribute kann nicht geladen werden.",
 			"err-faulty-preference-for-attributes-to-ignore": "Einstellung für die zu ignorierenden Attribute ist fehlerhaft."
 		},
+		"mdm-detail": {
+			"general": "General",
+			"parametersets": "Parametersets",
+			"sensors": "Sensoren",
+			"test-equipment": "Messgerät",
+			"test-sequence": "Testablauf",
+			"unit-under-test": "Prüfling"
+		},
 		"mdm-detail-descriptive-data": {
 			"btn-cancel": "Abbrechen",
 			"btn-edit": "Bearbeiten",
@@ -293,6 +339,7 @@
 		"mdm-detail-panel": {
 			"btn-into-shopping-basket": "In den Warenkorb",
 			"btn-show-in-tree": "Im Baum zeigen",
+			"cannot-update-node": "Knoten kann nicht aktualisiert werden.",
 			"tblhdr-attribute": "Attribut",
 			"tblhdr-unit": "Einheit",
 			"tblhdr-value": "Wert"
@@ -300,13 +347,9 @@
 		"mdm-detail-view": {
 			"cannot-update-node": "Knoten kann nicht aktualisiert werden."
 		},
-		"mdm-detail": {
-			"general": "General",
-			"parametersets": "Parametersets",
-			"sensors": "Sensoren",
-			"test-equipment": "Messgerät",
-			"test-sequence": "Testablauf",
-			"unit-under-test": "Prüfling"
+		"parameterset": {
+			"err-cannot-load-data": "Daten können nicht geladen werden.",
+			"status-no-parametersets": "Keine Parametersets vorhanden."
 		},
 		"parameterset-panel": {
 			"btn-cancel-parameterset": "Abbrechen",
@@ -317,13 +360,10 @@
 			"tblhdr-unit": "Einheit",
 			"tblhdr-value": "Wert"
 		},
-		"parameterset": {
-			"err-cannot-load-data": "Daten können nicht geladen werden.",
-			"status-no-parametersets": "Keine Parametersets vorhanden."
-		},
 		"sensor": {
 			"err-cannot-load-data": "Daten können nicht geladen werden.",
 			"err-cannot-load-descriptive-data": "Beschreibende Daten können nicht geladen werden.",
+			"err-cannot-load-scope": "Bereich kann nicht geladen werden.",
 			"status-loading": "Lädt...",
 			"status-no-descriptive-data-available": "Keine beschreibenden Daten verfügbar.",
 			"status-no-nodes-available": "Keine Knoten verfügbar.",
@@ -351,6 +391,7 @@
 			"btn-refresh": "Aktualisieren",
 			"btn-remove-all-files-from-selection": "Dateiauswahl leeren",
 			"btn-remove-file-from-selection": "Datei aus Auswahl entfernen",
+			"btn-upload-file": "Datei hochladen",
 			"btn-upload-file-selection": "Ausgewählte Dateien hochladen",
 			"btn-upload-files": "Dateien hochladen",
 			"hdr-description": "Beschreibung",
@@ -363,14 +404,19 @@
 			"ttl-attached-to": "Dateien angehangen an: ",
 			"ttl-confirmation": "Bestätigung"
 		},
+		"file-explorer-nav-card": {
+			"status-no-node-selected": "Kein Knoten ausgewählt.",
+			"status-node-is-no-files-attachable": "An {{type}}s können keine Dateien angehangen werden.",
+			"status-virtual-node-selected": "Virtueller Knoten ausgewählt."
+		},
+		"file-link-editor": {
+			"hdr-file-upload-wizard": "Datei-Upload Wizard für {{name}}"
+		},
 		"file-link-editor-dialog": {
 			"btn-cancel": "Abbrechen",
 			"btn-change-file": "Datei ändern",
 			"btn-save-changes": "Speichern"
 		},
-		"file-link-editor": {
-			"hdr-file-upload-wizard": "Datei-Upload Wizard für {{name}}"
-		},
 		"file-link-sequence-editor": {
 			"hdr-file-upload-wizard": "Datei-Upload Wizard für {{name}}"
 		},
@@ -393,27 +439,6 @@
 			"state-release-processing-error": "Systemfehler",
 			"state-release-released": "freigegeben"
 		},
-		"mdm-filerelease-create": {
-			"btn-release-request": "Freigabeanfrage",
-			"btn-send": "Senden",
-			"err-cannot-create-release": "Release kann nicht erzeugt werden.",
-			"lbl-format": "Format",
-			"lbl-reason": "Begründung",
-			"lbl-validity-days": "Gültigkeit (Tage)",
-			"title-release": "Freigabe"
-		},
-		"mdm-filerelease-display": {
-			"lbl-error-message": "Fehlerbericht",
-			"lbl-expires-on": "Freigegeben bis",
-			"lbl-reason-for-declining": "Begründung für Ablehnung",
-			"lbl-reason-for-release": "Begründung für Freigabe",
-			"lbl-requested-by": "Antragsteller",
-			"lbl-state": "Status",
-			"lbl-test-name": "Versuchsname",
-			"lbl-test-responsible-person": "Messungsverantwortlicher",
-			"lbl-validity": "Freigabedauer",
-			"tlbl-format": "Format"
-		},
 		"mdm-filerelease": {
 			"btn-approve": "Genehmigen",
 			"btn-cancel": "Abbrechen",
@@ -435,6 +460,27 @@
 			"tblhdr-status": "Status",
 			"tblhdr-test-name": "Versuchsname",
 			"tblhdr-test-responsible-person": "Messungsverantwortlicher"
+		},
+		"mdm-filerelease-create": {
+			"btn-release-request": "Freigabeanfrage",
+			"btn-send": "Senden",
+			"err-cannot-create-release": "Release kann nicht erzeugt werden.",
+			"lbl-format": "Format",
+			"lbl-reason": "Begründung",
+			"lbl-validity-days": "Gültigkeit (Tage)",
+			"title-release": "Freigabe"
+		},
+		"mdm-filerelease-display": {
+			"lbl-error-message": "Fehlerbericht",
+			"lbl-expires-on": "Freigegeben bis",
+			"lbl-reason-for-declining": "Begründung für Ablehnung",
+			"lbl-reason-for-release": "Begründung für Freigabe",
+			"lbl-requested-by": "Antragsteller",
+			"lbl-state": "Status",
+			"lbl-test-name": "Versuchsname",
+			"lbl-test-responsible-person": "Messungsverantwortlicher",
+			"lbl-validity": "Freigabedauer",
+			"tlbl-format": "Format"
 		}
 	},
 	"modules": {
@@ -444,14 +490,6 @@
 			"mdm-search": "MDM Suche"
 		}
 	},
-	"navigator-view": {
-		"mdm-navigator-view": {
-			"err-cannot-update-node-provider": "Nodeprovider kann nicht aktualisiert werden.",
-			"navigator": "Navigator",
-			"select-node-provider": "Baumdarstellung auswählen",
-			"tooltip-scroll-up": "Zum Seitenanfang"
-		}
-	},
 	"navigator": {
 		"attribute-value": {
 			"msg-no-files-attached": "Keine Dateien angehangen",
@@ -459,6 +497,13 @@
 			"msg-x-files-attached": "{{numberOfFiles}} Dateien angehangen"
 		},
 		"mdm-navigator": {
+			"add-measurement": "Messergebnis",
+			"add-test": "Versuch",
+			"add-teststep": "Versuchsschritt",
+			"add-to-chart-viewer": "In Chartviewer anfügen",
+			"add-to-mdmtag": "Zu MDMTag hinzufügen",
+			"add-to-shopping-basket": "In Warenkorb legen",
+			"copy-link": "Link kopieren",
 			"err-cannot-find-node-in-navigation-tree": "Knoten kann nicht im Navigationsbaum gefunden werden.",
 			"err-cannot-load-nodes": "Knoten können nicht geladen werden.",
 			"err-cannot-open-node": "Knoten kann nicht geöffnet werden.",
@@ -467,8 +512,26 @@
 			"err-status-setting": "Beim Setzen des Status ist ein Fehler aufgetreten",
 			"loading-subordinate-items": "Unterpunkte werden geladen...",
 			"msg-item-type-not-supported": "'Dieser Knotentyp wird von der aktuellen Ansicht nicht angezeigt!",
+			"refresh-all-navigator": "Alles Aktualisieren",
+			"refresh-navigator": "Aktualisieren",
 			"set-status": "Status setzen",
-			"set_status-done": "Das Setzen des Status ist abgeschlossen."
+			"set_status-done": "Das Setzen des Status ist abgeschlossen.",
+			"set_status-in-progress": "Das Setzen des Status ist angestossen."
+		},
+		"navigator": {
+			"err-cannot-set-item": "Item konnte nicht gesetzt werden."
+		},
+		"nodeprovider": {
+			"err-cannot-load-node-provider-from-settings": "Nodeprovider kann nicht aus den Einstellungen geladen werden.",
+			"err-unsupported-type": "Typ {{ type }} wird nicht unterstützt! Es sollte Typ {{ typeToUse }} verwendet werden."
+		}
+	},
+	"navigator-view": {
+		"mdm-navigator-view": {
+			"err-cannot-update-node-provider": "Nodeprovider kann nicht aktualisiert werden.",
+			"navigator": "Navigator",
+			"select-node-provider": "Baumdarstellung auswählen",
+			"tooltip-scroll-up": "Zum Seitenanfang"
 		}
 	},
 	"search": {
@@ -522,6 +585,7 @@
 			"search-filter-name": "Filtername",
 			"search-filter-sources": "Fehlende Quelle",
 			"search-filter-sources-details": "Für die Suche ist mindestens eine Datenquelle auzuwählen.",
+			"select-search-filter": "Suchfilter auswählen",
 			"suggestion-value": "Suchwert",
 			"title-save-search-filter-as": "Suchfilter speichern unter",
 			"tooltip-add-selection-to-shopping-basket": "Auswahl zum Warenkorb hinzufügen",
@@ -532,13 +596,19 @@
 			"tooltip-edit-search-filter": "Suchattribute auswählen",
 			"tooltip-enable-advanced-search": "Erweiterte Suche aktivieren",
 			"tooltip-global-search-attributes": "Globale Suchattribute sind Attribute, die in allen ausgewählten Datenquellen vorhanden sind. Global Suchattribute werden nur einmal dargestellt und die definierte Bedingung wird in allen Datenquellen angewendet.",
+			"tooltip-link-search-attributes-to-navigator": "Suchattribute an den Navigator koppeln.",
 			"tooltip-local-search-attributes": "Suchattribute, die nicht in allen Datenquellen verfügbar sind, sondern nur in der aktuellen Datenquelle.",
 			"tooltip-no-name-set": "Name nicht gesetzt!",
 			"tooltip-remove-search-attributes": "Alle Suchattribute entfernen",
 			"tooltip-reset-search-conditions": "Suchkriterien zurücksetzen",
 			"tooltip-save-search-filter": "Suchfilter speichern",
 			"tooltip-search-text": "Mögliche Operatoren:\n+ steht für einen UND Operator, z.B. findet 'XY + 20.07.2021' nur Ergebnisse, die sowohl 'XY' als auch das Datum '20.07.2021' enthalten.\n| steht für einen ODER Operator, z.B. findet 'XY | 20.07.2021' alle Ergebnisse, die entweder 'XY' oder '20.07.2021' oder beide Terme enthalten.\n- negiert einen einzelnen Term, z.B. findet '-20.07.2021' alle Ergebnisse, die dieses Datum nicht enthalten.\n\" fasst eine Menge von Termen zu einer Phrase zusammen, z.B. findet die Suche nach \"noch zu prüfen\" alle Ergebnisse, die genau diese Phrase enthalten.\n* am Ende eines Suchterms beschreibt eine Präfixsuche, z.B. findet die Suche nach 'xy*' alle Ergebnisse, die nach 'xy' weitere Terme enthalten.\n( und ) beschreibt die Operatorpräferenz, z.B. wertet die Suche '(X + Y) | (A + B)' erst die geklammerten Ausdrück aus und danach den ODER-Operator.\n~N nach einem Wort beschreibt den Editierabstand (Unschärfe), z.B. 'Messergebnis ~2' findet auch Wörter, in denen zwei Buchstaben in anderer Reihenfolge enthalten sind ('Messegrebins').\n~N nach einer Phrase beschreibt den Wortabstand, z.B. 'noch zu prüfen ~1' findet auch Phrasen, in denen ein Wort an falscher Stelle steht ('zu prüfen noch').\n\nWenn nach einem der Spezialsymbole gesucht werden soll, müssen diese mit \\ escaped werden, z.B. die Suche nach einem Term, der * enthält: 'Test\\*'.",
-			"tooltip-select-sources": "Quellen auswählen"
+			"tooltip-select-sources": "Quellen auswählen",
+			"tooltip-unlink-search-attributes-from-navigator": "Suchattributen vom Navigator entkoppeln."
+		},
+		"search": {
+			"err-cannot-load-preference-for-attributes-to-ignore": "Einstellung für zu ignorierende Attribute kann nicht geladen werden.",
+			"err-faulty-preference-for-attributes-to-ignore": "Einstellung für zu ignorierende Attribute ist fehlerhaft."
 		},
 		"search-condition": {
 			"and": "und",
@@ -549,9 +619,9 @@
 			"single-value-input": "Bitte einen Wert für Suchattribute eingeben. Die Eingabe von mehreren Werten ist nicht möglich.\n\nMögliche Wildcards:\n'?' für genau ein beliebiges Zeichen, z.B. findet die Suche nach Version '1.?' alle Ergebnisse mit genau einem Zeichen nach dem Punkt.\n'*' für eine beliebige Zeichenkette, z.B. findet die Suche nach Version '1.*' alle Ergebnisse mit beliebigen Zeichenketten nach dem Punkt.",
 			"tooltip-select-search-operator": "Suchoperator auswählen"
 		},
-		"search": {
-			"err-cannot-load-preference-for-attributes-to-ignore": "Einstellung für zu ignorierende Attribute kann nicht geladen werden.",
-			"err-faulty-preference-for-attributes-to-ignore": "Einstellung für zu ignorierende Attribute ist fehlerhaft."
+		"search-datepicker": {
+			"placeholder-dateformat": "TT.MM.JJJJ HH:MM",
+			"tooltip-select-date": "Datum auswählen"
 		}
 	},
 	"tableview": {
@@ -606,4 +676,4 @@
 			"ttl-confirmation": "Bestätigung"
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/nucleus/webclient/src/main/webapp/src/assets/i18n/en.json b/nucleus/webclient/src/main/webapp/src/assets/i18n/en.json
index 8f0057f..547bb0e 100644
--- a/nucleus/webclient/src/main/webapp/src/assets/i18n/en.json
+++ b/nucleus/webclient/src/main/webapp/src/assets/i18n/en.json
@@ -15,6 +15,7 @@
 			"btn-cancel": "Cancel",
 			"btn-save": "Save",
 			"err-cannot-load-data-source": "Cannot load data source.",
+			"err-cannot-load-scope": "Cannot load scope.",
 			"lbl-key": "Key",
 			"lbl-scope": "Scope",
 			"lbl-source": "Source",
@@ -33,8 +34,10 @@
 			"component-name": "Component name",
 			"component-type": "Component type",
 			"description": "Description",
+			"dialog-ext-system-attr-title": "External system attribute",
 			"dialog-ext-system-delete-text": "Please confirm the deletion of the external system",
 			"dialog-ext-system-delete-title": "External system deletion",
+			"dialog-ext-system-mdm-attr-title": "MDM attribute",
 			"dialog-ext-system-title": "External system",
 			"dropdown-please-select": "Please select...",
 			"err-cannot-load-comp-types": "Cannot load component types",
@@ -45,6 +48,7 @@
 			"ext-system-attributes": "Ext. system attributes",
 			"loading": "Loading data...",
 			"loading-attributes": "Loading attributes...",
+			"loading-short": "Loading",
 			"mdm-attributes": "MDM attributes",
 			"name": "Name",
 			"select-system": "Select environment",
@@ -67,6 +71,7 @@
 			"btn-cancel": "Cancel",
 			"btn-copy": "Copy",
 			"btn-del": "Delete",
+			"btn-edit": "Edit",
 			"btn-new-version": "Create new version",
 			"btn-save": "Save",
 			"btn-valid": "Set valid",
@@ -88,6 +93,9 @@
 			"select-system": "Select environment",
 			"selected-system": "Selected environment",
 			"status": "Status",
+			"status-lbl-archived": "Archived",
+			"status-lbl-editable": "Editing",
+			"status-lbl-valid": "Valid",
 			"txt-copy-of": "Copy{0}Of",
 			"unit": "Unit",
 			"version": "Version"
@@ -97,6 +105,7 @@
 			"btn-cancel": "Cancel",
 			"btn-copy": "Copy",
 			"btn-del": "Remove",
+			"btn-edit": "Edit",
 			"btn-save": "Save",
 			"db": "dB",
 			"db-ref-factor": "dB Ref.-Factor",
@@ -112,6 +121,7 @@
 			"err-cannot-update-unit": "Unit could not be saved",
 			"factor": "Factor",
 			"loading": "Loading data...",
+			"loading-short": "Loading",
 			"name": "Name",
 			"offset": "Offset",
 			"phys-dim": "Phys. Dimension",
@@ -122,6 +132,15 @@
 	},
 	"app": {
 		"about": "About",
+		"datasources": "Datasource",
+		"dialog-preference-datasources": {
+			"btnselect": "Apply",
+			"btntitle": "Default datasources",
+			"choose": "choose",
+			"column-header": "Datasources",
+			"title": "Select default datasources",
+			"x-datasources-selected": "{0} datasources"
+		},
 		"language": "Language",
 		"logout": "Logout",
 		"roles": "Roles"
@@ -163,12 +182,14 @@
 	"chartviewer": {
 		"chart": "Chart",
 		"chart-viewer-nav-card": {
+			"channel-linked-to-multiple-channel-groups": "Cannot display data for channel {{channelname}} as it is linked to multiple channel groups.",
 			"load-missing-channels": "Load {{limit}} channels ({{offset}}/{{total}})"
 		},
 		"request-options": {
 			"apply": "Apply",
 			"from": "from",
 			"options": "Options",
+			"overall": "overall",
 			"preview-values": "preview values",
 			"reset": "Reset",
 			"step-size": "step size",
@@ -183,9 +204,13 @@
 		"table": "Table",
 		"x-axis": "X-axis",
 		"xy-chart-data-selection-panel": {
+			"all-results": "All",
 			"apply": "Apply",
 			"cancel": "Cancel",
+			"default-result-limit": "Default",
 			"filter": "Filter",
+			"manual-result-limit": "Maunal",
+			"measurement": "Measurement",
 			"no-x-channel-dialog-header": "Information",
 			"no-x-channel-dialog-message": "The current ChannelGroup has no Channels defined as X-axis or XY-axis. If you want to also allow Channels marked as Y-axis, toggle the corresponding filter in the toolbar.",
 			"result-limit": "Maximum number of results",
@@ -195,14 +220,27 @@
 			"tooltip-regexp-filter": "Regular expressions are enabled for filtering.",
 			"y-channel-query-config-editor": "Query config for Y-Channels"
 		},
+		"xy-chart-viewer": {},
 		"xy-chart-viewer-nav-card": {
 			"no-node-selected": "No node selected"
 		},
 		"xy-chart-viewer-toolbar": {
 			"absolute-drawing": "Absolute",
+			"activate-xy-mode": "Filter channel options by axis-type",
+			"clear-area": "Clear area underneath the graph",
+			"deactivate-xy-mode": "Provide all channel options",
+			"fill-area": "Fill area underneath the graph",
+			"hide-chart-legend": "Hide chart legend",
+			"hide-data-selection-panel": "Hide data selection panel",
+			"hide-datapoints": "Hide datapoints",
+			"hide-lines": "Hide lines",
 			"line-width": "Line width",
 			"open-popup": "Open Popup",
 			"relative-drawing": "Relative",
+			"show-chart-legend": "Show chart legend",
+			"show-data-selection-panel": "Show data selection panel",
+			"show-datapoints": "Mark datapoints",
+			"show-lines": "Draw lines",
 			"tension": "Line tension: 0 = linear, 0.4 = Bezier curve"
 		},
 		"y-axis": "Y-axis"
@@ -272,6 +310,14 @@
 			"err-cannot-load-preference-for-attributes-to-ignore": "Cannot load preference for attributes to ignore.",
 			"err-faulty-preference-for-attributes-to-ignore": "Faulty preference for attributes to ignore."
 		},
+		"mdm-detail": {
+			"general": "General",
+			"parametersets": "Parametersets",
+			"sensors": "Sensors",
+			"test-equipment": "Test equipment",
+			"test-sequence": "Test sequence",
+			"unit-under-test": "Unit under test"
+		},
 		"mdm-detail-descriptive-data": {
 			"btn-cancel": "Cancel",
 			"btn-edit": "Edit",
@@ -293,6 +339,7 @@
 		"mdm-detail-panel": {
 			"btn-into-shopping-basket": "Into shopping basket",
 			"btn-show-in-tree": "Show in tree",
+			"cannot-update-node": "Cannot update node.",
 			"tblhdr-attribute": "Attribute",
 			"tblhdr-unit": "Unit",
 			"tblhdr-value": "Value"
@@ -300,13 +347,9 @@
 		"mdm-detail-view": {
 			"cannot-update-node": "Cannot update node."
 		},
-		"mdm-detail": {
-			"general": "General",
-			"parametersets": "Parametersets",
-			"sensors": "Sensors",
-			"test-equipment": "Test equipment",
-			"test-sequence": "Test sequence",
-			"unit-under-test": "Unit under test"
+		"parameterset": {
+			"err-cannot-load-data": "Cannot load data.",
+			"status-no-parametersets": "No parametersets available."
 		},
 		"parameterset-panel": {
 			"btn-cancel-parameterset": "Abbrechen",
@@ -317,13 +360,10 @@
 			"tblhdr-unit": "Unit",
 			"tblhdr-value": "Value"
 		},
-		"parameterset": {
-			"err-cannot-load-data": "Cannot load data.",
-			"status-no-parametersets": "No parametersets available."
-		},
 		"sensor": {
 			"err-cannot-load-data": "Cannot load data.",
 			"err-cannot-load-descriptive-data": "Cannot load descriptive data.",
+			"err-cannot-load-scope": "Cannot load scope.",
 			"status-loading": "Loading...",
 			"status-no-descriptive-data-available": "No descriptive data available.",
 			"status-no-nodes-available": "No nodes available.",
@@ -351,6 +391,7 @@
 			"btn-refresh": "Update",
 			"btn-remove-all-files-from-selection": "Clean file selection",
 			"btn-remove-file-from-selection": "Remove file from selection",
+			"btn-upload-file": "Upload file",
 			"btn-upload-file-selection": "Upload selected files",
 			"btn-upload-files": "Upload files",
 			"hdr-description": "Description",
@@ -358,19 +399,24 @@
 			"hdr-filename": "Filename",
 			"hdr-size": "Size",
 			"hdr-type": "Type",
-			"msg-confirm-delete-file-from-db": "Are you sure you want to delete the selected file from the database?",
+			"msg-confirm-delete-file-from-db": "Are you sure you want to delete the selected file from database?",
 			"msg-no-files-attached": "No files attached.",
 			"ttl-attached-to": "Files attached to: ",
 			"ttl-confirmation": "Confirmation"
 		},
+		"file-explorer-nav-card": {
+			"status-no-node-selected": "No node selected.",
+			"status-node-is-no-files-attachable": "It is not possible to attach files to {{type}}s.",
+			"status-virtual-node-selected": "Virtual node selected."
+		},
+		"file-link-editor": {
+			"hdr-file-upload-wizard": "File upload wizard for {{name}}"
+		},
 		"file-link-editor-dialog": {
 			"btn-cancel": "Cancel",
 			"btn-change-file": "Change file",
 			"btn-save-changes": "Save"
 		},
-		"file-link-editor": {
-			"hdr-file-upload-wizard": "File upload wizard for {{name}}"
-		},
 		"file-link-sequence-editor": {
 			"hdr-file-upload-wizard": "File upload wizard for {{name}}"
 		},
@@ -393,27 +439,6 @@
 			"state-release-processing-error": "processing error",
 			"state-release-released": "released"
 		},
-		"mdm-filerelease-create": {
-			"btn-release-request": "Release request",
-			"btn-send": "Send",
-			"err-cannot-create-release": "Cannot create release.",
-			"lbl-format": "Format",
-			"lbl-reason": "Reason",
-			"lbl-validity-days": "Validity (days)",
-			"title-release": "Release"
-		},
-		"mdm-filerelease-display": {
-			"lbl-error-message": "Error message",
-			"lbl-expires-on": "Expires on",
-			"lbl-reason-for-declining": "Reson for declining",
-			"lbl-reason-for-release": "Reason for release",
-			"lbl-requested-by": "Requested by",
-			"lbl-state": "Status",
-			"lbl-test-name": "Test name",
-			"lbl-test-responsible-person": "Responsible person for test",
-			"lbl-validity": "Validity",
-			"tlbl-format": "Format"
-		},
 		"mdm-filerelease": {
 			"btn-approve": "Approve",
 			"btn-cancel": "Cancel",
@@ -435,6 +460,27 @@
 			"tblhdr-status": "Status",
 			"tblhdr-test-name": "Test name",
 			"tblhdr-test-responsible-person": "Responsible person for test"
+		},
+		"mdm-filerelease-create": {
+			"btn-release-request": "Release request",
+			"btn-send": "Send",
+			"err-cannot-create-release": "Cannot create release.",
+			"lbl-format": "Format",
+			"lbl-reason": "Reason",
+			"lbl-validity-days": "Validity (days)",
+			"title-release": "Release"
+		},
+		"mdm-filerelease-display": {
+			"lbl-error-message": "Error message",
+			"lbl-expires-on": "Expires on",
+			"lbl-reason-for-declining": "Reson for declining",
+			"lbl-reason-for-release": "Reason for release",
+			"lbl-requested-by": "Requested by",
+			"lbl-state": "Status",
+			"lbl-test-name": "Test name",
+			"lbl-test-responsible-person": "Responsible person for test",
+			"lbl-validity": "Validity",
+			"tlbl-format": "Format"
 		}
 	},
 	"modules": {
@@ -444,14 +490,6 @@
 			"mdm-search": "MDM Search"
 		}
 	},
-	"navigator-view": {
-		"mdm-navigator-view": {
-			"err-cannot-update-node-provider": "Cannot update node provider.",
-			"navigator": "Navigator",
-			"select-node-provider": "Select tree view",
-			"tooltip-scroll-up": "Top of page"
-		}
-	},
 	"navigator": {
 		"attribute-value": {
 			"msg-no-files-attached": "No files attached",
@@ -459,6 +497,13 @@
 			"msg-x-files-attached": "{{numberOfFiles}} files attached"
 		},
 		"mdm-navigator": {
+			"add-measurement": "Measurement",
+			"add-test": "Test",
+			"add-teststep": "Teststep",
+			"add-to-chart-viewer": "Add to chart viewer",
+			"add-to-mdmtag": "Add to MDMTag",
+			"add-to-shopping-basket": "Add to shopping basket",
+			"copy-link": "Copy link",
 			"err-cannot-find-node-in-navigation-tree": "Cannot find node in navigation tree.",
 			"err-cannot-load-nodes": "Cannot load nodes.",
 			"err-cannot-open-node": "Cannot open node.",
@@ -467,8 +512,26 @@
 			"err-status-setting": "Cannot set the status.",
 			"loading-subordinate-items": "Loading subordinate items...",
 			"msg-item-type-not-supported": "This node type is not supported by the current view!",
+			"refresh-all-navigator": "Refresh all",
+			"refresh-navigator": "Refresh",
 			"set-status": "Set Status",
-			"set_status-done": "Status setting completed."
+			"set_status-done": "Status setting completed.",
+			"set_status-in-progress": "Status setting in progress."
+		},
+		"navigator": {
+			"err-cannot-set-item": "Cannot set item."
+		},
+		"nodeprovider": {
+			"err-cannot-load-node-provider-from-settings": "Cannot load node provider from settings",
+			"err-unsupported-type": "Type {{ type }} is not supported. Type {{ typeToUse }} should be used instead."
+		}
+	},
+	"navigator-view": {
+		"mdm-navigator-view": {
+			"err-cannot-update-node-provider": "Cannot update node provider.",
+			"navigator": "Navigator",
+			"select-node-provider": "Select tree view",
+			"tooltip-scroll-up": "Top of page"
 		}
 	},
 	"search": {
@@ -522,6 +585,7 @@
 			"search-filter-name": "Filter name",
 			"search-filter-sources": "Missing source",
 			"search-filter-sources-details": "At least 1 source must be selected for searching.",
+			"select-search-filter": "Select search filter",
 			"suggestion-value": "Search value",
 			"title-save-search-filter-as": "Save search filter as",
 			"tooltip-add-selection-to-shopping-basket": "Add selection to shopping basket",
@@ -532,13 +596,19 @@
 			"tooltip-edit-search-filter": "Choose search attributes",
 			"tooltip-enable-advanced-search": "Enable advanced search",
 			"tooltip-global-search-attributes": "Global search attributes are attributes present in all data sources selected. Global search attributes are displayed only once and the condition defined in them is applied to all data sources.",
+			"tooltip-link-search-attributes-to-navigator": "Link search attribtues to the navigator.",
 			"tooltip-local-search-attributes": "Search attributes, which are not available in all data sources, but only in the current data source.",
 			"tooltip-no-name-set": "No name set!",
 			"tooltip-remove-search-attributes": "Remove all search attributes",
 			"tooltip-reset-search-conditions": "Reset search conditions",
 			"tooltip-save-search-filter": "Save search filter",
 			"tooltip-search-text": "Operators available:\n+ represents an AND operator\n| represents an OR operator\n- negates a single term\n\" combines a set of terms into a phrase\n* at the end of a search term describes a prefix search\n( and ) describe the operator preference\n~N after a word describes the edit distance (fuzziness)\n~N after a phrase describes the word distance\n\nIf one of the special symbols is to be included in a search, they must be escaped with \\.",
-			"tooltip-select-sources": "Select sources"
+			"tooltip-select-sources": "Select sources",
+			"tooltip-unlink-search-attributes-from-navigator": "Unlink search attribtues from the navigator."
+		},
+		"search": {
+			"err-cannot-load-preference-for-attributes-to-ignore": "Cannot load preference for attributes to ignore.",
+			"err-faulty-preference-for-attributes-to-ignore": "Faulty preference for attributes to ignore."
 		},
 		"search-condition": {
 			"and": "and",
@@ -549,9 +619,9 @@
 			"single-value-input": "Please enter a search value. Multiple input values are not allowed.\n\nPossible wildcards are '?' for one matching character and '*' for a sequence of matching characters.",
 			"tooltip-select-search-operator": "Select search operator"
 		},
-		"search": {
-			"err-cannot-load-preference-for-attributes-to-ignore": "Cannot load preference for attributes to ignore.",
-			"err-faulty-preference-for-attributes-to-ignore": "Faulty preference for attributes to ignore."
+		"search-datepicker": {
+			"placeholder-dateformat": "DD.MM.YYYY HH:MM",
+			"tooltip-select-date": "Select date"
 		}
 	},
 	"tableview": {
@@ -593,7 +663,7 @@
 			"err-deleting-view": "An error has occurred when deleting the view.",
 			"err-saving-view": "An error has occurred when saving the view.",
 			"existing-view-names": "Existing view names",
-			"msg-confirm-delete-view-from-db": "Are you sure you want to delete the selected view from the database?",
+			"msg-confirm-delete-view-from-db": "Are you sure you want to delete the selected view from database?",
 			"name-placeholder": "view name",
 			"new-view": "New view",
 			"title-save-view-as": "Save view as",
@@ -606,4 +676,4 @@
 			"ttl-confirmation": "Confirmation"
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/release_notes.md b/release_notes.md
index 77ae53b..b58856a 100644
--- a/release_notes.md
+++ b/release_notes.md
@@ -8,12 +8,15 @@
 
 ### Features ###
 
+* Selection dialog for connected datasources
 * Support Unit and Quantity in web client
 * Support for Tags
 * Support for ParameterSets
 * User guide available
 
 ### API changes ###
+* service.xml schema changed: tag <service> has a new attribute 'sourceName'. Make sure to update your existing service.xml.
+
 tbd
 
 ### Changes ###
@@ -26,6 +29,7 @@
 * [572514](https://bugs.eclipse.org/bugs/show_bug.cgi?id=572514) - Implemented support for ParameterSets
 * [577547](https://bugs.eclipse.org/bugs/show_bug.cgi?id=577547) - Add enpoints assigning and retrieve TemplateMeasurements for a TemplateTestStep
 * [577548](https://bugs.eclipse.org/bugs/show_bug.cgi?id=577548) - Add support to assign Files to a TemplateAttribute
+* [578740](https://bugs.eclipse.org/bugs/show_bug.cgi?id=578740) - Add selection dialog for connected datasources
 
 ### Bugzilla Bugs fixed ###
 * [577083](https://bugs.eclipse.org/bugs/show_bug.cgi?id=577083) - ATFx-Adapter throws IndexOutOfBoundsException for ATFx-Files containing Quantities without the optional Unit