Merge remote-tracking branch 'origin/master' into anehmer/integration
diff --git a/NOTICE.txt b/NOTICE.txt
index 5de48b2..56281c6 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -16,14 +16,15 @@
 For more information regarding authorship of content, please consult the listed
 source code repository logs.
 
-Copyright (c) 2016-2018 Gigatronik Ingolstadt GmbH
-Copyright (c) 2016-2019 Peak Solution GmbH
+Copyright (c) 2016-2019 Gigatronik Ingolstadt GmbH
+Copyright (c) 2016-2020 Peak Solution GmbH
 Copyright (c) 2017-2018 science + computing AG Tuebingen (ATOS SE)
 Copyright (c) 2017-2018 Canoo Engineering AG
 Copyright (c) 2017 Florian Schmitt
-Copyright (c) 2017-2019 Angelika Wittek
-Copyright (c) 2018 Elektronische Fahrwerksysteme GMBH
-Copyright (c) 2018-2019 Karakun AG
+Copyright (c) 2017-2020 Angelika Wittek
+Copyright (c) 2018-2019 Elektronische Fahrwerksysteme GMBH
+Copyright (c) 2018-2020 Karakun AG
+Copyright (c) 2018-2020 Alexander Nehmer
 
 ## Declared Project Licenses
 
@@ -37,7 +38,7 @@
 
 The project maintains the following source code repositories:
 
-org.eclipse.mdm.api.base.git	      - The openMDM(R) API.
+org.eclipse.mdm.api.base.git	    - The openMDM(R) API.
 org.eclipse.mdm.api.default.git	    - Extension of the openMDM(R) API containing default elements.
 org.eclipse.mdm.api.odsadapter.git	- ODS implementation of persistence adapter.
 org.eclipse.mdm.nucleus.git	        - Core building blocks for the openMDM Business Logic and Web Frontend.
@@ -67,9 +68,6 @@
 commons-text-1.6.jar (1.6)
     * License: Apache License, 2.0
 
-commons-math-2.2.jar (2.2)
-    * License: Apache License, 2.0
-
 gson-2.7.jar (2.7)
     * License: Apache License, 2.0
 
@@ -85,7 +83,7 @@
 hk2-locator-2.5.0-b05.jar(2.5.0-b05)
     * License: CDDL
 
-hk2-utils-2.5.0-b05.jar  (2.5.0-b05)
+hk2-utils-2.5.0-b05.jar (2.5.0-b05)
     * License: CDDL
 
 jackson-annotations-2.9.0.jar  (2.9.0)
@@ -151,6 +149,9 @@
 logback-core-1.2.3.jar(1.2.3)
     * License: Eclipse Public License 1.0
 
+mimepull-1.9.6.jar (1.9.4)
+    * License: CDDL
+
 openatfx-0.7.4.jar (0.7.4)
     * License: Apache-2.0
 
@@ -163,18 +164,30 @@
 protobuf-java-util-3.2.0.jar  (3.2.0)
     * License: New BSD license
 
+swagger-annotations-2.0.8.jar (2.0.8)
+    * License: Apache-2.0
+
+swagger-ui-3.23.0.jar (3.23.0)
+    * License: Apache-2.0
+
 slf4j-api-1.7.25.jar  (1.7.25)
     * License: MIT license
     * Licence Path: https://www.slf4j.org/license.html
     * Project URL: https://github.com/qos-ch/slf4j
     * Source URL:  https://github.com/qos-ch/slf4j/releases/tag/v_1.7.25
 
+stax2-api-3.1.4.jar (3.1.4)
+    * License: BSD-2-Clause
+
 validation-api-1.1.0.Final.jar (1.1.0.Final)
   * License: Apache License, 2.0
 
 vavr-0.9.1-sources.jar (0.9.1)
   * License: Apache License, 2.0
 
+vavr-match-0.9.1.jar (0.9.1)
+  * License: Apache License, 2.0
+
 woodstox-core-asl-4.4.1.jar (4.4.1)
   * License: Apache License, 2.0
 
