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