[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