@@ -288,6 +301,18 @@
     * Project: https://valor-software.com/ngx-bootstrap
     * Source:  https://github.com/valor-software/ngx-bootstrap/tree/v3.1.2
 
+@ngx-translate/core@11.0.1
+    * License: MIT 
+    * Licence Path:   https://github.com/ngx-translate/core/blob/v11.0.1/LICENSE  
+    * Project URL:    http://www.ngx-translate.com/
+    * Source URL:     https://github.com/ngx-translate/core
+
+@ngx-translate/http-loader@4.0.0
+    * License: MIT 
+    * Licence Path:   https://github.com/ngx-translate/http-loader/blob/v4.0.0/LICENSE  
+    * Project URL:    http://www.ngx-translate.com/
+    * Source URL:     https://github.com/ngx-translate/http-loader/tree/v4.0.0
+
 primeicons:1.0.0
     * License: MIT
     * Licence Path: https://github.com/primefaces/primeicons/blob/1.0.0/LICENSE
@@ -300,7 +325,7 @@
     * Project: https://www.primefaces.org/primeng
     * Source:  https://github.com/primefaces/primeng/tree/7.0.1
 
-rxjs@5.1.0
+rxjs@6.3.3
     * License: Apache-2.0
     * Project: https://rxjs-dev.firebaseapp.com/
     * Source:  https://github.com/ReactiveX/rxjs/tree/6.3.3
@@ -310,6 +335,10 @@
     * Project: https://rxjs-dev.firebaseapp.com/
     * Source:  https://github.com/ReactiveX/rxjs/tree/6.3.3/compat
 
+tslib@1.9.0
+    * License: Apache-2.0
+    * Project: https://github.com/Microsoft/tslib
+    * Source:  https://github.com/Microsoft/tslib/tree/1.9.0
 
 zone.js@0.8.26
     * License: MIT
@@ -330,17 +359,12 @@
 * Source: https://www.omg.org/spec/NOT/1.1/PDF
 
 ods530.idl
-Permission of use:
-From Hans-Georg Swolana, Chairman of the Board ASAM e.V.,
- Prof. Dr. Marcus Rieker, Member of the Board ASAM e.V.
 Date: Hoehenkirchen, 06/01/2016
 "The ASAM Board of Directors releases the IDL files for use under the EPL to the Eclipse IWG openMDM.
 This is valid for all versions of ASAM ODS 5.3.x.
 This permission is valid under the conditions of Eclipse will not modify the file."
 
 AvalonEvent.idl, CorbaFileServer.idl
-Permission of use:
-From Dr. Ralph Noerenberg
 Date: 08/15/2016
 "Herewith, we release the generated Client-Source-Code generated from our CORBA IDLs, namely
 * CORBANotification Service (generated from „AvalonEvent.idl”)
diff --git a/build.gradle b/build.gradle
index 735575a..240391c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -14,7 +14,7 @@
 
 description = 'MDM API - ODSAdapter'
 group = 'org.eclipse.mdm'
-version = '5.1.0M7'
+version = '5.1.0M8'
 
 apply plugin: 'java'
 apply plugin: 'maven'
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java
index f01c859..527a186 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/ODSEntityManager.java
@@ -44,6 +44,8 @@
 import org.eclipse.mdm.api.base.model.Environment;
 import org.eclipse.mdm.api.base.model.MeasuredValues;
 import org.eclipse.mdm.api.base.model.StatusAttachable;
+import org.eclipse.mdm.api.base.model.Test;
+import org.eclipse.mdm.api.base.model.TestStep;
 import org.eclipse.mdm.api.base.model.User;
 import org.eclipse.mdm.api.base.query.DataAccessException;
 import org.eclipse.mdm.api.base.query.Filter;
@@ -55,9 +57,12 @@
 import org.eclipse.mdm.api.dflt.EntityManager;
 import org.eclipse.mdm.api.dflt.model.Classification;
 import org.eclipse.mdm.api.dflt.model.Status;
