[Mobies-commit] [commit] r3558 - GReAT/trunk/Tools/MetaGME2UMX

ksmyth at redhat1.isis.vanderbilt.edu ksmyth at redhat1.isis.vanderbilt.edu
Thu Nov 18 13:19:18 CST 2010


Author: ksmyth
Date: Thu Nov 18 13:19:17 2010
New Revision: 3558

Log:
Support bidirectional connections. Only generate a refport association if the connection and refport container can be contained in a common model

Modified:
   GReAT/trunk/Tools/MetaGME2UMX/MetaGME2UML.h
   GReAT/trunk/Tools/MetaGME2UMX/MetaGME2UML_2.cpp

Modified: GReAT/trunk/Tools/MetaGME2UMX/MetaGME2UML.h
==============================================================================
--- GReAT/trunk/Tools/MetaGME2UMX/MetaGME2UML.h	Wed Nov 17 15:34:28 2010	(r3557)
+++ GReAT/trunk/Tools/MetaGME2UMX/MetaGME2UML.h	Thu Nov 18 13:19:17 2010	(r3558)
@@ -150,8 +150,9 @@
 	void CreateInheritanceAssociation(MetaGME::ParadigmSheet ps, UmlGME::ClassDiagram cd);
 
 	void CreateRefportContainersAssociations(MetaGME::ParadigmSheet ps, UmlGME::ClassDiagram cd);
-	void CreateRefportContainerAssociation(MetaGME::Connection connection, std::string assoc_rolename, std::string refport_container_rolename, MetaGME::BaseFCO atom, UmlGME::ClassDiagram cd);
-	void CreateRefportConnection(UmlGME::ClassBase& connection, UmlGME::ClassBase& refport_container, std::string& rolename);
+	std::set<MetaGME::Reference> GetRefportContainers(MetaGME::BaseFCO& connend, const MetaGME::Connection& connection);
+	void CreateRefportContainerAssociation(const MetaGME::Connection& connection, const std::string& assoc_rolename, const std::string& rolename, const std::set<MetaGME::Reference>& refport_containers, UmlGME::ClassDiagram& cd);
+	void CreateRefportConnection(const UmlGME::ClassBase& connection, const UmlGME::ClassBase& refport_container, const std::string& rolename);
 
 	void CreateEquivalenceAssociation(MetaGME::ParadigmSheet ps, UmlGME::ClassDiagram cd);
 	void CreateFolderEquivalenceAssociation(MetaGME::ParadigmSheet ps, UmlGME::ClassDiagram cd);

Modified: GReAT/trunk/Tools/MetaGME2UMX/MetaGME2UML_2.cpp
==============================================================================
--- GReAT/trunk/Tools/MetaGME2UMX/MetaGME2UML_2.cpp	Wed Nov 17 15:34:28 2010	(r3557)
+++ GReAT/trunk/Tools/MetaGME2UMX/MetaGME2UML_2.cpp	Thu Nov 18 13:19:17 2010	(r3558)
@@ -998,6 +998,59 @@
 	}
 };
 
