/*******************************************************************************
 * Copyright (c) 2004-2008 Andras Schmidt, Andras Balogh, Istvan Rath and Daniel Varro
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Andras Schmidt, Andras Balogh, Istvan Rath - initial API and implementation
 *******************************************************************************/

package org.eclipse.viatra2.core.simple;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.eclipse.viatra2.core.ICoreNotificationListener;
import org.eclipse.viatra2.core.IEntity;
import org.eclipse.viatra2.core.IModelElement;
import org.eclipse.viatra2.core.IModelSpace;
import org.eclipse.viatra2.core.IRelation;
import org.eclipse.viatra2.core.constraint.EConstraint;
import org.eclipse.viatra2.core.simple.tempdata.TemporaryData;

/**
 * This class implements the VPM core element representation
 * 
 * @author Andras Schmidt, Istvan Rath
 * 
 */
abstract public class SimpleModelElement implements KeyedObject, IModelElement {
	/**
	 * ID of this element. Unique in modelspace.
	 */
	long ID;

	/**
	 * Stores relations that have this element as source. Maps the ids of
	 * relations to the relations.
	 */
	protected TreeMap<Long, IRelation> relationsFrom;

	/**
	 * Stores relations that have this element as target.
	 */
	protected Set<IRelation> relationsTo;

	/**
	 * Stores elements in namespace. Maps elements name in namespace to the
	 * element's ID
	 */
	protected TreeMap<String, Long> namespace;

	/**
	 * Name of this element. Unique in namespace.
	 */
	String name = "";

	String viewInfo = null;

	boolean isFinalType = false;

	public boolean getIsFinalType() {
		return isFinalType;
	}

	/**
	 * The modelSpace in which this element is instantiated.
	 */
	SimpleModelSpace modelSpace;

	/**
	 * supertypes of this element.
	 */
	protected Set<IModelElement> supertype = null;

	/**
	 * types of this element.
	 */
	protected Set<IModelElement> type = null;

	/**
	 * subtypes of this element.
	 */
	protected Set<IModelElement> subtypes;

	/**
	 * instances of this element.
	 */
	protected Set<IModelElement> instances;

	/**
	 * Cached objects to store redundant data: they will become invalid when
	 * modelspace changes If we have a valid data then the get method returns
	 * it, if we have no valid data then the get method counts it.
	 */
	protected TemporaryData<Set<IModelElement>> allInstances;//=TemporaryData
																	// .
																	// create();

	protected TemporaryData<Set<IModelElement>> allTypes;// =TemporaryData.
																// create();

	protected TemporaryData<Set<IModelElement>> allSupertypes;// =
																	// TemporaryData
																	// .
																	// create();

	protected TemporaryData<Set<IModelElement>> allSubtypes;//=TemporaryData
																// .create();

	/**
	 * Listeners to notify, when this element changes.
	 */
	protected List<ICoreNotificationListener> notificationListeners;

	/**
	 * Compares this to o Two elements are compared by their IDs. This makes it
	 * fast to search an element by ID in a Set.
	 * 
	 * @return true if their ID are equal.
	 */
	@Override
	public boolean equals(Object o) {
		if (o instanceof SimpleModelElement)
			return ID == ((SimpleModelElement) o).ID;
		else
			return false;
	}

	/**
	 * Comapres this to o Two elements are compared by their IDs. This makes it
	 * fast to search an element by ID in a Set.
	 * 
	 * @return 1:greater, 0: equals, -1:less
	 */
	public int compareTo(IModelElement o) {
		long diff = ID - ((SimpleModelElement) o).ID;
		// Problem is: long->int conversion might fail to preserve sign, so we
		// need this
		// difficult construct.
		return diff > 0 ? 1 : (diff < 0 ? -1 : 0);
	}

	/**
	 * This will be used when implementing faster search.
	 */
	public static final int KEY_ID = 0;

	/**
	 * This will be used when implementing faster search.
	 */
	public static final int KEY_NAME = 1;

	/**
	 * This will be used when implementing faster search.
	 */
	public Comparable<?> getKey(int nr) {
		switch (nr) {
		case KEY_ID:
			return new Long(ID);
		case KEY_NAME:
			return name;
		}
		return null;
	}

