<@doc alias="ref" hierarchy="GMLDOM" also="@Infoshape, @BOInfoshape"> The RefInfoshape is a reference to @BOInfoshape object. All @Configurable elements contain instances of @RefInfoshape. (They can share the same @RefInfoshape, or have different @RefInfoshape objects that point to the same @BOInfoshape.) @RefInfoshape also stores a list of all elements that use this infoshape, to facilitate change notification. (c) SAP AG 2003-2006. All rights reserved. Class RefInfoshape inherit Infoshape; <@doc> A @BOInfoshapeUsage! object that points to a @BOInfoshapeUnit!. The pointer unit contains a single @BOInfoshape! object strong property boInfoshape = ^core.gml:BOInfoshapeUsage; //usage to BOInfoshape, or null if no BOInfoshape is pointed <@doc scope="private"> Collection of all elements in the model that store pointers to this RefInfoshape object. This collection is used for optimization of notification processes. virtual property elements_using_me = ^Element[id]; <@doc scope="private"> A string represenation of all the units that are using the current RefInfoshape, for internal use only. property unitsUsingMe = ','; virtual property dirty = true; override method notifyOnChange(changeType, changeData) var C = this.getElementsUsingMe(); for (var x in C) { var elem = C[x]; if (elem && elem.notifyOnInfoshapeChange) elem.notifyOnInfoshapeChange(changeType, changeData); } end <@doc scope="public"> Gets a collection of all elements in the model that store pointers to this RefInfoshape object. method getElementsUsingMe() if (!this.dirty) return this.elements_using_me; var A = SPLIT(TRIM(this.unitsUsingMe),','); if(!A) { this.dirty = false; return this.elements_using_me; } //load all depended units for(var i=0; i < A.length; i++){ if (!A[i]) continue; // load the unit in order that the elements in the unit will be loaded into memory. var unit = this.unit && this.unit.model && this.unit.model.getUnit(A[i]) || null; // The unit probably was deleted. if(!unit) REPLACE(this.unitsUsingMe,','+ A[i] + ',' ,','); } return this.elements_using_me; end <@doc scope="public"> A method for registering an element that points to this RefInfoshape object. method registerElement(element) if (!element) return; var unitId = element.unit && element.unit.id || null; if(!unitId) return; this.elements_using_me[element.id] = element; if (CONTAINS(this.unitsUsingMe,',' +unitId + ',')){ return ; }else{ if($ENV.recorder){ this.setProperty('unitsUsingMe',this.unitsUsingMe + unitId+ ','); }else{ this.unitsUsingMe = this.unitsUsingMe + unitId+ ',' ; } } end <@doc scope="public"> A method for unregistering an element from pointing to this RefInfoshape. method unregisterElement(element) if (!element) return; var unitId = element.unit && element.unit.id || null; if(!unitId) return; delete this.elements_using_me[element.id]; if (this.isUnitDepended(element.unit)) return; // If there is no elements using this infoshape then remove this refInfoshape from the infoshape pool. if(ISEMPTY(this.getElementsUsingMe())) { if (this.unit) this.unit.removeRefInfoshape(this); return ; } if(CONTAINS(this.unitsUsingMe,','+unitId+',' )){ if($ENV.recorder){ this.setProperty('unitsUsingMe', REPLACE(this.unitsUsingMe,','+ unitId + ',' ,',')); }else{ this.unitsUsingMe = REPLACE(this.unitsUsingMe,','+ unitId + ',' ,','); } } end <@doc scope="private"> Checks if a unit is dependend in this RefInfoshape. method isUnitDepended(unit) if(!unit) return false; var elements = this.getElementsUsingMe(); for ( var id in elements){ if (elements[id] && elements[id].unit === unit) return true; } return false; end <@doc> Changes this RefInfoshape to point to another @BOInfoshape! Also triggers a INFOSHAPE_CHANGE_BO_REPLACED notification. the @BOInfoshape! to which this object should point the BOInfoshapeUnit that stores the @BOInfoshape! to which this object should point method setBOInfoshape(bo_infoshape) if (bo_infoshape.isa('core.gml:BOInfoshapeUnit')) bo_infoshape = bo_infoshape.getBOInfoshapeElement(); if (!bo_infoshape || !bo_infoshape.isa('core.gml:BOInfoshape')) throw new Error(-1, "setBOInfoshape: invalid parameter passed to this method"); var old_bo_unit = (this.boInfoshape && this.boInfoshape.getTarget()) || null; var old_bo_id = (old_bo_unit && old_bo_unit.getUniqueID()) || null; var new_bo_id = (bo_infoshape && bo_infoshape.getUniqueID()) || null; if (old_bo_id == new_bo_id) { #TRACE[1, "setBOInfoshape: tried to set the same BO. Ignored."]; return; } // erase reference in existing BO infoshape if (this.boInfoshape) { this.getBOInfoshape().removeRefInfoshape(this); this.onRemoveMe(); } //now setting Id to the new infoshape. if need to create object - use the clone(), else, just copy content. var newUsage = bo_infoshape.unit && bo_infoshape.unit.createNewUsage({'boID':new_bo_id}) || null; if (newUsage) { this.insertElement(newUsage, 'boInfoshape'); this.getBOInfoshape().addRefInfoshape(this); this.notifyOnChange(#[INFOSHAPE_CHANGE_BO_REPLACED], {old_bo:old_bo_id, new_bo:new_bo_id}); } else { #LOG[1, "setBOInfoshape: Failed to change infoshape"]; } end <@doc> Clears the BOInfoshape that is pointed by this ref infoshape. Also triggers a INFOSHAPE_CHANGE_BO_REPLACED notification. method clearBOInfoshape() if (!this.boInfoshape) return; var old_bo_unit = this.boInfoshape.getTarget() || null; var old_bo_id = (old_bo_unit && old_bo_unit.getUniqueID()) || null; this.getBOInfoshape().removeRefInfoshape(this); this.removeElement(this.boInfoshape, 'boInfoshape'); this.notifyOnChange(#[INFOSHAPE_CHANGE_BO_REPLACED], {old_bo:old_bo_id, new_bo:null}); end <@doc> Get the BOInfoshape that is pointed by this ref infoshape The pointed BOInfoshape object method getBOInfoshape() if (!this.boInfoshape) return null; return this.boInfoshape.getTarget().getBOInfoshapeElement(); end <@doc> 2 RefInfoshape objects are compatible if they point to the same BOInfoshape object. Another RefInfoshape to be compared Returns ~true if infoshapes are compatible; otherwise, returns ~false 2 RefInfoshapes are compatible if they point to the same BOInfoshape object override method isCompatible(other_infoshape) if (!other_infoshape) return false; if (this.Class.fullname != other_infoshape.Class.fullname) return false; //optimization attempt if ((this.boInfopshape && this.boInfoshape.target && (typeof this.boInfoshape.target == 'string')) && (other_infoshape.boInfopshape && other_infoshape.boInfoshape.target && (typeof other_infoshape.boInfoshape.target == 'string'))) { TRACE[2, "Compaerd RefInfoshape objects by evaluating unloaded ids of infoshapes: " + this.boInfoshape.target + ' ' + other_infoshape.boInfoshape.target]; return (other_infoshape.boInfoshape.target == this.boInfoshape.target); } //if the other infoshape is a BOInfoshape, compare them, //if (other_infoshape.isa('core.gml:BOInfoshape')) // return other_infoshape.isCompatible(this.getBOInfoshape()); var this_bo = this.getBOInfoshape(); var other_bo = other_infoshape.getBOInfoshape(); if (!this_bo || !other_bo) return false; var res = this_bo.isCompatible(other_bo); return (res); end override method getFields(fieldSource) var bo_infoshape = this.getBOInfoshape(); return bo_infoshape && bo_infoshape.getFields(fieldSource) || null; end override method onRemoveMe() this.supercall(); // Triggers also removal of the BOInfoshapeUsage this is essential for the // registration of this in the index collection of the ModelOrganizer. if(this.boInfoshape) this.removeElement(this.boInfoshape, 'boInfoshape'); end