+import org.eclipse.mdm.api.dflt.model.TemplateTest;
+import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
 import org.eclipse.mdm.api.odsadapter.filetransfer.Transfer;
 import org.eclipse.mdm.api.odsadapter.lookup.EntityLoader;
 import org.eclipse.mdm.api.odsadapter.lookup.config.EntityConfig.Key;
+import org.eclipse.mdm.api.odsadapter.query.ODSEntityFactory;
 import org.eclipse.mdm.api.odsadapter.query.ODSEntityType;
 import org.eclipse.mdm.api.odsadapter.query.ODSModelManager;
 import org.eclipse.mdm.api.odsadapter.transaction.ODSTransaction;
@@ -443,4 +448,20 @@
 
 		return linkMap;
 	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<TemplateTest> loadTemplate(Test test) {
+		return Optional.of(ODSEntityFactory.extract(test).getMutableStore().get(TemplateTest.class));
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public Optional<TemplateTestStep> loadTemplate(TestStep testStep) {
+		return Optional.of(ODSEntityFactory.extract(testStep).getMutableStore().get(TemplateTestStep.class));
+	}
 }
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileServer.java b/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileServer.java
index bb54a03..d92c9b5 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileServer.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/filetransfer/CORBAFileServer.java
@@ -23,6 +23,7 @@
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
@@ -67,6 +68,7 @@
 	private static final int DEFAULT_BUFFER_SIZE = 100_000;
 	private static final int SOCKET_TIMEOUT = 5_000;
 	private static final String INTERFACE_NAME_PROPERTY = "org.eclipse.mdm.api.odsadapter.filetransfer.interfaceName";
+	private static final String HOST_NAME_PROPERTY = "org.eclipse.mdm.api.odsadapter.filetransfer.hostname";
 
 	private final CORBAFileServerIF fileServer;
 	private final AoSession aoSession;
@@ -207,8 +209,8 @@
 					 * socket's accept method is called, the registration is done asynchronously!
 					 */
 					fileServer.getForInstanceBySocket(aoSession, fileLink.getRemotePath(), elemId.aid, elemId.iid,
-							InetAddress.getLocalHost().getHostAddress(), serverSocket.getLocalPort());
-				} catch (CORBAFileServerException | IOException e) {
+							serverSocket.getInetAddress().getHostAddress(), serverSocket.getLocalPort());
+				} catch (CORBAFileServerException e) {
 					LOGGER.error("Unable to initialize socket stream, awaiting socket timeout.", e);
 				}
 			}).start();
@@ -220,6 +222,17 @@
 	}
 
 	private InetAddress getInterfaceAddress() throws SocketException {
+		String hostnameProperty = System.getProperty(HOST_NAME_PROPERTY);
+		if (!StringUtils.isEmpty(hostnameProperty)) {
+			LOGGER.debug("Using host name '" + hostnameProperty + "' for file transfer.");
+			try {
+				return InetAddress.getByName(hostnameProperty);
+			} catch (UnknownHostException e) {
+				LOGGER.warn("Specified host name '" + hostnameProperty + "' cannot be used for file transfer.", e);
+				// continue with lookup by interface name
+			}
+		}
+
 		String property = System.getProperty(INTERFACE_NAME_PROPERTY);
 		if (StringUtils.isEmpty(property)) {
 			LOGGER.debug("Using no specified interface for file transfer, property not set.");
@@ -321,7 +334,7 @@
 			}).start();
 
 			int localPort = serverSocket.getLocalPort();
