GME  13
MgaConnection.cpp
Go to the documentation of this file.
00001 // MgaConnection.cpp : Implementation of CMgaConnection
00002 #include "stdafx.h"
00003 #include "MgaConnection.h"
00004 
00006 // CMgaConnection
00007 const CComBSTR FCO::SrcName="src", FCO::DstName="dst";
00008 
00009 
00010 bool FCO::findroleobj(BSTR rolename, CoreObj &tt) {
00011                         CHECK_INSTRPAR(rolename);
00012                         CoreObjs roles = self[ATTRID_CONNROLE+ATTRID_COLLECTION];
00013                         ITERATE_THROUGH(roles) {
00014                                         CComBSTR n = ITER[ATTRID_NAME];
00015                                         if(n == rolename) {
00016                                                 tt <<= ITER;
00017                                                 return true;
00018                                         }
00019                         }
00020                         return false;
00021 }
00022 
00023 HRESULT FCO::get_NamedRoleReferences(BSTR rolename, IMgaFCOs **pVal) {
00024                 COMTRY {
00025                         CHECK_INSTRPAR(rolename); 
00026                         CHECK_OUTPTRPAR(pVal); 
00027                         CoreObj r;
00028                         if(!findroleobj(rolename, r))
00029                         {
00030                                 COMRETURN(E_MGA_NAME_NOT_FOUND);
00031                         }
00032                         CoreObjs segs = r[ATTRID_CONNSEG+ATTRID_COLLECTION];
00033                         segs.Sort();
00034                         CREATEEXCOLLECTION_FOR(MgaFCO, q);
00035                         ITERATE_THROUGH(segs) {
00036                           CoreObj seg = ITER[ATTRID_SEGREF];
00037                           ASSERT(seg);
00038                           CComPtr<IMgaFCO> ff;
00039                       ObjForCore(seg)->getinterface(&ff);
00040                           q->Add(ff);
00041                         }
00042                         *pVal = q.Detach();
00043                 } COMCATCH(;)
00044 }
00045         
00046 HRESULT FCO::get_NamedRoleTarget(BSTR rolename, IMgaFCO **pVal) {
00047                 COMTRY {
00048                         CHECK_INSTRPAR(rolename); 
00049                         CHECK_OUTPTRPAR(pVal); 
00050                         CoreObj r;
00051                         if(findroleobj(rolename, r)) { 
00052                                 CoreObj obj = r[ATTRID_XREF];
00053                                 if(obj) {
00054                                         ObjForCore(obj)->getinterface(pVal);
00055                                 }
00056                         }
00057                 } COMCATCH(;)
00058 }       
00059 
00060 
00061 HRESULT FCO::put_NamedRole(BSTR rolename,  IMgaFCOs *refs, IMgaFCO *endfco) {
00062         COMTRY_IN_TRANSACTION_MAYBE {
00063                         CheckWrite();
00064                         {
00065                                 booltempflag fl(mgaproject->checkofftemporary);
00066                                         
00067                                 CComPtr<IMgaConnPoints> p;
00068                                 COMTHROW(get_ConnPoints(&p)); 
00069                                 MGACOLL_ITERATE(IMgaConnPoint, p) {
00070                                         CComBSTR rn;
00071                                         COMTHROW(MGACOLL_ITER->get_ConnRole(&rn));
00072                                         if(rn == rolename) {
00073                                                 COMTHROW(MGACOLL_ITER->Remove());
00074                                                 break;
00075                                         }
00076                                 } MGACOLL_ITERATE_END;
00077                         }
00078                         if(endfco) {
00079                                 CComPtr<IMgaConnPoint> tt;
00080                                 COMRETURN_IN_TRANSACTION_MAYBE(AddConnPoint(rolename, 1, endfco, refs, &tt));
00081                         }
00082         } COMCATCH_IN_TRANSACTION_MAYBE(;)
00083 }       
00084 
00085 HRESULT FCO::CreateSimpleConn( IMgaMetaRole *metar,  IMgaFCO *src,  IMgaFCO *dst, 
00086                                                                                  IMgaFCOs *srcrefs, IMgaFCOs *dstrefs, IMgaFCO **newobj) {
00087         COMTRY_IN_TRANSACTION {
00088 
00089                 CComPtr<IMgaFCO> f;
00090                 {
00091                         booltempflag fl(mgaproject->checkofftemporary);
00092                         COMTHROW(CreateChildObject(metar, &f));
00093                         objtype_enum ot;
00094                         COMTHROW(f->get_ObjType(&ot));
00095                         if(ot != OBJTYPE_CONNECTION) COMTHROW(E_MGA_INVALID_ROLE);
00096                         COMTHROW(ObjFor(f)->put_NamedRole(SrcName,  srcrefs, src));
00097                 }       
00098                 COMTHROW(ObjFor(f)->put_NamedRole(DstName,  dstrefs, dst));
00099                 *newobj = f.Detach();
00100         } COMCATCH_IN_TRANSACTION(;)
00101 }
00102 
00103 static CComPtr<IMgaFCOs> GetRefChain(IMgaFCO* fco)
00104 {
00105         CREATEEXCOLLECTION_FOR(MgaFCO, srcrefs);
00106 
00107         CComQIPtr<IMgaReference> ref = fco;
00108         while (srcrefs && ref)
00109         {
00110                 srcrefs->Add(ref);
00111                 CComPtr<IMgaFCO> referred;
00112                 COMTHROW(ref->get_Referred(&referred));
00113                 if (referred)
00114                 {
00115                         ref.Release();
00116                         ref = referred;
00117                 }
00118         }
00119         return CComQIPtr<IMgaFCOs>(srcrefs);
00120 }
00121 
00122 HRESULT FCO::CreateSimpleConnDisp( IMgaMetaRole *metar
00123                                   , IMgaFCO *srcobj, IMgaFCO *dstobj
00124                                   , IMgaFCO *srcref, IMgaFCO *dstref
00125                                   , IMgaFCO **newobj) 
00126 {
00127         return CreateSimpleConn( metar, srcobj, dstobj, GetRefChain(srcref), GetRefChain(dstref), newobj);
00128 }
00129 
00130 
00131 /* ******************** CONNPOINT ********************************* */
00132 
00133 void CMgaConnPoint::GetConnPoint(FCO *f, CoreObj &c, IMgaConnPoint **cp) {
00134         ASSERT(GetMetaID(c) == DTID_CONNROLE);
00135         FCO::cphash::iterator ii;
00136         objid_type ll = c.GetObjID();
00137         if((ii = f->connpointhash.find(ll)) != f->connpointhash.end()) {
00138                 (*cp = (*ii).second)->AddRef();
00139         }
00140         else {
00141                 CComPtr<CMgaConnPoint> p; 
00142                 CreateComObject(p);
00143 #ifdef DEBUG
00144                 p->MARKSIG('1');
00145 #endif
00146                 p->fco = f;
00147                 p->cobj = c;
00148                 f->connpointhash.insert(FCO::cphash::value_type(ll, p));
00149                 *cp = p.Detach();
00150         }
00151 }
00152 
00153 
00154 CMgaConnPoint::~CMgaConnPoint() {
00155         MARKSIG('9');
00156         // n.b. don't use GetObjId, it can COMTHROW when the project is closed
00157         objid_type t;
00158         HRESULT hr = cobj->get_ObjID(&t);
00159         if (SUCCEEDED(hr)) {
00160                 FCO::cphash::iterator ii = fco->connpointhash.find(t);
00161                 ASSERT(ii != fco->connpointhash.end());
00162                 fco->connpointhash.erase(ii);
00163         }
00164 }       
00165 
00166 
00167 // the peers array is used in a tricky way here. 
00168 // the first peercnt-2 members (if any) are references for connsegments
00169 // the peer before the last is the target
00170 // the last peer points back to the master object of the new connpoint
00171 //    (it is protected by endreserve, and updated manually below)
00172 
00173 bool AddConnPTask::Do(CoreObj self, std::vector<CoreObj> *peers) {
00174         CoreObj role;
00175         CMgaProject *mgaproject = ObjForCore(self)->mgaproject;
00176         if(maxinrole > 0) {
00177                 long rolesofname = 0;
00178                 ITERATE_THROUGH(self[ATTRID_CONNROLE+ATTRID_COLLECTION]) {
00179                         if(rolename == CComBSTR(ITER[ATTRID_NAME])) rolesofname++;
00180                 }
00181                 if(rolesofname >= maxinrole) {
00182                         if(!(*peers)[peercnt-1]) {  // if this is the master connection
00183                                 COMTHROW(E_MGA_CONNROLE_USED);  // indicate error
00184                         }
00185                         return false;                      // ... else silently ignore it
00186                 }
00187         }
00188         COMTHROW(mgaproject->dataproject->CreateObject(DTID_CONNROLE,&role.ComPtr()));
00189         role[ATTRID_NAME] = rolename;
00190         role[ATTRID_CONNROLE] = self;
00191         role[ATTRID_XREF] = (*peers)[peercnt-2];
00192         role[ATTRID_MASTEROBJ] = (*peers)[peercnt-1];
00193         for(int i = 0; i < peercnt-2; i++) {
00194                 CoreObj seg;
00195                 COMTHROW(mgaproject->dataproject->CreateObject(DTID_CONNROLESEG,&seg.ComPtr()));
00196                 seg[ATTRID_CONNSEG] = role;
00197                 seg[ATTRID_SEGORDNUM] = i+1;
00198                 seg[ATTRID_SEGREF] = (*peers)[i];
00199         }
00200 
00201         if( peercnt-2 >= 1) // additional check
00202         {
00203                 CoreObj last_ref = (*peers)[peercnt - 3];
00204                 CoreObj tgt_model= last_ref[ATTRID_REFERENCE];
00205                 if (!last_ref.p)
00206                         throw_com_error(E_MGA_INVALID_ARG, L"Cannot add refport to null reference");
00207                 CoreObj tgt_elem = (*peers)[peercnt - 2];
00208                 CoreObj parent   = tgt_elem[ATTRID_FCOPARENT];
00209                 CoreObj bas_model= tgt_model[ATTRID_DERIVED]; // tgt_model must be a derived for GetDerivedEquivalent to succeed
00210                 if( !COM_EQUAL(parent, tgt_model) && bas_model) { // JIRA:130?
00211                         CoreObj new_tgt_elem;
00212                         GetDerivedEquivalent( tgt_elem, tgt_model, new_tgt_elem);
00213                         if( new_tgt_elem) // found tgt_elem's equivalent in tgt_model
00214                                 role[ATTRID_XREF] = new_tgt_elem; // overwrite the previous value: (*peers)[peercnt-2];
00215                 }
00216         }
00217 
00218         IMgaObjectPtr iObject;
00219         ObjForCore(self)->getinterface(&iObject, 0);
00220         iObject->__Check();
00221         ObjForCore((*peers)[0])->SelfMark(OBJEVENT_CONNECTED);
00222         ObjForCore(self)->SelfMark(OBJEVENT_RELATION);
00223         (*peers)[peercnt-1] = role;
00224         return true;
00225 }
00226 
00227 HRESULT FCO::AddConnPoint(BSTR rolename, long maxinrole, IMgaFCO *target, IMgaFCOs *refs, IMgaConnPoint **pVal) {
00228         COMTRY_IN_TRANSACTION_MAYBE {
00229            CheckWrite();
00230            long c = 0;
00231            if(refs) COMTHROW(refs->get_Count(&c));
00232            std::vector<CoreObj> peers(c+2);
00233            CHECK_INSTRPAR(rolename);
00234            CHECK_MYINPTRPAR(target);
00235            CHECK_OUTPTRPAR(pVal);
00236            int pos = 0;
00237            if(refs) {
00238                    CHECK_MYINPTRSPAR(refs);
00239 
00240                    MGACOLL_ITERATE(IMgaFCO, refs) {
00241                            CoreObj l(MGACOLL_ITER);
00242                            if(l.GetMetaID() != DTID_REFERENCE) COMTHROW(E_MGA_REFERENCE_EXPECTED);
00243                            peers[pos++] = l;
00244                    } MGACOLL_ITERATE_END;
00245            } 
00246            peers[pos++] = CoreObj(target);
00247            peers[pos] = NULLCOREOBJ;            
00248            AddConnPTask(maxinrole, rolename).DoWithDeriveds(self, &peers);
00249            CMgaConnPoint::GetConnPoint(this, peers[pos], pVal);
00250         } COMCATCH_IN_TRANSACTION_MAYBE(;);
00251 }
00252 
00253 HRESULT FCO::get_ConnPoints(IMgaConnPoints **pVal) {
00254         CREATECOLLECTION_FOR(IMgaConnPoint, q);
00255         COMTRY {
00256                 CoreObjs roles = self[ATTRID_CONNROLE + ATTRID_COLLECTION];
00257                 ITERATE_THROUGH(roles) {
00258                         CComPtr<IMgaConnPoint> p;
00259                         CMgaConnPoint::GetConnPoint(this, ITER, &p);
00260                         q->Add(p);
00261                 }
00262                 *pVal = q.Detach();
00263         } COMCATCH(;);
00264 }
00265 
00266 
00267 STDMETHODIMP CMgaConnPoint::get_Owner(IMgaConnection **pVal) {
00268         COMTRY { 
00269                 CHECK_OUTPTRPAR(pVal);
00270                 ObjForCore(CoreObj(cobj[ATTRID_CONNROLE]))->getinterface(pVal);
00271         } COMCATCH(;);
00272 }
00273 
00274 STDMETHODIMP CMgaConnPoint::get_ConnRole(BSTR *pVal) {
00275         COMTRY {
00276                 CHECK_OUTSTRPAR(pVal);
00277                 *pVal = CComBSTR(cobj[ATTRID_NAME]).Detach();
00278         } COMCATCH(;);
00279 }
00280 
00281 
00282 
00283 
00284 class put_ConnRoleTask : public DeriveTreeTask {
00285         CComBSTR newrname;
00286 
00287         bool Do(CoreObj self, std::vector<CoreObj> *peers = NULL) {
00288                 self[ATTRID_NAME] = newrname;
00289                 COMTHROW(ObjForCore(CoreObj(self[ATTRID_CONNROLE]))->Check());
00290                 return true;
00291         }
00292 
00293 public:
00294         put_ConnRoleTask(BSTR nname) : newrname(nname) { ; }
00295 };
00296 
00297 
00298 STDMETHODIMP CMgaConnPoint::put_ConnRole(BSTR newVal) {
00299         CMgaProject *mgaproject = fco->mgaproject;
00300         COMTRY_IN_TRANSACTION {
00301                 CHECK_INSTRPAR(newVal);
00302                 fco->CheckWrite();
00303                 //if(CComBSTR( cobj[ATTRID_NAME] ) = newVal) ... //zolmol: rewritten for VC7
00304                 //if( (CComBSTR) cobj[ATTRID_NAME] = newVal) ... // also would be ok for vc7
00305                 if( newVal) { // ... but this is more clear
00306                         // FIXME: doesn't look good; we don't need a & ?
00307                         (CComBSTR) cobj[ATTRID_NAME] = newVal;
00308                         cobj[ATTRID_MASTEROBJ] = NULLCOREOBJ;
00309                         put_ConnRoleTask(newVal).DoWithDeriveds(cobj);
00310                 }
00311         } COMCATCH_IN_TRANSACTION(;);
00312 }
00313 
00314 STDMETHODIMP CMgaConnPoint::get_Target(IMgaFCO **pVal) {
00315         COMTRY { 
00316                 CHECK_OUTPTRPAR(pVal);
00317                 CoreObj t = cobj[ATTRID_XREF];
00318                 ASSERT(t);
00319                 ObjForCore(t)->getinterface(pVal);
00320         } COMCATCH(;);
00321 }
00322 
00323 STDMETHODIMP CMgaConnPoint::get_References(IMgaFCOs **pVal) {
00324         COMTRY { 
00325                 CHECK_OUTPTRPAR(pVal);
00326                 CoreObjs refs = cobj[ATTRID_CONNSEG + ATTRID_COLLECTION];
00327                 refs.Sort();
00328                 CREATEEXCOLLECTION_FOR(MgaFCO, q);
00329                 ITERATE_THROUGH(refs) {
00330                         CComPtr<IMgaFCO> p;
00331                         CoreObj t = ITER[ATTRID_SEGREF];
00332                         ASSERT(t);
00333                         ObjForCore(t)->getinterface(&p);
00334                         q->Add(p);
00335                 }
00336                 *pVal = q.Detach();
00337         } COMCATCH(;);
00338 }
00339 
00340 
00341 void SingleObjTreeDelete(CoreObj &self, bool deleteself = true);
00342 
00343 
00344 void MgaConnPointDelete(CoreObj& cobj)
00345 {
00346                 CoreObj fco = cobj[ATTRID_CONNROLE];
00347                 CoreObj target = cobj[ATTRID_XREF];
00348                 CoreObjs children = cobj[ATTRID_MASTEROBJ + ATTRID_COLLECTION];
00349                 ITERATE_THROUGH(children)
00350                 {
00351                         MgaConnPointDelete(ITER);
00352                 }
00353                 SingleObjTreeDelete(cobj);
00354                 ObjForCore(fco)->SelfMark(OBJEVENT_RELATION);
00355                 ObjForCore(target)->SelfMark(OBJEVENT_DISCONNECTED);
00356 }
00357 
00358 STDMETHODIMP CMgaConnPoint::Remove() {
00359         CMgaProject *mgaproject = fco->mgaproject;
00360         COMTRY_IN_TRANSACTION {
00361                 fco->CheckWrite();
00362 
00363                 CoreObj fco = cobj[ATTRID_CONNROLE];
00364                 MgaConnPointDelete(cobj);
00365                 COMTHROW(ObjForCore(fco)->Check());
00366         } COMCATCH_IN_TRANSACTION(;);
00367 }
00368 
00369 
00370 // get conn points pointed at by this object
00371 HRESULT FCO::get_PartOfConns(IMgaConnPoints **pVal) {
00372                 COMTRY {
00373                         CheckRead();
00374                         CHECK_OUTPTRPAR(pVal);
00375                         CoreObjs segs = self[ATTRID_XREF+ATTRID_COLLECTION];
00376                         CREATECOLLECTION_FOR(IMgaConnPoint, q);
00377                         ITERATE_THROUGH(segs) {
00378                                 if(GetMetaID(ITER) != DTID_CONNROLE) continue;
00379                                 CoreObj conn = ITER[ATTRID_CONNROLE];
00380                                 CComPtr<IMgaConnPoint> p;
00381                             CMgaConnPoint::GetConnPoint(ObjForCore(conn), ITER, &p);
00382                                 q->Add(p); 
00383                         }
00384                         *pVal = q.Detach();
00385                 } COMCATCH(;)
00386 }
00387 
00388 
00389 // get conn points running through this reference
00390 HRESULT FCO::get_UsedByConns(IMgaConnPoints **pVal) {
00391                 COMTRY {
00392                         CheckRead();
00393                         CHECK_OUTPTRPAR(pVal);
00394                         CoreObjs segs = self[ATTRID_SEGREF+ATTRID_COLLECTION];
00395                         CREATECOLLECTION_FOR(IMgaConnPoint, q);
00396                         ITERATE_THROUGH(segs) {
00397                                 CoreObj connrole = ITER[ATTRID_CONNSEG];
00398                                 ASSERT(connrole);
00399                                 CoreObj conn = connrole[ATTRID_CONNROLE];
00400                                 CComPtr<IMgaConnPoint> p;
00401                             CMgaConnPoint::GetConnPoint(ObjForCore(conn), connrole, &p);
00402                                 q->Add(p); 
00403                         }
00404                         *pVal = q.Detach();
00405                 } COMCATCH(;)
00406 }
00407 
00408 HRESULT FCO::ConnCompareToBase(IMgaConnPoint *p, short *status) { 
00409         COMTRY {
00410                 CheckRead();
00411                 if(p) {
00412                         CComPtr<IMgaConnection> z;
00413                         COMTHROW(p->get_Owner(&z));
00414                         CHECK_MYINPTRPAR(z); 
00415                 }
00416                 CHECK_OUTPAR(status);
00417                 CoreObj base = self[ATTRID_DERIVED];
00418                 if(!base) COMTHROW(E_MGA_NOT_DERIVED);
00419 
00420                 if(p) {
00421                         CoreObj l = static_cast<CMgaConnPoint *>(p)->cobj;
00422                         *status = CoreObj(l[ATTRID_MASTEROBJ]) ? 0 : 1;
00423                 }
00424                 else {
00425                         CoreObjs cpoints = self[ATTRID_CONNROLE + ATTRID_COLLECTION];
00426                         *status = 1;
00427                         ITERATE_THROUGH(cpoints) {
00428                                 if(!CoreObj(ITER[ATTRID_MASTEROBJ])) break;
00429                         }
00430                         if(!ITER_BROKEN) *status = 0;
00431                 }
00432         } COMCATCH(;);
00433 }
00434 
00435 
00436 HRESULT FCO::ConnRevertToBase(IMgaConnPoint *p)  { 
00437         COMTRY_IN_TRANSACTION {
00438                 CheckWrite();
00439                 if(p) {
00440                         CComPtr<IMgaConnection> z;
00441                         COMTHROW(p->get_Owner(&z));
00442                         CHECK_MYINPTRPAR(z); 
00443                 }
00444                 CoreObj base = self[ATTRID_DERIVED];
00445                 if(!base) COMTHROW(E_MGA_NOT_DERIVED);
00446 
00447                 if(p) {
00448                         COMTHROW(E_MGA_NOT_IMPLEMENTED);
00449                 }
00450                 else {
00451                         std::set<CoreObj> vv;
00452                         {
00453                                 ITERATE_THROUGH(self[ATTRID_CONNROLE + ATTRID_COLLECTION]) {
00454                                         if (CoreObj(ITER[ATTRID_MASTEROBJ]))
00455                                                 vv.insert(ITER[ATTRID_MASTEROBJ]);
00456                                         else
00457                                                 MgaConnPointDelete(ITER);
00458                                 }
00459                         }
00460                         ITERATE_THROUGH(base[ATTRID_CONNROLE + ATTRID_COLLECTION]) {
00461                                 if(vv.find(ITER) == vv.end()) {
00462                                                 coreobjpairhash crealist;
00463                                                 CoreObj newcoreobj;
00464                                                 ObjTreeDerive(mgaproject, ITER, newcoreobj, crealist, 0);  // copy
00465                                                 newcoreobj[ATTRID_CONNROLE] = self;
00466                                                 int level;
00467                                                 CoreObj rfco;
00468                                                 GetRootOfDeriv(base, rfco, &level);
00469                                                 ObjTreeReconnect(newcoreobj, crealist, self.FollowChain(ATTRID_FCOPARENT, level));                      
00470                                 }
00471                         }
00472                 }
00473         } COMCATCH_IN_TRANSACTION(;);
00474 }
00475