GME  13
MgaLibRefr.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "MgaLibRefr.h"
00003 #include "MgaLibOps.h"
00004 #include "MgaComplexOps.h"
00005 #include "MgaConnection.h"
00006 
00007 #ifdef max
00008 #undef max
00009 #endif
00010 
00011 #define DONT_OPTIM              0
00012 // defined in MgaLibOps.cpp
00013 void steal(CoreObj &o, CoreObj &n, attrid_type ai);
00014 
00015 /*static*/
00016 bool SearchTool::m_optimized = false;
00017 
00018 short RefreshManager::distance( CoreObj& derd)
00019 {
00020         short res = 0;
00021         CoreObj cur = derd;
00022         bool goon = true;
00023         while( goon)
00024         {
00025                 CoreObj nxt = cur[ATTRID_DERIVED];
00026                 if( nxt && nxt.IsFCO())
00027                 {
00028                         ++res;
00029                         cur = nxt;
00030                 }
00031                 else
00032                         goon = false;
00033         }
00034 
00035         return res;
00036 }
00037 
00038 void RefreshManager::getElemDetails( CComPtr<IMgaFCO>& peer, elem_struct& elem)
00039 {
00040         VARIANT_BOOL in_lib;
00041         COMTHROW( peer->get_IsLibObject( &in_lib));
00042         bool in_refrd_lib = false; // in the refreshed lib exactly?
00043         if( in_lib == VARIANT_TRUE)
00044         {
00045                 BinGuid libgd1, libgd2;
00046                 libgd1 = Identifier::getTopLibRootOf( CoreObj( peer));
00047                 libgd2 = Identifier::getTopLibRootOf( m_oldLib);
00048                 in_refrd_lib = libgd1 == libgd2;
00049         }
00050 
00051         // if m_oldlib is virtually included there might be dependent elements (like subtypes)
00052         // in other libraries (a previous container library)
00053         // from the Refresh's perspective those elements are fixed elements (can be found based on ID)
00054         // and are not found by the SearchTool methods which look down from a given container element
00055         // usually the new version of the refreshed library: m_newLib
00056         // these libraries can be refreshed either with or without the optimized flag (that's why we
00057         // rely on m_isIncluded rather than on SearchTool::m_optimized
00058 
00059         // if optimized then additional conditions apply
00060         // if !optimized then in_lib is enough
00061         if( in_lib == VARIANT_TRUE && !m_isVirtuallyIncluded 
00062                 || in_refrd_lib        &&  m_isVirtuallyIncluded) // has guid, other things will change
00063         {
00064                 CoreObj cp( peer);
00065                 
00066                 elem.uid = Identifier::getDetailsOf( cp);
00067                 elem.inverysamelib = true;//elem.inlib = true;
00068                 elem.inanotherlib  = false;
00069         }
00070         else // in project, must not have guid
00071         {
00072                 PROJ_ID id;
00073                 COMTHROW( peer->get_ID( &id));
00074                 elem.id = id;
00075                 elem.inverysamelib = false;//elem.inlib = false;
00076                 elem.inanotherlib  = in_lib == VARIANT_TRUE;
00077         }
00078 }
00079 
00080 void RefreshManager::getElemDetails( CoreObj& peer, elem_struct& elem)
00081 {
00082         VARIANT_BOOL in_lib;
00083         COMTHROW( ObjForCore(peer)->get_IsLibObject( &in_lib));
00084         bool in_refrd_lib = false; // in the refreshed lib exactly?
00085         if( in_lib == VARIANT_TRUE)
00086         {
00087                 BinGuid libgd1, libgd2;
00088                 libgd1 = Identifier::getTopLibRootOf( peer);
00089                 libgd2 = Identifier::getTopLibRootOf( m_oldLib);
00090                 in_refrd_lib = libgd1 == libgd2;
00091         }
00092 
00093         // if optimized then additional conditions apply
00094         // if !optimized then in_lib is enough
00095         if( in_lib == VARIANT_TRUE && !m_isVirtuallyIncluded 
00096                 || in_refrd_lib        &&  m_isVirtuallyIncluded) // has guid, other things will change
00097         {
00098                 elem.uid = Identifier::getDetailsOf( peer);
00099                 elem.inverysamelib = true;//elem.inlib = true;
00100                 elem.inanotherlib  = false;
00101         }
00102         else // in project, must not have guid
00103         {
00104                 PROJ_ID id;
00105                 COMTHROW( ObjForCore(peer)->get_ID( &id));
00106                 elem.id = id;
00107                 elem.inverysamelib = false;//elem.inlib = false;
00108                 elem.inanotherlib  = in_lib == VARIANT_TRUE;
00109         }
00110 }
00111 
00112 bool RefreshManager::isDerivedRef( CComPtr<IMgaFCO>& p_ref, CComPtr<IMgaFCO>& p_tgt
00113                                                                   , bool *p_derdFromTheSameLib, bool *p_isRedirected
00114                                                                   , bool *p_isSecondaryDerd)
00115 {
00116         bool retv = false;
00117         CComQIPtr<IMgaReference> ref( p_ref);
00118 
00119         ASSERT(ref);
00120         if( !ref) return retv;
00121 
00122         ASSERT( p_derdFromTheSameLib);
00123         ASSERT( p_isRedirected);
00124         *p_derdFromTheSameLib = false;
00125         *p_isRedirected       = false;
00126         *p_isSecondaryDerd    = false;
00127 
00128         CComPtr<IMgaFCO> base;
00129         ref->get_DerivedFrom( &base); // ignore failure
00130 
00131         if( base)
00132         {
00133                 VARIANT_BOOL prim;
00134                 COMTHROW( ref->get_IsPrimaryDerived( &prim));
00135                 *p_isSecondaryDerd = prim == VARIANT_FALSE; // secondary derd
00136 
00137                 retv = true;
00138                 elem_struct elem_base;
00139                 getElemDetails( base, elem_base);
00140 
00141                 //if( elem_base.inlib 
00142                 if( elem_base.inverysamelib // TODO?
00143                  && Identifier::getTopLibRootOf( CoreObj( p_tgt)) == Identifier::getTopLibRootOf( CoreObj(base)))
00144                         *p_derdFromTheSameLib = true; // sec.derd ref from the same library as its target
00145 
00146                 // decide whether is redirected
00147                 CComQIPtr<IMgaReference> derdRef( ref), baseRef( base);
00148                 if( !derdRef || !baseRef) { ASSERT( 0); return retv; }
00149 
00150                 /*CComPtr<IMgaFCO> derdTarg, baseTarg;
00151                 COMTHROW( derdRef->get_Referred( &derdTarg));
00152                 COMTHROW( baseRef->get_Referred( &baseTarg));*/
00153                 
00154                 CComBSTR nm;
00155                 COMTHROW(derdRef->get_Name( &nm));
00156                 short st;
00157                 COMTHROW(derdRef->CompareToBase( &st));
00158                 /*bool x = COM_EQUAL( baseTarg, derdTarg);
00159                 ASSERT( x == (st==0));
00160                 if(x != (st==0))
00161                         m_reporter.show( MyCComBSTR( nm));*/
00162 
00163                 if( st != 0)
00164                 {
00165                         // the only scenario this can happen is when the library contains baseTarg
00166                         // and derdTarg as well
00167                         *p_isRedirected = true;
00168                 }
00169                 // else: no more needed than the default action (derivation will make sure the derdRef will point to baseTarg)
00170 
00171 
00172                 // the topmost base counts, so if the topmost base is in the library we consider it
00173                 // lib derived
00174                 if( *p_derdFromTheSameLib == false)
00175                 {
00176                         CComPtr<IMgaFCO> topmost_base = base;
00177                         bool stop = false;
00178                         while( !stop)
00179                         {
00180                                 CComPtr<IMgaFCO> nxt_base;
00181                                 COMTHROW( topmost_base->get_DerivedFrom( &nxt_base));
00182                                 if( nxt_base)
00183                                         topmost_base = nxt_base;
00184                                 else
00185                                         stop = true;
00186                         }
00187 
00188                         elem_struct elem_topbase;
00189                         getElemDetails( topmost_base, elem_topbase);
00190 
00191                         //if( elem_topbase.inlib 
00192                         if( elem_topbase.inverysamelib // TODO?
00193                         && Identifier::getTopLibRootOf( CoreObj( p_tgt)) == Identifier::getTopLibRootOf( CoreObj( topmost_base)))
00194                                 *p_derdFromTheSameLib = true; // actually derd ref from the same library as its target
00195                 }
00196         }
00197 
00198         return retv;
00199 }
00200 
00201 void RefreshManager::saveOwnedStuff( CComPtr<IMgaConnection>& p_owner, connEnds_struct& p_one_conn)
00202 {
00203         CoreObj owner( p_owner);
00204         ASSERT(!p_one_conn.saver);
00205         COMTHROW(m_mgaproject->dataproject->CreateObject( GetMetaID(owner), &p_one_conn.saver.ComPtr()));
00206 
00207         steal( owner, p_one_conn.saver, ATTRID_ATTRPARENT);
00208         steal( owner, p_one_conn.saver, ATTRID_CONSTROWNER);
00209 }
00210 
00211 void RefreshManager::loadSavedStuff( CComPtr<IMgaFCO>& p_nConn, connEnds_struct& p_one_conn)
00212 {
00213         CoreObj inheritor( p_nConn);
00214         steal( p_one_conn.saver, inheritor, ATTRID_ATTRPARENT);
00215         steal( p_one_conn.saver, inheritor, ATTRID_CONSTROWNER);
00216 
00217         SingleObjTreeDelete( p_one_conn.saver, true);
00218 }
00219 
00220 void RefreshManager::getConnPointDetails( CComPtr<IMgaConnPoint>& cp, conndetails_struct& det, bool* p_ptrIsDestination)
00221 {
00222         CComPtr<IMgaFCO> peer;
00223         COMTHROW( cp->get_Target( &peer));
00224 
00225         CComBSTR role;
00226         COMTHROW( cp->get_ConnRole( &role));
00227         if( role == "dst")
00228                 *p_ptrIsDestination = true;
00229         else
00230                 *p_ptrIsDestination = false;
00231 
00232         getElemDetails( peer, det.end);
00233 
00234         CComPtr<IMgaFCOs> refs;
00235         COMTHROW( cp->get_References( &refs));
00236         long l;
00237         COMTHROW( refs->get_Count( &l));
00238         for( long i = 1; i <= l; ++i)
00239         {
00240                 CComPtr<IMgaFCO> ref;
00241                 COMTHROW( refs->get_Item( i, &ref));
00242 
00243                 elem_struct chain_elem;
00244                 getElemDetails( ref, chain_elem);
00245 
00246                 det.chain.push_back( chain_elem);
00247         }
00248 }
00249 
00250 void RefreshManager::getConnectionDetails( CComPtr<IMgaConnection>& owner, connEnds_struct& one_conn)
00251 {
00252         saveOwnedStuff( owner, one_conn);
00253         // the connection's info stored in: one_conn
00254                                 
00255         // fill the conn id field, will help prevent duplicating loop connections
00256         COMTHROW( owner->get_ID( &one_conn.connid)); 
00257         COMTHROW( owner->get_Name( &one_conn.connname));
00258         COMTHROW( owner->GetGuidDisp( &one_conn.guid));
00259 
00260         CComPtr<IMgaModel> parentM;
00261         COMTHROW( owner->get_ParentModel( &parentM));
00262         CComPtr<IMgaFCO> parent = parentM;
00263         // fill the parent field
00264         getElemDetails( parent, one_conn.parent_model);
00265 
00266         one_conn.is_derived = one_conn.is_instance = false;
00267         one_conn.is_sec_derived = 0;
00268 
00269         // is it derived?
00270         CComPtr<IMgaFCO> arch;
00271         COMTHROW( owner->get_DerivedFrom( &arch));
00272         one_conn.is_derived = arch != 0;
00273         
00274         if( one_conn.is_derived)
00275         {
00276                 one_conn.baseConnInLib = false;
00277                 elem_struct arch_info;
00278                 getElemDetails( arch, arch_info);
00279                 if( arch_info.inverysamelib) // TODO? //if( arch_info.inlib) // the connection's basetype is in the library
00280                 {
00281                         one_conn.baseConnId    = arch_info.uid;
00282                         one_conn.baseConnInLib = true;
00283                 }
00284         }
00285 
00286         // is it instance?
00287         VARIANT_BOOL is_inst;
00288         COMTHROW( owner->get_IsInstance( &is_inst));
00289         one_conn.is_instance = is_inst == VARIANT_TRUE;
00290 
00291         // is it sec derived?
00292         VARIANT_BOOL is_prim;
00293         COMTHROW( owner->get_IsPrimaryDerived( &is_prim));
00294         one_conn.is_sec_derived = is_prim == VARIANT_FALSE?1:0;
00295 
00296         CComPtr<IMgaMetaRole> mrole;
00297         COMTHROW( owner->get_MetaRole( &mrole));
00298         // fill the role field the connection is inserted into its parent
00299         COMTHROW( mrole->get_Name( &one_conn.role));
00300 
00301         CComPtr<IMgaConnPoints> connected;
00302         COMTHROW( owner->get_ConnPoints( &connected));
00303         long lc;
00304         COMTHROW( connected->get_Count( &lc));
00305         for( long i = 1; i <= lc; ++i)
00306         {
00307                 CComPtr<IMgaConnPoint> conn_peer;
00308                 COMTHROW( connected->get_Item( i, &conn_peer));
00309                 // if the connection point is different from the originating one, that we started from
00310                 //if( conn_peer == cp)
00311                 //{
00312                 //}
00313 
00314                 conndetails_struct cdd;
00315                 bool isDestination;
00316                 getConnPointDetails( conn_peer, cdd, &isDestination);
00317                 if( isDestination)
00318                         one_conn.dst = cdd;
00319                 else
00320                         one_conn.src = cdd;
00321         }
00322 }
00323 
00324 void RefreshManager::addChangedLib( elem_struct& elem)
00325 {
00326         if( !elem.inanotherlib) return;
00327 
00328         if( m_changedLibs.end() == std::find( m_changedLibs.begin(), m_changedLibs.end(), elem.id))
00329                 m_changedLibs.push_back( elem.id);
00330 }
00331 
00332 void RefreshManager::collectMixedConns( CoreObj& one_fco)
00333 {
00334         auto obj = ObjForCore(one_fco);
00335         if( obj)
00336         {
00337                 CComPtr<IMgaConnPoints> cps1;
00338                 COMTHROW( obj->get_PartOfConns( &cps1));
00339                 long l1;
00340                 COMTHROW( cps1->get_Count( &l1));
00341                 // for all my connection points
00342                 for( long i = 1; i <= l1; ++i)
00343                 {
00344                         CComPtr<IMgaConnPoint> cp;
00345                         COMTHROW( cps1->get_Item( i, &cp));
00346 
00347                         // the connection itself
00348                         CComPtr<IMgaConnection> owner;
00349                         COMTHROW( cp->get_Owner( &owner));
00350 
00351                         VARIANT_BOOL in_lib;
00352                         COMTHROW( owner->get_IsLibObject( &in_lib));
00353                         
00354                         elem_struct elem_conn;
00355                         getElemDetails( CComQIPtr<IMgaFCO>( owner), elem_conn);
00356                         /*if( in_lib == VARIANT_TRUE && elem_conn.inlib) // which lib? it matters!
00357                         {
00358                                 if( elem_conn.uid.libId == Identifier::getLibRootOf( one_fco)
00359                                         || elem_conn.uid.libId == Identifier::getTopLibRootOf( one_fco)
00360                                         )
00361                                         continue;
00362                                 else
00363                                         if( m_changedLibs.end() == std::find( m_changedLibs.begin(), m_changedLibs.end(), elem_conn.uid.libId))
00364                                                 m_changedLibs.push_back( elem_conn.uid.libId);
00365                         }*/
00366 
00367                         /*if( in_lib == VARIANT_TRUE) // the connection also in the library
00368                                 continue;*/
00369                         if( elem_conn.inverysamelib)
00370                                 continue;
00371                         //WAS// 
00372                         //else if( elem_conn.inanotherlib)
00373                         //      addChangedLib( elem_conn);
00374 
00375                         CComPtr<IMgaFCO> myself;
00376                         COMTHROW( cp->get_Target( &myself));
00377                         //ASSERT( myself == obj);
00378 
00379                         // the connection's info stored in:
00380                         connEnds_struct one_conn;
00381                         getConnectionDetails( owner, one_conn);
00382 
00383                         // if sec derived from a project conn (non library conn)
00384                         // then no need to store it, since its base will be recreated
00385                         // and then the change propagated down into this place
00386                         if( one_conn.is_derived && one_conn.is_sec_derived)
00387                         {
00388                                 if( one_conn.baseConnId.libId != Identifier::getLibRootOf( one_fco)
00389                                         || one_conn.baseConnId.libId != Identifier::getTopLibRootOf( one_fco)
00390                                         ) // which lib? it matters!
00391                                         continue;
00392                         }
00393                         /*if( one_conn.is_derived && one_conn.is_sec_derived && !one_conn.baseConnInLib)
00394                                 continue;*/
00395 
00396                         // even a sec-derd connection from library needs to be stored
00397                         // because it needs to be deleted while the reference involved
00398                         // is redirected, thus later needs restoration
00399 
00400                         // examine if this connection has already been inserted into the vector
00401                         if( conns_stored.end() == std::find_if( conns_stored.begin(), conns_stored.end(), HasThisConn(one_conn.connid))) // not found
00402                                 conns_stored.push_back( one_conn);
00403 
00404                         // store the sets the connections is member of
00405                         // because these connection might get deleted
00406                         // their membership needs storage
00407                         collectMembershipOfConn( owner, one_conn);
00408                 }
00409         }
00410 }
00411 
00412 
00413 // input: a connection in a base, which needs to be propagated down later into derd
00414 // p_base: a fresh base which contains p_coreConn as a new connection
00415 // p_derd: an object detached from a previous version of base
00416 void RefreshManager::collectFreshConnection( const CoreObj& p_coreConn
00417                                            , const CoreObj& p_base, const CoreObj& p_derd)
00418 {
00419         CComPtr<IMgaFCO> fco;
00420         auto c = ObjForCore( p_coreConn);
00421         if( c) c->getinterface( &fco);
00422         CComQIPtr<IMgaConnection> conn( fco);
00423 
00424         CComPtr<IMgaFCO> b_fco, d_fco;
00425         c = static_cast<FCO *>(ObjForCore( p_base));
00426         if( c) c->getinterface( &b_fco);
00427         c = static_cast<FCO *>(ObjForCore( p_derd));
00428         if( c) c->getinterface( &d_fco);
00429         CComQIPtr<IMgaModel> b_model( b_fco), d_model( d_fco);
00430         if( conn && b_model && d_model)
00431         {
00432                 derConnEnds_struct derconn_details;
00433                 derconn_details.base_parent = b_model;
00434                 derconn_details.derd_parent = d_model;
00435                 derconn_details.b_conn      = conn;
00436 
00437                 COMTHROW(conn->get_MetaRole( &derconn_details.b_conn_role));
00438 
00439                 getConnectionDetails( conn, derconn_details.b_conn_struct);
00440                 
00441                 conns_to_derive.push_back( derconn_details);
00442 
00443                 
00444         }
00445         else ASSERT(0);
00446 }
00447 
00448 bool RefreshManager::buildRefChainColl( CMgaProject *mgaproject, CoreObj& folder, CHAIN_VEC& p_chain, CComPtr<IMgaFCOs>& p_sref_chain)
00449 {
00450         bool not_found = false;
00451         for( unsigned int i = 0; !not_found && i < p_chain.size(); ++i)
00452         {
00453                 CComPtr<IMgaFCO> ref_chain_elem = SearchTool::findObjWithDetails( mgaproject, folder, p_chain[i]);
00454                 if( !ref_chain_elem) not_found = true;
00455 
00456                 if( !p_sref_chain)
00457                         COMTHROW( p_sref_chain.CoCreateInstance( L"Mga.MgaFCOs"));
00458                 COMTHROW( p_sref_chain->Append( ref_chain_elem));
00459         }
00460 
00461         return !not_found;
00462 }
00463 
00464 void RefreshManager::collectMembershipOfConn( const CComPtr<IMgaConnection>& p_conn, const connEnds_struct& p_conn_info)
00465 {
00466         CComPtr<IMgaFCOs> sets;
00467         COMTHROW( p_conn->get_MemberOfSets( &sets));
00468         long c = 0;
00469         if( sets) COMTHROW( sets->get_Count( &c));
00470         for( long i = 1; i <= c; ++i)
00471         {
00472                 CComPtr<IMgaFCO> set;
00473                 COMTHROW( sets->get_Item( i, &set));
00474                 
00475                 // getting project id of set
00476                 PROJ_ID pid;
00477                 COMTHROW( set->get_ID( &pid));
00478 
00479                 // since usually sets survive the refresh
00480                 // project id is a good identifier
00481                 m_mapOfMemberships[p_conn_info.connid].push_back( pid);
00482         }
00483 }
00484 
00485 void RefreshManager::restoreMembership( const CComPtr<IMgaFCO>& p_conn, connEnds_struct& p_conn_info, const CComPtr<IMgaModel>& p_parent)
00486 {
00487         MEMBERMAP::iterator it = m_mapOfMemberships.find( p_conn_info.connid);
00488         if( it != m_mapOfMemberships.end())
00489         {
00490                 PIDVECTOR &pidvector = it->second;
00491                 for( unsigned int i = 0; i < pidvector.size(); ++i)
00492                 {
00493                         CComPtr<IMgaFCO> res;
00494                         findAmongContained( p_parent, pidvector[i], res);
00495                         if( res)
00496                         {
00497                                 CComQIPtr<IMgaSet> set( res);
00498                                 if( set)
00499                                 {
00500                                         VARIANT_BOOL it_is;
00501                                         COMTHROW( set->get_IsMember( p_conn, &it_is));
00502                                         if( it_is == VARIANT_FALSE)
00503                                                 COMTHROW( set->AddMember( p_conn));
00504                                 }
00505                         }
00506                 }
00507         }
00508 }
00509 
00510 void RefreshManager::restoreMixedConns( CoreObj& folder)
00511 {
00512         // restore deleted conns when ref redirect happened
00513         // those are saved already in conns_stored
00514         //restoreDeletedConns( folder);
00515         
00516         for( unsigned int i = 0; i < conns_stored.size(); ++i)
00517         {
00518                 connEnds_struct &current_i = conns_stored[i];
00519                 CComPtr<IMgaFCO> s = SearchTool::findObjWithDetails( m_mgaproject, folder, current_i.src.end);
00520                 CComPtr<IMgaFCO> d = SearchTool::findObjWithDetails( m_mgaproject, folder, current_i.dst.end);
00521                 CComPtr<IMgaFCO> p = SearchTool::findObjWithDetails( m_mgaproject, folder, current_i.parent_model);
00522                 CComPtr<IMgaModel> pM;
00523                 if( p) COMTHROW( p.QueryInterface( &pM));
00524 
00525                 CComPtr<IMgaFCOs> sref_chain;
00526                 CComPtr<IMgaFCOs> dref_chain;
00527                 bool chain1_rb_ok( false), chain2_rb_ok( false); // rebuilding ok?
00528                 bool chain1_vf_ok( false), chain2_vf_ok( false); // verification ok?
00529                 bool connends_and_parent_ok = s && d && pM;
00530 
00531                 if( connends_and_parent_ok)
00532                 {
00533                         chain1_rb_ok = buildRefChainColl( m_mgaproject, folder, current_i.src.chain, sref_chain);
00534                         chain2_rb_ok = buildRefChainColl( m_mgaproject, folder, current_i.dst.chain, dref_chain);
00535 
00536                         if( chain1_rb_ok && chain2_rb_ok)
00537                         {
00538                                 chain1_vf_ok = verifyChain( pM, sref_chain, s);
00539                                 chain2_vf_ok = verifyChain( pM, dref_chain, d);
00540                         }
00541                 }
00542 
00543                 if( connends_and_parent_ok
00544                         && chain1_rb_ok && chain2_rb_ok
00545                         && chain1_vf_ok && chain2_vf_ok)
00546                 { // OK
00547                         CComPtr<IMgaMetaFCO> p_meta;
00548 
00549                         COMTHROW( pM->get_Meta( &p_meta));
00550                         CComPtr<IMgaMetaModel> p_metaM;
00551                         COMTHROW( p_meta.QueryInterface( &p_metaM));
00552                         
00553                         CComPtr<IMgaMetaRole> metarole;
00554                         COMTHROW( p_metaM->get_RoleByName( current_i.role, &metarole));
00555 
00556                         try {
00557                                 CComPtr<IMgaFCO> new_conn;
00558                                 //COMTHROW( pM->CreateSimpleConn( metarole, s, d, sref_chain, dref_chain, &new_conn));
00559                                 COMTHROW( Creator::SimpleConn( pM, metarole, s, d, sref_chain, dref_chain, m_mgaproject, &new_conn));
00560 
00561                                 //COMTHROW( new_conn->put_Name( current_i.connname));
00562                                 COMTHROW( Worker::put_Name( m_mgaproject, new_conn, current_i.connname));
00563                                 //COMTHROW( new_conn->PutGuidDisp( current_i.guid));
00564                                 COMTHROW( Worker::PutGuidDisp( m_mgaproject, new_conn, current_i.guid));
00565 
00566                                 loadSavedStuff( new_conn, current_i);
00567                                 
00568                                 if( current_i.is_derived && current_i.is_sec_derived)
00569                                 {
00570                                         // We deleted and restored rigth now a connection.
00571                                         // We pretend that the object is the same
00572                                         // that is why we have changed the guid
00573                                         // we update the mapOfSecondaryDeriveds
00574                                         // because we must pretend the new connection
00575                                         // is a detached obj, formerly secderived.
00576 
00577                                         PROJ_ID new_conn_id;
00578                                         COMTHROW( new_conn->get_ID( &new_conn_id));
00579 #if(DONT_OPTIM)
00580                                         mapOfSecondaryDeriveds[ new_conn_id] = current_i.baseConnId;
00581 #endif
00582                                         napOfSecondaryDeriveds[ new_conn   ] = current_i.baseConnId;
00583                                 }
00584 
00585                                 MyCComBSTR msg;
00586                                 msg.appendLink( new_conn); 
00587 #ifdef _DEBUG
00588                                 CComBSTR ncid; COMTHROW(new_conn->get_ID( &ncid));
00589                                 COMTHROW(msg.AppendBSTR( ncid));
00590                                 if( current_i.is_derived && current_i.is_sec_derived) 
00591                                         COMTHROW(msg.Append( L" napofsec "));
00592                                 else 
00593                                         COMTHROW(msg.Append( L" reg "));
00594 #endif
00595                                 COMTHROW(msg.Append( L" reconstructed in "));
00596                                 msg.appendLink( pM);
00597                                 m_reporter.show( msg, false);
00598 
00599                                 // if the original connection was part of any set
00600                                 // we need to restore membership because the connection
00601                                 // has been deleted and replaced by a new one
00602                                 restoreMembership( new_conn, current_i, pM);
00603 
00604                         } catch( hresult_exception& ) {
00605 
00606                                 // report error
00607                                 //MyCComBSTR msg( "Connection ");
00608                                 //msg.Append( current_i.connname);
00609                                 //msg.Append( L" could not be reconstructed in "); 
00610                                 //msg.appendLink( pM);
00611                                 //msg.Append( L"<br>");
00612                                 //prepareConnErrMsg( pM, s, d, sref_chain, dref_chain,  current_i, msg); // the pointers are valid
00613                                 MyCComBSTR msg;
00614                                 prepareConnErrMsg( pM, s, d, sref_chain, dref_chain,  current_i, msg); // the pointers are valid
00615                                 m_reporter.show( msg);
00616                                 ASSERT(0);
00617                         }
00618                 }
00619                 else
00620                 {
00621                         // report error
00622                         //MyCComBSTR msg( "Connection ");
00623                         //msg.Append( current_i.connname);
00624                         //msg.Append( L" could not be reconstructed in "); 
00625                         //if( pM) msg.appendLink( pM);// pM might be 0
00626                         //else    msg.appendLink( current_i.parent_model.id, "Parent");
00627                         //msg.Append( L"<br>");
00628                         //if( chain1_rb_ok && chain2_rb_ok) // buildRefChainColl succeeded, verifyChain failed
00629                         //{
00630                         //      if( !chain1_vf_ok) msg.Append( L"Reason: SrcChain verification failed.");
00631                         //      if( !chain2_vf_ok) msg.Append( L"Reason: DstChain verification failed.");
00632                         //}
00633                         //else // buildRefChainColl failed
00634                         //{
00635                         //      if( !chain1_rb_ok) msg.Append( L"Reason: SrcChain rebuilding failed.");
00636                         //      if( !chain2_rb_ok) msg.Append( L"Reason: DstChain rebuilding failed.");
00637                         //}
00638                         //if( connends_and_parent_ok)
00639                         //{
00640                         //      msg.Append( L"<br>");
00641                         //      prepareConnErrMsg( pM, s, d, sref_chain, dref_chain, current_i, msg);
00642                         //}
00643                         MyCComBSTR msg;
00644                         prepareConnErrMsg( pM, s, d, sref_chain, dref_chain, current_i, msg);
00645                         if( chain1_rb_ok && chain2_rb_ok) // buildRefChainColl succeeded, verifyChain failed
00646                         {
00647                                 COMTHROW(msg.Append( L"<br>"));
00648                                 if( !chain1_vf_ok)
00649                                         COMTHROW(msg.Append( L"Reason: SrcChain verification failed. "));
00650                                 if( !chain2_vf_ok)
00651                                         COMTHROW(msg.Append( L"Reason: DstChain verification failed. "));
00652                         }
00653                         else // buildRefChainColl failed
00654                         {
00655                                 COMTHROW(msg.Append( L"<br>"));
00656                                 if( !chain1_rb_ok) 
00657                                         COMTHROW(msg.Append( L"Reason: SrcChain rebuilding failed. "));
00658                                 if( !chain2_rb_ok)
00659                                         COMTHROW(msg.Append( L"Reason: DstChain rebuilding failed. "));
00660                         }
00661                         m_reporter.show( msg);
00662                 }
00663         }
00664         conns_stored.clear();
00665 }
00666 
00667 // looks recursively for p_id in d_par
00668 void RefreshManager::findAmongContained( const CComPtr<IMgaModel>& d_par, const PROJ_ID& p_id, CComPtr<IMgaFCO>& res)
00669 {
00670         CComPtr<IMgaFCOs> children;
00671         COMTHROW( d_par->get_ChildFCOs( &children));
00672         long c = 0;
00673         if( children) COMTHROW( children->get_Count( &c));
00674         for( long i = 1; !res && i <= c; ++i)
00675         {
00676                 CComPtr<IMgaFCO> child;
00677                 COMTHROW( children->get_Item( i, &child));
00678 
00679                 PROJ_ID i_id;
00680                 COMTHROW( child->get_ID( &i_id));
00681 
00682                 if( i_id == p_id)
00683                 {
00684                         res = child;
00685                 }
00686                 else
00687                 {
00688                         CComQIPtr<IMgaModel> child_model( child);
00689                         if( child_model)
00690                                 findAmongContained( child_model, p_id, res);
00691                 }
00692         }
00693 }
00694 
00695 // searches for an element inside d_par, derived from the object with p_uid
00696 void RefreshManager::findAmongSecDerd( UniqueId& p_uid, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& res)
00697 {
00698 #if(DONT_OPTIM)
00699         SEC_DER_MAP::const_iterator it = mapOfSecondaryDeriveds.begin();
00700         while( !res && it != mapOfSecondaryDeriveds.end())
00701         {
00702                 if( it->second == p_uid) // an element (with id= it->first) is found as derived from p_uid
00703                 {
00704                         // it->first is the id of the derived element from p_uid
00705                         // d_par contains it->first (either as child or grandchild [in case of port])
00706                         findAmongContained( d_par, it->first, res);
00707                 }
00708                 ++it;
00709         }
00710 #endif
00711 }
00712 
00713 void RefreshManager::findAmongNecDerd( UniqueId& p_uid, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& res)
00714 {
00715         SEC_DER_NAP::const_iterator it = napOfSecondaryDeriveds.begin();
00716         while( !res && it != napOfSecondaryDeriveds.end())
00717         {
00718                 if( it->second == p_uid) // an element (with id= it->first) is found as derived from p_uid
00719                 {
00720                         // it->first is the once-derived element from libobj identified by p_uid
00721                         // d_par contains it->first (either as child or grandchild [in case of port])
00722                         if( isInside( d_par, it->first))
00723                                 res = it->first;
00724                 }
00725                 ++it;
00726         }
00727 }
00728 // more precisely: is equal or is inside?
00729 bool RefreshManager::isInside( const CComPtr<IMgaModel>& d_par, const CComPtr<IMgaFCO>& p_fco)
00730 {
00731         CoreObj d_parent( d_par);
00732         CoreObj p( p_fco);
00733         bool found = false;
00734         while( !found && p && p.IsFCO())
00735         {
00736                 found = COM_EQUAL( p, d_parent);
00737                 p = p[ATTRID_FCOPARENT];
00738         }
00739 
00740         return found;
00741 }
00742 
00743 void RefreshManager::findAmongPriDerd( UniqueId& p_uid, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& res)
00744 {
00745         SUB_PAR_MAP::const_iterator it = mapOfDeriveds.find( p_uid);
00746         if( it != mapOfDeriveds.end())
00747         {
00748                 const SUB_PAR_VEC &pair_vec = it->second;
00749                 for( SUB_PAR_VEC::const_iterator jt = pair_vec.begin();
00750                         !res && jt != pair_vec.end(); ++jt)
00751                 {
00752                         const CComPtr<IMgaFCO> &prev_detached_obj = jt->subt_ptr;
00753                         if( isInside( d_par, prev_detached_obj))
00754                                 res = prev_detached_obj;
00755                 }
00756         }
00757 }
00758 
00759 void RefreshManager::askTheMatchMaker( const CComPtr<IMgaFCO>& end, const CComPtr<IMgaModel>& b_par, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& n_end, bool checkParentHood)
00760 {
00761         CoreObj b_end( end), d_end;
00762         CORE_MATCH_MAP::iterator it = m_coreMatchMaker.begin();
00763         for( ; !d_end && it != m_coreMatchMaker.end(); ++it)
00764         {
00765                 if( it->second == b_end)
00766                 {
00767                         if( checkParentHood)
00768                         {
00769                                 CoreObj d_parent( d_par);
00770                                 CoreObj d_paren2( it->first[ATTRID_FCOPARENT]);
00771                                 CoreObj d_paren3;
00772                                 if( d_paren2.GetMetaID() != DTID_ROOT)
00773                                         d_paren3 = d_paren2[ATTRID_FCOPARENT];
00774 
00775                                 if( COM_EQUAL( d_parent, d_paren2)  // d_end child of d_parent
00776                                 || COM_EQUAL( d_parent, d_paren3)) // d_end grandchild of d_parent (visible as a port)
00777                                         d_end = it->first;
00778                         }
00779                         else
00780                                 d_end = it->first;
00781                 }
00782         }
00783 
00784         if( d_end)
00785         {
00786                 ObjForCore(d_end)->getinterface( &n_end); 
00787         }
00788 }
00789 
00790 //
00791 // something like GetDerivedEquivalent, based on our records
00792 // if checkParentHood turned on, then n_end is supposed to be in d_par (for sets, connections)
00793 // or to be a grandchild of d_par (if it is a port) for connections
00794 // if checkParentHood is false no such test is performed on the found element
00795 // ideally: end's relation to b_par (child, grandchild) should be the same as n_end's relation to d_par
00796 void RefreshManager::getLibDerdEquiv( const CComPtr<IMgaFCO>& end, const CComPtr<IMgaModel>& b_par, const CComPtr<IMgaModel>& d_par, CComPtr<IMgaFCO>& n_end, bool checkParentHood /*=true*/)
00797 {
00798         if( b_par == d_par || !end) 
00799         {
00800                 n_end = end;
00801                 return;
00802         }
00803         
00804         // first do a ptr based search among the derived objects
00805         askTheMatchMaker( end, b_par, d_par, n_end, checkParentHood);
00806 
00807         if( !n_end) // do a id-based search 
00808         {
00809                 // end is supposed to be in the library
00810                 UniqueId uid = Identifier::getDetailsOf( CoreObj( end));
00811                 findAmongSecDerd( uid, d_par, n_end);
00812                 
00813                 CComPtr<IMgaFCO> nnend;
00814                 findAmongNecDerd( uid, d_par, nnend);
00815                 ASSERT( n_end == nnend);
00816 
00817                 if( !n_end)
00818                         findAmongPriDerd( uid, d_par, n_end);
00819         }
00820 }
00821 
00822 CComPtr<IMgaModel> RefreshManager::nextContainer( CComPtr<IMgaFCO>& p_ref)
00823 {
00824         CComPtr<IMgaModel> retv;
00825         CComQIPtr<IMgaReference> ref( p_ref);
00826         if( !ref) return retv;
00827 
00828         CComPtr<IMgaFCO> tgt;
00829         COMTHROW( ref->get_Referred( &tgt));
00830         if( tgt)
00831         {
00832                 CComPtr<IMgaModel> par;
00833                 if( SUCCEEDED( tgt->get_ParentModel( &par)))
00834                         retv = par;
00835         }
00836 
00837         return retv;
00838 }
00839 
00840 // passes one step in a reference chain
00841 CComPtr<IMgaFCO> RefreshManager::nextElem( CComPtr<IMgaFCO>& p_ref)
00842 {
00843         CComPtr<IMgaFCO> retv;
00844         CComQIPtr<IMgaReference> ref( p_ref);
00845         if( !ref) return retv;
00846 
00847         CComPtr<IMgaFCO> tgt;
00848         COMTHROW( ref->get_Referred( &tgt));
00849         if( tgt)
00850         {
00851                 retv = tgt;
00852         }
00853 
00854         return retv;
00855 }
00856 
00857 // finds an element taking part in a connection
00858 bool RefreshManager::findConnEndPeer( const derConnEnds_struct& c_info
00859                 , const CComPtr<IMgaFCOs>& p_chainOrig, const CComPtr<IMgaFCO>& p_endOrig
00860                 ,       CComPtr<IMgaFCOs>& p_chainPeer,       CComPtr<IMgaFCO>& p_endPeer)
00861 {
00862 #ifdef _DEBUG
00863         bool details = false;
00864 #endif
00865         bool so_far_ok( true);
00866         long len( 0);
00867         if( p_chainOrig) COMTHROW( p_chainOrig->get_Count( &len));
00868         if( len == 0)
00869         {
00870                 getLibDerdEquiv( p_endOrig, c_info.base_parent, c_info.derd_parent, p_endPeer);
00871                 so_far_ok = p_endPeer != 0;
00872         }
00873         else
00874         {
00875                 // if p_chainOrig is a chain of lenght len
00876                 // we must find a similar chain for p_chainPeer
00877                 COMTHROW( p_chainPeer.CoCreateInstance( L"Mga.MgaFCOs"));
00878 
00879                 CComPtr<IMgaModel> base_cur_parent( c_info.base_parent);
00880                 CComPtr<IMgaModel> derd_cur_parent( c_info.derd_parent);
00881                 CComPtr<IMgaFCO>   prev_elem;
00882                 for( long i = 1; so_far_ok && i <= len; ++i)
00883                 {
00884                         CComPtr<IMgaFCO> chain_elem;   // orig chain elem
00885                         CComPtr<IMgaFCO> n_chain_elem; // new chain elem
00886 
00887                         COMTHROW( p_chainOrig->get_Item( i, &chain_elem));
00888 
00889                         if( i == 1) // the first step is special
00890                         {
00891                                 getLibDerdEquiv( chain_elem, base_cur_parent, derd_cur_parent, n_chain_elem);
00892                         }
00893                         else
00894                         {
00895                                 n_chain_elem = nextElem( prev_elem);
00896                         }
00897                         
00898                         if( n_chain_elem)
00899                         {
00900                                 COMTHROW( p_chainPeer->Append( n_chain_elem));
00901                                 //base_cur_parent = nextContainer( chain_elem);
00902                                 //derd_cur_parent = nextContainer( n_chain_elem);
00903 
00904                                 prev_elem = n_chain_elem;
00905 
00906 #ifdef _DEBUG
00907                                 MyCComBSTR msg;
00908                                 msg.appendLink( n_chain_elem);
00909                                 msg.Append( L" counterpart found for ");
00910                                 msg.appendLink( chain_elem);
00911                                 if( details) m_reporter.show( msg, false);
00912 #endif
00913                         }
00914                         else
00915                         {
00916                                 so_far_ok = false;
00917 #ifdef _DEBUG
00918                                 MyCComBSTR msg;
00919                                 msg.Append( L" Not found");
00920                                 msg.Append( L" counterpart for ");
00921                                 msg.appendLink( chain_elem);
00922                                 if( details) m_reporter.show( msg, true);
00923 #endif
00924                         }
00925                 }
00926 
00927                 if( so_far_ok) //
00928                 {
00929                         CComPtr<IMgaModel> base_connend_parent; // the connend container in base (a model)
00930                         CComPtr<IMgaModel> derd_connend_parent; // the connend container in derd (a model)
00931                         bool b_ok = followRefChain( p_chainOrig, base_connend_parent);
00932                         bool d_ok = followRefChain( p_chainPeer, derd_connend_parent);
00933 
00934                         if( b_ok && d_ok && base_connend_parent && derd_connend_parent)
00935                         {
00936 #ifdef _DEBUG
00937                                 // reporting progress
00938                                 MyCComBSTR msg;
00939                                 msg.Append( L"Looking for counterpart of ");
00940                                 msg.appendLink( p_endOrig);
00941                                 msg.Append( L" ( ");
00942                                 msg.appendLink( base_connend_parent);
00943                                 msg.Append( L" -basemodel) in ");
00944                                 msg.appendLink( derd_connend_parent);
00945                                 msg.Append( L" -derdmodel");
00946                                 if( details) m_reporter.show( msg, false);
00947 #endif
00948                                 getLibDerdEquiv( p_endOrig, base_connend_parent, derd_connend_parent, p_endPeer);
00949                                 so_far_ok = p_endPeer != 0;
00950                         }
00951                         else
00952                         {
00953                                 so_far_ok = false;
00954 
00955 #ifdef _DEBUG
00956                                 // reporting error
00957                                 MyCComBSTR msg;
00958                                 msg.Append( L"Invalid chain. Can't look for counterpart of ");
00959                                 msg.appendLink( p_endOrig);
00960                                 msg.Append( L" ( ");
00961                                 if( base_connend_parent) msg.appendLink( base_connend_parent);
00962                                 else                     msg.Append( L"empty basemodel");
00963                                 msg.Append( L" ) in ");
00964                                 if( derd_connend_parent) msg.appendLink( derd_connend_parent);
00965                                 else                     msg.Append( L"empty derdmodel");
00966                                 if( details) m_reporter.show( msg, false);
00967 
00968                                 ASSERT(0);
00969 #endif
00970                         }
00971                 }
00972         }
00973 
00974         return so_far_ok;
00975 }
00976 
00977 bool RefreshManager::fillConnectionPtrs( const derConnEnds_struct& c_info
00978                         , CComPtr<IMgaFCO>& p_newSrc,     CComPtr<IMgaFCO>& p_newDst
00979                         , CComPtr<IMgaFCOs>& p_newSChain, CComPtr<IMgaFCOs>& p_newDChain)
00980 {
00981         CComQIPtr<IMgaSimpleConnection> b_sconn( c_info.b_conn);
00982         ASSERT( b_sconn);
00983         if( !b_sconn) return false;
00984 
00985         bool rv = false;
00986         CComPtr<IMgaFCOs> s_chain, d_chain;
00987         COMTHROW( b_sconn->get_SrcReferences( &s_chain));
00988         COMTHROW( b_sconn->get_DstReferences( &d_chain));
00989 
00990         CComPtr<IMgaFCO> src, dst;
00991         COMTHROW( b_sconn->get_Src( &src));
00992         COMTHROW( b_sconn->get_Dst( &dst));
00993 
00994         bool v1 = findConnEndPeer( c_info, s_chain, src, p_newSChain, p_newSrc);
00995         bool v2 = findConnEndPeer( c_info, d_chain, dst, p_newDChain, p_newDst);
00996 
00997         rv = v1 && v2 && p_newSrc && p_newDst;
00998 
00999         return rv;
01000 }
01001 
01002 bool RefreshManager::followRefChain( const CComPtr<IMgaFCOs>& chain, CComPtr<IMgaModel>& final_m)
01003 {
01004         bool retv = false;
01005         long c(0);
01006         if( chain) COMTHROW( chain->get_Count( &c));
01007         if( c >= 1)
01008         {
01009                 CComPtr<IMgaFCO> it;
01010                 COMTHROW( chain->get_Item( c, &it)); // get the last item in the chain
01011                 CComQIPtr<IMgaReference> rit( it);
01012                 if( rit) // it is a reference
01013                 {
01014                         CComPtr<IMgaFCO> tgt;
01015                         COMTHROW( rit->get_Referred( &tgt)); 
01016                         if( tgt)
01017                         {
01018                                 CComQIPtr<IMgaModel> f_m( tgt);
01019                                 if( f_m) // it refers to a model
01020                                 {
01021                                         final_m = f_m;
01022                                         retv = true; // 
01023                                 }
01024                         }
01025                 }
01026         }
01027         return retv;
01028 }
01029 
01030 // a connection can be drawn to a
01031 // 1. connend in the same parent as the connection
01032 // 2. connend whose parent is sibling of the connection
01033 //    because the parent show this connend as a ports
01034 // 3. referenceports: at the end of the chain there is a model having the connend
01035 bool RefreshManager::verifyChain( const CComPtr<IMgaModel>& pM, const CComPtr<IMgaFCOs>& sref_chain, const CComPtr<IMgaFCO>& s)
01036 {
01037         ASSERT( s);
01038         ASSERT( pM);
01039         if( !s) return false;
01040         if( !pM) return false;
01041 
01042         bool ret = true;
01043         long c = 0;
01044         if( sref_chain)
01045                 COMTHROW(sref_chain->get_Count( &c));
01046         if( c == 0)
01047         {
01048                 // s must be pM's child, or its grandchild (but in this case must be a port)
01049                 CComPtr<IMgaModel> par;
01050                 HRESULT hr = s->get_ParentModel( &par);
01051                 ret = SUCCEEDED( hr) && COM_EQUAL(par, pM);
01052                 if( !ret && par) // test if grandchild
01053                 {
01054                         CComPtr<IMgaModel> par2;
01055                         hr = par->get_ParentModel( &par2);
01056                         ret = SUCCEEDED( hr) && COM_EQUAL( par2, pM); //is <s> a grandchild of pM?
01057                 }
01058         }
01059         else if( c >= 1)
01060         {
01061                 CComPtr<IMgaFCO> next;
01062                 COMTHROW(sref_chain->get_Item( 1, &next));
01063                 // next must be pM's child
01064                 CComPtr<IMgaModel> par;
01065                 HRESULT hr = E_FAIL;
01066                 if( next) hr = next->get_ParentModel( &par);
01067                 if( SUCCEEDED( hr) && COM_EQUAL( par, pM))
01068                 {
01069                         long i;
01070                         for( i = 2; ret && i <= c; ++i)
01071                         {
01072                                 CComPtr<IMgaFCO> chain_elem;
01073                                 COMTHROW(sref_chain->get_Item( i, &chain_elem));
01074 
01075                                 CComQIPtr<IMgaReference> next_as_ref( next);
01076                                 if( next_as_ref)
01077                                 {
01078                                         CComPtr<IMgaFCO> tgt;
01079                                         COMTHROW( next_as_ref->get_Referred( &tgt));
01080                                         
01081                                         // the 1st refs target must be the 2nd element in the array and so on
01082                                         ASSERT( COM_EQUAL( chain_elem, tgt));
01083                                         if( COM_EQUAL( chain_elem, tgt))
01084                                                 next = tgt;
01085                                         else // chain element (i) not pointing to element (i+1)
01086                                                 ret = false; // exit
01087                                 }
01088                                 else // chain_elem not a reference
01089                                         ret = false; // exit
01090                         
01091                         } // for
01092 
01093                         if( i == c+1 && ret) // ret is still ok, went through the chain
01094                         {
01095                                 CComPtr<IMgaFCO> last;
01096                                 COMTHROW(sref_chain->get_Item(c, &last));
01097                                 CComQIPtr<IMgaReference> last_ref( last);
01098                                 if( last_ref)
01099                                 {
01100                                         CComPtr<IMgaFCO> tgt;
01101                                         COMTHROW( last_ref->get_Referred( &tgt));
01102                                         CComQIPtr<IMgaModel> tgt_model( tgt);
01103                                         if( tgt_model)
01104                                         {
01105                                                 // s must be a child of tgt_model
01106                                                 CComPtr<IMgaModel> par;
01107                                                 HRESULT hr = s->get_ParentModel( &par);
01108                                                 
01109                                                 ret = SUCCEEDED( hr) && COM_EQUAL( par, tgt_model);
01110                                         }
01111                                         else // last element's target must be a model
01112                                                 ret = false;
01113                                 }
01114                                 else // last element is not a ref?
01115                                         ret = false;
01116                         }
01117                 }
01118                 else ret = false;
01119         } // c == 0 || c >= 1
01120 
01121         return ret;
01122 }
01123  
01124 
01125 void RefreshManager::prepareConnErrMsg( 
01126                         const CComPtr<IMgaModel>& pM
01127                         , const CComPtr<IMgaFCO>& s, const CComPtr<IMgaFCO>& d
01128                         , const CComPtr<IMgaFCOs>& sref_chain, const CComPtr<IMgaFCOs>& dref_chain
01129                         , const connEnds_struct& current_i, MyCComBSTR& msg)
01130 {
01131         //
01132         // prepare error message
01133         //msg.appendLink( current_i.connid, current_i.connname);
01134         COMTHROW(msg.Append( current_i.connname));
01135         COMTHROW(msg.Append( L" ["));
01136         COMTHROW(msg.Append( current_i.connid));
01137         COMTHROW(msg.Append( L"]"));
01138         COMTHROW(msg.Append( L" connection could not be reconstructed in "));
01139         if( pM)
01140                 msg.appendLink( pM);
01141         else
01142                 COMTHROW(msg.Append( L"Null"));
01143 
01144         COMTHROW(msg.Append( L"<br>\tSrc: "));
01145         if( s)
01146                 msg.appendLink( s);
01147         else
01148                 COMTHROW(msg.Append( L"Null"));
01149 
01150         COMTHROW(msg.Append( L" Dst: "));
01151         if( d)
01152                 msg.appendLink( d);
01153         else
01154                 COMTHROW(msg.Append( L"Null"));
01155 
01156         COMTHROW(msg.Append( L"<br>\tSrcRefs:"));
01157         long c_len = 0;
01158         if( sref_chain)
01159                 COMTHROW(sref_chain->get_Count( &c_len));
01160         for( long i = 1; i <= c_len; ++i)
01161         {
01162                 if( i != 1)
01163                         COMTHROW(msg.Append( L","));
01164                 COMTHROW(msg.Append( L" "));
01165                 CComPtr<IMgaFCO> r_i;
01166                 COMTHROW(sref_chain->get_Item( i, &r_i));
01167                 msg.appendLink( r_i);
01168         }
01169 
01170         COMTHROW(msg.Append( L" DstRefs:"));
01171         c_len = 0;
01172         if( dref_chain) 
01173                 COMTHROW(dref_chain->get_Count( &c_len));
01174         for( long i = 1; i <= c_len; ++i)
01175         {
01176                 if( i != 1)
01177                         COMTHROW(msg.Append( L","));
01178                 COMTHROW(msg.Append( L" "));
01179                 CComPtr<IMgaFCO> r_i;
01180                 COMTHROW(dref_chain->get_Item( i, &r_i));
01181                 msg.appendLink( r_i);
01182         }
01183 }
01184 
01185 // fresh connections are those which have appeared after our last refresh
01186 // so these must be propagated down into the derived object (if derived 
01187 // from a library object)
01188 // most typically such an object is a secondary derived object
01189 void RefreshManager::syncFreshConns()
01190 {
01191         for( unsigned int i = 0; i < conns_to_derive.size(); ++i)
01192         {
01193                 derConnEnds_struct &i_conn = conns_to_derive[i];
01194 
01195                 CComPtr<IMgaFCO>  s, d;
01196                 CComPtr<IMgaFCOs> sref_chain, dref_chain;
01197                 CComPtr<IMgaModel> pM = i_conn.derd_parent;
01198 
01199                 // we would have used GetDerivedEquivalent had the base-derive relation been re-established
01200                 bool chain1_ok = false;
01201                 bool chain2_ok = false;
01202                 bool valid = fillConnectionPtrs( i_conn, s, d, sref_chain, dref_chain);
01203                 if( valid)
01204                 {
01205                         // the pointers are found, but let's verify whether 
01206                         // the chain is leading really towards s, d
01207                         chain1_ok = verifyChain( pM, sref_chain, s);
01208                         chain2_ok = verifyChain( pM, dref_chain, d);
01209                 }
01210 
01211 
01212                 // this connection needs to be derived
01213                 // pointer in i_conn.b_conn
01214                 // structure info in i_conn.b_conn_struct
01215                 connEnds_struct &current_i = i_conn.b_conn_struct;
01216 
01217                 // we check again if the connend can be reached from pM though the chain
01218 
01219                 if( valid && chain1_ok && chain2_ok)
01220                 {   // OK
01221                         CComPtr<IMgaFCO> new_conn;
01222                         try {
01223                                 //COMTHROW( pM->CreateSimpleConn( i_conn.b_conn_role, s, d, sref_chain, dref_chain, &new_conn));
01224                                 COMTHROW( Creator::SimpleConn( pM, i_conn.b_conn_role, s, d, sref_chain, dref_chain, m_mgaproject, &new_conn));
01225                                 //COMTHROW( new_conn->put_Name( current_i.connname));
01226                                 COMTHROW( Worker::put_Name( m_mgaproject, new_conn, current_i.connname));
01227 
01228                                 m_coreMatchMaker[ CoreObj(new_conn)] = CoreObj(i_conn.b_conn);
01229 #if(0)
01230                                 //UniqueId base_conn_id = Identifier::getDetailsOf( CoreObj(i_conn.b_conn));
01231                                 //PROJ_ID new_conn_id;
01232                                 //COMTHROW( new_conn->get_ID( &new_conn_id));
01233                                 //mapOfSecondaryDeriveds[ new_conn_id] = base_conn_id;
01234 #endif
01235                                 // since this connection is fresh (just added to the base), it
01236                                 // had no peer in the prev version of the project, we don't care
01237                                 // about replacing its guid with the old one, nor we care about
01238                                 // inserting it into mapOfSecondaryDeriveds
01239                                 
01240                                 MyCComBSTR msg;
01241                                 msg.appendLink( new_conn); 
01242                                 COMTHROW(msg.Append( L" reconstructed in "));
01243                                 msg.appendLink( pM);
01244 #ifdef _DEBUG
01245                                 CComBSTR ncid, pmid;
01246                                 COMTHROW(new_conn->get_ID( &ncid));
01247                                 COMTHROW(msg.AppendBSTR( ncid));
01248                                 COMTHROW(msg.Append( " "));
01249                                 COMTHROW(pM->get_ID( &pmid));
01250                                 COMTHROW(msg.AppendBSTR( pmid));
01251 #endif
01252                                 m_reporter.show( msg, false);
01253 
01254                         } catch( hresult_exception& ) {
01255 
01256                                 // report error
01257                                 //MyCComBSTR msg( "Connection ");
01258                                 //msg.Append( current_i.connname);
01259                                 //msg.Append( L" could not be reconstructed in "); 
01260                                 //msg.appendLink( pM);
01261                                 //msg.Append( L"<br>");
01262                                 //prepareConnErrMsg( pM, s, d, sref_chain, dref_chain, current_i, msg);
01263                                 MyCComBSTR msg;
01264                                 prepareConnErrMsg( pM, s, d, sref_chain, dref_chain, current_i, msg);
01265                                 m_reporter.show( msg);
01266 
01267                                 ASSERT(0);
01268 
01269                                 if( new_conn && ObjForCore( CoreObj( new_conn)))
01270                                 {
01271                                         //new_conn->DestroyObject();
01272                                         ObjForCore( CoreObj(new_conn))->inDeleteObject();
01273                                 }
01274                         }
01275                 }
01276                 else
01277                 {
01278                         // report error
01279                         //MyCComBSTR msg( "Connection ");
01280                         //msg.Append( current_i.connname);
01281                         //msg.Append( L" could not be reconstructed in "); 
01282                         //if( pM) msg.appendLink( pM);
01283                         //else msg.appendLink( current_i.parent_model.id, "Parent");
01284 
01285                         //if( valid)
01286                         //{
01287                         //      if( !chain1_ok) msg.Append( L"Reason: SrcChain verification failed.");
01288                         //      if( !chain2_ok) msg.Append( L"Reason: DstChain verification failed.");
01289                         //      msg.Append( L"<br>");
01290                         //      prepareConnErrMsg( pM, s, d, sref_chain, dref_chain, current_i, msg);
01291                         //      m_reporter.show( msg);
01292                         //}
01293                         //m_reporter.show( msg);
01294                         MyCComBSTR msg;
01295                         prepareConnErrMsg( pM, s, d, sref_chain, dref_chain, current_i, msg);
01296                         if( valid)
01297                         {
01298                                 COMTHROW(msg.Append( L"<br>"));
01299                                 if( !chain1_ok)
01300                                         COMTHROW(msg.Append( L"Reason: SrcChain verification failed. "));
01301                                 if( !chain2_ok)
01302                                         COMTHROW(msg.Append( L"Reason: DstChain verification failed. "));
01303                         }
01304                                 
01305                         m_reporter.show( msg);
01306                 }
01307         }
01308         conns_to_derive.clear();
01309 }
01310 
01311 // obsolete, since any connection detected upon reference-redirection
01312 // is considered previously as a mixed connection, thus important
01313 // information is saved about it
01314 void RefreshManager::saveConnection( const CComPtr<IMgaFCO>& p_cn)
01315 {
01316 #if(DONT_OPTIM)
01317         CComQIPtr<IMgaSimpleConnection> cn( p_cn);
01318         if( !cn) return;
01319 
01320         connEnds_struct2 conn_info;
01321         cn->get_ParentModel( &conn_info.par);
01322         cn->get_MetaRole( &conn_info.mrole);
01323         cn->get_Src( &conn_info.src);
01324         cn->get_Dst( &conn_info.dst);
01325         cn->get_SrcReferences( &conn_info.srcRefs);
01326         cn->get_DstReferences( &conn_info.dstRefs);
01327         cn->get_Name( &conn_info.nm);
01328         cn->GetGuidDisp( &conn_info.guid);
01329         //getConnectionDetails( cn_i, conn_details.b_conn_struct);
01330         conns_to_recreate.push_back( conn_info);
01331 #endif
01332         CComQIPtr<IMgaConnection> owner( p_cn);
01333         if( !owner) return;
01334 
01335         connEnds_struct one_conn;
01336         getConnectionDetails( owner, one_conn);
01337 
01338         // check if connection is (or precisely: was) secondary derived
01339         SEC_DER_NAP::const_iterator it = napOfSecondaryDeriveds.find( p_cn);
01340         if( it != napOfSecondaryDeriveds.end()) // found
01341         {
01342                 ASSERT( !one_conn.is_derived);
01343                 // when this occurs relations are already cut
01344                 // that is why getConnectionDetails reported
01345                 // that one_conn is NOT derived (is_derived=false)
01346                 // but based on the napOfSecondaryDeriveds we can
01347                 // confirm that it is derived, and the connection
01348                 // will be saved altered into conns_stored
01349                 one_conn.is_derived = true;
01350                 one_conn.is_sec_derived = true;
01351                 one_conn.baseConnId = it->second;
01352                 one_conn.baseConnInLib = true;
01353         }
01354 
01355         // if sec derived from a project conn (non library conn)
01356         // then no need to store it, since its base will be recreated
01357         // and then the change propagated down into this place
01358         //if( one_conn.is_derived && one_conn.is_sec_derived && !one_conn.baseConnInLib)
01359         //      return;
01360 
01361         // even a sec-derd connection from library needs to be stored
01362         // because it needs to be deleted while the reference involved
01363         // is redirected, thus later needs restoration
01364 
01365         // examine if this connection has already been inserted into the vector
01366         if( conns_stored.end() == std::find_if( conns_stored.begin(), conns_stored.end(), HasThisConn(one_conn.connid))) // not found
01367                 conns_stored.push_back( one_conn);
01368 
01369 }
01370 
01371 // obsolete, like saveConnection
01372 void RefreshManager::restoreDeletedConns( CoreObj& nfolder)
01373 {
01374 #if(DONT_OPTIM)
01375         for( unsigned int i = 0; i < conns_to_recreate.size(); ++i)
01376         {
01377                 connEnds_struct2 &curr_i = conns_to_recreate[i];
01378                 try {
01379                         CComPtr<IMgaFCO> resu;
01380                         long c( 0);
01381                         MyCComBSTR ms1;
01382                         ms1.appendLink( ObjForCore(CoreObj(curr_i.src)));
01383                         ms1.Append( L" ChainS ");
01384                         curr_i.srcRefs->get_Count( &c);
01385                         for( long i = 1; i <= c; ++i)
01386                         {
01387                                 CComPtr<IMgaFCO> it;
01388                                 curr_i.srcRefs->get_Item( i, &it);
01389                                 CComQIPtr<IMgaReference> rit( it);
01390                                 
01391                                 ms1.appendLink( rit);
01392                                 ms1.Append( L" ");
01393                         }
01394                         m_reporter.show( ms1, false);
01395 
01396                         MyCComBSTR ms2;
01397                         ms2.appendLink( ObjForCore(CoreObj(curr_i.dst)));
01398                         ms2.Append( L" ChainD ");
01399                         curr_i.dstRefs->get_Count( &c);
01400                         for( long i = 1; i <= c; ++i)
01401                         {
01402                                 CComPtr<IMgaFCO> it;
01403                                 curr_i.dstRefs->get_Item( i, &it);
01404                                 CComQIPtr<IMgaReference> rit( it);
01405                                 
01406                                 ms2.appendLink( rit);
01407                                 ms2.Append( L" ");
01408                         }
01409                         m_reporter.show( ms2, false);
01410 
01411                         /*COMTHROW( curr_i.par->CreateSimpleConn( curr_i.mrole, 
01412                                 curr_i.src, curr_i.dst, 
01413                                 curr_i.srcRefs, curr_i.dstRefs, &resu));*/
01414                         COMTHROW( Creator::SimpleConn( curr_i.par, curr_i.mrole, 
01415                                 curr_i.src, curr_i.dst, 
01416                                 curr_i.srcRefs, curr_i.dstRefs, m_mgaproject, &resu));
01417 
01418                         //COMTHROW( resu->put_Name( curr_i.nm));
01419                         COMTHROW( Worker::put_Name( m_mgaproject, resu, curr_i.nm));
01420                         //COMTHROW( resu->PutGuidDisp( curr_i.guid));
01421                         COMTHROW( Worker::PutGuidDisp( m_mgaproject, resu, curr_i.guid));
01422 
01423                         MyCComBSTR msg( "Succesfully recreated (prev. deleted) ");
01424                         msg.appendLink( resu);
01425                         msg.Append( L" in ");
01426                         msg.appendLink( ObjForCore(CoreObj( curr_i.par)));
01427                         m_reporter.show( msg, false);
01428 
01429                 } catch( hresult_exception &) {
01430 
01431                         MyCComBSTR msg( "Could not recreate ");
01432                         msg.Append( curr_i.nm);
01433                         msg.Append( L" (a deleted connection) in ");
01434                         msg.appendLink( ObjForCore(CoreObj( curr_i.par)));
01435                         m_reporter.show( msg);
01436                 }
01437         }
01438 #endif
01439 }
01440 
01441 // it differs from the putRefTask().DoWithDeriveds that it disregards the MasterObj attribute
01442 // and it sets the same target for all Deriveds. 
01443 // Instead of ATTRID_MASTEROBJ it operates with ATTRID_DERIVED
01444 // TODO: improve parameter passing
01445 bool RefreshManager::ignoreFurtherRedir( CComPtr<IMgaReference>& orig_ref, CComPtr<IMgaFCO>& ref_tgt_newlib)
01446 {
01447         CoreObj one_ref = CoreObj( orig_ref);
01448 
01449         // will by skipped by the mapOfDependentRefs restoration
01450         m_alreadySetRefs.insert( one_ref);
01451 
01452         CoreObjs deriveds = one_ref[ATTRID_DERIVED + ATTRID_COLLECTION];
01453         ITERATE_THROUGH(deriveds) {
01454                 CComPtr<IMgaFCO> fco;
01455                 ObjForCore( ITER)->getinterface( &fco);
01456                 CComQIPtr<IMgaReference> derd_ref( fco);
01457                 if( !derd_ref) continue;
01458 
01459                 //redirectRefWithCare( derd_ref, ref_tgt_newlib);
01460 
01461                 ignoreFurtherRedir( derd_ref, ref_tgt_newlib); // recursive
01462         }
01463         return true;
01464 }
01465 
01466 bool RefreshManager::redirectRefWithCare( CComPtr<IMgaReference>& orig, CComPtr<IMgaFCO>& ref_tgt_newlib)
01467 {
01468         ASSERT( orig);
01469         if( !orig) return false;
01470 
01471         // first check if it plays a role in some connections (thru reference ports)
01472         // which involve orig as a reference in the chain
01473         // a reference in such a case can't simply be deleted because the
01474         // redirecting is blocked by the the hanging connection points 
01475 
01476         CComPtr<IMgaConnPoints> cps;
01477         //COMTHROW( orig->get_PartOfConns( &cps)); // in case of a reference this does not give you back the refport conns
01478         COMTHROW( orig->get_UsedByConns( &cps));
01479 
01480         long c(0);
01481         if( cps) COMTHROW( cps->get_Count( &c));
01482 
01483         if( c <= 0) // in case of a reference which is not involved in any refchains for Connections
01484         {
01485                 try {
01486                         // redirect it simply
01487                         //COMTHROW( orig->put_Referred( ref_tgt_newlib));
01488                         CoreObj corig( orig);
01489                         corig[ATTRID_REFERENCE] = CoreObj( ref_tgt_newlib);
01490 
01491                         // success
01492                         MyCComBSTR msg;
01493                         msg.appendLink( orig);
01494                         COMTHROW(msg.Append( L" stand alone reference retargeted to "));
01495                         if( ref_tgt_newlib)
01496                                 msg.appendLink( ref_tgt_newlib);
01497                         else
01498                                 COMTHROW(msg.Append( L"Null"));
01499                         m_reporter.show( msg, false);
01500 
01501                 } catch( hresult_exception&) {
01502 
01503                         // failure
01504                         MyCComBSTR msg;
01505                         msg.appendLink( orig);
01506                         COMTHROW(msg.Append( L" stand alone reference could not be retargeted to "));
01507                         if( ref_tgt_newlib)
01508                                 msg.appendLink( ref_tgt_newlib);
01509                         else
01510                                 COMTHROW(msg.Append( L"Null"));
01511                         m_reporter.show( msg);
01512                 }
01513         }
01514         else
01515         {
01516                 //
01517                 // we need to remove all connpoints which are attached to refports or orig
01518                 // because 
01519                 // but first we store them into coll_of_conns
01520                 CComPtr<IMgaFCOs> coll_of_conns;
01521                 COMTHROW( coll_of_conns.CoCreateInstance( L"Mga.MgaFCOs"));
01522 
01523                 for( long i = 1; i <= c; ++i) 
01524                 {
01525                         CComPtr<IMgaConnPoint> cp;
01526                         COMTHROW( cps->get_Item( i, &cp));
01527                         if( cp)
01528                         {
01529                                 CComPtr<IMgaConnection> cn;
01530                                 COMTHROW( cp->get_Owner( &cn));
01531 
01532                                 // if there is a loop connection and we destroy it
01533                                 // the connpoint will die along with it, so when
01534                                 // encountering the next connpoint belonging to this
01535                                 // connection will raise null ptr exception, because that
01536                                 // connpoint is 0 already
01537                                 //COMTHROW( cn->DestroyObject());
01538                                 long pos = 0;
01539                                 coll_of_conns->Find( cn, 1, &pos); // ignore failure
01540                                 if( pos < 1)
01541                                 {
01542                                         COMTHROW(coll_of_conns->Append( cn));
01543                                         // save it
01544                                         saveConnection( CComPtr<IMgaFCO>(cn));
01545                                 }
01546                         }
01547                 }
01548 
01549                 //
01550                 // now really remove the collected connections
01551                 // 
01552                 long conns_len = 0;
01553                 if( coll_of_conns) COMTHROW( coll_of_conns->get_Count( &conns_len));
01554                 for( long i = 1; i <= conns_len; ++i)
01555                 {
01556                         CComPtr<IMgaFCO> cn_i;
01557                         COMTHROW( coll_of_conns->get_Item( i, &cn_i));
01558 
01559                         // delete the connection
01560                         try {
01561 #ifdef _DEBUG
01562                                 long ci = CoreObj(cn_i)[ATTRID_RELID];
01563 #endif
01564                                 //COMTHROW( cn_i->DestroyObject());
01565                                 ObjForCore( CoreObj(cn_i))->inDeleteObject();
01566 
01567 
01568                                 MyCComBSTR msg;
01569                                 COMTHROW(msg.Append( L"Connection "));
01570                                 msg.appendLink( cn_i);
01571                                 COMTHROW(msg.Append( L" deleted while retargeting reference "));
01572                                 msg.appendLink( orig);
01573                                 m_reporter.show( msg, false);
01574 
01575                         } catch(hresult_exception&) {
01576 
01577                                 MyCComBSTR msg;
01578                                 COMTHROW(msg.Append( L"Connection "));
01579                                 msg.appendLink( cn_i);
01580                                 COMTHROW(msg.Append( L" could not be deleted while retargeting reference "));
01581                                 msg.appendLink( orig);
01582                                 m_reporter.show( msg);
01583                         }
01584                 }
01585                 
01586                 //
01587                 // retarget the orig reference into the newlibrary
01588                 //
01589                 try {
01590                         //COMTHROW( orig->put_Referred( ref_tgt_newlib));
01591                         CoreObj corig( orig);
01592                         corig[ATTRID_REFERENCE] = CoreObj( ref_tgt_newlib);
01593 
01594                         // success
01595                         MyCComBSTR msg;
01596                         msg.appendLink( orig);
01597                         COMTHROW(msg.Append( L" retargeted to "));
01598                         msg.appendLink( ref_tgt_newlib);
01599                         m_reporter.show( msg, false);
01600 
01601                 } catch( hresult_exception& ) {
01602 
01603                         // failure
01604                         MyCComBSTR msg;
01605                         msg.appendLink( orig);
01606                         COMTHROW(msg.Append( L" could not be retargeted to "));
01607                         msg.appendLink( ref_tgt_newlib);
01608                         m_reporter.show( msg);
01609                 }
01610         }
01611 
01612         CoreObj corig( orig);
01613         // remember that we already did retarget this corig object
01614         //m_alreadySetRefs.insert( corig);
01615 
01616         // propagate the target onto the deriveds objects
01617         CoreObjs deriveds = corig[ATTRID_DERIVED + ATTRID_COLLECTION];
01618         ITERATE_THROUGH(deriveds) {
01619                 CComPtr<IMgaFCO> fco;
01620                 ObjForCore( ITER)->getinterface( &fco);
01621                 CComQIPtr<IMgaReference> derd_ref( fco);
01622                 if( !derd_ref) continue;
01623 
01624                 redirectRefWithCare( derd_ref, ref_tgt_newlib);// recursive
01625         }
01626 
01627         return true;
01628 }
01629 
01630 void RefreshManager::restoreRefsToLib()
01631 {
01632         //
01633         // first do the archetype references
01634         for( REFERENCES_MAP::iterator it = mapOfReferences.begin();
01635                 it != mapOfReferences.end(); ++it)
01636         {
01637                 const UniqueId &guid_of_target = it->first;
01638                 CORE_REFERENCES_VEC &refs     = it->second;
01639                 
01640                 CComPtr<IMgaFCO> lib_target = SearchTool::findLibObj( m_newLib, guid_of_target);
01641                 if( !lib_target)
01642                 {
01643                         // report error:
01644                         // target element of ref not found in library
01645                         lib_target = SearchTool::findLibObj( m_oldLib, guid_of_target);
01646                         MyCComBSTR msg( "Reference target "); 
01647                         if( lib_target)
01648                                 msg.appendLink( lib_target);
01649                         else
01650                                 msg.appendGuid( guid_of_target);
01651                         COMTHROW(msg.Append( L" not found in new library!"));
01652                         m_reporter.show( msg);
01653 
01654                         continue;
01655                 }
01656 
01657                 
01658                 MyCComBSTR mm;
01659                 COMTHROW(mm.Append( L"Redirect refs to target: "));
01660                 mm.appendLink( lib_target);
01661                 m_reporter.show( mm, false);
01662                 for( CORE_REFERENCES_VEC::iterator jt = refs.begin();
01663                         jt != refs.end(); ++jt)
01664                 {
01665                         CComPtr<IMgaFCO> elem_in_proj;
01666                         ObjForCore( *jt)->getinterface( &elem_in_proj);
01667                         CComPtr<IMgaReference> ref_in_proj;
01668                         HRESULT res = E_FAIL;
01669                         long l = OBJECT_DELETED;
01670 
01671                         if( elem_in_proj) 
01672                         {
01673                                 res = elem_in_proj.QueryInterface( &ref_in_proj);
01674                                 if( ref_in_proj) 
01675                                         res = ref_in_proj->get_Status( &l);
01676                         }
01677 
01678                         if( SUCCEEDED( res) && ref_in_proj && l == OBJECT_EXISTS) // if we have a valid reference
01679                         {
01680                                 redirectRefWithCare( ref_in_proj, lib_target);
01681                         }
01682                         else
01683                         {
01684                                 // report error
01685                                 // elem_in_proj is not a reference any more
01686                                 // or is not found any more in the project,
01687                                 // however before RefreshLibrary it was a reference
01688                                 
01689                                 //MyCComBSTR msg("Could not find "); msg.appendLink( id_of_proj_elem, "Reference"); msg.Append( L" in project!");
01690                                 ASSERT(0);
01691                                 MyCComBSTR msg( "Could not find reference "); 
01692                                 msg.appendLink( elem_in_proj);
01693                                 COMTHROW(msg.Append( L" in project!"));
01694                                 m_reporter.show( msg);
01695                         }
01696                 }
01697         }
01698 
01699         //
01700         // now do the derd references (for these order matters)
01701         for( DEP_REFERENCES_MAP::iterator it = mapOfDependentReferences.begin();
01702                 it != mapOfDependentReferences.end(); ++it)
01703         {
01704                 // the key pair consists of the distance of the target (from its archetype) and the target uid
01705                 // so that those references are set first which have archetype targets, or
01706                 // at least higher level targets in a derivation hierarchy
01707                 //const short dist = it->first.first;
01708                 const UniqueId &guid_of_target = it->first.second;
01709                 CORE_REFERENCES_SET &refs     = it->second;
01710                 
01711                 CComPtr<IMgaFCO> lib_target = SearchTool::findLibObj( m_newLib, guid_of_target);
01712                 if( !lib_target)
01713                 {
01714                         // report error:
01715                         // element with guid not found in library
01716                         lib_target = SearchTool::findLibObj( m_oldLib, guid_of_target);
01717                         MyCComBSTR msg( "Reference target "); 
01718                         if( lib_target) msg.appendLink( lib_target);
01719                         else            msg.appendGuid( guid_of_target);
01720                         COMTHROW(msg.Append( L" not found in new library!"));
01721                         m_reporter.show( msg);
01722 
01723                         continue;
01724                 }
01725 
01726                 // lib_target is the new intended target for refs
01727                 for( CORE_REFERENCES_SET::iterator jt = refs.begin();
01728                         jt != refs.end(); ++jt)
01729                 {
01730                         if( m_alreadySetRefs.find( jt->second) != m_alreadySetRefs.end()) // found means already redirected/set
01731                                 continue;
01732 
01733                         CComPtr<IMgaFCO> elem_in_proj;
01734                         ObjForCore( jt->second)->getinterface( &elem_in_proj);
01735 
01736                         CComQIPtr<IMgaReference> ref_in_proj( elem_in_proj);
01737                         
01738                         if( ref_in_proj) // if we have a valid reference
01739                         {
01740                                 // is ref derived from library
01741                                 // or hosting project
01742                                 redirectRefWithCare( ref_in_proj, lib_target);
01743                         }
01744                         else
01745                         {
01746                                 // report error
01747                                 // elem_in_proj is not a reference any more
01748                                 // or is not found any more in the project,
01749                                 // however before RefreshLibrary it was a reference
01750                                 ASSERT(0);
01751                                 MyCComBSTR msg( "Could not find "); 
01752                                 msg.appendLink( elem_in_proj);
01753                                 COMTHROW(msg.Append( L" in project!"));
01754                                 m_reporter.show( msg);
01755                         }
01756                 }
01757         }
01758 
01759         mapOfReferences.clear();
01760 }
01761 
01762 //typedef std::pair< UniqueId, UniqueId >               LIBREF_AND_LIBTARGET;
01763 //typedef std::pair< short, LIBREF_AND_LIBTARGET >      LIB_REFTARG_PAIR;
01766 //typedef std::pair< UniqueId, CoreObj >                MIXED_TARGET;
01768 //typedef std::pair< CoreObj, MIXED_TARGET>             REGREF_AND_TARGET;
01769 //typedef std::vector< REGREF_AND_TARGET >              CORE_DERD_REF_VEC;
01770 //typedef std::map< LIB_REFTARG_PAIR, CORE_DERD_REF_VEC > ADAPTIVE_REFERENCES_MAP;
01771 void RefreshManager::adaptDerRefs()
01772 {
01773         for( SPECIAL_MAP::iterator it = mapOfDerdRefsFromAdaptiveRef.begin();
01774                 it != mapOfDerdRefsFromAdaptiveRef.end(); ++it)
01775         {
01776                 const DIST_AND_REFOBJ  &ref_info = it->first;
01777                 MIXED_TARGET2          &tgt_info = it->second;
01778                 
01779                 const CoreObj          &ref_core = ref_info.second;
01780                 const UniqueId         &tgt_guid = tgt_info.first;
01781                 const CoreObj          &tgt_core = tgt_info.second;
01782 
01783                 if( m_alreadySetRefs.find( ref_core) != m_alreadySetRefs.end()) // found means already redirected/set
01784                         continue;
01785 
01786                 // target
01787                 CComPtr<IMgaFCO> target;
01788 
01789                 if( tgt_guid == UniqueId()) // ptr tgt_core must be valid
01790                 {
01791                         ObjForCore( tgt_core)->getinterface( &target);
01792                 }
01793                 else
01794                 {
01795                         target = SearchTool::findLibObj( m_newLib, tgt_guid);
01796                 }
01797 
01798                 // ref
01799                 CComPtr<IMgaFCO> t_ref;
01800                 ObjForCore( ref_core)->getinterface( &t_ref);
01801                 CComQIPtr<IMgaReference> ref( t_ref);
01802 
01803                 if( ref)
01804                         redirectRefWithCare( ref, target);
01805         }
01806 }
01807 
01808 void RefreshManager::adaptTopRefs()
01809 {
01810         for( ADAPTIVE_REFERENCES_MAP::iterator it = mapOfAdaptiveReferences.begin();
01811                 it != mapOfAdaptiveReferences.end(); ++it)
01812         {
01813                 // the key pair consists of the distance of the target (from its archetype) and the target uid
01814                 // so that those references are set first which have archetype targets, or
01815                 // at least higher level targets in a derivation hierarchy
01816                 const LIB_REFTARG_PAIR  &base = it->first;
01817                 CORE_DERD_REF_VEC       &refs = it->second;
01818                 //short dist = base.first;
01819                 UniqueId base_id = base.second.first;
01820                 UniqueId targ_id = base.second.second;
01821                 
01822                 // finding the base reference
01823                 CComPtr<IMgaFCO> lib_refern = SearchTool::findLibObj( m_newLib, base_id);
01824                 if( lib_refern) 
01825                 {
01826                         CComQIPtr<IMgaReference> lib_r( lib_refern);
01827                         if( lib_r)
01828                         {
01829                                 CComPtr<IMgaFCO> tgt;
01830                                 COMTHROW( lib_r->get_Referred( &tgt));
01831                                 UniqueId frsh_tgt;
01832                                 if( tgt) // fresh version of base_ref has a target
01833                                 {
01834                                         frsh_tgt = Identifier::getDetailsOf( CoreObj( tgt));
01835                                         if( frsh_tgt == targ_id) //base's referral did not change
01836                                         {
01837                                                 // nop, we are satisfied with restoreRefsToLib's job
01838                                                 // we need to redirect safely some of the derived refs
01839                                                 // something similar to restoreRefsToLib
01840                                                 for( CORE_DERD_REF_VEC::iterator jt = refs.begin();
01841                                                         jt != refs.end(); ++jt)
01842                                                 {
01843                                                         CoreObj       &ref2        = jt->first;
01844                                                         MIXED_TARGET  &target_info = jt->second;
01845 
01846                                                         CComPtr<IMgaFCO> elem_in_proj;
01847                                                         ObjForCore( ref2)->getinterface( &elem_in_proj);
01848                                                         CComQIPtr<IMgaReference> ref_in_proj( elem_in_proj);
01849 
01850                                                         UniqueId &derd_tgt_uid        = target_info.first;
01851                                                         CoreObj  &derd_tgt_coreobj    = target_info.second;
01852 
01853                                                         if( derd_tgt_uid.libId != BinGuid()) 
01854                                                         { // lookup the target in the new version of the library
01855                                                                 CComPtr<IMgaFCO> der_target = SearchTool::findLibObj( m_newLib, derd_tgt_uid);
01856                                                                 redirectRefWithCare( ref_in_proj, der_target);
01857                                                         }
01858                                                         else if( derd_tgt_coreobj) // the target was a project object
01859                                                         {
01860                                                                 // although the target object survived the refresh we need to set 
01861                                                                 // back again for ref_in_proj because its ancestors have been
01862                                                                 // reset, thus its settings have been overwritten
01863                                                                 CComPtr<IMgaFCO> der_target;
01864                                                                 ObjForCore( derd_tgt_coreobj)->getinterface( &der_target);
01865                                                                 redirectRefWithCare( ref_in_proj, der_target);
01866                                                         }
01867                                                         else ASSERT(0);
01868                                                         
01869                                                 }
01870                                         }
01871                                         else // base redirected, dependents need redirection too
01872                                         {
01873                                                 if( targ_id == UniqueId()) {} // it was a null ref, easier (set happens)
01874                                                 else {} // old version of ref was referring somewhere (redirection happens)
01875                                                 
01876                                                 // same job:
01877                                                 for( CORE_DERD_REF_VEC::iterator jt = refs.begin();
01878                                                         jt != refs.end(); ++jt)
01879                                                 {
01880                                                         CoreObj &ref2 = jt->first;
01881                                                         CComPtr<IMgaFCO> elem_in_proj;
01882                                                         ObjForCore( ref2)->getinterface( &elem_in_proj);
01883                                                         CComQIPtr<IMgaReference> ref_in_proj( elem_in_proj);
01884 
01885                                                         redirectRefWithCare( ref_in_proj, tgt);
01886                                                         // brutal redirect happeened, mark all dependends of ref_in_proj
01887                                                         ignoreFurtherRedir( ref_in_proj, tgt);
01888                                                 }
01889                                         }
01890                                 }
01891                                 else // null-ref
01892                                 {
01893                                         // propagate down the null-referenceness only if:
01894                                         if( !(targ_id == UniqueId())) // old version of ref was referring somewhere
01895                                         {
01896                                                 for( CORE_DERD_REF_VEC::iterator jt = refs.begin();
01897                                                         jt != refs.end(); ++jt)
01898                                                 {
01899                                                         CoreObj &ref2 = jt->first;
01900                                                         CComPtr<IMgaFCO> elem_in_proj;
01901                                                         ObjForCore( ref2)->getinterface( &elem_in_proj);
01902                                                         CComQIPtr<IMgaReference> ref_in_proj( elem_in_proj);
01903 
01904                                                         // redirect to 0
01905                                                         redirectRefWithCare( ref_in_proj, CComPtr<IMgaFCO>());
01906                                                         // brutal redirect happeened, mark all dependends of ref_in_proj
01907                                                         ignoreFurtherRedir( ref_in_proj, CComPtr<IMgaFCO>());
01908                                                 }
01909                                         }
01910                                         // else : not needed, neither old nor new version point anywhere
01911                                 }
01912                         }
01913                         else
01914                         {
01915                                 ASSERT(0);
01916                         } // non-reference object has the same uid?
01917                 }
01918                 else
01919                 {
01920                 } // not found base in newlib, so the deriveds already are(/will be) deleted
01921         }
01922 }
01923 
01924 void RefreshManager::updateMatchDb( coreobjpairhash& p_creaList)
01925 {
01926         coreobjpairhash::iterator it  = p_creaList.begin();
01927         coreobjpairhash::iterator end = p_creaList.end();
01928         for( ; it != end; ++it)
01929         {
01930                 const CoreObj& oi = it->first;
01931                 const CoreObj& ni = it->second;
01932 
01933                 // important
01934                 PROJ_ID dr_id, bs_id;
01935                 ObjForCore(ni)->get_ID( &dr_id);
01936                 ObjForCore(oi)->get_ID( &bs_id);
01937 #if(DONT_OPTIM)
01938                 m_matchMaker[ dr_id ] = bs_id;
01939 #endif
01940                 m_coreMatchMaker[ ni ] = oi;
01941 
01942 #if(0)
01943                 //important, otherwise how the connections will be found
01944                 //UniqueId bs = Identifier::getDetailsOf( oi);
01945                 //mapOfSecondaryDeriveds[ dr_id ] = bs;
01946 #endif
01947         }
01948 }
01949 
01950 void RefreshManager::copyNewArrivals( CoreObj& p_adaptiveObj, std::vector< CoreObj>& p_newComers
01951                                                                          , SET_CREALIST& p_sets, REF_CREALIST& p_refs)
01952 {
01953         int targetlevel = 0;
01954         unsigned int cnt = p_newComers.size();
01955         CoreObj rootp;
01956         GetRootOfDeriv( p_adaptiveObj, rootp, &targetlevel);
01957 
01958         coreobjpairhash crealist;
01959         std::vector<CoreObj> nobjs( cnt);
01960         for( unsigned int i = 0; i < cnt; ++i)
01961         {
01962                 CoreObj oldobj = p_newComers[i];
01963                 int derdist = GetRealSubtypeDist( oldobj);
01964                 ObjTreeCopy( m_mgaproject, oldobj, nobjs[i], crealist);  // copy
01965                 if( derdist) ObjTreeDist( nobjs[i], derdist);
01966                 // assigns a new relid to nobjs[i]
01967                 ObjForCore( p_adaptiveObj)->assignnewchild( nobjs[i]);
01968 
01969                 // collect the sets (on the topmost level only)
01970                 if( oldobj.GetMetaID() == DTID_SET)
01971                         p_sets.push_back( std::make_pair( nobjs[i], oldobj));
01972                 else if( oldobj.GetMetaID() == DTID_REFERENCE)
01973                         p_refs.push_back( std::make_pair( nobjs[i], oldobj));
01974         }
01975 
01976         for( unsigned int i = 0; i < cnt; ++i)
01977         {
01978                 ObjTreeReconnect( nobjs[i], crealist);
01979         }
01980 
01981         // important!
01982         // update our matchinfo storage
01983         // (used later to recreate connections)
01984         updateMatchDb( crealist);
01985 
01986         coreobjhash newcrealist;
01987         shiftlist(crealist, newcrealist);
01988 
01989         for( unsigned int i = 0; i < cnt; ++i)
01990         {
01991                 ObjTreeCheckRelations( m_mgaproject, nobjs[i], newcrealist);
01992         }
01993 
01994         if(targetlevel >= 0) ReDeriveNewObjs( m_mgaproject, nobjs, cnt, targetlevel+1);
01995 }
01996 
01997 // let's remove those children of adaptiveobj which were once derived
01998 // from the master's children, but now we face that the master has been
01999 // simplified (some of its children are not present any more in it)
02000 // (Subtypes may contain additional children, those are not affected.)
02001 // By using the mapOfSecondaryDeriveds we decide the was-it-once-derived? question
02002 void RefreshManager::removeObsoleteChildren( const CoreObj& masterObj, CoreObj& adaptiveobj)
02003 {
02004         CoreObjs children = adaptiveobj[ATTRID_FCOPARENT + ATTRID_COLLECTION];
02005         ITERATE_THROUGH(children) {
02006                 PROJ_ID my_id;
02007                 ObjForCore(ITER)->get_ID( &my_id);
02008                 CComPtr<IMgaFCO> iter_fco;
02009                 ObjForCore(ITER)->getinterface( &iter_fco);
02010 
02011                 SEC_DER_NAP::iterator secder_jterator = napOfSecondaryDeriveds.find( iter_fco);
02012 #if(DONT_OPTIM)
02013                 SEC_DER_MAP::iterator secder_iterator = mapOfSecondaryDeriveds.find( my_id );
02014                 if( secder_iterator != mapOfSecondaryDeriveds.end()) // it is (actually was) a sec derived
02015 #endif
02016                 if( secder_jterator != napOfSecondaryDeriveds.end()) // it is (actually was) a sec derived
02017                 {
02018                         ASSERT( secder_jterator != napOfSecondaryDeriveds.end());
02019 
02020                         bool valid = true;
02021                         if( m_coreMatchMaker.find( ITER) == m_coreMatchMaker.end())
02022                         {
02023                                 // ITER seems to be an object whose base no longer exists in the fresh library
02024                                 valid = false;
02025                         }
02026 #if(DONT_OPTIM)
02027                         if( m_matchMaker.find( my_id) == m_matchMaker.end())
02028                         {
02029                                 // ITER seems to be an object whose base no longer exists in the fresh library
02030                                 if( valid) ASSERT(0); // TODO: is m_matchMaker needed at all? this line will detect it
02031                                 valid = false;
02032                         }
02033 #endif
02034                         if( !valid) // need to delete it
02035                         {
02036 //#ifdef _DEBUG
02037                                 MyCComBSTR msg;
02038                                 COMTHROW(msg.Append( L"Orphan child "));
02039                                 msg.appendLink( ObjForCore(ITER));
02040                                 COMTHROW(msg.Append( L" deleted."));
02041                                 m_reporter.show( msg, false);
02042 //#endif
02043                                 ObjForCore(ITER)->inDeleteObject();
02044                         }
02045                 }
02046                 else
02047                         ASSERT( secder_jterator == napOfSecondaryDeriveds.end());
02048         }
02049 }
02050 
02051 void RefreshManager::SyncDerSets( const CoreObj &p_frMasterSet, CoreObj &p_adaptiveSet
02052                                 , const CoreObj &p_frMasterPar, CoreObj &p_adaptivePar)
02053 {
02054         CComPtr<IMgaModel> masterParent, adaptvParent;
02055         ObjForCore( p_frMasterPar)->getinterface( &masterParent);
02056         ObjForCore( p_adaptivePar)->getinterface( &adaptvParent);
02057         CComPtr<IMgaSet> masterSet, adaptvSet;
02058         ObjForCore( p_frMasterSet)->getinterface( &masterSet);
02059         ObjForCore( p_adaptiveSet)->getinterface( &adaptvSet);
02060 
02061         CComPtr<IMgaFCOs> membs;
02062         COMTHROW( masterSet->get_Members( &membs));
02063         long c = 0;
02064         if( membs) COMTHROW( membs->get_Count( &c));
02065         for( long i = 1; i <= c; ++i)
02066         {
02067                 CComPtr<IMgaFCO> b_memb, d_memb;
02068                 COMTHROW( membs->get_Item( i, &b_memb));
02069                 getLibDerdEquiv( b_memb, masterParent, adaptvParent, d_memb);
02070                 
02071                 if( d_memb  // if member found and it is a sybling of the set (must be)
02072                         && COM_EQUAL( CoreObj(p_adaptiveSet[ATTRID_FCOPARENT]), CoreObj(CoreObj(d_memb)[ATTRID_FCOPARENT])))
02073                 {
02074                         COMTHROW( adaptvSet->AddMember( d_memb));
02075                 }
02076                 else
02077                 {
02078                         MyCComBSTR msg;
02079                         COMTHROW(msg.Append( L"Could not find derived peer of "));
02080                         msg.appendLink( b_memb);
02081                         COMTHROW(msg.Append( L" in order to add as a member in "));
02082                         msg.appendLink( adaptvSet);
02083                         m_reporter.show( msg);
02084                 }
02085         }
02086 }
02087 
02088 void RefreshManager::SyncDerRefs( const CoreObj &p_frMasterRef, CoreObj &p_adaptiveRef
02089                                 , const CoreObj &p_frPrimaryMasterPar, const CoreObj &p_primaryAdaptivePar)
02090 {
02091         CComPtr<IMgaModel> masterParent, adaptvParent;
02092         ObjForCore( p_frPrimaryMasterPar)->getinterface( &masterParent);
02093         ObjForCore( p_primaryAdaptivePar)->getinterface( &adaptvParent);
02094         CComPtr<IMgaReference> masterRef, adaptvRef;
02095         ObjForCore( p_frMasterRef)->getinterface( &masterRef);
02096         ObjForCore( p_adaptiveRef)->getinterface( &adaptvRef);
02097 
02098         CComPtr<IMgaFCO> b_tgt, d_tgt;
02099         COMTHROW( masterRef->get_Referred( &b_tgt));
02100         if( b_tgt) 
02101         {
02102                 getLibDerdEquiv( b_tgt, masterParent, adaptvParent, d_tgt, false); // no limitation if parent, grandparent ...
02103                 if( d_tgt)
02104                 {
02105                         COMTHROW( adaptvRef->put_Referred( d_tgt));
02106                 }
02107                 else
02108                 {
02109                         MyCComBSTR msg;
02110                         COMTHROW(msg.Append( L"Could not find derived peer of "));
02111                         msg.appendLink( b_tgt);
02112                         COMTHROW(msg.Append( L" in order to set as target of "));
02113                         msg.appendLink( adaptvRef);
02114                         m_reporter.show( msg);
02115                 }
02116         }
02117 }
02118 
02119 void RefreshManager::SyncObjectName( const CoreObj& p_masterObj, CoreObj &p_adaptiveObj)
02120 {
02121         // ITER must be a secondary derived, so propagate name change down
02122         CComBSTR masters_name = p_masterObj[ATTRID_NAME];
02123         CComBSTR adaptivs_name = p_adaptiveObj[ATTRID_NAME];
02124         if( adaptivs_name != masters_name) {
02125                 //put_NameTask( adaptivs_name, masters_name).DoWithDeriveds( p_adaptiveObj);
02126                 ObjForCore( p_adaptiveObj)->put_Name( masters_name);
02127         }
02128 }
02129 // masterobj is the fresh base
02130 // adaptiveobj is the (previously detached) derived object
02131 // these two must be synchronized
02132 // since the method is used recursively we have 
02133 // priMasterObj as the primary base
02134 // priAdaptiveObj as the primary derived (previously detached)
02135 void RefreshManager::SyncDerObjs( const CoreObj &masterobj, CoreObj &adaptiveobj
02136                                                                  , long instance, bool prim
02137                                                                  , const CoreObj &priMasterObj, const CoreObj &priAdaptiveObj)
02138 {
02139         // this is a variable which can change the behaviour when
02140         // a subtype is attached to a changed (simplified) basetype:
02141         //  true: any secondary derived object which now due to 
02142         //        simplification remained without base (its base
02143         //        was deleted from the primary basetype) will be deleted
02144         //  false: the old secondary derived objects now without base
02145         //         will be altered such that they will become archetypes
02146         //         in the containing subtype
02147         // static bool basetype_simplification_propagated_down = true;
02148 
02149         // this will hold those objects which have appeared in the new version of the library
02150         std::vector< CoreObj > newcomers;
02151 
02152         CComPtr<ICoreAttributes> atts;
02153         COMTHROW(masterobj->get_Attributes(&atts));
02154 
02155         MGACOLL_ITERATE(ICoreAttribute, atts) {
02156                         attrid_type ai;
02157                         CComPtr<ICoreMetaAttribute> mattr;
02158                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
02159                         COMTHROW(mattr->get_AttrID(&ai));
02160 
02161                         if(ai >= ATTRID_COLLECTION) {
02162                                 ai -= ATTRID_COLLECTION;
02163                                 if(LINKREF_ATTR(ai))  {
02164                                         if( ai == ATTRID_ATTRPARENT)       { } // don't care
02165                                         else if( ai == ATTRID_CONSTROWNER) { } // don't care
02166                                         else if( ai == ATTRID_CONNROLE)    { } // manually propagated, see collectFreshConnection below
02167                                         else if( ai == ATTRID_SETMEMBER)   { } // manually set, see SyncDerSets below
02168                                         else if( ai == ATTRID_FCOPARENT)
02169                                         {
02170                                                 {CoreObjs new_base_children = masterobj[ai + ATTRID_COLLECTION];
02171                                                 ITERATE_THROUGH(new_base_children) {
02172                                                         metaid_type meta_id = ITER.GetMetaID();
02173         
02174                                                         // acquire id and uid
02175                                                         PROJ_ID bs_id;
02176                                                         ObjForCore(ITER)->get_ID( &bs_id);
02177                                                         UniqueId bs_uid = Identifier::getDetailsOf( ITER);
02178 
02179                                                         // current original object held in outer_ITER
02180                                                         // actually is an element of the fresh basetype
02181                                                         // whose fresh inner elements need to be propagated 
02182                                                         // into adaptiveobj (a previously detached derdtype)
02183                                                         CoreObj outer_ITER = ITER;
02184                                                         bool fnd = false;
02185                                                         {CoreObjs detached_derd_children = adaptiveobj[ai + ATTRID_COLLECTION];
02186                                                         ITERATE_THROUGH(detached_derd_children) {
02187                                                                 // acquire id
02188                                                                 PROJ_ID dr_id;
02189                                                                 ObjForCore(ITER)->get_ID( &dr_id);
02190                                                                 CComPtr<IMgaFCO> iter_fco;
02191                                                                 ObjForCore(ITER)->getinterface( &iter_fco);
02192                                                                 
02193                                                                 // check if ITER (adaptiveobj's child) was a previously
02194                                                                 // dependent object (a secondary derived) or just an object
02195                                                                 // inserted as an archetype (possible only in subtypes)
02196                                                                 SEC_DER_NAP::iterator secder_jterator = napOfSecondaryDeriveds.find( iter_fco);
02197 #if(DONT_OPTIM)
02198                                                                 SEC_DER_MAP::iterator secder_iterator = mapOfSecondaryDeriveds.find( dr_id );
02199                                                                 if( secder_iterator != mapOfSecondaryDeriveds.end()) // yes, it was a sec derived
02200 #endif
02201                                                                 if( secder_jterator != napOfSecondaryDeriveds.end()) // yes, it was a sec derived
02202                                                                 {
02203                                                                         ASSERT( secder_jterator != napOfSecondaryDeriveds.end());
02204                                                                         // uid of old-base stored in VALUE
02205                                                                         UniqueId mine_bs_uid;
02206 #if(DONT_OPTIM)
02207                                                                         mine_bs_uid = secder_iterator->second;
02208 #endif
02209                                                                         mine_bs_uid = secder_jterator->second;
02210 
02211                                                                         if( bs_uid == mine_bs_uid                             // ITER was derived from outer_ITER before detach
02212                                                                                 && outer_ITER[ATTRID_META] == ITER[ATTRID_META])  // in the same role
02213                                                                         {
02214 #if(DONT_OPTIM)
02215                                                                                 m_matchMaker[ dr_id ] = bs_id;
02216 #endif
02217                                                                                 m_coreMatchMaker[ ITER] = outer_ITER;
02218                                                                                 
02219                                                                                 // for sec derd objects names are synchronized
02220                                                                                 SyncObjectName( outer_ITER, ITER);
02221 
02222                                                                                 if( meta_id == DTID_MODEL)
02223                                                                                 {
02224                                                                                         SyncDerObjs( outer_ITER, ITER, instance, false, priMasterObj, priAdaptiveObj);
02225                                                                                 }   // nothing to do for connections since they have no inner objects
02226 
02227                                                                                 fnd = true;
02228                                                                                 break;
02229                                                                         }
02230                                                                 }
02231                                                                 else
02232                                                                         ASSERT( secder_jterator == napOfSecondaryDeriveds.end());
02233                                                         }}
02234                                                         
02235                                                         if( !fnd) // fresh object in basetype
02236                                                         {
02237                                                                 if( meta_id == DTID_CONNECTION)
02238                                                                         collectFreshConnection( ITER, masterobj, adaptiveobj);
02239                                                                 else
02240                                                                         newcomers.push_back( ITER);
02241                                                         }
02242                                                 }}
02243 
02244                                                 //do it anyway
02245                                                 //if( basetype_simplification_propagated_down)
02246                                                 removeObsoleteChildren( masterobj, adaptiveobj);
02247                                         }
02248                                 }
02249                         }
02250 
02251         } MGACOLL_ITERATE_END;
02252 
02253         if( newcomers.size() > 0)
02254         {
02255                 // will contain the sets which are strictly children of adaptiveobj (excludes granchildren, ...)
02256                 // the inner sets will be copied along with their members, thus they don't need special care
02257                 SET_CREALIST set_pairs; REF_CREALIST ref_pairs;
02258                 copyNewArrivals( adaptiveobj, newcomers, set_pairs, ref_pairs);
02259                 
02260                 // if any set copied restore their members right now
02261                 for( unsigned int i = 0; i < set_pairs.size(); ++i)
02262                 {
02263                         //call SyncSets with (base_set  , derd_set          , base_parent, derd_parent)
02264                         SyncDerSets( set_pairs[i].second, set_pairs[i].first, masterobj, adaptiveobj);
02265                 }
02266 
02267                 // if refs
02268                 for( unsigned int i = 0; i < ref_pairs.size(); ++i)
02269                 {
02270                         SyncDerRefs( ref_pairs[i].second, ref_pairs[i].first, priMasterObj, priAdaptiveObj);
02271                 }
02272         }
02273 }
02274 
02275 void RefreshManager::syncStructureFromLib()
02276 {
02277         for( SUB_PAR_MAP::iterator it = mapOfDeriveds.begin();
02278                 it != mapOfDeriveds.end(); ++it)
02279         {
02280                 const UniqueId &guid_of_base   = it->first;
02281                 SUB_PAR_VEC    &pair_vec       = it->second;
02282 
02283                 CComPtr<IMgaFCO> lib_base = SearchTool::findLibObj( m_newLib, guid_of_base);
02284                 if( lib_base) // new version of the object found in new library
02285                 {
02286                         for( SUB_PAR_VEC::iterator jt = pair_vec.begin();
02287                                 jt != pair_vec.end(); ++jt)
02288                         {
02289                                 CComPtr<IMgaFCO> &prev_detached_obj = jt->subt_ptr;
02290 
02291                                 long st(-1);
02292                                 HRESULT hr = E_FAIL;
02293                                 if( prev_detached_obj) hr = prev_detached_obj->get_Status( &st);
02294                                 //CComPtr<IMgaFCO> prev_detached_obj = SearchTool::findRegularObj( m_mgaproject, nfolder, jt->subt_id);
02295                                 //if( prev_detached_obj)
02296                                 if( SUCCEEDED( hr) && st == OBJECT_EXISTS && prev_detached_obj) // a valid object ptr
02297                                 {
02298                                         CoreObj prev_detached( prev_detached_obj);
02299                                         CoreObj frsh_base( lib_base);
02300                                         
02301                                         // sync structure of fresh base with detached derive
02302                                         // the last two parameters helps in redirection of the internal references
02303                                         SyncDerObjs( frsh_base, prev_detached, 0, true, frsh_base, prev_detached);
02304                                         
02305                                         PROJ_ID b_id, d_id;
02306                                         COMTHROW( lib_base->get_ID( &b_id));
02307                                         COMTHROW( prev_detached_obj->get_ID( &d_id));
02308                                         // store the match info
02309                                         m_primMatchMaker[ prev_detached] = std::make_pair( frsh_base, jt->is_instance);
02310                                         m_coreMatchMaker[ prev_detached] = frsh_base;
02311 #if(DONT_OPTIM)
02312                                         m_matchMaker[ d_id ] = b_id;
02313 #endif
02314 
02315                                         MyCComBSTR msg;
02316                                         msg.appendLink( ObjForCore(frsh_base));
02317                                         COMTHROW(msg.Append( L" derived to "));
02318                                         msg.appendLink( ObjForCore(prev_detached));
02319                                         m_reporter.show( msg, false);
02320                                 }
02321                                 else
02322                                 {
02323                                         ASSERT(0); // error
02324                                         MyCComBSTR msg(" Could not find detached object "); msg.appendLink( jt->subt_ptr);
02325                                         COMTHROW(msg.Append( L" while trying to re-attach to base!"));
02326                                         m_reporter.show( msg);
02327                                 }
02328                         }
02329                 }
02330                 else
02331                 {
02332 #ifdef _DEBUG
02333                         // report library backroll: lib_base not found in new library
02334                         CComPtr<IMgaFCO> old_lib_base = SearchTool::findLibObj( m_oldLib, guid_of_base);
02335                         MyCComBSTR msg("Archetype "); 
02336                         if( old_lib_base) msg.appendLink( old_lib_base);
02337                         else              msg.appendGuid( guid_of_base);
02338                         msg.Append( L" not found in refreshed library.");
02339                         m_reporter.show( msg);
02340 #endif
02341                         // lib_base not found -> delete all existing primary (and secondary?) subtypes
02342                         for( SUB_PAR_VEC::iterator jt = pair_vec.begin();
02343                                 jt != pair_vec.end(); ++jt)
02344                         {
02345                                 //CComPtr<IMgaFCO> prev_detached_obj = SearchTool::findRegularObj( m_mgaproject, m_newLib, jt->subt_id);
02346                                 CComPtr<IMgaFCO> &prev_detached_obj = jt->subt_ptr;
02347                                 if( prev_detached_obj)
02348                                 {
02349 //#ifdef _DEBUG
02350                                         MyCComBSTR msg;
02351                                         msg.appendLink( prev_detached_obj);
02352                                         COMTHROW(msg.Append( L" deleted as "));
02353                                         if( jt->is_instance)
02354                                                 COMTHROW(msg.Append( L"an instance"));
02355                                         else
02356                                                 COMTHROW(msg.Append( L"a subtype"));
02357                                         COMTHROW(msg.Append( L" of an obsolete library object."));
02358                                         m_reporter.show( msg, false);
02359 //#endif
02360                                         ObjForCore(CoreObj(prev_detached_obj))->inDeleteObject();
02361                                 }
02362                         }
02363                 }
02364         }
02365 }
02366 
02367 void RefreshManager::reapplyLibFlagToChangedLibs()
02368 {
02369         ASSERT( m_mgaproject);
02370         if( !m_mgaproject) return;
02371 
02372         CComBSTR id; // the refreshed library's id
02373         COMTHROW( ObjForCore( m_newLib)->get_ID( &id));
02374 
02375         CComBSTR idlist;
02376         Ozer::StorageMgr::getIncludedBy( m_oldLib, idlist);
02377         for( Ozer::DependentIterator it( idlist); !it.isDone(); it.next())
02378         {
02379                 CoreObj libroot;
02380                 CComPtr<IMgaFolders> coll;
02381                 COMTHROW( m_mgaproject->GetTopLibraries( it.getCurrentBstr(), &coll));
02382                 // this lib may have gotten new elements during refresh, that's why
02383                 // for all such libs reapply the LIB flag onto the hierarchy
02384                 long len( 0);
02385                 if( coll) COMTHROW( coll->get_Count( &len));
02386                 for( long i = 1; i <= len; ++i)
02387                 {
02388                         CComPtr<IMgaFolder> ele;
02389                         COMTHROW( coll->get_Item( i, &ele));
02390                         applyLibFlag( CoreObj( ele));
02391                 }
02392         }
02393 }
02394 
02395 void RefreshManager::applyLibFlag( CoreObj& p_libObj)
02396 {
02397         // for all children
02398         CoreObjs kids = p_libObj[ATTRID_FCOPARENT + ATTRID_COLLECTION];
02399         ITERATE_THROUGH(kids) {
02400                 ITER[ATTRID_PERMISSIONS] = ITER[ATTRID_PERMISSIONS] | LIBRARY_FLAG;
02401 
02402                 if( ITER.IsContainer()) applyLibFlag( ITER);
02403         }
02404 }
02405 
02406 void RefreshManager::propObjRelidIncV2( CoreObj& p_obj)
02407 {
02408         long brelid = p_obj[ATTRID_RELID];
02409 
02410         // for all deriveds from p_obj
02411         CoreObjs deriveds = p_obj[ATTRID_DERIVED + ATTRID_COLLECTION];
02412         ITERATE_THROUGH(deriveds) {
02413                 // increase depth
02414                 ITER[ATTRID_RELID] = brelid + RELIDSPACE;
02415 
02416                 propObjRelidIncV2( ITER);
02417         }
02418 }
02419 
02420 void RefreshManager::DetachObjFromLibBase( const CoreObj& p_baseObj, CoreObj& p_derdObj, unsigned long nextrelid, bool prim)
02421 {
02422         bool has_last_relid_attr = false;
02423         long last_relid_set = 0;
02424         long max_relid_found= 0;
02425 #ifdef _DEBUG
02426         char p[151];p[0] = 0;
02427 #endif
02428 
02429         CComPtr<ICoreAttributes> atts;
02430         COMTHROW(p_baseObj->get_Attributes(&atts));
02431         MGACOLL_ITERATE(ICoreAttribute, atts) {
02432                         attrid_type ai;
02433                         CComPtr<ICoreMetaAttribute> mattr;
02434                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
02435                         COMTHROW(mattr->get_AttrID(&ai));
02436                         if(ai < ATTRID_COLLECTION) {
02437                                 switch(ai) {
02438                                         case ATTRID_GUID1:
02439                                         case ATTRID_GUID2:
02440                                         case ATTRID_GUID3:
02441                                         case ATTRID_GUID4: 
02442                                                 break; // do not copy from base these values
02443 
02444                                         case ATTRID_DERIVED: 
02445                                         case ATTRID_MASTEROBJ:
02446                                         {
02447                                                 p_derdObj[ai] = CComVariant( (IDispatch*) 0);//an empty value;
02448                                                 break;
02449                                         }
02450                                         case ATTRID_PERMISSIONS:
02451                                         {
02452                                                 //if( p_derdObj[ai] & INSTANCE_FLAG) //if INSTANCE_FLAG present
02453                                                 //      p_derdObj[ai] = (p_baseObj[ai]) & ~INSTANCE_FLAG;//then INSTANCE_FLAG removed;
02454                                                 
02455                                                 //do not copy the permissions from the base
02456                                                 p_derdObj[ai] = 0;
02457                                                 break;
02458                                         }
02459                                         case ATTRID_RELID:
02460                                         {
02461                                                 break;
02462                                         }
02463                                         case ATTRID_LASTRELID:
02464                                         {
02465                                                 // old val contains the number of the plain objects only
02466                                                 last_relid_set = p_derdObj[ai];
02467                                                 has_last_relid_attr = true;
02468                                                 break;
02469                                         }
02470 
02471                                         default:
02472                                                 break; // no copy/change needed in other plain cases
02473 
02474                                 } // endswitch
02475                         }
02476                         else if( LINKREF_ATTR(ai-ATTRID_COLLECTION)){
02477                                 ai -= ATTRID_COLLECTION;
02478 
02479                                 switch( ai) {
02480                                         case ATTRID_CONSTROWNER:        // the subobjects which are owned by p_derdObj
02481                                         case ATTRID_ATTRPARENT:         // p_baseObj's subobjects will be forgotten
02482                             break;                  // and when the new version is reattached
02483                                                     // then those will be propagated down to p_derdObj
02484                                                     // automatically by the derivation relationship
02485 
02486                                         case ATTRID_FCOPARENT: // for all secondary derived fco children-> detach
02487                                         {
02488                                                 // we will calc the max_relid of those child objects which are not secondary, tertiary, ... objects
02489                                                 // because in case of subtypes not all children originate from the current base:
02490                                                 // some children might be plain objects, and some others may be primary subtypes of other bases
02491                                                 //long cur_max_relid = p_derdObj[ATTRID_LASTRELID];
02492                                                 CoreObjs children = p_derdObj[ai + ATTRID_COLLECTION];
02493                                                 ITERATE_THROUGH(children) {
02494                                                         CoreObj base = (ITER)[ATTRID_DERIVED];
02495                                                         if( base) // child is also derived
02496                                                         {
02497                                                                 //MyCComBSTR m;
02498                                                                 //m.appendLink( ObjForCore( base));
02499                                                                 //m.Append( L" <--- ");
02500                                                                 //m.appendLink( ObjForCore( ITER));
02501                                                                 //m_reporter.show( m);
02502 
02503                                                                 VARIANT_BOOL primDer = VARIANT_FALSE;
02504                                                                 if( p_derdObj.IsFCO())
02505                                                                 {
02506                                                                         ObjForCore( ITER)->get_IsPrimaryDerived( &primDer);
02507                                                                         PROJ_ID my_id;
02508                                                                         ObjForCore( ITER)->get_ID( &my_id);
02509                                                                         UniqueId base_guid = Identifier::getDetailsOf( base);
02510 
02511                                                                         CComPtr<IMgaFCO> my_pt;
02512                                                                         ObjForCore(ITER)->getinterface( &my_pt);
02513 #if(DONT_OPTIM)
02514                                                                         mapOfSecondaryDeriveds [ my_id ] = base_guid;
02515 #endif
02516 #ifdef _DEBUG
02517                                                                         //MyCComBSTR m;
02518                                                                         //m.Append( my_id);
02519                                                                         //m.Append( L" ----::---- ");
02520                                                                         //if( primDer != VARIANT_TRUE) 
02521                                                                         //      m.Append( L" napOfSec");
02522                                                                         //else
02523                                                                         //      m.Append( L" nop");
02524                                                                         //m_reporter.show( m);
02525 #endif
02526                                                                         // check if its really a secondary derived object
02527                                                                         // before storing into map
02528                                                                         // FIX for bug submitted by Pramod
02529                                                                         // when A, B have subtypes AS and BS, and BS gets a new child
02530                                                                         // an instance of AS: ASI
02531                                                                         // upon refresh ASI was deleted as an orphan child
02532                                                                         // because it was derived and it seemed secondary derived
02533                                                                         // along with it parent, however it wasn't
02534                                                                         if( primDer != VARIANT_TRUE) 
02535                                                                                 napOfSecondaryDeriveds [ my_pt ] = base_guid;
02536                                                                 }
02537 
02538                                                                 if( primDer != VARIANT_TRUE) // it is a child derived along with 'p_baseObj'
02539                                                                 {
02540                                                                         // detach it as well from its base
02541                                                                         DetachObjFromLibBase( base, ITER, 0, false);
02542                                                                 }
02543                                                                 else 
02544                                                                 {       // it might be a primary subtype/instance placed into this subtype
02545                                                                         // leave this object untouched
02546                                                                 }
02547                                                         }
02548                                                         else
02549                                                         {       // additional child->no action needed
02550                                                         }
02551 
02552                                                         long i_relid = ITER[ATTRID_RELID];
02553                                                         if( i_relid < RELIDSPACE)
02554                                                                 max_relid_found = std::max(max_relid_found, i_relid);
02555                                                 }
02556                                                 break;
02557                                         }
02558                                         default: // for all others (CONNROLE, SETMEMB, REF) -> detach, 
02559                                         {        // otherwise they will be killed along with their master
02560 #ifdef _DEBUG
02561                                                 char p2[150];
02562                                                 sprintf( p2, "(%u) ", ai);
02563                                                 strcat( p, p2);
02564 #endif
02565                                                 // don't let connections die
02566                                                 CoreObjs collmembers = p_derdObj[ai + ATTRID_COLLECTION];
02567                                                 ITERATE_THROUGH(collmembers) {
02568                                                         // remove the ATTRID_DERIVED attrs if any?
02569                                                         // NOTE: 1st parameter is a dummy one: ITER
02570                                                         DetachObjFromLibBase( ITER, ITER, 0, false);
02571                                                 }
02572                                         }
02573                                 }; // endswitch
02574                         }
02575         } MGACOLL_ITERATE_END;
02576 
02577         if( has_last_relid_attr // if this CoreObj had RELID_LAST attribute
02578                 && max_relid_found > last_relid_set) // additional objects became plain
02579         {
02580                 p_derdObj[ATTRID_LASTRELID] = max_relid_found;
02581         }
02582 }
02583 
02584 void RefreshManager::AttachDerObjs( const CoreObj &p_baseObj, CoreObj &p_derdObj, long instance, bool prim) 
02585 {
02586         long nb_of_children = 0;
02587         long last_relid_set = 0;
02588         long max_relid_found= 0;
02589         bool has_last_relid_attr = false;
02590         bool instance_met = false;
02591         CComPtr<ICoreAttributes> atts;
02592         COMTHROW( p_baseObj->get_Attributes(&atts));
02593         MGACOLL_ITERATE(ICoreAttribute, atts) {
02594                         attrid_type ai;
02595                         CComPtr<ICoreMetaAttribute> mattr;
02596                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
02597                         COMTHROW(mattr->get_AttrID(&ai));
02598                         if(ai < ATTRID_COLLECTION) {
02599                                 switch(ai) {
02600                                         case ATTRID_GUID1:
02601                                         case ATTRID_GUID2:
02602                                         case ATTRID_GUID3:
02603                                         case ATTRID_GUID4: 
02604                                                 break; // nop
02605 
02606                                         case ATTRID_DERIVED: 
02607                                         case ATTRID_MASTEROBJ:
02608                                         {
02609                                                 p_derdObj[ai] = p_baseObj;
02610                                                 break;
02611                                         }
02612                                         case ATTRID_PERMISSIONS:
02613                                         // if it was instance or p_baseObj is instance or it is supposed to be an instance:
02614                                         {
02615                                                         p_derdObj[ai] = (p_derdObj[ai] | p_baseObj[ai] | long(instance)) & INSTANCE_FLAG;
02616                                                         instance_met = p_derdObj[ai] & INSTANCE_FLAG;
02617                                                         break;
02618                                         }
02619                                         case ATTRID_RELID: 
02620                                         {
02621                                                 if(!prim)
02622                                                 {       // Damage Control for GME-145 entry in JIRA
02623                                                         // relids were messed up by the other PropObjRelidInc mechanism
02624                                                         // because it was invoked to all children of the derd
02625                                                         // and children are not always homogeneous
02626                                                         unsigned long lb = p_baseObj[ai];
02627                                                         unsigned long ld = p_derdObj[ai];
02628                                                         if( ld <= lb) // FIXME: is this necessary?
02629                                                         {       // Shift relid
02630                                                                 p_derdObj[ai] = lb + RELIDSPACE;
02631                                                                 propObjRelidIncV2( p_derdObj);
02632 #ifdef _DEBUG
02633                                                                 CComBSTR msg = p_derdObj[ATTRID_NAME];
02634                                                                 msg.Append( " relid problem corrected");
02635                                                                 m_reporter.show( msg, false);
02636 #endif
02637                                                         }
02638                                                 }
02639                                                 break;
02640                                         }
02641                                         case ATTRID_LASTRELID: 
02642                                         {
02643                                                 last_relid_set = p_derdObj[ai];
02644                                                 has_last_relid_attr = true;
02645                                                 break;
02646                                         }
02647                                         
02648                                         default:
02649                                                 break;
02650                                 } // endswitch
02651                         }
02652         } MGACOLL_ITERATE_END;
02653 
02654         MGACOLL_ITERATE(ICoreAttribute, atts) {
02655                         attrid_type ai;
02656                         CComPtr<ICoreMetaAttribute> mattr;
02657                         COMTHROW(MGACOLL_ITER->get_MetaAttribute(&mattr));
02658                         COMTHROW(mattr->get_AttrID(&ai));
02659 
02660                         if(ai >= ATTRID_COLLECTION) {
02661                                 ai -= ATTRID_COLLECTION;
02662                                 if(LINKREF_ATTR(ai))  {
02663                                         //if( ai == ATTRID_ATTRPARENT)       { } // no need to copy these since the
02664                                         //else if( ai == ATTRID_CONSTROWNER) { } // automatically
02665                                         if(ai == ATTRID_CONNROLE) {
02666                                                 // ConnRoles also depend on their base with ATTRID_MASTEROBJ
02667                                                 // that's how a derived connections will be compared by
02668                                                 // ConnCompareToBase to its base.
02669                                                 // Thus the connroles will not be dumped into XML for derived conns
02670                                                 CoreObjs roles = p_derdObj[ai + ATTRID_COLLECTION];
02671                                                 ITERATE_THROUGH( roles) {
02672                                                         CComBSTR n = ITER[ATTRID_NAME];
02673                                                         CoreObj outer_ITER = ITER;
02674                                                         ITERATE_THROUGH( p_baseObj[ai + ATTRID_COLLECTION]) {
02675                                                                 CComBSTR in = ITER[ATTRID_NAME];
02676                                                                 if( n == in)
02677                                                                 {
02678                                                                         // almost similar to calling AttachDerObjs( ITER, outer_ITER, ...)
02679                                                                         // but simpler
02680                                                                         outer_ITER[ATTRID_MASTEROBJ] = ITER;
02681                                                                         break;
02682                                                                 }
02683                                                         }
02684                                                 }
02685                                         }
02686                                         if(ai == ATTRID_FCOPARENT) {
02687 
02688                                                 CoreObjs children_derd = p_derdObj[ai + ATTRID_COLLECTION];
02689                                                 ITERATE_THROUGH(children_derd) {
02690                                                         ++nb_of_children;
02691                                                         if( m_coreMatchMaker.find( ITER) != m_coreMatchMaker.end())
02692                                                         {
02693                                                                 CoreObj bs = m_coreMatchMaker[ ITER];
02694                                                                 bool found = false;
02695                                                                 {CoreObjs children_base = p_baseObj[ai + ATTRID_COLLECTION];
02696                                                                 ITERATE_THROUGH(children_base) {
02697                                                                         if( ITER == bs) found = true;
02698                                                                 }}
02699 
02700                                                                 if( found)
02701                                                                 {
02702                                                                         AttachDerObjs( bs, ITER, instance, false);
02703                                                                 }
02704 
02705                                                         }
02706                                                         // else: will become an archetype child in subtype. OK.
02707                                                         //       and what about instances? NOK.
02708                                                         else if( instance)
02709                                                                 ASSERT(0);
02710                                                 
02711                                                         long i_relid = ITER[ATTRID_RELID];
02712                                                         if( i_relid < RELIDSPACE)
02713                                                                 max_relid_found = std::max(max_relid_found, i_relid);
02714                                                 }
02715                                         }
02716                                 }
02717                         }
02718 
02719         } MGACOLL_ITERATE_END;
02720 
02721         if( has_last_relid_attr // if this CoreObj has RELID_LAST attribute
02722          && max_relid_found < last_relid_set) // prefer lower last relid
02723         {
02724                 p_derdObj[ATTRID_LASTRELID] = max_relid_found;
02725         }
02726 
02727 }
02728 
02729 // called from collectDersFromLib, in order to find and store all library dependent references
02730 // (aka adaptive refs) which must be conforming (as far as their target is concerned) to their
02731 // library object base
02732 // not only the immediate deriveds are considered to be adaptive, but their deriveds also
02733 // (the whole ref hierarchy stemming from the library reference)
02734 void RefreshManager::collectRefsDerdFromLib( CoreObj& one_ref, CoreObj& bas_ref)
02735 {
02736         // one_ref is (in the project) a primary derived object from a library object
02737         if( one_ref.GetMetaID() != DTID_REFERENCE) return;
02738 
02739 #if(0)
02740         CoreObj tgt = one_ref[ATTRID_REFERENCE];
02741 
02742         short dist_tgt = 0;
02743         elem_struct elem_tgt;
02744         if( tgt) // !null reference
02745         {
02746                 CComPtr<IMgaFCO> tgt_ptr;
02747                 ObjForCore(tgt)->getinterface( &tgt_ptr);
02748                 getElemDetails( tgt_ptr, elem_tgt);
02749 
02750                 dist_tgt = distance( tgt);
02751         }
02752 
02753         short dist_ref = distance( one_ref);
02754 
02755         short st = 0;
02756         ObjForCore( one_ref)->RefCompareToBase( &st);
02757         if( st == 0 && tgt) // 0 means equal, so it is non-redird
02758         {
02759                 dist_ref = -1;
02760         }
02761 #endif
02762         // updates mapOfAdaptiveReferences
02763         saveTopAdaptiveRef( one_ref, bas_ref);
02764 
02765         // updates mapOfDerdRefsFromAdaptiveRef
02766         saveDerAdaptiveRef( one_ref);
02767 }
02768 
02769 // 
02770 // RL = ref in library       RL
02771 // RPA= ref in project       / \ 
02772 //                            |
02773 // RPD1, RPD2 are            RPA
02774 // dependents refs of       / \ 
02775 // adaptive ref(RP)        /   \
02776 //                       RPD1  RPD2
02777 // 
02778 // this method deals with objects like RPD1
02779 void RefreshManager::saveDerAdaptiveRef( CoreObj& one_ref)
02780 {
02781         // save dependents of one_ref
02782         CoreObjs deriveds = one_ref[ATTRID_DERIVED + ATTRID_COLLECTION];
02783         ITERATE_THROUGH(deriveds) {
02784                 CoreObj tgt = ITER[ATTRID_REFERENCE];
02785                 if( tgt)
02786                 {
02787                         CComPtr<IMgaFCO> tgt_ptr;
02788                         ObjForCore( tgt)->getinterface( &tgt_ptr);
02789                         elem_struct tgt_elem;
02790                         getElemDetails( tgt_ptr, tgt_elem);
02791                         // save it only if targeted toward a nonlibrary object
02792                         //if( !tgt_elem.inlib)
02793                         {
02794                                 short dist = distance( ITER);
02795                                 DIST_AND_REFOBJ key = std::make_pair( dist, ITER);
02796 
02797                                 MIXED_TARGET2   val;
02798                                 //if( tgt_elem.inlib) val = std::make_pair( tgt_elem.uid, CoreObj());
02799                                 if( tgt_elem.inverysamelib) val = std::make_pair( tgt_elem.uid, CoreObj());
02800                                 else                val = std::make_pair( UniqueId()  , tgt);
02801 
02802                                 mapOfDerdRefsFromAdaptiveRef[ key] = val;
02803                         }
02804                 }
02805 
02806                 saveDerAdaptiveRef( ITER);
02807         }
02808 }
02809 
02810 // 
02811 // RL = ref in library       RL
02812 // RPA= ref in project       / \ 
02813 //                            |
02814 // RPD1, RPD2 are            RPA
02815 // dependents refs of       / \ 
02816 // adaptive ref(RP)        /   \
02817 //                       RPD1  RPD2
02818 // 
02819 // this method deals with objects like RPA
02820 void RefreshManager::saveTopAdaptiveRef( CoreObj& one_ref, CoreObj& bas_ref)
02821 {
02822         // base ref's info
02823         UniqueId bas_id = Identifier::getDetailsOf( bas_ref);
02824 
02825         // its target 
02826         UniqueId bas_tgt_id;
02827         CoreObj bas_tgt = bas_ref[ATTRID_REFERENCE];
02828         if( bas_tgt)
02829                 bas_tgt_id = Identifier::getDetailsOf( bas_tgt);
02830 
02831         LIBREF_AND_LIBTARGET base_ref_pair = std::make_pair( bas_id, bas_tgt_id );
02832         short dist = distance( one_ref);
02833         LIB_REFTARG_PAIR k = std::make_pair( dist, base_ref_pair);
02834 
02835         // derived ref's info
02836         // might be in project also
02837         UniqueId ref_id = Identifier::getDetailsOf( one_ref);
02838 
02839         // its target 
02840         CoreObj  ref_tgt_core;
02841         UniqueId ref_tgt_id;
02842         CoreObj ref_tgt = one_ref[ATTRID_REFERENCE];
02843         if( ref_tgt)
02844         {
02845                 ref_tgt_id = Identifier::getDetailsOf( ref_tgt);
02846                 if( ref_tgt_id.libId == BinGuid()) // regular target (is in project)
02847                         ref_tgt_core = ref_tgt;
02848         }
02849 
02850         MIXED_TARGET      target_info   = std::make_pair( ref_tgt_id, ref_tgt_core);
02851         REGREF_AND_TARGET derd_ref_pair = std::make_pair( one_ref, target_info );
02852         //short t_dist = 0;//distance( );
02853         //REF_PAIR v = std::make_pair( t_dist, derd_ref_pair);
02854 
02855         // insert the record into the storage
02856         mapOfAdaptiveReferences[ k ].push_back( derd_ref_pair);
02857 #if(0)
02858         // recursive
02859         CoreObjs deriveds = one_ref[ATTRID_DERIVED + ATTRID_COLLECTION];
02860         ITERATE_THROUGH(deriveds) {
02861                 //saveTopAdaptiveRef( ITER, one_ref);
02862         }
02863 #endif
02864 }
02865 
02866 // 
02867 void RefreshManager::collectDersFromLib( CoreObj& one_fco)
02868 {
02869         auto obj = ObjForCore(one_fco);
02870         if( obj)
02871         {
02872                 elem_struct elem_self;
02873 
02874                 CComPtr<IMgaFCO> obj_ptr;
02875                 obj->getinterface( &obj_ptr);
02876                 getElemDetails( obj_ptr, elem_self);
02877 
02878                 CComPtr<IMgaFCOs> subs;
02879                 COMTHROW( obj->get_DerivedObjects( &subs));
02880                 long l;
02881                 COMTHROW( subs->get_Count( &l));
02882                 for( long i = 1; i <= l; ++i)
02883                 {
02884                         CComPtr<IMgaFCO> sub;
02885                         COMTHROW( subs->get_Item( i, &sub));
02886 
02887                         elem_struct elem_sub;
02888                         getElemDetails( sub, elem_sub);
02889 
02890                         /*if( elem_sub.inlib) // which lib? it matters!
02891                         {
02892                                 if( elem_sub.uid.libId == Identifier::getLibRootOf( one_fco)
02893                                         || elem_sub.uid.libId == Identifier::getTopLibRootOf( one_fco)
02894                                         )
02895                                         continue;
02896                                 else
02897                                         if( m_changedLibs.end() == std::find( m_changedLibs.begin(), m_changedLibs.end(), elem_sub.uid.libId))
02898                                                 m_changedLibs.push_back( elem_sub.uid.libId);
02899                         }*/
02900                         /*if( elem_sub.inlib) // if subtype also in library, do not care
02901                                 continue;*/
02902                         if( elem_sub.inverysamelib)
02903                                 continue;
02904 
02905                         // collect references, both primary and secondary deriveds 
02906                         collectRefsDerdFromLib( CoreObj( sub), one_fco);
02907 
02908                         VARIANT_BOOL prim;
02909                         COMTHROW( sub->get_IsPrimaryDerived( &prim));
02910                         if( prim == VARIANT_FALSE) // secondary derived, will be handled by DetachObjFromLibBase
02911                                 continue;
02912 
02913                         // sub is in the project, primary derived
02914                         VARIANT_BOOL is_inst;
02915                         COMTHROW( sub->get_IsInstance( &is_inst));
02916 
02917                         /*CComPtr<IMgaModel> parentM;
02918                         CComPtr<IMgaFolder> parentF;
02919                         CComPtr<IMgaObject> parentMF;
02920                         HRESULT res = sub->get_ParentModel( &parentM);
02921                         if( FAILED( res) || !parentM)
02922                         {
02923                                 res = sub->get_ParentFolder( &parentF);
02924                         }*/
02925 
02926                         if( 1)//SUCCEEDED( res) && (parentM || parentF))
02927                         {
02928                                 SUB_PAR sp;
02929                                 // fill the known fields
02930                                 sp.subt_ptr = sub;
02931                                 sp.is_instance = is_inst == VARIANT_TRUE;
02932 #if(0)
02933                                 sp.subt_id = elem_sub.id;
02934                                 if( parentF)
02935                                 {
02936                                         // fill up subt_parent in sp SUB_PAR
02937                                         COMTHROW( parentF->get_ID( &sp.subt_parent));
02938                                         sp.parentIsFolder = true;
02939                                 }
02940                                 else if( parentM)
02941                                 {
02942                                         // fill up subt_parent in sp SUB_PAR
02943                                         COMTHROW( parentM->get_ID( &sp.subt_parent));
02944 
02945                                         CComPtr<IMgaMetaRole> meta_role;
02946                                         COMTHROW( sub->get_MetaRole( &meta_role));
02947                                         // fill up subt_metarole in sp SUB_PAR
02948                                         COMTHROW( meta_role->get_Name( &sp.subt_metarole));
02949                                         sp.parentIsFolder = false;
02950                                 }
02951 #endif                          
02952                                 // add structure to the storage map
02953                                 mapOfDeriveds[ elem_self.uid].push_back( sp);
02954 #ifdef _DEBUG
02955                                 //MyCComBSTR msg ("mapOfDeriveds ");
02956                                 //CComBSTR oid, sid; COMTHROW(ObjForCore( one_fco)->get_ID( &oid)); COMTHROW(sub->get_ID( &sid));
02957                                 //COMTHROW(msg.AppendBSTR( oid));COMTHROW(msg.Append( L" base of ")); COMTHROW(msg.AppendBSTR( sid));
02958                                 //COMTHROW(msg.appendLink( one_fco)); COMTHROW(msg.appendLink( sub));
02959                                 //m_reporter.show( msg);
02960 #endif
02961 
02962                         }
02963                         else 
02964                                 ASSERT(0);
02965                 }
02966         }
02967 }
02968 
02969 void RefreshManager::collectRefsToLib( CoreObj& one_fco)
02970 {
02971         auto obj = ObjForCore(one_fco);
02972         if( obj)
02973         {
02974                 short dist_self = distance( one_fco); // the distance to the archetype of target (one_fco)
02975 
02976                 elem_struct elem_self;
02977                 //getElemDetails( obj->getinterface(), elem_self);
02978                 
02979                 CComPtr<IMgaFCO> obj_ptr;
02980                 obj->getinterface( &obj_ptr);
02981                 getElemDetails( obj_ptr, elem_self);
02982 
02983                 CComPtr<IMgaFCOs> refs;
02984                 COMTHROW( obj->get_ReferencedBy( &refs));
02985                 long l;
02986                 COMTHROW( refs->get_Count( &l));
02987                 for( long i = 1; i <= l; ++i)
02988                 {
02989                         CComPtr<IMgaFCO> ref;
02990                         COMTHROW( refs->get_Item( i, &ref));
02991 
02992                         elem_struct elem_ref;
02993                         getElemDetails( ref, elem_ref);
02994 
02995                         /*if( elem_ref.inlib) // which lib? it matters!
02996                         {
02997                                 if( elem_ref.uid.libId == Identifier::getLibRootOf( one_fco)
02998                                         || elem_ref.uid.libId == Identifier::getTopLibRootOf( one_fco)
02999                                         )
03000                                         continue;
03001                                 else
03002                                         if( m_changedLibs.end() == std::find( m_changedLibs.begin(), m_changedLibs.end(), elem_ref.uid.libId))
03003                                                 m_changedLibs.push_back( elem_ref.uid.libId);
03004                         }*/
03005                         /*if( elem_ref.inlib) // ref also in library?
03006                                 continue;*/
03007                         if( elem_ref.inverysamelib)
03008                                 continue;
03009 
03010 
03011                         // So far we know that:
03012                         // ref in project
03013                         // target in libr
03014 
03015                         bool base_in_lib    = false;    // more precisely, base is the SAME lib as target
03016                                                                                         // and we are interested whether the object is participating in
03017                                                                                         // a derivation chain which has library objects at its top
03018                         bool is_redirected  = false;
03019                         bool is_secderd     = false;
03020                         bool isder = isDerivedRef( ref, obj_ptr, &base_in_lib, &is_redirected, &is_secderd);
03021                         if( isder)
03022                         {
03023                                 // ref's target is in libr, so we are sure
03024                                 // that base's target is also in libr
03025                                 // 
03026                                 // if base is in the same lib as target
03027                                 // then we get for granted that relationship (base-->target)
03028                                 // and must update the adaptives accordingly (ref-->target)
03029 
03030                                 short dist_ref = distance( CoreObj( ref));
03031                                 if( base_in_lib)
03032                                 {
03033                                         // base ---> target reference relationship may have changed 'overnight'
03034                                         // (during library project modification) so there exists a chance of
03035                                         // discrepancy upon update if we restore it to refer to its old target
03036                                         // this challenge is taken by the collectRefsDerdFromLib & mapOfAdaptiveReferences
03037                                         continue;
03038                                 }
03039                                 else
03040                                 {
03041                                         // base is not in the library (the same library where target is)
03042                                         // base's target is in the library because ref's target is in the library
03043                                         // if is not redirected specifically then we can rely on the default propagation
03044                                         // mechanism (collectRefsToLib, restoreRefsToLib will be invoked with base as well)
03045                                         if( is_redirected)
03046                                         {
03047                                                 mapOfDependentReferences[ std::make_pair( dist_self, elem_self.uid)].insert( std::make_pair( dist_ref, CoreObj( ref)));
03048                                                 continue;
03049                                         }
03050                                         else
03051                                                 continue; // no need for handling, when its base is handled that's enough for us
03052                                 }
03053                         }
03054 
03055                         mapOfReferences[ elem_self.uid].push_back( CoreObj( ref));
03056                 }
03057         }
03058 }
03059 
03060 // cuts dependencies of derived objects from one_fco (a lib object)
03061 // thus when one_fco is destroyed it won't be followed by them
03062 void RefreshManager::cutDersFromLib( CoreObj& one_fco)
03063 {
03064         auto obj = ObjForCore(one_fco);
03065         if( obj)
03066         {
03067                 CComPtr<IMgaFCOs> subs;
03068                 COMTHROW( obj->get_DerivedObjects( &subs));
03069                 long l;
03070                 COMTHROW( subs->get_Count( &l));
03071                 for( long i = 1; i <= l; ++i)
03072                 {
03073                         CComPtr<IMgaFCO> sub;
03074                         COMTHROW( subs->get_Item( i, &sub));
03075 
03076                         VARIANT_BOOL prim;
03077                         COMTHROW( sub->get_IsPrimaryDerived( &prim));
03078                         if( prim == VARIANT_FALSE) // secondary derived, do not care
03079                                 continue;
03080 
03081 
03082                         elem_struct elem_sub;
03083                         getElemDetails( sub, elem_sub);
03084 
03085                         /*if( elem_sub.inlib) // which lib? it matters!
03086                         {
03087                                 if( elem_sub.uid.libId == Identifier::getLibRootOf( one_fco)
03088                                         || elem_sub.uid.libId == Identifier::getTopLibRootOf( one_fco)
03089                                         )
03090                                         continue; // subtype also in the same library
03091                                 else
03092                                         if( m_changedLibs.end() == std::find( m_changedLibs.begin(), m_changedLibs.end(), elem_sub.uid.libId))
03093                                                 m_changedLibs.push_back( elem_sub.uid.libId);
03094                         }*/
03095                         /*if( elem_sub.inlib) // subtype also in library
03096                                 continue;*/
03097                         if( elem_sub.inverysamelib)
03098                                 continue;
03099 
03100                         // cut the relationship between derd and bs
03101                         // by removing the dependency me help derd 
03102                         // objects survive the death of bs object
03103                         CoreObj derd( sub);
03104                         DetachObjFromLibBase( one_fco, derd, 0, true);
03105                 }
03106         }
03107 }
03108 
03109 void RefreshManager::cutRelations( CoreObj& p_cont)
03110 {
03111         ITERATE_THROUGH( p_cont[ATTRID_FCOPARENT+ATTRID_COLLECTION]) 
03112         {
03113                 if(ITER.IsFCO())
03114                 {
03115                         cutDersFromLib( ITER); // also detaches objects from library base objects
03116                 }
03117                 
03118                 if( ITER.IsContainer()) cutRelations( ITER);
03119         }
03120 }
03121 
03122 void RefreshManager::reattachSubtypesInstances()
03123 {
03124         PRI_MATCHMAKER_MAP::const_iterator i = m_primMatchMaker.begin();
03125         for( ; i != m_primMatchMaker.end(); ++i)
03126         {
03127                 //i->first; // ptr of derd
03128                 //i->second; // PAIR <ptr of base, is_instance>
03129                 CoreObj prev_detached( i->first);
03130                 CoreObj fresh_base   ( i->second.first);
03131                 bool is_instance     ( i->second.second);
03132                 
03133                 AttachDerObjs( fresh_base, prev_detached, is_instance?VARIANT_TRUE:VARIANT_FALSE, true);
03134         }
03135 }
03136 
03137 void RefreshManager::clearDepStorage()
03138 {
03139         lib_stack.clear();
03140         conns_stored.clear();
03141         conns_to_derive.clear();
03142         m_mapOfMemberships.clear();
03143 
03144         mapOfReferences.clear();
03145         mapOfDependentReferences.clear();
03146         mapOfAdaptiveReferences.clear();
03147         mapOfDerdRefsFromAdaptiveRef.clear();
03148         m_alreadySetRefs.clear();
03149 
03150         mapOfDeriveds.clear();
03151         napOfSecondaryDeriveds.clear();
03152 
03153         m_primMatchMaker.clear();
03154         m_coreMatchMaker.clear();
03155 
03156 
03157 #if(DONT_OPTIM)
03158         conns_to_recreate.clear();
03159         mapOfSecondaryDeriveds.clear();
03160         m_matchMaker.clear();
03161 #endif
03162 }
03163 
03164 void RefreshManager::collectDependencies( CoreObj& p_container)
03165 {
03166         bool lib_root_found = false;
03167 
03168         long pm = p_container[ATTRID_PERMISSIONS];
03169         if( pm & LIBROOT_FLAG)
03170         {
03171                 BinGuid libn = Identifier::getPersistentIdOf( p_container);
03172                 lib_stack.push_back( libn);
03173                 lib_root_found = true;
03174         }
03175 
03176         ITERATE_THROUGH(p_container[ATTRID_FCOPARENT+ATTRID_COLLECTION]) 
03177         {
03178                 if(ITER.IsFCO())
03179                 {
03180                         collectRefsToLib( ITER);
03181                         collectMixedConns( ITER);
03182                         collectDersFromLib( ITER);
03183                 }
03184                 
03185                 if( ITER.IsContainer()) collectDependencies( ITER);
03186         }
03187 
03188         ASSERT( !lib_stack.empty());
03189         if( lib_root_found && !lib_stack.empty())
03190         {
03191                 lib_stack.pop_back();
03192         }
03193 }
03194 
03195 void RefreshManager::restoreDependencies()
03196 {
03197         // step 1
03198         m_reporter.show( CComBSTR(L"[Step 1] Restoring references to the new library..."), false);
03199         
03200         adaptTopRefs();
03201         adaptDerRefs();
03202         restoreRefsToLib();
03203 
03204         // step 2
03205         m_reporter.show( CComBSTR(L"[Step 1] Done."), false);
03206         m_reporter.show( CComBSTR(L"[Step 2] Restoring connections to the new library..."), false);
03207 
03208         restoreMixedConns( m_newLib);
03209 
03210         // step 3
03211         m_reporter.show( CComBSTR(L"[Step 2] Done."), false);
03212         m_reporter.show( CComBSTR(L"[Step 3] Updating subtypes and instances derived from the library..."), false);
03213 
03214         syncStructureFromLib();
03215 
03216         // step 4
03217         m_reporter.show( CComBSTR(L"[Step 3] Done."), false);
03218         m_reporter.show( CComBSTR(L"[Step 4] Updating new connections in subtypes and instances..."), false);
03219 
03220         syncFreshConns();
03221 
03222         // step 5
03223         m_reporter.show( CComBSTR(L"[Step 4] Done."), false);
03224         m_reporter.show( CComBSTR(L"[Step 5] Reattaching subtypes and instances..."), false);
03225         
03226         reattachSubtypesInstances();
03227 
03228         // step 6?
03229         reapplyLibFlagToChangedLibs();
03230 
03231         m_reporter.show( CComBSTR(L"[Step 5] Refresh done."), false);
03232 }
03233 
03234 int RefreshManager::getNumOfErrors( MyCComBSTR& msg)
03235 {
03236         int k = m_reporter.getErrors();
03237         TCHAR buf[32];
03238         _stprintf_s( buf, _T("%d"), k);
03239         COMTHROW(msg.Append( L"Warnings: "));
03240         COMTHROW(msg.Append( buf));
03241 
03242         return k;
03243 }
03244 
03245 /*static*/ const CComBSTR Creator::SrcName = L"src"; // keep in sync with FCO::SrcName in MgaConnection.cpp
03246 /*static*/ const CComBSTR Creator::DstName = L"dst"; // keep in sync with FCO::DstName
03247 
03248 /*static*/
03249 HRESULT Creator::SimpleConn( CComPtr<IMgaModel>&      p_parent
03250                            , CComPtr<IMgaMetaRole>&   p_mrole
03251                            , CComPtr<IMgaFCO>&        p_src
03252                            , CComPtr<IMgaFCO>&        p_dst
03253                            , CComPtr<IMgaFCOs>&       p_srcRefs
03254                            , CComPtr<IMgaFCOs>&       p_dstRefs
03255                            , CMgaProject*             p_mgaProject
03256                            , IMgaFCO**                p_newConn
03257                            )
03258 {       // copied from HRESULT FCO::CreateSimpleConn( ...)
03259         CMgaProject* &mgaproject = p_mgaProject;
03260         COMTRY_IN_TRANSACTION { // COMTRY_IN_TRANSACTION needs a variable named mgaproject
03261                 CComPtr<IMgaFCO> f;
03262                 {
03263                         booltempflag fl( p_mgaProject->checkofftemporary);
03264                         //COMTHROW(CreateChildObject(metar, &f));
03265                         COMTHROW( Creator::Child( p_mgaProject, CComPtr<IMgaFCO>( p_parent), p_mrole, &f));
03266                         objtype_enum ot;
03267                         COMTHROW( f->get_ObjType( &ot));
03268                         if( ot != OBJTYPE_CONNECTION) COMTHROW( E_MGA_INVALID_ROLE);
03269                         COMTHROW( Creator::put_NamedRole( p_mgaProject, f, SrcName, p_srcRefs, p_src));
03270                 }       
03271                 COMTHROW( Creator::put_NamedRole( p_mgaProject, f, DstName, p_dstRefs, p_dst));
03272                 *p_newConn = f.Detach();
03273         }
03274         COMCATCH_IN_TRANSACTION(;);     
03275 }
03276 
03277 /*static*/
03278 HRESULT Creator::Child( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_parent, CComPtr<IMgaMetaRole>& p_metar, IMgaFCO **p_newobj)
03279 {       // copied from HRESULT FCO::CreateChildObject(IMgaMetaRole *metar, IMgaFCO **newobj)
03280         CMgaProject* &mgaproject = p_mgaProject;
03281         COMTRY_IN_TRANSACTION { // COMTRY_IN_TRANSACTION needs a variable named mgaproject
03282                 //CheckWrite();
03283                 CHECK_INPTRPAR( p_metar);
03284                 CHECK_OUTPTRPAR( p_newobj);
03285                 //if((long)self[ATTRID_PERMISSIONS] & ~EXEMPT_FLAG) COMTHROW(E_MGA_NOT_CHANGEABLE);
03286                 CoreObj  nobj;
03287                 CComPtr<IMgaMetaFCO> meta;
03288                 metaref_type rr;
03289                 COMTHROW( p_metar->get_MetaRef( &rr));
03290                 COMTHROW( p_metar->get_Kind( &meta));
03291 
03292                 CoreObj a_self( p_parent);
03293                 auto parent = ObjForCore(a_self);
03294 
03295                 COMTHROW( parent->ContainerCreateFCO( meta, nobj));
03296 
03297                 nobj[ATTRID_ROLEMETA]=rr;
03298                 auto nfco = ObjForCore(nobj);
03299                 nfco->initialname();
03300 
03301                 setcheck( p_mgaProject, nobj, CHK_NEW);
03302 
03303                 int targetlevel = 0;
03304                 CoreObj rootp;
03305 
03306                 // a_self is not a member!
03307                 GetRootOfDeriv( a_self, rootp, &targetlevel);
03308                 if( targetlevel >= 0) ReDeriveNewObj( p_mgaProject, nobj, targetlevel+1);
03309                 docheck( mgaproject);
03310 
03311                 nfco->SelfMark(OBJEVENT_CREATED);
03312                 parent->SelfMark(OBJEVENT_NEWCHILD);
03313                 nfco->getinterface( p_newobj);
03314         }
03315         COMCATCH_IN_TRANSACTION(;);     
03316 }
03317 
03318 /*static*/
03319 HRESULT Creator::put_NamedRole( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_conn, BSTR p_rolename,  IMgaFCOs* p_refs, IMgaFCO* p_endfco)
03320 {       // copied from FCO::put_NamedRole(...)
03321         CMgaProject* &mgaproject = p_mgaProject;
03322         COMTRY_IN_TRANSACTION { // COMTRY_IN_TRANSACTION needs a variable named mgaproject
03323                 //CheckWrite();
03324                 {
03325                         booltempflag fl( p_mgaProject->checkofftemporary);
03326 
03327                         CComPtr<IMgaConnPoints> p;
03328                         CComQIPtr<IMgaConnection> a_conn( p_conn);
03329                         COMTHROW( a_conn->get_ConnPoints(&p)); 
03330                         MGACOLL_ITERATE(IMgaConnPoint, p) {
03331                                 CComBSTR rn;
03332                                 COMTHROW(MGACOLL_ITER->get_ConnRole(&rn));
03333                                 if(rn == p_rolename) {
03334                                         COMTHROW(MGACOLL_ITER->Remove());
03335                                         break;
03336                                 }
03337                         } MGACOLL_ITERATE_END;
03338                 }
03339                 if( p_endfco) {
03340                         CComPtr<IMgaConnPoint> tt;
03341                         COMTHROW( Creator::AddConnPoint( p_mgaProject, p_conn, p_rolename, 1, p_endfco, p_refs, &tt));
03342                 }
03343         } COMCATCH_IN_TRANSACTION(;)
03344 }       
03345 
03346 /*static*/
03347 HRESULT Creator::AddConnPoint( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_conn, BSTR p_rolename, long p_maxinrole, IMgaFCO* p_target, IMgaFCOs* p_refs, IMgaConnPoint** pVal) 
03348 {       // copied from FCO::AddConnPoint(...)
03349         CMgaProject* &mgaproject = p_mgaProject;
03350         COMTRY_IN_TRANSACTION { // COMTRY_IN_TRANSACTION needs a variable named mgaproject
03351                 //CheckWrite();
03352                 long c = 0;
03353                 if( p_refs) COMTHROW( p_refs->get_Count(&c));
03354                 std::vector<CoreObj> peers(c+2);
03355                 CHECK_INSTRPAR( p_rolename);
03356                 CHECK_MYINPTRPAR( p_target);
03357                 CHECK_OUTPTRPAR( pVal);
03358                 int pos = 0;
03359                 if( p_refs) {
03360                         CHECK_MYINPTRSPAR( p_refs);
03361 
03362                         MGACOLL_ITERATE(IMgaFCO, p_refs) {
03363                                 CoreObj l(MGACOLL_ITER);
03364                                 if(l.GetMetaID() != DTID_REFERENCE) COMTHROW(E_MGA_REFERENCE_EXPECTED);
03365                                 peers[pos++] = l;
03366                         } MGACOLL_ITERATE_END;
03367                 }
03368                 peers[pos++] = CoreObj( p_target);
03369                 peers[pos] = NULLCOREOBJ;
03370 
03371                 CoreObj a_self( p_conn);
03372                 auto this_conn( ObjForCore( a_self));
03373 
03374                 AddConnPTask( p_maxinrole, p_rolename).DoWithDeriveds( a_self, &peers);
03375                 CMgaConnPoint::GetConnPoint( this_conn, peers[pos], pVal);
03376         } COMCATCH_IN_TRANSACTION(;);
03377 }
03378 
03379 /*static*/ 
03380 HRESULT Worker::put_Name( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_elem, CComBSTR p_newVal)
03381 {       // copied from FCO::put_Name
03382         CMgaProject* &mgaproject = p_mgaProject;
03383         COMTRY_IN_TRANSACTION { // COMTRY_IN_TRANSACTION needs a variable named mgaproject
03384                 //CheckWrite();
03385                 CHECK_INPAR( p_newVal);  
03386                 CoreObj a_self( p_elem);
03387                 //if(self[ATTRID_PERMISSIONS] & LIBROOT_FLAG) COMTHROW(E_MGA_LIBOBJECT);
03388                 if(CComBSTR(a_self[ATTRID_NAME]) != p_newVal) {
03389                         put_NameTask(CComBSTR(a_self[ATTRID_NAME]), p_newVal).DoWithDeriveds(a_self);;
03390                 }
03391         }
03392         COMCATCH_IN_TRANSACTION(;);     
03393 }
03394 
03395 /*static*/ 
03396 HRESULT Worker::PutGuidDisp( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_elem, CComBSTR p_guidStr)
03397 {       // copied from FCO::PutGuidDisp
03398         CMgaProject* &mgaproject = p_mgaProject;
03399         COMTRY_IN_TRANSACTION { // COMTRY_IN_TRANSACTION needs a variable named mgaproject
03400                 //CheckWrite();
03401                 CHECK_INSTRPAR( p_guidStr);
03402                 //self[ATTRID_GUID1] = newVal;
03403                 GUID t_guid;
03404                 CopyTo( p_guidStr, t_guid);
03405 
03406                 long v1 = t_guid.Data1; // Data1: 32 b, Data2, Data 3: 16 b, Data4: 64 bit
03407                 long v2 = (t_guid.Data2 << 16) + t_guid.Data3;
03408                 long v3 = (((((t_guid.Data4[0] << 8) + t_guid.Data4[1]) << 8) + t_guid.Data4[2]) << 8) + t_guid.Data4[3];
03409                 long v4 = (((((t_guid.Data4[4] << 8) + t_guid.Data4[5]) << 8) + t_guid.Data4[6]) << 8) + t_guid.Data4[7];
03410 
03411                 Worker::PutGuid( p_mgaProject, p_elem, v1, v2, v3, v4);
03412         }  COMCATCH_IN_TRANSACTION(;)
03413 }
03414 
03415 HRESULT Worker::PutGuid( CMgaProject* p_mgaProject, CComPtr<IMgaFCO>& p_elem, long l1, long l2, long l3, long l4)
03416 {       // copied from FCO::PutGuid
03417         CMgaProject* &mgaproject = p_mgaProject;
03418         COMTRY_IN_TRANSACTION { // COMTRY_IN_TRANSACTION needs a variable named mgaproject
03419                 //CheckWrite();
03420                 //ASSERT( self.IsFCO());
03421                 //if( self.IsFCO()) {
03422                 CoreObj a_self( p_elem);
03423                 a_self[ATTRID_GUID1] = l1;
03424                 a_self[ATTRID_GUID2] = l2;
03425                 a_self[ATTRID_GUID3] = l3;
03426                 a_self[ATTRID_GUID4] = l4;
03427         }  COMCATCH_IN_TRANSACTION(;)
03428 }
03429