/********************************************************************************
 * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 ********************************************************************************/

package org.eclipse.mdm.businessobjects.service;

import static io.vavr.API.$;
import static io.vavr.API.Case;
import static io.vavr.API.Tuple;
import static io.vavr.Predicates.instanceOf;
import static org.eclipse.mdm.businessobjects.boundary.ResourceConstants.ENTITYATTRIBUTE_NAME;
import static org.eclipse.mdm.businessobjects.boundary.ResourceConstants.ENTITYATTRIBUTE_NUMBER_OF_VALUES;
import static org.eclipse.mdm.businessobjects.utils.Decomposer.decompose;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Inject;

import org.eclipse.mdm.api.base.adapter.Attribute;
import org.eclipse.mdm.api.base.adapter.ChildrenStore;
import org.eclipse.mdm.api.base.adapter.EntityStore;
import org.eclipse.mdm.api.base.adapter.EntityType;
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.Deletable;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.EnumRegistry;
import org.eclipse.mdm.api.base.model.EnumerationValue;
import org.eclipse.mdm.api.base.model.Environment;
import org.eclipse.mdm.api.dflt.EntityManager;
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.EntityFactory;
import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
import org.eclipse.mdm.api.dflt.model.TemplateComponent;
import org.eclipse.mdm.api.dflt.model.TemplateRoot;
import org.eclipse.mdm.api.dflt.model.TemplateSensor;
import org.eclipse.mdm.api.dflt.model.TemplateTest;
import org.eclipse.mdm.api.dflt.model.TemplateTestStepUsage;
import org.eclipse.mdm.api.dflt.model.ValueList;
import org.eclipse.mdm.api.dflt.model.ValueListValue;
import org.eclipse.mdm.businessobjects.control.I18NActivity;
import org.eclipse.mdm.businessobjects.control.MDMEntityAccessException;
import org.eclipse.mdm.businessobjects.control.NavigationActivity;
import org.eclipse.mdm.businessobjects.control.SearchActivity;
import org.eclipse.mdm.businessobjects.entity.MDMAttribute;
import org.eclipse.mdm.businessobjects.entity.MDMEntity;
import org.eclipse.mdm.businessobjects.entity.MDMEntityResponse;
import org.eclipse.mdm.businessobjects.entity.MDMRelation;
import org.eclipse.mdm.businessobjects.entity.MDMRelation.RelationType;
import org.eclipse.mdm.businessobjects.entity.SearchAttribute;
import org.eclipse.mdm.businessobjects.utils.Decomposer;
import org.eclipse.mdm.businessobjects.utils.EntityNotFoundException;
import org.eclipse.mdm.businessobjects.utils.ReflectUtil;
import org.eclipse.mdm.businessobjects.utils.RequestBody;
import org.eclipse.mdm.businessobjects.utils.Serializer;
import org.eclipse.mdm.businessobjects.utils.ServiceUtils;
import org.eclipse.mdm.connector.boundary.ConnectorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.VisibleForTesting;

import io.vavr.API;
import io.vavr.CheckedFunction0;
import io.vavr.Function0;
import io.vavr.Tuple;
import io.vavr.Value;
import io.vavr.collection.HashMap;
import io.vavr.collection.List;
import io.vavr.collection.Map;
import io.vavr.collection.Seq;
import io.vavr.collection.Set;
import io.vavr.collection.Stream;
import io.vavr.control.Option;
import io.vavr.control.Try;

/**
 * Class providing basic data access methods to {@link Entity}s.
 * 
 * @author Alexander Nehmer, science+computing AG Tuebingen (Atos SE)
 *
 */
@Stateless
public class EntityService {

	@Inject
	protected ConnectorService connectorService;

	@EJB
	private SearchActivity searchActivity;

	@EJB
	private NavigationActivity navigationActivity;

	@EJB
	private I18NActivity i18nActivity;

	private static final Logger LOGGER = LoggerFactory.getLogger(EntityService.class);

	/**
	 * Converts a {@code value} into a {@link Value}. If {@code value} is
	 * {@code null}, {@code Value.isEmpty() == true}.
	 * 
	 * @param value the value to wrap in a {@link Value}
	 * @return the created {@link Value}
	 */
	// TODO anehmer on 2017-11-26: rename to toValue()?
	public static <T> Value<T> V(T value) {
		return Option.of(value);
	}

	/**
	 * Converts the given string values into a {@link Seq} of {@link Value}s
	 * wrapping the value.
	 * 
	 * @param value the {@link Value}s to put in a {@link Seq}
	 * @return the created {@link Seq} of {@link Value}s
	 */
	public static Seq<String> SL(String... values) {
		return List.of(values);
	}

	/**
	 * Converts the given string {@link Value}s into a {@link Seq} of string
	 * {@link Value}s.
	 * 
	 * @param value the {@link Value}s to put in a {@link Seq}
	 * @return the created {@link Seq} of {@link Value}s
	 */
	@SafeVarargs
	public static Seq<Value<String>> SL(Value<String>... values) {
		return List.of(values);
	}

	/**
	 * Converts the given {@link Value}s into a {@link Seq} of {@link Value}s.
	 * 
	 * @param value the {@link Value}s to put in a {@link Seq}
	 * @return the created {@link Seq} of {@link Value}s
	 */
	@SafeVarargs
	public static Seq<Value<?>> L(Value<?>... values) {
		return List.of(values);
	}

