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    }