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