	/**
	 * @see #find(String, Class, Value, Value, Value...)
	 */
	public <T extends Entity> Try<T> find(String sourceName, Class<T> entityClass, String id) {
		return find(sourceName, entityClass, id, (Value<ContextType>) null, null);
	}

	/**
	 * @see #find(String, Class, Value, Value, Value...)
	 */
	public <T extends Entity> Try<T> find(String sourceName, Class<T> entityClass, String id,
			Seq<String> parentIdSuppliers) {
		return find(sourceName, entityClass, id, (Value<ContextType>) null, parentIdSuppliers);
	}

	/**
	 * @see #find(String, Class, Value, Value, Value...)
	 */
	public <T extends Entity> Try<T> find(String sourceName, Class<T> entityClass, String id,
			Value<ContextType> contextTypeSupplier) {
		return find(sourceName, entityClass, id, contextTypeSupplier, null);
	}

	/**
	 * Returns the specified entity by given {@code entityClass} and given
	 * {@code id}. If the {@code entityClass} is either {@link CatalogAttribute},
	 * {@link TemplateCompont}, {@link TemplateAttributeAttribute} or
	 * {@link ContextComponent} the respective root entities
	 * {@link CatalogComponent}, {@link TemplateRoot} or {@link ContextRoot} are
	 * used to get the entity to find.
	 * 
	 * @param sourceName          name of the source (MDM {@link Environment} name)
	 * @param entityClass         entityType
	 * @param id                  id of entity to find
	 * @param contextTypeSupplier {@link Value} with the contextType of entity to
	 *                            find. Can be {@code null} if {@code EntityType}
	 *                            has no {@code ContextType}.
	 * @param parentIds           {@link Value}s with the id(s) of parent(s). For
	 *                            {@link CatalogAttribute} the parentId must be the
	 *                            id of the {@link CatalogComponent}, for
	 *                            {@link TemplateComponent} it must be the id of the
	 *                            {@link TemplateRoot}, for
	 *                            {@link TemplateAttribute} it must be the id of the
	 *                            {@link TemplateRoot} first and also the
	 *                            {@link TemplateComponent}, for a nested
	 *                            {@link TemplateComponent} it must be the id of the
	 *                            {@link TemplateRoot} first and the id of the
	 *                            parent {@link TemplateComponent} second, for a
	 *                            {@link TemplateAttribute} within a nested
	 *                            {@link TemplateComponent} it must be the id of the
	 *                            {@link TemplateRoot} first, the id of the parent
	 *                            {@link TemplateComponent} second and the id of the
	 *                            {@link TemplateComponent} last and for
	 *                            {@link ContextComponent} it must be the id of the
	 *                            {@link ContextRoot}.
	 * @return {@link Try} with the found entity
	 */
	// TODO anehmer on 2017-11-22: complete javadoc for ValueListValue and
	// TemplateTestStepUsage
	// TODO anehmer on 2017-11-22: add comment for parentIds for TplSensors and
	// nested TplSensors as well as for TplSensorAttrs and nested TplSensorAttrs
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> find(String sourceName, Class<T> entityClass, String id,
			Value<ContextType> contextTypeSupplier, Seq<String> parentIds) {

		// validate parentIds count
		Map<Class<?>, Integer> minParentsForEntity = HashMap.empty();
		minParentsForEntity = minParentsForEntity.put(Tuple(CatalogAttribute.class, 1))
				.put(Tuple(CatalogSensor.class, 1)).put(Tuple(TemplateComponent.class, 1))
				.put(Tuple(TemplateAttribute.class, 2)).put(Tuple(TemplateSensor.class, 2))
				.put(Tuple(ValueListValue.class, 1)).put(Tuple(TemplateTestStepUsage.class, 1));

		// return failure if number of parentIds do not correspond with the minimu
		// required by the entity type
		Option<Integer> minParents = minParentsForEntity.get(entityClass);
		// TODO anehmer on 2017-11-25: add entity types to message
		if (minParents.isDefined() && (parentIds == null || minParents.get() > parentIds.size())) {
			return Try.failure(new IllegalArgumentException("ParentId(s) of " + entityClass.getSimpleName()
					+ " not set appropriately. Expected minimum: " + minParents.get()));
		}

		// if the find is contextType specific
		if (contextTypeSupplier != null && !contextTypeSupplier.isEmpty()) {
			if (entityClass.equals(CatalogAttribute.class)) {
				// get CatalogAttribute from CatalogComponent
				if (parentIds.size() == 1) {
					return find(sourceName, CatalogComponent.class, parentIds.get(0), contextTypeSupplier)
							.map(catComp -> (T) getChild(CatalogAttribute.class, id, catComp::getCatalogAttributes));
				}
				// get the CatalogAttribute from a CatalogSensor
				else if (parentIds.size() == 2) {
					return find(sourceName, CatalogSensor.class, parentIds.get(1), contextTypeSupplier,
							parentIds.dropRight(1)).map(
									catComp -> (T) getChild(CatalogAttribute.class, id, catComp::getCatalogAttributes));
				}
			}

			// get CatalogSensor from CatalogComponent
			else if (entityClass.equals(CatalogSensor.class)) {
				return find(sourceName, CatalogComponent.class, parentIds.get(0), contextTypeSupplier)
						.map(catComp -> (T) getChild(CatalogSensor.class, id, catComp::getCatalogSensors));
			}

			// get TemplateComponent from TemplateRoot or parent TemplateComponent(s)
			else if (entityClass.equals(TemplateComponent.class)) {
				// if nested TplComp has to be found
				if (parentIds.size() > 1) {
					return find(sourceName, TemplateComponent.class, parentIds.get(parentIds.size() - 1),
							contextTypeSupplier, parentIds.dropRight(1))
									.map(tplComp -> (T) getChild(TemplateComponent.class, id,
											tplComp::getTemplateComponents));
				}
				// if non-nested TplComp has to be found: exit condition of recursive call
				return find(sourceName, TemplateRoot.class, parentIds.get(0), contextTypeSupplier)
						.map(tplRoot -> (T) getChild(TemplateComponent.class, id, tplRoot::getTemplateComponents));
			}

			// get TemplateAttributes from TemplateComponent
			else if (entityClass.equals(TemplateAttribute.class)) {
				Try<TemplateComponent> tplCompTry = find(sourceName, TemplateComponent.class,
						parentIds.get(parentIds.size() - 1), contextTypeSupplier, parentIds.dropRight(1));
				// if TemplateSensorAttribute has to be found
				// TODO anehmer on 2019-11-18: another criteria to switch to TemplateSensor
				// search should be used
				if (!tplCompTry.isFailure()) {
					return tplCompTry
							.map(tplComp -> (T) getChild(TemplateAttribute.class, id, tplComp::getTemplateAttributes));
				} else {
					return find(sourceName, TemplateSensor.class, parentIds.get(parentIds.size() - 1),
							contextTypeSupplier, parentIds.dropRight(1))
									.map(tplComp -> (T) getChild(TemplateAttribute.class, id,
											tplComp::getTemplateAttributes));
				}
			}

			// get TemplateSensor from TemplateComponent
			else if (entityClass.equals(TemplateSensor.class)) {
				return find(sourceName, TemplateComponent.class, parentIds.get(parentIds.size() - 1),
						contextTypeSupplier, parentIds.dropRight(1))
								.map(tplComp -> (T) getChild(TemplateSensor.class, id, tplComp::getTemplateSensors));
			}

			// get ContextComponent from ContextRoot
			else if (entityClass.equals(ContextComponent.class)) {
				// TODO anehmer on 2017-11-09: implement (also for nested ContextComponents)
				throw new RuntimeException("NOT IMPLEMENTED YET");
			}

			// get root nested entities (CatalogComponent, TemplateRoot, ContextRoot)
			return getEntityManager(sourceName).mapTry(em -> em.load(entityClass, contextTypeSupplier.get(), id));
		}

		// get ValueListValue from ValueList
		else if (entityClass.equals(ValueListValue.class)) {
			return find(sourceName, ValueList.class, parentIds.get(0))
					.map(valueList -> (T) getChild(ValueListValue.class, id, valueList::getValueListValues));
		}

		// get TemplateTestStepUsage from TemplateTest
		else if (entityClass.equals(TemplateTestStepUsage.class)) {
			return find(sourceName, TemplateTest.class, parentIds.get(0))
					.map(tplTest -> (T) getChild(TemplateTestStepUsage.class, id, tplTest::getTemplateTestStepUsages));
		}

		// for all other cases
		return getEntityManager(sourceName).map(em -> em.load(entityClass, id));
	}

