[Mobies-commit] [commit] r4144 - in UDM/branches/UDM_next: include src/UdmBase src/UdmDom src/UdmUtil tests/test_refports
ksmyth at redhat1.isis.vanderbilt.edu
ksmyth at redhat1.isis.vanderbilt.edu
Thu Dec 27 10:56:18 CST 2012
Author: ksmyth
Date: Thu Dec 27 10:56:18 2012
New Revision: 4144
Log:
Merge 4138 and 4139
Modified:
UDM/branches/UDM_next/include/UdmDom.h
UDM/branches/UDM_next/include/UdmStatic.h
UDM/branches/UDM_next/include/UdmUtil.h
UDM/branches/UDM_next/src/UdmBase/UdmStatic.cpp
UDM/branches/UDM_next/src/UdmDom/UdmDom.cpp
UDM/branches/UDM_next/src/UdmUtil/UdmUtil.cpp
UDM/branches/UDM_next/tests/test_refports/RefPortsTest.cpp
Modified: UDM/branches/UDM_next/include/UdmDom.h
==============================================================================
--- UDM/branches/UDM_next/include/UdmDom.h Thu Dec 27 10:54:57 2012 (r4143)
+++ UDM/branches/UDM_next/include/UdmDom.h Thu Dec 27 10:56:18 2012 (r4144)
@@ -57,7 +57,7 @@
typedef std::map<Udm::ObjectImpl::uniqueId_type, DOMElement*> IdToDomElementMap;
typedef std::pair<const Udm::ObjectImpl::uniqueId_type, DOMElement*> IdToDomElementMapItem;
-
+
namespace UdmDom
{
using namespace std;
@@ -71,7 +71,7 @@
bool isXmi(const string& filename);
-
+
class DomDataNetwork : public Udm::DataNetwork
{
static bool multiroles;
@@ -90,6 +90,11 @@
//meta type-cache-by-name
map<string, ::Uml::Class> meta_class_cache;
+ //to temporarily store helper associations
+ typedef multimap<long, XMLCh*> to_assoc_help_mmap;
+ multimap<long, to_assoc_help_mmap> to_assoc_help;
+
+
UDM_DLL DomDataNetwork(const Udm::UdmDiagram &metainfo, Udm::UdmProject* pr = NULL);
UDM_DLL ~DomDataNetwork();
#ifdef _WIN32
Modified: UDM/branches/UDM_next/include/UdmStatic.h
==============================================================================
--- UDM/branches/UDM_next/include/UdmStatic.h Thu Dec 27 10:54:57 2012 (r4143)
+++ UDM/branches/UDM_next/include/UdmStatic.h Thu Dec 27 10:56:18 2012 (r4144)
@@ -340,7 +340,7 @@
// --- associations
typedef udm_multimap<uniqueId_type, StaticObject*> assoc_type;
assoc_type associations; // not reference counted, bidirectional
-
+ assoc_type to_assoc_help;
vector<ObjectImpl*> getAssociation(const ::Uml::AssociationRole &meta, int mode = Udm::TARGETFROMPEER) const;
void setAssociation(
Modified: UDM/branches/UDM_next/include/UdmUtil.h
==============================================================================
--- UDM/branches/UDM_next/include/UdmUtil.h Thu Dec 27 10:54:57 2012 (r4143)
+++ UDM/branches/UDM_next/include/UdmUtil.h Thu Dec 27 10:56:18 2012 (r4144)
@@ -42,6 +42,8 @@
};
extern UDM_DLL const CopyOpts DefCopyOpts;
+ UDM_DLL bool isHelperAssociation(Uml::AssociationRole assocRole, Uml::Class cls);
+
//utility which copies a subtree from a data network to another
//consistent (same) meta is assumed.
//direct parameter will be passed thru setAssociation
Modified: UDM/branches/UDM_next/src/UdmBase/UdmStatic.cpp
==============================================================================
--- UDM/branches/UDM_next/src/UdmBase/UdmStatic.cpp Thu Dec 27 10:54:57 2012 (r4143)
+++ UDM/branches/UDM_next/src/UdmBase/UdmStatic.cpp Thu Dec 27 10:56:18 2012 (r4144)
@@ -2005,6 +2005,56 @@
else if (mode == Udm::CLASSFROMTARGET) ms = "CLASSFROMTARGET";
cout << " mode: " << ms << endl;
*/
+
+ //ref port container change
+ bool isRefPortContChange = false;
+ bool isHelperAssoc = UdmUtil::isHelperAssociation(meta, m_type);
+
+ bool realConnExists = true;
+ Uml::Association assoc = m_type.association();
+
+
+ if(isHelperAssoc)
+ {
+ if (assoc)
+ {
+ vector<ObjectImpl*> a = getAssociation(meta.rp_helper_user(), Udm::TARGETFROMCLASS);
+ if (a.size() == 0) realConnExists = false;
+ } else
+ {
+ if (nvect.size()!=1) throw udm_exception("Assigning more than one connection to role {"+(string)meta.name()+"} is not permitted!");
+ ObjectImpl* connection = *(nvect.begin());
+ Uml::Class conn_type = connection->type();
+ Uml::Association conn_type_ass = conn_type.association();
+ if (! conn_type_ass ) throw udm_exception ("Association class {"+(string)conn_type.name()+"} without association!");
+
+ vector<ObjectImpl*> a = connection->getAssociation( Uml::theOther(meta).rp_helper_user(), Udm::TARGETFROMCLASS);
+ if (a.size() == 0) realConnExists = false;
+ }
+ }
+
+ isRefPortContChange = isHelperAssoc && realConnExists && direct;
+
+ if (!isRefPortContChange && direct) {
+ assoc_type::iterator it;
+
+ Uml::AssociationRole ar = meta.rp_helper();
+ long count = to_assoc_help.count(ar.uniqueId());
+ if (count)
+ {
+ if (count > 1) throw udm_exception("More than one reference assigned to association role: "+(string)ar.name());
+
+ pair<assoc_type::const_iterator, assoc_type::const_iterator> it1 = to_assoc_help.equal_range(ar.uniqueId());
+
+ vector<ObjectImpl*> v;
+ v.insert(v.begin(), (*it1.first).second);
+
+ setAssociation(ar, v, Udm::TARGETFROMPEER, false);
+ (*it1.first).second->release();
+ to_assoc_help.erase(ar.uniqueId());
+ }
+
+ }
//inherited children of instances
@@ -2239,8 +2289,11 @@
bidir_ass_pair iterators = bam_i->second;
//remove from both association maps
- associations.erase(iterators.first);
- so->associations.erase(iterators.second);
+ if(!isRefPortContChange){
+ associations.erase(iterators.first);
+ so->associations.erase(iterators.second);
+ }
+
//archetype/derived stuff.
//this link needs to be deleted in all my instantiated and derived objects
@@ -2324,10 +2377,12 @@
}
- so->release(); //because deleted my party from my assoc. table
+ if(!isRefPortContChange)
+ so->release(); //because deleted my party from my assoc. table
if (this->refCount <= 1)
throw udm_exception("Recount error is setassociation. At least my parent should have a reference to me!");
- this->release(); //because deleted myself from my party's assoc. table
+ if(!isRefPortContChange)
+ this->release(); //because deleted myself from my party's assoc. table
}
else
to_associate.erase(it_to_ass);
@@ -2338,18 +2393,30 @@
for(set<ObjectImpl*>::iterator it_to_ass = to_associate.begin(); it_to_ass != to_associate.end(); it_to_ass++)
{
//remove association between peer and its peers when the model says that peer can be connected to a single object
- if (orole.max() == 1 && mode == Udm::TARGETFROMPEER)
+ if (!isRefPortContChange && orole.max() == 1 && mode == Udm::TARGETFROMPEER)
((StaticObject*)(*it_to_ass))->setAssociation(orole, vector<ObjectImpl*>(), mode, false);
//ok, create the link(increment ref. count's)
//one for me,
pair<uniqueId_type const, StaticObject*> associated(meta.uniqueId(), ((StaticObject*)(*it_to_ass)->clone()));
- associations.safe_insert(associated);
+
+ if (!isRefPortContChange){
+ associations.safe_insert(associated);
+ }else {
+ to_assoc_help.safe_insert(associated);
+ }
+
//and the other one for my party
pair<uniqueId_type const, StaticObject*> ass_me(orole.uniqueId(), (StaticObject*)this->clone());
- ((StaticObject*)(*it_to_ass))->associations.safe_insert(ass_me);
+
+ if (!isRefPortContChange) {
+ ((StaticObject*)(*it_to_ass))->associations.safe_insert(ass_me);
+ }else{
+ ((StaticObject*)(*it_to_ass))->to_assoc_help.safe_insert(ass_me);
+ }
+
}
//it is a reference setting, we'll do it afterwards
Modified: UDM/branches/UDM_next/src/UdmDom/UdmDom.cpp
==============================================================================
--- UDM/branches/UDM_next/src/UdmDom/UdmDom.cpp Thu Dec 27 10:54:57 2012 (r4143)
+++ UDM/branches/UDM_next/src/UdmDom/UdmDom.cpp Thu Dec 27 10:56:18 2012 (r4144)
@@ -450,7 +450,8 @@
{
return ( ((string)(meta.name()) == "ref") && (mode == Udm::TARGETFROMPEER) && nvect.size()==1);
};
-
+
+
// --------------------------- DomObject
//function which returns the long id from the string id
@@ -2693,6 +2694,67 @@
void setAssociation(const ::Uml::AssociationRole &role, const vector<ObjectImpl*> &nvect, int mode = Udm::TARGETFROMPEER, const bool direct = true)
{
+ //handle ref port container change
+ bool isRefPortContChange = false;
+ bool isHelperAssoc = UdmUtil::isHelperAssociation(role, m_type);
+
+ bool realConnExists = true;
+ Uml::Association assoc = m_type.association();
+
+ if(isHelperAssoc)
+ {
+ if (assoc)
+ {
+ vector<ObjectImpl*> a = getAssociation(role.rp_helper_user(), Udm::TARGETFROMCLASS);
+ if (a.size() == 0) realConnExists = false;
+ } else
+ {
+ if (nvect.size()!=1) throw udm_exception("Assigning more than one connection to role {"+(string)role.name()+"} is not permitted!");
+ ObjectImpl* connection = *(nvect.begin());
+ Uml::Class conn_type = connection->type();
+ Uml::Association conn_type_ass = conn_type.association();
+ if (! conn_type_ass ) throw udm_exception ("Association class {"+(string)conn_type.name()+"} without association!");
+
+ vector<ObjectImpl*> a = connection->getAssociation( Uml::theOther(role).rp_helper_user(), Udm::TARGETFROMCLASS);
+ if (a.size() == 0) realConnExists = false;
+ }
+ }
+
+ isRefPortContChange = isHelperAssoc && realConnExists && direct;
+
+
+
+ if (!isRefPortContChange && direct) {
+
+ pair<multimap<long, DomDataNetwork::to_assoc_help_mmap>::const_iterator, multimap<long, DomDataNetwork::to_assoc_help_mmap>::const_iterator> it = ((DomDataNetwork*)mydn)->to_assoc_help.equal_range(uniqueId());
+
+ for (multimap<long, DomDataNetwork::to_assoc_help_mmap>::const_iterator j = it.first; j != it.second;)
+ {
+ DomDataNetwork::to_assoc_help_mmap emap = j->second;
+ multimap<long, DomDataNetwork::to_assoc_help_mmap>::const_iterator erase_it = j++;
+ Uml::AssociationRole ar = role.rp_helper();
+ long count = emap.count(ar.uniqueId());
+ if (count)
+ {
+ if (count > 1) throw udm_exception("More than one reference assigned to association role: "+(string)ar.name());
+ pair<DomDataNetwork::to_assoc_help_mmap::const_iterator, DomDataNetwork::to_assoc_help_mmap::const_iterator> it1 = emap.equal_range(ar.uniqueId());
+
+ vector<ObjectImpl*> v;
+ XMLCh* oid = (*it1.first).second;
+
+ DOMElement *elem = (dom_element->getOwnerDocument())->getElementById(oid);
+ DomObject dobj = DomObject(elem, mydn);
+
+ v.insert(v.begin(), (ObjectImpl*)&dobj);
+ setAssociation(ar, v, Udm::TARGETFROMPEER, false);
+ //(*it1.first).second->release();
+ XMLString::release(&oid);
+ ((DomDataNetwork*)mydn)->to_assoc_help.erase(erase_it);
+ }
+ }
+
+ }
+
Udm::Object this_o = clone(); //most of the archetype/derived/instances related
//code will use TOMI Object level functions
@@ -2788,21 +2850,33 @@
currentpeer->removeAttribute(tname_buf);
else
{
- int k = DSFind(cpa, peerid);
- if (k >= 0)
- {
- XMLCh *cpa_new = XMLString::replicate(cpa);
- DSRemoveSubstr(cpa_new, k, XMLString::stringLen(peerid) + 1);
- if (XMLString::stringLen(cpa_new))
- currentpeer->setAttribute(tname_buf, cpa_new);
+ if (!isRefPortContChange) {
+ int k = DSFind(cpa, peerid);
+ if (k >= 0)
+ {
+ XMLCh *cpa_new = XMLString::replicate(cpa);
+ DSRemoveSubstr(cpa_new, k, XMLString::stringLen(peerid) + 1);
+ if (XMLString::stringLen(cpa_new))
+ currentpeer->setAttribute(tname_buf, cpa_new);
+ else
+ currentpeer->removeAttribute(tname_buf);
+ }
else
currentpeer->removeAttribute(tname_buf);
}
- else
- currentpeer->removeAttribute(tname_buf);
}
}
- peer.dom_element->setAttribute(oname_buf, myid);
+ if (!isRefPortContChange){
+ peer.dom_element->setAttribute(oname_buf, myid);
+ } else {
+ if(nvect.size() == 1){
+ pair<long, XMLCh*> p = make_pair(orole.uniqueId(), XMLString::replicate(myid));
+ DomDataNetwork::to_assoc_help_mmap mmap;
+ mmap.insert(p);
+ ((DomDataNetwork*)mydn)->to_assoc_help.insert(make_pair(peer.uniqueId(), mmap));
+ }
+ }
+
}
else
{
@@ -2814,7 +2888,15 @@
if(aa == NULL) dom_element->removeAttribute(tname_buf);
else {
- dom_element->setAttribute(tname_buf, aa);
+ if(isRefPortContChange){
+ //save current to tmp map
+ pair<long, XMLCh*> p = make_pair(role.uniqueId(), XMLString::replicate(aa));
+ DomDataNetwork::to_assoc_help_mmap mmap;
+ mmap.insert(p);
+ ((DomDataNetwork*)mydn)->to_assoc_help.insert(make_pair(uniqueId(), mmap));
+ }else{
+ dom_element->setAttribute(tname_buf, aa);
+ }
XMLString::release(&aa);
}
Modified: UDM/branches/UDM_next/src/UdmUtil/UdmUtil.cpp
==============================================================================
--- UDM/branches/UDM_next/src/UdmUtil/UdmUtil.cpp Thu Dec 27 10:54:57 2012 (r4143)
+++ UDM/branches/UDM_next/src/UdmUtil/UdmUtil.cpp Thu Dec 27 10:56:18 2012 (r4144)
@@ -280,7 +280,10 @@
}
}
-
+ bool isHelperAssociation(Uml::AssociationRole assocRole, Uml::Class cls)
+ {
+ return (Uml::AssociationRole)theOther(assocRole).rp_helper_user() != Udm::null || (Uml::IsAssocClass(cls) && (Uml::AssociationRole)assocRole.rp_helper_user()!= Udm::null);
+ }
int reqCopyObjectHierarchy(ObjectImpl* p_srcRoot, ObjectImpl* p_dstRoot, DataNetwork* p_dstBackend, bool & finished, copy_assoc_map &cam)
{
Modified: UDM/branches/UDM_next/tests/test_refports/RefPortsTest.cpp
==============================================================================
--- UDM/branches/UDM_next/tests/test_refports/RefPortsTest.cpp Thu Dec 27 10:54:57 2012 (r4143)
+++ UDM/branches/UDM_next/tests/test_refports/RefPortsTest.cpp Thu Dec 27 10:56:18 2012 (r4144)
@@ -153,7 +153,7 @@
CPPUNIT_ASSERT_EQUAL((size_t)1, conns.size());
CPPUNIT_ASSERT_EQUAL(c, *conns.begin());
-#if 0
+#if 1
// what should happen when the reference port is connected and the
// user changes the reference port container preference?
// - reconnect with the new container?
@@ -172,17 +172,21 @@
CPPUNIT_ASSERT(BRef::Cast(c.b_end__rp_container()) == bref3);
#endif
- set<B> bs;
- conns.clear();
- a.b_end() = conns;
-
// connect to another refport using another refport container
- // c.b_end__rp_container() = bref3;
+ //c.b_end__rp_container() = bref3;
conns.clear();
conns.insert(c);
- bref3.b_end__rp_container_rev() = conns;
- c.b_end_end() = b2;
+ bref.b_end__rp_container_rev() = conns;
CPPUNIT_ASSERT_EQUAL(BRef::Cast(c.b_end__rp_container()), bref3);
+ // after port change, the preference becomes visible
+ c.b_end_end() = b;
+ CPPUNIT_ASSERT_EQUAL(BRef::Cast(c.b_end__rp_container()), bref);
+
+ c.b_end__rp_container() = bref3;
+ CPPUNIT_ASSERT(BRef::Cast(c.b_end__rp_container()) == bref);
+ // after port change, the preference becomes visible
+ c.b_end_end() = b2;
+ CPPUNIT_ASSERT(BRef::Cast(c.b_end__rp_container()) == bref3);
// show connecting chains
{
More information about the Mobies-commit
mailing list