	/**
	 * Instantiates new SimpleModelElement. Its ID will be set to _ID.
	 */
	public SimpleModelElement(long _ID, SimpleModelSpace ms) {
		ID = _ID;
		modelSpace = ms;
		allInstances = modelSpace.tempFactory.create();
		allTypes = modelSpace.tempFactory.create();
		allSupertypes = modelSpace.tempFactory.create();
		allSubtypes = modelSpace.tempFactory.create();

		// supertype=new TreeSet();
		// type=new TreeSet();
		// subtypes=new TreeSet();
		// instances=new TreeSet();

		relationsFrom = new TreeMap<Long, IRelation>();
		relationsTo = new SmallTreeSet<IRelation>();
		namespace = new TreeMap<String, Long>();

		supertype = new SmallTreeSet<IModelElement>();
		type = new SmallTreeSet<IModelElement>();
		subtypes = new SmallTreeSet<IModelElement>();
		instances = new SmallTreeSet<IModelElement>();
		notificationListeners = new ArrayList<ICoreNotificationListener>(0);
	}

	/**
	 * Gets the element's ID
	 * 
	 * @return id
	 */
	public String getID() {
		try {
			modelSpace.lock.readLock().lock();
			return Long.toString(ID);
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	public Long getLongID() {
		try {
			modelSpace.lock.readLock().lock();
			return new Long(ID);
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Gets the elements name
	 * 
	 * @return the name of the element
	 */
	public String getName() {
		try {
			// modelSpace.lock.lock();
			return name;
		} finally {
			// modelSpace.lock.unlock();
		}
	}

	/**
	 * Returns the collection of supertypes.
	 * 
	 * @return the collection of supertypes
	 */
	public Collection<IModelElement> getSupertypes() {
		try {
			modelSpace.lock.readLock().lock();
			if (SimpleModelSpace.isAncestorAware) {
				if (supertype.size() == 0 && modelSpace.ancestorEntity != null) {
					TreeSet<IModelElement> retSet = new TreeSet<IModelElement>(
							supertype);
					if (isEntity())
						retSet.add(modelSpace.ancestorEntity);
					else
						retSet.add(modelSpace.ancestorRelation);
					return retSet;
				} else {
					return supertype;
				}
			} else
				return supertype;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Gets the types of the element. The result set contains all Elements,
	 * which are instanciated by this Element.
	 * 
	 * @return set of elements.
	 */
	public Collection<IModelElement> getTypes() {
		try {
			modelSpace.lock.readLock().lock();
			if (SimpleModelSpace.isAncestorAware) {
				if (type.size() == 0 && modelSpace.ancestorEntity != null) {
					TreeSet<IModelElement> retSet = new TreeSet<IModelElement>(
							supertype);
					if (isEntity())
						retSet.add(modelSpace.ancestorEntity);
					else
						retSet.add(modelSpace.ancestorRelation);
					return retSet;
				}
				return type;
			} else
				return type;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Gets the list of subtypes of the current Element.
	 * 
	 * @return Set of elements
	 */
	public Collection<IModelElement> getSubtypes() {
		try {
			modelSpace.lock.readLock().lock();
			return subtypes;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Gets all elements that are instances of the current one.
	 * 
	 * @return collection of instances
	 */
	public Collection<IModelElement> getInstances() {
		try {
			modelSpace.lock.readLock().lock();
			return instances;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Gets the String representation of this object.
	 */
	@Override
	public String toString() {
		// TODO
		try {
			// modelSpace.lock.lock();
			return getFullyQualifiedName();
		} finally {
			// modelSpace.lock.unlock();
		}
	}

	/**
	 * Gets recursively all supertypes of the current Element.
	 * 
	 * @return set of Elements.
	 */
	public Collection<IModelElement> getAllSupertypes() {
		try {
			modelSpace.lock.readLock().lock();
			Set<IModelElement> retSet = allSupertypes
					.getObject(modelSpace.numberOfChanges);
			if (retSet != null)
				return retSet;
			retSet = new TreeSet<IModelElement>();
			Iterator<IModelElement> it = supertype.iterator();
			while (it.hasNext()) {
				SimpleModelElement me = (SimpleModelElement) it.next();
				retSet.add(me);
				retSet.addAll(me.getAllSupertypes());
			}
			allSupertypes.setObject(modelSpace.numberOfChanges, retSet);
			return retSet;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Gets recursively all types of the current Element.
	 * 
	 * @return set of Elements.
	 */
	public Collection<IModelElement> getAllTypes() {
		try {
			modelSpace.lock.readLock().lock();
			Set<IModelElement> retSet = allTypes
					.getObject(modelSpace.numberOfChanges);
			if (retSet != null)
				return retSet;
			retSet = new TreeSet<IModelElement>();
			Iterator<IModelElement> it = type.iterator();
			while (it.hasNext()) {
				SimpleModelElement me = (SimpleModelElement) it.next();
				retSet.add(me);
				retSet.addAll(me.getAllSupertypes());
			}
			allTypes.setObject(modelSpace.numberOfChanges, retSet);
			return retSet;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Gets recoursively all subtypes of the current element.
	 * 
	 * @return set of types.
	 */
	public Collection<IModelElement> getAllSubtypes() {
		try {
			modelSpace.lock.readLock().lock();
			Set<IModelElement> retSet = allSubtypes
					.getObject(modelSpace.numberOfChanges);
			if (retSet != null)
				return retSet;
			retSet = new TreeSet<IModelElement>();
			Iterator<IModelElement> it = subtypes.iterator();
			while (it.hasNext()) {
				SimpleModelElement me = (SimpleModelElement) it.next();
				retSet.add(me);
				retSet.addAll(me.getAllSubtypes());
			}
			allSubtypes.setObject(modelSpace.numberOfChanges, retSet);
			return retSet;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Gets recoursively all instances of the current element (and its
	 * subtypes).
	 * 
	 * @return set of types.
	 */
	public Collection<IModelElement> getAllInstances() {
		try {
			modelSpace.lock.readLock().lock();
			Set<IModelElement> retSet = allInstances
					.getObject(modelSpace.numberOfChanges);
			if (retSet == null) {
				//retSet = new TreeSet<IModelElement>();
				retSet = new HashSet<IModelElement>();
				
				retSet.addAll(instances);
				Iterator<IModelElement> itS = getAllSubtypes().iterator();
				while (itS.hasNext()) {
					SimpleModelElement meS = (SimpleModelElement) itS.next();
					retSet.addAll(meS.getAllInstances());
				}
				allInstances.setObject(modelSpace.numberOfChanges, retSet);
			}
			return retSet;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Adds a new notification listener to this element
	 * 
	 * @param l
	 *            the new listener
	 */
	protected void addNotificationListener(ICoreNotificationListener l) {
		try {
			modelSpace.lock.writeLock().lock();
			notificationListeners.add(l);
		} finally {
			modelSpace.lock.writeLock().unlock();
		}
	}

	/**
	 * Removes a notification listener
	 * 
	 * @param l
	 *            the listener to be removed
	 */
	public void removeNotificationListener(ICoreNotificationListener l) {
		try {
			modelSpace.lock.writeLock().lock();
			notificationListeners.remove(l);
		} finally {
			modelSpace.lock.writeLock().unlock();
		}
	}

	/**
	 * Returns the current set of listeners of this element
	 * 
	 * @return collection of listeners
	 */
	public Collection<ICoreNotificationListener> getNotificationListeners() {
		try {
			// modelSpace.lock.lock();
			return notificationListeners;
		} finally {
			// modelSpace.lock.unlock();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * hu.bme.mit.viatra.core.IModelElement#isInstanceOf(hu.bme.mit.viatra.core
	 * .IModelElement)
	 */
	public boolean isInstanceOf(IModelElement type) {
		if (type==null) {
			return false;
		}
		try {
			modelSpace.lock.readLock().lock();
			if (!this.type.contains(type))
				return getAllTypes().contains(type);
			else
				return true;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * hu.bme.mit.viatra.core.IModelElement#isSupertypeOf(hu.bme.mit.viatra.
	 * core.IModelElement)
	 */
	public boolean isSupertypeOf(IModelElement sub) {
		if (sub==null) return false;
		try {
			modelSpace.lock.readLock().lock();
			if (sub == this)
				return false; //TODO: ask Dani
			return getAllSubtypes().contains(sub);
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * hu.bme.mit.viatra.core.IModelElement#isSubtypeOf(hu.bme.mit.viatra.core
	 * .IModelElement)
	 */
	public boolean isSubtypeOf(IModelElement type) {
		if (type==null) return false;
		try {
			modelSpace.lock.readLock().lock();
			if (type == this)
				return false; //TODO: ask Dani
			return type.isSupertypeOf(this);
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * hu.bme.mit.viatra.core.IModelElement#isTypeOf(hu.bme.mit.viatra.core.
	 * IModelElement)
	 */
	public boolean isTypeOf(IModelElement inst) {
		if (inst==null) return false;
		try {
			modelSpace.lock.readLock().lock();
			return inst.isInstanceOf(this);
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/*
	 * corrected.
	 * (non-Javadoc)
	 * @see org.eclipse.viatra2.core.IModelElement#isDirectTypeOf(org.eclipse.viatra2.core.IModelElement)
	 */
	public boolean isDirectTypeOf(IModelElement inst) {
		if (inst==null) return false;
		try {
			modelSpace.lock.readLock().lock();
			return getInstances().contains(inst);
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/*
	 * corrected.
	 * (non-Javadoc)
	 * @see org.eclipse.viatra2.core.IModelElement#isDirectSubtypeOf(org.eclipse.viatra2.core.IModelElement)
	 */
	public boolean isDirectSubtypeOf(IModelElement sup) {
		if (sup==null) return false;
		try {
			modelSpace.lock.readLock().lock();
			if (sup == this)
				return true;
			return getSupertypes().contains(sup);
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/*
	 * Corrected.
	 * (non-Javadoc)
	 * @see org.eclipse.viatra2.core.IModelElement#isDirectSupertypeOf(org.eclipse.viatra2.core.IModelElement)
	 */
	public boolean isDirectSupertypeOf(IModelElement sub) {
		return sub.isDirectSubtypeOf(this);
	}

	/*
	 * Corrected.
	 * (non-Javadoc)
	 * @see org.eclipse.viatra2.core.IModelElement#isDirectInstanceOf(org.eclipse.viatra2.core.IModelElement)
	 */
	public boolean isDirectInstanceOf(IModelElement type) {
		return type.isDirectTypeOf(this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hu.bme.mit.viatra.core.IModelElement#getViewInfo()
	 */
	public String getViewInfo() {
		try {
			// modelSpace.lock.lock();
			return viewInfo;
		} finally {
			// modelSpace.lock.unlock();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see hu.bme.mit.viatra.core.IModelElement#getModelSpace()
	 */
	public IModelSpace getModelSpace() {
		try {
			// modelSpace.lock.lock();
			return modelSpace;
		} finally {
			// modelSpace.lock.unlock();
		}
	}

	/**
	 * Gets all connections (relations and functions) of the Entity.
	 * 
	 * @return Set of connections.
	 */
	/*
	 * public Collection<IRelation> getConnections() { try {
	 * modelSpace.lock.lock(); TreeSet<IRelation> retSet = new
	 * TreeSet<IRelation>(); retSet.addAll(relationsFrom.values());
	 * retSet.addAll(relationsTo); return retSet; } finally {
	 * modelSpace.lock.unlock(); } }
	 */

	/**
	 * Returns the first connection for a given name
	 * 
	 * @param n
	 *            then name of the connection
	 * @return The coresponding relation
	 */
	/*
	 * public IRelation getConnectionByName(String n) { try {
	 * modelSpace.lock.lock(); return (IRelation)
	 * getElemByName(getConnections(), n); } finally { modelSpace.lock.unlock();
	 * } }
	 */
	/**
	 * Returns the first connection for a given name
	 * 
	 * @param n
	 *            then name of the connection
	 * @return The coresponding relation
	 */
	/*
	 * public IRelation getConnectionFromByName(String n) { try {
	 * modelSpace.lock.lock(); IModelElement me =
	 * getElementInNamespaceByName(n); if (me == null) return null; if (me
	 * instanceof IRelation) return (IRelation) me; return null; } finally {
	 * modelSpace.lock.unlock(); } }
	 */
	/**
	 * Returns the first connection for a given type
	 * 
	 * @param n
	 *            then name of the connection
	 * @return The coresponding relation
	 */
	/*
	 * public IRelation getConnectionByType(IModelElement n) { try {
	 * modelSpace.lock.lock(); return (IRelation)
	 * getElemByType(getConnections(), n); } finally { modelSpace.lock.unlock();
	 * } }
	 * 
	 * public IRelation getConnectionFromByType(IRelation n) { try {
	 * modelSpace.lock.lock(); return (IRelation)
	 * getElemByType(getConnectionsFrom(), n); } finally {
	 * modelSpace.lock.unlock(); } }
	 * 
	 * public IRelation getConnectionToByType(IModelElement n) { try {
	 * modelSpace.lock.lock(); return (IRelation)
	 * getElemByType(getConnectionsTo(), n); } finally {
	 * modelSpace.lock.unlock(); } }
	 */
	public Collection<IRelation> getAllRelationFromByType(IRelation n) {
		try {
			// modelSpace.lock.lock();
			// return getAllElemByType(getConnectionsFrom(), n);
			return getAllElemByType(getRelationsFrom(), n);
		} finally {
			// modelSpace.lock.unlock();
		}
	}

	public Collection<IRelation> getAllRelationToByType(IRelation n) {
//		try {
			// modelSpace.lock.lock();
			// return getAllElemByType(getConnectionsTo(), n);
			return getAllElemByType(getRelationsTo(), n);
//		} finally {
			// modelSpace.lock.unlock();
//		}
	}

	public Collection<IRelation> getRelationsTo() {
		try {
			modelSpace.lock.readLock().lock();
			return relationsTo;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	public Collection<IRelation> getRelationsFrom() {
		try {
			modelSpace.lock.readLock().lock();
			return relationsFrom.values();
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	public IRelation getRelationToByType(IModelElement type) {
		return (IRelation) getElemByType(relationsTo, type);
	}

	public IRelation getRelationFromByType(IModelElement type) {
		return (IRelation) getElemByType(relationsFrom.values(), type);
	}

	public IRelation getRelationToByName(String name) {
		return (IRelation) getElemByName(relationsTo, name);
	}

	public IRelation getRelationFromByName(String name) {
		return (IRelation) getElemByName(relationsFrom.values(), name);
	}

	private IModelElement getElemByName(Collection<? extends IModelElement> elems, String name) {
		try {
			modelSpace.lock.readLock().lock();
			Iterator<? extends IModelElement> it = elems.iterator();
			while (it.hasNext()) {
				IModelElement rel = it.next();
				if (rel.getName().equals(name))
					return rel;
			}
			return null;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	private IModelElement getElemByType(Collection<? extends IModelElement> elems, IModelElement type) {
		try {
			modelSpace.lock.readLock().lock();

			// TODO mi a konkret szemantikja?
			Iterator<? extends IModelElement> it = elems.iterator();
			while (it.hasNext()) {
				IModelElement rel = it.next();
				if (rel.getAllTypes().contains(type))
					return rel;
			}
			return null;
		} finally {
			modelSpace.lock.readLock().unlock();
		}

	}

	private Collection<IRelation> getAllElemByType(Collection<? extends IModelElement> elems,
			IModelElement type) {
		try {
			modelSpace.lock.readLock().lock();

			Iterator<? extends IModelElement> it = elems.iterator();
			ArrayList<IRelation> ret = new ArrayList<IRelation>();
			while (it.hasNext()) {
				IRelation rel = (IRelation) it.next();
				if (rel.getAllTypes().contains(type))
					ret.add(rel);
			}
			return ret;
		} finally {
			modelSpace.lock.readLock().unlock();
		}

	}

	/**
	 * Returns the first connection source which is connected via a relation of
	 * the specified type.
	 * 
	 * @param type
	 *            The relation type.
	 * @return the first appropriate connection if found, null otherwise.
	 */
	public IModelElement getRelationSourceByType(IRelation type) {
		try {
			modelSpace.lock.readLock().lock();

			IRelation conn = getRelationToByType(type);
			if (conn == null)
				return null;
			else
				return conn.getFrom();
		} finally {
			modelSpace.lock.readLock().unlock();
		}

	}

	/**
	 * Returns all connection source which is conected via a relation with the
	 * specified type
	 * 
	 * @param type
	 *            the relation type
	 * @return set of appropriate entities.
	 */
	public Collection<IModelElement> getAllRelationSourceByType(IRelation type) {
		try {
			modelSpace.lock.readLock().lock();
			Collection<IRelation> conns = getAllRelationToByType(type);
			ArrayList<IModelElement> ret = new ArrayList<IModelElement>();
			Iterator<IRelation> it = conns.iterator();
			while (it.hasNext()) {
				ret.add(it.next().getFrom());
			}
			return ret;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/**
	 * Returns all relations associated with this entity
	 * 
	 * @return collection of relations
	 */
	public Collection<IRelation> getRelations() {
		try {
			modelSpace.lock.readLock().lock();
			TreeSet<IRelation> retSet = new TreeSet<IRelation>();
			retSet.addAll(relationsFrom.values());
			retSet.addAll(relationsTo);
			return retSet;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	/*
	 * public Collection<IRelation> getConnectionsTo() { TreeSet<IRelation>
	 * retSet = new TreeSet<IRelation>(); retSet.addAll(relationsTo); return
	 * retSet; }
	 * 
	 * public Collection<IRelation> getConnectionsFrom() { TreeSet<IRelation>
	 * retSet = new TreeSet<IRelation>(); retSet.addAll(relationsFrom.values());
	 * return retSet; }
	 */
	/**
	 * Returns the first relation for a given name
	 * 
	 * @param n
	 *            then name of the relation
	 * @return The coresponding relation
	 */
	public IRelation getRelationByName(String n) {
		return (IRelation) getElemByName(getRelations(), n);
	}

	/**
	 * Returns the first relation for a given type
	 * 
	 * @param n
	 *            the type of the relation
	 * @return The coresponding relation
	 */
	public IRelation getRelationByType(IModelElement n) {
		return (IRelation) getElemByType(getRelations(), n);
	}

	/**
	 * Get the target of the Relation typed type.
	 */
	public IModelElement getRelationTargetByType(IRelation type) {
		IRelation conn = getRelationFromByType(type);
		if (conn == null)
			return null;
		else
			return conn.getTo();
	}

	/**
	 * Returns all connection target which is conected via a relation with the
	 * specified type
	 * 
	 * @param type
	 *            the relation type
	 * @return set of appropriate entities.
	 */
	public Collection<IModelElement> getAllRelationTargetByType(IRelation type) {
		try {
			modelSpace.lock.readLock().lock();
			Collection<IRelation> conns = getAllRelationFromByType(type);
			ArrayList<IModelElement> ret = new ArrayList<IModelElement>();
			Iterator<IRelation> it = conns.iterator();
			while (it.hasNext()) {
				ret.add(it.next().getTo());
			}
			return ret;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	abstract public String getFullyQualifiedName();

	public IModelElement getElementInNamespaceByName(String name) {
		try {
			modelSpace.lock.readLock().lock();
			Long id = namespace.get(name);
			if (id != null) {
				IModelElement me = relationsFrom.get(id);
				if (me == null) {
					if (this instanceof SimpleEntity)
						me = ((SimpleEntity) this).containment
								.get(id);
				}
				if (me == null)
					// inkonzisztens a namespace, es a tartalmazasi cucc.
					throw new VPMCoreInternalRuntimeException();
				return me;
			} else {
				return null;
			}
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	public Collection<IModelElement> getElementsInNamespace() {
		try {
			modelSpace.lock.readLock().lock();
			int size = relationsFrom.size();
			if (this instanceof IEntity) {
				size += ((SimpleEntity) this).containment.size();
			}
			List<IModelElement> ret = new ArrayList<IModelElement>(size);
			for (Iterator<Long> it = namespace.values().iterator(); it.hasNext();) {
				Long id = it.next();
				IModelElement me = relationsFrom.get(id);
				if (me == null) {
					if (this instanceof SimpleEntity)
						me = ((SimpleEntity) this).containment
								.get(id);
				}
				if (me == null)
					// inkonzisztens a namespace, es a tartalmazasi cucc.
					throw new VPMCoreInternalRuntimeException();
				ret.add(me);
			}
			return ret;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	public Collection<IModelElement> getAllElementsInNamespace() {
		try {
			modelSpace.lock.readLock().lock();
			ArrayList<IModelElement> ret = new ArrayList<IModelElement>();
			ret.addAll(getElementsInNamespace());
			for (IModelElement elem : getElementsInNamespace()) {
				ret.addAll(elem.getAllElementsInNamespace());
			}
			return ret;
		} finally {
			modelSpace.lock.readLock().unlock();
		}
	}

	protected boolean isDeleted = false;

	public boolean isDeleted() {
		try {
			// modelSpace.lock.lock();
			return isDeleted;
		} finally {
			// modelSpace.lock.unlock();
		}
	}

	public boolean isBelowNamespace(IModelElement grandpa) {
		if (grandpa==null) {
			//throw new VPMCoreNullParameterException("parameter grandpa cannot be null!");
			modelSpace.framework.getLogger().warning("isBelowNamespace has been queried with a null parameter!");
			return false;
		}
		IModelElement namespce = getNamespace();
		if (namespce == null)
			return false;
		if (namespce.equals(grandpa))
//		if (grandpa.equals(namespce))
			return true;
		else
			return namespce.isBelowNamespace(grandpa);
	}

	public Collection<IModelElement> getElementsInRelation(
			EConstraint relationType) {
		// TODO Auto-generated method stub
		return null;
	}
}