	/**
	 * Gets the child with the given {@code childId} or an EntityNotFoundException
	 * if the child was not found
	 * 
	 * @param childClass    class of child to construct exception on failure
	 * @param childId       supplier of the id of child to find
	 * @param childSupplier function that gets all children
	 * @return the found child
	 */
	private <T extends Entity> T getChild(Class<T> childClass, String childId,
			Function0<java.util.List<T>> childSupplier) {
		return Stream.ofAll(childSupplier.apply()).find(childEntity -> childEntity.getID().equals(childId))
				.getOrElseThrow(() -> new EntityNotFoundException(childClass, childId));
	}

	/**
	 * Returns a {@link Try} of all {@link Entity}s if no filter is available.
	 * 
	 * @param sourceName  name of the source (MDM {@link Environment} name)
	 * @param entityClass class of the {@link Entity} to find
	 * @param filter      filter string to filter the {@link Entity} result. Can be
	 *                    null.
	 * @return a {@link Try} of the list of found {@link Entity}s
	 */
	// TODO anehmer on 2017-11-26: make filter Value<String>
	public <T extends Entity> Try<List<T>> findAll(String sourceName, Class<T> entityClass, String filter) {
		return findAll(sourceName, entityClass, filter, null);
	}

	/**
	 * Returns a {@link Try} of the matching {@link Entity}s of the given
	 * contextType using the given filter or all {@link Entity}s of the given
	 * contextType provided by the {@code contextTypeSupplier} if no filter is
	 * available.
	 * 
	 * @param sourceName          name of the source (MDM {@link Environment} name)
	 * @param entityClass         class of the {@link Entity} to find
	 * @param filter              filter string to filter the {@link Entity} result
	 * @param contextTypeSupplier a {@link Value} with the contextType of entity to
	 *                            find. Can be {@code null} if {@code EntityType}
	 *                            has no {@code ContextType}.
	 * @return a {@link Try} of the list of found {@link Entity}s
	 */
	// TODO anehmer on 2017-11-26: make filter Value<String>
	public <T extends Entity> Try<List<T>> findAll(String sourceName, Class<T> entityClass, String filter,
			Value<ContextType> contextTypeSupplier) {
		// TODO anehmer on 2017-11-22: do we need to implement the navigationActivity
		// filter shortcut like in ChannelGroupService.getChannelGroups()
		if (filter == null || filter.trim().length() <= 0) {
			return Try
					.of(getLoadAllEntitiesMethod(getEntityManager(sourceName).get(), entityClass, contextTypeSupplier))
					.map(javaList -> List.ofAll(javaList));
		} else {
			// TODO anehmer on 2017-11-15: not tested
			return Try.of(() -> this.searchActivity.search(connectorService.getContextByName(sourceName), entityClass,
					filter)).map(javaList -> List.ofAll(javaList));
		}
	}

