GME
13
|
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 }