GME  13
MgaComplexOps.cpp
Go to the documentation of this file.
00001 // MgaComplexOps.cpp : Implementation of FCO Copy/Move/Derive/Delete operations
00002 #include "stdafx.h"
00003 #include "MgaFCO.h"
00004 #include <map>
00005 #include "MgaComplexOps.h"
00006 #include "MgaSet.h"
00007 #include "limits.h"
00008 #define DETACHED_FROM "_detachedFrom"
00009 
00010 
00011 
00012 
00013 
00014 void SingleObjTreeDelete(CoreObj &self, bool deleteself) {
00015         CComPtr<ICoreAttributes> atts;
00016         COMTHROW(self->get_Attributes(&atts));
00017         MGACOLL_ITERATE(ICoreAttribute, atts) {
00018                 attrid_type ai;
00019                 CComPtr<ICoreMetaAttribute> mattr;
00020                 COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
00021                 COMTHROW(mattr->get_AttrID(&ai));
00022                 if(ai >= ATTRID_COLLECTION) {
00023                         ai -= ATTRID_COLLECTION;
00024                         if(LINKREF_ATTR(ai) && ai != ATTRID_PARENT) {
00025                                 CoreObjs collmembers = self[ai + ATTRID_COLLECTION];
00026                                 ITERATE_THROUGH(collmembers) {
00027                                         SingleObjTreeDelete(ITER);
00028                                 }
00029                         }
00030                 }
00031         } MGACOLL_ITERATE_END;
00032         if(deleteself) COMTHROW(self->Delete());
00033 }
00034 
00035 
00036 void FCO::inDeleteObject() { 
00037                         long status;
00038                         COMTHROW(get_Status(&status));
00039                         metaid_type typ = GetMetaID(self);
00040                         if(status == OBJECT_DELETED)
00041                                 return;  // since collections contain objects, it may happen!!!
00042 // Step 1: delete structure of this object, but not the object itself
00043                         if(typ == DTID_CONNECTION) {
00044                                 ITERATE_THROUGH(self[ATTRID_CONNROLE+ATTRID_COLLECTION]) CoreObjMark(ITER[ATTRID_XREF], OBJEVENT_DISCONNECTED);
00045                         }
00046                         else if(typ == DTID_SET) {
00047                                 ITERATE_THROUGH(self[ATTRID_SETMEMBER+ATTRID_COLLECTION]) CoreObjMark(ITER[ATTRID_XREF], OBJEVENT_SETEXCLUDED);
00048                         }
00049                         else if(typ == DTID_REFERENCE) {
00050                                 CoreObj h = self[ATTRID_REFERENCE]; if(h) CoreObjMark(h, OBJEVENT_REFRELEASED);
00051                         }
00052 
00053                         if(typ != DTID_FOLDER) {
00054                                 CoreObjs children = self[ATTRID_DERIVED + ATTRID_COLLECTION];
00055                                 ITERATE_THROUGH(children) ObjForCore(ITER)->inDeleteObject();
00056                         }
00057 
00058                         SingleObjTreeDelete(self, false);
00059 
00060 // Step 2: delete children, and derivated objects
00061                         if(typ == DTID_MODEL || typ == DTID_FOLDER) {
00062                                 CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00063                                 ITERATE_THROUGH(children) ObjForCore(ITER)->inDeleteObject();
00064                         }
00065 // Step 3: mark or delete objects that are affected
00066                         CoreObj parent;   
00067                         if(typ != DTID_FOLDER) {
00068                                 parent = self[ATTRID_FCOPARENT];
00069 // REFERENCES   set references to empty
00070                                 CoreObj const nil;  // Null COM pointer
00071                                 {
00072                                         CoreObjs referringobjs = self[ATTRID_REFERENCE + ATTRID_COLLECTION];
00073                                         ITERATE_THROUGH(referringobjs) {
00074                                                 if(ITER.IsDeleted()) continue;   // object was deleted during a previous iteration of the same cycle
00075                                                 int todo = MODEMASK(MM_REF, MM_INTO);
00076                                                 if(todo != MM_ERROR && MODEFLAG(MM_REF,MM_FULLDELETE)) {
00077                                                         ObjForCore(ITER)->inDeleteObject();
00078                                                 }
00079                                                 else    {
00080                                                         setcheck(mgaproject, ITER, todo == MM_ERROR ? CHK_ILLEGAL : CHK_CHANGED);
00081                                                         ITER[ATTRID_REFERENCE] = nil;
00082                                                         CoreObjMark(ITER, OBJEVENT_RELATION);
00083                                                 }
00084                                         }
00085                                 }
00086 // OTHER types of xrefs:
00087                                 CoreObjs xrefs = self[ATTRID_XREF + ATTRID_COLLECTION];
00088                                 ITERATE_THROUGH(xrefs) {
00089                                         if(ITER.IsDeleted()) continue; // object was deleted during a previous iteration of the same cycle
00090                                         switch(GetMetaID(ITER)) {
00091                                         case DTID_CONNROLE:
00092 // Connection role
00093                                                 {
00094                                                 CoreObj fco = ITER.GetMgaObj();
00095                                                 int todo = MODEMASK(MM_CONN, MM_INTO);
00096                                                 if(todo != MM_ERROR && MODEFLAG(MM_CONN,MM_FULLDELETE)) {
00097                                                         ObjForCore(fco)->inDeleteObject();
00098                                                 }
00099                                                 else    {
00100                                                         setcheck(mgaproject, fco, todo == MM_ERROR ? CHK_ILLEGAL : CHK_CHANGED);
00101                                                         SingleObjTreeDelete(ITER);
00102                                                         CoreObjMark(fco, OBJEVENT_RELATION);
00103                                                 }
00104                                                 break;
00105                                                 }
00106                                         case DTID_SETNODE:
00107 // Set
00108                                                 {
00109                                                 CoreObj fco = ITER.GetMgaObj();
00110                                                 int todo = MODEMASK(MM_SET, MM_INTO);
00111                                                 if(todo != MM_ERROR && MODEFLAG(MM_SET,MM_FULLDELETE)) {
00112                                                         ObjForCore(fco)->inDeleteObject();
00113                                                 }
00114                                                 else    {
00115                                                         setcheck(mgaproject, fco, todo == MM_ERROR ? CHK_ILLEGAL : CHK_CHANGED);
00116                                                         SingleObjTreeDelete(ITER);
00117                                                         CoreObjMark(fco, OBJEVENT_RELATION);
00118                                                 }
00119                                                 break;
00120                                                 }
00121                                         case DTID_REFATTR:
00122 // REF attribute:  set it to NIL
00123                                                 ITER[ATTRID_XREF] = nil;
00124                                                 CoreObjMark(ITER[ATTRID_ATTRPARENT], OBJEVENT_ATTR);
00125                                                 break;
00126                                         default:        
00127                                                 COMTHROW(E_MGA_META_INCOMPATIBILITY);
00128                                         }
00129                                 }
00130                                 if(typ == DTID_REFERENCE) {
00131                                         CoreObjs segrefs = self[ATTRID_SEGREF + ATTRID_COLLECTION];
00132                                         ITERATE_THROUGH(segrefs) {
00133                                             if(ITER.IsDeleted()) continue; // object was deleted during a previous iteration of the same cycle
00134                                                 CoreObj fco = ITER.GetMgaObj();
00135                                                 int todo = MODEMASK(MM_CONN, MM_INTO);
00136                                                 if(todo != MM_ERROR && MODEFLAG(MM_CONN,MM_FULLDELETE)) {
00137                                                         ObjForCore(fco)->inDeleteObject();
00138                                                 }
00139                                                 else    {
00140                                                         setcheck(mgaproject, fco, todo == MM_ERROR ? CHK_ILLEGAL : CHK_CHANGED);
00141                                                         SingleObjTreeDelete(CoreObj(ITER[ATTRID_CONNSEG]));
00142                                                         CoreObjMark(fco, OBJEVENT_RELATION);
00143                                                 }
00144                                         }
00145                                 }
00146                         } 
00147                         else parent = self[ATTRID_FPARENT];
00148 
00149 //Step4: delete the object itself
00150                         COMTHROW(self->Delete());
00151                         SelfMark(OBJEVENT_DESTROYED);
00152                         CoreObjMark(parent, OBJEVENT_LOSTCHILD);
00153 }
00154 
00155 // PreDelete Notification by Tihamer for the PAMS SynchTool
00156 void FCO::PreDeleteNotify()
00157 {
00158 /*
00159         
00160         long status;
00161         COMTHROW(get_Status(&status));
00162         metaid_type typ = GetMetaID(self);
00163         if(status == OBJECT_DELETED) return;  // since collections contain objects, it may happen!!!
00164 */
00165         metaid_type typ = GetMetaID(self);
00166 
00167         if(typ == DTID_MODEL || typ == DTID_FOLDER) 
00168         {
00169                 CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00170                 ITERATE_THROUGH(children) ObjForCore(ITER)->PreDeleteNotify();
00171         }
00172 
00173         // Notification
00174         PreNotify(OBJEVENT_PRE_DESTROYED, CComVariant());
00175 }
00176 
00177 // Added by lph (Taken from PreDeleteNotify) Notification service for precursory object events
00178 HRESULT FCO::PreNotify(unsigned long changemask, CComVariant param) {
00179         COMTRY {
00180                 CMgaProject::addoncoll::iterator ai, abeg = mgaproject->alladdons.begin(), aend = mgaproject->alladdons.end();
00181                 if(abeg != aend) 
00182                 {
00183                         bool push_terr = mgaproject->activeterr != mgaproject->reserveterr; // this method can be reentrant
00184                         if (push_terr)
00185                                 COMTHROW(mgaproject->pushterr(*mgaproject->reserveterr));
00186                         for(ai = abeg; ai != aend; ) 
00187                         {
00188                                 CComPtr<CMgaAddOn> t = *ai++;   
00189                                 unsigned long mmask;
00190                                 if((mmask = (t->eventmask & changemask)) != 0) {
00191                                         CComPtr<IMgaObject> tt;
00192                                         getinterface(&tt);
00193 
00194                                         if(t->handler->ObjectEvent(tt, mmask, param) != S_OK) {
00195                                                 ASSERT(("Notification failed", false));
00196                                         }
00197                                     t->notified = true;
00198                                 }
00199                         }
00200                         if (push_terr)
00201                                 COMTHROW(mgaproject->popterr());
00202                 }
00203         } COMCATCH(;)
00204 }
00205 
00206 HRESULT FCO::DeleteObject() { 
00207                 COMTRY_IN_TRANSACTION {
00208                         CheckWrite();
00209 
00210                         if(self[ATTRID_PERMISSIONS] & LIBRARY_FLAG) {
00211                                 SetErrorInfo(L"Object is in a library. Library objects cannot be deleted.");
00212                                 COMRETURN_IN_TRANSACTION(E_MGA_OP_REFUSED);
00213                         }
00214                         if(self[ATTRID_PERMISSIONS] & READONLY_FLAG)
00215                         {
00216                                 SetErrorInfo(L"Object is read-only");
00217                                 COMRETURN_IN_TRANSACTION(E_MGA_OP_REFUSED);
00218                         }
00219                         // check for non-primary derived
00220                         if(self[ATTRID_RELID] >= RELIDSPACE) {
00221                                 SetErrorInfo(L"Object is derived.");
00222                                 COMRETURN_IN_TRANSACTION(E_MGA_OP_REFUSED);
00223                         }
00224                         // check for rootfolder
00225                         if(!CoreObj(self[ATTRID_PARENT]).IsContainer()) {  
00226                                 COMTHROW(E_MGA_OP_REFUSED);  
00227                         }
00228 
00229                         PreDeleteNotify();
00230 
00231                         inDeleteObject();
00232 
00233                         docheck(mgaproject);
00234 
00235                 } COMCATCH_IN_TRANSACTION(;);
00236 }
00237 
00238 
00242 
00243 // take second objects from list1, and put them to the first place into list2
00244 void shiftlist(coreobjpairhash &list1, coreobjhash &list2) {
00245                 coreobjpairhash::iterator ii, beg = list1.begin(), end = list1.end();
00246                 for(ii = beg; ii != end; ++ii) list2.insert(coreobjhash::value_type((*ii).second, 0));
00247 }
00248 
00249 
00250 void ObjTreeCollect(CMgaProject *mgaproject, CoreObj &self, coreobjhash &crealist, int code ) {
00251         metaid_type s = s = GetMetaID(self);
00252         if(s >= DTID_MODEL && s <= DTID_SET) {
00253                 crealist.insert(coreobjhash::value_type(self, 0));
00254                 setcheck(mgaproject, self, code);
00255         }
00256         if(s == DTID_MODEL) {
00257                         CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00258                         ITERATE_THROUGH(children) {
00259                                 ObjTreeCollect(mgaproject, ITER, crealist, code);
00260                         }
00261         }
00262 }
00263 
00264 // by ZolMol -invented by
00265 void ObjTreeCollectFoldersToo(CMgaProject *mgaproject, CoreObj &self, coreobjhash &crealist, int code ) {
00266         metaid_type s = s = GetMetaID(self);
00267         if(s >= DTID_MODEL && s <= DTID_FOLDER) {
00268                 crealist.insert(coreobjhash::value_type(self, 0));
00269                 setcheck(mgaproject, self, code);
00270         }
00271         if(s == DTID_MODEL) {
00272                         CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00273                         ITERATE_THROUGH(children) {
00274                                 ObjTreeCollectFoldersToo(mgaproject, ITER, crealist, code);
00275                         }
00276         }
00277         if(s == DTID_FOLDER) {
00278                         CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00279                         ITERATE_THROUGH(children) {
00280                                 ObjTreeCollectFoldersToo(mgaproject, ITER, crealist, code);
00281                         }
00282         }
00283 }
00284 
00285 void ObjTreeCopy(CMgaProject *mgaproject, CoreObj self, CoreObj &nobj, coreobjpairhash &crealist)
00286 {
00287         metaid_type s;
00288         COMTHROW(mgaproject->dataproject->CreateObject(s = GetMetaID(self), &nobj.ComPtr()));
00289         if( s>= DTID_MODEL && s <= DTID_FOLDER)
00290                 assignGuid( mgaproject, nobj);
00291         if(s >= DTID_MODEL && s <= DTID_SET) {
00292                 crealist.insert(coreobjpairhash::value_type(self, nobj));
00293                 setcheck(mgaproject, nobj, CHK_NEW);
00294                 CoreObjMark(nobj, OBJEVENT_CREATED);
00295         }
00296 
00297         CComPtr<ICoreAttributes> atts;
00298         COMTHROW(self->get_Attributes(&atts));
00299         MGACOLL_ITERATE(ICoreAttribute, atts) {
00300                         attrid_type ai;
00301                         CComPtr<ICoreMetaAttribute> mattr;
00302                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
00303                         COMTHROW(mattr->get_AttrID(&ai));
00304                         if (ai == ATTRID_LOCK)
00305                                 continue;
00306                         if(ai < ATTRID_COLLECTION) {
00307                                 // remove library flags from a copy
00308                                 // FIXME this looks wrong
00309                                 if(ai == ATTRID_PERMISSIONS) nobj[ai] = self[ai] & INSTANCE_FLAG;
00310                                 else if( ai == ATTRID_GUID1 // don't copy these
00311                                         || ai == ATTRID_GUID2
00312                                         || ai == ATTRID_GUID3 
00313                                         || ai == ATTRID_GUID4) {}
00314                                 else nobj[ai] = static_cast<CComVariant>(self[ai]);
00315                         }
00316                         else {
00317                                 ai -= ATTRID_COLLECTION;
00318                                 if(LINKREF_ATTR(ai)) {
00319                                         CoreObjs collmembers = self[ai + ATTRID_COLLECTION];
00320                                         ITERATE_THROUGH(collmembers) {
00321                                                 CoreObj nchild;
00322                                                 ObjTreeCopy(mgaproject, ITER, nchild, crealist);
00323                                                 nchild[ai] = nobj;
00324                                         }
00325                                 }
00326                         }
00327 
00328         } MGACOLL_ITERATE_END;
00329 }
00330 
00331 
00332 void ObjTreeCopyFoldersToo(CMgaProject *mgaproject, CoreObj self, CoreObj &nobj, coreobjpairhash &crealist) {
00333         metaid_type s;
00334         COMTHROW(mgaproject->dataproject->CreateObject(s = GetMetaID(self), &nobj.ComPtr()));
00335         if(s >= DTID_MODEL && s <= DTID_FOLDER) {
00336                 assignGuid( mgaproject, nobj);
00337                 crealist.insert(coreobjpairhash::value_type(self, nobj));
00338                 setcheck(mgaproject, nobj, CHK_NEW);
00339                 CoreObjMark(nobj, OBJEVENT_CREATED);
00340         }
00341 
00342         CComPtr<ICoreAttributes> atts;
00343         COMTHROW(self->get_Attributes(&atts));
00344         MGACOLL_ITERATE(ICoreAttribute, atts) {
00345                         attrid_type ai;
00346                         CComPtr<ICoreMetaAttribute> mattr;
00347                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
00348                         COMTHROW(mattr->get_AttrID(&ai));
00349                         if(ai < ATTRID_COLLECTION) {
00350                                 if (ai == ATTRID_LOCK)
00351                                         continue;
00352                                 // remove library flags from a copy
00353                                 // FIXME this looks wrong
00354                                 if(ai == ATTRID_PERMISSIONS) nobj[ai] = self[ai] & INSTANCE_FLAG;
00355                                 else if( ai == ATTRID_GUID1 // don't copy these
00356                                         || ai == ATTRID_GUID2
00357                                         || ai == ATTRID_GUID3 
00358                                         || ai == ATTRID_GUID4) {}
00359                                 else nobj[ai] = static_cast<CComVariant>(self[ai]);
00360                         }
00361                         else {
00362                                 ai -= ATTRID_COLLECTION;
00363                                 if(LINKREF_ATTR(ai)) {
00364                                         CoreObjs collmembers = self[ai + ATTRID_COLLECTION];
00365                                         ITERATE_THROUGH(collmembers) {
00366                                                 CoreObj nchild;
00367                                                 ObjTreeCopyFoldersToo(mgaproject, ITER, nchild, crealist);
00368                                                 nchild[ai] = nobj;
00369                                         }
00370                                 }
00371                         }
00372 
00373         } MGACOLL_ITERATE_END;
00374 }
00375 
00376 // get the derived-chain distance of the closest real basetype (or if there is none, the length of the full base chain) 
00377 // if the object is not derived, or it is a real subtype/instance (i.e derived not because of its parent) 0 is returned
00378 
00379 int GetRealSubtypeDist(CoreObj oldobj) {
00380                         CoreObj pp = oldobj;
00381                         int derdist = 0;
00382                         while(pp[ATTRID_RELID] >= RELIDSPACE) { 
00383                                 pp = pp[ATTRID_DERIVED];
00384                                 ASSERT(pp);
00385                                 derdist++;
00386                         }
00387                         return derdist;
00388 }
00389 
00390 void ObjTreeDist(CoreObj self, int derdist) {
00391         CComPtr<ICoreAttributes> atts;
00392         COMTHROW(self->get_Attributes(&atts));
00393         MGACOLL_ITERATE(ICoreAttribute, atts) {
00394                         attrid_type ai;
00395                         CComPtr<ICoreMetaAttribute> mattr;
00396                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
00397                         COMTHROW(mattr->get_AttrID(&ai));
00398                         if(ai == ATTRID_DERIVED) {
00399                                 CoreObj h = self;
00400                                 for(int i = 0; i < derdist && (h = h[ATTRID_DERIVED]); i++) {
00401                                         MergeRegs(h,self);
00402                                         MergeAttrs(h,self);
00403                                 }
00404                                 CoreObj p;
00405                                 self[ai] = p = self.FollowChain(ai, derdist+1);
00406                                 // FIXME this looks wrong
00407                                 if(p) self[ATTRID_PERMISSIONS] = p[ATTRID_PERMISSIONS] & INSTANCE_FLAG;
00408                                 else self[ATTRID_PERMISSIONS] = 0;
00409                         }
00410                         else if(ai == ATTRID_MASTEROBJ) {
00411                                         self[ai] = self.FollowChain(ai, derdist+1);
00412                         }
00413                         if(ai == ATTRID_FCOPARENT + ATTRID_COLLECTION ||
00414                            ai == ATTRID_CONNROLE + ATTRID_COLLECTION ||
00415                            ai == ATTRID_SETMEMBER + ATTRID_COLLECTION) {
00416                                 CoreObjs collmembers = self[ai];
00417                                 ITERATE_THROUGH(collmembers) {
00418                                                         ObjTreeDist(ITER, derdist);
00419                                 }
00420                         }
00421 
00422         } MGACOLL_ITERATE_END;
00423 }       
00424 
00425 
00427 // ObjTreeDerive
00429 // Create a derived deep copy of 'origobj' to 'newobj'
00430 // -- 'newobj' tree is exact copy of 'origobj' tree, except 
00431 //                      ATTRID_INSTANCE: set if instance, copied from 'origobj' tree othervise
00432 //                      ATTRID_DERIVED & ATTRID_MASTEROBJ: point to the corresponding object in 'origobj' tree
00433 //                      ATTRID_GUID1..4, which are assigned new value
00434 // -- on return the new root object 'newobj' will also be contained in the container of 'origobj'.
00435 // -- new FCO-s are inserted in 'crealist'
00437 // !!! RECURSIVE 
00439 void ObjTreeDerive(CMgaProject *mgaproject, const CoreObj &origobj, CoreObj &newobj, coreobjpairhash &crealist, long instance) {
00440         metaid_type s;
00441         COMTHROW(mgaproject->dataproject->CreateObject(s = origobj.GetMetaID(), &newobj.ComPtr()));
00442         if( s >= DTID_MODEL && s <= DTID_FOLDER)
00443                 assignGuid( mgaproject, newobj); // assigns new value to ATTRID_GUID1..4
00444         if(s >= DTID_MODEL && s <= DTID_SET) {
00445                 crealist.insert(coreobjpairhash::value_type(origobj, newobj));
00446                 setcheck(mgaproject, newobj, CHK_NEW);
00447                 CoreObjMark(newobj, OBJEVENT_CREATED);
00448         }
00449         
00450         CComPtr<ICoreAttributes> atts;
00451         COMTHROW(origobj->get_Attributes(&atts));
00452         MGACOLL_ITERATE(ICoreAttribute, atts) {
00453                         attrid_type ai;
00454                         CComPtr<ICoreMetaAttribute> mattr;
00455                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
00456                         COMTHROW(mattr->get_AttrID(&ai));
00457                         if(ai < ATTRID_COLLECTION) {
00458                                 switch(ai) {
00459                                 case ATTRID_DERIVED: 
00460                                 case ATTRID_MASTEROBJ:
00461                                         newobj[ai] = origobj;
00462                                         break;
00463                                 case ATTRID_PERMISSIONS:
00464                                                 // overwrite copy only if instance
00465                                         // PETER'S FIX 
00466                                         // newobj[ai] = (origobj[ai] | long(instance)) & INSTANCE_FLAG;
00467                                         newobj[ai] = (origobj[ai] | long(instance)) & INSTANCE_FLAG;
00468                                         // PETER END
00469                                         break;
00470                                 case ATTRID_RELID: 
00471                                         {
00472                                         // if newobj[ai] + RELIDSPACE > LONG_MAX
00473                                         if (newobj[ai] > LONG_MAX - RELIDSPACE) 
00474                                                 COMTHROW(E_MGA_LONG_DERIVCHAIN);
00475                                         long relid = origobj[ai]+RELIDSPACE;
00476                                         ASSERT(relid > 0);
00477                                         newobj[ai] = relid;
00478                                         }
00479                                         break;
00480                                 case ATTRID_LASTRELID: 
00481                                         newobj[ai] = 0L;
00482                                         break;
00483                                 case ATTRID_REGNODE:
00484                                 case ATTRID_GUID1: // don't copy these
00485                                 case ATTRID_GUID2:
00486                                 case ATTRID_GUID3:
00487                                 case ATTRID_GUID4:
00488                                 case ATTRID_LOCK: break;
00489                                 default:
00490                                         newobj[ai] = static_cast<CComVariant>(origobj[ai]);
00491                                 }
00492                         }
00493                         else {
00494                                 ai -= ATTRID_COLLECTION;
00495                                 if(LINKREF_ATTR(ai) && ai != ATTRID_ATTRPARENT) {
00496                                         CoreObjs collmembers = origobj[ai + ATTRID_COLLECTION];
00497                                         ITERATE_THROUGH(collmembers) {
00498                                                 CoreObj nchild;
00499                                                 ObjTreeDerive(mgaproject, ITER, nchild, crealist, instance);
00500                                                 nchild[ai] = newobj;
00501                                         }
00502                                         if(ai == ATTRID_FCOPARENT && collmembers.Count() > 0) {
00503                                                         CoreObjMark(newobj, OBJEVENT_NEWCHILD);
00504                                         }
00505                                 }
00506                         }
00507 
00508         } MGACOLL_ITERATE_END;
00509 }
00510 
00511 
00512 
00514 // ObjTreeReconnect
00516 // Reconnects relations in a newly copied/derived tree
00517 // 
00518 // -- 'crealist'contains old-new equivalent pairs for quick access
00519 // -- if object is not in crealist, it may still be reconnected 
00520 //              if it is an internal reference, (i.e., the ends of the pointer belong to the same rootFCO).
00521 //        -- if the relation has a masterobj, then the relation of the root masterobj is checked
00522 //        -- otherwise the target of the ralation must be contained in the crealist (list of newly created objects)
00523 // -- return value used internally to indicate that the tree contained relations which were not reconnected
00525 // !!! RECURSIVE 
00527 bool ObjTreeReconnect(CoreObj self, coreobjpairhash &crealist, CoreObj const &derivtgt) {
00528         typedef struct { metaid_type mid; int search, reconnect; } table;
00529         static const table tab[] = {
00530                 {DTID_MODEL,    ATTRID_FCOPARENT,       0},
00531                 {DTID_REFERENCE, 0,                                     ATTRID_REFERENCE},
00532                 {DTID_SET,              ATTRID_SETMEMBER,       0},
00533                 {DTID_SETNODE,  0,                                      ATTRID_XREF },
00534                 {DTID_CONNECTION, ATTRID_CONNROLE,      0},
00535                 {DTID_CONNROLE, ATTRID_CONNSEG,         ATTRID_XREF},
00536                 {DTID_CONNROLESEG, 0,                           ATTRID_SEGREF}
00537         };
00538 
00539 
00540         bool containedexternal = false;
00541         metaid_type n = GetMetaID(self);
00542 
00543         for(int i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
00544                 if(tab[i].mid == n) {
00545                         const table *ll = &tab[i];
00546                         if(ll->search) {
00547                                 CoreObjs children = self[ll->search+ATTRID_COLLECTION];
00548                                 if(n == DTID_CONNROLE) {
00549                                         children.Sort();
00550                                 }
00551                                 ITERATE_THROUGH(children) {
00552                                         if(ObjTreeReconnect(ITER,crealist, derivtgt)) {
00553                                                 containedexternal = true;
00554                                                 if(n == DTID_CONNROLE) break; // stop processing rolesegments after an ext ref.
00555                                         }
00556                                 }
00557                         }
00558                         if(!containedexternal && ll->reconnect) {
00559                           // the relationship pointer will to be reconnected if
00560                                 // - the object has no master (only possible with copied objects)
00561                                 // - or the relation in the most original base is internal
00562                           if(!self.GetMaster() || IsInternalRelation(self)) {  
00563                                     CoreObj oldr = self[ll->reconnect];
00564                                         coreobjpairhash::iterator i = crealist.find(oldr);
00565                                         if(i != crealist.end()) {  
00566 // if it is a reference to a newly created object: use lookup
00567                                                 self[ll->reconnect] = (*i).second;
00568                                         }
00569                                         else if(derivtgt) {  
00570                                                 ASSERT(CoreObj(derivtgt[ATTRID_DERIVED]));
00571                                                 ASSERT(derivtgt[ATTRID_RELID] < RELIDSPACE);
00572                                                 CoreObj newr;
00573                                                 GetDerivedEquivalent(oldr, derivtgt, newr);
00574                                                 self[ll->reconnect] = newr;
00575                                         }
00576                                         else if( n == DTID_SETNODE) // if setnode not found while copying a set, 
00577                                         {   // delete the membership entry, thus allow a set to be copied without its members
00578                                                 // previously Sets could not be copied&pasted only along with their members
00579                                                 removemember().DoWithDeriveds(self);
00580                                         }
00581                           }
00582                           else containedexternal = true;
00583                         }
00584                         break;
00585                 }
00586         }
00587         return containedexternal;
00588 }
00589 
00590 bool ObjTreeReconnectFoldersToo(CoreObj self, coreobjpairhash &crealist, CoreObj const &derivtgt) {
00591         typedef struct { metaid_type mid; int search, reconnect; } table;
00592         static const table tab[] = {
00593                 {DTID_FOLDER,   ATTRID_FCOPARENT,       0},
00594                 {DTID_MODEL,    ATTRID_FCOPARENT,       0},
00595                 {DTID_REFERENCE, 0,                                     ATTRID_REFERENCE},
00596                 {DTID_SET,              ATTRID_SETMEMBER,       0},
00597                 {DTID_SETNODE,  0,                                      ATTRID_XREF },
00598                 {DTID_CONNECTION, ATTRID_CONNROLE,      0},
00599                 {DTID_CONNROLE, ATTRID_CONNSEG,         ATTRID_XREF},
00600                 {DTID_CONNROLESEG, 0,                           ATTRID_SEGREF}
00601         };
00602 
00603 
00604         bool containedexternal = false;
00605         metaid_type n = GetMetaID(self);
00606 
00607         for(int i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
00608                 if(tab[i].mid == n) {
00609                         const table *ll = &tab[i];
00610                         if(ll->search) {
00611                                 CoreObjs children = self[ll->search+ATTRID_COLLECTION];
00612                                 if(n == DTID_CONNROLE) {
00613                                         children.Sort();
00614                                 }
00615                                 ITERATE_THROUGH(children) {
00616                                         if (GetMetaID(ITER) == DTID_FOLDER) {
00617                                                 if(ObjTreeReconnectFoldersToo(ITER, crealist, derivtgt)) {
00618                                                         containedexternal = true;
00619                                                 }
00620                                         } else {
00621                                                 if(ObjTreeReconnect(ITER, crealist, derivtgt)) {
00622                                                         containedexternal = true;
00623                                                         if(n == DTID_CONNROLE) break; // stop processing rolesegments after an ext ref.
00624                                                 }
00625                                         }
00626                                 }
00627                         }
00628                         if(!containedexternal && ll->reconnect) {
00629                           // the relationship pointer will to be reconnected if
00630                                 // - the object has no master (only possible with copied objects)
00631                                 // - or the relation in the most original base is internal
00632                           if(!self.GetMaster() || IsInternalRelation(self)) {  
00633                                     CoreObj oldr = self[ll->reconnect];
00634                                         coreobjpairhash::iterator i = crealist.find(oldr);
00635                                         if(i != crealist.end()) {  
00636 // if it is a reference to a newly created object: use lookup
00637                                                 self[ll->reconnect] = (*i).second;
00638                                         }
00639                                         else if(derivtgt) {  
00640                                                 ASSERT(CoreObj(derivtgt[ATTRID_DERIVED]));
00641                                                 ASSERT(derivtgt[ATTRID_RELID] < RELIDSPACE);
00642                                                 CoreObj newr;
00643                                                 GetDerivedEquivalent(oldr, derivtgt, newr);
00644                                                 self[ll->reconnect] = newr;
00645                                         }
00646                           }
00647                           else containedexternal = true;
00648                         }
00649                         break;
00650                 }
00651         }
00652         return containedexternal;
00653 }
00654 
00655 
00656 
00658 // ObjTreeCheckRelations
00660 // Removes outgoing/internal relations (or whole objects) in a newly copied/derived/moved tree
00661 // The policy is based on the project-wide operationsmask queried with MM_OUTOF or MM_INTERNAL masks
00662 // 
00663 // -- 'self' is the root of the tree, 
00664 // -- 'internals' are all the objects that are considered internal for this operation
00665 // -- all relations hold by references, sets and connections are checked
00666 // -- if the required operation is
00667 //      - MM_ERROR: error is signaled
00668 //  - MM_CLEAR: the corresponding pointer is cleared
00669 //  - MM_CLEAR & MM_FULLDELETE: the object itself is cleared
00670 //  - MM_DO:    nothing happens 
00672 // !!! RECURSIVE 
00674 void ObjTreeCheckRelations(CMgaProject *mgaproject, CoreObj &self, coreobjhash &internals) {
00675         typedef struct { metaid_type mid; int search, check, mm; } table;
00676         static const table tab[] = {
00677                 {DTID_MODEL, ATTRID_FCOPARENT, 0},
00678                 {DTID_REFERENCE, 0, ATTRID_REFERENCE, MM_REF},
00679                 {DTID_SET, ATTRID_SETMEMBER, 0},
00680                 {DTID_SETNODE, 0, ATTRID_XREF, MM_SET },
00681                 {DTID_CONNECTION, ATTRID_CONNROLE, 0},
00682                 {DTID_CONNROLE, ATTRID_CONNSEG, ATTRID_XREF, MM_CONN},
00683                 {DTID_CONNROLESEG, 0, ATTRID_SEGREF}
00684         };
00685 
00686         metaid_type n = GetMetaID(self);
00687 
00688         for(int i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
00689                 if(tab[i].mid == n) {
00690                         const table *ll = &tab[i];
00691                         if(ll->search) {
00692                                 CoreObjs children = self[ll->search+ATTRID_COLLECTION];
00693                                 ITERATE_THROUGH(children) {
00694                                         if(ITER.IsDeleted()) continue;
00695                                         ObjTreeCheckRelations(mgaproject, ITER, internals);
00696                                 }
00697                         }
00698                         if(ll->check && !self.IsDeleted()) {
00699                                 CoreObj tgt = self[ll->check];
00700                                 int mm2 = (internals.find(tgt) != internals.end()) ? MM_INTERNAL : MM_OUTOF;
00701                                 switch(MODEMASK(ll->mm, mm2)) {
00702                                 case MM_ERROR: COMTHROW(E_MGA_OP_REFUSED);
00703                                 case MM_CLEAR: 
00704                                         self[ll->check] = NULLCOREOBJ;
00705                                         CoreObj selfobj = self.GetMgaObj();
00706                                         if( (GetMetaID(selfobj) == DTID_CONNECTION && ObjForCore(selfobj)->simpleconn()) ||
00707                                                 MODEFLAG(ll->mm, MM_FULLDELETE)) {
00708                                                         ObjForCore(selfobj)->inDeleteObject();
00709                                         }
00710                                         else {
00711                                                 if(n != DTID_REFERENCE) {
00712                                                         if(n == DTID_CONNROLESEG) self = self[ATTRID_CONNSEG];
00713                                                         SingleObjTreeDelete(self);
00714                                                 }
00715                                         }
00716                                 }
00717                         }
00718                         break;
00719                 }
00720         }
00721 }
00722 
00723 void ObjTreeCheckRelationsFoldersToo(CMgaProject *mgaproject, CoreObj &self, coreobjhash &internals) {
00724         typedef struct { metaid_type mid; int search, check, mm; } table;
00725         static const table tab[] = {
00726                 {DTID_FOLDER, ATTRID_FCOPARENT, 0},
00727                 {DTID_MODEL, ATTRID_FCOPARENT, 0},
00728                 {DTID_REFERENCE, 0, ATTRID_REFERENCE, MM_REF},
00729                 {DTID_SET, ATTRID_SETMEMBER, 0},
00730                 {DTID_SETNODE, 0, ATTRID_XREF, MM_SET },
00731                 {DTID_CONNECTION, ATTRID_CONNROLE, 0},
00732                 {DTID_CONNROLE, ATTRID_CONNSEG, ATTRID_XREF, MM_CONN},
00733                 {DTID_CONNROLESEG, 0, ATTRID_SEGREF}
00734         };
00735 
00736         metaid_type n = GetMetaID(self);
00737 
00738         for(int i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
00739                 if(tab[i].mid == n) {
00740                         const table *ll = &tab[i];
00741                         if(ll->search) {
00742                                 CoreObjs children = self[ll->search+ATTRID_COLLECTION];
00743                                 ITERATE_THROUGH(children) {
00744                                         if(ITER.IsDeleted()) continue;
00745                                         ObjTreeCheckRelationsFoldersToo(mgaproject, ITER, internals);
00746                                 }
00747                         }
00748                         if(ll->check && !self.IsDeleted()) {
00749                                 CoreObj tgt = self[ll->check];
00750                                 int mm2 = (internals.find(tgt) != internals.end()) ? MM_INTERNAL : MM_OUTOF;
00751                                 switch(MODEMASK(ll->mm, mm2)) {
00752                                 case MM_ERROR: COMTHROW(E_MGA_OP_REFUSED);
00753                                 case MM_CLEAR: 
00754                                         self[ll->check] = NULLCOREOBJ;
00755                                         CoreObj selfobj = self.GetMgaObj();
00756                                         if( (GetMetaID(selfobj) == DTID_CONNECTION && ObjForCore(selfobj)->simpleconn()) ||
00757                                                 MODEFLAG(ll->mm, MM_FULLDELETE)) {
00758                                                         ObjForCore(selfobj)->inDeleteObject();
00759                                         }
00760                                         else {
00761                                                 if(n != DTID_REFERENCE) {
00762                                                         if(n == DTID_CONNROLESEG) self = self[ATTRID_CONNSEG];
00763                                                         SingleObjTreeDelete(self);
00764                                                 }
00765                                         }
00766                                 }
00767                         }
00768                         break;
00769                 }
00770         }
00771 }
00772 
00774 // ObjTreeCheckINTORelations
00776 // Removes incoming relations (or whole objects) that point into a newly copied/derived/moved tree
00777 // The policy is based on the project-wide operationsmask queried with MM_INTO mask
00778 // 
00779 // -- 'self' is the root of the tree, 
00780 // -- 'internals' are all the objects that are considered internal for this operation
00781 // -- all relations that point to objects in the tree are checked.
00782 // -- if the required operation is
00783 //      - MM_ERROR: error is signaled
00784 //  - MM_CLEAR: the corresponding pointer is cleared
00785 //  - MM_CLEAR & MM_FULLDELETE: the object itself is cleared
00786 //  - MM_DO:    nothing happens 
00787 void ObjCheckINTORelations(CMgaProject* mgaproject, CoreObj& self, coreobjhash& internals) {
00788         metaid_type n = GetMetaID(self);
00789         ASSERT(n >= DTID_MODEL && n <= DTID_SET);
00790         if (n == DTID_REFERENCE) {
00791                 // GME-311: need to delete connections into refport 'conn_seg' iff 
00792                 //   connection 'rel_owner' is not in internals and 'conn_seg' is the actual connection end (not an intermediary)
00793                 CoreObjs conn_segs = self[ATTRID_SEGREF + ATTRID_COLLECTION];
00794                 ITERATE_THROUGH(conn_segs) {
00795                         CoreObj conn_seg = ITER;
00796                         metaid_type st = GetMetaID(conn_seg);
00797                         ASSERT(st == DTID_CONNROLESEG);
00798                         if (st != DTID_CONNROLESEG) {
00799                                 continue;
00800                         }
00801                         CoreObj rel_owner = conn_seg.GetMgaObj();
00802                         if (!rel_owner) {
00803                                 continue;       // connection might be deleted due to a previous relation
00804                         }
00805                         ASSERT(GetMetaID(rel_owner) == DTID_CONNECTION);
00806                         #ifdef _DEBUG
00807                         CoreObj role = conn_seg[ATTRID_CONNSEG];
00808                         CComBSTR conn_name = rel_owner[ATTRID_NAME], role_name = role[ATTRID_NAME];
00809                         #endif
00810                         ASSERT(ObjForCore(rel_owner)->simpleconn()); // KMS: don't think we can get here without a simpleconn
00811                         if (internals.find(rel_owner) == internals.end() && ObjForCore(rel_owner)->simpleconn()) {
00812                                 setcheck(mgaproject, rel_owner, CHK_CHANGED);
00813                                 switch(MODEMASK(MM_CONN, MM_INTO)) {
00814                                 case MM_ERROR: COMTHROW(E_MGA_OP_REFUSED);
00815                                         break;
00816                                 case MM_CLEAR:
00817                                         if (conn_seg[ATTRID_SEGORDNUM] == 1) {
00818                                                 ObjForCore(rel_owner)->inDeleteObject();
00819                                                 break;
00820                                         }
00821                                 }
00822                         }
00823                 }
00824         }
00825 
00826         CoreObjs xrefs = self[ATTRID_XREF + ATTRID_COLLECTION]; 
00827         ITERATE_THROUGH(xrefs) {
00828                 metaid_type st = GetMetaID(ITER);
00829                 if(st != DTID_SETNODE && st != DTID_CONNROLE) {
00830                         continue;
00831                 }
00832                 CoreObj rel_owner = ITER.GetMgaObj();
00833                 if (!rel_owner) {
00834                         continue;       // connection/set might be deleted due to a previous relation
00835                 }
00836 
00837                 if(internals.find(rel_owner) == internals.end()) {
00838                         int ttt = st == DTID_CONNROLE ? MM_CONN : MM_SET;
00839                         setcheck(mgaproject, rel_owner, CHK_CHANGED);
00840                         switch(MODEMASK(ttt, MM_INTO)) {
00841                         case MM_ERROR: COMTHROW(E_MGA_OP_REFUSED);
00842                                 break;
00843                         case MM_CLEAR: 
00844                                 if (st == DTID_CONNROLE && ObjForCore(rel_owner)->simpleconn()) {
00845                                         // GME-297: don't delete connections connecting to refports
00846                                         // (outside connections to inside refports are deleted above)
00847                                         long count = 0;
00848                                         CoreObjs refport_refs = ITER[ATTRID_CONNSEG+ATTRID_COLLECTION]; // i.e. refport containers
00849                                         COMTHROW(refport_refs->get_Count(&count));
00850                                         if (count == 0) {
00851                                                 // this connection role is connected directly; it is not connected to a refport
00852                                                 ObjForCore(rel_owner)->inDeleteObject();
00853                                         }
00854                                 } else if (MODEFLAG(ttt, MM_FULLDELETE)) {
00855                                         ObjForCore(rel_owner)->inDeleteObject();
00856                                 } 
00857                                 else {
00858                                         CoreObjMark(self, st == DTID_CONNROLE ? OBJEVENT_DISCONNECTED : OBJEVENT_SETEXCLUDED);
00859                                         CoreObjMark(rel_owner, OBJEVENT_RELATION);
00860                                         SingleObjTreeDelete(ITER);
00861                                 }
00862                                 break;
00863                         }
00864                 }       
00865         }
00866         {
00867         CoreObjs refs = self[ATTRID_REFERENCE + ATTRID_COLLECTION]; 
00868         ITERATE_THROUGH(refs) {
00869                 CoreObj rel_owner = ITER;
00870                 if(internals.find(rel_owner) == internals.end()) {
00871                         setcheck(mgaproject, rel_owner, CHK_CHANGED);
00872                         switch(MODEMASK(MM_REF, MM_INTO)) {
00873                         case MM_ERROR: COMTHROW(E_MGA_OP_REFUSED);
00874                         case MM_CLEAR: 
00875                                 if(MODEFLAG(MM_REF, MM_FULLDELETE)) {
00876                                         ObjForCore(rel_owner)->inDeleteObject();
00877                                 }
00878                                 else { 
00879                                         rel_owner[ATTRID_REFERENCE] = NULLCOREOBJ;
00880                                         CoreObjMark(self, OBJEVENT_REFRELEASED);
00881                                         CoreObjMark(rel_owner, OBJEVENT_RELATION);
00882                                 }
00883                         }
00884                 }
00885         }
00886         }
00887 }
00888 
00889 
00891 // !!! RECURSIVE 
00893 void ObjTreeCheckINTORelations(CMgaProject *mgaproject, CoreObj &self, coreobjhash &internals) {
00894         metaid_type n = GetMetaID(self);
00895         ASSERT(n >= DTID_MODEL && n <= DTID_SET);
00896         ObjCheckINTORelations(mgaproject, self, internals);
00897         
00898         if(n == DTID_MODEL) {
00899                 CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00900                 ITERATE_THROUGH(children) {
00901                         ObjTreeCheckINTORelations(mgaproject, ITER, internals);
00902                 }
00903         }
00904 }
00905 
00906 
00908 // !!! RECURSIVE 
00910 void ObjTreeCheckINTORelationsFoldersToo(CMgaProject *mgaproject, CoreObj &self, coreobjhash &internals) {
00911         metaid_type n = GetMetaID(self);
00912         ASSERT(n >= DTID_MODEL && n <= DTID_FOLDER);
00913         if ( n >= DTID_MODEL && n <= DTID_SET)
00914         {
00915                 ObjCheckINTORelations(mgaproject, self, internals);
00916         }
00917         if(n == DTID_MODEL || n == DTID_FOLDER) {
00918                 CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00919                 ITERATE_THROUGH(children) {
00920                         ObjTreeCheckINTORelationsFoldersToo(mgaproject, ITER, internals);
00921                 }
00922         }
00923 }
00924 
00925 void ObjTreeNotify(CMgaProject *mgaproject, CoreObj &self) {
00926         int k = OBJEVENT_CREATED;
00927         metaid_type typ = GetMetaID(self);
00928         if(typ == DTID_FOLDER || typ == DTID_MODEL) {
00929                         CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00930                         ITERATE_THROUGH(children) {
00931                                 k |= OBJEVENT_NEWCHILD;
00932                                 ObjTreeNotify(mgaproject, ITER);
00933                         }
00934         }
00935         else if(typ == DTID_REFERENCE) {
00936                         CoreObj rr = self[ATTRID_REFERENCE];
00937                         if(rr) { 
00938                                 CComPtr<IMgaFCO> fco;
00939                                 ObjForCore(rr)->getinterface(&fco);
00940                                 mgaproject->ObjMark(fco, OBJEVENT_REFERENCED);
00941                         }
00942         }
00943         else if(typ == DTID_CONNECTION || typ == DTID_SET) {
00944                         
00945                         CoreObjs rrs;
00946                         long msg;
00947                         if(typ == DTID_SET) {
00948                                 rrs = self[ATTRID_SETMEMBER+ATTRID_COLLECTION];
00949                                 msg = OBJEVENT_SETINCLUDED;
00950                         }
00951                         else {
00952                                 rrs = self[ATTRID_CONNROLE+ATTRID_COLLECTION];
00953                                 msg = OBJEVENT_CONNECTED;
00954                         }
00955                         ITERATE_THROUGH(rrs) { 
00956                                 CoreObj fff = ITER[ATTRID_XREF];
00957                                 if(fff) {
00958                                         CComPtr<IMgaFCO> fco;
00959                                         ObjForCore(fff)->getinterface(&fco);
00960                                         mgaproject->ObjMark(fco, msg);
00961                                 }
00962                         }
00963         }
00964         ObjForCore(self)->SelfMark(k);
00965 }
00966 
00967 // check of obj or any of its children is derived from root
00968 void CheckConflict(CoreObj &b, CoreObj &root) {
00969 
00970         if(GetMetaID(b) == DTID_MODEL) {
00971                 CoreObj base = b[ATTRID_DERIVED];
00972                 while(base) {
00973                         if(COM_EQUAL(base, root)) COMTHROW(E_MGA_OP_REFUSED);
00974                         base = base[ATTRID_DERIVED];
00975                 }
00976                 CoreObjs children = b[ATTRID_FCOPARENT + ATTRID_COLLECTION];
00977                 ITERATE_THROUGH(children) {
00978                         CheckConflict(ITER, root);
00979                 }
00980         }               
00981 }
00982 
00983 
00985 // DeriveNewObjs
00988 // !!! RECURSIVE 
00990 void ReDeriveNewObjs(CMgaProject *mgaproject, std::vector<CoreObj> &orignobjs, int cnt, int targetlevel) {
00991         ASSERT(targetlevel >= 1);
00992         if(cnt < 1) return;
00993         CoreObj orig = orignobjs[0][ATTRID_PARENT];
00994         if(!orig.IsFCO()) return;
00995         CoreObjs deriveds = orig[ATTRID_DERIVED+ATTRID_COLLECTION];
00996         ITERATE_THROUGH(deriveds) {
00997                 int i;
00998                 // we look for the object (subtypebase) which has been derived primarily (a parent of ITER most probably)
00999                 // subtypebase will be used when internal references need to be redirected [ObjTreeReconnect call]
01000                 // an internal reference is:
01001                 //  - part of a model which is derived
01002                 //  - its target is also part of that model
01003                 // when such a reference is found in a derived model it is redirected to 
01004                 // the target's derived counterpart. more details: GetDerivedEquivalent() [in MgaDeriveOps.cpp]
01005                 // WAS: CoreObj subtypebase = ITER.FollowChain(ATTRID_PARENT, targetlevel); 
01006                 CoreObj subtypebase = ITER.FollowChain(ATTRID_PARENT, targetlevel-1);
01007                 coreobjpairhash derivcrealist;
01008                 coreobjhash derivmovedlist;
01009                 long instance = ITER[ATTRID_PERMISSIONS] & INSTANCE_FLAG;
01010                 std::vector<CoreObj> newderiveds(cnt);
01011                 for(i = 0; i< cnt; i++) {
01012                         ObjTreeDerive(mgaproject, orignobjs[i], newderiveds[i], derivcrealist, instance);
01013                         newderiveds[i][ATTRID_FCOPARENT]=ITER;
01014                 }
01015                 if(cnt) CoreObjMark(ITER, OBJEVENT_NEWCHILD);
01016 // Reroute references
01017                 for(i = 0; i< cnt; i++) {
01018                         ObjTreeReconnect(newderiveds[i], derivcrealist, subtypebase);
01019                 }
01020                 shiftlist(derivcrealist, derivmovedlist);
01021                 for(i = 0; i< cnt; i++) {
01022                         ObjTreeCheckRelations(mgaproject, newderiveds[i], derivmovedlist);                      
01023                 }
01024                 ReDeriveNewObjs(mgaproject, newderiveds, cnt, targetlevel);
01025         }
01026 }
01027 
01028 
01029 void ReDeriveNewObj(CMgaProject *mgaproject, CoreObj &orignobj, int targetlevel) {
01030    std::vector<CoreObj> vv(1);
01031    vv[0] = orignobj;
01032    ReDeriveNewObjs(mgaproject, vv, 1, targetlevel);
01033 }
01034 
01035 
01036 
01040 
01041 
01042 HRESULT FCO::CopyFCOs(IMgaFCOs *copylist, IMgaMetaRoles *rlist,IMgaFCOs **objs) {
01043         COMTRY_IN_TRANSACTION_MAYBE {
01044                 CheckWrite();
01045                 CHECK_MYINPTRSPAR(copylist);
01046                 long cnt;
01047                 COMTHROW(copylist->get_Count(&cnt));
01048                 if(rlist) {
01049                         long rlcnt;
01050                         COMTHROW(rlist->get_Count(&rlcnt));
01051                         if(rlcnt != cnt) COMTHROW(E_MGA_BAD_COLLENGTH);
01052                 }
01053                 metaid_type targettype = GetMetaID(self);
01054                 int targetlevel = 0;
01055                 CoreObj rootp;
01056 // Pre check:
01057                 if(targettype == DTID_MODEL) {
01058                         if(self[ATTRID_PERMISSIONS] & ~EXEMPT_FLAG) COMTHROW(E_MGA_NOT_CHANGEABLE);
01059                         GetRootOfDeriv(self, rootp, &targetlevel);
01060                         if(rootp) {
01061                                 MGACOLL_ITERATE(IMgaFCO, copylist) {
01062                                         CheckConflict(CoreObj(MGACOLL_ITER), rootp);
01063                                 } MGACOLL_ITERATE_END;
01064                         }
01065                 }
01066 
01067 // Copy trees
01068                 coreobjpairhash crealist;
01069                 int i = 0;
01070 
01071                 std::vector<CoreObj> nobjs(cnt);
01072                 MGACOLL_ITERATE(IMgaFCO, copylist) {
01073                         long relId;
01074                         COMTHROW(MGACOLL_ITER->get_RelID(&relId)); // GME-335:essentially CheckRead
01075                         CoreObj oldobj = CoreObj(MGACOLL_ITER);
01076                         ObjForCore(oldobj)->SelfMark(OBJEVENT_COPIED);
01077                         int derdist = GetRealSubtypeDist(oldobj);
01078                         ObjTreeCopy(mgaproject, oldobj, nobjs[i], crealist);  // copy
01079                         if(derdist) ObjTreeDist(nobjs[i], derdist);
01080                         // assigns a new relid to nobjs[i]
01081                         assignnewchild(nobjs[i]);
01082                         // derdist is >0 for previously secondary derived objects so if such an object
01083                         // was copied (and detached above by ObjTreeDist) then some of its children
01084                         // have become archetypes now, but their relid still reflects the secondary 
01085                         // derived status
01086                         //
01087                         // we must assign a new relid for the children of nobjs[i]
01088                         if(derdist) newrelidforchildren(nobjs[i]);
01089                         metaref_type trole = METAREF_NULL;
01090                         if(targettype != DTID_FOLDER) {
01091                                 ASSERT(targettype == DTID_MODEL);
01092                                 CComPtr<IMgaMetaRole> r;
01093                                 if(rlist) COMTHROW(rlist->get_Item(i+1, &r));
01094                                 CComPtr<IMgaMetaFCO> mf; 
01095                                 COMTHROW(get_Meta(&mf));
01096                                 if(!r) {   // NO metarole given, inherit that of original object
01097                                         CComQIPtr<IMgaMetaModel> parentmeta = mf;
01098                                         if(!parentmeta) COMTHROW(E_MGA_META_INCOMPATIBILITY);
01099                                         metaref_type t;
01100                                         t = (nobjs[i])[ATTRID_ROLEMETA];
01101                                         if(!t) COMTHROW(E_MGA_NO_ROLE);
01102                                         CComQIPtr<IMgaMetaRole> metar = mgaproject->FindMetaRef(t);
01103                                         if(!metar) COMTHROW(E_MGA_META_INCOMPATIBILITY);
01104                                         CComBSTR rolename;
01105                                         COMTHROW(metar->get_Name(&rolename));
01106                                         COMTHROW(parentmeta->get_RoleByName(rolename, &r));
01107                                         if(!r) COMTHROW(E_MGA_NO_ROLE);
01108                                 }
01109                                 {
01110                                         metaref_type kt;
01111                                         CComPtr<IMgaMetaFCO> mfco;
01112                                         COMTHROW(r->get_Kind(&mfco));
01113                                         COMTHROW(mfco->get_MetaRef(&kt));
01114                                         if(kt != (nobjs[i])[ATTRID_META])
01115                                                 COMTHROW(E_MGA_NO_ROLE);
01116                                         CComPtr<IMgaMetaModel> mmodel;
01117                                         COMTHROW(r->get_ParentModel(&mmodel));
01118                                         if (!mf.IsEqualObject(mmodel))
01119                                                 COMTHROW(E_MGA_INVALID_ROLE);
01120                                 }
01121 
01122                                 COMTHROW(r->get_MetaRef(&trole));
01123                                 if(trole == METAREF_NULL)  COMTHROW(E_MGA_INVALID_ROLE);
01124                         }
01125                         (nobjs[i])[ATTRID_ROLEMETA] = trole;
01126                         i++;
01127                 } MGACOLL_ITERATE_END;
01128 
01129 // Reroute references
01130                 for(i = 0; i< cnt; i++) {
01131                         ObjTreeReconnect(nobjs[i], crealist);                   
01132                 }
01133 
01134                 coreobjhash newcrealist;
01135                 shiftlist(crealist, newcrealist);
01136 
01137                 for(i = 0; i< cnt; i++) {
01138                         ObjTreeCheckRelations(mgaproject, nobjs[i], newcrealist);                       
01139                 }
01140 
01141                 if(targetlevel >= 0) ReDeriveNewObjs(mgaproject, nobjs, cnt, targetlevel+1);
01142 
01143                 docheck(mgaproject);
01144 
01145 // Assemble return array:
01146                 if(objs) {
01147                         CREATEEXCOLLECTION_FOR(MgaFCO, q);
01148                         for(i = 0; i< cnt; i++) {
01149                                 CComPtr<IMgaFCO> ff;
01150                                 ObjForCore(nobjs[i])->getinterface(&ff);
01151                                 q->Add(ff); 
01152                         }
01153                         *objs = q.Detach();
01154                 }
01155 
01156 
01157 
01158                 SelfMark(OBJEVENT_NEWCHILD);
01159 
01160         } COMCATCH_IN_TRANSACTION_MAYBE(;);
01161 }
01162 
01163 HRESULT FCO::CopyFCODisp(IMgaFCO *copiedobj, IMgaMetaRole *role, IMgaFCO **nobj)
01164 {
01165         COMTRY_IN_TRANSACTION_MAYBE {
01166                 CComPtr<IMgaFCO> new_fco;
01167 
01168                 // copy in param to a folder coll
01169                 CREATEEXCOLLECTION_FOR(MgaFCO, q);
01170                 q->Add( CComPtr<IMgaFCO>( copiedobj));
01171 
01172                 CComPtr<IMgaMetaRoles> roles;
01173                 if (role)
01174                 {
01175                         COMTHROW(roles.CoCreateInstance(L"Mga.MgaMetaRoles", NULL, CLSCTX_INPROC));
01176                         COMTHROW(roles->Append(CComPtr<IMgaMetaRole>(role)));
01177                 }
01178 
01179                 CComPtr<IMgaFCOs> newfcos;
01180                 COMTHROW(CopyFCOs( q, roles, &newfcos));
01181                 
01182                 // extract ret value from returned coll
01183                 long cnt = 0; 
01184                 if( newfcos)  COMTHROW( newfcos->get_Count( &cnt));
01185                 if( cnt == 1) COMTHROW( newfcos->get_Item( 1, &new_fco));
01186                 
01187                 if( nobj) {
01188                         *nobj = new_fco.Detach();
01189                 }
01190         } COMCATCH_IN_TRANSACTION_MAYBE(;);
01191 }
01192 
01193 
01197 
01198 
01199 // give new value to subobj, and also give the same value to all its slave subobjs
01200 void RedirectMasterTree(CoreObj &subobj, attrid_type ai, CoreObj &newval) {
01201         subobj[ai] = newval;
01202         CoreObjs slso;
01203         slso = subobj[ATTRID_MASTEROBJ+ATTRID_COLLECTION];
01204         ITERATE_THROUGH(slso) {
01205                 RedirectMasterTree(ITER, ai, newval);
01206         }
01207 }
01208 
01209 // An object with tree has been moved into a type, fixup relations that used to point from inside
01210 // to the object just moved, i.e. which have just became 'internal'
01211 // self = the target object that may have too many pointers pointing at itself
01212 // selfbase = the base of the subtype/instance (self is contained by that)
01213 // level = the distance between self and selfbase
01214 
01215 void ObjTreeInternalize(CMgaProject *mgaproject, CoreObj &self, CoreObj &selfbase, int tlevel) {
01216         CoreObj origbase = selfbase[ATTRID_DERIVED];
01217         CoreObj orig = self[ATTRID_DERIVED];
01218         static attrid_type ais[] = {ATTRID_SEGREF, ATTRID_REFERENCE, ATTRID_XREF };
01219 // do loop for ATTRID_REFERENCE, ATTRID_XREF, and also for ATTRID_SEGREF in case of ref objs
01220         for(int i = (self.GetMetaID() == DTID_REFERENCE) ? 0 : 1; i < DIM(ais); i++) {
01221                 attrid_type ai = ais[i];
01222                 CoreObjs rels = orig[ai + ATTRID_COLLECTION];
01223                 ITERATE_THROUGH(rels) {
01224                         metaid_type typ = ITER.GetMetaID();
01225 // 1. The object must be CONNROLE or SETNODE
01226                         if(typ != DTID_CONNROLE && typ != DTID_SETNODE) continue;
01227 // 2. The object must not have a master pointing to the same object
01228                         CoreObj obmaster = ITER[ATTRID_MASTEROBJ];
01229                         if(obmaster && COM_EQUAL(orig, CoreObj(obmaster[ai]))) continue;
01230                         CoreObj srcobj = ITER.GetMgaObj();
01231                         int srclevel;
01232 // 3. The relation object must be part of the same type (i.e common derivation parent)
01233                         if(!IsContained(srcobj, origbase, &srclevel)) continue;  // it is an external reference
01234 
01235                         CoreObjs slso = ITER[ATTRID_MASTEROBJ+ATTRID_COLLECTION];
01236         
01237                         ITERATE_THROUGH(slso) {
01238                                 CoreObj derivedsrc = ITER.GetMgaObj();
01239                                 if(COM_EQUAL(selfbase, derivedsrc.FollowChain(ATTRID_FCOPARENT, srclevel))) {
01240                                         ASSERT(COM_EQUAL(orig, CoreObj(ITER[ai])));
01241                                         RedirectMasterTree(ITER,ai,self);
01242                                         setcheck(mgaproject, derivedsrc, CHK_CHANGED);
01243                                         break;
01244                                 }
01245                         }
01246                 }
01247         }
01248 // descend to children, increase level
01249         if(self.GetMetaID() == DTID_MODEL) {
01250                 CoreObjs children = self[ATTRID_FCOPARENT + ATTRID_COLLECTION];
01251                 ITERATE_THROUGH(children) {
01252                         ObjTreeInternalize(mgaproject, ITER, selfbase, tlevel+1);
01253                 }
01254         }
01255 }
01256 
01257 
01258 
01259 
01261 // DeriveMoveds
01263 //   We have set of objects ('orignobjs') moved into a single model in a (base)type. 
01264 //   Reflect changes in its deriveds. 
01265 //   -- 'extmoved' objects must be 
01266 //              - newly derived,  
01267 //              - 'internalized'
01268 //              - reconnected
01269 //   -- others must be located and moved here
01270 //   They all need to be checked.
01271 //   
01273 // !!! RECURSIVE 
01275 void DeriveMoveds(CMgaProject *mgaproject, std::vector<CoreObj> &orignobjs, std::vector<int> &extmoved, int cnt, int targetlevel)
01276 {
01277         if(cnt < 1) return;
01278 
01279         CoreObj orig = orignobjs[0][ATTRID_FCOPARENT];
01280         metaid_type n = GetMetaID( orig);
01281 
01282         if (n >= DTID_MODEL && n <= DTID_SET)
01283         {
01284                 CoreObjs deriveds = orig[ATTRID_DERIVED+ATTRID_COLLECTION];
01285                 ITERATE_THROUGH(deriveds) {
01286                         int i;
01287                         CoreObj subtypebase = ITER.FollowChain(ATTRID_FCOPARENT, targetlevel);
01288                         coreobjpairhash derivcrealist;
01289                         coreobjhash derivmovedlist;
01290                         long instance = ITER[ATTRID_PERMISSIONS] & INSTANCE_FLAG;
01291                         std::vector<CoreObj> newderiveds(cnt);
01292                         for(i = 0; i< cnt; i++) {
01293                                 if(extmoved[i] < 0) {   // the movedobject is a newcomer in the basetype, derive new obj in subtype
01294                                         ObjTreeDerive(mgaproject, orignobjs[i], newderiveds[i], derivcrealist, instance);
01295                                         newderiveds[i][ATTRID_FCOPARENT]=ITER;
01296                                         ObjTreeInternalize(mgaproject, newderiveds[i], subtypebase, targetlevel+1);
01297                                 }
01298                                 else {
01299                                         CoreObj tgt(ITER);      // locate the corresponding object in subtype and move it
01300                                         CoreObjs ders = orignobjs[i][ATTRID_DERIVED+ATTRID_COLLECTION];
01301                                         ITERATE_THROUGH(ders) {
01302                                                 CoreObj der(ITER);
01303                                                 if(COM_EQUAL(subtypebase, ITER.FollowChain(ATTRID_FCOPARENT, extmoved[i]))) {
01304                                                                 newderiveds[i] = ITER;
01305                                                                 CoreObjMark(ITER[ATTRID_FCOPARENT], OBJEVENT_LOSTCHILD);
01306                                                                 ITER[ATTRID_FCOPARENT] = tgt;
01307                                                                 ITER[ATTRID_ROLEMETA] = orignobjs[i][ATTRID_ROLEMETA];
01308                                                                 ObjTreeCollect(mgaproject, ITER, derivmovedlist, CHK_MOVED);
01309                                                                 break;
01310                                                 }
01311                                         }
01312                                         ASSERT(ITER_BROKEN);
01313                                 }
01314                         }
01315                         CoreObjMark(ITER, OBJEVENT_NEWCHILD);
01316         // Reroute references
01317                         for(i = 0; i< cnt; i++) {
01318                                 ObjTreeReconnect(newderiveds[i], derivcrealist, subtypebase);
01319                         }
01320                         shiftlist(derivcrealist, derivmovedlist);
01321                         for(i = 0; i< cnt; i++) {
01322                                 ObjTreeCheckRelations(mgaproject, newderiveds[i], derivmovedlist);                      
01323                         }
01324                         DeriveMoveds(mgaproject, newderiveds, extmoved, cnt, targetlevel);
01325 
01326                         for(i = 0; i< cnt; i++) {
01327                                 ObjTreeCheckINTORelations(mgaproject, newderiveds[i], derivmovedlist);                  
01328                         }
01329                 }
01330         }
01331 }
01332 
01333 
01334 HRESULT FCO::MoveFCOs(IMgaFCOs *movelist, IMgaMetaRoles *rlist,IMgaFCOs **objs) {
01335         COMTRY_IN_TRANSACTION_MAYBE {
01336                 CheckWrite();
01337                 CHECK_MYINPTRSPAR(movelist);
01338                 long cnt;
01339                 COMTHROW(movelist->get_Count(&cnt));
01340 
01341                 bool valid = ( cnt > 0);
01342                 if ( cnt == 1)
01343                 {
01344                         valid = false;
01345                         // check whether the source folder is the target as well
01346                         CComPtr<IMgaFCO> mf;
01347                         MGACOLL_ITERATE( IMgaFCO, movelist) {
01348                                 mf = MGACOLL_ITER;
01349                         } MGACOLL_ITERATE_END;
01350 
01351                         VARIANT_BOOL is_equal;
01352                         CComPtr<IMgaFCO> thisptr;
01353                         getinterface( &thisptr);
01354                         COMTHROW( mf->get_IsEqual( thisptr, &is_equal));
01355 
01356                         if (is_equal == VARIANT_FALSE) // not equal
01357                                 //COMTHROW( E_MGA_INVALID_ARG); // do not copy/move onto itself
01358                                 valid = true;
01359                 }
01360 
01361                 if ( valid) 
01362                 {
01363                         if(rlist) {
01364                                 long rlcnt;
01365                                 COMTHROW(rlist->get_Count(&rlcnt));
01366                                 if(rlcnt != cnt) COMTHROW(E_MGA_BAD_COLLENGTH);
01367                         }
01368                         metaid_type targettype = GetMetaID(self);
01369                         int targetlevel = 0;
01370                         CoreObj rootp;
01371 // Pre check:
01372                         if(targettype == DTID_MODEL) {
01373                                 if(self[ATTRID_PERMISSIONS]  & ~EXEMPT_FLAG) COMTHROW(E_MGA_NOT_CHANGEABLE);
01374                                 GetRootOfDeriv(self, rootp, &targetlevel);
01375                                 MGACOLL_ITERATE(IMgaFCO, movelist) {
01376                                         CoreObj cur = CoreObj(MGACOLL_ITER);
01377                                         if(IsContained(self, cur)) COMTHROW(E_MGA_OP_REFUSED);
01378                                         if(cur[ATTRID_RELID] >= RELIDSPACE) COMTHROW(E_MGA_OP_REFUSED); 
01379                                         if(rootp) {
01380                                                 CheckConflict(cur, rootp);
01381                                         }
01382                                 } MGACOLL_ITERATE_END;
01383                         }
01384 
01385 // move trees
01386                         coreobjhash moveslist;
01387                         int i = 0;
01388 
01389                         std::vector<CoreObj> nobjs(cnt);
01390                         std::vector<int> moved_into(cnt);  // >= 0 for objects moved inside the tree, -1 for newcomers
01391                         MGACOLL_ITERATE(IMgaFCO, movelist) {
01392                                 CoreObj cur = nobjs[i] = CoreObj(MGACOLL_ITER);
01393                                 CoreObj movedobjrootp;
01394                                 int movedobjlevel;
01395                                 GetRootOfDeriv(cur, movedobjrootp, &movedobjlevel);
01396                                 int derdist = GetRealSubtypeDist(cur);
01397                                 if(derdist) COMTHROW(E_MGA_OP_REFUSED);
01398         //                      if(derdist)     ObjTreeDist(cur, derdist);  // move
01399 
01400                                 CoreObj curp = cur[ATTRID_FCOPARENT];
01401                                 if(!COM_EQUAL(curp, self)) {
01402                                         ObjForCore(curp)->CheckWrite(); // parent of cur will change, so check for WRITE permission
01403                                         CoreObjMark(curp, OBJEVENT_LOSTCHILD);
01404                                         assignnewchild(cur);
01405                                         CoreObjMark(cur, OBJEVENT_PARENT);
01406                                 }
01407                                 ObjTreeCollect(mgaproject, cur, moveslist, CHK_MOVED);
01408                                 metaref_type trole = METAREF_NULL;
01409                                 if(targettype != DTID_FOLDER) {
01410                                         ASSERT(targettype == DTID_MODEL);
01411                                         CComPtr<IMgaMetaRole> r;
01412                                         if(rlist) COMTHROW(rlist->get_Item(i+1, &r));
01413                                         if(!r) {   // NO metaname given, inherit that of original object
01414                                                 CComPtr<IMgaMetaFCO> mf; 
01415                                                 COMTHROW(get_Meta(&mf));
01416                                                 CComQIPtr<IMgaMetaModel> parentmeta = mf;
01417                                                 if(!parentmeta) COMTHROW(E_MGA_META_INCOMPATIBILITY);
01418                                                 cur[ATTRID_ROLEMETA];
01419                                                 metaref_type t;
01420                                                 t = (nobjs[i])[ATTRID_ROLEMETA];
01421                                                 if(!t) COMTHROW(E_MGA_NO_ROLE);
01422                                                 CComQIPtr<IMgaMetaRole> metar = mgaproject->FindMetaRef(t);
01423                                                 if(!metar) COMTHROW(E_MGA_META_INCOMPATIBILITY);
01424                                                 CComBSTR rolename;
01425                                                 COMTHROW(metar->get_Name(&rolename));
01426                                                 COMTHROW(parentmeta->get_RoleByName(rolename, &r));
01427                                                 if(!r) COMTHROW(E_MGA_NO_ROLE);
01428                                         }
01429                                         {
01430                                                 metaref_type kt;
01431                                                 CComPtr<IMgaMetaFCO> mfco;
01432                                                 COMTHROW(r->get_Kind(&mfco));
01433                                                 COMTHROW(mfco->get_MetaRef(&kt));
01434                                                 if(kt != cur[ATTRID_META]) COMTHROW(E_MGA_META_INCOMPATIBILITY);
01435                                         }
01436 
01437                                         COMTHROW(r->get_MetaRef(&trole));
01438                                         if(trole == METAREF_NULL)  COMTHROW(E_MGA_INVALID_ROLE);
01439                                 }
01440                                 cur[ATTRID_ROLEMETA] = trole;
01441 
01442                                 // Determine what to do with subtypes of the objects moved 
01443                                 CoreObjs ders = cur[ATTRID_DERIVED+ATTRID_COLLECTION];
01444                                 if(!rootp || !COM_EQUAL(movedobjrootp, rootp)) {     // ********* moving out of a type
01445                                         moved_into[i] = -1;                                // ******** true if moving into a type
01446                                         if(movedobjlevel < 1) { // not derived, or derived as self
01447                                                                                         // if the object to be moved is a root of derivs,
01448                                                                                         // and not moved to a model, thst model must not have any subtypes/instances
01449                                                 if(ders.Count() &&
01450                                                         targettype == DTID_MODEL && 
01451                                                         CoreObjs(self[ATTRID_DERIVED+ATTRID_COLLECTION]).Count()) {
01452                                                                 COMTHROW(E_MGA_OP_REFUSED);  
01453                                                 }
01454                                         }
01455                                         else {
01456                                                 ITERATE_THROUGH(ders) {                            // ******* erase all previous subtypes
01457                                                         ObjForCore(ITER)->inDeleteObject();
01458                                                 }
01459                                         }
01460                                 }
01461                                 else moved_into[i] = movedobjlevel;        // ***** the object remains under the same rootmodel
01462                                 i++;
01463                         } MGACOLL_ITERATE_END;
01464 
01465                         for(i = 0; i< cnt; i++) {
01466                                 ObjTreeCheckRelations(mgaproject, nobjs[i], moveslist);                 
01467                         }
01468 
01469                         if(targettype == DTID_MODEL) {
01470                                 DeriveMoveds(mgaproject, nobjs, moved_into, cnt, targetlevel);
01471                         }
01472 
01473 // Reroute references
01474                         for(i = 0; i< cnt; i++) {
01475                                 ObjTreeCheckINTORelations(mgaproject, nobjs[i], moveslist);                     
01476                         }
01477 
01478 
01479                         docheck(mgaproject);
01480 
01481 // Assemble return array:
01482                         CREATEEXCOLLECTION_FOR(MgaFCO, q);
01483                         for(i = 0; i< cnt; i++) {
01484                                 CComPtr<IMgaFCO> n;
01485                                 ObjForCore(nobjs[i])->getinterface(&n);
01486                                 q->Add(n); 
01487                         }
01488 
01489                         
01490                         if(objs) {
01491                                 *objs = q.Detach();
01492                         }
01493 
01494 
01495                         SelfMark(OBJEVENT_NEWCHILD);
01496                 } // if valid
01497 
01498         } COMCATCH_IN_TRANSACTION_MAYBE(;);
01499 }
01500 
01501 HRESULT FCO::MoveFCODisp(IMgaFCO *movedobj, IMgaMetaRole *role, IMgaFCO **nobj)
01502 {
01503         COMTRY_IN_TRANSACTION_MAYBE {
01504                 CComPtr<IMgaFCO> new_fco;
01505 
01506                 // copy in param to a folder coll
01507                 CREATEEXCOLLECTION_FOR(MgaFCO, q);
01508                 q->Add( CComPtr<IMgaFCO>( movedobj));
01509 
01510                 CComPtr<IMgaMetaRoles> roles;
01511                 if (role)
01512                 {
01513                         COMTHROW(roles.CoCreateInstance(L"Mga.MgaMetaRoles", NULL, CLSCTX_INPROC));
01514                         COMTHROW(roles->Append(CComPtr<IMgaMetaRole>(role)));
01515                 }
01516 
01517                 CComPtr<IMgaFCOs> newfcos;
01518                 COMTHROW(MoveFCOs( q, roles, &newfcos));
01519                 
01520                 // extract ret value from returned coll
01521                 long cnt = 0; 
01522                 if( newfcos)  COMTHROW( newfcos->get_Count( &cnt));
01523                 if( cnt == 1) COMTHROW( newfcos->get_Item( 1, &new_fco));
01524                 
01525                 if( nobj) {
01526                         *nobj = new_fco.Detach();
01527                 }
01528         } COMCATCH_IN_TRANSACTION_MAYBE(;);
01529 }
01530 
01531 
01535 
01536 // do not use with folders
01537 bool IsAnythingDerivedFromChildren(CoreObj cbase) {
01538         if(GetMetaID(cbase) == DTID_MODEL) {
01539                 ITERATE_THROUGH(CoreObjs(cbase[ATTRID_FCOPARENT + ATTRID_COLLECTION])) {
01540                         if(CoreObjs(ITER[ATTRID_DERIVED + ATTRID_COLLECTION]).Count() ||
01541                                 IsAnythingDerivedFromChildren(ITER) ) return true;
01542                 }
01543         }
01544         return false;
01545 }
01546 
01547 
01548 
01549 HRESULT FCO::DeriveFCO(IMgaFCO *base, IMgaMetaRole *role, VARIANT_BOOL binstance, IMgaFCO** newobj) {
01550         COMTRY_IN_TRANSACTION {
01551                 CheckWrite();
01552                 CHECK_INBOOLPAR(binstance);
01553                 CHECK_MYINPTRPAR(base);
01554                 CHECK_OUTPTRPAR(newobj);
01555                 metaid_type targettype = GetMetaID(self);
01556 
01557 // Pre check:
01558 // ERROR if object is not rootobject
01559                 objtype_enum l;
01560                 CoreObj cbase(base);
01561                 COMTHROW(base->get_ObjType(&l));
01562                 if(l == OBJTYPE_FOLDER) COMTHROW(E_MGA_NOT_DERIVABLE);
01563 //NCH
01564 //              COMTHROW(base->GetParent(NULL, &l));
01565 //              if(l != OBJTYPE_FOLDER) COMTHROW(E_MGA_NOT_DERIVABLE);
01566 
01567 //              Derivable: the FCO parent of base has 0 deriveds
01568 //                                 base already has deriveds, or all the children have 0 deriveds too.
01569                 CoreObj parent = cbase[ATTRID_FCOPARENT];
01570                 int lev;
01571                 CoreObj rr;
01572                 GetRootOfDeriv(cbase, rr, &lev);
01573                 if( lev > 0 ||
01574                         lev == -1 && IsAnythingDerivedFromChildren(cbase) ) {
01575                                 // COMTHROW(E_MGA_NOT_DERIVABLE);
01576                 }
01577 
01578 
01579 // Check if object to be created or any of its children will become children of their own basetypes
01580                 int targetlevel = 0;
01581                 if(targettype != DTID_FOLDER) {
01582                         if(self[ATTRID_PERMISSIONS] & ~EXEMPT_FLAG) COMTHROW(E_MGA_NOT_CHANGEABLE);
01583                         CoreObj root;
01584                         GetRootOfDeriv(self, root, &targetlevel);
01585                         if(root) {
01586                                 CoreObj c1(base);
01587                                 if(COM_EQUAL(root, c1)) COMTHROW(E_MGA_NOT_DERIVABLE);
01588                                 CheckConflict(c1, root);
01589                         }
01590                 }
01591 
01592 
01593                 
01594 // Copy trees
01595                 CoreObj newcoreobj;
01596                 coreobjpairhash crealist;
01597                 ObjTreeDerive(mgaproject, cbase, newcoreobj, crealist, binstance ? INSTANCE_FLAG : 0);  // copy
01598                 assignnewchild(newcoreobj);
01599 
01600                 if (targettype == DTID_FOLDER)
01601                         newcoreobj[ATTRID_ROLEMETA] = METAREF_NULL;
01602                 else {
01603                         metaref_type t;
01604                         if(!role)  COMTHROW(E_MGA_INVALID_ROLE);
01605                         COMTHROW(role->get_MetaRef(&t));
01606                         if(t == METAREF_NULL)  COMTHROW(E_MGA_INVALID_ROLE);
01607                         {
01608                                 metaref_type kt;
01609                                 CComPtr<IMgaMetaFCO> mfco;
01610                                 COMTHROW(role->get_Kind(&mfco));
01611                                 COMTHROW(mfco->get_MetaRef(&kt));
01612                                 if(kt != newcoreobj[ATTRID_META])COMTHROW(E_MGA_META_INCOMPATIBILITY);
01613                         }
01614 
01615                         newcoreobj[ATTRID_ROLEMETA] = t;
01616                 }
01617 
01618 
01619 // Reroute references
01620                 ObjTreeReconnect(newcoreobj, crealist);                 
01621 // Post check:
01622                 coreobjhash newcrealist;
01623                 shiftlist(crealist, newcrealist);
01624 
01625                 ObjTreeCheckRelations(mgaproject, newcoreobj, newcrealist);                     
01626 
01627                 ObjTreeNotify(mgaproject, newcoreobj);
01628 
01629                 if(targetlevel >= 0) ReDeriveNewObj(mgaproject, newcoreobj, targetlevel+1);
01630 
01631                 SelfMark(OBJEVENT_NEWCHILD);
01632                 ObjFor(base)->SelfMark(OBJEVENT_SUBT_INST);
01633 
01634                 docheck(mgaproject);
01635 
01636 
01637 // Notification
01638                 ObjForCore(newcoreobj)->getinterface(newobj);
01639         } COMCATCH_IN_TRANSACTION(;)
01640 }
01641 
01642 
01643 
01644 
01645 
01646 // this recursive method is different from ObjTreeCopy in that it doesn't
01647 // create a new object into 'nobj' as its first step
01648 // some inner collections are copied with the help of ObjTreeCopy
01649 // it doesn't create anything except RegNodes and Attributes which are still tied to the base
01650 void ObjDetachAndMerge( CMgaProject *mgaproject, CoreObj orig, CoreObj &nobj, coreobjpairhash& crealist, unsigned long nextrelid, bool prim = true)
01651 {
01652         bool has_last_relid_attr = false;
01653         unsigned long nb_of_children = 0;
01654         unsigned long last_relid_set = 0;
01655 
01656         CComPtr<ICoreAttributes> atts;
01657         COMTHROW(orig->get_Attributes(&atts));
01658         MGACOLL_ITERATE(ICoreAttribute, atts) {
01659                         attrid_type ai;
01660                         CComPtr<ICoreMetaAttribute> mattr;
01661                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
01662                         COMTHROW(mattr->get_AttrID(&ai));
01663                         if(ai < ATTRID_COLLECTION) {
01664                                 switch(ai) {
01665                                         case ATTRID_DERIVED: 
01666                                         case ATTRID_MASTEROBJ:
01667                                         {
01668                                                 CoreObj nmas = nobj[ai];
01669                                                 if( nobj.IsFCO() && nmas && nmas.IsFCO()) // save its master's guid into registry
01670                                                 {
01671                                                         CComBSTR bstr;
01672                                                         ObjForCore( nmas)->GetGuidDisp( &bstr);
01673                                                         if( bstr) ObjForCore( nobj)->put_RegistryValue( CComBSTR( DETACHED_FROM), bstr);
01674                                                 }
01675                                                 CComPtr<ICoreAttribute> regattr;
01676                                                 HRESULT hr = orig->get_Attribute(ATTRID_REGNODE, &regattr);
01677                                                 if (SUCCEEDED(hr))
01678                                                         MergeRegs(orig, nobj);
01679                                                 else if (hr != E_INVALIDARG)
01680                                                         COMTHROW(hr);
01681                                                 nobj[ai] = CComVariant( (IDispatch*) 0);//an empty value;
01682                                                 break;
01683                                         }
01684                                         case ATTRID_PERMISSIONS:
01685                                         {
01686                                                 nobj[ai] = nobj[ai] & ~INSTANCE_FLAG; // remove INSTANCE_FLAG
01687                                                 // do not modify LIBROOT_FLAG LIBRARY_FLAG READONLY_FLAG EXEMPT_FLAG as these are not inherited
01688                                                 //   (though LIBROOT_FLAG LIBRARY_FLAG READONLY_FLAG should be false here or CheckWrite would have failed)
01689 
01690                                                 break;
01691                                         }
01692                                         case ATTRID_RELID:
01693                                         {
01694                                                 if( !prim) // it was a child of a primary derived, being detached
01695                                                 {
01696                                                         // since it was called recursively we know for sure that
01697                                                         // this object is a secondary derived object along with its
01698                                                         // parent. 
01699                                                         // (the level of the derivation in its case might have been 
01700                                                         // higher than the parent's level of derivation)
01701                                                         // but since the parent is detached totally from its
01702                                                         // base, these kinds of children (for which the method
01703                                                         // has been invoked recursively) will become archetypes
01704                                                         // no matter how they have been derived originally
01705                                                         // that is why the relid has to be decreased to the
01706                                                         // [0, RELIDSPACE) interval
01707                                                         
01708                                                         // revert a secondary derived objects relid to a normal relid
01709                                                         //long relid = nobj[ai];
01710                                                         //ASSERT( relid >= 0);
01711                                                         //while( relid >= RELIDSPACE) relid -= RELIDSPACE;
01712 
01713                                                         if( nextrelid >= 0 && nextrelid < RELIDSPACE)
01714                                                         {
01715                                                                 // this command would cause ambiguity if the parent has plain children
01716                                                                 //nobj[ai] = relid; // object will be no more secondary derived!
01717                                                                 // that is why we use new relids
01718                                                                 nobj[ai] = nextrelid;
01719                                                         }
01720                                                         else
01721                                                         {
01722                                                                 ASSERT(0); // problem
01723                                                                 COMTHROW(E_MGA_LONG_DERIVCHAIN);
01724                                                         }
01725                                                 }
01726                                                 break;
01727                                         }
01728                                         case ATTRID_LASTRELID:
01729                                         {
01730                                                 // unsigned long old_val = nobj[ai];
01731                                                 // the old value 'nobj[ai]' contains only the number of the plain objects
01732                                                 // this is a temp value (the correct value is inserted upon exit)
01733                                                 //nobj[ai] = 0L;
01734                                                 has_last_relid_attr = true;
01735                                                 break;
01736                                         }
01737                                         default:
01738                                                 break; // no copy/change needed in other plain cases
01739                                 }; // endswitch
01740                         }
01741                         else if( LINKREF_ATTR(ai-ATTRID_COLLECTION)){
01742                                 ai -= ATTRID_COLLECTION;
01743 
01744                                 switch( ai) {
01745                                         case ATTRID_ATTRPARENT: // copy the unfilled attributes
01746                                         {
01747                                                 unsigned int owned_attrs(0), inherited_attrs(0), l3(0);
01748                                                 CComBSTR nm;
01749                                                 ObjForCore(nobj)->get_Name( &nm);
01750 
01751                                                 std::list<metaref_type> ownedAttrVec;
01752                                                 {
01753                                                         CoreObjs my_attrs = nobj[ai + ATTRID_COLLECTION]; // count first the # of owned attributes
01754                                                         ITERATE_THROUGH(my_attrs) { 
01755                                                                 ++owned_attrs;
01756                                                                 metaref_type attr_i = ITER[ATTRID_META];
01757                                                                 if( std::find( ownedAttrVec.begin(), ownedAttrVec.end(), attr_i) == ownedAttrVec.end())
01758                                                                         ownedAttrVec.push_back( attr_i);
01759                                                                 else
01760                                                                         ASSERT(0); // can an attribute belong to self twice?
01761                                                         }
01762                                                 }
01763                                                 // owned_attrs is the number of owned attributes
01764                                                 // in case the user overwrites the inherited attribute values 
01765                                                 // the instance or subtype gets an additional attribute (initially had none)
01766                                                 // thus in case of detaching, we need to distinguish between owned values
01767                                                 // and inherited values (owned preferred)
01768 
01769                                                 {
01770                                                         CoreObjs base_attrs = orig[ai + ATTRID_COLLECTION]; // copy the base's values selectively
01771                                                         ITERATE_THROUGH(base_attrs) { 
01772                                                                 bool fnd = std::find( ownedAttrVec.begin(), ownedAttrVec.end(), ITER[ATTRID_META]) != ownedAttrVec.end();
01773                                                                 if( !fnd)
01774                                                                 {
01775                                                                         ++inherited_attrs;
01776                                                                         CoreObj nchild;
01777                                                                         ObjTreeCopy(mgaproject, ITER, nchild, crealist);
01778                                                                         nchild[ai] = nobj;
01779                                                                 }
01780                                                         }
01781                                                 }
01782                                                 {
01783                                                         CoreObjs mine = nobj[ai + ATTRID_COLLECTION]; // overwrite with mine 
01784                                                         ITERATE_THROUGH( mine) { 
01785                                                                 ++l3;
01786                                                         }
01787                                                 }
01788 
01789                                                 ASSERT( owned_attrs + inherited_attrs == l3);
01790                                                 break;
01791                                         }
01792                                         case ATTRID_FCOPARENT: // for all secondary derived fco children-> detach
01793                                         {
01794                                                 // we will calc the max_relid of those child objects which are not secondary, tertiary, ... objects
01795                                                 // because in case of subtypes not all children originate from the current base:
01796                                                 // some children might be plain objects, and some others may be primary subtypes of other bases
01797                                                 long cur_max_relid = nobj[ATTRID_LASTRELID];
01798                                                 CoreObjs children = nobj[ai + ATTRID_COLLECTION];
01799                                                 ITERATE_THROUGH(children) {
01800                                                         // this will help set the last relid correctly
01801                                                         ++nb_of_children;
01802                                                         CoreObj base = (ITER)[ATTRID_DERIVED];
01803                                                         if( base) // child is also derived
01804                                                         {
01805                                                                 VARIANT_BOOL primDer = VARIANT_FALSE;
01806                                                                 if( nobj.IsFCO()) ObjForCore( ITER)->get_IsPrimaryDerived( &primDer);
01807                                                                 if( primDer != VARIANT_TRUE) // it is a child derived along with 'orig'
01808                                                                 {
01809                                                                         // detach it as well from its base
01810                                                                         ObjDetachAndMerge(mgaproject, base, ITER, crealist, ++cur_max_relid, false);
01811                                                                         // increase the cur_max_relid for the next child
01812                                                                         // FIXME: should this be max?
01813                                                                         nobj[ATTRID_LASTRELID] = last_relid_set = cur_max_relid;
01814                                                                 }
01815                                                                 else 
01816                                                                 {       // it might be a primary subtype/instance placed into this subtype
01817                                                                         // leave this object untouched
01818                                                                 }
01819                                                         }
01820                                                         else
01821                                                         {       // additional child->no action needed
01822                                                         }
01823                                                 }
01824                                                 break;
01825                                         }
01826                                         default: // for all others -> detach
01827                                         { 
01828                                                 CoreObjs collmembers = nobj[ai + ATTRID_COLLECTION];
01829                                                 ITERATE_THROUGH(collmembers) {
01830                                                         // remove the ATTRID_DERIVED attrs if any?
01831                                                         ObjDetachAndMerge(mgaproject, ITER, ITER, crealist, 0, false);
01832                                                 }
01833                                         }
01834                                 }; // endswitch
01835                         }
01836 
01837         } MGACOLL_ITERATE_END;
01838 
01839         if( has_last_relid_attr) // if this CoreObj has RELID_LAST attribute
01840         {
01841                 unsigned long r = nobj[ATTRID_LASTRELID];
01842                 ASSERT( last_relid_set >= nb_of_children);
01843                 if( r < last_relid_set)
01844                         nobj[ATTRID_LASTRELID] = last_relid_set; // fill it with the correct value
01845         }
01846 }
01847 
01848 void ObjAttach(CMgaProject *mgaproject, const CoreObj &origobj, CoreObj &newobj, coreobjpairhash &crealist, long instance, bool prim) 
01849 {
01850         // this variable will make sure that if an instance is met inside a base (origobj) which is subtyped (!)
01851         // then assure that though a subtype may have additional children, but the instance brach might not 
01852         // contain additional children
01853         bool instance_met = false;
01854         CComPtr<ICoreAttributes> atts;
01855         COMTHROW(origobj->get_Attributes(&atts));
01856         MGACOLL_ITERATE(ICoreAttribute, atts) {
01857                         attrid_type ai;
01858                         CComPtr<ICoreMetaAttribute> mattr;
01859                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
01860                         COMTHROW(mattr->get_AttrID(&ai));
01861                         if(ai < ATTRID_COLLECTION) {
01862                                 switch(ai) {
01863                                 case ATTRID_DERIVED: 
01864                                 case ATTRID_MASTEROBJ:
01865                                         newobj[ai] = origobj;
01866                                         break;
01867                                 case ATTRID_PERMISSIONS:
01868                                         // if it was instance or orig is instance or it is supposed to be an instance:
01869                                         newobj[ai] = (newobj[ai] | origobj[ai] | long(instance)) & INSTANCE_FLAG;
01870                                         instance_met = newobj[ai] & INSTANCE_FLAG;
01871                                         break;
01872                                 case ATTRID_RELID: 
01873                                         {
01874                                                 if( !prim)
01875                                                 {
01876                                                         // if newobj[ai] + RELIDSPACE > LONG_MAX
01877                                                         if (newobj[ai] > LONG_MAX - RELIDSPACE)
01878                                                                 COMTHROW(E_MGA_LONG_DERIVCHAIN);
01879                                                         newobj[ai] = newobj[ai]+RELIDSPACE; //shift its own relid
01880                                                         ASSERT(newobj[ai] >= 0);
01881                                                 }
01882                                         }
01883                                         break;
01884                                 case ATTRID_LASTRELID: 
01885                                         newobj[ai] = 0L;
01886                                         break;
01887                                 //default:
01888                                 //      newobj[ai] = static_cast<CComVariant>(origobj[ai]);
01889                                 }
01890                         }
01891                         else {
01892                                 ai -= ATTRID_COLLECTION;
01893                                 if(LINKREF_ATTR(ai))  {
01894                                         if( ai == ATTRID_ATTRPARENT) { } // no need to copy attr values since the newobj already had its own
01895                                         else if( ai == ATTRID_CONSTROWNER) { }
01896                                         else if( ai == ATTRID_CONNROLE) { }
01897                                         else if( ai == ATTRID_SETMEMBER) { }
01898                                         else if(ai == ATTRID_FCOPARENT) {
01899                                                 
01900                                                 std::map< int, int> match;
01901                                                 std::map< CoreObj, CoreObj> matchO;
01902                                                 //std::vector<metaref_type> kidsVec, kidsVec2;
01903                                                 //std::vector<std::string> nameVec, nameVec2;
01904                                                 
01905                                                 unsigned int kids_o = 0;
01906                                                 {CoreObjs children = origobj[ai + ATTRID_COLLECTION];
01907                                                 ITERATE_THROUGH(children) {
01908                                                         ++kids_o;
01909                                                         metaref_type role_i = ITER[ATTRID_META];
01910                                                         //kidsVec.push_back( role_i);
01911                                                         
01912                                                         CComBSTR nm_i;
01913                                                         ObjForCore(ITER)->get_Name( &nm_i);
01914                                                         //std::string nm_ii; CopyTo( nm_i, nm_ii);
01915                                                         //nameVec.push_back( nm_ii);
01916 
01917                                                         CComBSTR gd_i;
01918                                                         ObjForCore(ITER)->GetGuidDisp( &gd_i);
01919 
01920                                                         CoreObj outer_ITER = ITER;
01921                                                         unsigned int kids_n = 0;
01922                                                         bool fnd = false;
01923                                                         {CoreObjs children2 = newobj[ai + ATTRID_COLLECTION];
01924                                                         ITERATE_THROUGH(children2) {
01925                                                                 ++kids_n;
01926                                                                 metaref_type role_j = ITER[ATTRID_META];
01927                                                                 //kidsVec2.push_back( role_j);
01928                                                                 
01929                                                                 CComBSTR nm_j;
01930                                                                 ObjForCore(ITER)->get_Name( &nm_j);
01931                                                                 //std::string nm_jj; CopyTo( nm_j, nm_jj);
01932                                                                 //nameVec2.push_back( nm_jj);
01933 
01934                                                                 CComBSTR gd_j;
01935                                                                 ObjForCore(ITER)->get_RegistryValue( CComBSTR( DETACHED_FROM), &gd_j);
01936                                                                 
01937                                                                 // name based equality is considered only if 
01938                                                                 // no stored master guid (Detached from) was found
01939                                                                 if( ( gd_j == gd_i && gd_j.Length() > 0 || nm_j == nm_i && gd_j.Length() == 0) 
01940                                                                         && role_i == role_j 
01941                                                                         && match.find(kids_n) == match.end()) // not found <==> not assigned
01942                                                                 {
01943                                                                         // kids_o <---> kids_n
01944                                                                         //ObjAttach( mgaproject, kids_o, kids_n)
01945                                                                         ObjAttach( mgaproject, outer_ITER, ITER, crealist, instance, false);
01946                                                                         match[kids_n] = kids_o;
01947                                                                         matchO[ITER] = outer_ITER;
01948                                                                         fnd = true;
01949                                                                         break;
01950                                                                 }
01951                                                         }}
01952                                                         
01953                                                         if( !fnd)
01954                                                         {
01955                                                                 CoreObj i;
01956                                                                 ObjTreeCopy( mgaproject, ITER, i, crealist);//, instance, false);
01957                                                                 ObjAttach( mgaproject, ITER, i, crealist, instance, false);
01958                                                                 i[ATTRID_FCOPARENT] = newobj;
01959                                                         }
01960                                                 }}
01961 
01962                                                 if( instance || instance_met) 
01963                                                 {
01964                                                         unsigned int kids_o( 0), kids_n( 0);
01965                                                         {CoreObjs children = origobj[ai + ATTRID_COLLECTION];
01966                                                         ITERATE_THROUGH(children) {
01967                                                                 ++kids_o;
01968                                                         }}
01969                                                         {CoreObjs children = newobj[ai + ATTRID_COLLECTION];
01970                                                         ITERATE_THROUGH(children) {
01971                                                                 ++kids_n;
01972                                                         }}
01973 
01974                                                         if( kids_o != kids_n) // at this point the instance should have the same number of elements like its base
01975                                                                 COMTHROW(E_FAIL);
01976                                                 }
01977                                         }
01978                                         else {
01979                                                 CoreObjs collmembers = origobj[ai + ATTRID_COLLECTION];
01980                                                 ITERATE_THROUGH(collmembers) {
01981                                                         CoreObj nchild;
01982                                                         ObjAttach(mgaproject, ITER, nchild, crealist, instance, false);
01983                                                         nchild[ai] = newobj;
01984                                                 }
01985                                         }
01986                                 }
01987                         }
01988 
01989         } MGACOLL_ITERATE_END;
01990 }
01991 
01992 void getMeAGuid( long *p_l1, long *p_l2, long *p_l3, long *p_l4)
01993 {
01994         GUID t_guid = GUID_NULL;
01995         COMTHROW(CoCreateGuid(&t_guid));
01996                 
01997         ASSERT(t_guid != GUID_NULL);
01998         //char buff[39];
01999         //sprintf( buff, "{%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}",
02000         //      t_guid.Data1, t_guid.Data2, t_guid.Data3,
02001         //      t_guid.Data4[0], t_guid.Data4[1], t_guid.Data4[2], t_guid.Data4[3],
02002         //      t_guid.Data4[4], t_guid.Data4[5], t_guid.Data4[6], t_guid.Data4[7]);
02003 
02004         // thus replace the old guid with a new one
02005         *p_l1 = t_guid.Data1; // Data1: 32 b, Data2, Data 3: 16 b, Data4: 64 bit
02006         *p_l2 = (t_guid.Data2 << 16) + t_guid.Data3;
02007         *p_l3 = (((((t_guid.Data4[0] << 8) + t_guid.Data4[1]) << 8) + t_guid.Data4[2]) << 8) + t_guid.Data4[3];
02008         *p_l4 = (((((t_guid.Data4[4] << 8) + t_guid.Data4[5]) << 8) + t_guid.Data4[6]) << 8) + t_guid.Data4[7];
02009 }
02010 
02011 void assignGuid( CMgaProject *mgaproject, CoreObj& ss)
02012 {
02013         ASSERT( ss.IsFCO() || ss.IsContainer());
02014         if( !ss.IsFCO() && !ss.IsContainer()) return;
02015         //if( mgaproject->mgaversion <= 1) return;
02016 
02017         long l1(0), l2(0), l3(0), l4(0);
02018         getMeAGuid( &l1, &l2, &l3, &l4);
02019 
02020         ss[ATTRID_GUID1] = l1;
02021         ss[ATTRID_GUID2] = l2;
02022         ss[ATTRID_GUID3] = l3;
02023         ss[ATTRID_GUID4] = l4;
02024 }
02025 
02026