GME
13
|
00001 #ifndef MGALIBREFRESH_H 00002 #define MGALIBREFRESH_H 00003 00004 #define DONT_OPTIMIZE 0 00005 00006 #include <stdio.h> 00007 #include <map> 00008 #include <vector> 00009 #include "Gme.h" 00010 00011 // ****************************************************************************** 00012 // C L A S S BinGuid 00013 // for representing the globally unique id assigned to each object 00014 // NOTE: 00015 // this class (BinGuid) represents a persistent ID of any MGA object (fco or folder) 00016 // these persistent ids are not changing upon export/import/refresh/detach/reattach 00017 // unlike mga ids which can change upon export-import 00018 // beware that if you import twice the same xme file into separate projects 00019 // then these persistent ids will remain equal in those separate projects 00020 // so if these projects later are altered and thus considered different after a while 00021 // they still might contain objects with the same persistent id (a GUID form id) 00022 // in order to tackle this non-uniqueness the id assigned to the rootfolder (as a folder) 00023 // plays an important role in identifying the scope (the realm where uniqueness applies) 00024 // of a persistent id 00025 // 00026 class BinGuid 00027 { 00028 protected: 00029 long v1; 00030 long v2; 00031 long v3; 00032 long v4; 00033 00034 public: 00035 BinGuid() 00036 : v1( 0) 00037 , v2( 0) 00038 , v3( 0) 00039 , v4( 0) 00040 { 00041 } 00042 00043 BinGuid( long p1, long p2, long p3, long p4) 00044 : v1( p1) 00045 , v2( p2) 00046 , v3( p3) 00047 , v4( p4) 00048 { 00049 } 00050 00051 void Set( long p1, long p2, long p3, long p4) 00052 { 00053 v1 = p1; 00054 v2 = p2; 00055 v3 = p3; 00056 v4 = p4; 00057 } 00058 00059 bool operator == (const BinGuid& peer) const 00060 { 00061 if( v1 != peer.v1) return false; // speed-up 00062 00063 return ( v1 == peer.v1 00064 && v2 == peer.v2 00065 && v3 == peer.v3 00066 && v4 == peer.v4); 00067 } 00068 00069 bool operator != ( const BinGuid& peer) const 00070 { 00071 return !( *this == peer); 00072 } 00073 00074 bool operator < ( const BinGuid& peer) const 00075 { 00076 if( v1 < peer.v1) return true; // speed-up 00077 00078 return v1 < peer.v1 00079 || v1 == peer.v1 && v2 < peer.v2 00080 || v1 == peer.v1 && v2 == peer.v2 && v3 < peer.v3 00081 || v1 == peer.v1 && v2 == peer.v2 && v3 == peer.v3 && v4 < peer.v4; 00082 } 00083 00084 void ConvertToStd( GUID& p_guid) const 00085 { 00086 const BinGuid &m_guid = *this; 00087 p_guid.Data1 = m_guid.v1; 00088 p_guid.Data2 = m_guid.v2 >> 16; 00089 p_guid.Data3 = m_guid.v2 & 0xFFFF; 00090 p_guid.Data4[0] = (m_guid.v3 >> 24); 00091 p_guid.Data4[1] = (m_guid.v3 >> 16) & 0xFF; 00092 p_guid.Data4[2] = (m_guid.v3 >> 8) & 0xFF; 00093 p_guid.Data4[3] = m_guid.v3 & 0xFF; 00094 00095 p_guid.Data4[4] = (m_guid.v4 >> 24); 00096 p_guid.Data4[5] = (m_guid.v4 >> 16) & 0xFF; 00097 p_guid.Data4[6] = (m_guid.v4 >> 8) & 0xFF; 00098 p_guid.Data4[7] = m_guid.v4 & 0xFF; 00099 } 00100 }; 00101 00102 // ****************************************************************************** 00103 // C L A S S UniqueId 00104 // this class comprises the 00105 // -- persistent id of an object and the 00106 // -- persistent id of the library's rootfolder 00107 // 00108 // IMPORTANT: the uniqueness of an fco guid is guarranteed within the scope 00109 // of a project/rootfolder 00110 class UniqueId 00111 { 00112 public: 00113 BinGuid objectId; 00114 BinGuid libId; 00115 00116 UniqueId() 00117 { 00118 } 00119 00120 UniqueId( const BinGuid& po, const BinGuid& pl) 00121 : objectId( po) 00122 , libId( pl) 00123 { 00124 } 00125 00126 void SetObj( const BinGuid& obj) 00127 { 00128 objectId = obj; 00129 } 00130 00131 void SetLib( const BinGuid& lib) 00132 { 00133 libId = lib; 00134 } 00135 00136 bool operator == (const UniqueId& peer) const 00137 { 00138 return ( libId == peer.libId 00139 && objectId == peer.objectId); 00140 } 00141 00142 bool operator< ( const UniqueId& peer) const 00143 { 00144 if( objectId < peer.objectId) return true; 00145 00146 return objectId < peer.objectId 00147 || objectId == peer.objectId && libId < peer.libId; 00148 } 00149 }; 00150 00151 // regular project id of 0x0065-00000001 form 00152 // (it is a temporary id in fact, it might change after an export-import) 00153 // used for identifying objects in the hosting project (where libraries are attached) 00154 typedef CComBSTR PROJ_ID; 00155 00156 struct elem_struct 00157 { 00158 // 00159 // an object's project id if the referred object is not in a library 00160 PROJ_ID id; 00161 00162 // 00163 // an object's persistent id if its a library element 00164 UniqueId uid; 00165 00166 // 00167 // this variable indicates whether id or uid is filled 00168 // if inlib the uid, else id is filled 00169 // we could have used a union as well 00170 bool inverysamelib; 00171 00172 bool inanotherlib; 00173 }; 00174 00175 // ****************************************************************************** 00176 // C L A S S MyCComBSTR 00177 // for enhancing CComBSTR with easy output of anchors to objects 00178 // 00179 class MyCComBSTR : public CComBSTR 00180 { 00181 public: 00182 MyCComBSTR() : CComBSTR() { } 00183 MyCComBSTR( const CComBSTR& p) : CComBSTR( p) {} 00184 00185 template<class T> 00186 void appendLink( const T& ptr) 00187 { 00188 if( ptr) 00189 appendLink( ObjForCore( CoreObj(ptr))); 00190 else 00191 COMTHROW(Append( L"NullObject")); 00192 } 00193 00194 template<> 00195 void appendLink<FCOPtr>( const FCOPtr& ptr) 00196 { 00197 appendLink(static_cast<FCO*>(ptr)); 00198 } 00199 00200 void appendLink( const CComBSTR& id, const CComBSTR& nm = L"NonameObject") 00201 { 00202 COMTHROW(Append(L"<A HREF=\"mga:")); 00203 COMTHROW(AppendBSTR( id)); 00204 COMTHROW(Append(L"\">")); 00205 COMTHROW(AppendBSTR( nm)); 00206 COMTHROW(Append(L"</A>")); 00207 } 00208 00209 void appendLink( FCO* fco) 00210 { 00211 CComBSTR id, nm; 00212 if( fco) 00213 { 00214 COMTHROW(fco->get_ID( &id)); 00215 COMTHROW(fco->get_Name( &nm)); 00216 appendLink( id, nm); 00217 } 00218 else 00219 COMTHROW(Append(L"NullObject")); 00220 } 00221 00222 void appendGuid( const GUID& t_guid) 00223 { 00224 wchar_t buff[39]; 00225 wsprintf( buff, L"{%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}", 00226 t_guid.Data1, t_guid.Data2, t_guid.Data3, 00227 t_guid.Data4[0], t_guid.Data4[1], t_guid.Data4[2], t_guid.Data4[3], 00228 t_guid.Data4[4], t_guid.Data4[5], t_guid.Data4[6], t_guid.Data4[7]); 00229 00230 COMTHROW(Append( buff)); 00231 } 00232 00233 void appendGuid( const BinGuid& p_guid) 00234 { 00235 GUID t_guid; 00236 p_guid.ConvertToStd( t_guid); 00237 00238 appendGuid( t_guid); 00239 } 00240 00241 void appendGuid( const UniqueId& p_uid) 00242 { 00243 appendGuid( p_uid.objectId); 00244 COMTHROW(Append( L" in library ")); 00245 appendGuid( p_uid.libId); 00246 } 00247 }; 00248 00249 // ****************************************************************************** 00250 // C L A S S Identifier 00251 // for getting identifying properties about object 00252 // 00253 class Identifier 00254 { 00255 public: 00256 static BinGuid getPersistentIdOf( const CoreObj& i) 00257 { 00258 return BinGuid( i[ATTRID_GUID1], i[ATTRID_GUID2], i[ATTRID_GUID3], i[ATTRID_GUID4]); 00259 } 00260 00261 static bool isRefreshableLibRoot( const CoreObj& i) 00262 { 00263 // only toplibs can be refreshed (the inner libraries can't) 00264 bool retv = false; 00265 retv = getTopLibRootOf( i) == getLibRootOf( i); 00266 00267 return retv; 00268 } 00269 00270 static bool isLibRoot( const CoreObj& i) 00271 { 00272 bool retv = false; 00273 long perm = i[ATTRID_PERMISSIONS]; 00274 ASSERT( perm & LIBROOT_FLAG); 00275 retv = (perm & LIBROOT_FLAG) != 0; 00276 00277 return retv; 00278 } 00279 00280 // gives back the uid of the realm (territory) 00281 // where the object uid is supposed to be unique 00282 static BinGuid getLibRootOf( const CoreObj& i) 00283 { 00284 CoreObj cur = i; 00285 00286 bool goon = true; 00287 while( goon) 00288 { 00289 //CComBSTR nm; 00290 //ObjForCore(cur)->get_Name( &nm); 00291 //nm.Append(";"); 00292 00293 long perm = cur[ATTRID_PERMISSIONS]; 00294 if( perm & LIBROOT_FLAG) 00295 return getPersistentIdOf( cur); 00296 00297 // commented because sometimes regular objects are 00298 // identified with these helper method: 00299 // [we must be in a library if LibRoot still not found] 00300 //ASSERT( perm & LIBRARY_FLAG); 00301 00302 // if no library element, nor libroot element, must be a regular project 00303 // element, so we consider these having a BinGuid(0) as their realm uid 00304 if( (perm & LIBRARY_FLAG) == 0) 00305 return BinGuid(); 00306 00307 metaid_type mt = cur.GetMetaID(); 00308 ASSERT( mt != DTID_ROOT); 00309 cur = cur[ATTRID_PARENT]; 00310 goon = cur != 0;// && ( mt != DTID_ROOT); 00311 } 00312 00313 return BinGuid(); 00314 } 00315 00316 // used for getting the uid of the topmost library (the one we 00317 // are refreshing now) in case of cascading libraries 00318 static BinGuid getTopLibRootOf( const CoreObj& i) 00319 { 00320 CoreObj cur = i; 00321 BinGuid lastgood; 00322 00323 bool goon = true; 00324 while( goon) 00325 { 00326 //CComBSTR nm; 00327 //ObjForCore(cur)->get_Name( &nm); 00328 //nm.Append(";"); 00329 00330 long perm = cur[ATTRID_PERMISSIONS]; 00331 00332 if( perm & LIBROOT_FLAG) 00333 lastgood = getPersistentIdOf( cur); 00334 00335 cur = cur[ATTRID_PARENT]; 00336 metaid_type mt = cur.GetMetaID(); 00337 //ASSERT( mt != DTID_ROOT); 00338 goon = cur != 0 && mt != DTID_ROOT; 00339 } 00340 00341 return lastgood; 00342 } 00343 00344 static UniqueId getDetailsOf( const CoreObj& i) 00345 { 00346 UniqueId uid; 00347 00348 uid.SetObj( getPersistentIdOf( i)); 00349 uid.SetLib( getLibRootOf( i)); 00350 00351 return uid; 00352 } 00353 00354 static UniqueId getDetailsOf( const CoreObj& i, BinGuid& pLibCursor) 00355 { 00356 UniqueId uid; 00357 00358 uid.SetObj( getPersistentIdOf( i)); 00359 ASSERT( pLibCursor != BinGuid()); 00360 uid.SetLib( pLibCursor); 00361 00362 return uid; 00363 } 00364 }; 00365 00366 // ****************************************************************************** 00367 // C L A S S Reporter 00368 // sends info and error messages to the console if feature run with GUI 00369 // 00370 class Reporter 00371 { 00372 protected: 00373 int m_counter; 00374 CComPtr<IGMEOLEApp> m_gme; 00375 00376 static CComPtr<IGMEOLEApp> get_GME( CMgaProject *p_mgaproject) 00377 { 00378 CComPtr<IGMEOLEApp> gme; 00379 if( p_mgaproject) { 00380 CComBSTR bstrName("GME.Application"); 00381 CComPtr<IMgaClient> pClient; 00382 HRESULT hr = p_mgaproject->GetClientByName(bstrName, &pClient); 00383 if (SUCCEEDED(hr) && pClient) { 00384 CComPtr<IDispatch> pDispatch; 00385 hr = pClient->get_OLEServer(&pDispatch); 00386 if (SUCCEEDED(hr) && pDispatch) { 00387 hr = pDispatch.QueryInterface(&gme); 00388 if (FAILED(hr)) { 00389 gme = NULL; 00390 } 00391 } 00392 } 00393 } 00394 return gme; 00395 } 00396 00397 public: 00398 00399 Reporter( CMgaProject *p_mgaproject) 00400 : m_counter( 0) 00401 { 00402 m_gme = get_GME( p_mgaproject); 00403 } 00404 00405 void show( CComBSTR msg, bool error = true ) 00406 { 00407 if( error) ++m_counter; 00408 if( m_gme) 00409 { 00410 COMTHROW(m_gme->ConsoleMessage( msg, error?MSG_ERROR:MSG_INFO)); 00411 } 00412 } 00413 00414 int getErrors() const 00415 { 00416 return m_counter; 00417 } 00418 00419 static void showIt( CMgaProject *p_mgaproject, CComBSTR msg, bool error = true ) 00420 { 00421 CComPtr<IGMEOLEApp> t_gme = get_GME( p_mgaproject); 00422 00423 if( t_gme) 00424 { 00425 COMTHROW(t_gme->ConsoleMessage( msg, error?MSG_ERROR:MSG_INFO)); 00426 } 00427 } 00428 }; 00429 00430 // ****************************************************************************** 00431 // C L A S S SearchTool 00432 // for searching project objects based on project id 00433 // and library objects based on uid 00434 // 00435 class SearchTool 00436 { 00437 public: 00438 //static std::list<BinGuid> m_sLibIdStack; // the search position is inside the topmost library right now 00439 static bool m_optimized; // if the current operation in progress is optimized? 00440 00441 static CComPtr<IMgaFCO> findLibObj(CoreObj& folder, const UniqueId& p_toFind, const BinGuid& p_inLib = BinGuid()) 00442 { 00443 BinGuid act_lib_cursor = p_inLib; 00444 long pm = folder[ATTRID_PERMISSIONS]; 00445 if( pm & LIBROOT_FLAG) 00446 { 00447 BinGuid act_lib_id = Identifier::getPersistentIdOf( folder); 00448 //m_sLibIdStack.push_back( act_lib_id); 00449 00450 act_lib_cursor = act_lib_id; 00451 } 00452 00453 //BinGuid lib_cursor; 00454 //ASSERT( !m_sLibIdStack.empty()); 00455 //if( !m_sLibIdStack.empty()) lib_cursor = m_sLibIdStack.back(); 00456 00457 ITERATE_THROUGH(folder[ATTRID_FCOPARENT+ATTRID_COLLECTION]) 00458 { 00459 if(ITER.IsFCO()) 00460 { 00461 //UniqueId iters_id = Identifier::getDetailsOf( ITER, lib_cursor); 00462 UniqueId iters_id = Identifier::getDetailsOf( ITER, act_lib_cursor); 00463 if( iters_id == p_toFind) 00464 //if( iters_guid == p_toFind.objectId) 00465 //if( ITER[ATTRID_GUID1] == p_toFind.v1 00466 // && ITER[ATTRID_GUID2] == p_toFind.v2 00467 // && ITER[ATTRID_GUID3] == p_toFind.v3 00468 // && ITER[ATTRID_GUID4] == p_toFind.v4) 00469 { 00470 CComPtr<IMgaFCO> fco; 00471 ObjForCore(ITER)->getinterface(&fco); 00472 return fco; // found 00473 } 00474 } 00475 00476 if( ITER.IsContainer()) 00477 { 00478 CComPtr<IMgaFCO> fco = findLibObj(ITER, p_toFind, act_lib_cursor); 00479 if( fco) return fco; // found 00480 } 00481 } 00482 if( pm & LIBROOT_FLAG) 00483 { 00484 //m_sLibIdStack.pop_back(); // pop the library id when finished with depth first search of this branch 00485 } 00486 00487 if( folder && m_optimized) // current operation in progress is optimized 00488 { 00489 CoreObj parnt = folder[ATTRID_FCOPARENT]; 00490 if( parnt && parnt.GetMetaID() == DTID_FOLDER) 00491 { 00492 // process further down if really the rootfolder is met 00493 CoreObj grandparnt = parnt[ ATTRID_FCOPARENT]; 00494 if( grandparnt && grandparnt.GetMetaID() == DTID_ROOT) 00495 { 00496 // check other toplevel libraries (some of them might be the virtually included one 00497 ITERATE_THROUGH( parnt[ ATTRID_FCOPARENT + ATTRID_COLLECTION]) 00498 { 00499 long prm = ITER[ATTRID_PERMISSIONS]; 00500 if( prm & LIBROOT_FLAG) 00501 { 00502 BinGuid act_lib_id = Identifier::getPersistentIdOf( ITER); 00503 if( p_toFind.libId == act_lib_id // proper toplevel library found 00504 && act_lib_id != act_lib_cursor) // is not the very same the search already has analyzed 00505 { 00506 CComPtr<IMgaFCO> fco = findLibObj( ITER, p_toFind); 00507 if( fco) return fco; // found 00508 } 00509 } 00510 00511 } 00512 } 00513 //findLibObj( parnt, p_toFind, 00514 } 00515 } 00516 return 0; 00517 } 00518 00519 static CComPtr<IMgaFCO> findObjWithDetails( CMgaProject *mgaproject, CoreObj& folder, elem_struct& elem) 00520 { 00521 if( elem.inverysamelib)//if( elem.inlib) 00522 return findLibObj( folder, elem.uid); 00523 else 00524 return findRegularObj( mgaproject, folder, elem.id); 00525 } 00526 00527 00528 static CComPtr<IMgaFCO> findRegularObj(CMgaProject * mgaproject, CoreObj& folder, const PROJ_ID& p_toFind) 00529 { 00530 CComPtr<IMgaFCO> res; 00531 try { 00532 COMTHROW( mgaproject->GetFCOByID( p_toFind, &res)); 00533 } catch( hresult_exception&) { 00534 res = CComPtr<IMgaFCO>(0); 00535 } 00536 return res; 00537 } 00538 00539 static CComPtr<IMgaFolder> findFolInHostProjectWithProjId(CMgaProject * mgaproject, CoreObj& folder, const PROJ_ID& p_toFind) 00540 { 00541 CComPtr<IMgaFolder> res; 00542 try { 00543 CComPtr<IMgaObject> ro; 00544 COMTHROW( mgaproject->GetObjectByID( p_toFind, &ro)); 00545 if( ro) COMTHROW( ro.QueryInterface( &res)); 00546 } catch( hresult_exception&) { 00547 res = CComPtr<IMgaFolder>(0); 00548 } 00549 return res; 00550 } 00551 00552 static CoreObj findLibrary( CoreObj& p_folder, BinGuid& p_libId) 00553 { 00554 long pm = p_folder[ATTRID_PERMISSIONS]; 00555 if( pm & LIBROOT_FLAG) 00556 { 00557 BinGuid act_lib_id = Identifier::getPersistentIdOf( p_folder); 00558 if( act_lib_id == p_libId) 00559 return p_folder; 00560 } 00561 00562 ITERATE_THROUGH( p_folder[ATTRID_FCOPARENT+ATTRID_COLLECTION]) 00563 { 00564 metaid_type mi = ITER.GetMetaID(); 00565 if( mi == DTID_FOLDER) 00566 { 00567 CoreObj lib = findLibrary( ITER, p_libId); 00568 if( lib) return lib; // found 00569 } 00570 } 00571 00572 return CoreObj(); 00573 } 00574 00575 static CoreObj findTopLibrary( CoreObj& p_folder, CComBSTR& p_libId) 00576 { 00577 ITERATE_THROUGH( p_folder[ATTRID_FCOPARENT+ATTRID_COLLECTION]) 00578 { 00579 metaid_type mi = ITER.GetMetaID(); 00580 long pm = ITER[ATTRID_PERMISSIONS]; 00581 if( mi == DTID_FOLDER && (pm & LIBROOT_FLAG)) 00582 { 00583 //BinGuid lib_id = Identifier::getPersistentIdOf( ITER); 00584 CComBSTR lib_id; 00585 ObjForCore( ITER)->GetGuidDisp( &lib_id); 00586 if( lib_id == p_libId) 00587 return ITER; 00588 } 00589 } 00590 00591 return CoreObj(); 00592 } 00593 00594 static bool findTopLibInProj( CMgaProject* p_mgaProject 00595 , const PROJ_ID& p_idOfLib 00596 , CoreObj& p_libObjCore) 00597 { 00598 bool all_right = false; 00599 00600 ASSERT( p_idOfLib.Length() == 16); // id like: "id-006a-00000002" 00601 00602 try 00603 { 00604 CComPtr<IMgaFolder> rf; 00605 p_mgaProject->get_RootFolder( &rf); 00606 CoreObj crf = CoreObj( rf); 00607 00608 ITERATE_THROUGH( crf[ ATTRID_FCOPARENT + ATTRID_COLLECTION]) 00609 { 00610 metaid_type mtyp = ITER.GetMetaID(); 00611 if( mtyp == DTID_FOLDER) 00612 { 00613 auto kid = ObjForCore( ITER); 00614 if( !kid) continue; 00615 00616 CComBSTR id; 00617 COMTHROW( kid->get_ID( &id)); 00618 00619 if( id == p_idOfLib // equal id 00620 && !ITER.IsDeleted() // not a zombie 00621 && ( ITER[ATTRID_PERMISSIONS] & LIBROOT_FLAG)) // a library root 00622 { 00623 p_libObjCore = ITER; 00624 all_right = true; 00625 break; 00626 } 00627 } 00628 } 00629 } 00630 catch( hresult_exception& ) 00631 { 00632 ASSERT(0); 00633 } 00634 00635 ASSERT( all_right); 00636 return all_right; 00637 } 00638 00639 00640 }; 00641 00642 00643 // ****************************************************************************** 00644 // C L A S S RefreshManager 00645 // for managing the refresh procedure 00646 // 00647 class RefreshManager 00648 { 00649 public: 00650 RefreshManager( CMgaProject *p_mgaproject, CoreObj& p_oldRoot, CoreObj& p_newRoot, bool p_isIncluded) 00651 : m_mgaproject( p_mgaproject) 00652 , m_newLib( p_newRoot) 00653 , m_oldLib( p_oldRoot) 00654 , m_reporter( p_mgaproject) 00655 , m_isVirtuallyIncluded( p_isIncluded) 00656 { 00657 } 00658 00659 protected: 00660 CMgaProject * m_mgaproject; 00661 CoreObj m_newLib; 00662 CoreObj m_oldLib; 00663 Reporter m_reporter; 00664 bool m_isVirtuallyIncluded; 00665 // for reference recreating 00666 //typedef std::vector< PROJ_ID > REFERENCES_VEC; 00667 //typedef std::map< UniqueId, REFERENCES_VEC > REFERENCES_MAP; // KEY: GUID of LibTarget, VALUE: vector of Reference ids, which need to be redirected to LibTarget 00668 typedef std::vector< CoreObj > CORE_REFERENCES_VEC; 00669 typedef std::map< UniqueId, CORE_REFERENCES_VEC > REFERENCES_MAP; // KEY: GUID of LibTarget, VALUE: vector of Reference ids, which need to be redirected to LibTarget 00670 REFERENCES_MAP mapOfReferences; 00671 00672 typedef std::pair< short, CoreObj> SORTED_REF_ELEM; 00673 00674 class RefComp 00675 { 00676 public: 00677 bool operator () ( const std::pair< short, CoreObj>& p1 00678 , const std::pair< short, CoreObj>& p2) const 00679 //bool operator < ( const SORTED_REF_ELEM& p1, const SORTED_REF_ELEM& p2) 00680 { 00681 if( p1.first < p2.first) return true; 00682 else if( p1.first > p2.first) return false; 00683 else return p1.second < p2.second; 00684 } 00685 }; 00686 00687 typedef std::set< SORTED_REF_ELEM, RefComp > CORE_REFERENCES_SET; // short: the distance from the topmost base 00688 // by using a pair as the key of the map we make sure that hierarchy 00689 // of reference is observed, the ones at the top will be set before those 00690 // at the bottom 00691 00692 typedef std::map< std::pair<short,UniqueId>, CORE_REFERENCES_SET > DEP_REFERENCES_MAP; 00693 DEP_REFERENCES_MAP mapOfDependentReferences; 00694 00695 typedef std::pair< UniqueId, UniqueId > LIBREF_AND_LIBTARGET; 00696 typedef std::pair< short, LIBREF_AND_LIBTARGET > LIB_REFTARG_PAIR; 00697 // if target is in library then UniqueId identifies it 00698 // otherwise the CoreObj is the target 00699 typedef std::pair< UniqueId, CoreObj > MIXED_TARGET; 00700 // CoreObj is the regular reference in the project, mixedtarget is its target 00701 typedef std::pair< CoreObj, MIXED_TARGET> REGREF_AND_TARGET; 00702 typedef std::vector< REGREF_AND_TARGET > CORE_DERD_REF_VEC; 00703 typedef std::map< LIB_REFTARG_PAIR, CORE_DERD_REF_VEC > ADAPTIVE_REFERENCES_MAP; 00704 00705 // will store adaptive refs (they must be knowledgable of the fact whether their base 00706 // was redirected or not, while they are not attached to them yet) 00707 ADAPTIVE_REFERENCES_MAP mapOfAdaptiveReferences; 00708 00709 typedef std::pair< short, CoreObj > DIST_AND_REFOBJ; 00710 typedef std::pair< UniqueId, CoreObj > MIXED_TARGET2; // these refs might point to the library or to the project 00711 typedef std::map< DIST_AND_REFOBJ, MIXED_TARGET2> SPECIAL_MAP; // Key: <levelOfRef, Ref>, Value: <TgtId, TgtObj> 00712 00713 // will store dependents of adaptive references (they must conform to the adaptive refs 00714 // while they ARE attached to them) 00715 SPECIAL_MAP mapOfDerdRefsFromAdaptiveRef; 00716 00717 // will prevent dependents of changed (redirected in library) refs 00718 // to be restored according to the pre-refresh database 00719 std::set< CoreObj> m_alreadySetRefs; 00720 00721 // for subtype recreating 00722 struct SUB_PAR 00723 { 00724 CComPtr<IMgaFCO> subt_ptr; 00725 #if(0) 00726 PROJ_ID subt_id; // is this needed at all? YES ! if Detach/Attach procedure is used definitely 00727 PROJ_ID subt_parent; //obsolete: // these are NOT needed since Detach/Attach //CComBSTR subt_parent; // where to recreate the subtype? 00728 CComBSTR subt_metarole; //obsolete: // these are NOT needed since Detach/Attach 00729 bool parentIsFolder;//obsolete: // these are NOT needed since Detach/Attach 00730 #endif 00731 bool is_instance; 00732 }; 00733 00734 typedef std::vector< SUB_PAR > SUB_PAR_VEC; 00735 typedef std::map< UniqueId, SUB_PAR_VEC > SUB_PAR_MAP; // KEY: GUID of LibBase, VALUE: vector of subtype related info, which need to be recreated/rederived from LibBase 00736 SUB_PAR_MAP mapOfDeriveds; 00737 #if(DONT_OPTIMIZE) 00738 typedef std::map< PROJ_ID, UniqueId > SEC_DER_MAP; // KEY: ID in secondary derived object, VALUE: GUID of base in library 00739 SEC_DER_MAP mapOfSecondaryDeriveds; 00740 #endif 00741 typedef std::map< CComPtr<IMgaFCO>, UniqueId > SEC_DER_NAP; 00742 SEC_DER_NAP napOfSecondaryDeriveds; 00743 00744 00745 typedef std::map< CoreObj, std::pair< CoreObj, bool > > PRI_MATCHMAKER_MAP; // KEY: DERD Obj, VALUE: pair of <BASE, is_instance> 00746 PRI_MATCHMAKER_MAP m_primMatchMaker; // holds only the primary deriveds 00747 00748 typedef std::map< CoreObj, CoreObj > CORE_MATCH_MAP; 00749 CORE_MATCH_MAP m_coreMatchMaker; // holds both primary and secondary deriveds 00750 #if(DONT_OPTIMIZE) 00751 // OBSOLETE: 00752 std::map< PROJ_ID, PROJ_ID> m_matchMaker; // map of ids already matched objects 00753 // prevents assigning the same 00754 // base to two different objects 00755 #endif 00756 00757 // 00758 // for connection recreating 00759 typedef std::vector< elem_struct > CHAIN_VEC; 00760 struct conndetails_struct 00761 { 00762 elem_struct end; 00763 CHAIN_VEC chain; 00764 }; 00765 00766 struct connEnds_struct 00767 { 00768 conndetails_struct src; 00769 conndetails_struct dst; 00770 elem_struct parent_model; 00771 CComBSTR role; 00772 PROJ_ID connid;//will prevent loopnode duplication 00773 CComBSTR connname; 00774 bool is_derived; 00775 int is_sec_derived; 00776 bool is_instance; 00777 bool baseConnInLib; 00778 UniqueId baseConnId; 00779 CComBSTR guid; 00780 CoreObj saver; // will save owned Attributes, Regnodes & Constraints 00781 }; 00782 00783 typedef std::vector< connEnds_struct > CONN_STORAGE; 00784 CONN_STORAGE conns_stored; 00785 00786 00787 #if(DONT_OPTIMIZE) 00788 struct connEnds_struct2 00789 { 00790 CComPtr<IMgaFCO> src; 00791 CComPtr<IMgaFCO> dst; 00792 CComPtr<IMgaFCOs> srcRefs; 00793 CComPtr<IMgaFCOs> dstRefs; 00794 CComPtr<IMgaModel> par; 00795 CComPtr<IMgaMetaRole> mrole; 00796 CComBSTR nm; 00797 CComBSTR guid; 00798 }; 00799 typedef std::vector< connEnds_struct2 > CONN_STORAGE2; 00800 CONN_STORAGE2 conns_to_recreate; 00801 #endif 00802 struct derConnEnds_struct 00803 { 00804 CComPtr<IMgaModel> base_parent; 00805 CComPtr<IMgaModel> derd_parent; 00806 CComPtr<IMgaConnection> b_conn; // the base connection (new connection found in library) 00807 CComPtr<IMgaMetaRole> b_conn_role; 00808 connEnds_struct b_conn_struct; 00809 00810 CComPtr<IMgaFCO> src; 00811 CComPtr<IMgaFCO> dst; 00812 CComPtr<IMgaFCOs> srcRefs; 00813 CComPtr<IMgaFCOs> dstRefs; 00814 CComBSTR nm; 00815 }; 00816 00817 typedef std::vector< derConnEnds_struct > DERCONN_STORAGE; 00818 DERCONN_STORAGE conns_to_derive; // new connections found in base which must be derived into derd 00819 00820 struct HasThisConn // unary predicate, to search for a connection in the vector based on ID 00821 { 00822 HasThisConn( const PROJ_ID& id_to_store) : m_id( id_to_store) { } 00823 bool operator () (connEnds_struct& peer) { return peer.connid == m_id; } 00824 private: 00825 PROJ_ID m_id; 00826 }; 00827 00828 struct OldConn // unary predicate, to decide whether existed connections that were derived from p_uid 00829 { 00830 OldConn( const UniqueId& p_uid) : m_uid( p_uid) { } 00831 bool operator () ( connEnds_struct& peer) { return peer.baseConnId == m_uid; } 00832 private: 00833 UniqueId m_uid; 00834 }; 00835 00836 // 00837 // for recreating connection memberships in sets 00838 typedef std::vector< PROJ_ID> PIDVECTOR; 00839 typedef std::map< PROJ_ID, PIDVECTOR > MEMBERMAP; 00840 MEMBERMAP m_mapOfMemberships; 00841 00842 00843 std::list<BinGuid> lib_stack;// this stack maintains the library root's guid 00844 // imagine that a library may contain inner libraries 00845 // and during dependency storage (collectDependencies) 00846 // we have to know which library contains the element 00847 // whose guid we are storing 00848 // 00849 // element guids are not unique globally 00850 // <project_guid, element_guid> pair is unique 00851 // TODO: this project guid changes every time the project 00852 // is modified (?) 00853 std::vector<PROJ_ID> m_changedLibs; 00854 void addChangedLib( elem_struct& elem); 00855 // -----------------------------COLLECTORS & RESTORERS---------------------------- 00856 void reapplyLibFlagToChangedLibs(); 00857 void applyLibFlag( CoreObj& p_libObj); 00858 00859 void DetachObjFromLibBase( const CoreObj& baseObj, CoreObj& derdObj, unsigned long nextrelid, bool prim); 00860 void AttachDerObjs( const CoreObj& baseObj, CoreObj& derdObj, long instance, bool prim); 00861 00862 // cuts or detaches libraryderived objects 00863 void cutDersFromLib( CoreObj& one_fco); 00864 // does the final reattachment of derived objects 00865 // to the refreshed base objects (found in the library) 00866 void reattachSubtypesInstances();// CoreObj& ofolder, CoreObj& nfolder); 00867 00868 // -after the cut we decrease relids to seem consistent 00869 // (to be consistent with the changed hierarchy) 00870 // -after the reattach we increase relids to be consistent 00871 // with the actual restored hierarchy 00872 void propObjRelidIncV2( CoreObj& orig); 00873 00874 // aggregates objects in the project which are 00875 // derived from library objects 00876 void saveTopAdaptiveRef( CoreObj& one_ref, CoreObj& bas_ref); 00877 void saveDerAdaptiveRef( CoreObj& one_ref); 00878 00879 void collectRefsDerdFromLib( CoreObj& one_ref, CoreObj& bas_ref); 00880 void collectDersFromLib ( CoreObj& one_fco); 00881 void syncStructureFromLib(); 00882 00883 // propagates any change in the base object 00884 // into subtypes aggregated by collectDersFromLib 00885 void SyncDerObjs( const CoreObj &freshMasterObj, CoreObj &adaptiveObj, long instance, bool prim, const CoreObj &priMasterObj, const CoreObj &priAdaptiveObj); 00886 void SyncObjectName( const CoreObj& p_masterObj, CoreObj &p_adaptiveObj); 00887 void SyncDerSets( const CoreObj &freshMasterSet, CoreObj &adaptiveSet, const CoreObj &freshMasterPar, CoreObj &adaptivePar); 00888 void SyncDerRefs( const CoreObj &freshMasterRef, CoreObj &adaptiveRef, const CoreObj &priFreshMasterPar, const CoreObj &priAdaptivePar); 00889 00890 00891 // aggregates references which are in the project 00892 // and are directed towards the library 00893 void collectRefsToLib( CoreObj& one_fco); 00894 void restoreRefsToLib(); 00895 00896 // adapts library derived refs to the new situation 00897 void adaptTopRefs(); 00898 void adaptDerRefs(); 00899 00900 // a mixed connection is an archetype connection in the project 00901 // (it is not a secondary derived connection) 00902 void collectMixedConns( CoreObj& one_fco); 00903 void restoreMixedConns( CoreObj& folder); 00904 00905 // a fresh connection is a newly appeared connection in a library base object 00906 // which needs to be propagated down into the derived objects in the project 00907 // so it will become secondary derived 00908 void collectFreshConnection( const CoreObj& p_coreConn, const CoreObj& p_base, const CoreObj& p_derd); 00909 void syncFreshConns();// CoreObj& ofolder, CoreObj& nfolder); 00910 00911 void collectMembershipOfConn( const CComPtr<IMgaConnection>& p_conn, const connEnds_struct& conn_info); 00912 void restoreMembership( const CComPtr<IMgaFCO>& p_conn, connEnds_struct& conn_info, const CComPtr<IMgaModel>& parent); 00913 00914 00915 // ----------------------------------HELPERS--------------------------------------- 00916 00917 void getElemDetails( CComPtr<IMgaFCO>& peer, elem_struct& elem); 00918 void getElemDetails( CoreObj& peer, elem_struct& elem); 00919 00920 short distance( CoreObj& derd); 00921 bool isDerivedRef( CComPtr<IMgaFCO>& p_ref, CComPtr<IMgaFCO>& p_tgt, bool *p_fromLib, bool *p_isRedirected, bool *p_isSecondaryDerd); 00922 bool isSecondaryDerivedRef( CComPtr<IMgaFCO>& p_ref, CComPtr<IMgaFCO>& p_tgt, bool* p_fromLib); 00923 bool isSecondaryDerivedRefFromLibraryObj( CComPtr<IMgaFCO>& ref, bool *p_pbIsRedirected); 00924 00925 bool ignoreFurtherRedir ( CComPtr<IMgaReference>& orig, CComPtr<IMgaFCO>& ref_tgt_newlib); 00926 // todo: convert to CoreObj parameters 00927 bool redirectRefWithCare( CComPtr<IMgaReference>& orig, CComPtr<IMgaFCO>& ref_tgt_newlib); 00928 00929 void saveConnection( const CComPtr<IMgaFCO>& p_cn); 00930 void restoreDeletedConns( CoreObj& nfolder); 00931 void getConnPointDetails( CComPtr<IMgaConnPoint>& cp, conndetails_struct& det, bool* p_ptrIsDestination); 00932 void getConnectionDetails ( CComPtr<IMgaConnection>& owner, connEnds_struct& one_conn); 00933 00934 void findAmongNecDerd( UniqueId& p_uid, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& res); 00935 void findAmongSecDerd( UniqueId& p_uid, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& res); 00936 void findAmongPriDerd( UniqueId& p_uid, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& res); 00937 void findAmongContained( const CComPtr<IMgaModel>& d_par, const PROJ_ID& p_id, CComPtr<IMgaFCO>& res); 00938 bool isInside( const CComPtr<IMgaModel>& d_par, const CComPtr<IMgaFCO>& res); 00939 00940 void askTheMatchMaker( const CComPtr<IMgaFCO>& end, const CComPtr<IMgaModel>& b_par, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& n_end, bool checkParentHood); 00941 void getLibDerdEquiv( const CComPtr<IMgaFCO>& end, const CComPtr<IMgaModel>& b_par, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& n_end, bool checkParentHood = true); 00942 00943 void removeObsoleteChildren( const CoreObj& masterObj, CoreObj& adaptiveobj); 00944 void updateMatchDb( coreobjpairhash& p_creaList); 00945 // copy a fresh container into the whole subtype tree 00946 typedef std::vector< std::pair< CoreObj, CoreObj> > SET_CREALIST; 00947 typedef std::vector< std::pair< CoreObj, CoreObj> > REF_CREALIST; 00948 void copyNewArrivals( CoreObj& adaptiveobj, std::vector< CoreObj> & newcomers 00949 , SET_CREALIST& set_crealist, REF_CREALIST& ref_crealist); 00950 00951 // for mixed connection recreation 00952 bool buildRefChainColl( CMgaProject *mgaproject, CoreObj& folder, CHAIN_VEC& p_chain, CComPtr<IMgaFCOs>& p_sref_chain); 00953 bool followRefChain( const CComPtr<IMgaFCOs>& chain, CComPtr<IMgaModel>& final_m); 00954 00955 // for storing previously owned properties of mixed connections 00956 void loadSavedStuff( CComPtr<IMgaFCO>& p_nConn, connEnds_struct& p_one_conn); 00957 void saveOwnedStuff( CComPtr<IMgaConnection>& owner, connEnds_struct& one_conn); 00958 00959 // for fresh connection recreation 00960 CComPtr<IMgaModel> nextContainer( CComPtr<IMgaFCO>& ref); 00961 CComPtr<IMgaFCO> nextElem( CComPtr<IMgaFCO>& p_ref); 00962 00963 bool verifyChain( const CComPtr<IMgaModel>& pM 00964 , const CComPtr<IMgaFCOs>& sref_chain, const CComPtr<IMgaFCO>& s); 00965 00966 bool findConnEndPeer( const derConnEnds_struct& c_info 00967 , const CComPtr<IMgaFCOs>& p_origChain, const CComPtr<IMgaFCO>& p_origConnEnd 00968 , CComPtr<IMgaFCOs>& p_peerChain, CComPtr<IMgaFCO>& p_peerConnEnd); 00969 00970 bool fillConnectionPtrs( const derConnEnds_struct& c_info 00971 , CComPtr<IMgaFCO>& s, CComPtr<IMgaFCO>& d 00972 , CComPtr<IMgaFCOs>& s_chain, CComPtr<IMgaFCOs>& d_chain); 00973 00974 // for both 00975 void prepareConnErrMsg( const CComPtr<IMgaModel>& pM 00976 , const CComPtr<IMgaFCO>& s, const CComPtr<IMgaFCO>& d 00977 , const CComPtr<IMgaFCOs>& sref_chain, const CComPtr<IMgaFCOs>& dref_chain 00978 , const connEnds_struct& current_i, MyCComBSTR& msg); 00979 00980 public: 00981 void collectDependencies( CoreObj& p_container); 00982 void cutRelations( CoreObj& container); 00983 void restoreDependencies(); 00984 void clearDepStorage(); 00985 int getNumOfErrors( MyCComBSTR& msg); 00986 }; 00987 00988 class Creator 00989 { 00990 public: 00991 static const CComBSTR SrcName; // keep in sync with FCO::SrcName in MgaConnection.cpp 00992 static const CComBSTR DstName; // keep in sync with FCO::DstName 00993 00994 static HRESULT SimpleConn( CComPtr<IMgaModel>& p_parent 00995 , CComPtr<IMgaMetaRole>& p_mrole 00996 , CComPtr<IMgaFCO>& p_src 00997 , CComPtr<IMgaFCO>& p_dst 00998 , CComPtr<IMgaFCOs>& p_srcRefs 00999 , CComPtr<IMgaFCOs>& p_dstRefs 01000 , CMgaProject* p_mgaProject 01001 , IMgaFCO** p_newConn); 01002 01003 private: 01004 static HRESULT Child ( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_parent, CComPtr<IMgaMetaRole>& metar, IMgaFCO **newobj); 01005 01006 static HRESULT put_NamedRole ( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_conn, BSTR p_rolename, IMgaFCOs* p_refs, IMgaFCO* p_endfco); 01007 static HRESULT AddConnPoint ( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_conn, BSTR p_rolename, long p_maxinrole, IMgaFCO* p_target, IMgaFCOs* p_refs, IMgaConnPoint** pVal); 01008 }; 01009 01010 class Worker 01011 { 01012 public: 01013 static HRESULT put_Name ( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_elem, CComBSTR p_newVal); 01014 static HRESULT PutGuidDisp ( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_elem, CComBSTR p_guidStr); 01015 private: 01016 static HRESULT PutGuid ( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_elem, long l1, long l2, long l3, long l4); 01017 }; 01018 01019 #endif