[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