	/**
	 * Returns the method to load all entities of type {@code entityClass}. If a
	 * {@code ContextType} is given the appropriate method in
	 * {@link org.eclipse.mdm.api.dflt.EntityManager} is used
	 * 
	 * @param entityManager entityManager to load entities with
	 * @param entityClass   class of entites to load
	 * @param contextType   {@link ContextType} of entities of null if none
	 * @return the appropriate loadAllEntities() method
	 */
	private <T extends Entity> CheckedFunction0<java.util.List<T>> getLoadAllEntitiesMethod(EntityManager entityManager,
			Class<T> entityClass, Value<ContextType> contextType) {
		// if contextType is specified
		if (contextType != null && !contextType.isEmpty()) {
			return (() -> entityManager.loadAll(entityClass, contextType.get()));
		}
		return (() -> entityManager.loadAll(entityClass));
	}

	/**
	 * Creates a new {@link Entity} of type entityClass. The method searches the
	 * {@link EntityFactory} for a suitable create() method by matching the return
	 * parameter and the given entity class. If more than one method is found, the
	 * first one is taken. The argument are provided by {@link Try<Object>}s so that
	 * any exceptions thrown throughout retrieval will be wrapped in the returned
	 * {@link Try}.
	 * 
	 * @param sourceName  name of the source (MDM {@link Environment} name)
	 * @param entityClass class of the {@link Entity} to create
	 * @param arguments   arguments for corresponding EntityFactory.createX()
	 * @return a {@link Try} with the created {@link Entity}
	 */
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> create(String sourceName, Class<T> entityClass, Seq<Value<?>> argumentSuppliers) {
		// get corresponding create method for entityClass from EntityFactory
		return Try.of(() -> connectorService.getContextByName(sourceName).getEntityFactory())
				.mapTry(factory -> (T) Stream.of(EntityFactory.class.getMethods())
						// find method with the return type matching entityClass
						.filter(m -> m.getReturnType().equals(entityClass))
						.filter(m -> satisfiesParameters(m.getParameterTypes(),
								argumentSuppliers.flatMap(s -> s.map(Object::getClass))))
						.getOrElseThrow(
								() -> new NoSuchMethodException("No matching create()-method found for EntityType "
										+ entityClass.getSimpleName() + " taking the parameters "
										+ argumentSuppliers.flatMap(s -> s.map(a -> a.getClass().getName()))
												.collect(Collectors.joining(", "))))
						// invoke with given arguments
						.invoke(factory.get(), argumentSuppliers.map(Value::get).toJavaArray()))
				.mapFailure(Case($(instanceOf(InvocationTargetException.class)),
						t -> ((InvocationTargetException) t).getTargetException()), Case($(), t -> t))
				.map(e -> (T) DataAccessHelper
						.execute(getEntityManager(sourceName).get(), Tuple.of(e, DataAccessHelper.CREATE))
						.toArray()[0]);
	}

	/**
	 * Checks if the given parameter types are all assignable from the required
	 * parameters
	 * 
	 * @param parameterTypes
	 * @param requiredParameters
	 * @return true if the given parameter types are all assignable from the
	 *         required parameters
	 */
	@VisibleForTesting
	boolean satisfiesParameters(Class<?>[] parameterTypes, Seq<Class<?>> requiredParameters) {
		boolean result = parameterTypes.length == requiredParameters.length();
		result &= List.of(parameterTypes).zip(requiredParameters).filter(t -> !ReflectUtil.isAssignable(t._2(), t._1()))
				.isEmpty();
		return result;
	}

	/**
	 * Extract arguments from request defaulting to extract MDMEntity.name see also
	 * {@link #extractArgumentsFromRequestBody(String, MDMEntityResponse, List, List)}
	 */
	public Seq<Value<?>> extractArgumentsFromRequestBody(String sourceName, MDMEntityResponse body) {
		return extractArgumentsFromRequestBody(sourceName, body, List.of("Name"), List.empty());
	}

