001    package railo.transformer.bytecode.statement.tag;
002    
003    import java.util.Iterator;
004    import java.util.List;
005    
006    import org.objectweb.asm.Type;
007    import org.objectweb.asm.commons.GeneratorAdapter;
008    import org.objectweb.asm.commons.Method;
009    
010    import railo.transformer.bytecode.BytecodeContext;
011    import railo.transformer.bytecode.BytecodeException;
012    import railo.transformer.bytecode.Position;
013    import railo.transformer.bytecode.Statement;
014    import railo.transformer.bytecode.expression.Expression;
015    import railo.transformer.bytecode.util.Types;
016    import railo.transformer.bytecode.visitor.ConditionVisitor;
017    import railo.transformer.bytecode.visitor.DecisionIntVisitor;
018    
019    public final class TagSwitch extends TagBaseNoFinal {
020    
021            // int listFindNoCase(String list, String value, String delimiter)
022            private static final Method LIST_FIND_NO_CASE = new Method(
023                                                                                                                    "listFindForSwitch",
024                                                                                                                    Types.INT_VALUE,
025                                                                                                                    new Type[]{Types.STRING,Types.STRING,Types.STRING});
026    
027            /**
028             * Constructor of the class
029             * @param sl
030             * @param el
031             */
032            public TagSwitch(Position start,Position end) {
033                    super(start,end);
034            }
035            
036            /**
037             *
038             * @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter)
039             */
040            public void _writeOut(BytecodeContext bc) throws BytecodeException {
041                    GeneratorAdapter adapter = bc.getAdapter();
042    
043                    // expression
044                    int expression=adapter.newLocal(Types.STRING);
045                    getAttribute("expression").getValue().writeOut(bc, Expression.MODE_REF);
046                    adapter.storeLocal(expression);
047                    
048                    
049                    List statements = getBody().getStatements();
050                    Statement stat;
051                    Tag tag;
052    
053                    ConditionVisitor cv=new ConditionVisitor();
054                    cv.visitBefore();
055    
056                    // cases
057                    Iterator it = statements.iterator();
058                    Tag def=null;
059                    while(it.hasNext()) {
060                            stat=(Statement) it.next();
061                            if(stat instanceof Tag) {
062                                    tag=(Tag) stat;
063                                    if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Case"))       {
064                                            addCase(bc,cv,tag,expression);
065                                            continue;
066                                    }
067                                    else if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Defaultcase"))   {
068                                            if(def!=null)
069                                                    throw new BytecodeException("multiple defaultcases are not allowed",getStart());
070                                            def=tag;
071                                            //setDefaultCase(bc,cv,tag);
072                                            //break;
073                                    }
074                            }
075                    }
076    
077                    // default
078                    if(def!=null)setDefaultCase(bc,cv,def);
079                    
080                    cv.visitAfter(bc);
081                    
082                    
083                    /*
084                     
085    <!-- cases -->
086            <xsl:for-each select="./body/tag[@name='case']">
087                    if(List.listFindNoCase(case.value,expression,
088                            <xsl:if test="./attribute[@name='delimiters']">,delimiters)!=-1) {
089                    <xsl:apply-templates select="./body/*"/>
090                    }
091            </xsl:for-each>
092            
093    <!-- default -->
094            <xsl:if test="./body/tag[@name='defaultcase']">
095                    <xsl:if test="count(./body/tag[@name='case'])&gt;0">else </xsl:if> {
096                            <xsl:apply-templates select="./body/tag[@name='defaultcase']/body/*"/>
097                    }
098            </xsl:if>
099    </xsl:template>*/
100            }
101    
102            private void setDefaultCase(BytecodeContext bc, ConditionVisitor cv, Tag tag) throws BytecodeException {
103                    cv.visitOtherviseBeforeBody();
104                            tag.getBody().writeOut(bc);
105                    cv.visitOtherviseAfterBody();
106            }
107    
108            private void addCase(BytecodeContext bc, ConditionVisitor cv, Tag tag, int expression) throws BytecodeException {
109                    GeneratorAdapter adapter = bc.getAdapter();
110                    
111                    cv.visitWhenBeforeExpr();
112                            DecisionIntVisitor div=new DecisionIntVisitor();
113                            div.visitBegin();
114                                    // List.listFindNoCase(case.value,expression,del);
115                                    tag.getAttribute("value").getValue().writeOut(bc,Expression.MODE_REF);
116                                    adapter.loadLocal(expression);
117                                    Attribute attr = tag.getAttribute("delimiters");
118                                    if(attr!=null)attr.getValue().writeOut(bc,Expression.MODE_REF);
119                                    else adapter.push(",");
120                                    adapter.invokeStatic(Types.LIST_UTIL, LIST_FIND_NO_CASE);
121                            div.visitNEQ();
122                                    adapter.push(-1);
123                            div.visitEnd(bc);
124                    cv.visitWhenAfterExprBeforeBody(bc);
125                            tag.getBody().writeOut(bc);
126                    cv.visitWhenAfterBody(bc);
127                    
128                    
129                    
130                    /*if(List.listFindNoCase(case.value,expression,delimiters)!=-1) {
131                    <xsl:apply-templates select="./body/*"/>
132                    }*/
133            }
134    
135    }