[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