	/**
	 * Extract arguments from request body to use for {@link EntityFactory} create
	 * methods. If and argument given by attributeArguments or relationArguments
	 * cannot be found, they are skipped.
	 * 
	 * @param sourceName         name of the source (MDM {@link Environment} name)
	 * @param body               deserialized request to extract arguments from
	 * @param attributeArguments list of names of attributes to extract values from
	 * @param relationArguments  classes of related entities to extract from
	 * @return the extracted arguments as a {@link Seq} of {@link Value}.
	 */
	public final Seq<Value<?>> extractArgumentsFromRequestBody(String sourceName, MDMEntityResponse body,
			List<String> attributeArguments, List<Class<? extends Entity>> relationArguments) {
		List<Try<?>> extractedArguments = List.empty();

		// if there arguments to be extracted from MDMEntity.attributes
		if (attributeArguments != null) {
			// although the name of the entity to be created is an attribute, it could also
			// be given as MDMEntity.name instead of MDMEntity.attributes("Name")
			extractedArguments = extractedArguments.appendAll(
					attributeArguments.filter(attrName -> attrName.equalsIgnoreCase("name")).map(attrName -> Try
							.of(() -> decompose(body::getData).<MDMEntity>getAt(0).get(MDMEntity::getName)).get()));

			extractedArguments = extractedArguments
					// ignore name attr if already processed
					.appendAll(attributeArguments.filter(attrName -> !attrName.equalsIgnoreCase("name"))//
							.map(attrName -> Try.of(() -> //
							decompose(body::getData) //
									.<MDMEntity>getAt(0) //
									.<MDMAttribute, String>getFiltered(MDMEntity::getAttributes, MDMAttribute::getName,
											attrName) //
									.map(attr -> {
										Object value = attr.getValue().toString();
										if (attr.getDataType().equals("ENUMERATION")) {
											value = EnumRegistry.getInstance().get(EnumRegistry.VALUE_TYPE)
													.valueOf(value.toString());
										}
										return value;
									}).get())));
		}

		// wrap find in Try to handle non-existing relation (not all entityClasses must
		// exist as a relation)
		if (relationArguments != null) {
			extractedArguments = extractedArguments
					.appendAll(relationArguments.map(clazz -> Try.of(() -> find(sourceName, clazz, //
							// get IDs of related entities
							decompose(body::getData).<MDMEntity>getAt(0) //
									.<MDMRelation, String>getFiltered(MDMEntity::getRelations,
											MDMRelation::getEntityType, clazz.getSimpleName()) //
									.get(MDMRelation::getIds).getValueAt(0),
							// get ContextType; if not present, find() ignores null value
							Try.of(() -> decompose(body::getData).<MDMEntity>getAt(0) //
									.<MDMRelation, String>getFiltered(MDMEntity::getRelations,
											MDMRelation::getEntityType, clazz.getSimpleName()) //
									.get(MDMRelation::getContextType)).getOrElse((Decomposer<ContextType>) null)) //
											.get())));
		}

		// log failures as warnings
		extractedArguments.filter(Try::isFailure)
				.forEach(failure -> LOGGER.warn("Argument to extract not found: {}", failure.getCause().getMessage()));

		return extractedArguments.filter(Try::isSuccess).map(Try::toOption);
	}

	/**
	 * Updates the given {@link Entity} with the values of the given map provided by
	 * the {@code valueMapSupplier}.
	 * 
	 * @param sourceName       name of the source (MDM {@link Environment} name)
	 * @param entity           the entity to update
	 * @param valueMapSupplier {@link Supplier<Map<String, Object>> of a map of
	 * values to update the entity with according to matching attribute values by
	 * name case sensitive
	 * @return a {@link Try} of the updated entity
	 */
	// TODO "anehmer" on 2019-03-29: remove method
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> update(String sourceName, Try<T> entity,
			Value<Map<String, Object>> valueMapSupplier) {
		// return updated entity
		return
		// update entity values
		entity.map(e -> updateEntityValues(sourceName, e, valueMapSupplier.get()))
				// persist entity
				.map(e -> (T) DataAccessHelper
						.execute(getEntityManager(sourceName).get(), Tuple.of(e.get(), DataAccessHelper.UPDATE))
						.toArray()[0]);
	}

	/**
	 * Updates the given {@link Entity} with the values of the given
	 * {@link MDMEntity}
	 * 
	 * @param sourceName name of the source (MDM {@link Environment} name)
	 * @param entity     the entity to update
	 * @param mdmEntity  the update source
	 * @return a {@link Try} of the updated entity
	 */
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> update(String sourceName, Try<T> entity, MDMEntity mdmEntity) {
		// return updated entity
		return
		// update entity values
		entity.map(e -> updateEntity(e, mdmEntity))
				// persist entity
				.map(e -> (T) DataAccessHelper
						.execute(getEntityManager(sourceName).get(), Tuple.of(e.get(), DataAccessHelper.UPDATE))
						.toArray()[0]);
	}

	/**
	 * Deletes the given {@link Entity} {@code valueMapSupplier}.
	 * 
	 * @param sourceName name of the source (MDM {@link Environment} name)
	 * @param entity     the entity to delete
	 * @return a {@link Try} of the deleted entity
	 */
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> delete(String sourceName, Try<T> entity) {
		return entity.map(e -> (T) DataAccessHelper
				.execute(getEntityManager(sourceName).get(), Tuple.of(e, DataAccessHelper.DELETE)).toArray()[0]);
	}