-			String localHostName = serverSocket.getInetAddress().getHostName();
+			String localHostName = serverSocket.getInetAddress().getHostAddress();
 			try {
 				return fileServer.saveForInstanceBySocket(aoSession, fileLink.getFileName(), "", elemId.aid, elemId.iid,
 						localHostName, localPort);
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRecord.java b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRecord.java
index 0d31655..b25e997 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRecord.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRecord.java
@@ -48,4 +48,14 @@
 		this.core = core;
 	}
 
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return "EntityRecord [core=" + core + ", entity=" + entity + "]";
+	}
+
 }
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRequest.java b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRequest.java
index 092f60c..27e7f6d 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRequest.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/EntityRequest.java
@@ -198,7 +198,8 @@
 			if (!relationConfig.dependants.isEmpty()) {
 				// this may occur if the instance id of the related entity
 				// is defined, but the entity itself does not exist
-				throw new IllegalStateException("Unable to load related entities.");
+				throw new IllegalStateException(
+						"Unable to load related entities: " + relationConfig.dependants.toString());
 			}
 		}
 	}
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
index ae94376..adbf57e 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/lookup/config/DefaultEntityConfigRepositoryLoader.java
@@ -39,9 +39,13 @@
 import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
 import org.eclipse.mdm.api.dflt.model.CatalogComponent;
 import org.eclipse.mdm.api.dflt.model.CatalogSensor;
+import org.eclipse.mdm.api.dflt.model.Classification;
+import org.eclipse.mdm.api.dflt.model.Domain;
 import org.eclipse.mdm.api.dflt.model.Pool;
 import org.eclipse.mdm.api.dflt.model.Project;
+import org.eclipse.mdm.api.dflt.model.ProjectDomain;
 import org.eclipse.mdm.api.dflt.model.Role;
+import org.eclipse.mdm.api.dflt.model.Status;
 import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
 import org.eclipse.mdm.api.dflt.model.TemplateComponent;
 import org.eclipse.mdm.api.dflt.model.TemplateRoot;
@@ -148,16 +152,29 @@
 		templateTestStepConfig.setComparator(Versionable.COMPARATOR);
 		entityConfigRepository.register(templateTestStepConfig);
 
-		// Status TestStep
-		// TODO check MIME type genration
-		// entityConfigRepository.register(create(new Key<>(Status.class,
-		// TestStep.class), "StatusTestStep", true));
+		// Status
+		entityConfigRepository.register(create(modelManager, new Key<>(Status.class), "Status", false));
+
+		// ProjectDomain
+		entityConfigRepository.register(create(modelManager, new Key<>(ProjectDomain.class), "ProjectDomain", false));
+
+		// Domain
+		entityConfigRepository.register(create(modelManager, new Key<>(Domain.class), "Domain", false));
+
+		// Classification
+		EntityConfig<Classification> classificationConfig = create(modelManager, new Key<>(Classification.class),
+				"Classification", false);
+		classificationConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Status.class)));
+		classificationConfig.addOptional(entityConfigRepository.findRoot(new Key<>(ProjectDomain.class)));
+		classificationConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Domain.class)));
+		entityConfigRepository.register(classificationConfig);
 
 		// TestStep
 		EntityConfig<TestStep> testStepConfig = create(modelManager, new Key<>(TestStep.class), "TestStep", true);
 		// testStepConfig.addMandatory(entityConfigRepository.findRoot(new
 		// Key<>(Status.class, TestStep.class)));
 		testStepConfig.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateTestStep.class)));
+		testStepConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Classification.class)));
 		testStepConfig.setComparator(Sortable.COMPARATOR);
 		entityConfigRepository.register(testStepConfig);
 
@@ -183,6 +200,7 @@
 		// testConfig.addMandatory(entityConfigRepository.findRoot(new
 		// Key<>(Status.class, Test.class)));
 		testConfig.addOptional(entityConfigRepository.findRoot(new Key<>(TemplateTest.class)));
+		testConfig.addOptional(entityConfigRepository.findRoot(new Key<>(Classification.class)));
 		entityConfigRepository.register(testConfig);
 
 		// ContextRoots