+template<class T>
+std::set<T> flatten_set(const std::set<std::set<T> >& s) {
+	std::set<T> ret;
+	std::for_each(s.begin(), s.end(), Copy_Set<T>(ret));
+	return ret;
+}
+
+template<typename UF>
+struct _GetAllConnections {
+	// i.e. UF::result_type should be a AClassAssocAttr
+	typedef typename UF::result_type::connector Conn;
+	const UF& F;
+	_GetAllConnections(const UF& f) : F(f) { }
+	std::set<Conn> operator()(const MetaGME::BaseFCO& fco)
+	{
+		std::set<std::set<Conn> > conns;
+		MetaGME::BaseFCO base = RefByProxy(fco);
+		conns.insert(F(base));
+		if (base.type() == MetaGME::Atom::meta) {
+			MetaGME::Atom atom = MetaGME::Atom::Cast(base);
+			trans(std::set<MetaGME::AtomProxy>(atom.src()), conns, F);
+		} else if (base.type() == MetaGME::FCO::meta) {
+			MetaGME::FCO fco = MetaGME::FCO::Cast(base);
+			trans(std::set<MetaGME::FCOProxy>(fco.src()), conns, F);
+		} else if (base.type() == MetaGME::Model::meta) {
+			MetaGME::Model model = MetaGME::Model::Cast(base);
+			trans(std::set<MetaGME::ModelProxy>(model.src()), conns, F);
+		} else if (base.type() == MetaGME::Set::meta) {
+			MetaGME::Set set = MetaGME::Set::Cast(base);
+			trans(std::set<MetaGME::SetProxy>(set.src()), conns, F);
+		} else if (base.type() == MetaGME::Reference::meta) {
+			MetaGME::Reference ref = MetaGME::Reference::Cast(base);
+			trans(std::set<MetaGME::ReferenceProxy>(ref.src()), conns, F);
+		} else if (base.type() == MetaGME::Connection::meta) {
+			MetaGME::Connection ref = MetaGME::Connection::Cast(base);
+			trans(std::set<MetaGME::ConnectionProxy>(ref.src()), conns, F);
+		}
+		return flatten_set(conns);
+	}
+};
+
+template<class UF>
+std::set<typename _GetAllConnections<UF>::Conn> GetAllConnections(const MetaGME::BaseFCO& fco, const UF& f) {
+	_GetAllConnections<UF> gac(f);
+	return gac(fco);
+}
+
+template<class UF>
+_GetAllConnections<UF> GetAllConnectionsFunctor(const UF& f) {
+	return _GetAllConnections<UF>(f);
+}
+
+
 void MetaGME2UML::CreateRefportContainersAssociations(MetaGME::ParadigmSheet ps, UmlGME::ClassDiagram cd)
 {
 	vector<MetaGME::Connection> connections = ps.Connection_kind_children();
@@ -1012,8 +1065,7 @@
 		std::set<std::set<MetaGME::AssociationClass> > aclasses;
 		trans(baseConnections, aclasses, std::mem_fun_ref(&MetaGME::BaseConnection::srcConnection));
 		trans(baseConnections, aclasses, std::mem_fun_ref(&MetaGME::BaseConnection::dstConnection));
-		std::set<MetaGME::AssociationClass> aclasses_;
-		for_each(aclasses.begin(), aclasses.end(), Copy_Set<MetaGME::AssociationClass>(aclasses_));
+		std::set<MetaGME::AssociationClass> aclasses_ = flatten_set(aclasses);
 		if (aclasses_.size() == 0)
 			continue;
 		if (aclasses_.size() > 1)
@@ -1040,34 +1092,43 @@
 
 		strmap prefMap;
 		ConverGeneralPreferenceToMap((string)connection.GeneralPreferences(), prefMap);
-		std::string rolename;
-
+		
 		MetaGME::BaseFCO dstFco = ctodst.begin()->dstFCO_end();
-		rolename = GetValueForName("dRefParent",prefMap);
+		std::string dstrolename = GetValueForName("dRefParent",prefMap);
 		string dst_assoc_rolename = GetValueForName("dName",prefMap);
-		if (dstFco && rolename != "")
+		MetaGME::BaseFCO srcFco = srctoc.begin()->srcFCO_end();
+		string srcrolename = GetValueForName("sRefParent",prefMap);
+		string src_assoc_rolename = GetValueForName("sName",prefMap);
+
+		if (dstFco && dstrolename != "")
 		{
-			CreateRefportContainerAssociation(connection, dst_assoc_rolename, rolename, RefByProxy(dstFco), cd);
+			std::set<MetaGME::Reference> refport_containers = GetRefportContainers(RefByProxy(dstFco), connection);
+			if (ctodst.begin()->dstRolename() == "" && srctoc.begin()->srcRolename() == "") { // bidirectional connection
+				std::set<MetaGME::Reference> src_refport_containers = GetRefportContainers(RefByProxy(srcFco), connection);
+				std::copy(src_refport_containers.begin(), src_refport_containers.end(), set_inserter(refport_containers));
+			}
+			CreateRefportContainerAssociation(connection, dst_assoc_rolename, dstrolename, refport_containers, cd);
 		}
 
-		MetaGME::BaseFCO srcFco = srctoc.begin()->srcFCO_end();
-		rolename = GetValueForName("sRefParent",prefMap);
-		string src_assoc_rolename = GetValueForName("sName",prefMap);
-		if (srcFco && rolename != "")
+		if (srcFco && srcrolename != "")
 		{
-			CreateRefportContainerAssociation(connection, src_assoc_rolename, rolename, RefByProxy(srcFco), cd);
+			std::set<MetaGME::Reference> refport_containers = GetRefportContainers(RefByProxy(srcFco), connection);
+			if (ctodst.begin()->dstRolename() == "" && srctoc.begin()->srcRolename() == "") { // bidirectional connection
+				std::set<MetaGME::Reference> dst_refport_containers = GetRefportContainers(RefByProxy(dstFco), connection);
+				std::copy(dst_refport_containers.begin(), dst_refport_containers.end(), set_inserter(refport_containers));
+			}
+			CreateRefportContainerAssociation(connection, src_assoc_rolename, srcrolename, refport_containers, cd);
 		}
 
 	}
 }
 
