[Mobies-commit] [commit] r4138 - in UDM/trunk: include src/UdmBase src/UdmDom src/UdmUtil tests/test_refports
endre at redhat1.isis.vanderbilt.edu
endre at redhat1.isis.vanderbilt.edu
Thu Dec 6 06:58:23 CST 2012
Author: endre
Date: Thu Dec 6 06:58:22 2012
New Revision: 4138
Log:
when the reference port is connected and the user changes the reference port container preference, this becomes visible only after changing the endpoint as well.
The case is documented in refporttest.cpp lines 160 - 190
Modified:
UDM/trunk/include/UdmDom.h
UDM/trunk/include/UdmStatic.h
UDM/trunk/include/UdmUtil.h
UDM/trunk/src/UdmBase/UdmStatic.cpp
UDM/trunk/src/UdmDom/UdmDom.cpp
UDM/trunk/src/UdmUtil/UdmUtil.cpp
UDM/trunk/tests/test_refports/RefPortsTest.cpp
Modified: UDM/trunk/include/UdmDom.h
==============================================================================
--- UDM/trunk/include/UdmDom.h Tue Oct 16 17:22:39 2012 (r4137)
+++ UDM/trunk/include/UdmDom.h Thu Dec 6 06:58:22 2012 (r4138)
@@ -89,6 +89,9 @@
static UDM_DLL string DTDPath;
//meta type-cache-by-name
map<string, ::Uml::Class> meta_class_cache;
+ //to temporarily store helper associations
+ multimap<long, multimap<long, XMLCh*>> to_assoc_help;
+
UDM_DLL DomDataNetwork(const Udm::UdmDiagram &metainfo, Udm::UdmProject* pr = NULL);
UDM_DLL ~DomDataNetwork();
Modified: UDM/trunk/include/UdmStatic.h
==============================================================================
--- UDM/trunk/include/UdmStatic.h Tue Oct 16 17:22:39 2012 (r4137)
+++ UDM/trunk/include/UdmStatic.h Thu Dec 6 06:58:22 2012 (r4138)
@@ -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/trunk/include/UdmUtil.h
==============================================================================
--- UDM/trunk/include/UdmUtil.h Tue Oct 16 17:22:39 2012 (r4137)
+++ UDM/trunk/include/UdmUtil.h Thu Dec 6 06:58:22 2012 (r4138)
@@ -42,6 +42,8 @@
};
extern UDM_DLL const CopyOpts DefCopyOpts;
+ UDM_DLL bool isHelperAssociation(string roleName, bool isAssocClass);
+
//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/trunk/src/UdmBase/UdmStatic.cpp
==============================================================================
--- UDM/trunk/src/UdmBase/UdmStatic.cpp Tue Oct 16 17:22:39 2012 (r4137)
+++ UDM/trunk/src/UdmBase/UdmStatic.cpp Thu Dec 6 06:58:22 2012 (r4138)
@@ -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(Uml::MakeRoleName(meta), Uml::IsAssocClass(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/trunk/src/UdmDom/UdmDom.cpp
==============================================================================
--- UDM/trunk/src/UdmDom/UdmDom.cpp Tue Oct 16 17:22:39 2012 (r4137)
+++ UDM/trunk/src/UdmDom/UdmDom.cpp Thu Dec 6 06:58:22 2012 (r4138)
@@ -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,73 @@
void setAssociation(const ::Uml::AssociationRole &role, const vector<ObjectImpl*> &nvect, int mode = Udm::TARGETFROMPEER, const bool direct = true)
{
+ //handle ref port container change
+ ::Uml::Class m_type = ((ObjectImpl*)this)->type();
+
+ bool isRefPortContChange = false;
+ bool isHelperAssoc = UdmUtil::isHelperAssociation(Uml::MakeRoleName(role), Uml::IsAssocClass(m_type));
+
+ if (isHelperAssoc){
+ long dnid = ((DomDataNetwork*)mydn)->uniqueId();
+ }
+
+ 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, multimap<long, XMLCh*>>::const_iterator, multimap<long, multimap<long, XMLCh*>>::const_iterator> it = ((DomDataNetwork*)mydn)->to_assoc_help.equal_range(uniqueId());
+
+ for (multimap<long, multimap<long, XMLCh*>>::const_iterator j = it.first; j != it.second;)
+ {
+ multimap<long, XMLCh*> emap = j->second;
+ multimap<long, multimap<long, XMLCh*>>::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<multimap<long, XMLCh*>::const_iterator, multimap<long, XMLCh*>::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 +2856,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));
+ multimap<long, XMLCh*> mmap;
+ mmap.insert(p);
+ ((DomDataNetwork*)mydn)->to_assoc_help.insert(make_pair(peer.uniqueId(), mmap));
+ }
+ }
+
}
else
{
@@ -2814,8 +2894,17 @@
if(aa == NULL) dom_element->removeAttribute(tname_buf);
else {
- dom_element->setAttribute(tname_buf, aa);
- XMLString::release(&aa);
+ if(isRefPortContChange){
+ //save current to tmp map
+ pair<long, XMLCh*> p = make_pair(role.uniqueId(), XMLString::replicate(aa));
+ multimap<long, XMLCh*> 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/trunk/src/UdmUtil/UdmUtil.cpp
==============================================================================
--- UDM/trunk/src/UdmUtil/UdmUtil.cpp Tue Oct 16 17:22:39 2012 (r4137)
+++ UDM/trunk/src/UdmUtil/UdmUtil.cpp Thu Dec 6 06:58:22 2012 (r4138)
@@ -280,7 +280,10 @@
}
}
-
+ bool isHelperAssociation(string roleName, bool isAssocClass)
+ {
+ return (!isAssocClass ? roleName.find("_rp_container_rev") != string::npos : roleName.find("_rp_container") != string::npos);
+ }
int reqCopyObjectHierarchy(ObjectImpl* p_srcRoot, ObjectImpl* p_dstRoot, DataNetwork* p_dstBackend, bool & finished, copy_assoc_map &cam)
{
Modified: UDM/trunk/tests/test_refports/RefPortsTest.cpp
==============================================================================
--- UDM/trunk/tests/test_refports/RefPortsTest.cpp Tue Oct 16 17:22:39 2012 (r4137)
+++ UDM/trunk/tests/test_refports/RefPortsTest.cpp Thu Dec 6 06:58:22 2012 (r4138)
@@ -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