@@ -296,7 +314,7 @@
 	/**
 	 * Creates a new {@link EntityConfig}.
 	 *
-	 * @param <T>        The entity type.
+	 * @param            <T> The entity type.
 	 * @param key        Used as identifier.
 	 * @param typeName   Name of the associated {@link EntityType}.
 	 * @param appendName Flag indicates whether to append the entity types base name
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/EventProcessor.java b/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/EventProcessor.java
index 25b0f49..1efb5a4 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/EventProcessor.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/EventProcessor.java
@@ -43,6 +43,7 @@
 	private PeakNotificationManager odsNotificationManager;
 	private MediaType eventMediaType;
 	private boolean closeInvoked = false;
+	private boolean disconnected = false;
 
 	public EventProcessor(EventInput eventInput, NotificationListener listener,
 			PeakNotificationManager odsNotificationManager, MediaType eventMediaType) {
@@ -64,6 +65,7 @@
 					odsNotificationManager
 							.processException(new NotificationException("Inbound event input stream closed!"));
 				}
+				disconnected = true;
 				return;
 			}
 
@@ -76,9 +78,16 @@
 			} catch (ProcessingException e) {
 				odsNotificationManager
 						.processException(new NotificationException("Cannot deserialize notification event!", e));
+				disconnected = true;
 				return;
 			}
 		}
+
+		disconnected = true;
+	}
+
+	public boolean isDisconnected() {
+		return disconnected;
 	}
 
 	public void stop() {
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationManager.java b/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationManager.java
index 5c3976d..37a67b7 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationManager.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/notification/peak/PeakNotificationManager.java
@@ -18,6 +18,7 @@
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 import javax.ws.rs.client.Client;
@@ -87,6 +88,8 @@
 					.build();
 
 			endpoint = client.target(url).path("events");
+
+			Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> reconnect(), 10, 10, TimeUnit.SECONDS);
 		} catch (Exception e) {
 			throw new NotificationException("Could not create " + PeakNotificationManager.class.getName() + "!", e);
 		}
@@ -123,27 +126,7 @@
 					"Could not create registration at notification service: " + response.readEntity(String.class));
 		}
 
-		try {
-			LOGGER.info("Requesting event input for {}", registration);
-			EventInput eventInput = endpoint.path(registration).request(SseFeature.SERVER_SENT_EVENTS_TYPE)
-					.get(EventInput.class);
-
-			LOGGER.info("Received event input, starting event processor.");
-			EventProcessor processor = new EventProcessor(eventInput, listener, this, MediaType.APPLICATION_JSON_TYPE);
-
-			executor.submit(processor);
-
-			processors.put(registration, processor);
-			LOGGER.info("Event processor started.");
-		} catch (Exception e) {
-			try {
-				deregister(registration);
-			} catch (Exception ex) {
-				LOGGER.error("Exception upon deregistering!");
-			}
-			throw new NotificationException("Could not create event input stream!", e);
-		}
-
+		recreateEventStream(registration, listener);
 	}
 
 	/*
@@ -177,6 +160,55 @@
 		}
 	}
 
+	/**
+	 * Recreates the {@link EventInput}, attaches an {@link EventProcessor} to it
+	 * and stores the {@link EventProcessor} in the processors map.
+	 * 
+	 * @param registration
+	 * @param listener
+	 * @throws NotificationException
+	 */
+	private void recreateEventStream(String registration, NotificationListener listener) throws NotificationException {
+		try {
+			LOGGER.info("Requesting event input for {}", registration);
+			EventInput eventInput = endpoint.path(registration).request(SseFeature.SERVER_SENT_EVENTS_TYPE)
+					.get(EventInput.class);
+
+			LOGGER.info("Received event input, starting event processor.");
+			EventProcessor processor = new EventProcessor(eventInput, listener, this, MediaType.APPLICATION_JSON_TYPE);
+
+			executor.submit(processor);
+
+			processors.put(registration, processor);
+			LOGGER.info("Event processor started.");
+		} catch (Exception e) {
+			try {
+				deregister(registration);
+			} catch (Exception ex) {
+				LOGGER.error("Exception upon deregistering!");
+			}
+			throw new NotificationException("Could not create event input stream!", e);
+		}
+	}
+
+	/**
+	 * Checks if any registered event processor got disconnected and tries to
+	 * recreate the event stream, if necessary.
+	 */
+	private void reconnect() {
+
+		for (Map.Entry<String, EventProcessor> entry : processors.entrySet()) {
+			if (entry.getValue().isDisconnected()) {
+				try {
+					LOGGER.trace("Registration '{}' was disconnected and will be recreated.", entry.getKey());
+					recreateEventStream(entry.getKey(), entry.getValue().getListener());
+				} catch (NotificationException e) {
+					LOGGER.warn("Cannot recreate event stream for registration " + entry.getKey(), e);
+				}
+			}
+		}
+	}
+
 	private void close(String registration) {
 		if (processors.containsKey(registration)) {
 			EventProcessor processor = processors.get(registration);
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java
index 1e81b17..8a7f7f1 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSModelManager.java
@@ -33,11 +33,11 @@
 import org.asam.ods.ApplElem;
 import org.asam.ods.ApplElemAccess;
 import org.asam.ods.ApplRel;
-import org.asam.ods.ApplicationStructure;
 import org.asam.ods.ApplicationStructureValue;
 import org.asam.ods.ElemResultSetExt;
 import org.asam.ods.EnumerationAttributeStructure;
-import org.asam.ods.EnumerationDefinition;
+import org.asam.ods.EnumerationItemStructure;
+import org.asam.ods.EnumerationStructure;
 import org.asam.ods.JoinDef;
 import org.asam.ods.QueryStructureExt;
 import org.asam.ods.SelAIDNameUnitId;
@@ -388,22 +388,20 @@
 		// enumeration mappings (aeID -> (aaName -> enumClass))
 		Map<String, Map<String, Enumeration<?>>> enumClassMap = new HashMap<>();
 		EnumRegistry er = EnumRegistry.getInstance();
-		ApplicationStructure applicationStructure = aoSession.getApplicationStructure();
-		for (EnumerationAttributeStructure eas : aoSession.getEnumerationAttributes()) {
 
-			EnumerationDefinition bubu = applicationStructure.getEnumerationDefinition(eas.enumName);
-			for (String itemName : bubu.listItemNames()) {
-				final int intValue = bubu.getItem(itemName);
-				LOGGER.trace("{}:{}:{}", eas.enumName, itemName, intValue);
-			}
+		Map<String, EnumerationItemStructure[]> map = new HashMap<>();
+		for (EnumerationStructure es : aoSession.getEnumerationStructure()) {
+			map.put(es.enumName, es.items);
+		}
+
+		for (EnumerationAttributeStructure eas : aoSession.getEnumerationAttributes()) {
 
 			// make sure the enumeration is found
 			if (ODSEnumerations.getEnumObj(eas.enumName) == null) {
 				Enumeration<ODSEnum> enumdyn = new Enumeration<>(ODSEnum.class, eas.enumName);
-				EnumerationDefinition enumdef = applicationStructure.getEnumerationDefinition(eas.enumName);
-				for (String itemName : enumdef.listItemNames()) {
-					final int intValue = enumdef.getItem(itemName);
-					enumdyn.addValue(new ODSEnum(itemName, intValue));
+				for (EnumerationItemStructure enumItemStruct : map.get(eas.enumName)) {
+					LOGGER.trace("{}:{}:{}", eas.enumName, enumItemStruct.itemName, enumItemStruct.index);
+					enumdyn.addValue(new ODSEnum(enumItemStruct.itemName, enumItemStruct.index));
 				}
 				er.add(eas.enumName, enumdyn);
 			}
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQuery.java b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQuery.java
index dc10886..38748ca 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQuery.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/query/ODSQuery.java
@@ -92,6 +92,8 @@
 
 	private final ApplElemAccess applElemAccess;
 
+	private int limit;
+
 	// ======================================================================
 	// Constructors
 	// ======================================================================
@@ -103,6 +105,7 @@
 	 */
 	ODSQuery(ApplElemAccess applElemAccess) {
 		this.applElemAccess = applElemAccess;
+		limit = 0;
 	}
 
 	// ======================================================================
@@ -121,6 +124,15 @@
 	 * {@inheritDoc}
 	 */
 	@Override
+	public Query limit(int limit) {
+		this.limit = limit;
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
 	public Query select(Attribute attribute, Aggregation aggregation) {
 		EntityType entityType = attribute.getEntityType();
 		entityTypesByID.put(Long.toString(ODSConverter.fromODSLong(((ODSEntityType) entityType).getODSID())),
@@ -219,7 +231,7 @@
 
 			List<Result> results = new ArrayList<>();
 			long start = System.currentTimeMillis();
-			for (Result result : new ResultFactory(entityTypesByID, applElemAccess.getInstancesExt(qse, 0)[0])) {
+			for (Result result : new ResultFactory(entityTypesByID, applElemAccess.getInstancesExt(qse, limit)[0])) {
 				results.add(result);
 			}
 			long stop = System.currentTimeMillis();
diff --git a/src/main/java/org/eclipse/mdm/api/odsadapter/search/BaseEntitySearchQuery.java b/src/main/java/org/eclipse/mdm/api/odsadapter/search/BaseEntitySearchQuery.java
index 4f75079..cc2db44 100644
--- a/src/main/java/org/eclipse/mdm/api/odsadapter/search/BaseEntitySearchQuery.java
+++ b/src/main/java/org/eclipse/mdm/api/odsadapter/search/BaseEntitySearchQuery.java
@@ -89,9 +89,10 @@
 		EntityConfig<?> entityConfig = modelManager.getEntityConfig(new Key<>(entityClass));
 		EntityType source = entityConfig.getEntityType();
 
-		entityConfig.getOptionalConfigs().stream().map(EntityConfig::getEntityType).forEach(entityType -> {
-			joinTree.addNode(source, entityType, true, JoinType.OUTER);
-		});
+		entityConfig.getOptionalConfigs().stream().map(EntityConfig::getEntityType)
+				.filter(et -> !"Classification".equals(et.getName())).forEach(entityType -> {
+					joinTree.addNode(source, entityType, true, JoinType.OUTER);
+				});
 
 		entityConfig.getMandatoryConfigs().stream().map(EntityConfig::getEntityType).forEach(entityType -> {
 			joinTree.addNode(source, entityType, true, JoinType.INNER);
@@ -195,9 +196,10 @@
 		joinTree.addNode(modelManager.getEntityType(joinConfig.source), target, joinConfig.viaParent, JoinType.INNER);
 
 		// add target's optional dependencies
-		targetEntityConfig.getOptionalConfigs().stream().map(EntityConfig::getEntityType).forEach(entityType -> {
-			joinTree.addNode(target, entityType, true, JoinType.OUTER);
-		});
+		targetEntityConfig.getOptionalConfigs().stream().map(EntityConfig::getEntityType)
+				.filter(et -> !"Classification".equals(et.getName())).forEach(entityType -> {
+					joinTree.addNode(target, entityType, true, JoinType.OUTER);
+				});
 
 		// add target's mandatory dependencies
 		targetEntityConfig.getMandatoryConfigs().stream().map(EntityConfig::getEntityType).forEach(entityType -> {
diff --git a/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java b/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java
index 4e84e9e..8b2a9da 100644
--- a/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java
+++ b/src/test/java/org/eclipse/mdm/api/odsadapter/ODSRoleTest.java
@@ -36,10 +36,11 @@
 import org.eclipse.mdm.api.dflt.model.Role;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-//@Ignore
+@Ignore
 // FIXME 10.7.2017: this test needs a running ODS Server, that is not suitable for continous build in Jenkins.
 // Comment this in for local tests only.
 public class ODSRoleTest {