	/**
	 * Returns a {@link Try} of the the {@link SearchAttribute}s for the given
	 * entityClass
	 * 
	 * @param sourceName  name of the source (MDM {@link Environment} name)
	 * @param entityClass class of the {@link Entity} to get the
	 *                    {@link SearchAttribute}s for
	 * 
	 * @return a {@link Try} with the {@link SearchAttribute}s
	 */
	public <T extends Entity> Try<List<SearchAttribute>> getSearchAttributesSupplier(String sourceName,
			Class<T> entityClass) {
		return Try.of(() -> List.ofAll(this.searchActivity
				.listAvailableAttributes(connectorService.getContextByName(sourceName), entityClass)));
	}

	/**
	 * Returns a {@link Try} of the localized {@link Entity} type name
	 * 
	 * @param sourceName  name of the source (MDM {@link Environment} name)
	 * @param entityClass class of the {@link Entity} to be localized
	 * 
	 * @return a {@link Try} with the localized {@link Entity} type name
	 */
	public <T extends Entity> Try<Map<EntityType, String>> getLocalizeTypeSupplier(String sourceName,
			Class<T> entityClass) {
		return Try.of(() -> HashMap.ofAll(this.i18nActivity.localizeType(sourceName, entityClass)));
	}

	/**
	 * Returns a {@link Try} of the localized {@link Entity} attributes
	 * 
	 * @param sourceName  name of the source (MDM {@link Environment} name)
	 * @param entityClass class of the {@link Entity} to be localized
	 * @return a {@link Try} with the the localized {@link Entity} attributes
	 */
	public <T extends Entity> Try<Map<Attribute, String>> getLocalizeAttributesSupplier(String sourceName,
			Class<T> entityClass) {
		return Try.of(() -> HashMap.ofAll(this.i18nActivity.localizeAttributes(sourceName, entityClass)));
	}

	/**
	 * Returns a {@link Try} of an {@link EnumerationValue} for the name supplied by
	 * the {@code enumValueNameSupplier}
	 * 
	 * @param enumValueNameSupplier supplies the name of the
	 *                              {@link EnumerationValue} to get
	 * @return a {@link Try} with the resolved {@link EnumerationValue}
	 */
	public Try<EnumerationValue> getEnumerationValueSupplier(Try<?> enumValueNameSupplier) {
		return Try.of(() -> EnumRegistry.getInstance().get(EnumRegistry.VALUE_TYPE)
				.valueOf(enumValueNameSupplier.get().toString()));
	}

	/**
	 * Gets the EntityManager from the ConnectorService with the given source name
	 * 
	 * @param sourceName the name of the datasource to get EntityManager for
	 * @return the found EntityManager. Throws {@link MDMEntityAccessException} if
	 *         not found.
	 */
	public Try<EntityManager> getEntityManager(String sourceName) {
		return Try.of(() -> this.connectorService.getContextByName(sourceName).getEntityManager()
				.orElseThrow(() -> new MDMEntityAccessException("Entity manager not present")));
	}

