GME  13
MgaReference.cpp
Go to the documentation of this file.
00001 // MgaReference.cpp : Implementation of CMgaReference
00002 #include "stdafx.h"
00003 #include "Mga.h"
00004 #include "MgaReference.h"
00005 
00006 
00008 // CMgaReference
00009 
00010 
00011 HRESULT FCO::CreateReference( IMgaMetaRole *meta,  IMgaFCO *target,  IMgaFCO **newobj) {
00012         COMTRY_IN_TRANSACTION {
00013                 CheckWrite();
00014                 CHECK_INPTRPAR(meta);
00015                 CHECK_MYINPTRPARVALIDNULL(target);
00016                 CHECK_OUTPTRPAR(newobj);
00017 // parameters will be checked by functions called 
00018                 CComPtr<IMgaFCO> nobj;
00019                 {
00020                         booltempflag fl(mgaproject->checkofftemporary);
00021                         COMTHROW(CreateChildObject(meta,&nobj));
00022                         objtype_enum ot;
00023                         COMTHROW(nobj->get_ObjType(&ot));
00024                         if(ot != OBJTYPE_REFERENCE) COMTHROW(E_MGA_INVALID_ROLE);
00025                 }
00026                 COMTHROW(ObjFor(nobj)->put_Referred(target));
00027                 *newobj = nobj.Detach();
00028         } COMCATCH_IN_TRANSACTION(mgaproject->checkofftemporary = false;);
00029 }
00030 
00031 
00032 HRESULT FCO::get_Referred(IMgaFCO **pVal) {
00033                 COMTRY {
00034                         CheckRead();
00035                         CHECK_OUTPTRPAR(pVal);
00036                         CoreObj retval;
00037                         retval = self[ATTRID_REFERENCE];
00038                         if(retval) ObjForCore(retval)->getinterface(pVal);
00039                 } COMCATCH(;)
00040 }
00041 
00042 bool putreftask::Do(CoreObj self, std::vector<CoreObj> *peers) {
00043         CoreObj t = self[ATTRID_REFERENCE];
00044         if(!COM_EQUAL(t, (*peers)[0])) {
00045                 if(t) {
00046                         CoreObjs segs = self[ATTRID_SEGREF + ATTRID_COLLECTION];
00047                         if(segs.Count()) COMTHROW(E_MGA_REFPORTS_USED);
00048                         ObjForCore(t)->SelfMark(OBJEVENT_REFRELEASED);
00049                 }
00050                 t = (*peers)[0];
00051                 self[ATTRID_REFERENCE] = t;
00052                 if(t) ObjForCore(t)->SelfMark(OBJEVENT_REFERENCED);
00053                 ObjForCore(self)->SelfMark(OBJEVENT_RELATION);
00054                 COMTHROW(ObjForCore(self)->Check());
00055 
00056                 ITERATE_THROUGH(self[ATTRID_DERIVED + ATTRID_COLLECTION])
00057                 {
00058                         if (!static_cast<CoreObj>(ITER[ATTRID_MASTEROBJ]))
00059                         {
00060                                 COMTHROW(ObjForCore(ITER)->Check());
00061                         }
00062                 }
00063         }
00064         return true;
00065 }
00066 
00067 
00068 HRESULT FCO::put_Referred(IMgaFCO *newVal)      {
00069                 // Inherited ref can only refer to a derived instance of the target
00070                 // of its base. This is checked in FCO::CheckRCS
00071                 COMTRY_IN_TRANSACTION_MAYBE {
00072                         CheckWrite();
00073                         CHECK_MYINPTRPARVALIDNULL(newVal);
00074                         std::vector<CoreObj> peer(1);
00075                         peer[0] = CoreObj(newVal);
00076                         CoreObj t = self[ATTRID_REFERENCE];
00077 
00078                         // FIXME: this is suspect; it makes ref.Referred = ref.Referred a mutating operation (i.e. => CompareToBase() == true)
00079                         // fix: if(!COM_EQUAL(t, peer[0])) {
00080                         self[ATTRID_MASTEROBJ] = NULLCOREOBJ;
00081                         putreftask(false).DoWithDeriveds(self, &peer);
00082                 } COMCATCH_IN_TRANSACTION_MAYBE(;);
00083 }
00084 
00085 HRESULT FCO::get_RefAspect(IMgaMetaAspect **pVal)
00086 {
00087         COMTRY {
00088                 CHECK_OUTPTRPAR(pVal);
00089                 metaref_type t = self[ATTRID_REFASPECT];
00090                 if(t) {
00091                         CComQIPtr<IMgaMetaAspect> metaa = mgaproject->FindMetaRef(t);
00092                         *pVal = metaa.Detach();
00093                 }
00094         } COMCATCH(;);
00095 }
00096 
00097 HRESULT FCO::put_RefAspect(IMgaMetaAspect *newVal)
00098 {
00099         COMTRY_IN_TRANSACTION {
00100                 CHECK_INPTRPAR(newVal);
00101                 metaref_type t = METAREF_NULL;
00102                 if(newVal) COMTHROW(newVal->get_MetaRef(&t));
00103                 self[ATTRID_REFASPECT] = t;
00104         } COMCATCH_IN_TRANSACTION(;);
00105 
00106 }
00107 
00108 
00109 // get references pointing to this object
00110 HRESULT FCO::get_ReferencedBy(IMgaFCOs **pVal) {
00111                 COMTRY {
00112                         CheckRead();
00113                         CHECK_OUTPTRPAR(pVal);
00114                         CoreObjs segs = self[ATTRID_REFERENCE+ATTRID_COLLECTION];
00115                         CREATEEXCOLLECTION_FOR(MgaFCO, q);
00116                         ITERATE_THROUGH(segs) {
00117                                 CComPtr<IMgaFCO> ffco;
00118                                 ObjForCore(ITER)->getinterface(&ffco);
00119                                 q->Add(ffco); 
00120                         }
00121                         *pVal = q.Detach();
00122                 } COMCATCH(;)
00123 }       
00124 
00125 
00126 HRESULT FCO::RefCompareToBase(short *status) { 
00127         COMTRY {
00128                 CHECK_INPAR(status);
00129                 CoreObj base = self[ATTRID_DERIVED];
00130                 if(!base) COMTHROW(E_MGA_NOT_DERIVED);
00131                 if(CoreObj(self[ATTRID_MASTEROBJ])) *status = 0;
00132                 else *status = 1;
00133         } COMCATCH(;);
00134 }
00135 
00136 
00137 HRESULT FCO::RefRevertToBase()  { 
00138         COMTRY_IN_TRANSACTION { 
00139                 CheckWrite();
00140                 CoreObj base = self[ATTRID_DERIVED];
00141                 if (!base)
00142                         COMTHROW(E_MGA_NOT_DERIVED);
00143                 std::vector<CoreObj> peer(1);
00144                 CoreObj rb;
00145                 int d;
00146                 GetRootOfDeriv(base, rb, &d);
00147                 CoreObj subt = self.FollowChain(ATTRID_FCOPARENT,d);
00148 //  if it is external in the most original base, the target must be kept the same
00149                 bool isinternal = IsInternalRelation(base);
00150                 if (isinternal) {
00151                         GetDerivedEquivalent(base[ATTRID_REFERENCE], subt, peer[0]);
00152                 }
00153                 else {
00154                         peer[0] = base[ATTRID_REFERENCE];
00155                 }
00156                 self[ATTRID_MASTEROBJ] = base;
00157                 putreftask(!isinternal).DoWithDeriveds(self, &peer);
00158         } COMCATCH_IN_TRANSACTION(;);
00159 }
00160