GME
13
|
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 ¤t_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 ¤t_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