	/**
	 * Updates the given {@link Entity} with the values from the given valueMap. All
	 * matching attributes (case sensitive) are updated as well as the referenced
	 * relations by the id of the given
	 * {@link org.eclipse.mdm.api.base.model.Entity} and the simple class name as
	 * the key (the data model attribute name is the reference, case sensitive).
	 * 
	 * @param entity   the entity to update
	 * @param valueMap values to update the entity with according to matching
	 *                 attribute names. The keys are compared case sensitive.
	 * @return a {@link Try} with the the updated entity
	 */
	// TODO "anehmer" on 2019-03-29: remove method
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> updateEntityValues(String sourceName, T entity, Map<String, Object> valueMap) {

		HashMap<String, org.eclipse.mdm.api.base.model.Value> entityValues = HashMap.ofAll(entity.getValues());
		// normalized value map (convert all attribute names to upper camel case)
		valueMap = valueMap.bimap(k -> k.substring(0, 1).toUpperCase() + k.substring(1), v -> v);

		// update primitive values where the key from the valueMap has a matching entity
		// value and collect the updated keys
		Set<String> updatedPrimitiveValues = valueMap
				.filter((valueMapEntryKey, valueMapEntryValue) -> entityValues.containsKey(valueMapEntryKey)
						&& !(valueMapEntryValue instanceof java.util.Map))
				.map((entityValueEntryKey, entityValueEntryValue) -> {
					entityValues.get(entityValueEntryKey)
							.forEach(value -> Serializer.applyValue(value, entityValueEntryValue));
					return Tuple.of(entityValueEntryKey, entityValueEntryValue);
				}).keySet();

		// update enumeration values
		Set<String> updatedEnumerationValues = valueMap
				.filter((valueMapEntryKey, valueMapEntryValue) -> entityValues.containsKey(valueMapEntryKey)
						&& (valueMapEntryValue instanceof java.util.Map))
				.map((entityValueEntryKey, entityValueEntryValue) -> {
					entityValues.get(entityValueEntryKey).forEach(value -> {
						// get key-value-pairs that identify the enum und enumValue
						String enumName = ((java.util.Map<String, String>) entityValueEntryValue).get("Enumeration");
						String enumValueName = ((java.util.Map<String, String>) entityValueEntryValue)
								.get("EnumerationValue");

						if (enumName == null || enumValueName == null) {
							throw new IllegalArgumentException("EnumerationValue is set by providing a map "
									+ "containing the keys 'Enumeration' and 'EnumerationValue' "
									+ "and the respective names as the values");
						}

						// find enumeration and the enumeration value
						Option.of(EnumRegistry.getInstance()
								// get enum
								.get(enumName)).onEmpty(() -> {
									throw new IllegalArgumentException("Enumeration [" + enumName + "] not found");
								})
								// get enumValue
								.map(enumeration -> enumeration.valueOf(enumValueName))
								// if enumValue is not found, null is returned
								.filter(Objects::nonNull).onEmpty(() -> {
									throw new IllegalArgumentException("EnumerationValue [" + enumValueName
											+ "] not found in Enumeration [" + enumName + "]");
								})
								// set enumValue
								.map(enumValue -> {
									value.set(enumValue);
									return enumValue;
								});

					});
					return Tuple.of(entityValueEntryKey, entityValueEntryValue);
				}).keySet();

		// update the relations and gather the updated keys
		// use only those keys that have not been updated yet and can be resolved as
		// class names. If so, try to update accordingly named relation with the entity
		// found by its id given as the value
		Set<String> updatedRelations = valueMap
				.filter((valueMapEntryKey, valueMapEntryValue) -> !updatedPrimitiveValues.contains(valueMapEntryKey)
						&& !updatedEnumerationValues.contains(valueMapEntryKey))
				.filter((relatedEntityClassName, relatedEntityId) -> {
					EntityStore store = ServiceUtils.getCore(entity).getMutableStore();

					ContextType contextType = null;
					// determine if class has a context type
					for (ContextType ct : ContextType.values()) {
						int index = relatedEntityClassName.toUpperCase().indexOf(ct.name());
						if (index > 0) {
							contextType = ct;
							// cut out ContextType
							relatedEntityClassName = relatedEntityClassName.substring(0, index)
									+ relatedEntityClassName.substring(index + ct.name().length());
						}
					}

					// to have final variables for Try
					final String processedRelatedEntityClassName = relatedEntityClassName;
					final ContextType contextTypeIfPresent = contextType;

					// load class from model packages
					Try<Class<Entity>> updateTry = Try
							.of(() -> (Class<Entity>) Class
									.forName("org.eclipse.mdm.api.base.model." + processedRelatedEntityClassName))
							.orElse(Try.of(() -> (Class<Entity>) Class
									.forName("org.eclipse.mdm.api.dflt.model." + processedRelatedEntityClassName)))
							// update related entity by first finding the related entity by its id
							// use find and store.set() with ContextType if needed
							.andThenTry(entityClass -> {
								if (contextTypeIfPresent == null) {
									store.set(find(sourceName, entityClass, relatedEntityId.toString())
											.onFailure(e -> LOGGER.error(e.getMessage())).get());
								} else {
									store.set(
											find(sourceName, entityClass, relatedEntityId.toString(),
													V(contextTypeIfPresent))
															.onFailure(e -> LOGGER.error(e.getMessage())).get(),
											contextTypeIfPresent);
								}
							}).onFailure(e -> LOGGER.error("Entity of type [" + processedRelatedEntityClassName
									+ "] and ID " + relatedEntityId + " not found", e));

					return updateTry.isSuccess() ? true : false;
				}).keySet();

		// return Try.Failure if there are keys that are not present in the entity and
		// thus are not updated
		String unmappedKeys = valueMap.filterKeys(key -> !updatedPrimitiveValues.contains(key)
				&& !updatedEnumerationValues.contains(key) && !updatedRelations.contains(key)).map(Tuple::toString)
				.collect(Collectors.joining(", "));

		if (unmappedKeys != null && !unmappedKeys.isEmpty()) {
			return Try.failure(
					new IllegalArgumentException("ValueMap to update entity contains the following keys that either "
							+ "have no match in the entity vaues or relations to update "
							+ "or an error occurred while finding the related entity: " + unmappedKeys));
		} else {
			return Try.of(() -> entity);
		}
	}

	/**
	 * Updates the given {@link Entity} with the values from the given
	 * {@link MDMEntity}. Values are ignored if value attribute is empty. Lists are
	 * fully replaced as no remove-from-related-entities-list-operation is
	 * available.
	 * 
	 * @param entity   the entity to update
	 * @param valueMap values to update the entity (attributes and related entities)
	 *                 according to matching MDMAttribute and MDMRelation data
	 * @return a {@link Try} with the the updated entity
	 */
	@SuppressWarnings("unchecked")
	public <T extends Entity> Try<T> updateEntity(T entity, MDMEntity mdmEntity) {
		// update attributes
		// take all given attributes
		return Try.of(() -> List.ofAll(mdmEntity.getAttributes())
				// and filter out those which dont't have values
				.filter(Objects::nonNull)
				// update the single values of the entity
				// call applyValue() on entity for every given attribute. If an error occurs
				// the returned Try holds the Failure
				.foldLeft(Try.of(() -> entity), //
						(updateTry, attr) -> updateTry.andThen(() -> //
						// encapsulate applyValue in a Try to get attribute specific error
						Try.of(() -> {
							Serializer.applyValue(entity.getValue(attr.getName()), attr.getValue());
							return null;
						}).mapFailure(
								Case($(),
										t -> new MDMEntityAccessException("Error while updating attribute ["
												+ attr.getName() + "]: " + t.getMessage(), t)))
								.get()))
				// update relations
				.transform(updateTry ->
				// take all given relations
				List.ofAll(mdmEntity.getRelations())
						// call this::updateRelation with every relation on the entity
						.foldLeft(updateTry, this::updateRelation))
				.get());
	}

