/********************************************************************************
 * 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.apicopy.control;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.eclipse.mdm.api.base.ServiceNotProvidedException;
import org.eclipse.mdm.api.base.Transaction;
import org.eclipse.mdm.api.base.adapter.EntityType;
import org.eclipse.mdm.api.base.adapter.Relation;
import org.eclipse.mdm.api.base.massdata.ReadRequest;
import org.eclipse.mdm.api.base.massdata.ReadRequest.ValuesMode;
import org.eclipse.mdm.api.base.massdata.WriteRequest;
import org.eclipse.mdm.api.base.model.Channel;
import org.eclipse.mdm.api.base.model.ChannelGroup;
import org.eclipse.mdm.api.base.model.ContextComponent;
import org.eclipse.mdm.api.base.model.ContextRoot;
import org.eclipse.mdm.api.base.model.ContextType;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.MeasuredValues;
import org.eclipse.mdm.api.base.model.Measurement;
import org.eclipse.mdm.api.base.model.Quantity;
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.model.Value;
import org.eclipse.mdm.api.base.model.VersionState;
import org.eclipse.mdm.api.base.query.Filter;
import org.eclipse.mdm.api.base.search.SearchService;
import org.eclipse.mdm.api.dflt.ApplicationContext;
import org.eclipse.mdm.api.dflt.EntityManager;
import org.eclipse.mdm.api.dflt.model.Pool;
import org.eclipse.mdm.api.dflt.model.Project;
import org.eclipse.mdm.api.dflt.model.TemplateComponent;
import org.eclipse.mdm.api.dflt.model.TemplateRoot;
import org.eclipse.mdm.api.dflt.model.TemplateTest;
import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
import org.eclipse.mdm.api.dflt.model.Versionable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Strings;
import com.google.common.collect.ListMultimap;

public class ImportTask extends TransferBase implements ApiCopyTask {

	/**
	 * Property to configure to overwrite the existing test step
	 * 
	 * Default: false
	 * 
	 * If true and the matching target test step exists, context data will be
	 * overwriten and the measurements will be imported as childs of the existing
	 * teststep.
	 * 
	 * Otherwise a new test step will be created
	 */
	private static final String PROPERTY_OVERWRITE_EXISTING_ELEMENTS = "overwriteExistingElements";
	private static final String DEFAULT_OVERWRITE_EXISTING_ELEMENTS = "false";

	/**
	 * Property to configure that existing measured values will be appended
	 * 
	 * Default: false
	 * 
	 * If true the measured value of the import data set will be appended to the
	 * existing. That means, if the target measurement already exists the importer
	 * will add the measured values of the source column to the target column. If at
	 * the the target measurement the column not exists, the importer create a new
	 * one, add first invalid values with the count of the target submatrix size,
	 * and add there the source values.
	 * 
	 * If false and the target measurement already exists, the import task will be
	 * canceled
	 */
	private static final String PROPERTY_APPEND = "append";
	private static final String DEFAULT_APPEND = "false";

	/**
	 * Property to configure that existing file links will be replaced
	 * 
	 * Default: false
	 * 
	 * If true, file links of the target entities will be replaced, if in the source
	 * the file link exists
	 * 
	 * Otherwise new file links will be added to the existing sequence.
	 */
	private static final String PROPERTY_REPLACE_FILELINKS = "replaceFileLinks";
	private static final String DEFAULT_REPLACE_FILES = "false";

	private static final Logger LOG = LoggerFactory.getLogger(ImportTask.class);

	private SearchService searchServiceDst;
	private ClassificationUtil classificationUtil;
	private TemplateManager templateManager;

	private Map<String, String> quantityMapping = new HashMap<>();

	private Map<String, String> unitMapping = new HashMap<>();

	private Map<String, String> properties = new HashMap<>();

	private boolean replaceFileLinks = false;

	public ImportTask(ApplicationContext src, ApplicationContext dst, TemplateManager templateManager) {
		super(src, dst);

		searchServiceDst = contextDst.getSearchService()
				.orElseThrow(() -> new ServiceNotProvidedException(SearchService.class));

		if (templateManager == null) {
			this.templateManager = new DefaultTemplateManager();
		} else {
			this.templateManager = templateManager;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.mdm.apicopy.control.ApiCopyTask#setUnitMapping(java.util.Map)
	 */
	@Override
	public void setUnitMapping(Map<String, String> unitMapping) {
		this.unitMapping = unitMapping;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.mdm.apicopy.control.ApiCopyTask#setQuantityMapping(java.util.Map)
	 */
	@Override
	public void setQuantityMapping(Map<String, String> quantityMapping) {
		this.quantityMapping = quantityMapping;
	}

	@Override
	public void copy(List<? extends Entity> entities) {
		Transaction transaction = entityManagerDst.startTransaction();
		classificationUtil = new ClassificationUtil(transaction, contextDst);
		try {
			mapSrcDstEntities.clear();

			ListMultimap<Class<? extends Entity>, Entity> parents = loadParents(entities);
			LOG.trace("Resolved parents: {}", parents);
			supportedRootEntities.forEach(ec -> parents.get(ec).forEach(e -> copyEntity(e, false, transaction)));

			LOG.trace("Export entities: {}", entities);
			entities.forEach(e -> copyEntity(e, true, transaction));
			transaction.commit();
			deleteFilesOfReplacedFileLinks();
		} catch (Exception exc) {
			try {
				transaction.abort();
			} catch (Exception exc2) {
				LOG.error("Could not abort transaction!");
			}
			deleteFilesOfUploadedFileLinks();

			throw new ApiCopyException("Could not copy data.", exc);
		} finally {
			classificationUtil.clearCache();
			clearReplacedFileLinkCache();
			clearUploadedFileLinkCache();
		}
	}

	private Entity copyEntity(Entity entity, boolean recursive, Transaction transaction) {
		if (entity instanceof Project) {
			return copyProject((Project) entity, recursive, transaction);
		} else if (entity instanceof Pool) {
			return copyPool((Pool) entity, recursive, transaction);
		} else if (entity instanceof Test) {
			return copyTest((Test) entity, recursive, transaction);
		} else if (entity instanceof TestStep) {
			return copyTestStep((TestStep) entity, recursive, transaction);
		} else if (entity instanceof Measurement) {
			return copyMeasurement((Measurement) entity, new ArrayList<ContextRoot>(), recursive, transaction);
		} else {
			throw new ApiCopyException("Unsupported entity: '" + entity.getClass().getName() + "'");
		}
	}

	private Project copyProject(Project projectSrc, boolean recursive, Transaction transaction) {
		EntityHolder ehSrc = new EntityHolder(projectSrc, entityManagerSrc);

		EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);

		if (null == ehDst) {
			LOG.trace("Importing Project '{}'", projectSrc.getName());
			EntityType etProject = modelManagerDst.getEntityType(Project.class);

			Filter filter = Filter.nameOnly(etProject, projectSrc.getName());

			Project projectDst = fetchOne(searchServiceDst, Project.class, filter)
					.orElseGet(() -> entityFactoryDst.createProject(projectSrc.getName()));

			copyValues(projectSrc, projectDst, Arrays.asList("Id", "Name"), false, replaceFileLinks);

			persist(transaction, projectDst);

			ehDst = new EntityHolder(projectDst, entityManagerDst);
			mapSrcDstEntities.put(ehSrc, ehDst);

			if (recursive) {
				entityManagerSrc.loadChildren(projectSrc, Pool.class)
						.forEach(pool -> copyPool(pool, recursive, transaction));
			}
		}

		return (Project) ehDst.getEntity();
	}

	private Pool copyPool(Pool poolSrc, boolean recursive, Transaction transaction) {
		EntityHolder ehSrc = new EntityHolder(poolSrc, entityManagerSrc);

		EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);

		if (null == ehDst) {
			LOG.trace("Importing Pool '{}'", poolSrc.getName());

			Project projectParentDst = (Project) mapSrcDstEntities
					.get(new EntityHolder(entityManagerSrc.loadParent(poolSrc, Project.class).get(), entityManagerSrc))
					.getEntity();

			EntityType etPool = modelManagerDst.getEntityType(Pool.class);
			EntityType etProject = modelManagerDst.getEntityType(Project.class);

			Relation relProject = etPool.getRelation(etProject);

			if (null == relProject) {
				throw new ApiCopyException("No relation to Project found at Pool!");
			}

			Filter filter = Filter.nameOnly(etPool, poolSrc.getName()).id(relProject, projectParentDst.getID());
			Pool poolDst = fetchOne(searchServiceDst, Pool.class, filter)
					.orElseGet(() -> entityFactoryDst.createPool(poolSrc.getName(), projectParentDst));

			copyValues(poolSrc, poolDst, Arrays.asList("Id", "Name"), false, replaceFileLinks);

			persist(transaction, poolDst);

			ehDst = new EntityHolder(poolDst, entityManagerDst);
			mapSrcDstEntities.put(ehSrc, ehDst);

			if (recursive) {
				entityManagerSrc.loadChildren(poolSrc, Test.class)
						.forEach(test -> copyTest(test, recursive, transaction));
			}
		}

		return (Pool) ehDst.getEntity();
	}

	private Test copyTest(Test testSrc, boolean recursive, Transaction transaction) {
		EntityHolder ehSrc = new EntityHolder(testSrc, entityManagerSrc);

		EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);

		if (null == ehDst) {

			Pool poolParentDst = (Pool) mapSrcDstEntities
					.get(new EntityHolder(entityManagerSrc.loadParent(testSrc, Pool.class).get(), entityManagerSrc))
					.getEntity();

			EntityType etTest = modelManagerDst.getEntityType(Test.class);
			EntityType etPool = modelManagerDst.getEntityType(Pool.class);

			Relation relPool = etTest.getRelation(etPool);

			if (null == relPool) {
				throw new ApiCopyException("No relation to StructureLevel found at Test!");
			}

			Optional<TemplateTest> templateTestDst = loadTemplateTest(testSrc);

			Filter filter = Filter.nameOnly(etTest, testSrc.getName()).id(relPool, poolParentDst.getID());

			String rootProjectName = getProjectName(testSrc);

			Test testDst;

			if (templateTestDst.isPresent()) {
				LOG.trace("Importing Test '{}' using TestTemplate '{}'", testSrc.getName(),
						templateTestDst.get().getName());
				testDst = fetchOne(searchServiceDst, Test.class, filter)
						.orElseGet(() -> entityFactoryDst.createTest(testSrc.getName(), poolParentDst,
								templateTestDst.get(), classificationUtil.getClassification(rootProjectName), false));
			} else {
				LOG.trace("Importing Test '{}' using no TestTemplate", testSrc.getName());
				testDst = fetchOne(searchServiceDst, Test.class, filter)
						.orElseGet(() -> entityFactoryDst.createTest(testSrc.getName(), poolParentDst, null,
								classificationUtil.getClassification(rootProjectName), false));
			}

			copyValues(testSrc, testDst, Arrays.asList("Id", "Name"), true, replaceFileLinks);

			// copy responsible person:
			Optional<User> userSrc = testSrc.getResponsiblePerson();
			if (userSrc.isPresent()) {
				User userDst = entityManagerDst.loadAll(User.class, userSrc.get().getName()).stream().findFirst()
						.orElseThrow(() -> new ApiCopyException(String.format(
								"No User instance with name %s found in destination!", userSrc.get().getName())));

				testDst.setResponsiblePerson(userDst);
			}

			persist(transaction, testDst);

			ehDst = new EntityHolder(testDst, entityManagerDst);
			mapSrcDstEntities.put(ehSrc, ehDst);

			if (recursive) {
				EntityType etTestStep = modelManagerDst.getEntityType(TestStep.class);
				Relation relTest = etTestStep.getRelation(etTest);

				if (null == relTest) {
					throw new ApiCopyException("No relation to Test found at TestStep!");
				}

				copyTestSteps(testSrc, recursive, templateTestDst, testDst, transaction);
				entityManagerSrc.loadChildren(testSrc, TestStep.class)
						.forEach(testStep -> copyTestStep(testStep, recursive, transaction));
			}
		}

		return (Test) ehDst.getEntity();
	}

	private TestStep copyTestStep(TestStep testStepSrc, boolean recursive, Transaction transaction) {
		EntityHolder ehSrc = new EntityHolder(testStepSrc, entityManagerSrc);

		EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);

		if (null == ehDst) {
			LOG.trace("Importing TestStep '{}'", testStepSrc.getName());
			EntityType etTestStep = modelManagerDst.getEntityType(TestStep.class);
			EntityType etTest = modelManagerDst.getEntityType(Test.class);

			Relation relTest = etTestStep.getRelation(etTest);

			if (null == relTest) {
				throw new ApiCopyException("No relation to Test found at TestStep!");
			}

			Test testDst = (Test) mapSrcDstEntities
					.get(new EntityHolder(entityManagerSrc.loadParent(testStepSrc, Test.class).get(), entityManagerSrc))
					.getEntity();

			Optional<TemplateTestStep> templateTestStep = loadTemplateTestStep(testStepSrc);

			Filter filter = Filter.nameOnly(etTestStep, testStepSrc.getName()).id(relTest, testDst.getID());

			String rootProjectName = getProjectName(testStepSrc);

			TestStep testStepDst = fetchOne(searchServiceDst, TestStep.class, filter).orElseGet(() -> {
				if (templateTestStep.isPresent() && hasContextData(testStepSrc)) {
					LOG.trace("Importing TestStep '{}' using TestStepTemplate '{}' and create context roots",
							testStepSrc.getName(), templateTestStep.get().getName());
					return entityFactoryDst.createTestStep(testDst, templateTestStep.get(),
							classificationUtil.getClassification(rootProjectName));
				} else if (templateTestStep.isPresent()) {
					LOG.trace("Importing TestStep '{}' using TestStepTemplate '{}'", testStepSrc.getName(),
							templateTestStep.get().getName());
					return entityFactoryDst.createTestStepWithOutContextRoots(testDst, templateTestStep.get(),
							classificationUtil.getClassification(rootProjectName));
				} else {
					LOG.trace("Importing TestStep '{}' using no TestStepTemplate", testStepSrc.getName());
					TestStep createdTestStep = entityFactoryDst.createTestStep(testStepSrc.getName(), testDst,
							classificationUtil.getClassification(rootProjectName));
					Value value = createdTestStep.getValue("TplTestStep");
					return createdTestStep;
				}
			});

			copyValues(testStepSrc, testStepDst, Arrays.asList("Id"), true, replaceFileLinks);

			persist(transaction, testStepDst);

			ehDst = new EntityHolder(testStepDst, entityManagerDst);
			mapSrcDstEntities.put(ehSrc, ehDst);

			Map<ContextType, ContextRoot> mapContextRootsSrc = testStepSrc.loadContexts(entityManagerSrc,
					ContextType.values());
			Map<ContextType, ContextRoot> mapContextRootsDst = testStepDst.loadContexts(entityManagerDst,
					ContextType.values());

			copyContext(mapContextRootsSrc, mapContextRootsDst, templateTestStep, transaction);

			if (recursive) {
				List<ContextRoot> listContextRoots = new ArrayList<>();
				entityManagerSrc.loadChildren(testStepSrc, Measurement.class)
						.forEach(measurement -> copyMeasurement(measurement, listContextRoots, recursive, transaction));
			}
		}
		return (TestStep) ehDst.getEntity();
	}

	private String getProjectName(TestStep testStepSrc) {
		Optional<Test> parentTest = entityManagerSrc.loadParent(testStepSrc, Test.class);

		if (!parentTest.isPresent()) {
			throw new ApiCopyException("Parent of source teststep not found!");
		}

		return getProjectName(parentTest.get());
	}

	private String getProjectName(Test testSrc) {

		Optional<Pool> parentPool = entityManagerSrc.loadParent(testSrc, Pool.class);

		if (!parentPool.isPresent()) {
			throw new ApiCopyException("Parent of source test not found!");
		}

		Optional<Project> parentProject = entityManagerSrc.loadParent(parentPool.get(), Project.class);

		if (!parentProject.isPresent()) {
			throw new ApiCopyException("Parent of source pool not found!");
		}

		return parentProject.get().getName();
	}

	/**
	 * Check if the teststep has context data
	 * 
	 * @param testStepSrc
	 * @return true if the teststep has conteyt data
	 */
	private boolean hasContextData(TestStep testStepSrc) {
		boolean hasContextData = false;

		Optional<EntityManager> entityManager = contextSrc.getEntityManager();
		if (entityManager.isPresent()) {
			Map<ContextType, ContextRoot> loadContexts = entityManager.get().loadContexts(testStepSrc,
					ContextType.UNITUNDERTEST, ContextType.TESTEQUIPMENT, ContextType.TESTSEQUENCE);
			if (!loadContexts.isEmpty()) {
				hasContextData = true;
			}
		}

		return hasContextData;

	}

	private List<TestStep> copyTestSteps(Test testSrc, boolean recursive, Optional<TemplateTest> templateTestDst,
			Test testDst, Transaction transaction) {
		EntityType etTestStep = modelManagerDst.getEntityType(TestStep.class);
		EntityType etTest = modelManagerDst.getEntityType(Test.class);

		Relation relTest = etTestStep.getRelation(etTest);

		if (null == relTest) {
			throw new ApiCopyException("No relation to Test found at TestStep!");
		}

		List<TestStep> listTestStepsSrc = entityManagerSrc.loadChildren(testSrc, TestStep.class);

		List<TestStep> listTestStepsDst = new ArrayList<>();
		for (int i = 0, len = listTestStepsSrc.size(); i < len; ++i) {
			TestStep testStepSrc = listTestStepsSrc.get(i);
			Optional<TemplateTestStep> templateTestStep = loadTemplateTestStep(testStepSrc);

			String rootProjectName = getProjectName(testStepSrc);

			Filter filter = Filter.nameOnly(etTestStep, testStepSrc.getName()).id(relTest, testDst.getID());
			Optional<TestStep> oTestSTepDst = fetchOne(searchServiceDst, TestStep.class, filter);

			TestStep testStepDst;

			boolean overwriteExistingElements = Boolean.valueOf(
					properties.getOrDefault(PROPERTY_OVERWRITE_EXISTING_ELEMENTS, DEFAULT_OVERWRITE_EXISTING_ELEMENTS));

			if (!overwriteExistingElements || (overwriteExistingElements && !oTestSTepDst.isPresent())) {
				if (templateTestStep.isPresent() && hasContextData(testStepSrc)) {
					LOG.trace("Importing TestStep '{}' using TestStepTemplate '{}' and create context roots",
							testStepSrc.getName(), templateTestStep.get().getName());
					testStepDst = entityFactoryDst.createTestStep(testDst, templateTestStep.get(),
							classificationUtil.getClassification(rootProjectName));
					testStepDst.setName(testStepSrc.getName());
				} else if (templateTestStep.isPresent()) {
					LOG.trace("Importing TestStep '{}' using TestStepTemplate '{}' and create context roots",
							testStepSrc.getName(), templateTestStep.get().getName());
					testStepDst = entityFactoryDst.createTestStepWithOutContextRoots(testDst, templateTestStep.get(),
							classificationUtil.getClassification(rootProjectName));
				} else {
					LOG.trace("Importing TestStep '{}' using no TestStepTemplate", testStepSrc.getName());
					testStepDst = entityFactoryDst.createTestStep(testStepSrc.getName(), testDst,
							classificationUtil.getClassification(rootProjectName));
				}
			} else {
				testStepDst = oTestSTepDst.get();
			}

			copyValues(testStepSrc, testStepDst, Arrays.asList("Id"), true, replaceFileLinks);

			listTestStepsDst.add(testStepDst);

			mapSrcDstEntities.put(new EntityHolder(testStepSrc, entityManagerSrc),
					new EntityHolder(testStepDst, entityManagerDst));
		}

		for (TestStep testStepSrc : listTestStepsSrc) {
			Optional<TestStep> testStepDst = listTestStepsDst.stream()
					.filter(n -> n.getName().equals(testStepSrc.getName())).findFirst();

			if (testStepDst.isPresent()) {
				Map<ContextType, ContextRoot> mapContextRootsSrc = testStepSrc.loadContexts(entityManagerSrc,
						ContextType.values());
				Map<ContextType, ContextRoot> mapContextRootsDst = testStepDst.get().loadContexts(entityManagerDst,
						ContextType.values());
				copyContext(mapContextRootsSrc, mapContextRootsDst, loadTemplateTestStep(testStepSrc), transaction);
			}
		}

		persist(transaction, listTestStepsDst);

		if (recursive) {
			for (TestStep testStep : listTestStepsSrc) {
				List<ContextRoot> listContextRoots = new ArrayList<>();
				entityManagerSrc.loadChildren(testStep, Measurement.class)
						.forEach(measurement -> copyMeasurement(measurement, listContextRoots, recursive, transaction));
			}
		}

		return listTestStepsDst;
	}

	private void copyContext(Map<ContextType, ContextRoot> mapContextRootsSrc,
			Map<ContextType, ContextRoot> mapContextRootsDst, Optional<TemplateTestStep> optTemplateTestStep,
			Transaction transaction) {

		for (Map.Entry<ContextType, ContextRoot> me : mapContextRootsSrc.entrySet()) {
			LOG.trace("Importing ContextRoot '{}'", me.getKey());
			ContextRoot contextRootDst = mapContextRootsDst.get(me.getKey());
			if (null != contextRootDst && contextRootDst.getName().equals(me.getValue().getName())) {
				ContextRoot contextRootSrc = me.getValue();
				copyValues(contextRootSrc, contextRootDst, Arrays.asList("Id", "Name"), false, replaceFileLinks);

				TemplateRoot templateRootDst = null;

				if (optTemplateTestStep.isPresent()) {
					Optional<TemplateRoot> optTemplateRoot = optTemplateTestStep.get()
							.getTemplateRoot(contextRootDst.getContextType());

					templateRootDst = optTemplateRoot.orElse(null);
				}

				for (ContextComponent contextComponentSrc : me.getValue().getContextComponents()) {
					LOG.trace("Importing ContextComponent '{}'", contextComponentSrc.getName());
					Optional<ContextComponent> o = contextRootDst.getContextComponent(contextComponentSrc.getName());

					if (o.isPresent()) {
						ContextComponent contextComponentDst = o.get();

						copyValues(contextComponentSrc, contextComponentDst, Arrays.asList("Id", "Name"), true,
								replaceFileLinks);

					} else if (null != templateRootDst) {
						Optional<TemplateComponent> optTemplateComponent = templateRootDst
								.getTemplateComponent(contextComponentSrc.getName());

						if (optTemplateComponent.isPresent()) {
							TemplateComponent templateComponent = optTemplateComponent.get();
							if (templateComponent.isOptional() && !templateComponent.isDefaultActive()) {
								ContextComponent contextComponentDst = entityFactoryDst
										.createContextComponent(contextComponentSrc.getName(), contextRootDst);

								copyValues(contextComponentSrc, contextComponentDst, Arrays.asList("Id", "Name"), true,
										replaceFileLinks);

								persist(transaction, contextComponentDst);
							}
						}
					}
				}
			}
		}
	}

	private Measurement copyMeasurement(Measurement measurementSrc, List<ContextRoot> listContextRootsDst,
			boolean recursive, Transaction transaction) {
		EntityHolder ehSrc = new EntityHolder(measurementSrc, entityManagerSrc);

		EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);

		boolean append = Boolean.valueOf(properties.getOrDefault(PROPERTY_APPEND, DEFAULT_APPEND));

		if (null == ehDst) {
			LOG.trace("Importing Measurement '{}'", measurementSrc.getName());
			TestStep testStepSrs = entityManagerSrc.loadParent(measurementSrc, TestStep.class).get();
			TestStep testStepParentDst = (TestStep) mapSrcDstEntities
					.get(new EntityHolder(testStepSrs, entityManagerSrc)).getEntity();

			EntityType etMeasurement = modelManagerDst.getEntityType(Measurement.class);
			EntityType etTestStep = modelManagerDst.getEntityType(TestStep.class);

			Relation relTestStep = etMeasurement.getRelation(etTestStep);

			if (null == relTestStep) {
				throw new ApiCopyException("No relation to TestStep found at MeaResult!");
			}

			Filter filter = Filter.nameOnly(etMeasurement, measurementSrc.getName()).id(relTestStep,
					testStepParentDst.getID());

			Optional<Measurement> optMeasurement = fetchOne(searchServiceDst, Measurement.class, filter);
			Measurement measurementDst = null;

			if (optMeasurement.isPresent() && !append) {
				throw new ApiCopyException(String.format("TestStep '%s' has already a measurement with name '%s'!",
						testStepParentDst.getName(), measurementSrc.getName()));
			} else if (optMeasurement.isPresent()) {
				measurementDst = optMeasurement.get();
			} else {
				append = false;
			}

			Optional<TemplateTestStep> optTemplateTestStep = loadTemplateTestStep(testStepSrs);

			// If no ContextRoots to use with the newly created Measurement are passed into
			// this method, use ContextRoots
			// of any already existing Measurement under the parent test step.
			// First look in destination...
			if (listContextRootsDst.isEmpty()) {
				for (Measurement existingMeasurementDst : entityManagerDst.loadChildren(testStepParentDst,
						Measurement.class)) {
					listContextRootsDst.addAll(
							existingMeasurementDst.loadContexts(entityManagerDst, ContextType.values()).values());

					if (!listContextRootsDst.isEmpty()) {
						break;
					}
				}
			}

			// ...then, if nothing has been found, in source and try to find destination
			// counterpart in cache map:
			if (listContextRootsDst.isEmpty()) {
				for (Measurement existingMeasurementSrc : entityManagerSrc.loadChildren(testStepSrs,
						Measurement.class)) {
					EntityHolder eh = mapSrcDstEntities.get(new EntityHolder(existingMeasurementSrc, entityManagerSrc));
					if (null != eh) {
						listContextRootsDst.addAll(((Measurement) eh.getEntity())
								.loadContexts(entityManagerDst, ContextType.values()).values());
					}

					if (!listContextRootsDst.isEmpty()) {
						break;
					}
				}
			}

			// Still no ContextRoots found? Create them from the test step template:
			if (listContextRootsDst.isEmpty() && optTemplateTestStep.isPresent()) {
				optTemplateTestStep.get().getTemplateRoots()
						.forEach(tr -> listContextRootsDst.add(entityFactoryDst.createContextRoot(tr)));
			}

			if (measurementDst == null) {
				measurementDst = entityFactoryDst.createMeasurement(measurementSrc.getName(), testStepParentDst,
						listContextRootsDst.toArray(new ContextRoot[listContextRootsDst.size()]));
			}

			copyValues(measurementSrc, measurementDst, Arrays.asList("Id", "Name"), true, replaceFileLinks);

			ehDst = new EntityHolder(measurementDst, entityManagerDst);
			mapSrcDstEntities.put(ehSrc, ehDst);

			Map<ContextType, ContextRoot> mapContextRootsSrc = testStepParentDst.loadContexts(entityManagerDst,
					ContextType.values());
			Map<ContextType, ContextRoot> mapContextRootsDst = measurementDst.loadContexts(entityManagerDst,
					ContextType.values());

			copyContext(mapContextRootsSrc, mapContextRootsDst, optTemplateTestStep, transaction);

			mapContextRootsSrc = measurementSrc.loadContexts(entityManagerSrc, ContextType.values());
			mapContextRootsDst = measurementDst.loadContexts(entityManagerDst, ContextType.values());
			copyContext(mapContextRootsSrc, mapContextRootsDst, optTemplateTestStep, transaction);

			persist(transaction, measurementDst);

			Iterator<ContextRoot> contextRootIter = mapContextRootsDst.values().iterator();

			while (contextRootIter.hasNext()) {
				ContextRoot contextRootForUpdate = contextRootIter.next();
				persist(transaction, contextRootForUpdate);
			}

			if (recursive) {
				List<WriteRequest> listWriteRequests = new ArrayList<>();

				Map<String, Channel> mapChannels = new HashMap<>();

				if (append && !isSrcChannelsValid(entityManagerSrc.loadChildren(measurementSrc, Channel.class),
						entityManagerDst.loadChildren(measurementDst, Channel.class))) {
					throw new ApiCopyException(
							"Appending not possible. All channels of existing measurement have to be in the source measurement");
				}

				for (Channel channel : entityManagerSrc.loadChildren(measurementSrc, Channel.class)) {
					Channel channelDst = copyChannel(channel, transaction);
					mapChannels.put(channel.getName(), channelDst);
				}

				for (ChannelGroup channelGroup : entityManagerSrc.loadChildren(measurementSrc, ChannelGroup.class)) {
					Map<String, MeasuredValues> existingMeasValuesToAppend = new HashMap<>();

					Integer numberOfValues = 0;
					if (append) {
						Optional<ChannelGroup> optChannelGroup = fetchOneChannelGroup(channelGroup);

						if (optChannelGroup.isPresent()) {
							numberOfValues = optChannelGroup.get().getNumberOfValues();
							existingMeasValuesToAppend = getMeasurementValuesMap(entityManagerDst,
									optChannelGroup.get());
						}

					}

					ChannelGroup channelGroupDst = copyChannelGroup(channelGroup, transaction, append);

					for (MeasuredValues measuredValues : entityManagerSrc.readMeasuredValues(ReadRequest
							.create(channelGroup).valuesMode(ValuesMode.STORAGE).allChannels().allValues())) {
						LOG.trace("Importing MeasuredValues '{}'", measuredValues.getName());
						if (!mapChannels.containsKey(measuredValues.getName())) {
							throw new ApiCopyException(
									String.format("Cannot find Channel %s in destination!", measuredValues.getName()));
						}

						Channel channelDst = mapChannels.get(measuredValues.getName());

						String mappedUnit = unitMapping.get(measuredValues.getUnit());

						if (!Strings.isNullOrEmpty(mappedUnit)) {
							measuredValues = MeasuredValuesHelper.mapUnitOfMeasuredValues(measuredValues, mappedUnit);
						}

						if (append) {

							channelDst = replaceChannelDst(channelDst, measurementDst, ehSrc, transaction);

							MeasuredValues measuredValuesOld = existingMeasValuesToAppend.get(channelDst.getName());

							if (measuredValuesOld == null) {
								measuredValuesOld = MeasuredValuesHelper.createEmptyValues(measuredValues.getName(),
										measuredValues.getScalarType(), measuredValues.getUnit(),
										measuredValues.getSequenceRepresentation(),
										measuredValues.getGenerationParameters(), measuredValues.isIndependent(),
										measuredValues.getAxisType(), numberOfValues);

							}

							measuredValues = MeasuredValuesHelper.appenMeasuredValues(measuredValuesOld,
									measuredValues);

						}

						listWriteRequests.add(createWriteRequest(channelGroupDst, channelDst, measuredValues));

					}
				}

				transaction.writeMeasuredValues(listWriteRequests);
			}
		}

		return (Measurement) ehDst.getEntity();
	}

	private boolean isSrcChannelsValid(List<Channel> channelsSrc, List<Channel> channelsDst) {
		boolean isSrcChannelsValid = true;

		Map<String, Channel> sourceMap = new HashMap<>();
		channelsSrc.forEach(srcChannel -> sourceMap.put(srcChannel.getName(), srcChannel));

		for (Channel channelDst : channelsDst) {
			if (sourceMap.get(channelDst.getName()) == null) {
				isSrcChannelsValid = false;
				break;
			}
		}

		return isSrcChannelsValid;
	}

	private Channel replaceChannelDst(Channel channelDst, Measurement measurementDst, EntityHolder ehSrc,
			Transaction transaction) {
		Channel channelNew = entityFactoryDst.createChannel(channelDst.getName(), measurementDst,
				channelDst.getQuantity());

		copyValues(channelDst, channelNew, Arrays.asList("Id"), false, replaceFileLinks);
		persist(transaction, channelNew);
		mapSrcDstEntities.put(ehSrc, new EntityHolder(channelNew, entityManagerDst));

		transaction.delete(Collections.singletonList(channelDst));
		return channelNew;
	}

	private Map<String, MeasuredValues> getMeasurementValuesMap(EntityManager entityManager,
			ChannelGroup channelGroup) {

		Map<String, MeasuredValues> returnVal = new HashMap<>();

		for (MeasuredValues measuredValues : entityManager.readMeasuredValues(
				ReadRequest.create(channelGroup).valuesMode(ValuesMode.STORAGE).allChannels().allValues())) {
			returnVal.put(measuredValues.getName(), measuredValues);
		}
		return returnVal;
	}

	private Channel copyChannel(Channel channelSrc, Transaction transaction) {
		EntityHolder ehSrc = new EntityHolder(channelSrc, entityManagerSrc);

		EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);

		if (null == ehDst) {
			LOG.trace("Importing Channel '{}'", channelSrc.getName());
			Measurement measurementParentDst = (Measurement) mapSrcDstEntities
					.get(new EntityHolder(entityManagerSrc.loadParent(channelSrc, Measurement.class).get(),
							entityManagerSrc))
					.getEntity();

			EntityType etChannel = modelManagerDst.getEntityType(Channel.class);
			EntityType etMeasurement = modelManagerDst.getEntityType(Measurement.class);

			Relation relMeasurement = etChannel.getRelation(etMeasurement);

			if (null == relMeasurement) {
				throw new ApiCopyException("No relation to MeaResult found at MeaQuantity!");
			}

			// Find a valid quantity with the highest version
			/*
			 * TODO Quantity should actually implement Versionable, then we could just use
			 * org.eclipse.mdm.api.dflt.EntityManager.loadLatestValid(Class<T>, String) Bug:
			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=553368
			 */

			Quantity quantity = entityManagerDst
					.loadAll(Quantity.class,
							quantityMapping.getOrDefault(channelSrc.getQuantity().getName(),
									channelSrc.getQuantity().getName()))
					.stream().filter(q -> q.getValue(Versionable.ATTR_VERSION_STATE).extract() == VersionState.VALID)
					.sorted(Comparator.comparing(q -> Integer.valueOf(q.getValue(Versionable.ATTR_VERSION).extract())))
					.findFirst().orElseThrow(() -> new ApiCopyException(String
							.format("Cannot find Quantity %s in destination!", channelSrc.getQuantity().getName())));

			Filter filter = Filter.nameOnly(etChannel, channelSrc.getName()).id(relMeasurement,
					measurementParentDst.getID());

			Channel channelDst = fetchOne(searchServiceDst, Channel.class, filter).orElseGet(
					() -> entityFactoryDst.createChannel(channelSrc.getName(), measurementParentDst, quantity));

			copyValues(channelSrc, channelDst, Arrays.asList("Id"), false, replaceFileLinks);

			persist(transaction, channelDst);

			ehDst = new EntityHolder(channelDst, entityManagerDst);
			mapSrcDstEntities.put(ehSrc, ehDst);
		}

		return (Channel) ehDst.getEntity();
	}

	private Optional<ChannelGroup> fetchOneChannelGroup(ChannelGroup channelGroupSrc) {
		Measurement measurementParentDst = (Measurement) mapSrcDstEntities
				.get(new EntityHolder(entityManagerSrc.loadParent(channelGroupSrc, Measurement.class).get(),
						entityManagerSrc))
				.getEntity();
		EntityType etChannelGroup = modelManagerDst.getEntityType(ChannelGroup.class);
		EntityType etMeasurement = modelManagerDst.getEntityType(Measurement.class);

		Relation relMeasurement = etChannelGroup.getRelation(etMeasurement);

		if (null == relMeasurement) {
			throw new ApiCopyException("No relation to MeaResult found at SubMatrix!");
		}

		Filter filter = Filter.nameOnly(etChannelGroup, channelGroupSrc.getName()).id(relMeasurement,
				measurementParentDst.getID());

		return fetchOne(searchServiceDst, ChannelGroup.class, filter);
	}

	private ChannelGroup copyChannelGroup(ChannelGroup channelGroupSrc, Transaction transaction, boolean append) {
		EntityHolder ehSrc = new EntityHolder(channelGroupSrc, entityManagerSrc);

		EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);

		if (null == ehDst) {
			LOG.trace("Importing ChannelGroup '{}'", channelGroupSrc.getName());
			Measurement measurementParentDst = (Measurement) mapSrcDstEntities
					.get(new EntityHolder(entityManagerSrc.loadParent(channelGroupSrc, Measurement.class).get(),
							entityManagerSrc))
					.getEntity();

			EntityType etChannelGroup = modelManagerDst.getEntityType(ChannelGroup.class);
			EntityType etMeasurement = modelManagerDst.getEntityType(Measurement.class);

			Relation relMeasurement = etChannelGroup.getRelation(etMeasurement);

			if (null == relMeasurement) {
				throw new ApiCopyException("No relation to MeaResult found at SubMatrix!");
			}

			Optional<ChannelGroup> channelGroupOptional = fetchOneChannelGroup(channelGroupSrc);

			ChannelGroup channelGroupDst = null;

			if (append && channelGroupOptional.isPresent()) {
				transaction.delete(Collections.singletonList(channelGroupOptional.get()));
				channelGroupDst = entityFactoryDst.createChannelGroup(channelGroupSrc.getName(),
						channelGroupSrc.getNumberOfValues(), measurementParentDst);
			} else {
				channelGroupDst = channelGroupOptional
						.orElseGet(() -> entityFactoryDst.createChannelGroup(channelGroupSrc.getName(),
								channelGroupSrc.getNumberOfValues(), measurementParentDst));
			}

			copyValues(channelGroupSrc, channelGroupDst, Arrays.asList("Id"), false, replaceFileLinks);

			persist(transaction, channelGroupDst);

			ehDst = new EntityHolder(channelGroupDst, entityManagerDst);
			mapSrcDstEntities.put(ehSrc, ehDst);
		}

		return (ChannelGroup) ehDst.getEntity();
	}

	private Optional<TemplateTest> loadTemplateTest(Test testSrc) {
		Optional<TemplateTest> returnVal = Optional.empty();

		String templateTestName = templateManager.getTemplateTestName(testSrc);

		if (!Strings.isNullOrEmpty(templateTestName)) {
			returnVal = getCurrentValidTestTemplate(entityManagerDst.loadAll(TemplateTest.class, templateTestName));

		}

		return returnVal;
	}

	private Optional<TemplateTest> getCurrentValidTestTemplate(List<TemplateTest> listTemplateTests) {
		Optional<TemplateTest> returnVal = Optional.empty();

		if (listTemplateTests != null && !listTemplateTests.isEmpty()) {
			int highestVersion = -1;
			TemplateTest highestValidTemplate = null;

			for (TemplateTest templateTest : listTemplateTests) {
				Value value = templateTest.getValue(TemplateTest.ATTR_VERSION_STATE);

				if (VersionState.VALID.equals(value.extract())) {
					int version = Integer.parseInt(templateTest.getValue(TemplateTest.ATTR_VERSION).extract());

					if (version > highestVersion) {
						highestValidTemplate = templateTest;
						highestVersion = version;
					}
				}

			}

			if (highestValidTemplate != null) {
				returnVal = Optional.of(highestValidTemplate);
			}

		}
		return returnVal;
	}

	private Optional<TemplateTestStep> loadTemplateTestStep(TestStep testStepSrc) {
		Optional<TemplateTestStep> returnVal = Optional.empty();

		String templateTestStepName = templateManager.getTemplateTestStepName(testStepSrc);

		if (!Strings.isNullOrEmpty(templateTestStepName)) {
			returnVal = getCurrentValidTestStepTemplate(
					entityManagerDst.loadAll(TemplateTestStep.class, templateTestStepName));
		}

		return returnVal;
	}

	private Optional<TemplateTestStep> getCurrentValidTestStepTemplate(List<TemplateTestStep> listTemplateTestSteps) {
		Optional<TemplateTestStep> returnVal = Optional.empty();

		if (listTemplateTestSteps != null && !listTemplateTestSteps.isEmpty()) {
			int highestVersion = -1;
			TemplateTestStep highestValidTemplate = null;

			for (TemplateTestStep templateTestStep : listTemplateTestSteps) {
				Value value = templateTestStep.getValue(TemplateTestStep.ATTR_VERSION_STATE);

				if (VersionState.VALID.equals(value.extract())) {
					int version = Integer.parseInt(templateTestStep.getValue(TemplateTestStep.ATTR_VERSION).extract());

					if (version > highestVersion) {
						highestValidTemplate = templateTestStep;
						highestVersion = version;
					}
				}

			}

			if (highestValidTemplate != null) {
				returnVal = Optional.of(highestValidTemplate);
			}

		}
		return returnVal;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.mdm.apicopy.control.ApiCopyTask#setProperties(java.util.Map)
	 */
	@Override
	public void setProperties(Map<String, String> properties) {
		this.properties = properties;
		this.replaceFileLinks = Boolean
				.valueOf(this.properties.getOrDefault(PROPERTY_REPLACE_FILELINKS, DEFAULT_REPLACE_FILES));
	}

}
