GME  13
MgaLibRefr.h
Go to the documentation of this file.
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