	/**
	 * Updates the entity's relation with the given relation
	 * 
	 * @param entityTry entity to update
	 * @param relation  relation to update corresponding entity relation with
	 */
	private <T extends Entity> Try<T> updateRelation(Try<T> entityTry, MDMRelation relation) {
		return entityTry.map(e -> API.unchecked(() -> {
			RelationType type = relation.getType();

			if (type == RelationType.CHILDREN) {
				Class<Deletable> entityClass = getEntityClass(relation.getEntityType());
				ChildrenStore childrenStore = ServiceUtils.getCore(e).getChildrenStore();
				List<Deletable> relatedEntities = List
						// children can be empty
						.ofAll(childrenStore.getCurrent().getOrDefault(entityClass, new ArrayList<Deletable>()));

				return List.ofAll(relation.getIds())
						// delete all entities not present in given relations
						.transform(relationList -> {
							relatedEntities.filter(relatedEntity -> !relationList.contains(relatedEntity.getID()))
									.forEach(childrenStore::remove);
							return relationList;
						})
						// process new related entities; get all ids not already in relatedEntities
						.filter(id -> !relatedEntities.map(Entity::getID).contains(id))
						// find entity for id
						.foldLeft(entityTry,
								// find the entity by the given id and the loaded class from the relation
								(findTry, id) -> {
									// use diffenrent find method if ContextType is present
									Try.of(relation::getContextType)
											// if ContextType is given, find with ContextType
											.map(contextType -> find(e.getSourceName(), entityClass, id, V(contextType),
													SL(e.getID())))
											// find without contextType
											.getOrElse(find(e.getSourceName(), entityClass, id, SL(e.getID())))
											// add to children store
											.andThen(childrenStore::add).get();
									return entityTry;
								});
			} else if (type == RelationType.MUTABLE) {
				EntityStore mutableStore = ServiceUtils.getCore(e).getMutableStore();
				List<Entity> relatedEntities = List.ofAll(mutableStore.getCurrent())
						.filter(re -> re.getTypeName().equals(relation.getEntityType()));
				Class<Entity> entityClass = getEntityClass(relation.getEntityType());

				return List.ofAll(relation.getIds())
						// delete all entities not present in given relations
						.transform(relationList -> {
							relatedEntities.filter(relatedEntity -> !relationList.contains(relatedEntity.getID()))
									.forEach(relatedEntity ->
							// diff if ContextType
							mutableStore.remove(relatedEntity.getClass()));
							return relationList;
						})
						// process new related entities; get all ids not already in relatedEntities
						.filter(id -> !relatedEntities.map(Entity::getID).contains(id))
						// find entity for id
						.foldLeft(entityTry,
								// find the entity by the given id and the loaded class from the relation
								(findTry, id) -> {
									// safe use of get() as any exception thrown is covered by the enclosing Try
									ContextType ct = relation.getContextType();
									if (ct != null) {
										mutableStore.set(find(e.getSourceName(), entityClass, id, V(ct)).get(), ct);
									} else {
										mutableStore.set(find(e.getSourceName(), entityClass, id).get());
									}

									return entityTry;
								});

			}
			// return updated entity
			return entityTry;
		}).apply()).get();
	}

	@SuppressWarnings("unchecked")
	private <T extends Entity> Class<T> getEntityClass(String type) throws ClassNotFoundException {
		return Try.of(() -> (Class<T>) Class.forName("org.eclipse.mdm.api.base.model." + type))
				.orElse(Try.of(() -> (Class<T>) Class.forName("org.eclipse.mdm.api.dflt.model." + type)))
				.getOrElseThrow(e -> new ClassNotFoundException(
						"No corresponding class with name [" + type + "] found in base.model or dflt.model"));
	}

	// TODO: Clarify which input should be handled.
	// TODO: Improve error msg?
	public Seq<Value<?>> extractRequestBody(String body, String sourceName,
			List<Class<? extends Entity>> entityClasses) {
		RequestBody requestBody = RequestBody.create(body);
		List<Try<?>> name = List.of(requestBody.getStringValueSupplier(ENTITYATTRIBUTE_NAME));

		// Mandatory in ChannelGroup.
		Try<?> numberOfValues = requestBody.getStringValueSupplier(ENTITYATTRIBUTE_NUMBER_OF_VALUES)
				.map(val -> Integer.parseInt(val));

		if (numberOfValues.isSuccess()) {
			name = name.append(numberOfValues);
		}

		return entityClasses
				.map(clazz -> find(sourceName, clazz, requestBody.getStringValueSupplier(clazz.getSimpleName()).get()))
				.foldLeft(name, (l, e) -> l.append(e)).filter(Try::isSuccess).map(Try::toOption);
	}

	public MDMEntity removeVirtualAttributes(MDMEntity entity) {
		java.util.List<MDMAttribute> attributes = entity.getAttributes().stream()
				.filter(attr -> !attr.getName().startsWith("@")).collect(Collectors.toList());
		return new MDMEntity(entity.getName(), entity.getId(), entity.getType(), entity.getSourceType(),
				entity.getSourceName(), attributes, entity.getRelations());
	}
}