GME  13
MakeClosure.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "MakeClosure.h"
00003 
00004 #include <string>
00005 #include <map>
00006 #include <set>
00007 #include <algorithm>
00008 #include <iterator>
00009 //
00010 // C O M M E N T
00011 // In this file the term "The RootFolder" means the default root folder any project is placed in
00012 // Not to be confused with top folder which means the folder staying on the top of the selected
00013 // object hierarchy
00014 //
00015 const std::string rootfolder_str = "RootFolder";
00016 const wchar_t* CMakeClosure::m_markerNode = L"inClosure";
00017 
00018 inline void nop( IMgaMetaFCO * f)
00019 {
00020 #ifdef _DEBUG
00021         CComObjPtr<IMgaMetaFCO> ff( f);
00022         CComBstrObj name; std::string s;
00023         COMTHROW( ff->get_Name( PutOut( name)));
00024         CopyTo( name, s);
00025         s = s + "|";
00026 #endif
00027 }
00028 
00029 inline void nop( IMgaMetaFolder * f)
00030 {
00031 #ifdef _DEBUG
00032         CComObjPtr<IMgaMetaFolder> ff( f);
00033         CComBstrObj name; std::string s;
00034         COMTHROW( ff->get_Name( PutOut( name)));
00035         CopyTo( name, s);
00036         s = s + "|";
00037 #endif
00038 }
00039 
00040 inline void nop( IMgaMetaModel * f)
00041 {
00042 #ifdef _DEBUG
00043         CComObjPtr<IMgaMetaModel> ff( f);
00044         CComBstrObj name; std::string s;
00045         COMTHROW( ff->get_Name( PutOut( name)));
00046         CopyTo( name, s);
00047         s = s + "|";
00048 #endif
00049 }
00050 
00051 inline void nop( IMgaFCO * f)
00052 {
00053 #ifdef _DEBUG
00054         CComObjPtr<IMgaFCO> ff( f);
00055         CComBstrObj name; std::string s;
00056         COMTHROW( ff->get_Name( PutOut( name)));
00057         CopyTo( name, s);
00058         s = s + "|";
00059 #endif
00060 }
00061 
00062 inline void nop( IMgaFolder * f)
00063 {
00064 #ifdef _DEBUG
00065         CComObjPtr<IMgaFolder> ff( f);
00066         CComBstrObj name; std::string s;
00067         COMTHROW( ff->get_Name( PutOut( name)));
00068         CopyTo( name, s);
00069         s = s + "|";
00070 #endif
00071 }
00072 
00073 inline void nop( IMgaModel * f)
00074 {
00075 #ifdef _DEBUG
00076         CComObjPtr<IMgaModel> ff( f);
00077         CComBstrObj name; std::string s;
00078         COMTHROW( ff->get_Name( PutOut( name)));
00079         CopyTo( name, s);
00080         s = s + "|";
00081 #endif
00082 }
00083 
00084 // -----------------------------------------------------------
00085 // --------------------------- GmeEqual ----------------------
00086 // -----------------------------------------------------------
00087 GmeEqual::GmeEqual( CComObjPtr<IMgaObject> obj)
00088 : m_objToFind( obj), m_which( 1)
00089 { }
00090 
00091 
00092 GmeEqual::GmeEqual( CComObjPtr<IMgaFCO> fco)
00093 : m_fcoToFind( fco), m_which( 2)
00094 { }
00095 
00096 
00097 GmeEqual::GmeEqual( CComObjPtr<IMgaFolder> folder)
00098 : m_folderToFind( folder), m_which( 3)
00099 { }
00100 
00101 
00102 GmeEqual::GmeEqual( CComObjPtr<IMgaModel> model)
00103 : m_modelToFind( model), m_which( 4)
00104 { }
00105 
00106 
00107 bool GmeEqual::operator() ( CComObjPtr<IMgaObject>& op )
00108 {
00109         ASSERT( m_which == 1); // which variable is set
00110 
00111         VARIANT_BOOL is_equal;
00112         COMTHROW( m_objToFind->get_IsEqual( op, &is_equal));
00113 
00114         if (is_equal != VARIANT_FALSE)
00115                 return true;
00116 
00117         return false;
00118 }
00119 
00120 bool GmeEqual::operator() ( CComObjPtr<IMgaFCO>& op )
00121 {
00122         ASSERT( m_which == 2); // which variable is set
00123 
00124         VARIANT_BOOL is_equal;
00125         COMTHROW( m_fcoToFind->get_IsEqual( op, &is_equal));
00126 
00127         if (is_equal != VARIANT_FALSE)
00128                 return true;
00129 
00130         return false;
00131 }
00132 
00133 bool GmeEqual::operator() ( CComObjPtr<IMgaFolder>& op )
00134 {
00135         ASSERT( m_which == 3); // which variable is set
00136 
00137         VARIANT_BOOL is_equal;
00138         COMTHROW( m_folderToFind->get_IsEqual( op, &is_equal));
00139 
00140         if (is_equal != VARIANT_FALSE)
00141                 return true;
00142 
00143         return false;
00144 }
00145 
00146 bool GmeEqual::operator() ( CComObjPtr<IMgaModel>& op )
00147 {
00148         ASSERT( m_which == 4); // which variable is set
00149 
00150         VARIANT_BOOL is_equal;
00151         COMTHROW( m_modelToFind->get_IsEqual( op, &is_equal));
00152 
00153         if (is_equal != VARIANT_FALSE)
00154                 return true;
00155 
00156         return false;
00157 }
00158 
00159 // -----------------------------------------------------------
00160 // --------------------------- CMakeClosure ------------------
00161 // -----------------------------------------------------------
00162 long CMakeClosure::process()
00163 {
00164         CHECK_IN( m_project); // the constructor initialized it
00165         COMTRY
00166         {
00167                 initTrans();
00168                 
00169                 if( isValidSelection()) doClosure();
00170 
00171                 doneTrans( false);
00172         }
00173         COMCATCH( doneTrans(true) );
00174 }
00175 
00176 void CMakeClosure::doClosure()
00177 {
00178         if ( m_bDirection) // down
00179         {
00180                 preProcess();
00181                 processFolders();
00182                 processFCOs();
00183                 postValidateSelection();
00184                 postProcess();
00185         }
00186         else // up -> so first process the fcos
00187         {
00188                 preProcess();
00189                 processFCOs();
00190                 processFolders();
00191                 postValidateSelection();
00192                 postProcess();
00193         }
00194 }
00195 
00196 void CMakeClosure::preProcess()
00197 {
00198         send2Console("[Closure Copy] Working...");
00199 }
00200 
00201 void CMakeClosure::postProcess()
00202 {
00203         // wrapping needed
00204         if ( m_iContainerOption == 0) // miniproject wrapping
00205         {
00206                 selectTop();
00207                 totalWrap();
00208                 clearTopObjs(); // no need for the top objects, this is a sign to dump from the RootFolder
00209 
00210                 send2Console("[Closure Copy] The miniproject can be either Imported or Pasted in a new/existing project.");
00211         }
00212         else if ( m_iContainerOption == 1) // automatic wrapping
00213         {
00214                 selectTop();
00215                 autoWrap(); // resets the Top top values
00216                 checkMeta( m_topFolds, m_topFcos);
00217 
00218                 std::string res_str;
00219                 getAccKindsInString( res_str);
00220                 if( !res_str.empty()) send2Console( "[Closure Copy] The following kinds may accept the copied data: " + res_str + ".");
00221                 else send2Console( "[Closure Copy] Possible accepting kind not found based on the meta.");
00222         }
00223         else if ( m_iContainerOption == 2) // as is, no wrapping
00224         {
00225                 selectTop();
00226                 checkMeta( m_topFolds, m_topFcos);
00227 
00228                 std::string res_str;
00229                 getAccKindsInString( res_str);
00230                 if( !res_str.empty()) send2Console( "[Closure Copy] The following kinds may accept the copied data: " + res_str + ".");
00231                 else send2Console( "[Closure Copy] Possible accepting kind not found based on the meta.");
00232         }
00233 }
00234 
00235 void CMakeClosure::selectTop()
00236 {
00237         CComObjPtrVector<IMgaFCO> &parentless = m_topFcos;
00238         CComObjPtrVector<IMgaFolder> &parentless_folders = m_topFolds;
00239 
00240         // selecting parentless ( = top) fcos   
00241         CComObjPtrVector<IMgaFCO>::iterator i = m_selFcos.begin();
00242         for( ; i != m_selFcos.end(); ++i)
00243         {
00244                 CComObjPtr<IMgaModel> parent;
00245                 COMTHROW( (*i)->get_ParentModel( PutOut( parent)));
00246                 if ( parent) // not a root object
00247                 {
00248                         CComObjPtr<IMgaFCO> fco;
00249                         COMTHROW( ::QueryInterface( parent, fco));
00250                         
00251                         ASSERT( fco);
00252 
00253                         // check if model parent is in the selected set of objects
00254                         // and if *i is already in the parentless
00255                         if ( std::find_if( m_selFcos.begin(), m_selFcos.end(), GmeEqual( fco)) == m_selFcos.end() &&
00256                                  std::find_if( parentless.begin(), parentless.end(), GmeEqual( *i)) == parentless.end())
00257                         {
00258                                 parentless.push_back( *i);
00259                         }
00260                 }
00261                 else // it may be contained by a folder
00262                 {
00263                         CComObjPtr<IMgaFolder> parent;
00264                         COMTHROW( (*i)->get_ParentFolder( PutOut( parent)));
00265                         if ( parent)
00266                         {
00267                                 // check if folder parent is in the selected set of objects
00268                                 // and if *i is already in the parentless
00269                                 if ( std::find_if( m_selFolds.begin(), m_selFolds.end(), GmeEqual( parent)) == m_selFolds.end() &&
00270                                          std::find_if( parentless.begin(), parentless.end(), GmeEqual( *i)) == parentless.end())
00271                                 {
00272                                         parentless.push_back( *i);      
00273                                 }
00274                         }
00275                         else 
00276                         { 
00277                                 ASSERT( 0);
00278                         } // what the heck: *i is an fco and does not have a valid model or a valid folder parent?
00279                 }
00280         }
00281 
00282         // selecting parentless folders 
00283         CComObjPtrVector<IMgaFolder>::iterator k = m_selFolds.begin();
00284         for( ; k != m_selFolds.end(); ++k)
00285         {
00286                 CComObjPtr<IMgaFolder> parent;
00287                 COMTHROW( (*k)->get_ParentFolder( PutOut( parent)));
00288                 if ( parent) // is not a root object
00289                 {
00290                         // check if parent is in the selected set of objects
00291                         if ( std::find_if( m_selFolds.begin(), m_selFolds.end(), GmeEqual( parent)) == m_selFolds.end() &&
00292                                  std::find_if( parentless_folders.begin(), parentless_folders.end(), GmeEqual( *k)) == parentless_folders.end())
00293                         {
00294                                 parentless_folders.push_back( *k);
00295                         }
00296                 }
00297                 //else root: The RootFolder is not considered anymore a top object, see noTopObjs() method
00298         }
00299 }
00300 
00301 void CMakeClosure::processFolders()
00302 {
00303         unsigned int curr_start = 0;
00304         bool continju = true;
00305         while (continju)
00306         {
00307                 continju = false;
00308                 CComObjPtrVector<IMgaFolder>::iterator i = m_selFolds.begin();
00309                 for( unsigned int j = curr_start; j < m_selFolds.size() && i != m_selFolds.end(); ++j, ++i)
00310                 {
00311                         procObj( m_selFolds[j]);
00312                 }
00313 
00314                 continju = !m_newlySelFolds.empty() || !m_newlySelFcos.empty();
00315                 if ( continju)
00316                 {
00317                         curr_start = m_selFolds.size();
00318                         m_selFolds.insert( m_selFolds.end(), m_newlySelFolds.begin(), m_newlySelFolds.end());
00319                         m_selFcos.insert( m_selFcos.end(), m_newlySelFcos.begin(), m_newlySelFcos.end());
00320                 }
00321                 
00322                 m_newlySelFcos.clear();
00323                 m_newlySelFolds.clear();
00324         }
00325 }
00326 
00327 void CMakeClosure::processFCOs()
00328 {
00329         unsigned int curr_start = 0;
00330         bool continju = true;
00331         while (continju)
00332         {
00333                 continju = false;
00334                 CComObjPtrVector<IMgaFCO>::iterator i = m_selFcos.begin();
00335                 for( unsigned int j = curr_start; j < m_selFcos.size() && i != m_selFcos.end(); ++j, ++i)
00336                 {
00337                         procObj( m_selFcos[j]);
00338                 }
00339 
00340                 continju = !m_newlySelFolds.empty() || !m_newlySelFcos.empty();
00341                 if ( continju)
00342                 {
00343                         curr_start = m_selFcos.size();
00344                         m_selFolds.insert( m_selFolds.end(), m_newlySelFolds.begin(), m_newlySelFolds.end());
00345                         m_selFcos.insert( m_selFcos.end(), m_newlySelFcos.begin(), m_newlySelFcos.end());
00346                 }
00347                 m_newlySelFcos.clear();
00348                 m_newlySelFolds.clear();
00349         }
00350 }
00351 
00352 //---------------------------------------------------------------------------------------
00353 //-------------------------------------------------processor methods---------------------
00354 //---------------------------------------------------------------------------------------
00355 void CMakeClosure::procFolder( IMgaFolder *folder)
00356 {
00357         ASSERT( folder != NULL );
00358         insertNew( folder);
00359 
00360         if ( m_bFolderContainment)
00361         {
00362                 insertNew( folder, &IMgaFolder::get_ChildFolders);
00363                 insertNew( folder, &IMgaFolder::get_ChildFCOs);
00364         }
00365 }
00366 
00367 void CMakeClosure::procModel( IMgaModel *model)
00368 {
00369         ASSERT( model != NULL );
00370         insertNew( CComObjPtr<IMgaModel>( model));
00371 
00372         if ( m_bContainment)
00373         {
00374                 insertNew( model, &IMgaModel::get_ChildFCOs);
00375         }
00376 }
00377 
00378 void CMakeClosure::procReference( IMgaReference *reference)
00379 {
00380         ASSERT( reference != NULL );
00381         insertNew( CComObjPtr<IMgaFCO>( reference));
00382 
00383         CComObjPtr<IMgaFCO> fco;
00384         COMTHROW( reference->get_Referred( PutOut( fco)) );
00385 
00386         if ( m_bRefersTo && fco) // test if null reference
00387         {
00388                 bool inlib = isInLibrary( fco); // a referred fco may be in a library
00389                 if ( inlib && m_iIntoLibraries == LIB_CONT || !inlib)
00390                         insertNew( fco);
00391         }
00392 }
00393 
00394 
00395 void CMakeClosure::procSet( IMgaSet *one_set)
00396 {
00397         ASSERT( one_set != NULL );
00398         insertNew( one_set);
00399 
00400         CComObjPtrVector<IMgaFCO> members;
00401         COMTHROW( one_set->get_Members( PutOut( members)) );//zz1
00402         
00403         if ( m_bSetMember)
00404         {
00405                 insertNew( members);
00406         }
00407 }
00408 
00409 void CMakeClosure::procAtom( IMgaAtom *atom)
00410 {
00411         ASSERT( atom != NULL );
00412         insertNew( atom);
00413 }
00414 
00415 
00416 bool CMakeClosure::isValidSelection()
00417 {
00418         // check each object for validity
00419         CComObjPtrVector<IMgaFCO>::iterator fco_it = m_selFcos.begin();
00420         while( fco_it != m_selFcos.end())
00421         {
00422                 if( !isValidFCO( *fco_it))
00423                         fco_it = m_selFcos.erase( fco_it);
00424                 else
00425                         ++fco_it;
00426         }
00427 
00428         return m_selFcos.size() + m_selFolds.size() > 0;
00429 }
00430 
00431 bool CMakeClosure::isValidFCO( IMgaFCO * fco)
00432 {
00433         objtype_enum objtype;
00434         COMTHROW( fco->get_ObjType( &objtype) );
00435         if( objtype == OBJTYPE_CONNECTION)
00436         {
00437                 CComObjPtr<IMgaConnection> c;
00438                 COMTHROW( ::QueryInterface( fco, c) );
00439                 return isValidConnection( c);
00440         }
00441 
00442         return true;
00443 }
00444 
00445 /*static*/ CComPtr<IGMEOLEApp> CMakeClosure::get_GME(CComObjPtr<IMgaProject> project)
00446 {
00447         CComPtr<IGMEOLEApp> gme;
00448         if (/*mb_is_interactive &&*/ (project != NULL)) {               
00449                 CComBSTR bstrName("GME.Application");
00450                 CComPtr<IMgaClient> pClient;
00451                 HRESULT hr = project->GetClientByName(bstrName, &pClient);
00452                 if (SUCCEEDED(hr) && pClient) {
00453                         CComPtr<IDispatch> pDispatch;
00454                         hr = pClient->get_OLEServer(&pDispatch);
00455                         if (SUCCEEDED(hr) && pDispatch) {
00456                                 hr = pDispatch.QueryInterface(&gme);
00457                                 if (FAILED(hr)) {
00458                                         gme = NULL;
00459                                 }
00460                         }
00461                 }
00462         }
00463         return gme;
00464 } 
00465 
00466 bool CMakeClosure::isSimpleConnection( IMgaConnection * connection)
00467 {
00468         bool res = true;
00469         CComObjPtrVector<IMgaConnPoint> v;
00470         COMTHROW( connection->get_ConnPoints( PutOut( v)) );//zz1
00471 
00472         for( CComObjPtrVector<IMgaConnPoint>::iterator i = v.begin(); res && i != v.end(); ++i)
00473         {
00474                 CComObjPtr<IMgaConnPoint> connpoint = *i;
00475                 
00476                 CComObjPtrVector<IMgaFCO> refs;
00477                 COMTHROW( connpoint->get_References(PutOut( refs)) );//zz1
00478                 if( !refs.empty()) // it is a connection thru reference ports
00479                         res = false;
00480         }
00481 
00482         return res;
00483 }
00484 
00485 
00486 bool CMakeClosure::isValidConnection( IMgaConnection * connection)
00487 {
00488         bool res = true;
00489 
00490         CComObjPtrVector<IMgaConnPoint> v;
00491         COMTHROW( connection->get_ConnPoints( PutOut( v)) );//zz1
00492 
00493         for( CComObjPtrVector<IMgaConnPoint>::iterator i = v.begin(); res && i != v.end(); ++i)
00494         {
00495                 CComObjPtr<IMgaConnPoint> connpoint = *i;
00496                 
00497                 // general constraints (which apply for each case: LIB_*
00498                 CComObjPtrVector<IMgaFCO> refs;
00499                 COMTHROW( connpoint->get_References(PutOut( refs)) );//zz1
00500                 for( CComObjPtrVector<IMgaFCO>::iterator ref_i = refs.begin(); res && ref_i != refs.end(); ++ref_i )
00501                 {
00502                         if( !m_bRefPortConnection)
00503                         {
00504                                 res = false;//this is a connection between at least one reference port, so if the corresponding option is not set (m_bRefPortConnection) then we consider it invalid
00505                                 
00506                                 if( m_GME) 
00507                                 {
00508                                         CComBSTR bstr, id, nm;
00509                                         COMTHROW( connection->get_ID( &id));
00510                                         COMTHROW( connection->get_Name( &nm));
00511                                         COMTHROW(bstr.Append("Closure: <A HREF=\"mga:"));
00512                                         COMTHROW(bstr.AppendBSTR( id));
00513                                         COMTHROW(bstr.Append("\">"));
00514                                         COMTHROW(bstr.AppendBSTR( nm));
00515                                         COMTHROW(bstr.Append("</A> disregarded. Connection involving reference ports. Use the \"Connection thru refport\" option to include it."));
00516 
00517                                         COMTHROW(m_GME->ConsoleMessage(bstr, MSG_ERROR));
00518                                 }
00519 
00520                         }
00521                 }
00522 
00523                 // constraints for lib_stop case
00524                 if( m_iIntoLibraries == LIB_STOP)
00525                 {
00526                         CComObjPtr<IMgaFCO> target; // the src or dst of a connection
00527                         COMTHROW( connpoint->get_Target( PutOut( target)) );
00528                         if( target && isInLibrary( target))
00529                                 res = false; // this is a connection with one end in a library which in lib_stop case is not good
00530                 }
00531         }
00532 
00533         return res;
00534 }
00535 
00536 bool CMakeClosure::postValidateSelection()
00537 {
00538         // check each object for validity...
00539         return true;
00540 }
00541 
00542 bool CMakeClosure::postValidateFCO( IMgaFCO * fco)
00543 {
00544         return true;
00545 }
00546 
00547 bool CMakeClosure::postValidateConnection( IMgaConnection * connection)
00548 {
00549         return true;
00550 }
00551 
00552 void CMakeClosure::procConnection( IMgaConnection *connection)
00553 {
00554         ASSERT( connection != NULL );
00555 
00556         bool simple = isSimpleConnection( connection);
00557         if ( simple && m_bConnection || !simple && m_bRefPortConnection)
00558         {
00559                 CComObjPtrVector<IMgaConnPoint> v;
00560                 COMTHROW( connection->get_ConnPoints( PutOut( v)) );//zz1
00561                 
00562                 insertNew( CComObjPtr<IMgaFCO>( connection));
00563                 for( CComObjPtrVector<IMgaConnPoint>::iterator i = v.begin(); i != v.end(); ++i)
00564                 {
00565                         procConnPoint( *i);
00566                 }
00567         }
00568 }
00569 
00570 // if called from procConnection then the validity is checked
00571 // if called from procMyConnections then it is checked as well
00572 void CMakeClosure::procConnPoint( IMgaConnPoint *connpoint)
00573 {
00574         ASSERT( connpoint != NULL );
00575 
00576         CComObjPtr<IMgaFCO> target; // the src or dst of a connection
00577         COMTHROW( connpoint->get_Target( PutOut( target)) );
00578 
00579         CComObjPtr<IMgaConnection> conn; // the connection itself
00580         COMTHROW( connpoint->get_Owner( PutOut( conn)) );
00581 
00582         CComObjPtr<IMgaFCO> conn_fco;
00583         COMTHROW( conn.QueryInterface( conn_fco));
00584 
00585         CComObjPtrVector<IMgaFCO> refs; // the reference chain the connection is drawn
00586         COMTHROW( connpoint->get_References( PutOut( refs)) );//zz1
00587 
00588         if ( refs.empty()) // simple connection, no reference ports involved
00589         {
00590                 insertNew( target);
00591                 insertNew( conn_fco);
00592         }
00593         else // refport conn, so insert everything 
00594         {
00595                 bool inlib;
00596                 inlib = isInLibrary( target);
00597                 if ( inlib && m_iIntoLibraries == LIB_CONT || !inlib) insertNew( target);
00598                 
00599                 inlib = isInLibrary( conn_fco); // the connection might be in the library (=both endtargets are as well in the library)
00600                 if ( inlib && m_iIntoLibraries == LIB_CONT || !inlib) 
00601                 {
00602                         insertNew( conn_fco);
00603                         insertNew( refs);
00604                 }
00605         }
00606 }
00607 
00608 // this method is needed after an fco is processed to insert the attaching connections as well
00609 void CMakeClosure::procMyConnections( IMgaFCO * fco)
00610 {
00611         if ( m_bConnection || m_bRefPortConnection)
00612         {
00613                 CComObjPtrVector<IMgaConnPoint> my_conns;       
00614                 COMTHROW( fco->get_PartOfConns( PutOut( my_conns)) );//zz1
00615                 for( CComObjPtrVector<IMgaConnPoint>::iterator i = my_conns.begin(); i != my_conns.end(); ++i)
00616                 {
00617                         CComObjPtr<IMgaConnection> conn; // the connection itself
00618                         COMTHROW( (*i)->get_Owner( PutOut( conn)) );
00619                         bool simple = isSimpleConnection( conn);
00620                         if( simple && m_bConnection || !simple && m_bRefPortConnection)
00621                                 procConnPoint( *i);//the validity of each connection is tested
00622                 }
00623         }
00624 }
00625 
00626 void CMakeClosure::procMyContainerSets( IMgaFCO * fco)
00627 {
00628         if ( m_bMemberOfSets)
00629         {
00630                 CComObjPtrVector<IMgaFCO> my_sets;
00631                 COMTHROW( fco->get_MemberOfSets( PutOut( my_sets)) );//zz1
00632                 insertNew( my_sets);
00633         }
00634 }
00635 
00636 void CMakeClosure::procMyReferences( IMgaFCO * fco)
00637 {
00638         if ( m_bReferredBy)
00639         {
00640                 CComObjPtrVector<IMgaFCO> my_references;
00641                 COMTHROW( fco->get_ReferencedBy( PutOut( my_references)) );//zz1
00642                 insertNew( my_references);
00643         }
00644 }
00645 
00646 void CMakeClosure::procMyParent( IMgaFCO * fco)
00647 {
00648         CComObjPtr<IMgaModel> mod;
00649         COMTHROW( fco->get_ParentModel( PutOut( mod)) );
00650         if ( mod)
00651         {
00652                 if ( m_bPartOfModels)
00653                 {
00654                         insertNew( mod);
00655                 }
00656         }
00657         else
00658         {
00659                 CComObjPtr<IMgaFolder> fold;
00660                 COMTHROW( fco->get_ParentFolder( PutOut( fold)) );
00661                 if ( fold)
00662                 {
00663                         if ( m_bPartOfFolders)
00664                         {
00665                                 insertNew( fold);
00666                         }
00667                 }
00668                 // else rootfolder
00669         }
00670 }
00671 
00672 void CMakeClosure::procMyParent( IMgaFolder * folder)
00673 {
00674         CComObjPtr<IMgaFolder> parent;
00675         COMTHROW( folder->get_ParentFolder( PutOut( parent)) );
00676         if ( parent)
00677         {
00678                 if ( m_bPartOfFolders)
00679                 {
00680                         insertNew( parent);
00681                 }
00682         }
00683         // else rootfolder
00684 }
00685 
00686 template<class T>
00687 void CMakeClosure::markObj( CComObjPtr<T> obj)
00688 {
00689         if( m_markWith != -1)
00690         {
00691                 CComBSTR buf0;
00692                 COMTHROW( obj->get_RegistryValue( CComBSTR( m_markerNode), &buf0));
00693 
00694                 // check if the new marker appears already in the marker list
00695                 std::wstring str_buf = buf0.Length() ? buf0 : L"";
00696 
00697                 TCHAR buf1[12];
00698                 swprintf_s( buf1, L",%i", m_markWith);
00699                 std::wstring new_mrk( buf1);
00700 
00701                 str_buf += L","; // will ease the eos comparison
00702                 new_mrk += L","; // and the exact match is guaranteed
00703                 
00704                 if( str_buf.find( new_mrk) == std::string::npos) // if marker not present
00705                 {
00706                         COMTHROW(buf0.Append( buf1)); // insert new marker into list & update
00707                         COMTHROW( obj->put_RegistryValue( CComBSTR( m_markerNode), buf0));
00708                 }
00709         }
00710 }
00711 
00712 void CMakeClosure::procObj( IMgaObject* obj)
00713 {
00714         ASSERT( obj != NULL );
00716         if ( m_iIntoLibraries != LIB_CONT && isInLibrary( obj)) // if no intention to step into libraries and the object is in a library then return
00717                 return;
00718 
00719         objtype_enum objtype;
00720         COMTHROW( obj->get_ObjType( &objtype) );
00721 
00722         switch( objtype)
00723         {
00724         case OBJTYPE_MODEL:
00725         case OBJTYPE_ATOM:
00726         case OBJTYPE_REFERENCE:
00727         case OBJTYPE_CONNECTION:
00728         case OBJTYPE_SET:
00729                 {
00730                         CComObjPtr<IMgaFCO> p;
00731                         COMTHROW( ::QueryInterface( obj, p) );
00732 
00733                         markObj( p);
00734 
00735                         if ( m_bConnection)             procMyConnections( p);
00736                         if ( m_bMemberOfSets)           procMyContainerSets( p);
00737                         if ( m_bReferredBy)                     procMyReferences( p);
00738 
00739                         procMyParent( p);                       // we don't know what kind of parent the fco has: Model or Folder
00740 
00741                         if ( m_bBaseTypes)                      procMyBaseTypes( p);
00742                         if ( m_bDerivedTypes)           procMyDerivedTypes( p);
00743                         break;
00744                 }
00745 
00746         case OBJTYPE_FOLDER:
00747                 {
00748                         CComObjPtr<IMgaFolder> p;
00749                         COMTHROW( ::QueryInterface( obj, p) );
00750                         
00751                         markObj( p);
00752 
00753                         if ( m_bPartOfFolders)          procMyParent( p);
00754                         break;
00755                 }
00756 
00757         default:
00758                 HR_THROW(E_INVALID_MGA);
00759         };
00760 
00761 
00762         switch( objtype)
00763         {
00764         case OBJTYPE_MODEL:
00765                 {
00766                         if ( m_bContainment)
00767                         {
00768                                 CComObjPtr<IMgaModel> m;
00769                                 COMTHROW( ::QueryInterface( obj, m) );
00770 
00771                                 procModel( m);
00772                         }
00773                         break;
00774                 }
00775 
00776         case OBJTYPE_ATOM:
00777                 {
00778                         CComObjPtr<IMgaAtom> a;
00779                         COMTHROW( ::QueryInterface( obj, a) );
00780                         procAtom( a);
00781                         break;
00782                 }
00783 
00784         case OBJTYPE_REFERENCE:
00785                 {
00786                         if ( m_bRefersTo)
00787                         {
00788                                 CComObjPtr<IMgaReference> r;
00789                                 COMTHROW( ::QueryInterface( obj, r) );
00790                                 procReference( r);
00791                         }
00792                         break;
00793                 }
00794 
00795         case OBJTYPE_CONNECTION:
00796                 {
00797                         if ( m_bConnection)
00798                         {
00799                                 CComObjPtr<IMgaConnection> c;
00800                                 COMTHROW( ::QueryInterface( obj, c) );
00801                                 procConnection( c);
00802                         }
00803                         break;
00804                 }
00805 
00806         case OBJTYPE_SET:
00807                 {
00808                         if ( m_bSetMember)
00809                         {
00810                                 CComObjPtr<IMgaSet> s;
00811                                 COMTHROW( ::QueryInterface( obj, s) );
00812                                 procSet( s);
00813                         }
00814                         break;
00815                 }
00816 
00817         case OBJTYPE_FOLDER:
00818                 {
00819                         if ( m_bFolderContainment)
00820                         {
00821                                 CComObjPtr<IMgaFolder> f;
00822                                 COMTHROW( ::QueryInterface( obj, f) );
00823                                 procFolder( f);
00824                         }
00825                         break;
00826                 }
00827 
00828         default:
00829                 HR_THROW(E_INVALID_MGA);
00830         };
00831 }
00832 
00833 void CMakeClosure::procMyBaseTypes( IMgaFCO * fco)
00834 {
00835         if ( !m_bBaseTypes)
00836                 return;
00837 
00838         CComObjPtr<IMgaFCO> base;
00839         COMTHROW( fco->get_DerivedFrom( PutOut( base)));
00840         if( base)
00841         {
00842                 bool inlib = isInLibrary( base); // base types may be in a library
00843                 if ( inlib && m_iIntoLibraries == LIB_CONT || !inlib)
00844                         insertNew( base); 
00845         }
00846 
00847 }
00848 
00849 void CMakeClosure::procMyDerivedTypes( IMgaFCO * fco)
00850 {
00851         if ( !m_bDerivedTypes) 
00852                 return;
00853 
00854         CComObjPtrVector<IMgaFCO> der_fcos;
00855         COMTHROW( fco->get_DerivedObjects( PutOut( der_fcos)) );//zz1
00856         insertNew( der_fcos);
00857 }
00858 
00859 void CMakeClosure::insertNew( const std::string& id, bool is_top /* = false */)
00860 {
00861         CComObjPtr<IMgaObject> obj;
00862         COMTHROW( m_project->GetObjectByID( PutInBstr( id), PutOut( obj)) );
00863         if ( obj)
00864         {
00865                 objtype_enum objtype;
00866                 COMTHROW( obj->get_ObjType(&objtype) );
00867 
00868                 switch( objtype)
00869                 {
00870                 case OBJTYPE_MODEL:
00871                 case OBJTYPE_SET:
00872                 case OBJTYPE_REFERENCE:
00873                 case OBJTYPE_CONNECTION:
00874                 case OBJTYPE_ATOM:
00875                         {
00876                                 CComObjPtr<IMgaFCO> model;
00877                                 COMTHROW( ::QueryInterface(obj, model) );
00878                                 ASSERT( model);
00879                                 
00880                                 insertNew( model);
00881                                 if ( is_top)
00882                                 {
00883                                         nop( model);
00884                                         if ( std::find_if( m_topFcos.begin(), m_topFcos.end(), GmeEqual( model)) == m_topFcos.end())
00885                                                 m_topFcos.push_back( model);
00886                                 }
00887 
00888                                 break;
00889                         }
00890                 case OBJTYPE_FOLDER:
00891                         {
00892                                 CComObjPtr<IMgaFolder> folder;
00893                                 COMTHROW( ::QueryInterface( obj, folder));
00894                                 ASSERT( folder);
00895                                 
00896                                 insertNew( folder);
00897                                 if ( is_top)
00898                                 {
00899                                         nop( folder);
00900                                         if ( std::find_if( m_topFolds.begin(), m_topFolds.end(), GmeEqual( folder)) == m_topFolds.end())
00901                                                 m_topFolds.push_back( folder);
00902                                 }
00903 
00904                                 break;
00905                         }
00906                 default:
00907                         ASSERT( 0);
00908                 } // switch
00909         } // if
00910 }
00911 
00912 void CMakeClosure::insertNew( const CComObjPtr<IMgaFCO>& in)
00913 {
00914         nop( in);
00915 
00916         if ( in != NULL
00917                 && !findAmongNews( in)
00918                 && !findAmongSelected( in)
00919                 ) 
00920                 m_newlySelFcos.push_back( in);
00921 }
00922 
00923 void CMakeClosure::insertNew( const CComObjPtr<IMgaFolder>& in)
00924 {
00925         nop( in);
00926 
00927         if ( in != NULL
00928                 && !findAmongNews( in)
00929                 && !findAmongSelected( in)
00930                 ) 
00931                 m_newlySelFolds.push_back( in);
00932 }
00933 
00934 void CMakeClosure::insertNew( const CComObjPtr<IMgaModel>& in)
00935 {
00936         if ( in != NULL)
00937         {
00938                 CComObjPtr<IMgaFCO> fco;
00939                 COMTHROW( ::QueryInterface( in, fco));
00940 
00941                 insertNew( fco);
00942         }
00943 }
00944 
00945 void CMakeClosure::insertNew( const CComObjPtrVector<IMgaFCO>& in_v)
00946 {
00947         CComObjPtrVector<IMgaFCO>::const_iterator it = in_v.begin();
00948         for( ; it != in_v.end(); ++it)
00949                 insertNew( *it);
00950 }
00951 
00952 void CMakeClosure::insertNew( const CComObjPtrVector<IMgaFolder>& in_v)
00953 {
00954         CComObjPtrVector<IMgaFolder>::const_iterator it = in_v.begin();
00955         for( ; it != in_v.end(); ++it)
00956                 insertNew( *it);
00957 }
00958 
00959 bool CMakeClosure::findAmongSelected(const CComObjPtr<IMgaFCO>& in)
00960 {
00961         return std::find_if( m_selFcos.begin(), m_selFcos.end(), GmeEqual( in)) != m_selFcos.end();
00962 }
00963 
00964 bool CMakeClosure::findAmongSelected(const CComObjPtr<IMgaFolder>& in)
00965 {
00966         return std::find_if( m_selFolds.begin(), m_selFolds.end(), GmeEqual( in)) != m_selFolds.end();
00967 }
00968 
00969 bool CMakeClosure::findAmongNews(const CComObjPtr<IMgaFCO>& in)
00970 {
00971         return std::find_if( m_newlySelFcos.begin(), m_newlySelFcos.end(), GmeEqual( in)) != m_newlySelFcos.end();
00972 }
00973 
00974 bool CMakeClosure::findAmongNews(const CComObjPtr<IMgaFolder>& in)
00975 {
00976         return std::find_if( m_newlySelFolds.begin(), m_newlySelFolds.end(), GmeEqual( in)) != m_newlySelFolds.end();
00977 }
00978 
00979 bool CMakeClosure::isInLibrary( IMgaObject * obj)
00980 {
00981         VARIANT_BOOL vbLibrary;
00982         COMTHROW( obj->get_IsLibObject( &vbLibrary ) );
00983         return ( vbLibrary ) ? true : false;
00984 }
00985 
00986 // --------------------------------------------------------- wrappers
00987 void CMakeClosure::totalWrap()
00988 {
00989         CComObjPtrVector<IMgaFolder> fo_parents; // will collect the parents of all objects
00990         CComObjPtrVector<IMgaModel> mo_parents;
00991 
00992         CComObjPtrVector<IMgaFCO>::iterator fco_it = m_topFcos.begin();
00993         for( ; fco_it != m_topFcos.end(); ++fco_it)
00994         {
00995                 processUpward( *fco_it, fo_parents, mo_parents);
00996         }
00997         //int sz = m_selFcos.size();
00998 
00999         CComObjPtrVector<IMgaFolder>::iterator fold_it = m_topFolds.begin();
01000         for( ; fold_it != m_topFolds.end(); ++fold_it)
01001         {
01002                 processUpward( *fold_it, fo_parents, mo_parents);
01003         }
01004         //sz = m_selFolds.size();
01005 
01006         //append the folder parents to selected folders
01007         //m_selFolds.insert( m_selFolds.end(), fo_parents.begin(), fo_parents.end());
01008         CComObjPtrVector<IMgaFolder>::iterator fol_it = fo_parents.begin();
01009         for( ; fol_it != fo_parents.end(); ++fol_it)
01010         {
01011                 if ( std::find_if( m_selFolds.begin(), m_selFolds.end(), GmeEqual( *fol_it)) == m_selFolds.end())
01012                         m_selFolds.push_back( *fol_it);
01013                 else
01014                         ASSERT( 0);
01015         }
01016         
01017         //append the model parents to selected fcos
01018         CComObjPtrVector<IMgaModel>::iterator mod_it = mo_parents.begin();
01019         for( ; mod_it != mo_parents.end(); ++mod_it)
01020         {
01021                 CComObjPtr<IMgaFCO> fco;
01022                 COMTHROW( ::QueryInterface( *mod_it, fco));
01023                 if ( fco && std::find_if( m_selFcos.begin(), m_selFcos.end(), GmeEqual( fco)) == m_selFcos.end())
01024                         m_selFcos.push_back( fco);
01025                 else
01026                         ASSERT( 0);
01027         }
01028 }
01029 
01030 std::string CMakeClosure::processUpward( IMgaObject *obj, CComObjPtrVector<IMgaFolder>& f_parents, CComObjPtrVector<IMgaModel>& m_parents)
01031 {
01032         ASSERT( obj != NULL );
01033 
01034         objtype_enum objtype;
01035         COMTHROW( obj->get_ObjType(&objtype) );
01036 
01037         switch(objtype) {
01038         case OBJTYPE_MODEL:
01039         case OBJTYPE_ATOM:
01040         case OBJTYPE_REFERENCE:
01041         case OBJTYPE_CONNECTION:
01042         case OBJTYPE_SET:
01043                 {
01044                         CComObjPtr<IMgaFCO> fco;
01045                         COMTHROW( ::QueryInterface( obj, fco) );
01046                         ASSERT( fco);
01047 
01048                         bool topmost_m_set( false);
01049                         CComObjPtr<IMgaModel> m, topmost_m;
01050                         COMTHROW( fco->get_ParentModel( PutOut( m)));
01051                         while ( m)
01052                         {
01053                                 if ( std::find_if( m_parents.begin(), m_parents.end(), GmeEqual( m)) == m_parents.end())
01054                                         m_parents.push_back( m);
01055 
01056                                 topmost_m = m; topmost_m_set = true;
01057                                 CComObjPtr<IMgaModel> m_out;
01058                                 COMTHROW( m->get_ParentModel( PutOut( m_out)));
01059                                 m = m_out;
01060                         }
01061 
01062                         CComObjPtr<IMgaFolder> f;
01063                         if ( topmost_m_set)
01064                                 COMTHROW( topmost_m->get_ParentFolder( PutOut( f)));
01065                         else
01066                                 COMTHROW( fco->get_ParentFolder( PutOut( f)));
01067 
01068                         while( f)
01069                         {
01070                                 if ( std::find_if( f_parents.begin(), f_parents.end(), GmeEqual( f)) == f_parents.end())
01071                                         f_parents.push_back( f);
01072                                 
01073                                 CComObjPtr<IMgaFolder> f_out;
01074                                 COMTHROW( f->get_ParentFolder( PutOut( f_out)));
01075                                 f = f_out;
01076                         }
01077                         break;
01078                 }
01079         case OBJTYPE_FOLDER:
01080                 {
01081                         CComObjPtr<IMgaFolder> folder, f;
01082                         COMTHROW( ::QueryInterface( obj, folder));
01083                         ASSERT( folder);
01084 
01085                         COMTHROW( folder->get_ParentFolder( PutOut( f)));
01086 
01087                         while( f)
01088                         {
01089                                 if ( std::find_if( f_parents.begin(), f_parents.end(), GmeEqual( f)) == f_parents.end())
01090                                         f_parents.push_back( f);
01091 
01092                                 CComObjPtr<IMgaFolder> f_out;
01093                                 COMTHROW( f->get_ParentFolder( PutOut( f_out)));
01094                                 f = f_out;
01095                         }
01096                         break;
01097                 }
01098         default:
01099                 HR_THROW(E_INVALID_MGA);
01100         }; // endswitch
01101 
01102         return "";
01103 }
01104 
01105 void CMakeClosure::autoWrap()
01106 {
01107         if( m_topFcos.empty() && m_topFolds.empty()) // no top objects == root folder selected
01108                 return;
01109 
01110         CComObjPtrVector<IMgaFolder> f_parents;
01111         CComObjPtrVector<IMgaModel> m_parents;
01112 
01113         std::map< int, std::string> path_map;
01114         std::map< int, std::string> name_map;
01115 
01116         unsigned int k = 0;
01117         CComObjPtrVector<IMgaFCO>::iterator i = m_topFcos.begin();
01118         for( ; i != m_topFcos.end(); ++i, ++k)
01119         {
01120                 std::string res, resid;
01121 
01122                 // initialize the values
01123                 CComBstrObj name, id;
01124                 COMTHROW( (*i)->get_Name( PutOut(name)) );
01125                 COMTHROW( (*i)->get_ID( PutOut( id)) );
01126                 CopyTo( name, res);
01127                 CopyTo( id, resid);
01128                 res += '/';
01129                 resid += '/';
01130 
01131                 
01132                 bool topmost_m_set = false;
01133                 CComObjPtr<IMgaModel> m, topmost_m;
01134                 COMTHROW( (*i)->get_ParentModel( PutOut( m)));
01135                 while ( m)
01136                 {
01137                         CComBstrObj name, id;
01138                         std::string s, ids;
01139                         COMTHROW( m->get_Name( PutOut(name)) );
01140                         COMTHROW( m->get_ID( PutOut( id)) );
01141                         CopyTo( name, s);
01142                         CopyTo( id, ids);
01143                         res = s + '/' + res;
01144                         resid = ids + '/' + resid;
01145 
01146                         
01147                         if ( std::find_if( m_parents.begin(), m_parents.end(), GmeEqual( m)) == m_parents.end())
01148                                 m_parents.push_back( m);
01149 
01150                         topmost_m = m; topmost_m_set = true;
01151                         CComObjPtr<IMgaModel> m_out;
01152                         COMTHROW( m->get_ParentModel( PutOut( m_out)));
01153                         m = m_out;
01154                 }
01155 
01156                 CComObjPtr<IMgaFolder> f;
01157                 if ( topmost_m_set)
01158                         COMTHROW( topmost_m->get_ParentFolder( PutOut( f)));
01159                 else
01160                         COMTHROW( (*i)->get_ParentFolder( PutOut( f)));
01161 
01162                 while( f)
01163                 {
01164                         CComBstrObj name, id;
01165                         std::string s, ids;
01166                         COMTHROW( f->get_Name( PutOut( name)) );
01167                         COMTHROW( f->get_ID( PutOut( id)) );
01168                         CopyTo( name, s);
01169                         CopyTo( id, ids);
01170                         res = s + '/' + res;
01171                         resid = ids + '/' + resid;
01172 
01173                         if ( std::find_if( f_parents.begin(), f_parents.end(), GmeEqual( f)) == f_parents.end())
01174                                 f_parents.push_back( f);
01175                         
01176                         CComObjPtr<IMgaFolder> f_out;
01177                         COMTHROW( f->get_ParentFolder( PutOut( f_out)));
01178                         f = f_out;
01179                 }
01180 
01181                 path_map[ k] = resid;
01182                 name_map[ k] = res;
01183         }
01184 
01185         CComObjPtrVector<IMgaFolder>::iterator j = m_topFolds.begin();
01186         for(  ; j != m_topFolds.end(); ++j, ++k)
01187         {
01188                 std::string res, resid;
01189 
01190                 // initialize the values
01191                 CComBstrObj name, id;
01192                 COMTHROW( (*j)->get_Name( PutOut(name)) );
01193                 COMTHROW( (*j)->get_ID( PutOut( id)) );
01194                 CopyTo( name, res);
01195                 CopyTo( id, resid);
01196                 res += '/';
01197                 resid += '/';
01198 
01199 
01200                 CComObjPtr<IMgaFolder> f;
01201                 COMTHROW( (*j)->get_ParentFolder( PutOut( f)));
01202 
01203                 while( f)
01204                 {
01205                         CComBstrObj name, id;
01206                         std::string s, ids;
01207                         COMTHROW( f->get_Name( PutOut(name)) );
01208                         COMTHROW( f->get_ID( PutOut( id)) );
01209                         CopyTo( name, s);
01210                         CopyTo( id, ids);
01211                         res = s + '/' + res;
01212                         resid = ids + '/' + resid;
01213 
01214                         if ( std::find_if( f_parents.begin(), f_parents.end(), GmeEqual( f)) == f_parents.end())
01215                                 f_parents.push_back( f);
01216 
01217                         CComObjPtr<IMgaFolder> f_out;
01218                         COMTHROW( f->get_ParentFolder( PutOut( f_out)));
01219                         f = f_out;
01220                 }
01221 
01222                 path_map[ k] = resid;
01223                 name_map[ k] = res;
01224         }
01225 
01226         ASSERT( k > 0);
01227         if ( k == 0) // no top objects == root folder selected
01228                 return;
01229 
01230         std::string common_path = path_map[ 0];
01231         std::string common_name = name_map[ 0];
01232         for( unsigned int l = 1; l < k; ++l)
01233         {
01234                 std::string next_path = path_map[ l];
01235                 unsigned int minlen = std::min( next_path.length(), common_path.length());
01236 
01237                 // the strings may look like
01238                 // id-0065-001/id-0065-002/id-0065-003/
01239                 // id-0065-001/id-0065-002/id-0065-004/
01240                 // thus the common part of all may look like
01241                 // id-0065-001/id-0065-002/id-0065-00
01242                 // for this we use the position of the last slash
01243                 unsigned int pos_of_last_slash = 0;
01244                 unsigned int newlen = 0;
01245 
01246                 while( newlen < minlen && next_path[ newlen] == common_path[ newlen])
01247                 {
01248                         if ( common_path[ newlen] == '/') 
01249                                 pos_of_last_slash = newlen;
01250 
01251                         ++newlen;
01252                 }
01253                 common_path = common_path.substr( 0, pos_of_last_slash + 1); // tailing '/' needed
01254 
01255                 std::string next_name = name_map[ l];
01256                 minlen = std::min( next_name.length(), common_name.length());
01257 
01258                 pos_of_last_slash = 0;
01259                 newlen = 0;
01260                 while( newlen < minlen && next_name[ newlen] == common_name[ newlen])
01261                 {
01262                         if ( common_name[ newlen] == '/') 
01263                                 pos_of_last_slash = newlen;
01264 
01265                         ++newlen;
01266                 }
01267 
01268                 common_name = common_name.substr( 0, pos_of_last_slash + 1); // tailing '/' needed
01269         }
01270 
01271         common_name = common_name.substr( 0, common_name.length() - 1);
01272         common_path = common_path.substr( 0, common_path.length() - 1);
01273 
01274         std::string common_root_name; // the common model's name
01275         int pos = common_name.rfind( "/"); // tailing '/' removed previously
01276         common_root_name = common_name.substr( pos + 1, common_name.length() - pos - 1);
01277 
01278         std::string common_root_id; // the common model's id
01279         pos = common_path.rfind( "/"); // tailing '/' removed previously
01280         common_root_id = common_path.substr( pos + 1, common_path.length() - pos - 1);
01281         
01282         //AfxMessageBox( CString( "The common part of the paths is: ") + common_name.c_str() + CString( "\nThe last common part of the paths is: ") + common_root_name.c_str() );
01283 
01284         m_topFcos.clear(); // these two will be reset soon
01285         m_topFolds.clear();
01286         m_newlySelFcos.clear();
01287         m_newlySelFolds.clear();
01288 
01289         // are all selected objects children (not equal) of the common root?
01290         // checks if the common root is among the selected objects
01291         // ?indicates if the common root of the objects is a selected object itself
01292         bool are_all_seld_children_of_common_root = true; 
01293         for( unsigned int l = 0; l < k; ++l)
01294         {
01295                 // this happens when one of the sel objs is the grandparent/parent of all other sel objs
01296                 // in this case the common_root is a selected object
01297                 // and only this needs to be inserted in the m_topFCOs/Folders
01298                 if ( path_map[ l].length() == common_path.length() + 1 )
01299                         are_all_seld_children_of_common_root = false;
01300         }
01301 
01302         if ( !are_all_seld_children_of_common_root) // there is one root/top obj; otherwise the for cycle belwo will do the job
01303                 insertNew( common_root_id, true); // inserting the common root/top object
01304 
01305 
01306         // inserting the objects which stay between the common root and the top objects in the containment hierarchy
01307         for( unsigned int l = 0; l < k; ++l)
01308         {
01309                 std::string rest_of_path = path_map[ l];
01310                 rest_of_path = rest_of_path.substr( common_path.length() + 1, rest_of_path.length() - common_path.length() - 1); 
01311 
01312                 bool first_after_the_common_root = true;
01313                 while( !rest_of_path.empty())
01314                 {
01315                         std::string next_id;
01316                         pos = rest_of_path.find( '/'); // no leading '/' but a tailing '/' is there anyway
01317                         ASSERT( pos); // pos != 0
01318 
01319                         if ( pos != -1)
01320                         {
01321                                 next_id = rest_of_path.substr( 0, pos);
01322                                 rest_of_path = rest_of_path.substr( pos + 1, rest_of_path.length() - pos - 1);
01323                         }
01324                         else
01325                         {
01326                                 ASSERT( 0);
01327                                 next_id = rest_of_path;
01328                                 rest_of_path = ""; // to end the loop
01329                         }
01330 
01331                         insertNew( next_id, are_all_seld_children_of_common_root && first_after_the_common_root);
01332                         first_after_the_common_root = false;
01333                 }
01334 
01335                 // rest_of_path cannot be empty ( <=> first_after_the_common_root cannot be true) 
01336                 // with 'are_all_seld_children_of_common_root' being true
01337                 // p: all selected are children (not equal) of the common root
01338                 // q: the remaining path is not empty <==> first after the common root is false
01339                 // ASSERT( p -> q)  <=> ASSERT( !p || q)
01340 
01341                 ASSERT( !are_all_seld_children_of_common_root || !first_after_the_common_root);
01342         }
01343 
01344 
01345         // inserting into the list of selected objects the newly selected ones
01346         m_selFolds.insert( m_selFolds.end(), m_newlySelFolds.begin(), m_newlySelFolds.end());
01347         m_selFcos.insert( m_selFcos.end(), m_newlySelFcos.begin(), m_newlySelFcos.end());
01348 
01349         m_newlySelFolds.clear();
01350         m_newlySelFcos.clear();
01351 }
01352 
01353 void CMakeClosure::checkMeta( const CComObjPtrVector<IMgaFolder>& p_folds, const CComObjPtrVector<IMgaFCO>& p_fcos)
01354 {
01355         if ( p_folds.empty() && p_fcos.empty())
01356         {
01357                 m_acceptingKindsAndFolders.push_back( rootfolder_str);
01358                 return;
01359         }
01360 
01361         //
01362         // looking for potential folder containers
01363         unsigned int how_many_libraries = 0;
01364         std::set < std::string > goody_folds;
01365         bool goody_folds_init_done = false;
01366         for( CComObjPtrVector<IMgaFolder>::const_iterator fold_it = p_folds.begin(); fold_it != p_folds.end(); ++fold_it)
01367         {
01368                 // obtaining its meta
01369                 CComObjPtr<IMgaMetaFolder> f_meta;
01370                 COMTHROW( (*fold_it)->get_MetaFolder( PutOut( f_meta)));
01371                 
01372                 // check if exists library among the top folders
01373                 CComBstrObj kind_name;
01374                 COMTHROW( f_meta->get_Name( PutOut(kind_name)) );
01375                 std::string kind_nm;
01376                 CopyTo( kind_name, kind_nm);
01377                 if ( kind_nm == rootfolder_str)
01378                 {
01379                         ++how_many_libraries;
01380                         continue;
01381                 }
01382 
01383                 // will store the folder parents this folder may be part of
01384                 std::set < std::string > actual;
01385                 CComObjPtrVector<IMgaMetaFolder> act_vec;
01386                 f_meta->get_UsedInFolders( PutOut( act_vec) );//zz1
01387                 for( CComObjPtrVector<IMgaMetaFolder>::iterator a_i = act_vec.begin(); a_i != act_vec.end(); ++a_i)
01388                 {
01389                         CComBstrObj name;
01390                         COMTHROW( (*a_i)->get_Name( PutOut(name)) );
01391                         std::string s;
01392                         CopyTo( name, s);
01393 
01394                         actual.insert( s);
01395                 }
01396 
01397                 // calculate the intersection of the possible parent folders
01398                 if ( goody_folds_init_done)
01399                 {
01400                         std::set < std::string > res;
01401                         std::set_intersection( goody_folds.begin(), goody_folds.end(), actual.begin(), actual.end(), std::inserter( res, res.begin()));
01402                         goody_folds = res;
01403                 }
01404                 else
01405                 {
01406                         goody_folds = actual;
01407                         goody_folds_init_done = true;
01408                 }
01409         }
01410         
01411         for( CComObjPtrVector<IMgaFCO>::const_iterator kind_it = p_fcos.begin(); kind_it != p_fcos.end(); ++kind_it)
01412         {
01413                 // obtaining its meta
01414                 CComObjPtr<IMgaMetaFCO> k_meta;
01415                 COMTHROW( (*kind_it)->get_Meta( PutOut( k_meta)));
01416 
01417                 // will store the folder parents this fco may be part of
01418                 std::set < std::string > actual;
01419                 CComObjPtrVector<IMgaMetaFolder> act_vec;
01420                 k_meta->get_UsedInFolders( PutOut( act_vec) );//zz1
01421                 for( CComObjPtrVector<IMgaMetaFolder>::iterator a_i = act_vec.begin(); a_i != act_vec.end(); ++a_i)
01422                 {
01423                         CComBstrObj name;
01424                         COMTHROW( (*a_i)->get_Name( PutOut(name)) );
01425                         std::string s;
01426                         CopyTo( name, s);
01427 
01428                         actual.insert( s);
01429                 }
01430 
01431                 // calculate the intersection of the possible parent folders ( goody_folds might be already filled from the cycle before)
01432                 if ( goody_folds_init_done) // if goody_folds inited already
01433                 {
01434                         std::set < std::string > res;
01435                         std::set_intersection( goody_folds.begin(), goody_folds.end(), actual.begin(), actual.end(), std::inserter( res, res.begin()));
01436                         goody_folds = res;
01437                 }
01438                 else
01439                 {
01440                         goody_folds = actual;
01441                         goody_folds_init_done = true;
01442                 }
01443         }
01444 
01445         if( how_many_libraries == 0) //regular case
01446         {
01447                 // these folders may contain all objects ( topFCOs and topFolders)
01448                 for( std::set< std::string > :: iterator git = goody_folds.begin(); git != goody_folds.end(); ++git)
01449                         m_acceptingKindsAndFolders.push_back( *git);
01450         }
01451         else // there are some libraries as top folders, the only possible target to paste in is the roofolder
01452         {
01453                 if( p_folds.size() == how_many_libraries || // there are no other folders OR
01454                         goody_folds.end() != goody_folds.find( rootfolder_str))  // the RootFolder is a good target for the regular folders and kinds
01455                         m_acceptingKindsAndFolders.push_back( rootfolder_str);
01456         }
01457 
01458         
01459         //
01460         // looking for potential model containers
01461         
01462         if ( p_folds.empty()) // if folds needed to be inserted then models positively are not possible containers
01463         {       
01464                 // will store the intersection of accepting models
01465                 std::set < std::string > goody_models;
01466                 bool goody_models_init_done = false;
01467                 CComObjPtrVector<IMgaFCO>::const_iterator fco_it = p_fcos.begin();
01468                 for( ; fco_it != p_fcos.end(); ++fco_it)
01469                 {
01470                         // will store the names of those models which may contain this kind (*fco_it)
01471                         std::set < std::string > actual_models;
01472                         CComObjPtr<IMgaMetaFCO> k_meta;
01473                         COMTHROW( (*fco_it)->get_Meta( PutOut( k_meta)));
01474                         
01475                         // when checking the possible container kinds it is enough if we check the kind
01476                         // name matching, since an acceptable kind (even with different role) can be inserted 
01477                         // into a model (if ambiguities exist the resolver is invoked)
01478                         // that is why the role the topFCOs have in the containing models is ignored
01479 
01480                         CComPtr<IMgaMetaRoles> roles;
01481                         k_meta->get_UsedInRoles( &roles); // the fco may be used in these roles in the models (in this paradigm)
01482                         MGACOLL_ITERATE(IMgaMetaRole, roles) {
01483                                 // the parent model may contain the kind
01484                                 CComObjPtr<IMgaMetaModel> m;
01485                                 COMTHROW( MGACOLL_ITER->get_ParentModel( PutOut( m)));
01486 
01487                                 // take its name
01488                                 CComBstrObj name;
01489                                 COMTHROW( m->get_Name( PutOut(name)) );
01490                                 std::string s;
01491                                 CopyTo( name, s); // we have the name of a kind that may appear in the model
01492 
01493                                 actual_models.insert( s);
01494                         }
01495                         MGACOLL_ITERATE_END; 
01496 
01497                         // calculate the intersection of the possible parent models
01498                         if ( goody_models_init_done) // if set already
01499                         {
01500                                 std::set < std::string > res;
01501                                 std::set_intersection( goody_models.begin(), goody_models.end(), actual_models.begin(), actual_models.end(), std::inserter( res, res.begin()));
01502                                 goody_models = res;
01503                         }
01504                         else
01505                         {
01506                                 goody_models = actual_models;
01507                                 goody_models_init_done = true;
01508                         }
01509                 }
01510 
01511                 // these models may contain all objects ( topFCOs only since topFolders is empty)
01512                 for( std::set < std::string > :: iterator gid = goody_models.begin(); gid != goody_models.end(); ++gid)
01513                 {
01514                         m_acceptingKindsAndFolders.push_back( *gid);
01515                 }
01516         }
01517 }
01518 
01519 // --------------------------------------------------------- transactions
01520 void CMakeClosure::initTrans()
01521 {
01522         //ASSERT( m_project == NULL ); // the constructor initialized it
01523         ASSERT( m_territory == NULL );
01524 
01525         m_territory = NULL;
01526         COMTHROW( m_project->CreateTerritory(NULL, PutOut(m_territory), NULL) );
01527 
01528         // needs write access, when guids are created for all objects in the closure
01529         COMTHROW( m_project->BeginTransaction(m_territory, TRANSACTION_GENERAL) );
01530 
01531         m_GME = get_GME(m_project);
01532 
01533         // put the objects into the new territory
01534         CComObjPtrVector<IMgaFCO>::iterator fco_it = m_selFcos.begin();
01535         for( ; fco_it != m_selFcos.end(); ++fco_it )
01536         {
01537                 CComObjPtr<IMgaObject> obj;
01538                 COMTHROW(m_territory->OpenObj(*fco_it, PutOut(obj)));
01539                 CComObjPtr<IMgaFCO> fco;
01540                 COMTHROW(obj.QueryInterface(fco));
01541                 *fco_it = fco;
01542         }
01543 
01544         CComObjPtrVector<IMgaFolder>::iterator fold_it = m_selFolds.begin();
01545         for( ; fold_it != m_selFolds.end(); ++fold_it )
01546         {
01547                 CComObjPtr<IMgaObject> obj;
01548                 COMTHROW(m_territory->OpenObj(*fold_it, PutOut(obj)));
01549                 CComObjPtr<IMgaFolder> fold;
01550                 COMTHROW(obj.QueryInterface(fold));
01551                 *fold_it = fold;
01552         }
01553 }
01554 
01555 void CMakeClosure::doneTrans(bool abort)
01556 {
01557         if( m_territory != NULL )
01558                 m_territory->Destroy();
01559         m_territory = NULL;
01560 
01561         if( m_project != NULL )
01562         {
01563                 if( abort )
01564                         m_project->AbortTransaction();
01565                 else
01566                         m_project->CommitTransaction();
01567         }
01568         m_project = NULL;
01569 }
01570 
01571 // --------------------------------------------------------- getters
01572 void CMakeClosure::getFCOs( IMgaFCOs **res_fcos)
01573 {
01574         CComPtr<IMgaFCOs> coll;
01575         COMTHROW(coll.CoCreateInstance(OLESTR("Mga.MgaFCOs")));
01576         
01577         CComObjPtrVector<IMgaFCO>::iterator i = m_selFcos.begin();
01578         for( ; i != m_selFcos.end(); ++i)
01579                 COMTHROW(coll->Append( *i));
01580 
01581         *res_fcos = coll.Detach();
01582 }
01583 
01584 void CMakeClosure::getFolders( IMgaFolders **res_folds)
01585 {
01586         CComPtr<IMgaFolders> coll;
01587         COMTHROW(coll.CoCreateInstance(OLESTR("Mga.MgaFolders")));
01588         
01589         CComObjPtrVector<IMgaFolder>::iterator i = m_selFolds.begin();
01590         for( ; i != m_selFolds.end(); ++i)
01591                 COMTHROW(coll->Append( *i));
01592 
01593         *res_folds = coll.Detach();
01594 }
01595 
01596 bool CMakeClosure::noTopObjs()
01597 {
01598         // this means that either the variables are not calculated
01599         // or The RootFolder is the common root object of all selected objects
01600         //      in the latter case for dumping and parsing reasons (is not nice if
01601         // the clipboard contains a project dumped?) another dumper is used
01602         return m_topFcos.empty() && m_topFolds.empty();
01603 }
01604 
01605 void CMakeClosure::clearTopObjs()
01606 {
01607         m_topFcos.clear();
01608         m_topFolds.clear();
01609 }
01610 
01611 void CMakeClosure::getTopFCOs( IMgaFCOs **res_fcos)
01612 {
01613         CComPtr<IMgaFCOs> coll;
01614         COMTHROW(coll.CoCreateInstance(OLESTR("Mga.MgaFCOs")));
01615         
01616         CComObjPtrVector<IMgaFCO>::iterator i = m_topFcos.begin();
01617         for( ; i != m_topFcos.end(); ++i)
01618                 COMTHROW(coll->Append( *i));
01619 
01620         *res_fcos = coll.Detach();
01621 }
01622 
01623 void CMakeClosure::getTopFolders( IMgaFolders **res_folds)
01624 {
01625         CComPtr<IMgaFolders> coll;
01626         COMTHROW(coll.CoCreateInstance(OLESTR("Mga.MgaFolders")));
01627         
01628         CComObjPtrVector<IMgaFolder>::iterator i = m_topFolds.begin();
01629         for( ; i != m_topFolds.end(); ++i)
01630                 COMTHROW(coll->Append( *i));
01631 
01632         *res_folds = coll.Detach();
01633 }
01634 
01635 bool CMakeClosure::isAnyAccepting() const
01636 {
01637         return m_acceptingKindsAndFolders.size() > 0;
01638 }
01639 
01640 void CMakeClosure::getAccKindsInString( std::string& p_resStr) const
01641 {
01642         unsigned int i = 0;
01643         for( i = 0; i < m_acceptingKindsAndFolders.size(); ++i)
01644         {
01645                 if(i) p_resStr += " ";
01646 
01647                 p_resStr += m_acceptingKindsAndFolders[i];
01648         }
01649 }
01650 
01651 const std::vector< std::string >& CMakeClosure::getAccKindsVector() const
01652 {
01653         return m_acceptingKindsAndFolders;
01654 }
01655 
01656 void CMakeClosure::send2Console( const std::string& msg)
01657 {
01658         CComBSTR bstr( msg.c_str());
01659         if( m_GME) m_GME->ConsoleMessage( bstr, MSG_INFO);
01660         else ASSERT(0);// m_GME is not valid
01661 }