GME  13
MgaFCO.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include <stdio.h>
00003 #include "MgaFCO.h"
00004 
00005 
00006 #include "MgaFolder.h"
00007 #include "MgaModel.h"
00008 #include "MgaConnection.h"
00009 #include "MgaReference.h"
00010 #include "MgaSet.h"
00011 
00012 // ----------------------------------------
00013 // Constructor, destructor, FinalConstruct, getinterace
00014 // ----------------------------------------
00015 
00016 FCO::FCO()  { 
00017                 INITSIG('F')
00018 #ifdef DEBUG
00019                 MGA_TRACE("Constructed: %s - %08X\n", sig, this);
00020 #endif
00021                 notifymask = changemask = temporalmask = 0;
00022 }
00023 
00024 STDMETHODIMP FCO::FinalConstruct() {
00025         COMTRY {
00026                         {
00027                                 CoreObj myself;
00028                                 QueryInterface(__uuidof(ICoreObject),(void **)&myself);
00029                                 self = myself;  // self does not hold reference!!!
00030                         }
00031                         CComPtr<ICoreProject> cp;
00032                         COMTHROW(self->get_Project(&cp));
00033 #ifdef _ATL_DEBUG_INTERFACES
00034                         CComPtr<IMgaProject> proj;
00035                         COMTHROW(cp->QueryInterface(__uuidof(IMgaProject),(void **)&proj));
00036                         IUnknown* pUnk = ((ATL::_QIThunk *)(proj.p))->m_pUnk;
00037                         pUnk->AddRef();
00038                         mgaproject.Attach((CMgaProject*)(IDispatchImpl<IMgaProject, &__uuidof(IMgaProject), &__uuidof(__MGALib)>*)(pUnk));
00039 #else
00040                         COMTHROW(cp->QueryInterface(__uuidof(IMgaProject),(void **)&mgaproject));
00041 #endif
00042         } COMCATCH(;);
00043 }
00044 
00045 
00046 FCO::~FCO() { 
00047 #ifdef DEBUG
00048                 MGA_TRACE("Destructed: %s - %08X\n", sig, this);
00049 #endif
00050                 MARKSIG('9');
00051                 ASSERT(pubfcos.begin() == pubfcos.end());
00052 }
00053 
00054 
00055 // return an IMgaObject for this FCO. By default, use the active territory to create it
00056 template <>
00057 void FCO::getinterface<IMgaObject>(IMgaObject **p, CMgaTerritory *terr) {
00058         ASSERT(mgaproject->activeterr);
00059         if(terr == NULL) terr = mgaproject->activeterr;
00060         pubfcohash::iterator ii = pubfcos.find(terr);
00061         if(ii != pubfcos.end())  ((*p) = (*ii).second)->AddRef();
00062         else {
00063                 switch(GetMetaID(self)) {
00064                 case DTID_MODEL:                { CComPtr< CMgaModel > np; CreateComObject(np); np->Initialize(terr, this); *p = np.Detach(); } break;
00065                 case DTID_ATOM:                 { CComPtr< CMgaAtom > np; CreateComObject(np); np->Initialize(terr, this); *p = np.Detach(); } break;
00066                 case DTID_REFERENCE:    { CComPtr< CMgaReference > np; CreateComObject(np); np->Initialize(terr, this); *p = np.Detach(); } break;
00067                 case DTID_CONNECTION:   { CComPtr< CMgaConnection > np; CreateComObject(np); np->Initialize(terr, this); *p = np.Detach(); } break;
00068                 case DTID_SET:                  { CComPtr< CMgaSet > np; CreateComObject(np); np->Initialize(terr, this); *p = np.Detach(); } break;
00069                 case DTID_FOLDER:               { CComPtr< CMgaFolder > np; CreateComObject(np); np->Initialize(terr, this); *p = np.Detach(); } break;
00070                 }
00071         }
00072         ASSERT(("Could not create MGA object",p));
00073 }
00074 
00075 // ----------------------------------------
00076 // FCO status information methods: readibility, writability, IsEqual
00077 // ----------------------------------------
00078 //throws!!
00079 long FCO::getstatus() {
00080                 if(!mgaproject) COMTHROW(E_MGA_ZOMBIE_NOPROJECT);
00081                 if(!mgaproject->opened) COMTHROW(E_MGA_ZOMBIE_CLOSED_PROJECT);
00082                 if(!mgaproject->activeterr) COMTHROW(E_MGA_NOT_IN_TRANSACTION);
00083                 VARIANT_BOOL pp;
00084                 if(self->get_IsDeleted(&pp) != S_OK) return OBJECT_ZOMBIE;
00085                 return pp ? OBJECT_DELETED  :  OBJECT_EXISTS;
00086 }
00087 
00088 //throws!!
00089 void FCO::CheckDeletedRead() {
00090                 if(getstatus() == OBJECT_ZOMBIE) COMTHROW(E_MGA_OBJECT_ZOMBIE);
00091 }
00092 
00093 //throws!!
00094 void FCO::CheckRead() {
00095                 if(getstatus() != OBJECT_EXISTS) COMTHROW(E_MGA_OBJECT_DELETED);
00096 }
00097 
00098 //throws!!
00099 void FCO::CheckWrite() {
00100                 CheckRead();
00101                 if(mgaproject->read_only) COMTHROW(E_MGA_READ_ONLY_ACCESS);
00102                 if(self[ATTRID_PERMISSIONS] & LIBRARY_FLAG) COMTHROW(E_MGA_LIBOBJECT);
00103                 if(self[ATTRID_PERMISSIONS] & READONLY_FLAG) COMTHROW(E_MGA_READ_ONLY_ACCESS);
00104 }
00105 
00106 HRESULT FCO::get_IsEqual(IMgaObject *o, VARIANT_BOOL *pVal) {
00107         COMTRY {
00108                 CHECK_OUTPAR(pVal);
00109                 if(o == NULL) *pVal = VARIANT_FALSE;
00110                 else {
00111                         CHECK_MYINPTRPAR(o);
00112                         *pVal = (ObjFor(o) == this) ? VARIANT_TRUE : VARIANT_FALSE;
00113                 }
00114         } COMCATCH(;)
00115 }
00116 
00117 
00118 HRESULT FCO::get_Status(long *p) {
00119         COMTRY {
00120                 CHECK_OUTPAR(p);
00121                 *p = getstatus(); 
00122         } COMCATCH(;);
00123 }
00124 
00125 HRESULT FCO::get_IsWritable(VARIANT_BOOL *p) {
00126         COMTRY {
00127                 CHECK_OUTPAR(p);
00128                 *p = VARIANT_TRUE;
00129         } COMCATCH(;)
00130 }
00131 
00132 
00133 // is its metaobject a simpleconnection??
00134 bool FCO::simpleconn() {
00135         CComPtr<IMgaMetaFCO> meta;
00136         if(get_Meta(&meta) != S_OK) return false;
00137         CComQIPtr<IMgaMetaConnection> metac = meta;
00138         if(!metac) return false;
00139         VARIANT_BOOL s;
00140         if(metac->get_IsSimple(&s) != S_OK) return false;
00141         return s ? true : false;
00142 }
00143 
00144 
00145 // ----------------------------------------
00146 // Basic FCO info: project, ID, relID, meta, metarole, 
00147 // ----------------------------------------
00148 
00149 HRESULT FCO::get_Project(IMgaProject **pVal) { 
00150         COMTRY {
00151                 CHECK_OUTPTRPAR(pVal); 
00152                 *pVal = mgaproject; (*pVal)->AddRef(); 
00153         } COMCATCH(;)
00154 } 
00155 
00156 
00157 HRESULT FCO::CheckProject(IMgaProject *project) {
00158         return(project == mgaproject? S_OK : E_MGA_FOREIGN_PROJECT);
00159 }
00160 
00161 
00162 HRESULT FCO::get_ObjType(objtype_enum *pVal) { 
00163                 COMTRY {
00164                         CheckDeletedRead();
00165                         CHECK_OUTPAR(pVal);
00166                         *pVal = static_cast<objtype_enum>(GetMetaID(self) - DTID_BASE);
00167                 } COMCATCH(;)
00168         };
00169 
00170 
00171 HRESULT FCO::get_ID(ID_type *pVal) {
00172         COMTRY {
00173                 CheckDeletedRead();
00174                 CHECK_OUTSTRPAR(pVal);
00175                 OLECHAR t[20];
00176                 objid_type ss;
00177                 COMTHROW(self->get_ObjID(&ss));
00178                 swprintf(t, 20, OLESTR("id-%04lx-%08lx"),GetMetaID(self), ss);
00179                 *pVal = CComBSTR(t).Detach();
00180         } COMCATCH(;);
00181 }
00182 
00183 HRESULT FCO::get_RelID(long *pVal) {
00184         COMTRY {
00185                 CheckRead();
00186                 CHECK_OUTPAR(pVal);
00187                 *pVal = self[ATTRID_RELID];
00188         } COMCATCH(;);
00189 }
00190 
00191 HRESULT FCO::put_RelID(long newVal) {
00192         COMTRY_IN_TRANSACTION {
00193                 CheckWrite();
00194                 if(newVal <= 0 || newVal >= RELIDSPACE) COMTHROW(E_MGA_ARG_RANGE);
00195                 self[ATTRID_RELID] = newVal;
00196         } COMCATCH_IN_TRANSACTION(;);
00197 }
00198 
00199 
00200 HRESULT FCO::get_MetaRole( IMgaMetaRole **pVal) {
00201                 COMTRY {
00202                         CheckDeletedRead();
00203                         CHECK_OUTPTRPAR(pVal);
00204                         metaref_type role = self[ATTRID_ROLEMETA];
00205                         if(role) {
00206                                 mgaproject->SetNmspaceInMeta();
00207                                 *pVal = CComQIPtr<IMgaMetaRole>(mgaproject->FindMetaRef(role)).Detach();
00208                                 if(!(*pVal)) COMTHROW(E_MGA_META_INCOMPATIBILITY);
00209                         }
00210                         // FIXME: need to return an E_ here
00211 
00212                 } COMCATCH(;);
00213 }
00214 
00215 HRESULT FCO::get_Meta(IMgaMetaFCO **pVal) { 
00216         COMTRY {
00217                 CheckDeletedRead();
00218                 CHECK_OUTPTRPAR(pVal);
00219                 COMTRY {
00220                         mgaproject->SetNmspaceInMeta();
00221                         *pVal = CComQIPtr<IMgaMetaFCO>(mgaproject->FindMetaRef(self[ATTRID_META])).Detach();
00222                 } COMCATCH(e.hr = E_MGA_META_INCOMPATIBILITY;)
00223 
00224                 // unreachable code ? really?
00225                 if(!(*pVal)) 
00226                         COMTHROW(E_MGA_META_INCOMPATIBILITY);
00227         } COMCATCH(;)
00228 }
00229 
00230 HRESULT FCO::get_MetaBase(IMgaMetaBase **pVal) { 
00231         COMTRY {
00232                 CheckDeletedRead();
00233                 CHECK_OUTPTRPAR(pVal);
00234                 mgaproject->SetNmspaceInMeta();
00235                 *pVal = mgaproject->FindMetaRef(self[ATTRID_META]).Detach();
00236         } COMCATCH(;)
00237 }
00238 
00239 HRESULT FCO::get_MetaRef(metaref_type *pVal) { 
00240         COMTRY {
00241                 CheckDeletedRead();
00242                 CHECK_OUTPTRPAR(pVal);
00243                 mgaproject->SetNmspaceInMeta();
00244                 *pVal = self[ATTRID_META];
00245         } COMCATCH(;)
00246 }
00247 
00248 // ----------------------------------------
00249 // Parent and grandparent access
00250 // ----------------------------------------
00251 
00252 HRESULT FCO::GetParent(IMgaContainer **pVal, objtype_enum *l) { 
00253                 COMTRY {
00254                         CheckRead();
00255                         CHECK_OUTPTRPARVALIDNULL(pVal);
00256                         CComPtr<IMgaContainer> pv;
00257                         CoreObj par;
00258                         par = self[ATTRID_PARENT];
00259                         if(par.GetMetaID() != DTID_ROOT) {
00260                                 ObjForCore(par)->getinterface(&pv);
00261                                 if (l != NULL)
00262                                         COMTHROW(pv->get_ObjType(l));
00263                                 if(pVal != NULL) {
00264                                         *pVal = pv.Detach();
00265                                 }
00266                         }
00267                         else {
00268                                 if(l != NULL) *l = OBJTYPE_NULL;
00269                                 if(pVal != NULL) *pVal = NULL;
00270                         }
00271                 } COMCATCH(;)
00272         };
00273 
00274 
00275 HRESULT FCO::get_ParentModel(IMgaModel **pVal) {
00276                 COMTRY {
00277                         CheckRead();
00278                         CHECK_OUTPTRPAR(pVal);
00279                         CoreObj par;
00280                         par = self[ATTRID_FCOPARENT];
00281                         if(par.GetMetaID() == DTID_MODEL) {
00282                                 CComPtr<IMgaModel> pv;
00283                                 ObjForCore(par)->getinterface(&pv);
00284                                 *pVal = pv.Detach();
00285                                 COMTHROW((*pVal)->Open(OPEN_READ));
00286                         }
00287                 } COMCATCH(;);
00288 }
00289 
00290 HRESULT FCO::get_ParentFolder(IMgaFolder **pVal) {
00291                 COMTRY {
00292                         CheckRead();
00293                         CHECK_OUTPTRPAR(pVal);
00294                         CoreObj par;
00295                         par = self[ATTRID_FCOPARENT];
00296                         if(par.GetMetaID() == DTID_FOLDER) {
00297                                 CComPtr<IMgaFolder> pv;
00298                                 ObjForCore(par)->getinterface(&pv);
00299                                 *pVal = pv.Detach();
00300                                 COMTHROW((*pVal)->Open(OPEN_READ));
00301                         }
00302                 } COMCATCH(;);
00303 }
00304 
00305 
00306 
00307 HRESULT FCO::get_RootParent(IMgaFCO **parent, long *distance) {       // retuns itself if root model
00308         COMTRY {
00309                 long d = 0;
00310                 CComPtr<IMgaFCO> cur;
00311                 getinterface(&cur);
00312                 while(true) {
00313                         CComPtr<IMgaContainer> f;
00314                         objtype_enum t;
00315                         COMTHROW(cur->GetParent(&f, &t));
00316                         if(t != OBJTYPE_MODEL) break;
00317                         cur = NULL;
00318                         f.QueryInterface(&cur);
00319                         d++;
00320                 }
00321                 if(parent) {
00322                         CHECK_OUTPTRPAR(parent);
00323                         *parent = cur.Detach();
00324                 }
00325                 if(distance) *distance = d;
00326         } COMCATCH(;)
00327 }
00328 
00329 HRESULT FCO::get_ParentChain(IMgaFCOs **parents) {    // returns the real parents only (not self)
00330         COMTRY {
00331                 CComPtr<IMgaFCO> cur;
00332                 getinterface(&cur);
00333                 CREATEEXCOLLECTION_FOR(MgaFCO, q);
00334                 while(true) {
00335                         CComPtr<IMgaContainer> f;
00336                         objtype_enum t;
00337                         COMTHROW(cur->GetParent(&f, &t));
00338                         if(t != OBJTYPE_MODEL) break;
00339                         f.QueryInterface(&cur);
00340                         q->Add(cur);
00341                 }
00342                 *parents = q.Detach();
00343         } COMCATCH(;)
00344 }
00345 
00346 // check if object is a child or any grandchild of parentobject (also true if itself)
00347 bool FCO::IsDescendantOf(IMgaFCO *object, long *distance) {
00348                 int d;
00349                 if(IsContained(self, CoreObj(object), &d)) {
00350                         if(distance) *distance = d;
00351                         return true;
00352                 }
00353                 else return false;
00354 
00355 }
00356 
00357 // ----------------------------------------
00358 // Name access
00359 // ----------------------------------------
00360 HRESULT FCO::get_Name(BSTR *pVal)               { 
00361         COMTRY {
00362                 CheckDeletedRead();
00363                 CHECK_OUTPAR(pVal);  
00364                 *pVal = CComBSTR(self[ATTRID_NAME]).Detach();
00365         } COMCATCH(;);
00366 };
00367 
00368 
00369 /*class put_NameTask : public DeriveTreeTask {
00370         CComBSTR oldname, newname;
00371 
00372         bool Do(CoreObj self, std::vector<CoreObj> *peers = NULL) {
00373                 if(!(oldname == CComBSTR(self[ATTRID_NAME]))) return false;
00374                 if(ObjForCore(self)->mgaproject->preferences & MGAPREF_NODUPLICATENAMES) {
00375                         CoreObj parent = self[ATTRID_PARENT];
00376                         if(parent.GetMetaID() != DTID_ROOT) {  // Make sure it is not rootfolder (=parent is not rootobj)
00377                                 CoreObjs children = parent[ATTRID_PARENT+ATTRID_COLLECTION];
00378                                 ITERATE_THROUGH(children) {
00379                                         CComBSTR n = ITER[ATTRID_NAME];
00380                                         if(n == newname && !COM_EQUAL(self, ITER)) COMTHROW(E_MGA_NAME_DUPLICATE);
00381                                 }
00382                         }               
00383                 }
00384                 self[ATTRID_NAME] = newname;
00385                 ObjForCore(self)->SelfMark(OBJEVENT_PROPERTIES);
00386                 if(self.IsFCO() && self.IsRootOfDeriv()) return false;   // Type renaming does not affect instances
00387                 return true;
00388         }
00389 
00390 public:
00391         put_NameTask(BSTR oname, BSTR nname) : oldname(oname), newname(nname) { ; }
00392 };*/
00393 
00394 put_NameTask::put_NameTask(BSTR oname, BSTR nname) : oldname(oname), newname(nname) { ; }
00395 
00396 bool put_NameTask::Do(CoreObj self, std::vector<CoreObj> *peers /*= NULL*/) {
00397                 if(!(oldname == CComBSTR(self[ATTRID_NAME]))) return false;
00398                 if(ObjForCore(self)->mgaproject->preferences & MGAPREF_NODUPLICATENAMES) {
00399                         CoreObj parent = self[ATTRID_PARENT];
00400                         if(parent.GetMetaID() != DTID_ROOT) {  // Make sure it is not rootfolder (=parent is not rootobj)
00401                                 CoreObjs children = parent[ATTRID_PARENT+ATTRID_COLLECTION];
00402                                 ITERATE_THROUGH(children) {
00403                                         CComBSTR n = ITER[ATTRID_NAME];
00404                                         if(n == newname && !COM_EQUAL(self, ITER)) COMTHROW(E_MGA_NAME_DUPLICATE);
00405                                 }
00406                         }               
00407                 }
00408                 self[ATTRID_NAME] = newname;
00409                 ObjForCore(self)->SelfMark(OBJEVENT_PROPERTIES);
00410                 if(self.IsFCO() && self.IsRootOfDeriv()) return false;   // Type renaming does not affect instances
00411                 return true;
00412         }
00413 
00414 
00415 void  FCO::initialname() { 
00416         if(mgaproject->preferences & MGAPREF_NAMENEWOBJECTS) {
00417                 metaref_type mr;
00418                 if(self.IsFCO() && !self.IsRootFCO()) mr = self[ATTRID_ROLEMETA];
00419                 else mr = self[ATTRID_META];
00420                 CComBSTR nname;
00421                 COMTHROW(mgaproject->FindMetaRef(mr)->get_Name(&nname));
00422                 if(mgaproject->preferences & MGAPREF_NODUPLICATENAMES) {
00423                         size_t len = nname.Length();
00424                         unsigned int freenum = 0;
00425                         CoreObj parent = self[ATTRID_PARENT];
00426                         if(parent.GetMetaID() != DTID_ROOT) {  // Make sure it is not rootfolder (=parent is not rootobj)
00427                                 CoreObjs children = parent[ATTRID_PARENT+ATTRID_COLLECTION];
00428                                 ITERATE_THROUGH(children) {
00429                                         CComBSTR n = ITER[ATTRID_NAME];
00430                                         if(!wcsncmp(nname, n, len)) {
00431                                                 unsigned int f = 0;
00432                                                 if (n.Length() == len)
00433                                                         f = 1;
00434                                                 else {
00435                                                         swscanf(n+len,L"-%d", &f);
00436                                                         f++;
00437                                                         if(f > NEWNAME_MAXNUM) COMTHROW(E_MGA_GEN_OUT_OF_SPACE);
00438                                                 }
00439                                                 if(f > freenum) freenum = f;
00440                                         }
00441                                 }
00442                         }
00443                         if(freenum) {
00444                                 OLECHAR p[10];
00445                                 swprintf(p, 10, L"-%d",freenum);
00446                                 COMTHROW(nname.Append(p));
00447                         }
00448                 }
00449                 self[ATTRID_NAME] = nname;
00450         }
00451 }
00452 
00453 HRESULT FCO::put_Name(BSTR newVal)    { 
00454         COMTRY_IN_TRANSACTION_MAYBE {
00455         CheckWrite();
00456                 CHECK_INPAR(newVal);  
00457                 if(self[ATTRID_PERMISSIONS] & LIBROOT_FLAG) COMTHROW(E_MGA_LIBOBJECT);
00458                 if(CComBSTR(self[ATTRID_NAME]) != newVal) {
00459                         put_NameTask(CComBSTR(self[ATTRID_NAME]), newVal).DoWithDeriveds(self);;
00460                 }
00461         }
00462         COMCATCH_IN_TRANSACTION_MAYBE(;);       
00463 };
00464 
00465 void giveme( CMgaProject *mgaproject, CoreObj par, CoreObj cur, CComBSTR cur_kind, int *relpos)
00466 {
00467         int count_lower_ids = 0;
00468         CComBSTR cur_name = cur[ATTRID_NAME];
00469         objid_type cur_id = cur.GetObjID();
00470         
00471         CoreObjs children = par[ATTRID_FCOPARENT+ATTRID_COLLECTION];
00472         ITERATE_THROUGH(children) {
00473                 CComBSTR n = ITER[ATTRID_NAME];
00474 
00475                 CComBSTR kind;
00476                 COMTHROW( mgaproject->FindMetaRef( ITER[ATTRID_META])->get_Name( &kind));
00477 
00478                 bool similar = n == cur_name;
00479                 //similar = similar || ITER[ATTRID_PERMISSIONS] == LIBROOT_FLAG && libraryNameEqual(n, name_b);
00480                 similar = similar && kind == cur_kind;
00481                 if( similar) // similar name 
00482                 {
00483                         objid_type id = ITER.GetObjID();
00484                         if( cur_id > id)
00485                                 ++count_lower_ids;
00486                 }
00487         }
00488         *relpos = count_lower_ids;
00489 }
00490 
00491 // gives back the path to an object starting from the rootfolder (does not include project name)
00492 HRESULT FCO::get_AbsPath(BSTR *pVal)            { 
00493         COMTRY {
00494                 CheckRead();
00495                 CComBSTR path("");
00496 
00497                 CoreObj par = self[ATTRID_PARENT];
00498                 CoreObj cur = self;
00499                 while( !par.IsRootFolder())
00500                 {
00501                         CComBSTR tp("/@");
00502                         COMTHROW(tp.Append( cur[ATTRID_NAME]));
00503 
00504                         COMTHROW(tp.Append("|kind="));
00505                         CComBSTR metakind;
00506                         COMTHROW( mgaproject->FindMetaRef( cur[ATTRID_META])->get_Name( &metakind));
00507                         COMTHROW(tp.Append( metakind));
00508 
00509                         int n;
00510                         giveme( mgaproject, par, cur, metakind, &n);
00511                         char p[10]; sprintf( p, "%d", n);
00512                         CComBSTR relative_pos;
00513                         COMTHROW(tp.Append("|relpos="));
00514                         COMTHROW(tp.Append( p));
00515 
00516                         COMTHROW(tp.Append( path));
00517                         path = tp;
00518                         cur = par;
00519                         par = par[ATTRID_PARENT];
00520                 }
00521                 CheckDeletedRead();
00522                 CHECK_OUTPAR(pVal);  
00523                 *pVal = path.Detach();
00524         } COMCATCH(;);
00525 };
00526 
00527 // ----------------------------------------
00528 // Add FCO to a collection (create new coll if null)
00529 // ----------------------------------------
00530 HRESULT FCO::CreateCollection(IMgaFCOs **pVal) {
00531         COMTRY {
00532 // check type of collection
00533                 CComPtr<IMgaFCO> tthis;
00534                 getinterface(&tthis);
00535                 if(*pVal) {
00536                         CComPtr< COLLECTIONTYPE_FOR(IMgaFCO)> q;
00537                         q.Attach(static_cast< COLLECTIONTYPE_FOR(IMgaFCO) *>(*pVal));
00538                         q->Add(tthis);
00539                         /* *pVal = */q.Detach(); // modified by ZolMol
00540                 }
00541                 else {
00542                         CREATEEXCOLLECTION_FOR(MgaFCO,q2)
00543                         COMTHROW(q2->Append(tthis));
00544                         *pVal = q2.Detach(); // added by ZolMol
00545                 }
00546         } COMCATCH(;);
00547 }
00548 
00549 
00550 // ----------------------------------------
00551 // Parts access
00552 // ----------------------------------------
00553 HRESULT FCO::get_Parts(struct IMgaParts ** pVal) {
00554                 COMTRY {
00555                         CheckRead();
00556                         CHECK_OUTPTRPAR(pVal);
00557 
00558                         CComPtr<IMgaMetaRole> metaro;                                   
00559                         COMTHROW(get_MetaRole(&metaro));
00560                         if(!metaro) COMTHROW( E_MGA_ROOTFCO);
00561 
00562                         CComPtr<IMgaMetaParts> metaps;                                  
00563                         COMTHROW(metaro->get_Parts(&metaps));
00564 
00565                         CREATECOLLECTION_FOR(IMgaPart,q);
00566                         MGACOLL_ITERATE(IMgaMetaPart, metaps) {
00567                                         metaref_type r;                                         
00568                                         COMTHROW(MGACOLL_ITER->get_MetaRef(&r));
00569                                         q->Add(ppool.getpoolobj(r, this, mgaproject));
00570                         }
00571                         MGACOLL_ITERATE_END;
00572                         *pVal = q.Detach();
00573 
00574                 } COMCATCH(;);
00575 }
00576 
00577 HRESULT FCO::get_Part(IMgaMetaAspect * asp, IMgaPart **pVal) {
00578                 COMTRY {
00579                         CheckRead();
00580                         CHECK_INPTRPAR(asp);
00581                         CHECK_OUTPTRPAR(pVal);
00582 
00583                         CComPtr<IMgaPart> ret;
00584 
00585                         CComPtr<IMgaMetaRole> metaro;                                   
00586                         COMTHROW(get_MetaRole(&metaro));
00587                         if(!metaro) COMTHROW( E_MGA_ROOTFCO);
00588 
00589                         CComPtr<IMgaMetaParts> metaps;                                  
00590                         COMTHROW(metaro->get_Parts(&metaps));
00591                         MGACOLL_ITERATE(IMgaMetaPart, metaps) {
00592                                 CComPtr<IMgaMetaAspect> metaa;                                  
00593                                 COMTHROW(MGACOLL_ITER->get_ParentAspect(&metaa));
00594                                 if(COM_EQUAL(metaa, asp)) {
00595                                         metaref_type r;                                         
00596                                         COMTHROW(MGACOLL_ITER->get_MetaRef(&r));
00597                                         ret = ppool.getpoolobj(r, this, mgaproject);
00598                                         break;
00599                                 }
00600                         }
00601                         if (ret == nullptr)
00602                         {
00603                                 return E_NOTFOUND;
00604                         }
00605                         *pVal = ret.Detach();
00606 
00607                         MGACOLL_ITERATE_END;
00608                 } COMCATCH(;);
00609 }
00610 
00611 HRESULT FCO::get_PartByMP(IMgaMetaPart *part, IMgaPart **pVal) {
00612                 COMTRY {
00613                         CheckRead();
00614                         CHECK_INPTRPAR(part);
00615                         CHECK_OUTPTRPAR(pVal);
00616 
00617                         CComPtr<IMgaMetaRole> metaro, metaro2;                                  
00618                         COMTHROW(get_MetaRole(&metaro));
00619                         if(!metaro) COMTHROW( E_MGA_ROOTFCO);
00620 
00621                         COMTHROW(part->get_Role(&metaro2));
00622                         if(!COM_EQUAL(metaro, metaro2)) COMTHROW( E_MGA_INVALID_ROLE);
00623 
00624                         metaref_type r;                                         
00625                         COMTHROW(part->get_MetaRef(&r));
00626                         *pVal = ppool.getpoolobj(r, this, mgaproject).Detach();
00627                 } COMCATCH(;);
00628 }
00629 
00630 
00631 
00632 // ----------------------------------------
00633 // Attributes access
00634 // ----------------------------------------
00635 HRESULT FCO::get_Attributes(IMgaAttributes **pVal) { 
00636                 COMTRY {
00637                         CheckRead();
00638                         CHECK_OUTPTRPAR(pVal);
00639 
00640                         CComPtr<IMgaMetaFCO> metao;                                     
00641                         COMTHROW(get_Meta(&metao));
00642 
00643                         CComPtr<IMgaMetaAttributes> metaas;                                     
00644                         COMTHROW(metao->get_Attributes(&metaas));
00645 
00646                         CREATECOLLECTION_FOR(IMgaAttribute,q);
00647                         MGACOLL_ITERATE(IMgaMetaAttribute, metaas) {
00648                                         metaref_type r;                                         
00649                                         COMTHROW(MGACOLL_ITER->get_MetaRef(&r));
00650                                         q->Add(apool.getpoolobj(r, this, mgaproject));
00651                         }
00652                         MGACOLL_ITERATE_END;
00653                         *pVal = q.Detach();
00654 
00655                 } COMCATCH(;);
00656 }
00657 
00658 HRESULT FCO::get_Attribute(IMgaMetaAttribute *metaa,  IMgaAttribute **pVal) { 
00659                 COMTRY {
00660                         CheckRead();
00661                         CHECK_OUTPTRPAR(pVal);
00662                         CHECK_INPTRPAR(metaa);
00663                         CComPtr<IMgaMetaFCO> metao;                                     
00664                         COMTHROW(get_Meta(&metao));
00665                         metaref_type r;                                         
00666                         COMTHROW(metaa->get_MetaRef(&r));
00667 #ifdef OWN_META
00668                         CComPtr<IMgaMetaFCO> meta;                                  
00669                         COMTHROW(metaa->get_Owner(&meta));
00670                         if(!meta.IsEqualObject(metao)) return E_META_INVALIDATTR;
00671 #else
00672                         {
00673                         CComPtr<IMgaMetaFCOs> metas;                                
00674                         COMTHROW(metaa->get_UsedIn(&metas));
00675                         MGACOLL_ITERATE(IMgaMetaFCO,metas) {
00676                                 if(MGACOLL_ITER.IsEqualObject(metao)) break;
00677                         }
00678                         if(MGACOLL_AT_END) return E_META_INVALIDATTR;
00679                         MGACOLL_ITERATE_END;
00680                         }
00681 #endif
00682 
00683                         *pVal = apool.getpoolobj(r, this, mgaproject).Detach();
00684                 } COMCATCH(;);
00685         };
00686 
00687 // THROWS!!, always returns a valid attr.
00688 CComPtr<IMgaAttribute> FCO::AbyN(BSTR name) {
00689                 CHECK_INSTRPAR(name);
00690                 CComPtr<IMgaMetaAttribute> metaattr;
00691                 CComPtr<IMgaMetaFCO> meta;
00692                 metaref_type r;
00693                 COMTHROW(get_Meta(&meta));
00694                 COMTHROW(meta->get_AttributeByName(name, &metaattr));
00695                 COMTHROW(metaattr->get_MetaRef(&r));
00696                 return apool.getpoolobj(r, this, mgaproject);
00697 }
00698 
00699 HRESULT FCO::get_AttributeByName(BSTR name, VARIANT *pVal) { 
00700                 COMTRY {
00701                         CheckRead();
00702                         // parameter will be checked by attr. fun
00703                         COMTHROW(AbyN(name)->get_Value(pVal));
00704                 } COMCATCH(;);
00705 };
00706 HRESULT FCO::put_AttributeByName(BSTR name, VARIANT newVal) { 
00707                 COMTRY {
00708                         CheckRead();
00709                         // parameter will be checked by attr. fun
00710                         COMTHROW(AbyN(name)->put_Value(newVal));
00711                 } COMCATCH(;);
00712 }
00713 HRESULT FCO::get_StrAttrByName( BSTR name,  BSTR *pVal) {  
00714                 COMTRY {
00715                         CheckRead();
00716                         // parameter will be checked by attr. fun
00717                         COMTHROW(AbyN(name)->get_StringValue(pVal));
00718                 } COMCATCH(;);
00719 }
00720 HRESULT FCO::put_StrAttrByName( BSTR name,  BSTR newVal) {
00721                 COMTRY {
00722                         CheckRead();
00723                         // parameter will be checked by attr. fun
00724                         COMTHROW(AbyN(name)->put_StringValue(newVal));
00725                 } COMCATCH(;);
00726 }
00727 HRESULT FCO::get_IntAttrByName( BSTR name,  long *pVal) { 
00728                 COMTRY {
00729                         CheckRead();
00730                         // parameter will be checked by attr. fun
00731                         COMTHROW(AbyN(name)->get_IntValue(pVal));
00732                 } COMCATCH(;);
00733 }
00734 HRESULT FCO::put_IntAttrByName( BSTR name,  long newVal) {
00735                 COMTRY {
00736                         CheckRead();
00737                         // parameter will be checked by attr. fun
00738                         COMTHROW(AbyN(name)->put_IntValue(newVal));
00739                 } COMCATCH(;);
00740 }
00741 HRESULT FCO::get_FloatAttrByName( BSTR name,  double *pVal) { 
00742                 COMTRY {
00743                         CheckRead();
00744                         // parameter will be checked by attr. fun
00745                         COMTHROW(AbyN(name)->get_FloatValue(pVal));
00746                 } COMCATCH(;);
00747 }
00748 HRESULT FCO::put_FloatAttrByName( BSTR name,  double newVal) { 
00749                 COMTRY {
00750                         CheckRead();
00751                         // parameter will be checked by attr. fun
00752                         COMTHROW(AbyN(name)->put_FloatValue(newVal));
00753                 } COMCATCH(;);
00754 }
00755 HRESULT FCO::get_BoolAttrByName( BSTR name,  VARIANT_BOOL *pVal) { 
00756                 COMTRY {
00757                         CheckRead();
00758                         // parameter will be checked by attr. fun
00759                         COMTHROW(AbyN(name)->get_BoolValue(pVal));
00760                 } COMCATCH(;);
00761 }
00762 HRESULT FCO::put_BoolAttrByName( BSTR name,  VARIANT_BOOL newVal) {
00763                 COMTRY {
00764                         CheckRead();
00765                         // parameter will be checked by attr. fun
00766                         COMTHROW(AbyN(name)->put_BoolValue(newVal));
00767                 } COMCATCH(;);
00768 }
00769 HRESULT FCO::get_RefAttrByName( BSTR name,  IMgaFCO **pVal) {
00770                 COMTRY {
00771                         CheckRead();
00772                         // parameter will be checked by attr. fun
00773                         COMTHROW(AbyN(name)->get_FCOValue(pVal));
00774                 } COMCATCH(;);
00775 }
00776 HRESULT FCO::put_RefAttrByName( BSTR name,  IMgaFCO * newVal) {
00777                 COMTRY {
00778                         CheckRead();
00779                         if(newVal) CHECK_MYINPTRPAR(newVal);
00780                         // parameter will be checked by attr. fun
00781                         COMTHROW(AbyN(name)->put_FCOValue(newVal));
00782                 } COMCATCH(;);
00783 }
00784 
00785 HRESULT FCO::ClearAttrByName( BSTR name) { 
00786                 COMTRY_IN_TRANSACTION {
00787                         CheckWrite();
00788                         COMTHROW(AbyN(name)->Clear());
00789                 } COMCATCH_IN_TRANSACTION(;);
00790 }
00791 
00792 HRESULT FCO::get_RegistryNode( BSTR path,  IMgaRegNode **pVal) {  
00793         COMTRY {
00794                 CheckRead();
00795                 CHECK_INSTRPAR(path);
00796                 CHECK_OUTPTRPAR(pVal);
00797 
00798                 CComPtr<CMgaRegNode> s;
00799                 CreateComObject(s);
00800 
00801                 s->Initialize(path, this, mgaproject);
00802 
00803                 CComPtr<IMgaRegNode> retval = s;
00804 
00805                 *pVal = s.Detach();
00806         } COMCATCH(;)
00807 }
00808 
00809 
00810 // ----------------------------------------
00811 // Registry access
00812 // ----------------------------------------
00813 HRESULT FCO::get_Registry(VARIANT_BOOL virtuals, IMgaRegNodes **pVal) {  
00814         COMTRY {  
00815                 CheckRead();
00816                 CHECK_OUTPTRPAR(pVal);
00817 
00818                 CComPtr<CMgaRegNode> regnode;
00819                 CreateComObject(regnode);
00820 
00821                 regnode->Initialize(CComBSTR(L""), this, mgaproject);
00822 
00823                 COMTHROW(regnode->get_SubNodes(virtuals, pVal));
00824         } COMCATCH(;);
00825 }
00826 HRESULT FCO::get_RegistryValue( BSTR path,  BSTR *pVal) {  
00827         COMTRY {
00828                 CheckRead();
00829                 CHECK_OUTVARIANTPAR(pVal);
00830                 MgaRegNode_get_Value(mgaproject, this, self, path, pVal);
00831         } COMCATCH(;)
00832 }
00833 HRESULT FCO::put_RegistryValue( BSTR path,  BSTR newval) {  
00834         COMTRY {  // no arg check, called methods will do that
00835                 CheckRead();  // put_Value will check write
00836                 CComPtr<IMgaRegNode> node;
00837                 COMTHROW(get_RegistryNode(path, &node));
00838                 COMTHROW(node->put_Value(newval));
00839         } COMCATCH(;)
00840 }
00841 
00842 //-------------------------------------------------------------------------------------
00843 // lph: Change description for ATTR, REGISTRY and PROPERTIES notifications
00844 
00845 typedef std::vector<CComVariant> ModificationsVector;
00846 
00847 void getRegistryModifications(CoreObj &cobj, CComBSTR &path, ModificationsVector &mv) {
00848         // TODO
00849 }
00850 
00851 HRESULT get_Modifications(FCO *fco, unsigned long changemask, CComVariant *mods) {
00852         COMTRY {
00853         ModificationsVector modifications;
00854         if (changemask & OBJEVENT_REGISTRY) {
00855                 // TODO
00856         }
00857         if (changemask & OBJEVENT_ATTR) {
00858                 CComPtr<IMgaMetaFCO> mfco;
00859                 COMTHROW(fco->get_Meta(&mfco));
00860                 ITERATE_THROUGH(fco->self[ATTRID_ATTRPARENT+ATTRID_COLLECTION]) {
00861                         CComPtr<IMgaMetaAttribute> ma;
00862                         COMTHROW(mfco->get_AttributeByRef(ITER[ATTRID_META], &ma));
00863                         attval_enum vt;
00864                         COMTHROW(ma->get_ValueType(&vt));
00865                         if (vt == ATTVAL_ENUM) vt = ATTVAL_STRING;
00866                         attrid_type aid = ATTRID_ATTRTYPESBASE + vt;
00867                         CComVariant current = ITER[aid];
00868                         static const VARTYPE vartypes[] = { VT_NULL, VT_BSTR, VT_I4, VT_R8, VT_BOOL, VT_DISPATCH, VT_BSTR, VT_NULL };
00869                         if(vartypes[vt] != current.vt) {
00870                                 COMTHROW(current.ChangeType(vartypes[vt]));
00871                         }
00872                         CComVariant previous;
00873                         COMTHROW(ITER->get_PreviousAttrValue(aid, &previous));
00874                         if(vartypes[vt] != previous.vt) {
00875                                 COMTHROW(previous.ChangeType(vartypes[vt]));
00876                         }
00877                         if (previous != current) {
00878                                 CComBSTR name;
00879                                 COMTHROW(ma->get_Name(&name));
00880                                 CComBSTR label = "ATTR:";
00881                                 COMTHROW(label.Append(name));
00882                                 CComVariant ident = label;
00883                                 modifications.push_back(ident);
00884                                 modifications.push_back(previous);
00885                         }
00886                 }
00887         }
00888         if (changemask & OBJEVENT_PROPERTIES) {
00889                 CComVariant name = fco->self[ATTRID_NAME];
00890                 CComVariant pname;
00891                 COMTHROW(fco->self->get_PreviousAttrValue(ATTRID_NAME, &pname));
00892                 if (pname != name) {
00893                         CComVariant ident = "PROPERTIES:Name";
00894                         modifications.push_back(ident);
00895                         modifications.push_back(pname);
00896                 }
00897 /* lph: possibly necessary, but not yet
00898                 CComVariant perm = fco->self[ATTRID_PERMISSIONS];
00899                 CComVariant pperm;
00900                 COMTHROW(fco->self->get_PreviousAttrValue(ATTRID_PERMISSIONS, &pperm));
00901                 if (pperm != perm) {
00902                         CComVariant ident = "PROPERTIES:Permissions";
00903                         modifications.push_back(ident);
00904                         modifications.push_back(pperm);
00905                 }
00906 */
00907         }
00908         if (modifications.size() > 0) {
00909                 SAFEARRAY *pVariantsArray = NULL;
00910                 SAFEARRAYBOUND rgsabound[1];
00911                 rgsabound[0].lLbound = 0;
00912                 rgsabound[0].cElements = modifications.size();
00913                 pVariantsArray = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
00914                 for (LONG i=0; i<LONG(modifications.size()); i++) {
00915                         COMTHROW(SafeArrayPutElement(pVariantsArray, &i, &modifications[i]));
00916                 }
00917                 CComVariant varOut;
00918                 varOut.vt = VT_ARRAY | VT_VARIANT;
00919                 varOut.parray = pVariantsArray;
00920                 varOut.Detach(mods);
00921         }
00922         } COMCATCH(;)
00923         return S_OK;
00924 }
00925 //-------------------------------------------------------------------------------------
00926 
00927 HRESULT FCO::objrwnotify() {
00928         COMTRY {
00929                         unsigned long chmask = this->changemask;
00930                         this->changemask = 0;
00931                         // No other notification on deleted objects
00932                         if(chmask & OBJEVENT_DESTROYED) chmask = OBJEVENT_DESTROYED;
00933                         CMgaProject::addoncoll::iterator ai, abeg = mgaproject->alladdons.begin(), aend = mgaproject->alladdons.end();
00934                         if(abeg != aend) {
00935                                 CComVariant mods;
00936                                 if(!(chmask & OBJEVENT_CREATED) && (chmask & (OBJEVENT_REGISTRY+OBJEVENT_ATTR+OBJEVENT_PROPERTIES)))
00937                                         COMTHROW(get_Modifications(this, chmask, &mods));
00938                                 COMTHROW(mgaproject->pushterr(*mgaproject->reserveterr));
00939                                 for(ai = abeg; ai != aend; ) {
00940                                         CComPtr<CMgaAddOn> t = *ai++;   // it is important to incr ii here, while obj 
00941                                                                                                     // still holds a reference to the (*ai) object
00942                                         unsigned long mmask;
00943                                         if((mmask = (t->eventmask & chmask)) != 0) {
00944                                                 CComPtr<IMgaObject> tt;
00945                                                 getinterface(&tt);
00946 
00947                                                 try
00948                                                 {
00949                                                         t->handler->__ObjectEvent(tt, mmask, mods);
00950                                                 }
00951                                                 catch (_com_error& e)
00952                                                 {
00953                                                         if (t->progid.length() == 0)
00954                                                                 throw;
00955                                                         _bstr_t error = e.Description();
00956                                                         if (!error.length())
00957                                                         {
00958                                                                 GetErrorInfo(e.Error(), error.GetAddress());
00959                                                                 if (error.length() == 0)
00960                                                                 {
00961                                                                         error = L"Unknown error";
00962                                                                 }
00963                                                         }
00964                                                         error = _bstr_t(L"Error in Addon '") + t->progid + _bstr_t("'. Addon returned error: ") + error;
00965                                                         SetErrorInfo(error);
00966                                                         _com_issue_errorex(e.Error(), t->handler, __uuidof(t->handler));
00967                                                 }
00968                                             t->notified = true;
00969                                         }
00970                                 }
00971                                 COMTHROW(mgaproject->popterr());
00972                         }
00973                         if(chmask & OBJEVENT_CREATED) {
00974                                 // send message to all territories that contain parent, 
00975                                 CoreObj parent = self[ATTRID_PARENT];
00976                                 // n.b. parent may be null if an addon deleted self and parent
00977                                 if (parent && parent.IsContainer()) {
00978                                         auto objforcore = ObjForCore(parent);
00979                                         FCO &p = *objforcore;
00980                                         
00981                                         // if parent is also new, notify it first
00982                                         if(p.notifymask & OBJEVENT_CREATED) COMTHROW(p.objnotify());
00983 
00984                                         pubfcohash::iterator ii, pbeg = p.pubfcos.begin(), pend = p.pubfcos.end();
00985                                         for(ii = pbeg; ii != pend;) {  
00986                                                 CMgaTerritory *t = (*ii).second->territory;
00987                                                 CComPtr<IMgaObject> obj = (*ii).second;
00988                                                 ++ii;  // it is important to incr ii here, while obj 
00989                                                            // still holds a reference to the (*ii) object
00990                                                 CComVariant dummy;
00991                                                 if(t->rwhandler && (t->eventmask & OBJEVENT_CREATED) != 0) {
00992                                                         COMTHROW(mgaproject->pushterr(*t));
00993                                                         {
00994                                                                 CComPtr<IMgaObject> newoo;
00995                                                                 getinterface(&newoo, t);
00996                                                                 COMTHROW(t->rwhandler->ObjectEvent(newoo, (unsigned long)OBJEVENT_CREATED, dummy));
00997                                                         }
00998                                                         COMTHROW(mgaproject->popterr());
00999                                                         t->notified = true;
01000                                                 }
01001                                         }
01002                                 }
01003                                 chmask &= ~OBJEVENT_CREATED;
01004                         }
01005                         pubfcohash::iterator ii, beg = pubfcos.begin(), end = pubfcos.end();
01006                         for(ii = beg; ii != end;) {  
01007                                 CMgaTerritory *t = (*ii).second->territory;
01008                                 CComVariant &ud = (*ii).second->userdata;
01009                                 CComPtr<IMgaObject> obj = (*ii).second;
01010                                 ++ii;  // it is important to incr ii here, while obj 
01011                                            // still holds a reference to the (*ii) object
01012                                 long mmask;
01013                                 if(t->rwhandler && (mmask = (t->rweventmask & chmask)) != 0) {
01014                                         COMTHROW(mgaproject->pushterr(*t));
01015                                         COMTHROW(t->rwhandler->ObjectEvent(obj, mmask,ud));
01016                                         t->notified = true;
01017                                         COMTHROW(mgaproject->popterr());  // this may release the territory!!!
01018                                 }
01019                         }
01020                         this->temporalmask = 0; // may have been changed during notification (but we won't notify about it)
01021         } COMCATCH(;)
01022 }
01023 
01024 
01025 
01026 
01027 
01028 HRESULT FCO::objnotify() {
01029         if(notifymask == 0) return S_OK;
01030         COMTRY {
01031                         unsigned long chmask = notifymask;
01032                         notifymask = 0;
01033                         // No other notification on deleted objects
01034                         if(chmask & OBJEVENT_DESTROYED) chmask = OBJEVENT_DESTROYED;
01035                         if(chmask & OBJEVENT_CREATED) {
01036                                 // send message to all territories that contain parent, 
01037                                 CoreObj parent = self[ATTRID_PARENT];
01038                                 if(parent.IsContainer()) {
01039                                         auto objforcore = ObjForCore(parent);
01040                                         FCO &p = *objforcore;
01041                                         
01042                                         // if parent is also new, notify it first
01043                                         if(p.notifymask & OBJEVENT_CREATED) COMTHROW(p.objnotify());
01044 
01045                                         pubfcohash::iterator ii, pbeg = p.pubfcos.begin(), pend = p.pubfcos.end();
01046                                         for(ii = pbeg; ii != pend;) {  
01047                                                 CMgaTerritory *t = (*ii).second->territory;
01048                                                 CComPtr<IMgaObject> obj = (*ii).second;
01049                                                 ++ii;  // it is important to incr ii here, while obj 
01050                                                            // still holds a reference to the (*ii) object
01051                                                 CComVariant dummy;
01052                                                 if(t->handler && (t->eventmask & OBJEVENT_CREATED) != 0) {
01053                                                         COMTHROW(mgaproject->pushterr(*t));
01054                                                         {
01055                                                                 CComPtr<IMgaObject> newoo;
01056                                                                 getinterface(&newoo, t);
01057                                                                 if(t->handler->ObjectEvent(newoo, (unsigned long)OBJEVENT_CREATED, dummy) != S_OK) {
01058                                                                         ASSERT(("Notification failed", false));
01059                                                                 }
01060                                                         }
01061                                                         COMTHROW(mgaproject->popterr());
01062                                                         t->notified = true;
01063                                                 }
01064                                         }
01065                                 }
01066                                 chmask &= ~OBJEVENT_CREATED;
01067                         }
01068                         pubfcohash::iterator ii, beg = pubfcos.begin(), end = pubfcos.end();
01069                         for(ii = beg; ii != end;) {  
01070                                 CMgaTerritory *t = (*ii).second->territory;
01071                                 CComVariant &ud = (*ii).second->userdata;
01072                                 CComPtr<IMgaObject> obj = (*ii).second;
01073                                 ++ii;  // it is important to incr ii here, while obj 
01074                                            // still holds a reference to the (*ii) object
01075                                 unsigned long mmask;
01076                                 if(t->handler && (mmask = (t->eventmask & chmask)) != 0) {
01077                                         COMTHROW(mgaproject->pushterr(*t));
01078                                         if(t->handler->ObjectEvent(obj, mmask, ud) != S_OK) {
01079                                                 // FIXME: allow addons to return constraint error, don't silently swallow error
01080                                                 ASSERT(("Notification failed", false));
01081                                         }
01082                                         COMTHROW(mgaproject->popterr());
01083                                         t->notified = true;
01084                                 }
01085                         }
01086                         ASSERT(notifymask == 0);
01087         } COMCATCH(;)
01088 }
01089 
01090 void FCO::objforgetchange() {
01091         temporalmask = 0;
01092 }
01093 
01094 void FCO::objrecordchange() {
01095         ASSERT(temporalmask != 0);
01096         if(!changemask) {
01097                 mgaproject->changedobjs.push(this);
01098         }       
01099         changemask |= temporalmask;
01100 // 
01101         if(!notifymask) {
01102                 mgaproject->notifyobjs.push(this);
01103         }       
01104         notifymask |= temporalmask;
01105         temporalmask = 0;
01106 }
01107 
01108 
01109 HRESULT FCO::SendEvent(long mask) {
01110         COMTRY_IN_TRANSACTION {
01111                 CheckRead();
01112                 if((mask | OBJEVENT_USERBITS) != OBJEVENT_USERBITS) COMTHROW(E_MGA_BAD_MASKVALUE);
01113                 SelfMark(mask);
01114         } COMCATCH_IN_TRANSACTION(;)
01115 }
01116 
01117 void FCO::SelfMark(long newmask) {
01118         ASSERT(("Error: event generated in read-only transaction",!mgaproject->read_only));
01119         ASSERT(newmask);
01120         if(!temporalmask) {
01121                 mgaproject->temporalobjs.push(this);
01122         }       
01123         temporalmask |= (unsigned long)newmask;
01124 }
01125 
01126 void FCO::objsetuserdata(CMgaTerritory *t, VARIANT udata) {
01127                 pubfcohash::iterator i = pubfcos.find(t); 
01128                 if(i == pubfcos.end()) COMTHROW(E_MGA_NOT_IN_TERRITORY);
01129                 (*i).second->userdata = udata;
01130 }
01131 
01132 /*
01133 HRESULT FCO::Associate(VARIANT userdata) {
01134   COMTRY {
01135         CheckDeletedRead();
01136         objsetuserdata(mgaproject->activeterr, userdata);
01137   } COMCATCH(;);
01138 }
01139 
01140 HRESULT FCO::get_CurrentAssociation(VARIANT *userdata) {
01141   COMTRY {
01142         CheckDeletedRead();
01143                 pubfcohash::iterator i = pubfcos.find(mgaproject->activeterr);
01144                 if(i == pubfcos.end()) COMTHROW(E_MGA_NOT_IN_TERRITORY);
01145                 VariantCopy(userdata, &((*i).second->userdata)); 
01146    } COMCATCH(;);
01147 }
01148 */
01149 
01150 HRESULT FCO::Open(openmode mode)  { 
01151         return S_OK;
01152 };
01153 
01154 HRESULT FCO::Close() {
01155         return S_OK;
01156 }
01157 
01158 FCOPtr::FCOPtr(FCOPtr const &o) {
01159         p = o.p;
01160         p->AddRef();
01161 }
01162 
01163 FCOPtr::FCOPtr(FCOPtr&& o) {
01164         p = o.p;
01165         o.p = NULL;
01166 }
01167 
01168 FCOPtr::FCOPtr(FCO *f) {
01169         p = f;
01170         p->AddRef();
01171 }
01172 
01173 FCOPtr::FCOPtr() {
01174         p = NULL;
01175 }
01176 
01177 FCOPtr::~FCOPtr() {
01178         if(p) p->Release();
01179 }
01180 
01181 void FCOPtr::operator= (FCO *f) {       
01182         if(p == f) return;
01183         if(p) p->Release();
01184         p = f;
01185         p->AddRef();
01186 }
01187 
01188 bool FCOPtr::operator< (const FCOPtr &o) const {
01189         return p < o.p;
01190 }
01191 
01192 void CoreObjMark(CoreObj const &ob, long mask) {
01193         ObjForCore(ob)->SelfMark(mask);
01194 }
01195         
01196 HRESULT FCO::GetGuid(long* pl1, long* pl2, long* pl3, long* pl4)
01197 {
01198         COMTRY {
01199                 CheckRead();
01200                 CHECK_OUTPAR( pl1);
01201                 CHECK_OUTPAR( pl2);
01202                 CHECK_OUTPAR( pl3);
01203                 CHECK_OUTPAR( pl4);
01204 
01205                 *pl1 = self[ATTRID_GUID1];
01206                 *pl2 = self[ATTRID_GUID2];
01207                 *pl3 = self[ATTRID_GUID3];
01208                 *pl4 = self[ATTRID_GUID4];
01209 
01210         } COMCATCH(;)
01211 }
01212 
01213 HRESULT FCO::PutGuid( long l1, long l2, long l3, long l4)
01214 {
01215         COMTRY_IN_TRANSACTION {
01216                 CheckWrite();
01217                 //ASSERT( self.IsFCO());
01218                 //if( self.IsFCO()) {
01219                 self[ATTRID_GUID1] = l1;
01220                 self[ATTRID_GUID2] = l2;
01221                 self[ATTRID_GUID3] = l3;
01222                 self[ATTRID_GUID4] = l4;
01223         }  COMCATCH_IN_TRANSACTION(;)
01224 }
01225 
01226 HRESULT FCO::GetGuidDisp( BSTR *p_pGuidStr)
01227 {
01228         // keep logic in sync with LibImgHelper::GetItsGuid() in MgaLibOps.cpp
01229         COMTRY {
01230                 CheckRead();
01231                 CHECK_OUTPAR( p_pGuidStr);
01232                 long v1(0), v2(0), v3(0), v4(0);
01233 
01234                 COMTHROW( this->GetGuid( &v1, &v2, &v3, &v4));
01235 
01236                 GUID t_guid;
01237                 t_guid.Data1 = v1;
01238                 t_guid.Data2 = (v2 >> 16);
01239                 t_guid.Data3 = v2 & 0xFFFF;
01240                 t_guid.Data4[0] = (v3 >> 24);
01241                 t_guid.Data4[1] = (v3 >> 16) & 0xFF;
01242                 t_guid.Data4[2] = (v3 >> 8) & 0xFF;
01243                 t_guid.Data4[3] = v3 & 0xFF;
01244 
01245                 t_guid.Data4[4] = (v4 >> 24);
01246                 t_guid.Data4[5] = (v4 >> 16) & 0xFF;
01247                 t_guid.Data4[6] = (v4 >> 8) & 0xFF;
01248                 t_guid.Data4[7] = v4 & 0xFF;
01249 
01250                 char buff[39];
01251                 sprintf( buff, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
01252                         t_guid.Data1, t_guid.Data2, t_guid.Data3,
01253                         t_guid.Data4[0], t_guid.Data4[1], t_guid.Data4[2], t_guid.Data4[3],
01254                         t_guid.Data4[4], t_guid.Data4[5], t_guid.Data4[6], t_guid.Data4[7]);
01255 
01256                 *p_pGuidStr = CComBSTR( buff).Detach();
01257 
01258         } COMCATCH(;)
01259 }
01260 
01261 HRESULT FCO::PutGuidDisp( BSTR p_guidStr)
01262 {
01263         COMTRY_IN_TRANSACTION {
01264                 CheckWrite();
01265                 CHECK_INSTRPAR( p_guidStr);
01266                 //self[ATTRID_GUID1] = newVal;
01267                 GUID t_guid;
01268                 CopyTo( p_guidStr, t_guid);
01269 
01270                 long v1 = t_guid.Data1; // Data1: 32 b, Data2, Data 3: 16 b, Data4: 64 bit
01271                 long v2 = (t_guid.Data2 << 16) + t_guid.Data3;
01272                 long v3 = (((((t_guid.Data4[0] << 8) + t_guid.Data4[1]) << 8) + t_guid.Data4[2]) << 8) + t_guid.Data4[3];
01273                 long v4 = (((((t_guid.Data4[4] << 8) + t_guid.Data4[5]) << 8) + t_guid.Data4[6]) << 8) + t_guid.Data4[7];
01274 
01275                 PutGuid( v1, v2, v3, v4);
01276         }  COMCATCH_IN_TRANSACTION(;)
01277 }
01278 
01279 #ifdef _ATL_DEBUG_INTERFACES
01280 bool IsQIThunk(IUnknown *p) {
01281         ATL::_QIThunk dummy((IUnknown*)(void*)1, L"dummy", IID_IUnknown, 0, false);
01282 
01283         return *((int**)(void*)p) == *((int**)(void*)&dummy);
01284 }
01285 #endif