@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