001 package railo.runtime.tag; 002 003 import javax.servlet.jsp.tagext.Tag; 004 005 import railo.runtime.exp.ApplicationException; 006 import railo.runtime.exp.PageException; 007 import railo.runtime.ext.tag.TagImpl; 008 import railo.runtime.functions.other.GetBaseTagData; 009 import railo.runtime.op.Caster; 010 import railo.runtime.op.Decision; 011 import railo.runtime.type.Array; 012 import railo.runtime.type.ArrayImpl; 013 import railo.runtime.type.Collection; 014 import railo.runtime.type.Collection.Key; 015 import railo.runtime.type.KeyImpl; 016 import railo.runtime.type.Struct; 017 018 /** 019 * Allows subtag data to be saved with the base tag. Applies only to custom tags. 020 * 021 * 022 * 023 **/ 024 public final class Associate extends TagImpl { 025 026 private static final Key ASSOC_ATTRS = KeyImpl.intern("AssocAttribs"); 027 028 029 /** The name of the structure in which the base tag stores subtag data. */ 030 private Collection.Key datacollection=ASSOC_ATTRS; 031 032 /** The name of the base tag. */ 033 private String basetag; 034 035 /** 036 * @see javax.servlet.jsp.tagext.Tag#release() 037 */ 038 public void release() { 039 super.release(); 040 datacollection=ASSOC_ATTRS; 041 } 042 043 /** set the value datacollection 044 * The name of the structure in which the base tag stores subtag data. 045 * @param datacollection value to set 046 **/ 047 public void setDatacollection(String datacollection) { 048 this.datacollection=KeyImpl.init(datacollection); 049 } 050 051 /** set the value basetag 052 * The name of the base tag. 053 * @param basetag value to set 054 **/ 055 public void setBasetag(String basetag) { 056 this.basetag=basetag; 057 } 058 059 060 /** 061 * @throws PageException 062 * @see javax.servlet.jsp.tagext.Tag#doStartTag() 063 */ 064 public int doStartTag() throws PageException { 065 066 // current 067 CFTag current=getCFTag(); 068 Struct value; 069 if(current==null || (value=current.getAttributesScope())==null) 070 throw new ApplicationException("invalid context, tag is no inside a custom tag"); 071 072 // parent 073 CFTag parent=GetBaseTagData.getParentCFTag(current.getParent(), basetag, -1); 074 if(parent==null) throw new ApplicationException("there is no parent tag with name ["+basetag+"]"); 075 076 Struct thisTag=parent.getThis(); 077 Object obj=thisTag.get(datacollection,null); 078 079 Array array; 080 081 if(obj==null) { 082 array=new ArrayImpl(new Object[]{value}); 083 thisTag.set(datacollection,array); 084 } 085 else if(Decision.isArray(obj) && (array=Caster.toArray(obj)).getDimension()==1) { 086 array.append(value); 087 } 088 else { 089 array=new ArrayImpl(new Object[]{obj,value}); 090 thisTag.set(datacollection,array); 091 } 092 return SKIP_BODY; 093 } 094 095 /*private static CFTag getParentCFTag(Tag srcTag,String trgTagName) { 096 String pureName=trgTagName; 097 CFTag cfTag; 098 if(StringUtil.startsWithIgnoreCase(pureName,"cf_")) { 099 pureName=pureName.substring(3); 100 } 101 if(StringUtil.startsWithIgnoreCase(pureName,"cf")) { 102 pureName=pureName.substring(2); 103 } 104 int count=0; 105 while((srcTag=srcTag.getParent())!=null) { 106 if(srcTag instanceof CFTag) { 107 if(count++==0)continue; 108 cfTag=(CFTag)srcTag; 109 if(cfTag instanceof CFTagCore){ 110 CFTagCore tc=(CFTagCore) cfTag; 111 if(tc.getName().equalsIgnoreCase(pureName)) 112 return cfTag; 113 continue; 114 } 115 if(cfTag.getAppendix().equalsIgnoreCase(pureName)) { 116 return cfTag; 117 } 118 } 119 } 120 return null; 121 }*/ 122 123 private CFTag getCFTag() { 124 Tag tag=this; 125 while((tag=tag.getParent())!=null) { 126 if(tag instanceof CFTag) { 127 return (CFTag)tag; 128 } 129 } 130 return null; 131 } 132 133 /** 134 * @see javax.servlet.jsp.tagext.Tag#doEndTag() 135 */ 136 public int doEndTag() { 137 return EVAL_PAGE; 138 } 139 140 }