package railo.runtime.tag;
import javax.servlet.jsp.tagext.Tag;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.PageException;
import railo.runtime.ext.tag.TagImpl;
import railo.runtime.functions.other.GetBaseTagData;
import railo.runtime.op.Caster;
import railo.runtime.op.Decision;
import railo.runtime.type.Array;
import railo.runtime.type.ArrayImpl;
import railo.runtime.type.Collection;
import railo.runtime.type.Collection.Key;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.Struct;
/**
* Allows subtag data to be saved with the base tag. Applies only to custom tags.
*
*
*
**/
public final class Associate extends TagImpl {
private static final Key ASSOC_ATTRS = KeyImpl.intern("AssocAttribs");
/** The name of the structure in which the base tag stores subtag data. */
private Collection.Key datacollection=ASSOC_ATTRS;
/** The name of the base tag. */
private String basetag;
@Override
public void release() {
super.release();
datacollection=ASSOC_ATTRS;
}
/** set the value datacollection
* The name of the structure in which the base tag stores subtag data.
* @param datacollection value to set
**/
public void setDatacollection(String datacollection) {
this.datacollection=KeyImpl.init(datacollection);
}
/** set the value basetag
* The name of the base tag.
* @param basetag value to set
**/
public void setBasetag(String basetag) {
this.basetag=basetag;
}
@Override
public int doStartTag() throws PageException {
// current
CFTag current=getCFTag();
Struct value;
if(current==null || (value=current.getAttributesScope())==null)
throw new ApplicationException("invalid context, tag is no inside a custom tag");
// parent
CFTag parent=GetBaseTagData.getParentCFTag(current.getParent(), basetag, -1);
if(parent==null) throw new ApplicationException("there is no parent tag with name ["+basetag+"]");
Struct thisTag=parent.getThis();
Object obj=thisTag.get(datacollection,null);
Array array;
if(obj==null) {
array=new ArrayImpl(new Object[]{value});
thisTag.set(datacollection,array);
}
else if(Decision.isArray(obj) && (array=Caster.toArray(obj)).getDimension()==1) {
array.append(value);
}
else {
array=new ArrayImpl(new Object[]{obj,value});
thisTag.set(datacollection,array);
}
return SKIP_BODY;
}
/*private static CFTag getParentCFTag(Tag srcTag,String trgTagName) {
String pureName=trgTagName;
CFTag cfTag;
if(StringUtil.startsWithIgnoreCase(pureName,"cf_")) {
pureName=pureName.substring(3);
}
if(StringUtil.startsWithIgnoreCase(pureName,"cf")) {
pureName=pureName.substring(2);
}
int count=0;
while((srcTag=srcTag.getParent())!=null) {
if(srcTag instanceof CFTag) {
if(count++==0)continue;
cfTag=(CFTag)srcTag;
if(cfTag instanceof CFTagCore){
CFTagCore tc=(CFTagCore) cfTag;
if(tc.getName().equalsIgnoreCase(pureName))
return cfTag;
continue;
}
if(cfTag.getAppendix().equalsIgnoreCase(pureName)) {
return cfTag;
}
}
}
return null;
}*/
private CFTag getCFTag() {
Tag tag=this;
while((tag=tag.getParent())!=null) {
if(tag instanceof CFTag) {
return (CFTag)tag;
}
}
return null;
}
@Override
public int doEndTag() {
return EVAL_PAGE;
}
}