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            @Override
036            public void release()   {
037                    super.release();
038                    datacollection=ASSOC_ATTRS;
039            }
040    
041            /** set the value datacollection
042            *  The name of the structure in which the base tag stores subtag data.
043            * @param datacollection value to set
044            **/
045            public void setDatacollection(String datacollection)    {
046                    this.datacollection=KeyImpl.init(datacollection);
047            }
048    
049            /** set the value basetag
050            *  The name of the base tag.
051            * @param basetag value to set
052            **/
053            public void setBasetag(String basetag)  {
054                    this.basetag=basetag;
055            }
056    
057    
058            @Override
059            public int doStartTag() throws PageException    {
060                    
061                    // current
062            CFTag current=getCFTag();
063            Struct value;
064            if(current==null || (value=current.getAttributesScope())==null) 
065                    throw new ApplicationException("invalid context, tag is no inside a custom tag");
066            
067            // parent
068            CFTag parent=GetBaseTagData.getParentCFTag(current.getParent(), basetag, -1);
069            if(parent==null) throw new ApplicationException("there is no parent tag with name ["+basetag+"]");
070            
071            Struct thisTag=parent.getThis();
072            Object obj=thisTag.get(datacollection,null);
073            
074            Array array;
075    
076            if(obj==null) {
077                array=new ArrayImpl(new Object[]{value});
078                thisTag.set(datacollection,array);   
079            }
080            else if(Decision.isArray(obj) && (array=Caster.toArray(obj)).getDimension()==1) {
081                array.append(value);
082            }
083            else {
084                array=new ArrayImpl(new Object[]{obj,value});
085                thisTag.set(datacollection,array);   
086            }
087                    return SKIP_BODY; 
088            }
089    
090            /*private static CFTag getParentCFTag(Tag srcTag,String trgTagName) {
091            String pureName=trgTagName;
092            CFTag cfTag;
093            if(StringUtil.startsWithIgnoreCase(pureName,"cf_")) {
094                pureName=pureName.substring(3);
095            }
096            if(StringUtil.startsWithIgnoreCase(pureName,"cf")) {
097                pureName=pureName.substring(2);
098            }
099            int count=0;
100            while((srcTag=srcTag.getParent())!=null) {
101                    if(srcTag instanceof CFTag) {
102                    if(count++==0)continue;
103                    cfTag=(CFTag)srcTag;
104                    if(cfTag instanceof CFTagCore){
105                            CFTagCore tc=(CFTagCore) cfTag;
106                            if(tc.getName().equalsIgnoreCase(pureName))
107                                    return cfTag;
108                            continue;
109                    }
110                    if(cfTag.getAppendix().equalsIgnoreCase(pureName)) {
111                        return cfTag;
112                    }
113                }
114            }
115            return null;
116        }*/
117            
118            private CFTag getCFTag() {
119            Tag tag=this;
120            while((tag=tag.getParent())!=null) {
121                if(tag instanceof CFTag) {
122                    return (CFTag)tag;
123                }
124            }
125            return null;
126        }
127    
128        @Override
129            public int doEndTag()   {
130                    return EVAL_PAGE;
131            }
132    
133    }