GME  13
MgaMetaProject.cpp
Go to the documentation of this file.
00001 
00002 #include "stdafx.h"
00003 #include "MgaMetaProject.h"
00004 #include "MgaMetaFolder.h"
00005 #include <time.h>
00006 #include <functional>
00007 
00008 // ------- CurrentTime
00009 
00010 CComVariant CurrentTime(void) 
00011 {
00012         time_t t;
00013         time(&t);
00014         char *p = ctime(&t);
00015         ASSERT( p != NULL );
00016 
00017         p[strlen(p)-1] = 0;
00018         return p;
00019 }
00020 
00021 // --------------------------- CMgaMetaProject
00022 
00023 CMgaMetaProject::CMgaMetaProject()
00024 {
00025         max_metaref = 1000;
00026 }
00027 
00028 CMgaMetaProject::~CMgaMetaProject()
00029 {
00030         if( coreproject != NULL )
00031         {
00032                 ASSERT( coreterritory != NULL );
00033 
00034                 // If this assertion fails then we have killed the CMgaMetaProject
00035                 // while working in the Close method. Probably the reference
00036                 // count on this object is wrong.
00037 
00038                 ASSERT( rootobject != NULL );
00039                 ASSERT( !metaobj_lookup.empty() );
00040 
00041                 Close();
00042         }
00043 
00044         ASSERT( coreproject == NULL );
00045         ASSERT( coreterritory == NULL );
00046         ASSERT( rootobject == NULL );
00047         ASSERT( metaobj_lookup.empty() );
00048 }
00049         
00050 // ------- Methods
00051 
00052 STDMETHODIMP CMgaMetaProject::Open(BSTR connection)
00053 {
00054         COMTRY
00055         {
00056                 if( coreproject != NULL )
00057                         __Close();
00058 
00059                 CComPtr<ICoreMetaProject> coremetaproject;
00060                 CreateCoreMetaProject(coremetaproject);
00061 
00062                 COMTHROW( coreproject.CoCreateInstance(OLESTR("MGA.CoreProject")) );
00063                 ASSERT( coreproject != NULL );
00064 
00065                 coreproject->__OpenProject(connection, coremetaproject, NULL);
00066 
00067                 coreproject->__CreateTerritory(PutOut(coreterritory));
00068                 ASSERT( coreterritory != NULL );
00069 
00070                 coreproject->__BeginTransaction(TRANSTYPE_READFIRST);
00071                 coreproject->__PushTerritory(coreterritory);
00072 
00073                 rootobject.p = coreproject->RootObject;
00074 
00075                 CMgaMetaFolder::Traverse(this, rootobject);
00076 
00077                 coreproject->__CommitTransaction(TRANSTYPE_READFIRST);
00078         }
00079         COMCATCH(
00080                 metaobj_lookup.clear();
00081                 rootobject = NULL;
00082                 coreterritory = NULL;
00083                 coreproject = NULL;
00084         )
00085 }
00086 
00087 STDMETHODIMP CMgaMetaProject::Create(BSTR connection)
00088 {
00089         COMTRY
00090         {
00091                 if( coreproject != NULL )
00092                         COMTHROW( Close() );
00093 
00094                 CComPtr<ICoreMetaProject> coremetaproject;
00095                 CreateCoreMetaProject(coremetaproject);
00096 
00097                 COMTHROW( coreproject.CoCreateInstance(OLESTR("MGA.CoreProject")) );
00098                 ASSERT( coreproject != NULL );
00099 
00100                 coreproject->__CreateProject(connection, coremetaproject);
00101 
00102                 coreproject->__CreateTerritory(PutOut(coreterritory));
00103                 ASSERT( coreterritory != NULL );
00104 
00105                 COMTHROW( coreproject->BeginTransaction(TRANSTYPE_FIRST) );
00106                 COMTHROW( coreproject->PushTerritory(coreterritory) );
00107 
00108                 COMTHROW( coreproject->get_RootObject(PutOut(rootobject)) );
00109                 COMTHROW( rootobject->put_AttributeValue(ATTRID_CDATE, CurrentTime()) );
00110                 COMTHROW( rootobject->put_AttributeValue(ATTRID_MDATE, CurrentTime()) );
00111                 COMTHROW( rootobject->put_AttributeValue(ATTRID_NAME, CComVariant()) );
00112                 COMTHROW( rootobject->put_AttributeValue(ATTRID_METAREF, PutInVariant(max_metaref)) );
00113 
00114                 COMTHROW( coreterritory->Clear() );
00115 
00116                 CMgaMetaFolder::Traverse(this, rootobject);
00117 
00118                 COMTHROW( coreproject->CommitTransaction(TRANSTYPE_FIRST) );
00119         }
00120         COMCATCH(
00121                 metaobj_lookup.clear();
00122                 rootobject = NULL;
00123                 coreterritory = NULL;
00124                 coreproject = NULL;
00125         )
00126 }
00127 
00128 STDMETHODIMP CMgaMetaProject::BeginTransaction()
00129 {
00130         COMTRY
00131         {
00132                 _ThrowExceptionIfNotOpen();
00133 
00134                 coreproject->__BeginTransaction(TRANSTYPE_FIRST);
00135 
00136                 ASSERT( coreterritory != NULL );
00137                 coreproject->__PushTerritory(coreterritory);
00138         }
00139         COMCATCH(;)
00140 }
00141 
00142 STDMETHODIMP CMgaMetaProject::CommitTransaction()
00143 {
00144         COMTRY
00145         {
00146                 _ThrowExceptionIfNotOpen();
00147 
00148                 rootobject->AttributeValue[ATTRID_MDATE] = CurrentTime();
00149                 coreproject->__CommitTransaction(TRANSTYPE_FIRST);
00150         }
00151         COMCATCH(;)
00152 }
00153 
00154 STDMETHODIMP CMgaMetaProject::AbortTransaction()
00155 {
00156 
00157         COMTRY
00158         {
00159                 _ThrowExceptionIfNotOpen();
00160 
00161                 coreproject->__AbortTransaction(TRANSTYPE_FIRST);
00162         }
00163         COMCATCH(;)
00164 }
00165 
00166 STDMETHODIMP CMgaMetaProject::Close()
00167 {
00168         COMTRY
00169         {
00170                 if( coreproject != NULL )
00171                 {
00172                         short count = 0;
00173                         COMTHROW( coreproject->get_NestedTransactionCount(&count) );
00174 
00175                         if( count == 1 )
00176                                 COMTHROW( coreproject->AbortTransaction(TRANSTYPE_ANY) );
00177 
00178                         short undos;
00179                         COMTHROW(coreproject->get_UndoQueueSize(&undos));
00180                         if (undos)
00181                         {
00182                                 HRESULT hr = coreproject->SaveProject(L"", VARIANT_TRUE);
00183                                 if (FAILED(hr))
00184                                         return hr;
00185                         }
00186                         COMTHROW(coreproject->FlushRedoQueue());
00187                         COMTHROW(coreproject->FlushUndoQueue());
00188 
00189                         COMTHROW( coreproject->BeginTransaction(TRANSTYPE_FIRST) );
00190                         COMTHROW( coreproject->PushTerritory(coreterritory) );
00191 
00192 
00193                         for (auto it = metaobj_lookup.begin(); it != metaobj_lookup.end(); it++)
00194                         {
00195                                 CCoreObjectPtr self(it->second);
00196                                 COMTHROW(self->put_AttributeValue(ATTRID_LOCK, CComVariant((locking_type)-1)));
00197                         }
00198                         for (auto it = core_object_cleanup.begin(); it != core_object_cleanup.end(); it++)
00199                         {
00200                                 COMTHROW((*it)->put_AttributeValue(ATTRID_LOCK, CComVariant((locking_type)-1)));
00201                         }
00202                         core_object_cleanup.clear();
00203 
00204                         COMTHROW( coreproject->CommitTransaction(TRANSTYPE_FIRST) );
00205 
00206                         metaobj_lookup.clear();
00207                         max_metaref = 1000;
00208 
00209                         rootobject = NULL;
00210 
00211                         if( coreterritory != NULL )
00212                         {
00213                                 COMTHROW( coreterritory->Clear() );
00214                                 coreterritory = NULL;
00215                         }
00216 
00217                         coreproject->__CloseProject(VARIANT_TRUE);
00218                         coreproject = NULL;
00219                 }
00220 
00221                 ASSERT( coreproject == NULL );
00222                 ASSERT( coreterritory == NULL );
00223                 ASSERT( rootobject == NULL );
00224                 ASSERT( metaobj_lookup.empty() );
00225         }
00226         COMCATCH(;)
00227 }
00228 
00229 STDMETHODIMP CMgaMetaProject::get_GUID(VARIANT *p)
00230 {
00231 
00232         CHECK_OUT(p);
00233 
00234         COMTRY
00235         {
00236                 _ThrowExceptionIfNotOpen();
00237 
00238                 CCoreObjectPtr me(rootobject);
00239                 me.GetVariantValue(ATTRID_GUID, p);
00240 
00241                 if( p->vt != (VT_UI1 | VT_ARRAY) || GetArrayLength(*p) != sizeof(::GUID) )
00242                 {
00243                         ::GUID guid;
00244                         memset(&guid, 0, sizeof(::GUID));
00245 
00246                         CopyTo(guid, p);
00247                 }
00248         }
00249         COMCATCH(;)
00250 }
00251 
00252 STDMETHODIMP CMgaMetaProject::put_GUID(VARIANT p)
00253 {
00254         COMTRY
00255         {
00256                 _ThrowExceptionIfNotOpen();
00257 
00258                 if( p.vt != (VT_UI1 | VT_ARRAY) || GetArrayLength(p) != sizeof(::GUID) )
00259                         COMRETURN(E_INVALIDARG);
00260 
00261                 return ComPutAttrValue(rootobject, ATTRID_GUID, p);
00262         }
00263         COMCATCH(;)
00264 }
00265 
00266 STDMETHODIMP CMgaMetaProject::get_Name(BSTR *p)
00267 {
00268         COMTRY
00269         {
00270                 _ThrowExceptionIfNotOpen();
00271 
00272                 return ComGetAttrValue(rootobject, ATTRID_PARNAME, p);
00273         }
00274         COMCATCH(;)
00275 }
00276 
00277 STDMETHODIMP CMgaMetaProject::put_Name(BSTR p)
00278 {
00279         COMTRY
00280         {
00281                 _ThrowExceptionIfNotOpen();
00282 
00283                 return ComPutAttrValue(rootobject, ATTRID_PARNAME, p);
00284         }
00285         COMCATCH(;)
00286 }
00287 
00288 STDMETHODIMP CMgaMetaProject::get_DisplayedName(BSTR *p)
00289 {
00290         COMTRY
00291         {
00292                 _ThrowExceptionIfNotOpen();
00293 
00294                 return ComGetDisplayedName(rootobject, ATTRID_PARDISPNAME, ATTRID_PARNAME, p);
00295         }
00296         COMCATCH(;)
00297 }
00298 
00299 STDMETHODIMP CMgaMetaProject::put_DisplayedName(BSTR p)
00300 {
00301         COMTRY
00302         {
00303                 _ThrowExceptionIfNotOpen();
00304 
00305                 return ComPutAttrValue(rootobject, ATTRID_PARDISPNAME, p);
00306         }
00307         COMCATCH(;)
00308 }
00309 
00310 STDMETHODIMP CMgaMetaProject::get_Version(BSTR *p)
00311 {
00312         COMTRY
00313         {
00314                 _ThrowExceptionIfNotOpen();
00315 
00316                 return ComGetAttrValue(rootobject, ATTRID_VERSION, p);
00317         }
00318         COMCATCH(;)
00319 }
00320 
00321 STDMETHODIMP CMgaMetaProject::put_Version(BSTR p)
00322 {
00323         COMTRY
00324         {
00325                 _ThrowExceptionIfNotOpen();
00326 
00327                 return ComPutAttrValue(rootobject, ATTRID_VERSION, p);
00328         }
00329         COMCATCH(;)
00330 }
00331 
00332 STDMETHODIMP CMgaMetaProject::get_Author(BSTR *p)
00333 {
00334         COMTRY
00335         {
00336                 _ThrowExceptionIfNotOpen();
00337 
00338                 return ComGetAttrValue(rootobject, ATTRID_AUTHOR, p);
00339         }
00340         COMCATCH(;)
00341 }
00342 
00343 STDMETHODIMP CMgaMetaProject::put_Author(BSTR p)
00344 {
00345         COMTRY
00346         {
00347                 _ThrowExceptionIfNotOpen();
00348 
00349                 return ComPutAttrValue(rootobject, ATTRID_AUTHOR, p);
00350         }
00351         COMCATCH(;)
00352 }
00353 
00354 STDMETHODIMP CMgaMetaProject::get_Comment(BSTR *p)
00355 {
00356         COMTRY
00357         {
00358                 _ThrowExceptionIfNotOpen();
00359 
00360                 return ComGetAttrValue(rootobject, ATTRID_COMMENT, p);
00361         }
00362         COMCATCH(;)
00363 }
00364 
00365 STDMETHODIMP CMgaMetaProject::put_Comment(BSTR p)
00366 {
00367         COMTRY
00368         {
00369                 _ThrowExceptionIfNotOpen();
00370 
00371                 return ComPutAttrValue(rootobject, ATTRID_COMMENT, p);
00372         }
00373         COMCATCH(;)
00374 }
00375 
00376 STDMETHODIMP CMgaMetaProject::get_CreatedAt(BSTR *p)
00377 {
00378         COMTRY
00379         {
00380                 _ThrowExceptionIfNotOpen();
00381 
00382                 return ComGetAttrValue(rootobject, ATTRID_CDATE, p);
00383         }
00384         COMCATCH(;)
00385 }
00386 
00387 STDMETHODIMP CMgaMetaProject::put_CreatedAt(BSTR p)
00388 {
00389         COMTRY
00390         {
00391                 _ThrowExceptionIfNotOpen();
00392 
00393                 return ComPutAttrValue(rootobject, ATTRID_CDATE, p);
00394         }
00395         COMCATCH(;)
00396 }
00397 
00398 STDMETHODIMP CMgaMetaProject::get_ModifiedAt(BSTR *p)
00399 {
00400         COMTRY
00401         {
00402                 _ThrowExceptionIfNotOpen();
00403 
00404                 return ComGetAttrValue(rootobject, ATTRID_MDATE, p);
00405         }
00406         COMCATCH(;)
00407 }
00408 
00409 STDMETHODIMP CMgaMetaProject::put_ModifiedAt(BSTR p)
00410 {
00411         COMTRY
00412         {
00413                 _ThrowExceptionIfNotOpen();
00414 
00415                 return ComPutAttrValue(rootobject, ATTRID_MDATE, p);
00416         }
00417         COMCATCH(;)
00418 }
00419 
00420 STDMETHODIMP CMgaMetaProject::get_FindObject(metaref_type metaref, IMgaMetaBase **p)
00421 {
00422         metaobj_lookup_iterator i = metaobj_lookup.find(metaref);
00423         if( i == metaobj_lookup.end() )
00424                 COMRETURN(E_NOTFOUND);
00425 
00426         CopyTo((*i).second.p, p);
00427         return S_OK;
00428 }
00429 
00430 STDMETHODIMP CMgaMetaProject::SetNmspc(BSTR p)
00431 {
00432         m_namespace = p;
00433         return S_OK;
00434 }
00435 
00436 STDMETHODIMP CMgaMetaProject::GetNmspc(BSTR *p)
00437 {
00438         CComBSTR nms = m_namespace;
00439         *p = nms.Detach();
00440 
00441         return S_OK;
00442 }
00443 
00444 // ------- metaobj_lookup
00445 
00446 void CMgaMetaProject::RegisterMetaBase(metaref_type metaref, IMgaMetaBase *obj)
00447 {
00448         ASSERT( obj != NULL );
00449 
00450         if( metaobj_lookup.find(metaref) != metaobj_lookup.end() )
00451                 HR_THROW(E_METAREF);
00452 
00453         if( metaref > max_metaref )
00454                 max_metaref = metaref;
00455 
00456         metaobj_lookup[metaref] = obj;
00457 }
00458 
00459 void CMgaMetaProject::UnregisterMetaBase(metaref_type metaref, IMgaMetaBase *obj)
00460 {
00461         ASSERT( obj != NULL );
00462         // Under GC, we may be here via ~CMgaMetaBase after Close clear()s the map
00463         if (metaobj_lookup.size() == 0)
00464                 return;
00465         ASSERT( metaobj_lookup.find(metaref) != metaobj_lookup.end() );
00466         ASSERT( metaobj_lookup[metaref] == obj );
00467 
00468         metaobj_lookup.erase(metaref);
00469 }
00470 
00471 //  ------- Edit
00472 
00473 void CMgaMetaProject::CreateMetaBase(metaid_type metaid, CCoreObjectPtr &obj)
00474 {
00475         ASSERT( obj == NULL );
00476         ASSERT( coreproject != NULL );
00477 
00478         COMTHROW( coreproject->CreateObject(metaid, PutOut(obj)) );
00479         COMTHROW( obj->put_AttributeValue(ATTRID_METAREF, PutInVariant(max_metaref + 1)) );
00480         CMgaMetaBase::Traverse(this, obj);
00481         
00482         ++max_metaref;
00483 }
00484 
00485 void CMgaMetaProject::CreateMetaObj(metaid_type metaid, CCoreObjectPtr &obj)
00486 {
00487         ASSERT( obj == NULL );
00488         ASSERT( coreproject != NULL );
00489 
00490         COMTHROW( coreproject->CreateObject(metaid, PutOut(obj)) );
00491 }
00492 
00493 // ------- CheckPath
00494 
00495 void CMgaMetaProject::CreatePathItems(bstr_const_iterator i, bstr_const_iterator e, pathitems_type &pathitems)
00496 {
00497         ASSERT( pathitems.empty() );
00498 
00499         while( i != e && *(e-1) == L' ' )
00500                 --e;
00501 
00502         while( i < e )
00503         {
00504                 wchar_t *j = 0;
00505                 long metaref = wcstol(i, &j, 10);
00506 
00507                 if( i == j || j == 0 )
00508                         COMTHROW(E_INVALID_PATH);
00509 
00510                 metaobj_lookup_iterator k = metaobj_lookup.find(metaref);
00511                 if( k == metaobj_lookup.end() )
00512                         COMTHROW(E_INVALID_PATH);
00513 
00514                 pathitems.push_back(pathitem_type());
00515                 
00516                 COMTHROW( k->second->get_Name(PutOut(pathitems.back().continual_name)) );
00517 
00518                 CComObjPtr<IMgaMetaRole> role;
00519                 if( SUCCEEDED( ::QueryInterface(k->second, role)) )
00520                 {
00521                         CComObjPtr<IMgaMetaFCO> fco;
00522                         COMTHROW( role->get_Kind(PutOut(fco)) );
00523                         COMTHROW( fco->get_Name(PutOut(pathitems.back().terminal_name)) );
00524                 }
00525                 else
00526                 {
00527                         pathitems.back().terminal_name = pathitems.back().continual_name;
00528                 }
00529 
00530                 i = j;
00531         }
00532 }
00533 
00534 void CMgaMetaProject::CreateJointPaths(BSTR paths, jointpaths_type &jointpaths)
00535 {
00536         ASSERT( jointpaths.empty() );
00537 
00538         bstr_const_iterator i = begin(paths);
00539         bstr_const_iterator e = end(paths);
00540         while( i != e )
00541         {
00542                 i = std::find_if(i, e, std::bind2nd( std::not_equal_to<wchar_t>(), L' '));
00543                 if( i == e )
00544                         break;
00545                 
00546                 bstr_const_iterator j = std::find(i, e, L' ');
00547                 bstr_const_iterator k = std::find(j, e, L',');
00548 
00549                 jointpaths.push_back(jointpath_type());
00550                 CopyTo(i, j, jointpaths.back().ptrspec_name);
00551 
00552                 CreatePathItems(j, k, jointpaths.back().pathitems);
00553 
00554                 i = k;
00555                 if( i != e )
00556                 {
00557                         ASSERT( *i == L',' );
00558                         ++i;
00559                 }
00560         }
00561 }
00562 
00563 void CMgaMetaProject::_ThrowExceptionIfNotOpen()
00564 {
00565         if (rootobject == NULL)
00566                 throw_com_error(E_META_NOTOPEN, L"MgaMetaProject is not open");
00567 }