text: #include "uml/impl/DependencyImpl.hpp"
  
  #ifdef NDEBUG
  	#define DEBUG_MESSAGE(a) /**/
  #else
  	#define DEBUG_MESSAGE(a) a
  #endif
  
  #ifdef ACTIVITY_DEBUG_ON
      #define ACT_DEBUG(a) a
  #else
      #define ACT_DEBUG(a) /**/
  #endif
  
  //#include "util/ProfileCallCount.hpp"
  
  #include <cassert>
  #include <iostream>
  #include <sstream>
  
  #include "abstractDataTypes/Bag.hpp"
  #include "abstractDataTypes/Subset.hpp"
  #include "abstractDataTypes/SubsetUnion.hpp"
  #include "abstractDataTypes/Union.hpp"
  #include "abstractDataTypes/SubsetUnion.hpp"
  #include "ecore/EAnnotation.hpp"
  #include "ecore/EClass.hpp"
  #include "uml/impl/UmlPackageImpl.hpp"
  
  //Forward declaration includes
  #include "persistence/interfaces/XLoadHandler.hpp" // used for Persistence
  #include "persistence/interfaces/XSaveHandler.hpp" // used for Persistence
  #include "uml/UmlFactory.hpp"
  #include "uml/UmlPackage.hpp"
  #include "uml/UmlFactory.hpp"
  #include "uml/UmlPackage.hpp"
  #include "uml/UmlFactory.hpp"
  #include "uml/UmlPackage.hpp"
  #include "uml/UmlFactory.hpp"
  #include "uml/UmlPackage.hpp"
  #include "uml/UmlFactory.hpp"
  #include "uml/UmlPackage.hpp"
  
  #include <exception> // used in Persistence
  
  #include "uml/Comment.hpp"
  
  #include "uml/Dependency.hpp"
  
  #include "uml/DirectedRelationship.hpp"
  
  #include "uml/Element.hpp"
  
  #include "uml/NamedElement.hpp"
  
  #include "uml/Namespace.hpp"
  
  #include "uml/Package.hpp"
  
  #include "uml/PackageableElement.hpp"
  
  #include "uml/StringExpression.hpp"
  
  #include "uml/TemplateParameter.hpp"
  
  #include "ecore/EcorePackage.hpp"
  #include "ecore/EcoreFactory.hpp"
  #include "uml/UmlPackage.hpp"
  #include "uml/UmlFactory.hpp"
  #include "ecore/EAttribute.hpp"
  #include "ecore/EStructuralFeature.hpp"
  
  using namespace uml;
  
  //*********************************
  // Constructor / Destructor
  //*********************************
  DependencyImpl::DependencyImpl()
  {
  	//*********************************
  	// Attribute Members
  	//*********************************
  
  	//*********************************
  	// Reference Members
  	//*********************************
  	//References
  		/*SubsetUnion*/
  		m_client.reset(new SubsetUnion<uml::NamedElement, uml::Element >());
  		#ifdef SHOW_SUBSET_UNION
  			std::cout << "Initialising shared pointer SubsetUnion: " << "m_client - SubsetUnion<uml::NamedElement, uml::Element >()" << std::endl;
  		#endif
  	
  	
  
  		/*SubsetUnion*/
  		m_supplier.reset(new SubsetUnion<uml::NamedElement, uml::Element >());
  		#ifdef SHOW_SUBSET_UNION
  			std::cout << "Initialising shared pointer SubsetUnion: " << "m_supplier - SubsetUnion<uml::NamedElement, uml::Element >()" << std::endl;
  		#endif
  	
  	
  
  	//Init references
  		/*SubsetUnion*/
  		m_client->initSubsetUnion(m_source);
  		#ifdef SHOW_SUBSET_UNION
  			std::cout << "Initialising value SubsetUnion: " << "m_client - SubsetUnion<uml::NamedElement, uml::Element >(m_source)" << std::endl;
  		#endif
  	
  	
  
  		/*SubsetUnion*/
  		m_supplier->initSubsetUnion(m_target);
  		#ifdef SHOW_SUBSET_UNION
  			std::cout << "Initialising value SubsetUnion: " << "m_supplier - SubsetUnion<uml::NamedElement, uml::Element >(m_target)" << std::endl;
  		#endif
  	
  	
  }
  
  DependencyImpl::~DependencyImpl()
  {
  #ifdef SHOW_DELETION
  	std::cout << "-------------------------------------------------------------------------------------------------\r\ndelete Dependency "<< this << "\r\n------------------------------------------------------------------------ " << std::endl;
  #endif
  }
  
  
  //Additional constructor for the containments back reference
  			DependencyImpl::DependencyImpl(std::weak_ptr<uml::Namespace > par_namespace)
  			:DependencyImpl()
  			{
  			    m_namespace = par_namespace;
  				m_owner = par_namespace;
  			}
  
  
  
  
  
  //Additional constructor for the containments back reference
  			DependencyImpl::DependencyImpl(std::weak_ptr<uml::Element > par_owner)
  			:DependencyImpl()
  			{
  			    m_owner = par_owner;
  			}
  
  
  
  
  
  //Additional constructor for the containments back reference
  			DependencyImpl::DependencyImpl(std::weak_ptr<uml::Package > par_owningPackage)
  			:DependencyImpl()
  			{
  			    m_owningPackage = par_owningPackage;
  				m_namespace = par_owningPackage;
  			}
  
  
  
  
  
  //Additional constructor for the containments back reference
  			DependencyImpl::DependencyImpl(std::weak_ptr<uml::TemplateParameter > par_owningTemplateParameter)
  			:DependencyImpl()
  			{
  			    m_owningTemplateParameter = par_owningTemplateParameter;
  				m_owner = par_owningTemplateParameter;
  			}
  
  
  
  
  
  
  DependencyImpl::DependencyImpl(const DependencyImpl & obj):DependencyImpl()
  {
  	//create copy of all Attributes
  	#ifdef SHOW_COPIES
  	std::cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\ncopy Dependency "<< this << "\r\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ " << std::endl;
  	#endif
  	m_name = obj.getName();
  	m_qualifiedName = obj.getQualifiedName();
  	m_visibility = obj.getVisibility();
  
  	//copy references with no containment (soft copy)
  	
  	std::shared_ptr<Bag<uml::Dependency>> _clientDependency = obj.getClientDependency();
  	m_clientDependency.reset(new Bag<uml::Dependency>(*(obj.getClientDependency().get())));
  
  	m_namespace  = obj.getNamespace();
  
  	m_owner  = obj.getOwner();
  
  	m_owningPackage  = obj.getOwningPackage();
  
  	m_owningTemplateParameter  = obj.getOwningTemplateParameter();
  
  	std::shared_ptr<Union<uml::Element>> _relatedElement = obj.getRelatedElement();
  	m_relatedElement.reset(new Union<uml::Element>(*(obj.getRelatedElement().get())));
  
  	m_templateParameter  = obj.getTemplateParameter();
  
  
  	//Clone references with containment (deep copy)
  
  	std::shared_ptr<Bag<uml::NamedElement>> _clientList = obj.getClient();
  	for(std::shared_ptr<uml::NamedElement> _client : *_clientList)
  	{
  		this->getClient()->add(std::shared_ptr<uml::NamedElement>(std::dynamic_pointer_cast<uml::NamedElement>(_client->copy())));
  	}
  	#ifdef SHOW_SUBSET_UNION
  		std::cout << "Copying the Subset: " << "m_client" << std::endl;
  	#endif
  	if(obj.getNameExpression()!=nullptr)
  	{
  		m_nameExpression = std::dynamic_pointer_cast<uml::StringExpression>(obj.getNameExpression()->copy());
  	}
  	#ifdef SHOW_SUBSET_UNION
  		std::cout << "Copying the Subset: " << "m_nameExpression" << std::endl;
  	#endif
  	std::shared_ptr<Bag<uml::Comment>> _ownedCommentList = obj.getOwnedComment();
  	for(std::shared_ptr<uml::Comment> _ownedComment : *_ownedCommentList)
  	{
  		this->getOwnedComment()->add(std::shared_ptr<uml::Comment>(std::dynamic_pointer_cast<uml::Comment>(_ownedComment->copy())));
  	}
  	#ifdef SHOW_SUBSET_UNION
  		std::cout << "Copying the Subset: " << "m_ownedComment" << std::endl;
  	#endif
  	std::shared_ptr<Bag<uml::NamedElement>> _supplierList = obj.getSupplier();
  	for(std::shared_ptr<uml::NamedElement> _supplier : *_supplierList)
  	{
  		this->getSupplier()->add(std::shared_ptr<uml::NamedElement>(std::dynamic_pointer_cast<uml::NamedElement>(_supplier->copy())));
  	}
  	#ifdef SHOW_SUBSET_UNION
  		std::cout << "Copying the Subset: " << "m_supplier" << std::endl;
  	#endif
  
  }
  
  std::shared_ptr<ecore::EObject>  DependencyImpl::copy() const
  {
  	std::shared_ptr<DependencyImpl> element(new DependencyImpl(*this));
  	element->setThisDependencyPtr(element);
  	return element;
  }
  
  std::shared_ptr<ecore::EClass> DependencyImpl::eStaticClass() const
  {
  	return UmlPackageImpl::eInstance()->getDependency_Class();
  }
  
  //*********************************
  // Attribute Setter Getter
  //*********************************
  
  //*********************************
  // Operations
  //*********************************
  
  //*********************************
  // References
  //*********************************
  std::shared_ptr<SubsetUnion<uml::NamedElement, uml::Element>> DependencyImpl::getClient() const
  {
  //assert(m_client);
      return m_client;
  }
  
  
  std::shared_ptr<SubsetUnion<uml::NamedElement, uml::Element>> DependencyImpl::getSupplier() const
  {
  //assert(m_supplier);
      return m_supplier;
  }
  
  
  //*********************************
  // Union Getter
  //*********************************
  std::weak_ptr<uml::Namespace > DependencyImpl::getNamespace() const
  {
  	return m_namespace;
  }
  std::shared_ptr<Union<uml::Element>> DependencyImpl::getOwnedElement() const
  {
  	return m_ownedElement;
  }
  std::weak_ptr<uml::Element > DependencyImpl::getOwner() const
  {
  	return m_owner;
  }
  std::shared_ptr<Union<uml::Element>> DependencyImpl::getRelatedElement() const
  {
  	return m_relatedElement;
  }
  std::shared_ptr<SubsetUnion<uml::Element, uml::Element>> DependencyImpl::getSource() const
  {
  	return m_source;
  }
  std::shared_ptr<SubsetUnion<uml::Element, uml::Element>> DependencyImpl::getTarget() const
  {
  	return m_target;
  }
  
  
  std::shared_ptr<Dependency> DependencyImpl::getThisDependencyPtr() const
  {
  	return m_thisDependencyPtr.lock();
  }
  void DependencyImpl::setThisDependencyPtr(std::weak_ptr<Dependency> thisDependencyPtr)
  {
  	m_thisDependencyPtr = thisDependencyPtr;
  	setThisDirectedRelationshipPtr(thisDependencyPtr);
  	setThisPackageableElementPtr(thisDependencyPtr);
  }
  std::shared_ptr<ecore::EObject> DependencyImpl::eContainer() const
  {
  	if(auto wp = m_namespace.lock())
  	{
  		return wp;
  	}
  
  	if(auto wp = m_owner.lock())
  	{
  		return wp;
  	}
  
  	if(auto wp = m_owningPackage.lock())
  	{
  		return wp;
  	}
  
  	if(auto wp = m_owningTemplateParameter.lock())
  	{
  		return wp;
  	}
  	return nullptr;
  }
  
  //*********************************
  // Structural Feature Getter/Setter
  //*********************************
  Any DependencyImpl::eGet(int featureID, bool resolve, bool coreType) const
  {
  	switch(featureID)
  	{
  		case UmlPackage::DEPENDENCY_ATTRIBUTE_CLIENT:
  		{
  			std::shared_ptr<Bag<ecore::EObject>> tempList(new Bag<ecore::EObject>());
  			Bag<uml::NamedElement>::iterator iter = m_client->begin();
  			Bag<uml::NamedElement>::iterator end = m_client->end();
  			while (iter != end)
  			{
  				tempList->add(*iter);
  				iter++;
  			}
  			return eAny(tempList); //6815
  		}
  		case UmlPackage::DEPENDENCY_ATTRIBUTE_SUPPLIER:
  		{
  			std::shared_ptr<Bag<ecore::EObject>> tempList(new Bag<ecore::EObject>());
  			Bag<uml::NamedElement>::iterator iter = m_supplier->begin();
  			Bag<uml::NamedElement>::iterator end = m_supplier->end();
  			while (iter != end)
  			{
  				tempList->add(*iter);
  				iter++;
  			}
  			return eAny(tempList); //6816
  		}
  	}
  	Any result;
  	result = DirectedRelationshipImpl::eGet(featureID, resolve, coreType);
  	if (!result->isEmpty())
  	{
  		return result;
  	}
  	result = PackageableElementImpl::eGet(featureID, resolve, coreType);
  	return result;
  }
  bool DependencyImpl::internalEIsSet(int featureID) const
  {
  	switch(featureID)
  	{
  		case UmlPackage::DEPENDENCY_ATTRIBUTE_CLIENT:
  			return getClient() != nullptr; //6815
  		case UmlPackage::DEPENDENCY_ATTRIBUTE_SUPPLIER:
  			return getSupplier() != nullptr; //6816
  	}
  	bool result = false;
  	result = DirectedRelationshipImpl::internalEIsSet(featureID);
  	if (result)
  	{
  		return result;
  	}
  	result = PackageableElementImpl::internalEIsSet(featureID);
  	return result;
  }
  bool DependencyImpl::eSet(int featureID, Any newValue)
  {
  	switch(featureID)
  	{
  		case UmlPackage::DEPENDENCY_ATTRIBUTE_CLIENT:
  		{
  			// BOOST CAST
  			std::shared_ptr<Bag<ecore::EObject>> tempObjectList = newValue->get<std::shared_ptr<Bag<ecore::EObject>>>();
  			std::shared_ptr<Bag<uml::NamedElement>> clientList(new Bag<uml::NamedElement>());
  			Bag<ecore::EObject>::iterator iter = tempObjectList->begin();
  			Bag<ecore::EObject>::iterator end = tempObjectList->end();
  			while (iter != end)
  			{
  				clientList->add(std::dynamic_pointer_cast<uml::NamedElement>(*iter));
  				iter++;
  			}
  			
  			Bag<uml::NamedElement>::iterator iterClient = m_client->begin();
  			Bag<uml::NamedElement>::iterator endClient = m_client->end();
  			while (iterClient != endClient)
  			{
  				if (clientList->find(*iterClient) == -1)
  				{
  					m_client->erase(*iterClient);
  				}
  				iterClient++;
  			}
  
  			iterClient = clientList->begin();
  			endClient = clientList->end();
  			while (iterClient != endClient)
  			{
  				if (m_client->find(*iterClient) == -1)
  				{
  					m_client->add(*iterClient);
  				}
  				iterClient++;			
  			}
  			return true;
  		}
  		case UmlPackage::DEPENDENCY_ATTRIBUTE_SUPPLIER:
  		{
  			// BOOST CAST
  			std::shared_ptr<Bag<ecore::EObject>> tempObjectList = newValue->get<std::shared_ptr<Bag<ecore::EObject>>>();
  			std::shared_ptr<Bag<uml::NamedElement>> supplierList(new Bag<uml::NamedElement>());
  			Bag<ecore::EObject>::iterator iter = tempObjectList->begin();
  			Bag<ecore::EObject>::iterator end = tempObjectList->end();
  			while (iter != end)
  			{
  				supplierList->add(std::dynamic_pointer_cast<uml::NamedElement>(*iter));
  				iter++;
  			}
  			
  			Bag<uml::NamedElement>::iterator iterSupplier = m_supplier->begin();
  			Bag<uml::NamedElement>::iterator endSupplier = m_supplier->end();
  			while (iterSupplier != endSupplier)
  			{
  				if (supplierList->find(*iterSupplier) == -1)
  				{
  					m_supplier->erase(*iterSupplier);
  				}
  				iterSupplier++;
  			}
  
  			iterSupplier = supplierList->begin();
  			endSupplier = supplierList->end();
  			while (iterSupplier != endSupplier)
  			{
  				if (m_supplier->find(*iterSupplier) == -1)
  				{
  					m_supplier->add(*iterSupplier);
  				}
  				iterSupplier++;			
  			}
  			return true;
  		}
  	}
  
  	bool result = false;
  	result = DirectedRelationshipImpl::eSet(featureID, newValue);
  	if (result)
  	{
  		return result;
  	}
  	result = PackageableElementImpl::eSet(featureID, newValue);
  	return result;
  }
  
  //*********************************
  // Persistence Functions
  //*********************************
  void DependencyImpl::load(std::shared_ptr<persistence::interfaces::XLoadHandler> loadHandler)
  {
  	std::map<std::string, std::string> attr_list = loadHandler->getAttributeList();
  	loadAttributes(loadHandler, attr_list);
  
  	//
  	// Create new objects (from references (containment == true))
  	//
  	// get UmlFactory
  	std::shared_ptr<uml::UmlFactory> modelFactory = uml::UmlFactory::eInstance();
  	int numNodes = loadHandler->getNumOfChildNodes();
  	for(int ii = 0; ii < numNodes; ii++)
  	{
  		loadNode(loadHandler->getNextNodeName(), loadHandler, modelFactory);
  	}
  }		
  
  void DependencyImpl::loadAttributes(std::shared_ptr<persistence::interfaces::XLoadHandler> loadHandler, std::map<std::string, std::string> attr_list)
  {
  	try
  	{
  		std::map<std::string, std::string>::const_iterator iter;
  		std::shared_ptr<ecore::EClass> metaClass = this->eClass(); // get MetaClass
  		iter = attr_list.find("client");
  		if ( iter != attr_list.end() )
  		{
  			// add unresolvedReference to loadHandler's list
  			loadHandler->addUnresolvedReference(iter->second, loadHandler->getCurrentObject(), metaClass->getEStructuralFeature("client")); // TODO use getEStructuralFeature() with id, for faster access to EStructuralFeature
  		}
  
  		iter = attr_list.find("supplier");
  		if ( iter != attr_list.end() )
  		{
  			// add unresolvedReference to loadHandler's list
  			loadHandler->addUnresolvedReference(iter->second, loadHandler->getCurrentObject(), metaClass->getEStructuralFeature("supplier")); // TODO use getEStructuralFeature() with id, for faster access to EStructuralFeature
  		}
  	}
  	catch (std::exception& e)
  	{
  		std::cout << "| ERROR    | " << e.what() << std::endl;
  	}
  	catch (...) 
  	{
  		std::cout << "| ERROR    | " <<  "Exception occurred" << std::endl;
  	}
  
  	DirectedRelationshipImpl::loadAttributes(loadHandler, attr_list);
  	PackageableElementImpl::loadAttributes(loadHandler, attr_list);
  }
  
  void DependencyImpl::loadNode(std::string nodeName, std::shared_ptr<persistence::interfaces::XLoadHandler> loadHandler, std::shared_ptr<uml::UmlFactory> modelFactory)
  {
  
  
  	DirectedRelationshipImpl::loadNode(nodeName, loadHandler, modelFactory);
  	PackageableElementImpl::loadNode(nodeName, loadHandler, modelFactory);
  }
  
  void DependencyImpl::resolveReferences(const int featureID, std::list<std::shared_ptr<ecore::EObject> > references)
  {
  	switch(featureID)
  	{
  		case UmlPackage::DEPENDENCY_ATTRIBUTE_CLIENT:
  		{
  			std::shared_ptr<Bag<uml::NamedElement>> _client = getClient();
  			for(std::shared_ptr<ecore::EObject> ref : references)
  			{
  				std::shared_ptr<uml::NamedElement> _r = std::dynamic_pointer_cast<uml::NamedElement>(ref);
  				if (_r != nullptr)
  				{
  					_client->push_back(_r);
  				}				
  			}
  			return;
  		}
  
  		case UmlPackage::DEPENDENCY_ATTRIBUTE_SUPPLIER:
  		{
  			std::shared_ptr<Bag<uml::NamedElement>> _supplier = getSupplier();
  			for(std::shared_ptr<ecore::EObject> ref : references)
  			{
  				std::shared_ptr<uml::NamedElement> _r = std::dynamic_pointer_cast<uml::NamedElement>(ref);
  				if (_r != nullptr)
  				{
  					_supplier->push_back(_r);
  				}				
  			}
  			return;
  		}
  	}
  	DirectedRelationshipImpl::resolveReferences(featureID, references);
  	PackageableElementImpl::resolveReferences(featureID, references);
  }
  
  void DependencyImpl::save(std::shared_ptr<persistence::interfaces::XSaveHandler> saveHandler) const
  {
  	saveContent(saveHandler);
  
  	DirectedRelationshipImpl::saveContent(saveHandler);
  	PackageableElementImpl::saveContent(saveHandler);
  	
  	NamedElementImpl::saveContent(saveHandler);
  	ParameterableElementImpl::saveContent(saveHandler);
  	RelationshipImpl::saveContent(saveHandler);
  	
  	ElementImpl::saveContent(saveHandler);
  	
  	ObjectImpl::saveContent(saveHandler);
  	
  	ecore::EObjectImpl::saveContent(saveHandler);
  	
  	
  	
  	
  }
  
  void DependencyImpl::saveContent(std::shared_ptr<persistence::interfaces::XSaveHandler> saveHandler) const
  {
  	try
  	{
  		std::shared_ptr<uml::UmlPackage> package = uml::UmlPackage::eInstance();
  
  	
  
  		// Add references
  		std::shared_ptr<Bag<uml::NamedElement>> client_list = this->getClient();
  		for (std::shared_ptr<uml::NamedElement > object : *client_list)
  		{ 
  			saveHandler->addReferences("client", object);
  		}
  		std::shared_ptr<Bag<uml::NamedElement>> supplier_list = this->getSupplier();
  		for (std::shared_ptr<uml::NamedElement > object : *supplier_list)
  		{ 
  			saveHandler->addReferences("supplier", object);
  		}
  
  	}
  	catch (std::exception& e)
  	{
  		std::cout << "| ERROR    | " << e.what() << std::endl;
  	}
  }
  
  