GME  13
MgaDumper.cpp
Go to the documentation of this file.
00001 
00002 #include "stdafx.h"
00003 #include "Parser.h"
00004 #include "MgaDumper.h"
00005 #include "Transcoder.h"
00006 #include <algorithm>
00007 
00008 #define FLUSH_LIMIT                     1000
00009 
00010 // -----------------------------------------------------------
00011 // --------------------------- GmeEqual ----------------------
00012 // -----------------------------------------------------------
00013 GmeEqual::GmeEqual( CComObjPtr<IMgaObject> obj)
00014 : m_objToFind( obj), m_which( 1)
00015 { }
00016 
00017 
00018 GmeEqual::GmeEqual( CComObjPtr<IMgaFCO> fco)
00019 : m_fcoToFind( fco), m_which( 2)
00020 { }
00021 
00022 
00023 GmeEqual::GmeEqual( CComObjPtr<IMgaFolder> folder)
00024 : m_folderToFind( folder), m_which( 3)
00025 { }
00026 
00027 
00028 GmeEqual::GmeEqual( CComObjPtr<IMgaModel> model)
00029 : m_modelToFind( model), m_which( 4)
00030 { }
00031 
00032 
00033 bool GmeEqual::operator() ( CComObjPtr<IMgaObject>& op )
00034 {
00035         ASSERT( m_which == 1); // which variable is set
00036 
00037         VARIANT_BOOL is_equal;
00038         COMTHROW( m_objToFind->get_IsEqual( op, &is_equal));
00039 
00040         if (is_equal != VARIANT_FALSE)
00041                 return true;
00042 
00043         return false;
00044 }
00045 
00046 bool GmeEqual::operator() ( CComObjPtr<IMgaFCO>& op )
00047 {
00048         ASSERT( m_which == 2); // which variable is set
00049 
00050         VARIANT_BOOL is_equal;
00051         COMTHROW( m_fcoToFind->get_IsEqual( op, &is_equal));
00052 
00053         if (is_equal != VARIANT_FALSE)
00054                 return true;
00055 
00056         return false;
00057 }
00058 
00059 bool GmeEqual::operator() ( CComObjPtr<IMgaFolder>& op )
00060 {
00061         ASSERT( m_which == 3); // which variable is set
00062 
00063         VARIANT_BOOL is_equal;
00064         COMTHROW( m_folderToFind->get_IsEqual( op, &is_equal));
00065 
00066         if (is_equal != VARIANT_FALSE)
00067                 return true;
00068 
00069         return false;
00070 }
00071 
00072 bool GmeEqual::operator() ( CComObjPtr<IMgaModel>& op )
00073 {
00074         ASSERT( m_which == 4); // which variable is set
00075 
00076         VARIANT_BOOL is_equal;
00077         COMTHROW( m_modelToFind->get_IsEqual( op, &is_equal));
00078 
00079         if (is_equal != VARIANT_FALSE)
00080                 return true;
00081 
00082         return false;
00083 }
00084 
00085 
00086 // --------------------------- CMgaDumper
00087 
00088 void CMgaDumper::InitDump(IMgaProject *p, BSTR xmlfile, BSTR encoding)
00089 {
00090         if( p == NULL )
00091                 HR_THROW(E_INVALIDARG);
00092 
00093         std::tstring filename;
00094         CopyTo(xmlfile, filename);
00095 
00096         if( filename.empty() )
00097                 HR_THROW(E_INVALIDARG);
00098 
00099         ofs.init( filename.c_str(), encoding);
00100 
00101         elems.clear();
00102 
00103         ASSERT( project == NULL );
00104         ASSERT( territory == NULL );
00105 
00106         territory = NULL;
00107         COMTHROW( p->CreateTerritory(NULL, PutOut(territory), NULL) );
00108 
00109         COMTHROW( p->BeginTransaction(territory, TRANSACTION_READ_ONLY) );
00110         project = p;
00111 
00112         fco_count = 0;
00113 }
00114 
00115 void CMgaDumper::DoneDump(bool abort)
00116 {
00117         ofs.finalize();
00118         elems.clear();
00119 
00120         if( territory != NULL )
00121                 COMTHROW(territory->Destroy());
00122         territory = NULL;
00123 
00124         if( project != NULL )
00125         {
00126                 if( abort )
00127                         COMTHROW(project->AbortTransaction());
00128                 else
00129                         COMTHROW(project->CommitTransaction());
00130         }
00131         
00132         m_selFcos.clear();
00133         m_selFolders.clear();
00134         project = NULL;
00135 }
00136 
00137 STDMETHODIMP CMgaDumper::DumpProject(IMgaProject *p, BSTR xmlfile)
00138 {
00139         return DumpProject2(p, xmlfile, NULL);
00140 }
00141 
00142 STDMETHODIMP CMgaDumper::DumpProject2(IMgaProject *p, BSTR xmlfile, ULONGLONG hwndParent_)
00143 {
00144         CHECK_IN(p);
00145         m_dumpGuids = true; // dump GUIDs with the whole project
00146         m_closureDump = false;
00147         m_v2          = false;
00148         m_strictDump = false;
00149         m_dumpRelids = true;
00150         m_dumpLibraryStubs = false; // make sure closure logic does not involve in it
00151 
00152         COMTRY
00153         {
00154                 HWND hwndParent = (HWND)hwndParent_;
00155                 if (hwndParent != 0)
00156                 {
00157                         COMTHROW( m_progress.CoCreateInstance(L"Mga.MgaProgressDlg") );
00158                         COMTHROW( m_progress->SetTitle(_bstr_t(L"Exporting XME file...")) );
00159                         COMTHROW( m_progress->StartProgressDialog(hwndParent) );
00160                 }
00161                 InitDump(p, xmlfile, _bstr_t(L"UTF-8"));
00162 
00163                 ofs << L"<!DOCTYPE project SYSTEM \"mga.dtd\">\n\n";
00164 
00165                 Dump(p);
00166 
00167                 DoneDump(false);
00168                 if (m_progress != NULL )
00169                 {
00170                         COMTHROW(m_progress->StopProgressDialog());
00171                         m_progress = NULL;
00172                 }
00173         }
00174         COMCATCH(
00175                 DoneDump(true);
00176                 if (m_progress != NULL )
00177                 {
00178                         COMTHROW(m_progress->StopProgressDialog());
00179                         m_progress = NULL;
00180                 }
00181         )
00182 }
00183 
00184 STDMETHODIMP CMgaDumper::DumpFCOs(IMgaProject *proj, IMgaFCOs *p, IMgaFolders *f, IMgaRegNodes *r, BSTR xmlfile)
00185 {
00186         return DumpFCOs2(proj, p, f, r, xmlfile, NULL);
00187 }
00188 
00189 STDMETHODIMP CMgaDumper::DumpFCOs2(IMgaProject *proj, IMgaFCOs *p, IMgaFolders *f, IMgaRegNodes *r, BSTR xmlfile, ULONGLONG hwndParent)
00190 {
00191         m_dumpGuids = false; // while dumping selected FCOs do NOT dump guids of the fco's
00192         m_closureDump = false;
00193         m_v2          = false;
00194         m_strictDump = false; // this method uses the permissive dump
00195         // meaning that if a model/folder is in the closure then all children
00196         // and grandchildren are dumped as well
00197 
00198         m_dumpRelids = false; //dumpversion = 2; // no relids dumped
00199         m_dumpLibraryStubs = false; // make sure closure logic does not involve in it
00200 
00201         //CHECK_IN( (int)p | (int)f);
00202 
00203         COMTRY
00204         {
00205                 if ( p) CopyTo(p, m_selFcos);
00206                 if ( f) CopyTo(f, m_selFolders);
00207                 if ( r) CopyTo(r, m_selRegNodes);
00208 
00209                 if( m_selFcos.empty() && m_selFolders.empty() && m_selRegNodes.empty())
00210                         return S_OK;
00211 
00212                 CComObjPtr<IMgaProject> project;
00213 
00214                 if ( !m_selFcos.empty())
00215                         COMTHROW( m_selFcos.front()->get_Project( PutOut( project)) );
00216                 else if ( !m_selFolders.empty())
00217                         COMTHROW( m_selFolders.front()->get_Project( PutOut( project)) );
00218                 else if ( !m_selRegNodes.empty()) // newly added
00219                         project = proj;
00220                 else
00221                         return S_OK;
00222 
00223                 if( !project) return S_OK;
00224 
00225                 InitDump(project, xmlfile, _bstr_t(L"UTF-16"));
00226 
00227                 ofs << L"<!DOCTYPE clipboard SYSTEM \"mga.dtd\" [\r\n";
00228                 ofs << L"\t<!ELEMENT clipboard (folder|model|atom|reference|set|connection|regnode)*>\r\n";
00229                 //ofs << "\t<!ATTLIST clipboard acceptingkind CDATA     #IMPLIED>\n";
00230                 //ofs << "]>\n\n";
00231                 ofs << L"\t<!ATTLIST clipboard\r\n";
00232                 ofs << L"\t\tacceptingkind CDATA #IMPLIED\r\n";
00233                 ofs << L"\t\tparadigmnamehint CDATA #IMPLIED\r\n";//TODO: could be extended with targetnamespacehint, srcnamespacehint
00234                 ofs << L"\t>\r\n";
00235                 ofs << L"]>\r\n\r\n";
00236 
00237 
00238 
00239                 StartElem(_T("clipboard"));
00240 
00241                 // dumping originating paradigm name as a hint for the parser
00242                 CComObjPtr<IMgaMetaProject> metaproject;
00243                 COMTHROW( project->get_RootMeta(PutOut(metaproject)) );
00244                 ASSERT( metaproject != NULL );
00245                 if( metaproject) Attr(_T("paradigmnamehint"), metaproject, &IMgaMetaProject::get_Name);
00246 
00247                 CComObjPtrVector<IMgaFolder>::iterator fi = m_selFolders.begin();
00248                 while( fi != m_selFolders.end() )
00249                 {
00250                         CComObjPtr<IMgaObject> obj;
00251                         COMTHROW(territory->OpenObj(*fi, PutOut(obj)));
00252                         CComObjPtr<IMgaFolder> folder;
00253                         COMTHROW(obj.QueryInterface( folder));
00254                         *fi = folder;
00255                         ++fi;
00256                 }
00257 
00258                 CComObjPtrVector<IMgaFCO>::iterator i = m_selFcos.begin();
00259                 while( i != m_selFcos.end() )
00260                 {
00261                         // PETER: put the object into the parser's territory
00262                         CComObjPtr<IMgaObject> obj;
00263                         COMTHROW(territory->OpenObj(*i, PutOut(obj)));
00264                         CComObjPtr<IMgaFCO> fco;
00265                         COMTHROW(obj.QueryInterface( fco));
00266                         *i = fco;
00267                         ++i;
00268                 }
00269 
00270                 if( m_selFolders.size() + m_selFcos.size() > 0) removeInnerObjs();
00271                 
00272                 for( fi = m_selFolders.begin(); fi != m_selFolders.end(); ++fi )
00273                         Dump( *fi);
00274 
00275                 for( i = m_selFcos.begin(); i != m_selFcos.end(); ++i )
00276                         Dump ( *i);
00277 
00278                 if( !m_selRegNodes.empty())
00279                 {
00280                         StartElem(_T("regnode"));
00281                         Attr(_T("name"), _T("annotations"));
00282                         StartElem(_T("value"));
00283                         EndElem(); //value
00284 
00285                         for( CComObjPtrVector<IMgaRegNode>::iterator ri = m_selRegNodes.begin(); ri != m_selRegNodes.end(); ++ri)
00286                                 Dump( *ri);
00287 
00288                         EndElem(); // regnode of annotations
00289                 }
00290 
00291                 EndElem();
00292                 DoneDump(false);
00293         }
00294         COMCATCH( DoneDump(true); )
00295 }
00296 
00297 // ------- Low level stuff
00298 
00299 inline void CMgaDumper::Indent(int i)
00300 {
00301         for(; i > 0; --i)
00302                 ofs << '\t';
00303 }
00304 
00305 inline void CMgaDumper::StartElem(const TCHAR *name)
00306 {
00307         ASSERT( name != NULL );
00308 
00309         if( !elems.empty() && !elems.back().inbody )
00310         {
00311                 ASSERT( !elems.back().indata );
00312 
00313                 ofs << L">\n";
00314                 elems.back().inbody = true;
00315         }
00316 
00317         elems.push_back(elem());
00318         elems.back().name = name;
00319         elems.back().inbody = false;
00320         elems.back().indata = false;
00321 
00322         Indent(elems.size()-1);
00323         ofs << L'<' << name;
00324 }
00325 
00326 inline void CMgaDumper::Attr(const TCHAR *name, const TCHAR *value)
00327 {
00328         ASSERT( name != NULL );
00329         ASSERT( value != NULL );
00330 
00331         ASSERT( !elems.empty() && !elems.back().inbody );
00332         
00333         ofs << L' ' << name << L"=\"" << Transcoder::StdEscape << value << Transcoder::NoEscape << L'"';
00334 }
00335 
00336 inline void CMgaDumper::Attr(const TCHAR *name, const TCHAR *value, int len)
00337 {
00338         ASSERT( name != NULL );
00339         ASSERT( value != NULL );
00340         ASSERT( len >= 0 );
00341 
00342         ASSERT( !elems.empty() && !elems.back().inbody && !elems.back().indata );
00343 
00344         ofs << L' ' << name << L"=\"" << Transcoder::StdEscape << std::tstring( value, len) << Transcoder::NoEscape << L'"';
00345 }
00346 
00347 bool CMgaDumper::HasMarkup(const TCHAR *value, int len)
00348 {
00349         while( --len >= 0 )
00350         {
00351                 TCHAR c = *(value++);
00352                 if( c == '<' || c == '>' || c == '&' || c == '\'' || c == '\"' )
00353                         return true;
00354         }
00355 
00356         return false;
00357 }
00358 
00359 inline void CMgaDumper::Data(const TCHAR *value, int len)
00360 {
00361         ASSERT( value != NULL );
00362         ASSERT( len >= 0 );
00363         ASSERT( !elems.empty() );
00364 
00365         if( !elems.back().inbody )
00366         {
00367                 ofs << L">";
00368                 elems.back().inbody = true;
00369         }
00370 
00371         ofs << Transcoder::StdEscape << std::tstring( value, len) << Transcoder::NoEscape;
00372 
00373         elems.back().indata = true;
00374 
00375 }
00376 
00377 inline void CMgaDumper::EndElem()
00378 {
00379         ASSERT( !elems.empty() );
00380 
00381         if( elems.back().inbody )
00382         {
00383                 if( !elems.back().indata )
00384                         Indent(elems.size()-1);
00385 
00386                 ofs << L"</" << elems.back().name << L">\n";
00387         }
00388         else
00389         {
00390                 ofs << L"/>\n";
00391         }
00392 
00393         elems.pop_back();
00394 }
00395 
00396 // ------- CheckInClosure
00397 // there are two ways:
00398 //  strict: those objects are dumped which are selected ( can be found in m_selFCO/Folder)
00399 //          this method is used by the copy closure methods
00400 //  permissive: hierarchical selection, meaning that if a folder/model is selected then
00401 //              its children/grandchildren need not to be selected (need not be in m_selFCO/Folder)
00402 //              this is used by regular clipboard methods
00403 //
00404 inline bool CMgaDumper::CheckInClosure(CComObjPtr<IMgaAttribute> ) { return true;}
00405 inline bool CMgaDumper::CheckInClosure(CComObjPtr<IMgaConnPoint> ) { return true;}
00406 
00407 bool CMgaDumper::CheckInClosure(CComObjPtr<IMgaFolder> folder)
00408 {
00409         if ( m_selFolders.empty() && m_selFcos.empty()) {
00410                 // if the selected FCOs and selected Folders values are empty
00411                 // then everything is in the closure 
00412                 return true;
00413         }
00414 
00415         bool in_closure = false;
00416 
00417         if (m_strictDump)
00418         {
00419                 in_closure = std::find_if( m_selFolders.begin(), m_selFolders.end(), GmeEqual( folder)) != m_selFolders.end();
00420         }
00421         else
00422         {
00423                 CComObjPtr<IMgaFolder> curr_folder = folder;
00424                 while ( curr_folder != NULL && !in_closure)
00425                 {
00426                         in_closure = std::find_if( m_selFolders.begin(), m_selFolders.end(), GmeEqual( curr_folder)) != m_selFolders.end();
00427 
00428                         CComObjPtr<IMgaFolder> parent;
00429                         COMTHROW(curr_folder->get_ParentFolder(PutOut( parent)));
00430 
00431                         curr_folder = NULL;
00432                         
00433                         if (parent != NULL) {
00434                                 curr_folder = parent;
00435                         }
00436                 }
00437         }
00438         return in_closure;
00439 }
00440 
00441 bool CMgaDumper::CheckInClosure(CComObjPtr<IMgaFCO> fco) 
00442 {
00443         if ( m_selFolders.empty() && m_selFcos.empty()) {
00444                 // if the selected FCOs and selected Folders values are empty
00445                 // then everything is in the closure 
00446                 return true;
00447         }
00448 
00449         bool in_closure = false;
00450 
00451         if (m_strictDump)
00452         {
00453                 in_closure = std::find_if( m_selFcos.begin(), m_selFcos.end(), GmeEqual( fco)) != m_selFcos.end();
00454         }
00455         else
00456         {
00457 
00458                 CComObjPtr<IMgaFCO> curr_fco = fco;
00459                 CComObjPtr<IMgaFCO> last_fco = fco;
00460                 while ( curr_fco != NULL && !in_closure) {
00461                         
00462                         in_closure = std::find_if( m_selFcos.begin(), m_selFcos.end(), GmeEqual( curr_fco)) != m_selFcos.end();
00463 
00464                         CComObjPtr<IMgaModel> parent;
00465                         COMTHROW(curr_fco->get_ParentModel(PutOut(parent)));
00466                         last_fco = curr_fco;
00467                         curr_fco = NULL;
00468                         if (parent != NULL) {
00469                                 COMTHROW( ::QueryInterface(parent, curr_fco) );
00470                         }
00471                 }
00472 
00473                 if ( !in_closure) // no parent yet (model) in closure, need to check folders
00474                 {
00475                         CComObjPtr<IMgaFolder> par_folder;
00476                         COMTHROW( last_fco->get_ParentFolder(PutOut( par_folder)));
00477 
00478                         while ( par_folder != NULL && !in_closure)
00479                         {
00480                                 in_closure = std::find_if( m_selFolders.begin(), m_selFolders.end(), GmeEqual( par_folder)) != m_selFolders.end();
00481 
00482                                 CComObjPtr<IMgaFolder> parent;
00483                                 COMTHROW(par_folder->get_ParentFolder(PutOut( parent)));
00484 
00485                                 par_folder = NULL;
00486                                 
00487                                 if (parent != NULL)
00488                                         par_folder = parent;
00489                         }
00490                 }
00491         }
00492 
00493         return in_closure;
00494 }
00495 
00496 // ------- Dumpers
00497 
00498 void CMgaDumper::Dump(IMgaProject *project)
00499 {
00500         ASSERT( project != NULL );
00501 
00502         CComVariant variant;
00503         CComBstrObj bstr;
00504         GUID guid;
00505 
00506         StartElem(_T("project"));
00507 
00508         COMTHROW( project->get_GUID(PutOut(variant)) );
00509         CopyTo(variant, guid);
00510         CopyTo(guid, PutOut(bstr));
00511         Attr(_T("guid"), bstr);
00512 
00513         Attr(_T("cdate"), project, &IMgaProject::get_CreateTime);
00514         Attr(_T("mdate"), project, &IMgaProject::get_ChangeTime);
00515         Attr(_T("version"), project, &IMgaProject::get_Version);
00516 
00517         CComObjPtr<IMgaMetaProject> metaproject;
00518         COMTHROW( project->get_RootMeta(PutOut(metaproject)) );
00519         ASSERT( metaproject != NULL );
00520 
00521         variant.Clear();
00522         bstr.Empty();
00523         COMTHROW( metaproject->get_GUID(PutOut(variant)) );
00524         CopyTo(variant, guid);
00525         CopyTo(guid, PutOut(bstr));
00526         Attr(_T("metaguid"), bstr);
00527         Attr(_T("metaversion"), metaproject, &IMgaMetaProject::get_Version);
00528         Attr(_T("metaname"), metaproject, &IMgaMetaProject::get_Name);
00529         
00530 
00531 
00532         StartElem(_T("name"));
00533         Data(project, &IMgaProject::get_Name);
00534         EndElem();
00535 
00536         StartElem(_T("comment"));
00537         Data(project, &IMgaProject::get_Comment);
00538         EndElem();
00539 
00540         StartElem(_T("author"));
00541         Data(project, &IMgaProject::get_Author);
00542         EndElem();
00543 
00544         CComObjPtr<IMgaFolder> folder;
00545         COMTHROW( project->get_RootFolder(PutOut(folder)) );
00546         Dump(folder);
00547 
00548         EndElem();
00549 }
00550 
00551 void CMgaDumper::Dump(IMgaFolder *folder)
00552 {
00553         ASSERT( folder != NULL );
00554 
00555         StartElem(_T("folder"));
00556 
00557         Attr(_T("id"), folder, &IMgaFolder::get_ID);
00558 
00559         if( m_closureDump && m_v2)
00560         {
00561                 // dump closureguid attribute
00562                 CComObjPtr<IMgaRegNode> regnode;
00563                 COMTHROW( folder->get_RegistryNode( CComBSTR( GLOBAL_ID_STR), PutOut( regnode)));
00564                 long status;
00565                 COMTHROW( regnode->get_Status( &status));
00566                 if( status == ATTSTATUS_HERE)
00567                 {
00568                         CComBstrObj guid_str;
00569                         COMTHROW( regnode->get_Value( PutOut(guid_str)));
00570                         if( guid_str.Length() == GLOBAL_ID_LEN) // using { 8-4-4-4-12} form
00571                                 Attr( _T("closureguid"), guid_str);
00572                 }
00573 
00574 
00575                 Attr( _T("closurename"), folder, &IMgaFolder::get_Name);
00576 
00577         }
00578 
00579         if(dumpversion >= 1) {
00580                 if( m_dumpRelids)
00581                 {
00582                         LAttr(_T("relid"), folder, &IMgaFolder::get_RelID);
00583                         LAttr(_T("childrelidcntr"), folder, &IMgaFolder::get_ChildRelIDCounter);
00584                 }
00585 
00586                 CComBstrObj libname;
00587                 COMTHROW( folder->get_LibraryName(PutOut(libname)) );
00588                 if(libname) Attr(_T("libref"),libname);
00589 
00590                 VARIANT_BOOL readonly;
00591                 COMTHROW( folder->HasReadOnlyAccess( &readonly));
00592                 if( readonly) Attr( _T("perm"), _T("1"));
00593         }
00594 
00595         CComObjPtr<IMgaMetaFolder> metafolder;
00596         COMTHROW( folder->get_MetaFolder(PutOut(metafolder)) );
00597         Attr(_T("kind"), metafolder, &IMgaMetaFolder::get_Name);
00598 
00599         if( m_dumpGuids) // this is true if Project is dumped and mgaversion of project is 2
00600         {
00601                 try 
00602                 {
00603                         CComBstrObj bs;
00604                         HRESULT hr = folder->GetGuidDisp( PutOut( bs));
00605                         if( SUCCEEDED( hr) && bs && bs.Length() == 38) // {%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X} <-- dumping that form (38 chars long including braces)
00606                                 Attr( _T("guid"), bs);//Attr( _T("guid"), IMgaObject::GetGuidDisp);
00607 
00608                 } catch( hresult_exception& )
00609                 {
00610                 }
00611         }
00612 
00613         StartElem(_T("name"));
00614         Data(folder, &IMgaFolder::get_Name);
00615         EndElem();
00616 
00617         DumpConstraints(folder);
00618 
00619         Dump(folder, &IMgaFolder::get_ChildFolders);
00620 
00621         // dumping the regnodes
00622         CComObjPtrVector<IMgaRegNode> v;
00623         COMTHROW( folder->get_Registry(VARIANT_FALSE, PutOut(v)) );
00624         CComObjPtrVector<IMgaRegNode>::iterator i = v.begin();
00625         CComObjPtrVector<IMgaRegNode>::iterator e = v.end();
00626         
00627         Sort(&v);
00628         
00629         while( i != e )
00630         {
00631                 Dump(*i);
00632 
00633                 ++i;
00634         }
00635 
00636         Dump(folder, &IMgaFolder::get_ChildFCOs);
00637 
00638         EndElem();
00639 }
00640 
00641 void CMgaDumper::Dump(IMgaRegNode *regnode)
00642 {
00643         ASSERT( regnode != NULL );
00644 
00645         StartElem(_T("regnode"));
00646 
00647         Attr(_T("name"), regnode, &IMgaRegNode::get_Name);
00648 
00649         VARIANT_BOOL b;
00650         COMTHROW( regnode->get_Opacity(&b) );
00651 
00652         if( b != VARIANT_FALSE )
00653                 Attr(_T("isopaque"), _T("yes"));
00654 
00655         long status;
00656         COMTHROW( regnode->get_Status( &status ) );
00657         if( status == -2) // ATTSTATUS_UNDEFINED
00658                 Attr(_T("status"), _T("undefined"));
00659 
00660         StartElem(_T("value"));
00661         Data(regnode, &IMgaRegNode::get_Value);
00662         EndElem();
00663 
00664         // FIXME: MetaGME uses many regnodes on rootfolder, which makes progress bar freeze
00665 
00666         // dumping the subnodes
00667         CComObjPtrVector<IMgaRegNode> v;
00668         COMTHROW( regnode->get_SubNodes(VARIANT_FALSE, PutOut(v)) );
00669         Sort(&v);
00670 
00671         CComObjPtrVector<IMgaRegNode>::iterator i = v.begin();
00672         CComObjPtrVector<IMgaRegNode>::iterator e = v.end();
00673         while( i != e )
00674         {
00675                 Dump(*i);
00676 
00677                 ++i;
00678         }
00679 
00680         EndElem();
00681 }
00682 
00683 void CMgaDumper::Dump(IMgaObject *obj)
00684 {
00685         ASSERT( obj != NULL );
00686 
00687         objtype_enum objtype;
00688         COMTHROW( obj->get_ObjType(&objtype) );
00689 
00690         switch(objtype)
00691         {
00692         case OBJTYPE_MODEL:
00693                 {
00694                         CComObjPtr<IMgaModel> p;
00695                         COMTHROW( ::QueryInterface(obj, p) );
00696                         Dump(p);
00697                         break;
00698                 }
00699 
00700         case OBJTYPE_ATOM:
00701                 {
00702                         CComObjPtr<IMgaAtom> p;
00703                         COMTHROW( ::QueryInterface(obj, p) );
00704                         Dump(p);
00705                         break;
00706                 }
00707 
00708         case OBJTYPE_REFERENCE:
00709                 {
00710                         CComObjPtr<IMgaReference> p;
00711                         COMTHROW( ::QueryInterface(obj, p) );
00712                         Dump(p);
00713                         break;
00714                 }
00715 
00716         case OBJTYPE_CONNECTION:
00717                 {
00718                         CComObjPtr<IMgaConnection> p;
00719                         COMTHROW( ::QueryInterface(obj, p) );
00720                         Dump(p);
00721                         break;
00722                 }
00723 
00724         case OBJTYPE_SET:
00725                 {
00726                         CComObjPtr<IMgaSet> p;
00727                         COMTHROW( ::QueryInterface(obj, p) );
00728                         Dump(p);
00729                         break;
00730                 }
00731 
00732         case OBJTYPE_FOLDER:
00733                 {
00734                         CComObjPtr<IMgaFolder> p;
00735                         COMTHROW( ::QueryInterface(obj, p) );
00736                         Dump(p);
00737                         break;
00738                 }
00739 
00740         default:
00741                 HR_THROW(E_INVALID_MGA);
00742         };
00743 }
00744 
00745 void CMgaDumper::DumpFCO(IMgaFCO *fco, bool dump_attrs, bool dump_name, bool dump_elems)
00746 {
00747         ASSERT( fco != NULL );
00748 
00749         if (fco_count++ % FLUSH_LIMIT == 0)
00750         {
00751                 ASSERT( territory != NULL );
00752 
00753                 if (fco_count >= FLUSH_LIMIT)
00754                 {
00755                         COMTHROW( territory->Flush() );
00756                         COMTHROW( project->CommitTransaction() );
00757                         COMTHROW( project->BeginTransaction(territory, TRANSACTION_READ_ONLY) );
00758                 }
00759 
00760                 if (m_progress)
00761                 {
00762                         static TCHAR progress_msg[512];
00763                         _stprintf_s(progress_msg, _T("Number of exported FCOs: %ld"), (long)fco_count);
00764                         COMTHROW(m_progress->SetLine(0, PutInBstr(progress_msg)));
00765                         COMTHROW(m_progress->SetProgress(fco_count, 0));
00766                 }
00767         }
00768 
00769         if( dump_attrs )
00770         {
00771                 Attr(_T("id"), fco, &IMgaFCO::get_ID);
00772 
00773                 CComObjPtr<IMgaMetaFCO> metafco;
00774                 COMTHROW( fco->get_Meta(PutOut(metafco)) );
00775                 Attr(_T("kind"), metafco, &IMgaMetaFCO::get_Name);
00776 
00777                 CComObjPtr<IMgaMetaRole> role;
00778                 COMTHROW( fco->get_MetaRole(PutOut(role)) );
00779                 if( role != NULL )
00780                         Attr(_T("role"), role, &IMgaMetaRole::get_Name);
00781 
00782                 if( m_dumpGuids) // this is true if Project is dumped and mgaversion of project is 2
00783                 {
00784                         try 
00785                         {
00786                                 CComBstrObj bs;
00787                                 HRESULT hr = fco->GetGuidDisp( PutOut( bs));
00788                                 if( SUCCEEDED( hr) && bs && bs.Length() == 38) // {%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X} <-- dumping that form (38 chars long including braces)
00789                                         Attr( _T("guid"), bs);//Attr( _T("guid"), IMgaFCO::GetGuidDisp);
00790 
00791                         } catch( hresult_exception& )
00792                         {
00793                         }
00794                 }
00795 
00796                 if( m_closureDump && m_v2)
00797                 {
00798                         // dump closureguid attribute
00799                         CComBstrObj guid_str; // this form will not create the node if is not present
00800                         COMTHROW( fco->get_RegistryValue( CComBSTR( GLOBAL_ID_STR), PutOut( guid_str)));
00801                         if( guid_str != 0 && guid_str.Length() == GLOBAL_ID_LEN) // using { 8-4-4-4-12} form
00802                                 Attr( _T("closureguid"), guid_str);
00803 
00804                         Attr( _T("closurename"), fco, &IMgaFCO::get_Name);
00805 
00806                 }
00807 
00808                 VARIANT_BOOL prim = VARIANT_TRUE;
00809                 bool lost_basetype = false;
00810                 CComObjPtr<IMgaFCO> derivedfrom;
00811                 COMTHROW( fco->get_DerivedFrom(PutOut(derivedfrom)) );
00812                 if(derivedfrom != NULL )
00813                 {
00814                         if (CheckInClosure(derivedfrom)) {
00815                                 Attr(_T("derivedfrom"), derivedfrom, &IMgaFCO::get_ID);
00816 
00817                                 VARIANT_BOOL b;
00818 
00819                                 COMTHROW( fco->get_IsInstance(&b) );
00820                                 Attr(_T("isinstance"), b != VARIANT_FALSE ? _T("yes") : _T("no"));
00821 
00822                                 COMTHROW( fco->get_IsPrimaryDerived(&prim) );
00823                                 Attr(_T("isprimary"), prim != VARIANT_FALSE ? _T("yes") : _T("no"));
00824                         }
00825                         else {
00826                                 lost_basetype = true;
00827                         }
00828 
00829                         if( m_closureDump && !CheckInClosure(derivedfrom))
00830                         {
00831                                 if ( m_dumpLibraryStubs && !CheckInClosure(derivedfrom) && !isInLibrary( fco) && isInLibrary( derivedfrom)) { //derived from a type defined in a library
00832                                         CComBSTR name;
00833                                         COMTHROW( derivedfrom->get_AbsPath( &name));
00834                                         std::tstring nm;
00835                                         CopyTo( name, nm);
00836                                         
00837                                         Attr(_T("closurelibderivedfrom"), nm);
00838 
00839                                         VARIANT_BOOL b;
00840 
00841                                         COMTHROW( fco->get_IsInstance(&b) );
00842                                         Attr(_T("isinstance"), b != VARIANT_FALSE ? _T("yes") : _T("no"));
00843 
00844                                         COMTHROW( fco->get_IsPrimaryDerived(&prim) );
00845                                         Attr(_T("isprimary"), prim != VARIANT_FALSE ? _T("yes") : _T("no"));
00846                                 }
00847                                 else if( m_v2)
00848                                 {
00849                                         CComBSTR name;
00850 
00851                                         COMTHROW( derivedfrom->get_AbsPath( &name));
00852                                         std::tstring nm;
00853                                         CopyTo( name, nm);
00854                                         
00855                                         COMTHROW( fco->get_AbsPath( &name));
00856                                         std::tstring nm2;
00857                                         CopyTo( name, nm2);
00858 
00859                                         Attr(_T("closure2derivedfrom"), makeRel( nm, nm2));
00860 
00861                                         VARIANT_BOOL b;
00862 
00863                                         COMTHROW( fco->get_IsInstance(&b) );
00864                                         Attr(_T("isinstance"), b != VARIANT_FALSE ? _T("yes") : _T("no"));
00865 
00866                                         COMTHROW( fco->get_IsPrimaryDerived(&prim) );
00867                                         Attr(_T("isprimary"), prim != VARIANT_FALSE ? _T("yes") : _T("no"));
00868                                 }
00869                         }
00870 
00871                         if( m_closureDump && m_v2)
00872                         {
00873                                 CComBstrObj guid;
00874                                 COMTHROW( derivedfrom->get_RegistryValue( CComBSTR( GLOBAL_ID_STR), PutOut( guid)));
00875                                 if( guid != 0 && guid.Length() == GLOBAL_ID_LEN)
00876                                         Attr( _T("smartDerivedFromGUID"), guid);
00877                         }
00878                 }
00879                 if(prim && (dumpversion >= 1) && (!lost_basetype) && m_dumpRelids)
00880                         LAttr(_T("relid"), fco, &IMgaFCO::get_RelID);
00881 
00882                 VARIANT_BOOL readonly;
00883                 COMTHROW( fco->HasReadOnlyAccess( &readonly));
00884                 if( readonly) Attr( _T("perm"), _T("1"));
00885         }
00886 
00887         if( dump_name )
00888         {
00889                 StartElem(_T("name"));
00890                 Data(fco, &IMgaFCO::get_Name);
00891                 EndElem();
00892         }
00893 
00894         if( dump_elems )
00895         {
00896                 DumpConstraints(fco);
00897 
00898                 // dumping the regnodes
00899                 CComObjPtrVector<IMgaRegNode> v;
00900                 COMTHROW( fco->get_Registry(VARIANT_FALSE, PutOut(v)) );
00901                 CComObjPtrVector<IMgaRegNode>::iterator i = v.begin();
00902                 CComObjPtrVector<IMgaRegNode>::iterator e = v.end();
00903         
00904                 Sort(&v);
00905 
00906                 while( i != e )
00907                 {
00908                         Dump(*i);
00909 
00910                         ++i;
00911                 }
00912 
00913                 Dump(fco, &IMgaFCO::get_Attributes);
00914         }
00915 }
00916 
00917 void CMgaDumper::Dump(IMgaModel *model)
00918 {
00919         ASSERT( model != NULL );
00920 
00921         StartElem(_T("model"));
00922 
00923         DumpFCO(model, true, false, false);     
00924         if(dumpversion >= 1 && m_dumpRelids) LAttr(_T("childrelidcntr"), model, &IMgaModel::get_ChildRelIDCounter);
00925         DumpFCO(model, false, true, true);      
00926 
00927         Dump(model, &IMgaModel::get_ChildFCOs);
00928 
00929         EndElem();
00930 }
00931 
00932 void CMgaDumper::DumpConstraints(IMgaObject *object)
00933 {
00934         ASSERT( object != NULL );
00935 
00936         CComObjPtrVector<IMgaConstraint> v;
00937 
00938         CComObjPtr<IMgaFCO> fco;
00939         if( SUCCEEDED(::QueryInterface(object, fco)) )
00940         {
00941                 COMTHROW( fco->get_Constraints(VARIANT_FALSE, PutOut(v)) );
00942         }
00943         else
00944         {
00945                 CComObjPtr<IMgaFolder> folder;
00946                 COMTHROW( ::QueryInterface(object, folder) );
00947                 COMTHROW( folder->get_Constraints(VARIANT_FALSE, PutOut(v)) );
00948         }
00949 
00950         CComObjPtrVector<IMgaConstraint>::iterator i = v.begin();
00951         CComObjPtrVector<IMgaConstraint>::iterator e = v.end();
00952         while( i != e )
00953         {
00954                 Dump(*i);
00955 
00956                 ++i;
00957         }
00958 }
00959 
00960 void CMgaDumper::Dump(IMgaConstraint *constraint)
00961 {
00962         ASSERT( constraint != NULL );
00963 
00964         StartElem(_T("constraint"));
00965 
00966         StartElem(_T("name"));
00967         Data(constraint, &IMgaConstraint::get_Name);
00968         EndElem();
00969 
00970         StartElem(_T("value"));
00971         Data(constraint, &IMgaConstraint::get_Expression);
00972         EndElem();
00973 
00974         EndElem();
00975 }
00976 
00977 void CMgaDumper::Dump(IMgaAttribute *attribute)
00978 {
00979         ASSERT( attribute != NULL );
00980 
00981         StartElem(_T("attribute"));
00982         
00983         CComObjPtr<IMgaMetaAttribute> metaattr;
00984         COMTHROW( attribute->get_Meta(PutOut(metaattr)) );
00985         Attr(_T("kind"), metaattr, &IMgaMetaAttribute::get_Name);
00986 
00987         long status;
00988         COMTHROW( attribute->get_Status(&status) );
00989         if( status < 0 )
00990                 Attr(_T("status"), _T("meta"));
00991         else if( status > 0 )
00992                 Attr(_T("status"), _T("inherited"));
00993 
00994         StartElem(_T("value"));
00995 
00996         attval_enum attval;
00997         COMTHROW( metaattr->get_ValueType(&attval) );
00998 
00999         std::tstring data;
01000 
01001         switch(attval)
01002         {
01003         case ATTVAL_STRING:
01004         case ATTVAL_ENUM:
01005         case ATTVAL_DYNAMIC:
01006                 {
01007                         CComBstrObj bstr;
01008                         COMTHROW( attribute->get_StringValue(PutOut(bstr)) );
01009                         CopyTo(bstr, data);
01010                         break;
01011                 }
01012 
01013         case ATTVAL_INTEGER:
01014                 {
01015                         long l;
01016                         COMTHROW( attribute->get_IntValue(&l) );
01017                         Format(data, _T("%ld"), l);
01018                         break;
01019                 }
01020 
01021         case ATTVAL_DOUBLE:
01022                 {
01023                         double d;
01024                         COMTHROW( attribute->get_FloatValue(&d) );
01025                         wchar_t dblbuf[40];
01026                         _swprintf_s_l(dblbuf, sizeof(dblbuf) / sizeof(dblbuf[0]), L"%.17g", c_locale, d);
01027                         data = dblbuf;
01028                         break;
01029                 }
01030 
01031         case ATTVAL_BOOLEAN:
01032                 {
01033                         VARIANT_BOOL b;
01034                         COMTHROW( attribute->get_BoolValue(&b) );
01035 
01036                         if( b != VARIANT_FALSE )
01037                                 data = _T("true");
01038                         else
01039                                 data = _T("false");
01040 
01041                         break;
01042                 }
01043 
01044         case ATTVAL_REFERENCE:
01045                 {
01046                         CComObjPtr<IMgaFCO> fco;
01047                         COMTHROW( attribute->get_FCOValue(PutOut(fco)) );
01048 
01049                         if( (fco != NULL) && (CheckInClosure(fco)) )
01050                         {
01051                                 CComBstrObj bstr;
01052                                 COMTHROW( fco->get_ID(PutOut(bstr)) );
01053                                 CopyTo(bstr, data);
01054                         }
01055                         break;
01056                 }
01057 
01058         default:
01059                 HR_THROW(E_INVALID_META);
01060         };
01061                 
01062         Data(data);
01063         EndElem();
01064 
01065 //      Dump(attribute, IMgaAttribute::get_Registry);
01066 
01067         EndElem();
01068 }
01069 
01070 void CMgaDumper::Dump(IMgaAtom *atom)
01071 {
01072         ASSERT( atom != NULL );
01073 
01074         StartElem(_T("atom"));
01075 
01076         DumpFCO(atom);
01077 
01078         EndElem();
01079 }
01080 
01081 void CMgaDumper::Dump(IMgaReference *reference)
01082 {
01083         ASSERT( reference != NULL );
01084 
01085         StartElem(_T("reference"));
01086 
01087         DumpFCO(reference, true, false, false);
01088 
01089         CComObjPtr<IMgaFCO> fco;
01090         COMTHROW( reference->get_Referred(PutOut(fco)) );
01091         
01092         if( fco != NULL)
01093         {
01094                 if( CheckInClosure( fco)) // regular dump or the fco is really in the closure
01095                         Attr(_T("referred"), fco, &IMgaFCO::get_ID);
01096                 
01097                 if( m_closureDump)
01098                 {
01099                         if ( m_dumpLibraryStubs && !CheckInClosure( fco) && !isInLibrary( reference) && isInLibrary( fco)) //reference pointing out to a library
01100                         {
01101                                 CComBSTR name;
01102                                 COMTHROW( fco->get_AbsPath( &name));
01103                                 std::tstring nm;
01104                                 CopyTo( name, nm);
01105                                 
01106                                 Attr(_T("closurelibreferred"), nm);
01107                         }
01108 
01109                         // dump the relativepath of the referred object if v2
01110                         else if( m_v2) // _T("else") introd freshly, not to dump to paths, the parser will check first for closurelibreferred
01111                         {
01112                                 CComBSTR name;
01113                                 COMTHROW( fco->get_AbsPath( &name));
01114                                 std::tstring nm;
01115                                 CopyTo( name, nm);
01116 
01117                                 COMTHROW( reference->get_AbsPath( &name));
01118                                 std::tstring nm2;
01119                                 CopyTo( name, nm2);
01120 
01121                                 
01122                                 Attr(_T("closure2referred"), makeRel( nm, nm2));
01123                         }
01124 
01125                         // dump guid of fco if m_v2
01126                         if( m_v2)
01127                         {
01128                                 CComBstrObj ref_guid;
01129                                 COMTHROW( fco->get_RegistryValue( CComBSTR( GLOBAL_ID_STR), PutOut( ref_guid)));
01130                                 if( ref_guid != 0 && ref_guid.Length() == GLOBAL_ID_LEN) // valid guid
01131                                         Attr( _T("smartReferredGUID"), ref_guid);
01132                         }
01133                 }
01134         }
01135 
01136 
01137         CComObjPtr<IMgaFCO> base;
01138         COMTHROW( reference->get_DerivedFrom(PutOut(base)));
01139         if(base && CheckInClosure(base)
01140                 || base && m_closureDump && m_v2) {
01141                 short stat;
01142                 COMTHROW( reference->CompareToBase(&stat));
01143                 if(!stat) {
01144                         Attr(_T("isbound"), _T("yes") );
01145                 }
01146         }
01147 
01148         DumpFCO(reference, false, true, true);
01149 
01150         EndElem();
01151 }
01152 
01153 void CMgaDumper::Dump(IMgaConnection *connection)
01154 {
01155         ASSERT( connection != NULL );
01156 
01157         StartElem(_T("connection"));
01158 
01159         bool skipdump = false;
01160 
01161         CComObjPtr<IMgaFCO> base;
01162         COMTHROW( connection->get_DerivedFrom(PutOut(base)));
01163         if(base && CheckInClosure(base)
01164                 || base && m_closureDump && m_v2) {
01165                 short stat;
01166                 COMTHROW( connection->CompareToBase(NULL, &stat));
01167                 if(!stat) {
01168                         Attr(_T("isbound"), _T("yes") );
01169                         skipdump = true;
01170                 }
01171         }
01172 
01173         if( m_closureDump && m_v2)
01174                 DumpConnDetails( CComObjPtr<IMgaConnection>( connection));
01175 
01176         DumpFCO(connection);
01177 
01178         if(!skipdump)
01179                 Dump(connection, &IMgaConnection::get_ConnPoints);
01180 
01181         EndElem();
01182 }
01183 
01184 void CMgaDumper::Dump(IMgaSet *set)
01185 {
01186         ASSERT( set != NULL );
01187 
01188         StartElem(_T("set"));
01189 
01190         DumpFCO(set, true, false, false);
01191         bool skipdump = false;
01192         CComObjPtr<IMgaFCO> base;
01193         COMTHROW( set->get_DerivedFrom(PutOut(base)));
01194         if(base && CheckInClosure(base)
01195                 || base && m_closureDump && m_v2) {
01196                 short stat;
01197                 COMTHROW( set->CompareToBase(&stat));
01198                 if(!stat) {
01199                         Attr(_T("isbound"), _T("yes") );
01200                         skipdump = true;
01201                 }
01202         }
01203 
01204 
01205         if(!skipdump) {
01206                 CComObjPtrVector<IMgaFCO> members;
01207                 COMTHROW( set->get_Members(PutOut(members)) );
01208                 Sort( &members); // we sort the set members by ID
01209                 
01210                 if( m_closureDump)
01211                 {
01212                         CComBSTR name;
01213                         COMTHROW( set->get_AbsPath( &name));
01214                         CopyTo( name, m_currAbsPath); // will be used by the DumpIDRefs
01215 
01216                         if( m_v2)
01217                         {
01218                                 std::tstring memberguids = DumpMixedGUIDRefs( members); // uses m_currAbsPath
01219                                 if( !memberguids.empty()) Attr( _T("smartMemberGUIDs"), memberguids);
01220                         }
01221                 }
01222 
01223                 DumpIDRefs(_T("members"), members); // might use m_currAbsPath
01224         }
01225 
01226         DumpFCO(set, false, true, true);
01227 
01228         EndElem();
01229 }
01230 
01231 void CMgaDumper::Dump(IMgaConnPoint *connpoint)
01232 {
01233         ASSERT( connpoint != NULL );
01234 
01235         StartElem(_T("connpoint"));
01236 
01237 #ifdef _DEBUG
01238         CComBSTR rolename;
01239         connpoint->get_ConnRole(&rolename);
01240         ASSERT(rolename.Length() != 0);
01241 #endif
01242 
01243         Attr(_T("role"), connpoint, &IMgaConnPoint::get_ConnRole);
01244         
01245         CComObjPtr<IMgaFCO> target;
01246         COMTHROW( connpoint->get_Target(PutOut(target)) );
01247 
01248         if( target == NULL )
01249                 HR_THROW(E_INVALID_MGA);
01250 
01251 
01252         CComPtr<IMgaConnection> conn;
01253         COMTHROW( connpoint->get_Owner(&conn));
01254 
01255         CComObjPtr<IMgaFCO> base;
01256         COMTHROW( conn->get_DerivedFrom(PutOut(base)));
01257         if(base && CheckInClosure(base)
01258                 || base && m_closureDump && m_v2) {
01259                 short stat;
01260                 COMTHROW( conn->CompareToBase(connpoint, &stat));
01261                 if(!stat) {
01262                         Attr(_T("isbound"), _T("yes") );
01263                 }
01264         }
01265 
01266         Attr(_T("target"), target, &IMgaFCO::get_ID);
01267 
01268         if( m_closureDump)
01269         {
01270                 CComBSTR name;
01271                 COMTHROW( conn->get_AbsPath( &name));
01272                 CopyTo( name, m_currAbsPath); // used by DumpIDRefs
01273 
01274                 // m_dumpLibraryStubs is true, so the connection to a library element will be dumped with "closurelibtarget" attribute and a dummy! "target" attribute
01275                 if ( m_dumpLibraryStubs && !isInLibrary( conn) && isInLibrary( target))
01276                 {
01277                         CComBSTR name;
01278                         COMTHROW( target->get_AbsPath( &name));
01279                         std::tstring nm;
01280                         CopyTo( name, nm);
01281                         
01282                         Attr(_T("closurelibtarget"), nm);
01283                 }
01284                 else if( m_v2) // closure v2
01285                 {
01286                         CComBSTR name;
01287                         COMTHROW( target->get_AbsPath( &name));
01288                         std::tstring nm;
01289                         CopyTo( name, nm);
01290 
01291                         Attr(_T("closure2target"), makeRel( nm, m_currAbsPath));
01292                 } 
01293         }
01294 
01295 
01296         CComObjPtrVector<IMgaFCO> refs;
01297         COMTHROW( connpoint->get_References(PutOut(refs)) );
01298         // m_currAbsPath is set above, at the "closure2target" dump
01299         DumpIDRefs(_T("refs"), refs);
01300 
01301         EndElem();
01302 }
01303 
01304 void CMgaDumper::DumpIDRefs(const TCHAR *name, CComObjPtrVector<IMgaFCO> &fcos)
01305 {
01306         if( !fcos.empty() )
01307         {
01308                 std::tstring idrefs, clos_idrefs;
01309 
01310                 CComObjPtrVector<IMgaFCO>::iterator i = fcos.begin();
01311                 CComObjPtrVector<IMgaFCO>::iterator e = fcos.end();
01312                 while( i != e )
01313                 {
01314                         if( m_closureDump)
01315                         {
01316                                 CComBSTR name;
01317                                 COMTHROW( (*i)->get_AbsPath( &name));
01318                                 std::tstring nm;
01319                                 CopyTo( name, nm);
01320 
01321                                 if( !clos_idrefs.empty() )
01322                                         clos_idrefs += ' ';
01323 
01324                                 clos_idrefs += makeRel( nm, m_currAbsPath);
01325                         }
01326 
01327                         if (!CheckInClosure(*i)) {
01328                                 ++i; // inserted by ZolMol
01329                                 continue;
01330                         }
01331                         CComBstrObj bstr;
01332                         COMTHROW( (*i)->get_ID(PutOut(bstr)) );
01333 
01334                         std::tstring id;
01335                         CopyTo(bstr, id);
01336 
01337                         if( !idrefs.empty() )
01338                                 idrefs += ' ';
01339 
01340                         idrefs += id;
01341 
01342                         ++i;
01343                 }
01344 
01345                 if ( !idrefs.empty())
01346                         Attr(name, idrefs);
01347 
01348                 if( m_closureDump && m_v2 && !clos_idrefs.empty()) // closure v2
01349                 {
01350                         std::tstring clos_name(_T("closure2")); clos_name += name;
01351                         Attr( clos_name.c_str(), clos_idrefs);
01352                 }
01353         }
01354 }
01355 std::tstring CMgaDumper::DumpGUIDRefs( CComObjPtrVector<IMgaFCO>& fcos)
01356 {
01357         std::tstring guidrefs;
01358 
01359         for( CComObjPtrVector<IMgaFCO>::iterator i = fcos.begin(); i != fcos.end(); ++i)
01360         {
01361                 CComBSTR bstr;
01362                 COMTHROW( (*i)->get_RegistryValue( CComBSTR( GLOBAL_ID_STR), &bstr));
01363 
01364                 if( bstr != 0 && bstr.Length() == GLOBAL_ID_LEN)
01365                 {
01366                         std::tstring guid;
01367                         CopyTo(bstr, guid);
01368 
01369                         if( !guidrefs.empty() )
01370                                 guidrefs += ' ';
01371 
01372                         guidrefs += guid;
01373                 }
01374                 else
01375                         return _T(""); // if one guid not found, then all are disregarded
01376         }
01377 
01378         return guidrefs;
01379 }
01380 
01381 std::tstring CMgaDumper::DumpMixedGUIDRefs( CComObjPtrVector<IMgaFCO>& fcos)
01382 {
01383         // this method produces a sequence of the {guid}=path forms
01384         //{E200BEEB-34BC-4271-A134-AA5728C38124}\\/@../@module_ref1|kind=module_ref|relpos=0
01385         std::tstring guidrefs;
01386 
01387         for( CComObjPtrVector<IMgaFCO>::iterator i = fcos.begin(); i != fcos.end(); ++i)
01388         {
01389 
01390                 CComBSTR name;
01391                 COMTHROW( (*i)->get_AbsPath( &name));
01392                 std::tstring nm;
01393                 CopyTo( name, nm);
01394 
01395                 if( !guidrefs.empty() )
01396                         guidrefs += ' ';
01397 
01398                 CComBSTR bstr;
01399                 COMTHROW( (*i)->get_RegistryValue( CComBSTR( GLOBAL_ID_STR), &bstr));
01400 
01401                 if( bstr != 0 && bstr.Length() == GLOBAL_ID_LEN)
01402                 {
01403                         std::tstring guid;
01404                         CopyTo(bstr, guid);
01405 
01406 
01407                         guidrefs += guid;
01408                         guidrefs += '\\';
01409                 }
01410                 //else
01411                 //      return ""; // if one guid not found, then all are disregarded
01412                 
01413                 guidrefs += makeRel( nm, m_currAbsPath);
01414         }
01415 
01416         return guidrefs;
01417 }
01418 
01419 //sort the RegNode Vector in place by Name
01420 void CMgaDumper::Sort(CComObjPtrVector<IMgaRegNode> *v)
01421 {
01422         int n = v->size();
01423 
01424         //small speed up, build a vector of strings first, then sort the strings
01425         //while doing the sort operations on the original vector, so we don't have
01426         //to call the get_Name function each time we look at a RegNode
01427         std::vector<std::tstring> vPrime;
01428         for (int i=0; i<n; i++)
01429         {
01430                 CComBSTR bstr;
01431                 COMTHROW((*v)[i]->get_Name(&bstr));
01432                 std::tstring s;
01433                 CopyTo(bstr,s);
01434                 vPrime.push_back(s);
01435         }
01436         
01437         //in place insertion sort
01438         for (int x=1; x<n; x++) 
01439         {
01440                 std::tstring index = vPrime[x];
01441                 CComObjPtr<IMgaRegNode> indexRegNode = (*v)[x];
01442                 int y = x;
01443 
01444                 while ((y>0)&&(vPrime[y-1].compare(index)>0))
01445                 {
01446                                 vPrime[y]=vPrime[y-1];
01447 
01448                                 (*v)[y]=(*v)[y-1];
01449 
01450                                 --y;
01451                 }
01452 
01453                 vPrime[y] = index;
01454                 (*v)[y] = indexRegNode;
01455         }               
01456 
01457 }
01458 
01459 //Sort the Attribute Vector by Kind
01460 void CMgaDumper::Sort(CComObjPtrVector<IMgaAttribute> *v)
01461 {
01462         int n = v->size();
01463 
01464         //small speed up, build a vector of strings first, then sort the strings
01465         //while doing the sort operations on the original vector, so we don't have
01466         //to get the Kind Name every time
01467         std::vector<std::tstring> vPrime;
01468         for (int i=0; i<n; i++)
01469         {
01470                 CComBSTR bstr;
01471                 CComPtr<IMgaMetaAttribute> meta;
01472                 COMTHROW((*v)[i]->get_Meta(&meta));
01473                 COMTHROW(meta->get_Name(&bstr));
01474                 std::tstring s;
01475                 CopyTo(bstr,s);
01476                 vPrime.push_back(s);
01477         }
01478         
01479         //in place insertion sort
01480         for (int x=1; x<n; x++) 
01481         {
01482                 std::tstring index = vPrime[x];
01483                 CComObjPtr<IMgaAttribute> indexAttr = (*v)[x];
01484                 int y = x;
01485 
01486                 while ((y>0)&&(vPrime[y-1].compare(index)>0))
01487                 {
01488                                 vPrime[y]=vPrime[y-1];
01489 
01490                                 (*v)[y]=(*v)[y-1];
01491 
01492                                 --y;
01493                 }
01494 
01495                 vPrime[y] = index;
01496                 (*v)[y] = indexAttr;
01497         }       
01498 }
01499 
01500 //Sort the Connection Point Vector by Target ID
01501 void CMgaDumper::Sort(CComObjPtrVector<IMgaConnPoint> *v)
01502 {
01503         int n = v->size();
01504 
01505         //small speed up, build a vector of strings first, then sort the strings
01506         //while doing the sort operations on the original vector, so we don't have
01507         //to get the Target ID every time
01508         std::vector<std::tstring> vPrime;
01509         for (int i=0; i<n; i++)
01510         {
01511                 CComBSTR bstr;
01512                 CComPtr<IMgaFCO> fco;
01513                 COMTHROW((*v)[i]->get_Target(&fco));
01514                 COMTHROW(fco->get_ID(&bstr));
01515                 std::tstring s;
01516                 CopyTo(bstr,s);
01517                 // Tie-break sort on role, for self-connections
01518                 CComBSTR role;
01519                 COMTHROW((*v)[i]->get_ConnRole(&role));
01520                 s += role;
01521                 vPrime.push_back(s);
01522         }
01523         
01524         //in place insertion sort
01525         for (int x=1; x<n; x++) 
01526         {
01527                 std::tstring index = vPrime[x];
01528                 CComObjPtr<IMgaConnPoint> indexConnPoint = (*v)[x];
01529                 int y = x;
01530 
01531                 while ((y>0)&&(vPrime[y-1].compare(index)>0))
01532                 {
01533                                 vPrime[y]=vPrime[y-1];
01534 
01535                                 (*v)[y]=(*v)[y-1];
01536 
01537                                 --y;
01538                 }
01539 
01540                 vPrime[y] = index;
01541                 (*v)[y] = indexConnPoint;
01542         }       
01543 }
01544 
01545 //sort the Folder Vector by ID
01546 void CMgaDumper::Sort(CComObjPtrVector<IMgaFolder> *v)
01547 {
01548         int n = v->size();
01549         
01550         //small speed up, build a vector of strings first, then sort the strings
01551         //while doing the sort operations on the original vector, so we don't have
01552         //to call the get_ID function each time we look at a Folder
01553         std::vector<std::tstring> vPrime;
01554         for (int i=0; i<n; i++)
01555         {
01556                 CComBSTR bstr;
01557                 COMTHROW((*v)[i]->get_ID(&bstr));
01558                 std::tstring s;
01559                 CopyTo(bstr,s);
01560                 vPrime.push_back(s);
01561         }       
01562         
01563         //in place insertion sort
01564         for (int x=1; x<n; x++) 
01565         {
01566                 std::tstring index = vPrime[x];
01567                 CComObjPtr<IMgaFolder> indexFolder = (*v)[x];
01568                 int y = x;
01569 
01570                 while ((y>0)&&(vPrime[y-1].compare(index)>0))
01571                 {
01572                                 vPrime[y]=vPrime[y-1];
01573 
01574                                 (*v)[y]=(*v)[y-1];
01575 
01576                                 --y;
01577                 }
01578 
01579                 vPrime[y] = index;
01580                 (*v)[y] = indexFolder;
01581         }       
01582         
01583 }
01584 
01585 //Sort the FCO vector in place by ID
01586 void CMgaDumper::Sort(CComObjPtrVector<IMgaFCO> *v)
01587 {
01588         int n = v->size();
01589         
01590         //small speed up, build a vector of strings first, then sort the strings
01591         //while doing the sort operations on the original vector, so we don't have
01592         //to call the get_ID function each time we look at an FCO
01593         std::vector<std::tstring> vPrime;
01594         for (int i=0; i<n; i++)
01595         {
01596                 CComBSTR bstr;
01597                 COMTHROW((*v)[i]->get_ID(&bstr));
01598                 std::tstring s;
01599                 CopyTo(bstr,s);
01600                 vPrime.push_back(s);
01601         }
01602 
01603         //in place insertion sort
01604         for (int x=1; x<n; x++) 
01605         {
01606                 std::tstring index = vPrime[x];
01607                 CComObjPtr<IMgaFCO> indexFCO = (*v)[x];
01608                 int y = x;
01609 
01610                 while ((y>0)&&(vPrime[y-1].compare(index)>0))
01611                 {
01612                                 vPrime[y]=vPrime[y-1];
01613 
01614                                 (*v)[y]=(*v)[y-1];
01615 
01616                                 --y;
01617                 }
01618 
01619                 vPrime[y] = index;
01620                 (*v)[y] = indexFCO;
01621         }       
01622 
01623 }
01624 
01625 void CMgaDumper::putInTerritory( CComObjPtrVector<IMgaFCO>& fco_vec)
01626 {               
01627         CComObjPtrVector<IMgaFCO>::iterator i = fco_vec.begin();
01628         for( ; i != fco_vec.end(); ++i )
01629         {
01630                 CComObjPtr<IMgaObject> obj;
01631                 COMTHROW(territory->OpenObj(*i, PutOut(obj)));
01632                 CComObjPtr<IMgaFCO> fco;
01633                 COMTHROW(obj.QueryInterface(fco));
01634                 *i = fco;
01635         }
01636 }
01637 
01638 void CMgaDumper::putInTerritory( CComObjPtrVector<IMgaFolder>& fold_vec)
01639 {
01640         CComObjPtrVector<IMgaFolder>::iterator j = fold_vec.begin();
01641         for( ; j != fold_vec.end(); ++j )
01642         {
01643                 CComObjPtr<IMgaObject> obj;
01644                 COMTHROW(territory->OpenObj(*j, PutOut(obj)));
01645                 CComObjPtr<IMgaFolder> fold;
01646                 COMTHROW(obj.QueryInterface(fold));
01647                 *j = fold;
01648         }
01649 }
01650 
01651 //
01652 // method called from the DumpFCO
01653 // it is zombie-aware since it may happen that an object is placed to the clipboard
01654 // then deleted, then the clipboard may be dumped when the project is closed
01655 void CMgaDumper::removeInnerObjs()
01656 {
01657         bool zombies_found = false;
01658         // try to remove those objects which are part of (child, grandchild) of another selected object
01659         CComObjPtrVector<IMgaFCO>::iterator i = m_selFcos.begin();
01660         while( i != m_selFcos.end())
01661         {
01662                 bool zombie = false;
01663                 long status;
01664                 COMTHROW( (*i)->get_Status(&status));
01665                 if (status != OBJECT_EXISTS) 
01666                 {
01667                         zombies_found = zombie = true;
01668                 }
01669 
01670                 bool found_parent = false;
01671                 if( !zombie)
01672                 {
01673                         CComObjPtr<IMgaFCO> last_fco = *i, curr_fco = *i;
01674                         do
01675                         {
01676                                 CComObjPtr<IMgaModel> parent;
01677                                 COMTHROW( curr_fco->get_ParentModel(PutOut(parent)));
01678                                 last_fco = curr_fco;
01679                                 curr_fco = NULL;
01680                                 if (parent != NULL) {
01681                                         COMTHROW( ::QueryInterface(parent, curr_fco) );
01682                                         found_parent = std::find_if( m_selFcos.begin(), m_selFcos.end(), GmeEqual( curr_fco)) != m_selFcos.end();
01683                                 }
01684                         } while ( curr_fco != NULL && !found_parent);
01685 
01686                         if ( !found_parent) // no parent found in the set of fcos
01687                         {
01688                                 CComObjPtr<IMgaFolder> par_folder;
01689                                 COMTHROW( last_fco->get_ParentFolder(PutOut( par_folder)));
01690 
01691                                 while ( par_folder != NULL && !found_parent)
01692                                 {
01693                                         found_parent = std::find_if( m_selFolders.begin(), m_selFolders.end(), GmeEqual( par_folder)) != m_selFolders.end();
01694 
01695                                         CComObjPtr<IMgaFolder> parent;
01696                                         COMTHROW( par_folder->get_ParentFolder(PutOut( parent)));
01697 
01698                                         par_folder = parent;
01699                                 }
01700                         }
01701                 }
01702 
01703                 if ( found_parent || zombie)
01704                         i = m_selFcos.erase( i);
01705                 else
01706                         ++i;
01707         }       
01708 
01709 
01710         // try to remove those folders which are part of (child, grandchild) of another selected folder
01711         CComObjPtrVector<IMgaFolder>::iterator k = m_selFolders.begin();
01712         while( k != m_selFolders.end())
01713         {
01714                 bool zombie = false;
01715                 long status;
01716                 COMTHROW( (*k)->get_Status(&status));
01717                 if (status != OBJECT_EXISTS)
01718                 {
01719                         zombies_found = zombie = true;
01720                 }
01721 
01722                 bool found_parent = false;
01723                 if( !zombie)
01724                 {
01725                         CComObjPtr<IMgaFolder> par_folder;
01726                         COMTHROW( (*k)->get_ParentFolder(PutOut( par_folder)));
01727                         
01728                         while ( par_folder != NULL && !found_parent)
01729                         {
01730                                 found_parent = std::find_if( m_selFolders.begin(), m_selFolders.end(), GmeEqual( par_folder)) != m_selFolders.end();
01731 
01732                                 CComObjPtr<IMgaFolder> parent;
01733                                 COMTHROW(par_folder->get_ParentFolder(PutOut( parent)));
01734                                 par_folder = parent;
01735                         }
01736                 }
01737                 
01738                 if ( found_parent || zombie)
01739                         k = m_selFolders.erase( k);
01740                 else
01741                         ++k;
01742         }
01743 
01744         ASSERT( zombies_found || m_selFolders.size() + m_selFcos.size() > 0);
01745 }
01746 
01747 STDMETHODIMP CMgaDumper::DumpClos( IMgaFCOs *p_sel_fcos, IMgaFolders *p_sel_folds,  BSTR xmlfile, int dump_options)
01748 {
01749         m_closureDump = true;
01750         m_strictDump = true; // strict dump meaning that all dumped objects must be strictly in the closure
01751         
01752         m_dumpRelids = false; // dumpversion = 2; // no relids dumped
01753         m_dumpGuids  = true;  // dump these, as they are needed by new features
01754 
01755         m_dumpLibraryStubs =    (dump_options & 0x1) == 0x1; // dump library stubs ( absolute path used as libreferred or libderivedfrom attribute)
01756         m_v2 =                                  (dump_options & 0x2) == 0x2;
01757         
01758         COMTRY
01759         {
01760                 if ( p_sel_fcos )
01761                         CopyTo( p_sel_fcos, m_selFcos);
01762 
01763                 if ( p_sel_folds) 
01764                         CopyTo( p_sel_folds, m_selFolders);
01765 
01766                 CComObjPtr<IMgaProject> project;
01767 
01768                 if ( !m_selFcos.empty())
01769                         COMTHROW( m_selFcos.front()->get_Project( PutOut( project)) );
01770                 else if ( !m_selFolders.empty())
01771                         COMTHROW( m_selFolders.front()->get_Project( PutOut( project)) );
01772                 else
01773                         return S_OK;
01774 
01775 
01776                 InitDump( project, xmlfile, _bstr_t(L"UTF-16"));
01777 
01778                 putInTerritory( m_selFcos);
01779                 putInTerritory( m_selFolders);
01780                 
01781                 if ( false) // clipboard format
01782                 {
01783                         ofs << L"<!DOCTYPE clipboard SYSTEM \"mgaclosure.dtd\" [\n";
01784                         ofs << L"\t<!ELEMENT clipboard (folder|model|atom|reference|set|connection|regnode)*>\n";
01785                         ofs << L"\t<!ATTLIST clipboard\n";
01786                         ofs << L"\t\tclosureversion CDATA #IMPLIED\n";
01787                         ofs << L"\t\tacceptingkind CDATA #IMPLIED\n";
01788                         ofs << L"\t\tparadigmnamehint CDATA #IMPLIED\n"; // just for compatibility with raw copied data
01789                         ofs << L"\t>\n";
01790                         ofs << L"]>\n\n";
01791 
01792                         StartElem(_T("clipboard"));
01793                         Attr(_T("closureversion"), _T("1"));
01794                         Dump( project); 
01795                         EndElem();
01796                 }
01797                 else
01798                 {
01799                         ofs << L"<!DOCTYPE project SYSTEM \"mgaclosure.dtd\">\n\n";
01800 
01801                         Dump( project); 
01802                 }
01803                 DoneDump(false);
01804         }
01805         COMCATCH( DoneDump(true); )
01806 
01807         m_selFcos.clear();
01808         m_selFolders.clear();
01809 }
01810 
01811 STDMETHODIMP CMgaDumper::DumpClosR(
01812                         IMgaFCOs *p_sel_fcos, IMgaFolders *p_sel_folds, BSTR xmlfile, 
01813                         IMgaFCOs *p_top_fcos, IMgaFolders *p_top_folds, int dump_options, BSTR abspath, BSTR acceptingkinds)
01814 {
01815         m_closureDump = true;
01816         m_strictDump = true; // strict dump meaning that all dumped objects must be strictly in the closure
01817         m_dumpRelids = false; //dumpversion = 2; // no relids dumped
01818         m_dumpGuids  = true; // dump these, as they are needed by new features
01819 
01820         m_dumpLibraryStubs      = (dump_options & 0x1) == 0x1; // dump library stubs ( absolute path used as closurelibreferred, closurelibderivedfrom, closurelibtarget attribute)
01821         m_v2                            = (dump_options & 0x2) == 0x2; // dump the closure2members, closure2refs like attributes
01822 
01823         std::tstring version_string;
01824         if( dump_options & 0x4)
01825                 version_string = _T("4");
01826         else
01827                 version_string = _T("1");
01828         
01829         //CopyTo( abspath, m_currParAbsPath);
01830 
01831         COMTRY
01832         {
01833                 if ( p_sel_fcos )
01834                         CopyTo( p_sel_fcos, m_selFcos);
01835 
01836                 if ( p_sel_folds) 
01837                         CopyTo( p_sel_folds, m_selFolders);
01838 
01839                 CComObjPtr<IMgaProject> project;
01840 
01841                 if ( !m_selFcos.empty())
01842                         COMTHROW( m_selFcos.front()->get_Project( PutOut( project)) );
01843                 else if ( !m_selFolders.empty())
01844                         COMTHROW( m_selFolders.front()->get_Project( PutOut( project)) );
01845                 else
01846                         return S_OK;
01847 
01848                 CComObjPtrVector<IMgaFCO>       parentless_fcos; // parentless fcos from the selected set
01849                 CComObjPtrVector<IMgaFolder> parentless_folders; // parentless folders from the selected set
01850 
01851                 if ( p_top_fcos )
01852                         CopyTo( p_top_fcos, parentless_fcos);
01853 
01854                 if ( p_top_folds) 
01855                         CopyTo( p_top_folds, parentless_folders);
01856 
01857                 if ( parentless_fcos.empty() && parentless_folders.empty())
01858                 {
01859                         // this case should be handled by the DumpClos()
01860                         ASSERT( 0);
01861                         return DumpClos( p_sel_fcos, p_sel_folds, xmlfile, dump_options);
01862                 }
01863 
01864                 InitDump( project, xmlfile, _bstr_t(L"UTF-16"));
01865 
01866                 putInTerritory( m_selFcos);
01867                 putInTerritory( parentless_fcos);
01868                 putInTerritory( m_selFolders);
01869                 putInTerritory( parentless_folders);
01870 
01871                 ofs << L"<!DOCTYPE clipboard SYSTEM \"mgaclosure.dtd\" [\n";
01872                 ofs << L"\t<!ELEMENT clipboard (folder|model|atom|reference|set|connection|regnode)*>\n";
01873                 ofs << L"\t<!ATTLIST clipboard\n";
01874                 ofs << L"\t\tclosureversion CDATA #IMPLIED\n";
01875                 ofs << L"\t\tacceptingkind CDATA #IMPLIED\n";
01876                 ofs << L"\t\tparadigmnamehint CDATA #IMPLIED\n"; // just for compatibility with raw copied data
01877                 ofs << L"\t>\n";
01878                 ofs << L"]>\n\n";
01879 
01880                 StartElem(_T("clipboard"));
01881                 Attr(_T("closureversion"), version_string);
01882                 Attr(_T("acceptingkind"), CComBstrObj( acceptingkinds));
01883 
01884                 for( CComObjPtrVector<IMgaFolder>::iterator j = parentless_folders.begin(); j != parentless_folders.end(); ++j )
01885                 {
01886                         CComBSTR path;
01887 
01888                         CComObjPtr<IMgaFolder> parent;
01889                         COMTHROW( (*j)->get_ParentFolder( PutOut( parent)));
01890                         if ( parent) // it has a folder parent
01891                                 COMTHROW( parent->get_AbsPath( &path));
01892                         // else: a parentless_folder is the rootfolder, so the path = "";
01893                         
01894                         //CopyTo( path, m_curTopPath);// m_curTopPath will be used to dump the relative path in "closurename" attr
01895 
01896                         Dump( *j);
01897                 }
01898 
01899                 for( CComObjPtrVector<IMgaFCO>::iterator i = parentless_fcos.begin() ; i != parentless_fcos.end(); ++i )
01900                 {
01901                         CComBSTR path;
01902 
01903                         CComObjPtr<IMgaModel> parent;
01904                         COMTHROW( (*i)->get_ParentModel( PutOut( parent)));
01905                         if ( parent) // it has a model parent
01906                                 COMTHROW( parent->get_AbsPath( &path));
01907                         else // it may be contained by a folder
01908                         {
01909                                 CComObjPtr<IMgaFolder> parent;
01910                                 COMTHROW( (*i)->get_ParentFolder( PutOut( parent)));
01911                                 if ( parent) // it has a folder parent
01912                                         COMTHROW( parent->get_AbsPath( &path));
01913                                 else // what the heck! (a parentless fco cannot be the rootfolder)
01914                                         ASSERT(0);
01915                         }
01916 
01917 
01918                         //CopyTo( path, m_curTopPath);// m_curTopPath will be used to dump the relative path in "closurename" attr
01919 
01920                         Dump( *i); 
01921                 }
01922                 
01923                 EndElem();
01924 
01925                 DoneDump(false);
01926         }
01927         COMCATCH( DoneDump(true); )
01928 
01929         m_selFcos.clear();
01930         m_selFolders.clear();
01931 }
01932 
01933 void CMgaDumper::DumpConnDetails( CComObjPtr<IMgaConnection> connection)
01934 {
01935         const TCHAR * role_attr []       = { _T("smart0Role=")         , _T("smart1Role=")         };
01936         const TCHAR * targetGUID_attr [] = { _T("smart0TargetGUID=")   , _T("smart1TargetGUID=")   };
01937         const TCHAR * target_attr []     = { _T("smart0Target=")       , _T("smart1Target=")       };
01938         const TCHAR * refchainGUID_attr[]= { _T("smart0RefChainGUID=") , _T("smart1RefChainGUID=") };
01939         const TCHAR * refchain_attr []   = { _T("smart0RefChain=")     , _T("smart1RefChain=")     };
01940         const TCHAR * isbound_attr []    = { _T("smart0IsBound=")      , _T("smart1IsBound=")      };
01941 
01942         std::tstring array[2]; // { source_info, destin_info };
01943         CComObjPtrVector<IMgaConnPoint> cps;
01944         COMTHROW( connection->get_ConnPoints( PutOut( cps)));
01945 
01946         if( 2 == cps.size())
01947         {
01948                 for( unsigned int i = 0; i < cps.size(); ++i)
01949                 {
01950                         CComBSTR role_bstr;std::tstring role_str;
01951                         COMTHROW( cps[i]->get_ConnRole( &role_bstr));
01952                         int w = 0; // which?
01953                         if( role_bstr == CComBSTR(L"dst")) w = 1; // otherwise will fill arr[0]
01954                         CopyTo( role_bstr, role_str);
01955                         
01956                         array[w] += std::tstring( role_attr[w]) + _T("\"") + role_str + _T("\" ");
01957 
01958                         CComObjPtr<IMgaFCO> target;
01959                         COMTHROW( cps[i]->get_Target(PutOut(target)) );
01960 
01961                         if( target == NULL )
01962                                 HR_THROW(E_INVALID_MGA);
01963 
01964                         CComBSTR guid;
01965                         COMTHROW( target->get_RegistryValue( CComBSTR(GLOBAL_ID_STR), &guid));
01966                         if( guid != 0 && guid.Length() == GLOBAL_ID_LEN) // valid
01967                         {
01968                                 std::tstring guid_str; CopyTo( guid, guid_str);
01969                                 array[w] += std::tstring( targetGUID_attr[w]) + _T("\"") + guid_str + _T("\" ");
01970                         }
01971 
01972                         CComBSTR nameBstr;
01973                         COMTHROW( connection->get_AbsPath( &nameBstr));
01974                         CopyTo( nameBstr, m_currAbsPath); // will be used by the DumpConnPoint also
01975                                 
01976                         nameBstr.Empty(); 
01977                         std::tstring t_name;
01978                         COMTHROW( target->get_AbsPath( &nameBstr));
01979                         CopyTo( nameBstr, t_name);
01980 
01981                         //Attr("closure2target", makeRel( t_name, m_currAbsPath));
01982                         std::tstring relpath_to_end = makeRel( t_name, m_currAbsPath);
01983                         ASSERT( relpath_to_end.substr(0, 4) == _T("/@.."));
01984                         // the path to connection end is calculated relative to the connection
01985                         // so if we cut off the first node, then it will be relative to the container
01986                         array[w] += std::tstring( target_attr[w]) + _T("\"") + relpath_to_end.substr(4) + _T("\" ");
01987 
01988                         CComObjPtrVector<IMgaFCO> refs;
01989                         COMTHROW( cps[i]->get_References(PutOut(refs)) );
01990 
01991                         std::tstring guidrefs = DumpGUIDRefs( refs);
01992                         if( !guidrefs.empty()) array[w] += std::tstring( refchainGUID_attr[w]) + _T("\"") + guidrefs + _T("\" ");
01993 
01994                         std::tstring chain;
01995                         for( CComObjPtrVector<IMgaFCO>::iterator j = refs.begin(); j != refs.end(); ++j)
01996                         {
01997                                 CComBSTR name;
01998                                 COMTHROW( (*j)->get_AbsPath( &name));
01999                                 std::tstring nm;
02000                                 CopyTo( name, nm);
02001 
02002                                 if( !chain.empty() )
02003                                         chain += ' ';
02004 
02005                                 std::tstring rel_path_to = makeRel( nm, m_currAbsPath);
02006                                 ASSERT( rel_path_to.substr( 0, 4) == _T("/@.."));
02007                                 // rel path converted from relative to the m_currAbsPath to relative to the container
02008                                 chain += rel_path_to.substr(4);
02009                         }
02010 
02011                         array[w] += std::tstring( refchain_attr[w]) + _T("\"") + chain + _T("\" ");
02012                         
02013                         CComObjPtr<IMgaFCO> base;
02014                         COMTHROW( connection->get_DerivedFrom(PutOut(base)));
02015                         if(base) {
02016                                 short stat;
02017                                 COMTHROW( connection->CompareToBase( cps[i], &stat));
02018                                 if(!stat) {
02019                                         //Attr("isbound", "yes" );
02020                                         array[w] += std::tstring( isbound_attr[w]) + _T("\"yes\" ");
02021                                 }
02022                         }
02023                 }
02024 
02025                 if( !array[0].empty()) ofs << " " << array[0] << " "; //the attr names are already in the string
02026                 if( !array[1].empty()) ofs << " " << array[1] << " ";
02027         }
02028 }