[commit] r2713 - in trunk: Doc GME/Mga Tests/GPyUnit

GMESRC Repository Notifications gme-commit at list.isis.vanderbilt.edu
Fri Nov 10 16:01:54 CST 2017


Author: ksmyth
Date: Fri Nov 10 16:01:54 2017
New Revision: 2713

Log:
DetachFromArchetype: fix bug where attribute values from basetype's basetype were lost

Modified:
   trunk/Doc/README_in.txt
   trunk/GME/Mga/MgaComplexOps.cpp
   trunk/Tests/GPyUnit/test_instances.py

Modified: trunk/Doc/README_in.txt
==============================================================================
--- trunk/Doc/README_in.txt	Fri Nov 10 16:01:50 2017	(r2712)
+++ trunk/Doc/README_in.txt	Fri Nov 10 16:01:54 2017	(r2713)
@@ -30,6 +30,7 @@
   - Binary compatibility with 11.12.2
   - Fix crash under GME x64 and high memory usage
   - IMgaProject.ObjectByID fail when there is not object with the supplied ID
+  - DetachFromArchetype: fix bug where attribute values from basetype's basetype were lost
 
 Release Notes of Release 17.10.13
 ----------------------------------

Modified: trunk/GME/Mga/MgaComplexOps.cpp
==============================================================================
--- trunk/GME/Mga/MgaComplexOps.cpp	Fri Nov 10 16:01:50 2017	(r2712)
+++ trunk/GME/Mga/MgaComplexOps.cpp	Fri Nov 10 16:01:54 2017	(r2713)
@@ -2,6 +2,7 @@
 #include "stdafx.h"
 #include "MgaFCO.h"
 #include <map>
+#include <unordered_set>
 #include "MgaComplexOps.h"
 #include "MgaSet.h"
 #include "limits.h"
@@ -1658,6 +1659,7 @@
 	MGACOLL_ITERATE(ICoreAttribute, atts) {
 			attrid_type ai;
 			CComPtr<ICoreMetaAttribute> mattr;
+
 			COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
 			COMTHROW(mattr->get_AttrID(&ai));
 			if(ai < ATTRID_COLLECTION) {
@@ -1744,20 +1746,22 @@
 				switch( ai) {
 					case ATTRID_ATTRPARENT: // copy the unfilled attributes
 					{
+#ifdef _DEBUG
 						unsigned int owned_attrs(0), inherited_attrs(0), l3(0);
 						CComBSTR nm;
 						ObjForCore(nobj)->get_Name( &nm);
+#endif
 
-						std::list<metaref_type> ownedAttrVec;
+						std::unordered_set<metaref_type> setAttrs;
 						{
-							CoreObjs my_attrs = nobj[ai + ATTRID_COLLECTION]; // count first the # of owned attributes
+							CoreObjs my_attrs = nobj[ai + ATTRID_COLLECTION];
 							ITERATE_THROUGH(my_attrs) { 
+#ifdef _DEBUG
 								++owned_attrs;
+#endif
 								metaref_type attr_i = ITER[ATTRID_META];
-								if( std::find( ownedAttrVec.begin(), ownedAttrVec.end(), attr_i) == ownedAttrVec.end())
-									ownedAttrVec.push_back( attr_i);
-								else
-									ASSERT(0); // can an attribute belong to self twice?
+								bool inserted = setAttrs.insert(attr_i).second;
+								ASSERT(inserted); // can an attribute belong to self twice?
 							}
 						}
 						// owned_attrs is the number of owned attributes
@@ -1765,28 +1769,35 @@
 						// the instance or subtype gets an additional attribute (initially had none)
 						// thus in case of detaching, we need to distinguish between owned values
 						// and inherited values (owned preferred)
+						CoreObj baseObject = orig;
+						do {
+							CoreObjs base_attrs = baseObject[ai + ATTRID_COLLECTION]; // copy the base's values selectively
+							ITERATE_THROUGH(base_attrs) {
 
-						{
-							CoreObjs base_attrs = orig[ai + ATTRID_COLLECTION]; // copy the base's values selectively
-							ITERATE_THROUGH(base_attrs) { 
-								bool fnd = std::find( ownedAttrVec.begin(), ownedAttrVec.end(), ITER[ATTRID_META]) != ownedAttrVec.end();
-								if( !fnd)
+								if (setAttrs.insert(ITER[ATTRID_META]).second == true)
 								{
+#ifdef _DEBUG
 									++inherited_attrs;
+#endif
 									CoreObj nchild;
 									ObjTreeCopy(mgaproject, ITER, nchild, crealist);
 									nchild[ai] = nobj;
+									setAttrs.insert(ITER[ATTRID_META]);
 								}
 							}
-						}
-						{
-							CoreObjs mine = nobj[ai + ATTRID_COLLECTION]; // overwrite with mine 
-							ITERATE_THROUGH( mine) { 
-								++l3;
-							}
-						}
 
+							// folders may not be derived
+							ASSERT(baseObject.IsFCO());
+						} while (baseObject = baseObject[ATTRID_DERIVED]);
+
+#ifdef _DEBUG
+						CoreObjs mine = nobj[ai + ATTRID_COLLECTION];
+						ITERATE_THROUGH(mine) {
+							++l3;
+						}
 						ASSERT( owned_attrs + inherited_attrs == l3);
+#endif
+
 						break;
 					}
 					case ATTRID_FCOPARENT: // for all secondary derived fco children-> detach

Modified: trunk/Tests/GPyUnit/test_instances.py
==============================================================================
--- trunk/Tests/GPyUnit/test_instances.py	Fri Nov 10 16:01:50 2017	(r2712)
+++ trunk/Tests/GPyUnit/test_instances.py	Fri Nov 10 16:01:54 2017	(r2713)
@@ -110,6 +110,23 @@
         self.project.CommitTransaction()
 
     @dec_disable_early_binding
+    def test_DetachFromArcheType_Attrs(self):
+        self.project = GPyUnit.util.parse_xme(self.connstr)
+        self.project.BeginTransactionInNewTerr()
+        aspects = self.project.RootFolder.GetObjectByPathDisp("/@Aspects")
+        aspect = self.project.RootFolder.GetObjectByPathDisp("/@Aspects/@Aspect")
+        subtype = self.project.RootFolder.DeriveRootObject(aspects, False)
+        instance = self.project.RootFolder.DeriveRootObject(subtype, True)
+
+        aspect.SetStrAttrByNameDisp("GeneralPreferences", "test123")
+        aspect_instance = instance.GetObjectByPathDisp("/@Aspect")
+        self.assertEquals(aspect.GetStrAttrByNameDisp("GeneralPreferences"), aspect_instance.GetStrAttrByNameDisp("GeneralPreferences"))
+
+        instance.DetachFromArcheType()
+        self.assertEquals(aspect.GetStrAttrByNameDisp("GeneralPreferences"), aspect_instance.GetStrAttrByNameDisp("GeneralPreferences"))
+        self.project.CommitTransaction()
+
+    @dec_disable_early_binding
     def test_RemoveArchetypeConnpoint(self):
         self.project = GPyUnit.util.parse_xme(self.connstr)
         self.project.BeginTransactionInNewTerr()
@@ -190,3 +207,6 @@
         
         self.project.CommitTransaction()
         self.project.Save()
+
+if __name__ == "__main__":
+        unittest.main()


More information about the gme-commit mailing list