-void MetaGME2UML::CreateRefportContainerAssociation(MetaGME::Connection connection, std::string assoc_rolename, std::string rolename, MetaGME::BaseFCO connend, UmlGME::ClassDiagram cd)
+
+std::set<MetaGME::BaseFCO> GetSelfAndSubtypes(const MetaGME::BaseFCO& fco)
 {
-	std::set<MetaGME::BaseFCO> subtypes; // populate this in the while loop
-	// FIXME: should look at supertypes too
 	std::set<MetaGME::BaseFCO> basefcos_processed;
 	std::deque<MetaGME::BaseFCO> basefcos_to_process;
-	basefcos_to_process.push_back(connend);
+	basefcos_to_process.push_back(fco);
 	while (basefcos_to_process.size()) {
 		MetaGME::BaseFCO base = basefcos_to_process.front();
 		basefcos_to_process.pop_front();
@@ -1075,52 +1136,98 @@
 		if (basefcos_processed.find(base) != basefcos_processed.end())
 			continue;
 		basefcos_processed.insert(base);
-		if (base.type() != MetaGME::Connection::meta) // Connections cannot be ports
-			subtypes.insert(base);
 
 		// Get all derived FCOs of base
-		std::set<std::set<MetaGME::BaseInheritance> > baseinhs;
-		baseinhs.insert(base.bdst());
-		if (base.type() == MetaGME::Atom::meta) {
-			MetaGME::Atom atom = MetaGME::Atom::Cast(base);
-			trans(std::set<MetaGME::AtomProxy>(atom.src()), baseinhs, std::mem_fun_ref(&MetaGME::BaseFCO::bdst));
-		} else if (base.type() == MetaGME::FCO::meta) {
-			MetaGME::FCO fco = MetaGME::FCO::Cast(base);
-			trans(std::set<MetaGME::FCOProxy>(fco.src()), baseinhs, std::mem_fun_ref(&MetaGME::BaseFCO::bdst));
-		} else if (base.type() == MetaGME::Model::meta) {
-			MetaGME::Model model = MetaGME::Model::Cast(base);
-			trans(std::set<MetaGME::ModelProxy>(model.src()), baseinhs, std::mem_fun_ref(&MetaGME::BaseFCO::bdst));
-		} else if (base.type() == MetaGME::Set::meta) {
-			MetaGME::Set set = MetaGME::Set::Cast(base);
-			trans(std::set<MetaGME::SetProxy>(set.src()), baseinhs, std::mem_fun_ref(&MetaGME::BaseFCO::bdst));
-		} else if (base.type() == MetaGME::Reference::meta) {
-			MetaGME::Reference ref = MetaGME::Reference::Cast(base);
-			trans(std::set<MetaGME::ReferenceProxy>(ref.src()), baseinhs, std::mem_fun_ref(&MetaGME::BaseFCO::bdst));
-		} else {
-			continue;
-		}
-		std::set<MetaGME::BaseInheritance> baseinhs_;
-		for_each(baseinhs.begin(), baseinhs.end(), Copy_Set<MetaGME::BaseInheritance>(baseinhs_));
+		std::set<MetaGME::BaseInheritance> baseinhs = 
+			GetAllConnections(base, std::mem_fun_ref(&MetaGME::BaseFCO::bdst));
 		std::set<MetaGME::Inheritance> inheritances;
-		trans(baseinhs_, inheritances, std::mem_fun_ref(&MetaGME::BaseInheritance::bdst_end));
+		trans(baseinhs, inheritances, std::mem_fun_ref(&MetaGME::BaseInheritance::bdst_end));
 		std::set<std::set<MetaGME::DerivedInheritance> > derivedinhs;
 		trans(inheritances, derivedinhs, std::mem_fun_ref(&MetaGME::Inheritance::ddst));
-		std::set<MetaGME::DerivedInheritance> derivedinhs_;
-		for_each(derivedinhs.begin(), derivedinhs.end(), Copy_Set<MetaGME::DerivedInheritance>(derivedinhs_));
+		std::set<MetaGME::DerivedInheritance> derivedinhs_ = flatten_set(derivedinhs);
 		std::set<MetaGME::BaseFCO> derivedfcos;
 		trans(derivedinhs_, derivedfcos, std::mem_fun_ref(&MetaGME::DerivedInheritance::ddst_end));
 		std::copy(derivedfcos.begin(), derivedfcos.end(), std::back_inserter(basefcos_to_process));
 	}
+	return basefcos_processed;
+}
+
+
+std::set<MetaGME::BaseFCO> GetSelfAndSupertypes(const MetaGME::BaseFCO& fco)
+{
+	std::set<MetaGME::BaseFCO> basefcos_processed;
+	std::deque<MetaGME::BaseFCO> basefcos_to_process;
+	basefcos_to_process.push_back(fco);
+	while (basefcos_to_process.size()) {
+		MetaGME::BaseFCO base = basefcos_to_process.front();
+		basefcos_to_process.pop_front();
+		base = RefByProxy(base);
+		if (basefcos_processed.find(base) != basefcos_processed.end())
+			continue;
+		basefcos_processed.insert(base);
 
-	// all of the derived atoms of connend are in atom_subtypes now
-	// now compute port_containers: models that can contain an atom_subtype as a port
-	// FIXME: we should also look up in the inheritance hierarchy for port_containments
+		// Get all supertype FCOs of base
+		std::set<MetaGME::DerivedInheritance> dinhs = 
+			GetAllConnections(base, std::mem_fun_ref(&MetaGME::BaseFCO::dsrc));
+		std::set<MetaGME::Inheritance> inheritances;
+		trans(dinhs, inheritances, std::mem_fun_ref(&MetaGME::DerivedInheritance::dsrc_end));
+		std::set<std::set<MetaGME::BaseInheritance> > binhs;
+		trans(inheritances, binhs, std::mem_fun_ref(&MetaGME::Inheritance::bsrc));
+		std::set<MetaGME::BaseInheritance> binhs_ = flatten_set(binhs);
+		std::set<MetaGME::BaseFCO> superfcos;
+		trans(binhs_, superfcos, std::mem_fun_ref(&MetaGME::BaseInheritance::bsrc_end));
+		std::copy(superfcos.begin(), superfcos.end(), std::back_inserter(basefcos_to_process));
+	}
+	return basefcos_processed;
+}
+
+struct IsDerivedFrom : public unary_function<Udm::Object, bool>
+{
+	const Uml::Class& class_;
+	IsDerivedFrom(const Uml::Class& class_) : class_(class_) { }
+	bool operator()(const Udm::Object& o) const {
+		return Uml::IsDerivedFrom(o.type(), class_);
+	}
+};
+
+std::set<MetaGME::BaseFCO> GetContainersAndTheirSubtypes(const MetaGME::BaseFCO& fco) {
+	std::set<MetaGME::Containment> containments = GetAllConnections(fco, std::mem_fun_ref(&MetaGME::BaseFCO::dstContainment));
+	std::set<MetaGME::BaseModel> containers;
+	trans(containments, containers, std::mem_fun_ref(&MetaGME::Containment::dstContainment_end));
+	std::set<std::set<MetaGME::BaseFCO> > containers_and_supertypes;
+	trans(containers, containers_and_supertypes, std::ptr_fun(&GetSelfAndSubtypes));
+	return flatten_set(containers_and_supertypes);
+}
+
+struct CanBeContainedInSameContainer : public std::unary_function<const MetaGME::BaseFCO, bool> {
+	const MetaGME::BaseFCO& fco1;
+	CanBeContainedInSameContainer(const MetaGME::BaseFCO& fco1) : fco1(fco1) { }
+	
+	bool operator ()(const MetaGME::BaseFCO& fco2) const {
+		std::set<MetaGME::BaseFCO> fco1_containers = GetContainersAndTheirSubtypes(fco1);
+		std::set<MetaGME::BaseFCO> fco2_containers = GetContainersAndTheirSubtypes(fco2);
+
+		std::set<MetaGME::BaseFCO> common_container_subtypes;
+		std::set_intersection(fco1_containers.begin(), fco1_containers.end(),
+			fco2_containers.begin(), fco2_containers.end(),
+			set_inserter(common_container_subtypes));
+		return common_container_subtypes.size() != 0;
+	}
+};
+
+std::set<MetaGME::Reference> MetaGME2UML::GetRefportContainers(MetaGME::BaseFCO& connend, const MetaGME::Connection& connection)
+{
+	std::set<MetaGME::BaseFCO> subtypes;
+	std::set<MetaGME::BaseFCO> subtypes_ = GetSelfAndSubtypes(connend);
+	// connections cannot be ports
+	std::remove_copy_if(subtypes_.begin(), subtypes_.end(), set_inserter(subtypes), IsDerivedFrom(MetaGME::Connection::meta));
+
+	// now compute port_containers: models that can contain a subtype as a port
 	std::set<MetaGME::Model> port_containers;
 	{
 	std::set<std::set<MetaGME::Containment> > containments;
-	trans(subtypes, containments, std::mem_fun_ref(&MetaGME::FCOBase::dstContainment));
-	std::set<MetaGME::Containment> containments_;
-	for_each(containments.begin(), containments.end(), Copy_Set<MetaGME::Containment>(containments_));
+	trans(subtypes, containments, GetAllConnectionsFunctor(std::mem_fun_ref(&MetaGME::FCOBase::dstContainment)));
+	std::set<MetaGME::Containment> containments_ = flatten_set(containments);
 	std::set<MetaGME::Containment> port_containments;
 	std::remove_copy_if(containments_.begin(), containments_.end(), set_inserter(port_containments), std::not1(std::mem_fun_ref(&MetaGME::Containment::IsPort)));
 
@@ -1131,6 +1238,7 @@
 
 	MetaGME::Model (*Model_cast)(const Udm::Object&) = &MetaGME::Model::Cast;
 	trans(base_port_containers, port_containers, std::ptr_fun(Model_cast));
+	// FIXME: we should also look down in the inheritance hierarchy for port_containments
 	}
 
 	// Now compute refport_containers: the references that refer to port_containers
@@ -1138,30 +1246,40 @@
 	{
 	std::set<std::set<MetaGME::ModelProxy> > port_containers_refs;
 	trans(port_containers, port_containers_refs, std::mem_fun_ref(&MetaGME::Model::src));
-	std::set<MetaGME::ModelProxy> port_container_refs_;
-	for_each(port_containers_refs.begin(), port_containers_refs.end(), Copy_Set<MetaGME::ModelProxy>(port_container_refs_));
+	std::set<MetaGME::ModelProxy> port_container_refs_ = flatten_set(port_containers_refs);
 	std::set<MetaGME::BaseModel> port_container_refs_base;
 	std::copy(port_container_refs_.begin(), port_container_refs_.end(), set_inserter(port_container_refs_base));
 	std::copy(port_containers.begin(), port_containers.end(), set_inserter(port_container_refs_base));
 
 	std::set<std::set<MetaGME::ReferTo> > port_container_refs_refertos;
 	trans(port_container_refs_base, port_container_refs_refertos, std::mem_fun_ref(&MetaGME::BaseModel::srcReferTo));
-	std::set<MetaGME::ReferTo> port_container_refs_refertos_;
-	for_each(port_container_refs_refertos.begin(), port_container_refs_refertos.end(), Copy_Set<MetaGME::ReferTo>(port_container_refs_refertos_));
+	std::set<MetaGME::ReferTo> port_container_refs_refertos_ = flatten_set(port_container_refs_refertos);
 	std::set<MetaGME::BaseReference> baserefport_containers;
 	trans(port_container_refs_refertos_, baserefport_containers, std::mem_fun_ref(&MetaGME::ReferTo::srcReferTo_end));
 	std::set<MetaGME::BaseFCO> baserefport_containers_;
 	trans(baserefport_containers, baserefport_containers_, std::ptr_fun(&RefByProxy));
+	// references in refport_containers can only be refports if contained by something that can also contain the connection
+	// FIXME: a descendant of the other end of the connection must also be contained
+	std::set<MetaGME::BaseFCO> baserefport_containers__;
+	std::remove_copy_if(baserefport_containers_.begin(), baserefport_containers_.end(),
+		set_inserter(baserefport_containers__), 
+		std::not1(CanBeContainedInSameContainer(connection)));
+
 	MetaGME::Reference (*Reference_cast)(const Udm::Object&) = &MetaGME::Reference::Cast;
-	trans(baserefport_containers_, refport_containers, std::ptr_fun(Reference_cast));
+	trans(baserefport_containers__, refport_containers, std::ptr_fun(Reference_cast));
 	}
 
+	return refport_containers;
+}
+
+void MetaGME2UML::CreateRefportContainerAssociation(const MetaGME::Connection& connection, const std::string& assoc_rolename, const std::string& rolename, const std::set<MetaGME::Reference>& refport_containers, UmlGME::ClassDiagram& cd)
+{
 	if(refport_containers.size() == 0)
 	{
 		return;
 	}
-	// If there are more than one refport_container, or if the association class and references are in different namespaces,
-	// then we need to create an abstract class from which the references inherit
+	// If there are more than one refport_container (or if the association class and references are in different namespaces),
+	// then we need to create a ClassDiagram to contain the abstract base class (or references to the classes)
 	if (refport_containers.size() == 1)
 	{	
 		MetaGME::Reference ref = *refport_containers.begin();
@@ -1234,7 +1352,7 @@
 	}
 }
 
-void MetaGME2UML::CreateRefportConnection(UmlGME::ClassBase& connection, UmlGME::ClassBase& refport_container, std::string& rolename)
+void MetaGME2UML::CreateRefportConnection(const UmlGME::ClassBase& connection, const UmlGME::ClassBase& refport_container, const std::string& rolename)
 {
 	UmlGME::Association cref = UmlGME::Association::Create(connection.parent());
 


More information about the Mobies-commit mailing list