GME
13
|
00001 // 00002 // MgaDeriveInfoOps.cpp : Implementation of FCO Derive dependency operations 00003 // 00004 #include "stdafx.h" 00005 #include "MgaFCO.h" 00006 00007 // ---------------------------------------- 00008 // Derive information 00009 // ---------------------------------------- 00010 HRESULT FCO::GetBaseType(IMgaFCO ** basetype, IMgaFCO ** immbase, VARIANT_BOOL *isinst) { 00011 COMTRY { 00012 CheckRead(); 00013 CHECK_OUTPTRPARVALIDNULL(basetype) 00014 CHECK_OUTPTRPARVALIDNULL(immbase) 00015 if(isinst) { 00016 get_IsInstance(isinst); 00017 } 00018 if(basetype || immbase) { 00019 CoreObj base = self[ATTRID_DERIVED]; 00020 if(base) { 00021 if(immbase) { ObjForCore(base)->getinterface(immbase); } 00022 if(basetype) { 00023 while(self[ATTRID_PERMISSIONS] & INSTANCE_FLAG) { 00024 base = base[ATTRID_DERIVED]; 00025 ASSERT(base); 00026 } 00027 ObjForCore(base)->getinterface(basetype); 00028 } 00029 } 00030 else { 00031 if(immbase) *immbase = NULL; 00032 if(basetype) *basetype = NULL; 00033 } 00034 } 00035 } COMCATCH( if(immbase) *immbase = NULL; ) 00036 } 00037 00038 00039 HRESULT FCO::get_DerivedFrom( IMgaFCO **pVal) { 00040 COMTRY { 00041 CheckRead(); 00042 CHECK_OUTPTRPAR(pVal); 00043 CoreObj d = self[ATTRID_DERIVED]; 00044 if(d) ObjForCore(d)->getinterface(pVal); 00045 } COMCATCH(; ) 00046 } 00047 00048 HRESULT FCO::get_DerivedObjects( IMgaFCOs **pVal) { 00049 COMTRY { 00050 CheckRead(); 00051 CREATEEXCOLLECTION_FOR(MgaFCO, q); 00052 CoreObjs d = self[ATTRID_DERIVED+ATTRID_COLLECTION]; 00053 ITERATE_THROUGH(d) { 00054 CComPtr<IMgaFCO> p; 00055 ObjForCore(ITER)->getinterface(&p); 00056 q->Add(p); 00057 } 00058 *pVal = q.Detach(); 00059 } COMCATCH(; ) 00060 } 00061 00062 HRESULT FCO::get_Type( IMgaFCO **pVal) { 00063 COMTRY { 00064 CheckRead(); 00065 CHECK_OUTPTRPAR(pVal); 00066 ; 00067 if(!(self[ATTRID_PERMISSIONS] & INSTANCE_FLAG)) COMTHROW(E_MGA_NOT_INSTANCE); 00068 CoreObj d = self[ATTRID_DERIVED], d2; 00069 if(d) { 00070 while((d2 = d[ATTRID_DERIVED]) != NULL) d <<= d2; 00071 ObjForCore(d)->getinterface(pVal); 00072 } 00073 } COMCATCH(; ) 00074 } 00075 00076 HRESULT FCO::get_BaseType( IMgaFCO **pVal) { 00077 COMTRY { 00078 CheckRead(); 00079 CHECK_OUTPTRPAR(pVal); 00080 if(self[ATTRID_PERMISSIONS] & INSTANCE_FLAG) COMTHROW(E_MGA_INSTANCE); 00081 CoreObj d = self[ATTRID_DERIVED]; 00082 if(d) ObjForCore(d)->getinterface(pVal); 00083 } COMCATCH(; ) 00084 } 00085 00086 HRESULT FCO::get_ArcheType( IMgaFCO **pVal) { 00087 COMTRY { 00088 CheckRead(); 00089 CHECK_OUTPTRPAR(pVal); 00090 CoreObj d = self[ATTRID_DERIVED], d2; 00091 if(d) { 00092 while((d2 = d[ATTRID_DERIVED]) != NULL) d <<= d2; 00093 ObjForCore(d)->getinterface(pVal); 00094 } 00095 } COMCATCH(; ) 00096 } 00097 00098 HRESULT FCO::get_IsInstance( VARIANT_BOOL *pVal) { 00099 COMTRY { 00100 CheckRead(); 00101 CHECK_OUTPAR(pVal); 00102 *pVal = self[ATTRID_PERMISSIONS] & INSTANCE_FLAG ? VARIANT_TRUE : VARIANT_FALSE; 00103 } COMCATCH(; ) 00104 } 00105 00106 HRESULT FCO::get_IsLibObject( VARIANT_BOOL *pVal) { 00107 COMTRY { 00108 CheckRead(); 00109 CHECK_OUTPAR(pVal); 00110 *pVal = self[ATTRID_PERMISSIONS] & LIBRARY_FLAG ? VARIANT_TRUE : VARIANT_FALSE; 00111 } COMCATCH(; ) 00112 } 00113 00114 HRESULT FCO::get_IsPrimaryDerived( VARIANT_BOOL *pVal) { 00115 COMTRY { 00116 CheckRead(); 00117 CHECK_OUTPAR(pVal); 00118 CoreObj d = self[ATTRID_DERIVED]; 00119 if(d && self[ATTRID_RELID] < RELIDSPACE) { 00120 *pVal = VARIANT_TRUE; 00121 } 00122 else *pVal = VARIANT_FALSE; 00123 } COMCATCH(; ) 00124 } 00125 00126 00127 HRESULT FCO::get_AllBaseTypes(IMgaFCOs **bases) { // retuns itself if root model 00128 COMTRY { 00129 CoreObj cur = self; 00130 CREATEEXCOLLECTION_FOR(MgaFCO, q); 00131 while(GetMetaID(cur) != DTID_FOLDER) { 00132 if(cur[ATTRID_RELID] < RELIDSPACE) { 00133 CoreObj base = cur[ATTRID_DERIVED]; 00134 if(base) { 00135 CComPtr<IMgaFCO> ff; 00136 ObjForCore(base)->getinterface(&ff); 00137 q->Add(ff); 00138 } 00139 } 00140 cur = cur[ATTRID_FCOPARENT]; 00141 ASSERT(cur); 00142 } 00143 *bases = q.Detach(); 00144 } COMCATCH(;) 00145 } 00146 00147 00148 HRESULT FCO::get_ChildDerivedFrom(IMgaFCO *baseobj, IMgaFCO **pVal) { 00149 COMTRY { 00150 CHECK_MYINPTRPAR(baseobj); 00151 CHECK_OUTPTRPAR(pVal); 00152 CoreObj bchild(baseobj); 00153 CoreObj bparent = self[ATTRID_DERIVED]; 00154 if(!bparent || !COM_EQUAL(bparent, CoreObj(bchild[ATTRID_FCOPARENT]))) COMTHROW(E_MGA_NOT_DERIVED); 00155 CoreObj selfchild; 00156 GetDerivedEquivalent(bchild, self, selfchild, 1); 00157 if(!selfchild) COMTHROW(E_MGA_META_VIOLATION); 00158 ObjForCore(selfchild)->getinterface(pVal); 00159 } COMCATCH(;) 00160 } 00161 00162 00163 00164 // ---------------------------------------- 00165 // NON-members that use CoreObjs 00166 // ---------------------------------------- 00167 00168 // check if the original master of this relation is internal or external 00169 // does not check the internality of references within connections! 00170 bool IsInternalRelation(CoreObj src) { 00171 CoreObj m; 00172 while((m = src.GetMaster()) != NULL) src = m; 00173 attrid_type a = 0; 00174 switch(src.GetMetaID()) { 00175 case DTID_REFERENCE: a = ATTRID_REFERENCE; break; 00176 case DTID_CONNROLE: a = ATTRID_XREF; break; 00177 case DTID_SETNODE: a = ATTRID_XREF; break; 00178 case DTID_REFATTR: a = ATTRID_XREF; break; 00179 case DTID_CONNROLESEG: a = ATTRID_SEGREF; break; 00180 default: COMTHROW(E_MGA_DATA_INCONSISTENCY); 00181 } 00182 CoreObj target = src[a]; 00183 if(!target) return false; 00184 CoreObj p1, p2; 00185 GetRootOfDeriv(target, p1); 00186 GetRootOfDeriv(src.GetMgaObj(), p2); 00187 return p1 && COM_EQUAL(p1,p2); 00188 } 00189 00190 // in the diagram below a model M is instantiated/subtyped into Mi 00191 // M contains reference r, pointing to A 00192 // Mi will contain derived reference ri, and derived target object Ai 00193 // Mj will contain derived reference rj, and derived target object Aj 00194 // this is the internal reference redirection scenario, so when MGA detects 00195 // that secondary derived references (r) have their targets set like here to 00196 // another secondary derived object (A) it must perform the redirect job 00197 // i.e.: ri->Ai, rj->Aj 00198 // external references (let's suppose p refers to B, p->B) can't be redirected 00199 // automatically because there is no clue how Mi, Mj relate to B1, B2 00200 // 00201 // M------------- B 00202 // | | / \ 00203 // | r--->A | / \ 00204 // | p | / \ / \ 00205 // ------------- /I/S\ /I/S\ 00206 // / \ ---- ----- 00207 // | | | | 00208 // / \ / \ B1 B2 00209 // /I/S\ /I/S\ 00210 // ----- ----- 00211 // | | 00212 // Mi------------ Mj------------ 00213 // | | | | 00214 // | ri---->Ai | | rj---->Aj | 00215 // | | | | 00216 // ------------- ------------- 00217 // 00218 // this method GetDerivedEquivalent gives back/finds Ai [corresponding for A] in Mi 00219 // and is called like: 00220 // GetDerivedEquivalent( A, Mi, [out] Ai, [in] level = -1) 00221 // the corresponding parameters are (names taken from the diagram above) 00222 void GetDerivedEquivalent(CoreObj const &objinbase, CoreObj const &subtype, CoreObj &objinsubtype, int level) { 00223 CoreObj basetype= subtype[ATTRID_DERIVED]; 00224 ASSERT(basetype); 00225 CoreObj o = objinbase; 00226 00227 if(!objinbase || (level < 0 && !IsContained(o,basetype, &level)) ) { 00228 objinsubtype = objinbase; 00229 return; 00230 } 00231 CoreObjs subs = objinbase[ATTRID_DERIVED + ATTRID_COLLECTION]; 00232 ITERATE_THROUGH(subs) { 00233 if( COM_EQUAL(subtype, ITER.FollowChain(ATTRID_FCOPARENT, level))) { 00234 objinsubtype = ITER; 00235 return; 00236 } 00237 } 00238 COMTHROW(E_MGA_DATA_INCONSISTENCY); 00239 } 00240 00241 00242 // ---------------------------------------- 00243 // DeriveTreeTask 00244 // ---------------------------------------- 00245 void DeriveTreeTask::_DoWithDeriveds(CoreObj self, std::vector<CoreObj> *peers) { 00246 CoreObjs chds = self[masterattr + ATTRID_COLLECTION]; // do it first to enable delete operations... 00247 if(!Do(self, peers)) 00248 return; 00249 ITERATE_THROUGH(chds) { 00250 if(peercnt) { 00251 CoreObj r = ITER.FollowChain(ATTRID_FCOPARENT, selfdepth); 00252 std::vector<CoreObj> subpeers(peercnt); 00253 int i; 00254 for(i = 0; i < internalpeercnt; i++) { // first the internals 00255 GetDerivedEquivalent((*peers)[i], r, subpeers[i], peerdepths[i]); 00256 } 00257 for(; i < peercnt; i++) subpeers[i] = (*peers)[i]; // the rest are externals 00258 _DoWithDeriveds(ITER, &subpeers); 00259 } 00260 else _DoWithDeriveds(ITER, peers); 00261 } 00262 } 00263 00264 // before starting with the initial object it is determined 00265 // which targets are 'internal' i.e. to be adjusted for the subtypes 00266 // internal refs always preceed external refs in the peers list. 00267 // 'false internals' (references into the same derive tree, but inherited 00268 // from a basetype) are rare, but they can be avoided through setting 00269 // the 'endreserve' data member (e.g. at RevertToBase) 00270 00271 // masterattr the attribute followed recuresively. It can either be ATTRID_DERIVEDS 00272 // or ATTRID_MASTEROBJ. It is usually determined by the objecttype, but in case of 00273 // references, it can be preset by the user. 00274 void DeriveTreeTask::DoWithDeriveds(CoreObj self, std::vector<CoreObj> *peers) { 00275 if(GetMetaID(self) == DTID_FOLDER) Do(self, peers); // no derived objects 00276 else { 00277 ASSERT(!masterattr || self.GetMetaID() == DTID_REFERENCE); 00278 if(!masterattr) { 00279 if(self.IsFCO()) masterattr = ATTRID_DERIVED; 00280 else { 00281 ASSERT(GetMetaID(self) == DTID_CONNROLE || GetMetaID(self) == DTID_SETNODE); 00282 masterattr = ATTRID_MASTEROBJ; 00283 } 00284 } 00285 CoreObjs chds = self[masterattr + ATTRID_COLLECTION]; 00286 if(!peers) peercnt = internalpeercnt = 0; 00287 else if(!chds.Count()) { 00288 peercnt = (*peers).size(); 00289 internalpeercnt = 0; 00290 } 00291 else { 00292 CoreObj r; 00293 GetRootOfDeriv(self, r, &selfdepth); 00294 ASSERT(r); 00295 peercnt = (*peers).size(); 00296 peerdepths.resize(peercnt); // only internalpeercnt will be used, but we do not know that number yet 00297 int i; 00298 for(i = 0; i < peercnt-endreserve; i++) { 00299 int l; 00300 CoreObj r2; 00301 if((*peers)[i] == NULL) break; 00302 GetRootOfDeriv((*peers)[i], r2, &l); 00303 if(COM_EQUAL(r,r2)) peerdepths[i] = l; 00304 else break; 00305 } 00306 internalpeercnt = i; 00307 } 00308 _DoWithDeriveds(self, peers); 00309 } 00310 } 00311 00312 00313 // ---------------------------------------- 00314 // Attach/detach 00315 // ---------------------------------------- 00316 HRESULT FCO::DetachFromArcheType () 00317 { 00318 COMTRY_IN_TRANSACTION { 00319 CheckWrite(); 00320 CoreObj d = self[ATTRID_DERIVED], d2; 00321 if(d) { // if self is really derived from something (d) 00322 while((d2 = d[ATTRID_DERIVED]) != NULL) 00323 d <<= d2; 00324 00325 // copy/merge/detach from parent to self (overwrite the derivation) 00326 // almost like ObjTreeCopy, copies from 'd' (the archetype) to 'self' (the derived) 00327 coreobjpairhash crealist2; 00328 ObjDetachAndMerge(mgaproject, d, self, crealist2, 0, true); 00329 00330 } 00331 SelfMark(OBJEVENT_SUBT_INST); 00332 00333 // Need to run this check: "inherited ref can only refer to a derived instance of the target of its base" 00334 { 00335 CoreObjs segs = self[ATTRID_REFERENCE + ATTRID_COLLECTION]; 00336 ITERATE_THROUGH(segs) { 00337 CComPtr<IMgaFCO> ffco; 00338 ObjForCore(ITER)->getinterface(&ffco); 00339 COMTHROW(ffco->Check()); 00340 } 00341 } 00342 00343 CComPtr<IMgaFCO> selfFco; 00344 ObjForCore(self)->getinterface(&selfFco); 00345 COMTHROW(selfFco->Check()); 00346 00347 CoreObjMark(self[ATTRID_PARENT], OBJEVENT_LOSTCHILD); 00348 } COMCATCH_IN_TRANSACTION(;); 00349 00350 return S_OK; 00351 } 00352 00353 // if instance is needed all inner objects in 'self' must be attachable to a corresponding object in 'newtype' 00354 // if subtype is needed then attachment happens with (name & kind) matchable elements [these become secondary derived] 00355 // and any other object in 'self' will become additional plain object 00356 HRESULT FCO::AttachToArcheType( IMgaFCO *newtype, VARIANT_BOOL instance) { 00357 COMTRY_IN_TRANSACTION { 00358 CHECK_MYINPTRPAR(newtype); 00359 CoreObj ntype(newtype); 00360 coreobjpairhash crealist2; 00361 // attaches self to nettype (the new base) if possible 00362 ObjAttach( mgaproject, ntype, self, crealist2, instance, true ); 00363 CoreObjMark( ntype, OBJEVENT_SUBT_INST); 00364 } COMCATCH_IN_TRANSACTION(;) 00365 }