/*******************************************************************************
 * Copyright (c) 2011-2020 The University of York.
 * 
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
 *
 * Contributors:
 *     Konstantinos Barmpis - initial API and implementation
 *     Antonio Garcia-Dominguez - protect against null EPackage nsURIs
 ******************************************************************************/
package org.hawk.graph.updater;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.hawk.core.IMetaModelResourceFactory;
import org.hawk.core.IModelIndexer;
import org.hawk.core.graph.IGraphChangeListener;
import org.hawk.core.graph.IGraphDatabase;
import org.hawk.core.graph.IGraphEdge;
import org.hawk.core.graph.IGraphIterable;
import org.hawk.core.graph.IGraphNode;
import org.hawk.core.graph.IGraphNodeIndex;
import org.hawk.core.graph.IGraphTransaction;
import org.hawk.core.model.IHawkAttribute;
import org.hawk.core.model.IHawkClass;
import org.hawk.core.model.IHawkClassifier;
import org.hawk.core.model.IHawkDataType;
import org.hawk.core.model.IHawkMetaModelResource;
import org.hawk.core.model.IHawkObject;
import org.hawk.core.model.IHawkPackage;
import org.hawk.core.model.IHawkReference;
import org.hawk.core.model.IHawkStructuralFeature;
import org.hawk.core.runtime.CompositeGraphChangeListener;
import org.hawk.core.util.CompositeException;
import org.hawk.graph.FileNode;
import org.hawk.graph.ModelElementNode;
import org.hawk.graph.Slot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GraphMetaModelResourceInjector {
	private static final Logger LOGGER = LoggerFactory.getLogger(GraphMetaModelResourceInjector.class);

	/**
	 * Represents the case when the insertion of a metamodel fails.
	 */
	public static class FailedMetamodelRegistrationException extends Exception {
		private static final long serialVersionUID = 1L;

		public FailedMetamodelRegistrationException(String metamodelURI, Throwable reason) {
			super(String.format("Failed to register metamodel '%s': %s", metamodelURI, reason.getMessage()), reason);
		}
	}

	/**
	 * Represents the situation when a particular metamodel is missing, so a certain
	 * EClass cannot be registered.
	 */
	public static class MissingMetamodelException extends Exception {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public MissingMetamodelException(String metamodelURI) {
			super(String.format("Missing metamodel with URI '%s'", metamodelURI));
		}
	}

	// integer array containing the current number of added elements:
	// (element,((ofType)M->MM)reference,((ofKind)M->MM)reference,(unset(M->M))reference)
	private int objectCount = 0;

	private IModelIndexer hawk;
	private IGraphDatabase graph;

	private final long startTime = System.nanoTime();
	private final CompositeGraphChangeListener listener;

	public GraphMetaModelResourceInjector(IModelIndexer hawk, Set<IHawkMetaModelResource> set, CompositeGraphChangeListener listener) throws Exception {
		this.hawk = hawk;
		this.graph = hawk.getGraph();
		this.listener = listener;

		LOGGER.info("ADDING METAMODELS: ");
		LOGGER.info("ADDING: ");
		int nodes = insertMetamodels(set);
		LOGGER.info("{} METAMODEL NODES! (took ~{} sec)", nodes, (System.nanoTime() - startTime) / 1_000_000_000);
	}

	public GraphMetaModelResourceInjector(IModelIndexer hawk, CompositeGraphChangeListener listener) {
		this.hawk = hawk;
		this.graph = hawk.getGraph();
		this.listener = listener;
	}

	/**
	 * Removes all the metamodel resources and their dependent model elements from the index.
	 */
	public void removeMetamodels(Set<IHawkMetaModelResource> set) {

		try (IGraphTransaction t = graph.beginTransaction()) {
			listener.changeStart();
			IGraphNodeIndex ePackageDictionary = graph.getMetamodelIndex();
			Set<IGraphNode> epns = new HashSet<>();

			for (IHawkMetaModelResource metamodelResource : set) {
				// if (resourceset == null)
				// resourceset = metamodelResource.getResourceSet();

				Set<IHawkObject> children = metamodelResource.getAllContents();

				for (IHawkObject child : children) {

					// if (child.eIsProxy()) {
					// throw new Exception("FAILED. PROXY UNRESOLVED: "
					// + ((InternalEObject) child).eProxyURI()
					// .fragment());
					// }

					// add the element
					if (child instanceof IHawkPackage) {

						Iterator<? extends IGraphNode> it = ePackageDictionary.get("id", ((IHawkPackage) child).getNsURI()).iterator();

						if (!it.hasNext()) {
							LOGGER.warn("Metamodel: {} with uri: {} not indexed. Nothing happened.",
									((IHawkPackage) child).getName(), ((IHawkPackage) child).getNsURI());
						} else {
							IGraphNode epn = it.next();
							LOGGER.info("Removing metamodel: {} with uri: {}", ((IHawkPackage) child).getName(), ((IHawkPackage) child).getNsURI());
							epns.add(epn);
						}
					}
				}
			}

			removeAll(epns);

			t.success();
			listener.changeSuccess();

		} catch (Exception e1) {
			listener.changeFailure();
			LOGGER.error("Error in removing metamodels (all removal changes reverted)", e1);
		}

	}

	/**
	 * Removes all the metamodels and models dependent on the <code>epsn</code> metamodel nodes.
	 * 
	 * @return URIs of the repositories impacted by the removal.
	 */
	private Set<String> removeAll(Set<IGraphNode> epns) throws Exception {

		Set<String> affectedRepositories = new HashSet<>();

		DeletionUtils del = new DeletionUtils(graph);

		for (IGraphNode epn : epns)
			for (IGraphEdge rel : epn.getIncomingWithType(IModelIndexer.METAMODEL_DEPENDENCY_EDGE)) {
				LOGGER.debug("dependency from {} to {}",
						rel.getStartNode().getProperty(IModelIndexer.IDENTIFIER_PROPERTY),
						epn.getProperty(IModelIndexer.IDENTIFIER_PROPERTY));

				// delete all dependent metamodels and models
				IGraphNode depmm = rel.getStartNode();
				del.delete(rel);
				epns.add(depmm);
			}

		Set<IGraphNode> files = new HashSet<>();

		for (IGraphNode n : epns)
			files.addAll(remove(n));

		for (IGraphNode file : files)
			affectedRepositories.add(file.getProperty(FileNode.PROP_REPOSITORY).toString());

		for (IGraphNode file : files)
			del.delete(file);

		return affectedRepositories;

	}

	private Set<IGraphNode> remove(IGraphNode epn) throws Exception {

		long start = System.currentTimeMillis();

		HashSet<IGraphNode> fileNodes = new HashSet<IGraphNode>();

		try (IGraphTransaction transaction = graph.beginTransaction()) {
			LOGGER.info("Deleting nodes from metamodel: {}", epn.getProperty(IModelIndexer.IDENTIFIER_PROPERTY));

			HashSet<IGraphNode> metaModelElements = new HashSet<IGraphNode>();
			HashSet<IGraphNode> modelElements = new HashSet<IGraphNode>();

			DeletionUtils del = new DeletionUtils(graph);

			for (IGraphEdge rel : epn.getIncomingWithType("epackage")) {
				metaModelElements.add(rel.getStartNode());
				del.delete(rel);
			}

			for (IGraphEdge rel : epn.getOutgoingWithType(IModelIndexer.METAMODEL_DEPENDENCY_EDGE)) {
				del.delete(rel);
			}

			del.delete(epn);

			for (IGraphNode metamodelelement : metaModelElements) {
				for (IGraphEdge rel : metamodelelement.getIncomingWithType(ModelElementNode.EDGE_LABEL_OFTYPE)) {
					modelElements.add(rel.getStartNode());
					del.delete(rel);
				}
			}
			for (IGraphNode metamodelelement : metaModelElements) {
				for (IGraphEdge rel : metamodelelement.getIncomingWithType(ModelElementNode.EDGE_LABEL_OFKIND)) {
					modelElements.add(rel.getStartNode());
					del.delete(rel);
				}
			}

			for (IGraphNode metaModelElement : metaModelElements)
				del.delete(metaModelElement);

			// remove model elements and update derived attributes

			if (modelElements.size() > 0) {
				LOGGER.info("Deleting nodes from relevant models...");

				Set<IGraphNode> toBeUpdated = new HashSet<>();
				final DirtyDerivedFeaturesListener l = new DirtyDerivedFeaturesListener(graph);
				if (!hawk.getDerivedAttributes().isEmpty()) {
					hawk.addGraphChangeListener(l);
				}

				for (IGraphNode modelElement : modelElements) {
					Iterator<IGraphEdge> it = modelElement.getOutgoingWithType(ModelElementNode.EDGE_LABEL_FILE)
							.iterator();
					if (it.hasNext()) {
						IGraphEdge e = it.next();
						fileNodes.add(e.getEndNode());
						del.delete(e);

					}

					del.dereference(modelElement, listener, null);
				}

				for (IGraphNode modelElement : modelElements) {

					del.delete(modelElement);

				}

				toBeUpdated.addAll(l.getNodesToBeUpdated());
				listener.remove(l);

				LOGGER.info("Updating any relevant derived attributes...");
				try {
					new GraphModelInserter(hawk, () -> del, new TypeCache(hawk))
							.updateDerivedAttributes(hawk.getDerivedAttributeExecutionEngine(), toBeUpdated);
					toBeUpdated = new HashSet<>();
				} catch (Exception e) {
					toBeUpdated = new HashSet<>();
					LOGGER.error("Exception while updating derived attributes", e);
				}

			}

			transaction.success();
		}

		LOGGER.info("deleted all, took: {}s", (System.currentTimeMillis() - start) / 1000.0);
		return fileNodes;
	}

	/**
	 * Inserts a number of metamodels into the graph.
	 * 
	 * @param metamodels Metamodel resources to be registered.
	 * @return Number of added objects.
	 * @throws A single exception, or a {@link CompositeException} with multiple
	 *           exceptions that have happened for this set of metamodels.
	 */
	private int insertMetamodels(Set<IHawkMetaModelResource> metamodels) throws Exception {
		// Expand set with dependencies if needed
		Map<String, IHawkPackage> expanded = new HashMap<>();
		expandWithDependencies(metamodels, expanded);

		// TODO: simplify rest of code after testing early dependency detection

		// Create the EPackage nodes
		Set<IHawkPackage> addedPackages = new HashSet<>();
		try (IGraphTransaction t = graph.beginTransaction()) {
			listener.changeStart();
			IGraphNodeIndex ePackageDictionary = graph.getMetamodelIndex();

			for (IHawkPackage pkg : expanded.values()) {
				if (addEPackage(pkg, ePackageDictionary)) {
					addedPackages.add(pkg);
				}
			}

			t.success();
			listener.changeSuccess();
		} catch (Exception ex) {
			listener.changeFailure();
			throw ex;
		}

		// Create the EClass nodes inside each EPackage
		List<Exception> exceptions = new ArrayList<>();
		Iterator<IHawkPackage> itPackage = addedPackages.iterator();
		while (itPackage.hasNext()) {
			IHawkPackage epackage = itPackage.next();

			boolean revert = false;
			final IGraphTransaction t = graph.beginTransaction();
			try {
				listener.changeStart();
				addEClasses(epackage);
				t.success();
				listener.changeSuccess();
			} catch (Exception eAddPackage) {
				LOGGER.error(eAddPackage.getMessage(), eAddPackage);
				t.failure();
				listener.changeFailure();
				exceptions.add(new FailedMetamodelRegistrationException(epackage.getNsURI(), eAddPackage));
				itPackage.remove();
				revert = true;
			} finally {
				t.close();
			}

			if (revert) {
				// Revert the addition of the metamodel node
				try (IGraphTransaction t2 = graph.beginTransaction()) {
					IGraphNode ePackageNode = graph.getMetamodelIndex().get("id", epackage.getNsURI()).iterator().next();
					new DeletionUtils(graph).delete(ePackageNode);
					t2.success();
				} catch (Exception eRevertAddition) {
					LOGGER.error(eRevertAddition.getMessage(), eRevertAddition);
					exceptions.add(eRevertAddition);
				}
			}
		}

		for (IHawkPackage ePackage : addedPackages) {
			try (IGraphTransaction t = graph.beginTransaction()) {
				final IGraphNode epackagenode = graph.getMetamodelIndex().get("id", ePackage.getNsURI()).getSingle();

				// add resource to package
				final Optional<String> s = ePackage.getResource().getMetaModelResourceFactory().dumpPackageToString(ePackage);
				if (s.isPresent()) {
					epackagenode.setProperty(IModelIndexer.METAMODEL_RESOURCE_PROPERTY, s.get());
				}
				t.success();
			} catch (Exception eSaveResource) {
				LOGGER.error("Cannot save package into the metamodel node", eSaveResource);
				exceptions.add(eSaveResource);
			}
		}

		// Throw any collected exceptions if we have them
		if (!exceptions.isEmpty()) {
			throw new CompositeException(exceptions);
		}

		return objectCount;
	}

	/**
	 * Performs dependency resolution on a set of metamodels, by applying a
	 * fixed-point algorithm where we keep adding metamodels as we find new
	 * dependencies, until we do not have any pending metamodels or we run into a
	 * metamodel that we cannot obtain.
	 * 
	 * If we successfully exit from this method, it means that the value set of
	 * {@code expanded} is complete, perhaps reusing some packages that are already
	 * in the graph.
	 * 
	 * @throws MissingMetamodelException A metamodel that this set depends upon
	 *                                   could not be found.
	 * @throws Exception                 Another type of exception occurred during
	 *                                   the dependency resolution. This will most
	 *                                   likely be an issue with the node indices.
	 */
	private void expandWithDependencies(Set<IHawkMetaModelResource> metamodels, Map<String, IHawkPackage> expanded) throws Exception {
		final Set<String> alreadyInGraph = new HashSet<>();

		boolean firstBatch = false;
		do {
			for (Iterator<IHawkMetaModelResource> itM = metamodels.iterator(); itM.hasNext();) {
				IHawkMetaModelResource m = itM.next();
				for (IHawkObject child : m.getAllContents()) {
					if (child instanceof IHawkPackage) {
						final IHawkPackage pkg = (IHawkPackage) child;
						if (pkg.getNsURI() == null) {
							LOGGER.info("Package {} has null URI, ignoring", pkg.getName());
						} else if (firstBatch && isMetamodelRegistered(pkg.getNsURI())) {
							// First round: the graph may already have some of the provided metamodels 
							alreadyInGraph.add(pkg.getNsURI());
							itM.remove();
							LOGGER.info("Package {} already in the graph, ignoring", pkg.getNsURI());
						} else {
							expanded.put(pkg.getNsURI(), pkg);
						}
					}
				}
			}
			firstBatch = false;

			// Find out which metamodels this batch requires that we are missing so far
			final Set<String> missingURIs = new HashSet<>();
			addPendingDependencies(metamodels, expanded, missingURIs, alreadyInGraph);

			// Try to locate the missing metamodels, or abort
			metamodels.clear();
			missingMetamodels:
			for (String uri : missingURIs) {
				for (IMetaModelResourceFactory mp : hawk.getMetaModelParsers()) {
					IHawkMetaModelResource mr = mp.getMetamodel(uri);
					if (mr != null) {
						metamodels.add(mr);
						continue missingMetamodels;
					}
				}
				throw new MissingMetamodelException(uri);
			}

		} while (!metamodels.isEmpty());

	}

	private void addPendingDependencies(Set<IHawkMetaModelResource> metamodels, Map<String, IHawkPackage> expanded, final Set<String> missingURIs, final Set<String> alreadyInGraph) throws Exception {
		for (IHawkMetaModelResource m : metamodels) {
			for (IHawkObject child : m.getAllContents()) {
				if (child instanceof IHawkPackage) {
					final IHawkPackage pkg = (IHawkPackage) child;
					for (IHawkClassifier pkgClassifier : pkg.getClasses()) {
						if (pkgClassifier instanceof IHawkClass) {
							IHawkClass eClass = (IHawkClass) pkgClassifier;

							for (IHawkClass st : eClass.getAllSuperTypes()) {
								addPendingDependencies(expanded, missingURIs, alreadyInGraph, st);
							}
							for (IHawkAttribute e : eClass.getAllAttributes()) {
								if (e.getType() != null) {
									addPendingDependencies(expanded, missingURIs, alreadyInGraph, e.getType());
								}
							}
							for (IHawkReference r : eClass.getAllReferences()) {
								addPendingDependencies(expanded, missingURIs, alreadyInGraph, r.getType());
							}							
						}
					}
				}
			}
		}
	}

	private void addPendingDependencies(Map<String, IHawkPackage> toBeRegistered, final Set<String> missingURIs, final Set<String> alreadyInGraph, IHawkClassifier targetType) throws Exception {
		final String nsURI = targetType.getPackageNSURI();
		if (!toBeRegistered.containsKey(nsURI) && !missingURIs.contains(nsURI) && !alreadyInGraph.contains(nsURI)) {
			if (!isMetamodelRegistered(nsURI)) {
				// Not in the set to be registered, not pending yet, and not in the graph: mark as missing
				missingURIs.add(nsURI);
			} else {
				// Not in the set to be registered, but it is already in the graph
				alreadyInGraph.add(nsURI);
			}
		}
	}

	private boolean isMetamodelRegistered(String nsURI) throws Exception {
		boolean ret = false;
		try (IGraphTransaction tx = graph.beginTransaction()) {
			final IGraphIterable<? extends IGraphNode> iterMatches = graph.getMetamodelIndex().get("id", nsURI);
			ret = iterMatches.iterator().hasNext();
			tx.success();
		}
		return ret;
	}

	private void addEClasses(IHawkPackage ePackage) throws MissingMetamodelException {
		for (IHawkClassifier child : ePackage.getClasses()) {
			if (child instanceof IHawkClass) {
				addMetaClass((IHawkClass) child);
			} else if (child instanceof IHawkDataType) {
				// FIXME need to handle datatypes?
				if (child.getInstanceType() != null) {
					LOGGER.warn(
						"Hawk does not support custom data types yet: {}::{} will be handled as its instance type {}",
						ePackage.getNsURI(), child.getName(), child.getInstanceType());
				} else {
					LOGGER.warn(
						"Hawk does not support custom data types yet: {}::{} will be handled as a string",
						ePackage.getNsURI(), child.getName());
				}
			} else {
				LOGGER.error("Unknown classifier: ({}): {}", child.getName(), child.getClass());
			}
		}
	}

	/**
	 * Returns {@code true} iff we added a new package node to the graph.
	 */
	private boolean addEPackage(IHawkPackage ePackage, IGraphNodeIndex ePackageDictionary) throws IOException {
		final String uri = ePackage.getNsURI();
		if (uri == null) {
			LOGGER.warn("ePackage {} has null nsURI, ignoring", ePackage);
			return false;
		}

		if (ePackageDictionary.get("id", uri).iterator().hasNext() == false) {
			Map<String, Object> fields = new HashMap<>();
			fields.put(IModelIndexer.IDENTIFIER_PROPERTY, uri);
			fields.put(IModelIndexer.METAMODEL_TYPE_PROPERTY, ePackage.getResource().getMetaModelResourceFactory().getType());
			IGraphNode epackagenode = graph.createNode(fields, "epackage");

			ePackageDictionary.add(epackagenode, "id", uri);
			listener.metamodelAddition(ePackage, epackagenode);
			return true;
		} else {
			LOGGER.warn(
				"metamodel: {} ({}) already in store, updating it instead NYI -- doing nothing!",
				(ePackage).getName(), uri);
			return false;
		}
	}

	/**
	 * 
	 * @param eClass
	 * @return the URI ID of an eClass
	 */
	public String getEObjectId(IHawkClass eClass) {
		return eClass.getPackageNSURI() + "/" + eClass.getName();
	}

	/**
	 * Creates a node in the graph database with the given eClass's attributes
	 * in it.
	 * 
	 * @param eObject
	 * @param id
	 * @return the Node
	 */
	private void createEClassNode(IHawkClass eClass, String id) throws MissingMetamodelException {
		final Map<String, Object> map = new HashMap<>();
		map.put(IModelIndexer.IDENTIFIER_PROPERTY, id);

		final IGraphNode node = graph.createNode(new HashMap<String, Object>(), "eclass");
		final IGraphNode metamodelNode = graph.getMetamodelIndex().get("id", eClass.getPackageNSURI()).getSingle();
		graph.createRelationship(node, metamodelNode, "epackage");
		
		for (IHawkClass superType : eClass.getAllSuperTypes()) {
			addMetamodelDependency(eClass, metamodelNode, superType);
		}

		for (IHawkAttribute e : eClass.getAllAttributes()) {
			if (e.getType() != null) {
				addMetamodelDependency(eClass, metamodelNode, e.getType());
			}

			String[] metadata = new Slot.MetadataBuilder()
					.attribute()
					.many(e.isMany())
					.ordered(e.isOrdered())
					.unique(e.isUnique())
					.type(getPropertyType(e))
					.build();

			map.put(e.getName(), metadata);
		}

		for (IHawkReference r : eClass.getAllReferences()) {
			addMetamodelDependency(eClass, metamodelNode, r.getType());

			String[] metadata = new Slot.MetadataBuilder()
					.reference()
					.many(r.isMany())
					.ordered(r.isOrdered())
					.unique(r.isUnique())
					.type(getPropertyType(r))
					.build();

			map.put(r.getName(), metadata);
		}

		for (String s : map.keySet()) {
			node.setProperty(s, map.get(s));
		}

		listener.classAddition(eClass, node);
	}

	private String getPropertyType(IHawkStructuralFeature e) {
		String propType = "unknown";
		if (e.getType() != null) {
			if (e.getType().getName() != null) {
				// System.err.println(e.getType().getName());
				propType = e.getType().getInstanceType();
			} else {
				LOGGER.warn(
					"warning: unknown (null) type NAME found in metamodel parsing into db for attribute: {} of type: {}",
					e.getName(), e.getType());
			}
		} else {
			LOGGER.warn("warning: unknown (null) type found in metamodel parsing into db for attribute: {}", e.getName());
		}
		return propType;
	}

	private void addMetamodelDependency(IHawkClass sourceType, final IGraphNode metamodelNode, IHawkClassifier targetType) throws MissingMetamodelException {
		final String targetTypeMetamodelURI = targetType.getPackageNSURI();
		final IGraphIterable<? extends IGraphNode> metamodels = graph.getMetamodelIndex().get("id", targetTypeMetamodelURI);

		if (metamodels.iterator().hasNext() == false) {
			LOGGER.error(
					"EClass {} has supertype {} which is in a package not registered yet, "
							+ "reverting all changes to this package registration, please register "
							+ "package with URI {} first",
					sourceType.getName(), targetType.getName() == null ? targetType.getUri() : targetType.getName(), targetTypeMetamodelURI);

			throw new MissingMetamodelException(targetTypeMetamodelURI);
		} else if (!targetTypeMetamodelURI.equals(sourceType.getPackageNSURI())) {
			final IGraphNode superTypeEPackage = metamodels.getSingle();
			if (!metamodelDependencyExists(metamodelNode, superTypeEPackage)) {
				LOGGER.debug("supertype dependency from {} to {}", sourceType.getPackageNSURI(), targetTypeMetamodelURI);
				graph.createRelationship(metamodelNode, superTypeEPackage, IModelIndexer.METAMODEL_DEPENDENCY_EDGE);
			}
		}
	}

	private boolean metamodelDependencyExists(final IGraphNode metamodelNode, final IGraphNode superTypeEPackage) {
		boolean alreadythere = false;
		Iterable<IGraphEdge> depEdges = metamodelNode.getOutgoingWithType(IModelIndexer.METAMODEL_DEPENDENCY_EDGE);
		for (IGraphEdge r : depEdges) {
			if (r.getEndNode().equals(superTypeEPackage)) {
				alreadythere = true;
				break;
			}
		}
		return alreadythere;
	}

	/**
	 * Turns an {@link IHawkClass} into a graph node.
	 * 
	 * @param eClass Class to be added.
	 * @throws MissingMetamodelException A required metamodel is missing from the graph.
	 */
	private void addMetaClass(IHawkClass eClass) throws MissingMetamodelException {
		String id = eClass.getName();
		objectCount++;
		createEClassNode(eClass, id);
	}

	/**
	 * Adds a new derived attribute to a type. Returns whether propagation to
	 * current instances of this type is necessary.
	 * 
	 * @param metamodeluri
	 * @param typename
	 * @param attributename
	 * @param isMany
	 * @param isOrdered
	 * @param isUnique
	 * @param attributetype
	 * @param derivationlanguage
	 * @param derivationlogic
	 * @param graph
	 * @return
	 */
	public static boolean addDerivedAttribute(String metamodeluri, String typename, String attributename,
			boolean isMany, boolean isOrdered, boolean isUnique, String attributetype, String derivationlanguage,
			String derivationlogic, IGraphDatabase graph, IGraphChangeListener listener) {

		boolean requiresPropagationToInstances = false;

		try (IGraphTransaction t = graph.beginTransaction()) {
			listener.changeStart();
			IGraphIterable<? extends IGraphNode> ep = graph.getMetamodelIndex().get("id", metamodeluri);

			IGraphNode packagenode = null;

			if (ep.size() == 1) {
				packagenode = ep.getSingle();
			} else {
				throw new Exception("metamodel not found:" + metamodeluri);
			}

			IGraphNode typenode = null;

			for (IGraphEdge e : packagenode.getIncomingWithType("epackage")) {
				if (e.getStartNode().getProperty(IModelIndexer.IDENTIFIER_PROPERTY).equals(typename)) {
					typenode = e.getStartNode();
					break;
				}
			}

			if (typenode == null) {
				LOGGER.error("type: {} in: {} does not exist, aborting operation: addDerivedAttribute", typename, metamodeluri);
			} else {
				/*
				 * at least one instance already present so derived attribute
				 * needs to be reconfigured for each element already present
				 * (whether the derived attribute is new or existed already and
				 * is being updated)
				 */
				if (typenode.getIncomingWithType(ModelElementNode.EDGE_LABEL_OFTYPE).iterator().hasNext()
						|| typenode.getIncomingWithType(ModelElementNode.EDGE_LABEL_OFKIND).iterator().hasNext())
					requiresPropagationToInstances = true;

				String[] metadata = new String[7];
				metadata[0] = "d";
				metadata[1] = (isMany ? "t" : "f");
				metadata[2] = (isOrdered ? "t" : "f");
				metadata[3] = (isUnique ? "t" : "f");
				metadata[4] = attributetype;
				metadata[5] = derivationlanguage;
				metadata[6] = derivationlogic;

				if (typenode.getProperty(attributename) != null) {
					LOGGER.warn("Attribute already derived, nothing happened!");
					requiresPropagationToInstances = false;
				} else {
					typenode.setProperty(attributename, metadata);
					if (LOGGER.isInfoEnabled()) {
						final String logic = (derivationlogic.length() > 100
								? derivationlogic.substring(0, 100) + "\n[! long script, snipped !]"
								: derivationlogic);

						LOGGER.info(
								"Derived attribute added: {}::{}#{} (isMany={}|isOrdered={}|isUnique={}|type={}) {}#\n{}",
								metamodeluri, typename, attributename,
								isMany, isOrdered, isUnique, attributetype, derivationlanguage,
								logic);
					}
				}

				/** Must create the empty index so it will be known by the {@link ModelIndexerImpl} */
				graph.getOrCreateNodeIndex(metamodeluri + "##" + typename + "##" + attributename);
			}
			t.success();
			listener.changeSuccess();
		} catch (Exception e1) {
			LOGGER.error("error in adding a derived attribute to the metamodel", e1);
			listener.changeFailure();
		}

		return requiresPropagationToInstances;
	}

	/**
	 * Adds a new indexed attribute to a type. Returns whether propagation to
	 * current instances of this type is necessary.
	 * 
	 * @param metamodeluri
	 * @param typename
	 * @param attributename
	 * @param graph
	 * @param listener2
	 * @return
	 */
	public static boolean addIndexedAttribute(String metamodeluri, String typename, String attributename,
			IGraphDatabase graph, IGraphChangeListener listener) {

		boolean requiresPropagationToInstances = false;

		try (IGraphTransaction t = graph.beginTransaction()) {
			listener.changeStart();
			IGraphNode packagenode = graph.getMetamodelIndex().get("id", metamodeluri).getSingle();

			IGraphNode typenode = null;

			for (IGraphEdge e : packagenode.getIncomingWithType("epackage")) {
				if (e.getStartNode().getProperty(IModelIndexer.IDENTIFIER_PROPERTY).equals(typename)) {
					typenode = e.getStartNode();
					break;
				}
			}

			if (typenode == null) {
				LOGGER.error("type: {} in: {} does not exist, aborting operation: addIndexedAttribute", typename, metamodeluri);
			} else {

				// at least one instance already present so indexed attribute
				// needs
				// to be reconfigured for each element already present (whether
				// the
				// indexed attribute is new or existed already and is being
				// updated)

				String[] metadata = (String[]) typenode.getProperty(attributename);

				if (metadata == null) {
					LOGGER.error("attribute: {} in: {}#{} does not exist, aborting operation: addIndexedAttribute", attributename, metamodeluri, typename);
				} else if (!metadata[0].equals("a")) {
					LOGGER.error("{}#{} is not an attribute, aborting operation: addIndexedAttribute", metamodeluri, typename);
				} else {
					if (typenode.getIncomingWithType(ModelElementNode.EDGE_LABEL_OFTYPE).iterator().hasNext()
							|| typenode.getIncomingWithType(ModelElementNode.EDGE_LABEL_OFKIND).iterator().hasNext())
						requiresPropagationToInstances = true;

					if (metadata.length == 6) {
						if ("t".equals(metadata[5])) {
							LOGGER.warn("attribute already indexed, nothing happened!");
							requiresPropagationToInstances = false;
						} else {
							metadata[5] = "t";
							typenode.setProperty(attributename, metadata);
							//
							graph.getOrCreateNodeIndex(metamodeluri + "##" + typename + "##" + attributename);
							//
							LOGGER.info("indexed attribute added: {}::{}#{}", metamodeluri, typename, attributename);
						}
					} else if (metadata.length == 7) {
						LOGGER.warn("derived attributes are already indexed, nothing happened.");
					} else {
						// FIXME log actual exception
						LOGGER.error("unknown exception in addIndexedAttribute of GraphMetamodelResourceInjector");
					}
				}
			}
			t.success();
			listener.changeSuccess();
		} catch (Exception e) {
			LOGGER.error("Error in adding an indexed attribute", e);
			listener.changeFailure();
		}

		return requiresPropagationToInstances;

	}

	/**
	 * Removes all the metamodels with the specified URIs.
	 * 
	 * @return URIs of the repositories impacted by the removal.
	 */
	public Set<String> removeMetamodels(String[] mmuris) {

		Set<String> ret = new HashSet<>();

		try (IGraphTransaction t = graph.beginTransaction()) {

			Set<String> indexNames = graph.getNodeIndexNames();
			Set<IGraphNodeIndex> markedForRemoval = new HashSet<>();

			listener.changeStart();
			IGraphNodeIndex ePackageDictionary = graph.getMetamodelIndex();

			Set<IGraphNode> epns = new HashSet<>();
			for (String mmuri : mmuris) {
				try {

					for (Iterator<String> it = indexNames.iterator(); it.hasNext();) {
						String s = it.next();
						if (s.startsWith(mmuri + "##")) {
							IGraphNodeIndex i = graph.getOrCreateNodeIndex(s);
							markedForRemoval.add(i);
							it.remove();
						}
					}

					epns.add(ePackageDictionary.get("id", mmuri).getSingle());
				} catch (Exception e) {
					LOGGER.error("Metamodel with URI " + mmuri + " not indexed. Nothing happened.", e);
				}
			}
			if (epns.size() > 0) {
				LOGGER.info("Removing metamodels with URIs {}", Arrays.toString(mmuris));
				ret = removeAll(epns);
			}

			for (IGraphNodeIndex i : markedForRemoval) {
				LOGGER.info("Deleting index {} as its metamodel was removed.", i.getName());
				i.delete();
			}

			t.success();
			listener.changeSuccess();
		} catch (Exception e) {
			listener.changeFailure();
			LOGGER.error("Error in removing metamodels " + Arrays.toString(mmuris) + "\n(ALL removal changes reverted)", e);
		}
		return ret;
	}

	public static boolean removeIndexedAttribute(String metamodelUri, String typename, String attributename,
			IGraphDatabase graph, CompositeGraphChangeListener listener) {

		boolean found = false;

		try (IGraphTransaction t = graph.beginTransaction()) {
			listener.changeStart();

			IGraphNode packagenode = null;
			IGraphIterable<? extends IGraphNode> ep = graph.getMetamodelIndex().get("id", metamodelUri);

			if (ep.size() == 1) {
				packagenode = ep.getSingle();
			} else {
				throw new Exception("metamodel not found:" + metamodelUri);
			}

			IGraphNode typenode = null;

			for (IGraphEdge e : packagenode.getIncomingWithType("epackage")) {
				if (e.getStartNode().getProperty(IModelIndexer.IDENTIFIER_PROPERTY).equals(typename)) {
					typenode = e.getStartNode();
					break;
				}
			}

			if (typenode == null) {
				LOGGER.error(
					"type: {} in: {} does not exist, aborting operation: removeIndexedAttribute",
					typename, metamodelUri
				);
				listener.changeFailure();
			} else {
				String[] metadata = (String[]) typenode.getProperty(attributename);

				if (metadata == null) {
					LOGGER.error("attribute: {} in: {}::{} does not exist, aborting operation: removeIndexedAttribute",
							attributename, metamodelUri, typename);
					listener.changeFailure();
				} else if (!metadata[0].equals("a")) {
					// System.err.println(Arrays.toString(metadata));
					LOGGER.error("{}::{} is a reference not an attribute, aborting operation: removeIndexedAttribute",
							metamodelUri, typename);
					listener.changeFailure();
				} else {

					if (metadata.length == 6) {
						if ("t".equals(metadata[5])) {
							metadata[5] = "f";
							typenode.setProperty(attributename, metadata);
							//
							String indexname = metamodelUri + "##" + typename + "##" + attributename;

							if (graph.nodeIndexExists(indexname)) {
								graph.getOrCreateNodeIndex(indexname).delete();
								found = true;
							}

							t.success();
							listener.changeSuccess();
						} else {
							LOGGER.error("attribute was not indexed, nothing happened!");
							listener.changeFailure();
						}

					} else {
						LOGGER.error("error in removeIndexedAttribute (metadata.length!=6), nothing happened!");
						listener.changeFailure();
					}
				}

			}

		} catch (Exception e) {
			LOGGER.error("Error while removing an indexed attribute", e);
			listener.changeFailure();
		}
		return found;

	}

	public static boolean removeDerivedAttribute(String metamodelUri, String typeName, String attributeName,
			IGraphDatabase graph, CompositeGraphChangeListener listener) {

		boolean found = false;

		try (IGraphTransaction t = graph.beginTransaction()) {
			listener.changeStart();
			IGraphIterable<? extends IGraphNode> ep = graph.getMetamodelIndex().get("id", metamodelUri);

			IGraphNode packagenode = null;

			if (ep.size() == 1) {
				packagenode = ep.getSingle();
			} else {
				throw new Exception("metamodel not found:" + metamodelUri);
			}

			IGraphNode typenode = null;

			for (IGraphEdge e : packagenode.getIncomingWithType("epackage")) {
				if (e.getStartNode().getProperty(IModelIndexer.IDENTIFIER_PROPERTY).equals(typeName)) {
					typenode = e.getStartNode();
					break;
				}
			}

			if (typenode == null) {
				LOGGER.error(
					"type: {} in: {} does not exist, aborting operation: removeDerivedAttribute",
					typeName, metamodelUri);
				listener.changeFailure();
			} else {

				String[] metadata = (String[]) typenode.getProperty(attributeName);
				if (metadata != null) {

					if (metadata.length == 7 && metadata[0].equals("d")) {
						LOGGER.info("derived attribute removed: {}::{}", metamodelUri, typeName);
						IGraphNodeIndex derivedAccessDictionary = graph.getOrCreateNodeIndex(GraphModelInserter.DERIVED_ACCESS_IDXNAME);
						IGraphNodeIndex derivedProxyDictionary = graph.getOrCreateNodeIndex("derivedproxydictionary");

						typenode.removeProperty(attributeName);
						graph.getOrCreateNodeIndex(metamodelUri + "##" + typeName + "##" + attributeName).delete();

						boolean noerror = true;

						for (IGraphEdge e : (typenode.getIncomingWithType(ModelElementNode.EDGE_LABEL_OFTYPE)))
							noerror = noerror && removeDerivedAttribute(derivedAccessDictionary, derivedProxyDictionary,
									attributeName, e);

						for (IGraphEdge e : (typenode.getIncomingWithType(ModelElementNode.EDGE_LABEL_OFKIND)))
							noerror = noerror && removeDerivedAttribute(derivedAccessDictionary, derivedProxyDictionary,
									attributeName, e);

						if (noerror)
							found = true;

						t.success();
						listener.changeSuccess();
					} else {
						LOGGER.error("Error in removeDerivedAttribute, attribute metadata not valid");
						listener.changeFailure();
					}
				} else {
					LOGGER.error("Attribute was not already derived, nothing happened!");
					listener.changeFailure();
				}
			}

		} catch (Exception e1) {
			LOGGER.error("Error in removing a derived attribute to the metamodel", e1);
			listener.changeFailure();
		}

		return found;

	}

	/**
	 * Internal, to remove instance derived attributes
	 */
	private static boolean removeDerivedAttribute(IGraphNodeIndex derivedAccessDictionary,
			IGraphNodeIndex derivedProxyDictionary, String attributeName, IGraphEdge instanceToTypeEdge) {

		boolean error = true;

		IGraphNode n = instanceToTypeEdge.getStartNode();

		IGraphEdge dae = null;

		for (IGraphEdge ed : n.getOutgoingWithType(attributeName)) {
			if (dae == null)
				dae = ed;
			else {
				LOGGER.error("multiple edges found for derived attribute: {} in node {}", attributeName, n);
				dae = null;
				break;
			}
		}

		if (dae == null) {
			LOGGER.error("derived attribute ({}) not found for node {}", attributeName, n);
		} else {
			IGraphNode dan = dae.getEndNode();
			dae.delete();
			derivedAccessDictionary.remove(dan);
			derivedProxyDictionary.remove(dan);
			dan.delete();
			error = false;
		}

		return !error;

	}
}
