001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.bytecode.statement.tag; 020 021import java.util.Iterator; 022import java.util.List; 023 024import lucee.transformer.bytecode.BodyBase; 025import lucee.transformer.bytecode.BytecodeContext; 026import lucee.transformer.bytecode.BytecodeException; 027import lucee.transformer.bytecode.Position; 028import lucee.transformer.bytecode.Statement; 029import lucee.transformer.bytecode.expression.Expression; 030import lucee.transformer.bytecode.util.Types; 031import lucee.transformer.bytecode.visitor.ConditionVisitor; 032import lucee.transformer.bytecode.visitor.DecisionIntVisitor; 033 034import org.objectweb.asm.Type; 035import org.objectweb.asm.commons.GeneratorAdapter; 036import org.objectweb.asm.commons.Method; 037 038public final class TagSwitch extends TagBaseNoFinal { 039 040 // int listFindNoCase(String list, String value, String delimiter) 041 private static final Method LIST_FIND_NO_CASE = new Method( 042 "listFindForSwitch", 043 Types.INT_VALUE, 044 new Type[]{Types.STRING,Types.STRING,Types.STRING}); 045 046 /** 047 * Constructor of the class 048 * @param sl 049 * @param el 050 */ 051 public TagSwitch(Position start,Position end) { 052 super(start,end); 053 } 054 055 /** 056 * 057 * @see lucee.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter) 058 */ 059 public void _writeOut(BytecodeContext bc) throws BytecodeException { 060 GeneratorAdapter adapter = bc.getAdapter(); 061 062 // expression 063 int expression=adapter.newLocal(Types.STRING); 064 getAttribute("expression").getValue().writeOut(bc, Expression.MODE_REF); 065 adapter.storeLocal(expression); 066 067 068 List statements = getBody().getStatements(); 069 Statement stat; 070 Tag tag; 071 072 ConditionVisitor cv=new ConditionVisitor(); 073 cv.visitBefore(); 074 075 // cases 076 Iterator it = statements.iterator(); 077 Tag def=null; 078 while(it.hasNext()) { 079 stat=(Statement) it.next(); 080 if(stat instanceof Tag) { 081 tag=(Tag) stat; 082 if(tag.getTagLibTag().getTagClassName().equals("lucee.runtime.tag.Case")) { 083 addCase(bc,cv,tag,expression); 084 continue; 085 } 086 else if(tag.getTagLibTag().getTagClassName().equals("lucee.runtime.tag.Defaultcase")) { 087 if(def!=null) 088 throw new BytecodeException("multiple defaultcases are not allowed",getStart()); 089 def=tag; 090 //setDefaultCase(bc,cv,tag); 091 //break; 092 } 093 } 094 } 095 096 // default 097 if(def!=null)setDefaultCase(bc,cv,def); 098 099 cv.visitAfter(bc); 100 } 101 102 private void setDefaultCase(BytecodeContext bc, ConditionVisitor cv, Tag tag) throws BytecodeException { 103 cv.visitOtherviseBeforeBody(); 104 BodyBase.writeOut(bc, tag.getBody()); 105 //tag.getBody().writeOut(bc); 106 cv.visitOtherviseAfterBody(); 107 } 108 109 private void addCase(BytecodeContext bc, ConditionVisitor cv, Tag tag, int expression) throws BytecodeException { 110 GeneratorAdapter adapter = bc.getAdapter(); 111 112 cv.visitWhenBeforeExpr(); 113 DecisionIntVisitor div=new DecisionIntVisitor(); 114 div.visitBegin(); 115 // List.listFindNoCase(case.value,expression,del); 116 tag.getAttribute("value").getValue().writeOut(bc,Expression.MODE_REF); 117 adapter.loadLocal(expression); 118 Attribute attr = tag.getAttribute("delimiters"); 119 if(attr!=null)attr.getValue().writeOut(bc,Expression.MODE_REF); 120 else adapter.push(","); 121 adapter.invokeStatic(Types.LIST_UTIL, LIST_FIND_NO_CASE); 122 div.visitNEQ(); 123 adapter.push(-1); 124 div.visitEnd(bc); 125 cv.visitWhenAfterExprBeforeBody(bc); 126 BodyBase.writeOut(bc, tag.getBody()); 127 //tag.getBody().writeOut(bc); 128 cv.visitWhenAfterBody(bc); 129 130 131 132 /*if(List.listFindNoCase(case.value,expression,delimiters)!=-1) { 133 <xsl:apply-templates select="./body/*"/> 134 }*/ 135 } 136 137}