/**
* Copyright (c) 2014, the Railo Company Ltd.
* Copyright (c) 2015, Lucee Assosication Switzerland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
package lucee.transformer.bytecode.statement.tag;
import java.util.Iterator;
import java.util.List;
import lucee.transformer.Factory;
import lucee.transformer.Position;
import lucee.transformer.TransformerException;
import lucee.transformer.bytecode.BodyBase;
import lucee.transformer.bytecode.BytecodeContext;
import lucee.transformer.bytecode.Statement;
import lucee.transformer.bytecode.util.Types;
import lucee.transformer.bytecode.visitor.ConditionVisitor;
import lucee.transformer.bytecode.visitor.DecisionIntVisitor;
import lucee.transformer.expression.Expression;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
public final class TagSwitch extends TagBaseNoFinal {
// int listFindNoCase(String list, String value, String delimiter)
private static final Method LIST_FIND_NO_CASE = new Method(
"listFindForSwitch",
Types.INT_VALUE,
new Type[]{Types.STRING,Types.STRING,Types.STRING});
/**
* Constructor of the class
* @param sl
* @param el
*/
public TagSwitch(Factory f, Position start,Position end) {
super(f,start,end);
}
/**
*
* @see lucee.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter)
*/
@Override
public void _writeOut(BytecodeContext bc) throws TransformerException {
GeneratorAdapter adapter = bc.getAdapter();
// expression
int expression=adapter.newLocal(Types.STRING);
getAttribute("expression").getValue().writeOut(bc, Expression.MODE_REF);
adapter.storeLocal(expression);
List statements = getBody().getStatements();
Statement stat;
Tag tag;
ConditionVisitor cv=new ConditionVisitor();
cv.visitBefore();
// cases
Iterator it = statements.iterator();
Tag def=null;
while(it.hasNext()) {
stat=(Statement) it.next();
if(stat instanceof Tag) {
tag=(Tag) stat;
if(tag.getTagLibTag().getTagClassDefinition().isClassNameEqualTo("lucee.runtime.tag.Case")) {
addCase(bc,cv,tag,expression);
continue;
}
else if(tag.getTagLibTag().getTagClassDefinition().isClassNameEqualTo("lucee.runtime.tag.Defaultcase")) {
if(def!=null)
throw new TransformerException("multiple defaultcases are not allowed",getStart());
def=tag;
//setDefaultCase(bc,cv,tag);
//break;
}
}
}
// default
if(def!=null)setDefaultCase(bc,cv,def);
cv.visitAfter(bc);
}
private void setDefaultCase(BytecodeContext bc, ConditionVisitor cv, Tag tag) throws TransformerException {
cv.visitOtherviseBeforeBody();
BodyBase.writeOut(bc, tag.getBody());
//tag.getBody().writeOut(bc);
cv.visitOtherviseAfterBody();
}
private void addCase(BytecodeContext bc, ConditionVisitor cv, Tag tag, int expression) throws TransformerException {
GeneratorAdapter adapter = bc.getAdapter();
cv.visitWhenBeforeExpr();
DecisionIntVisitor div=new DecisionIntVisitor();
div.visitBegin();
// List.listFindNoCase(case.value,expression,del);
tag.getAttribute("value").getValue().writeOut(bc,Expression.MODE_REF);
adapter.loadLocal(expression);
Attribute attr = tag.getAttribute("delimiters");
if(attr!=null)attr.getValue().writeOut(bc,Expression.MODE_REF);
else adapter.push(",");
adapter.invokeStatic(Types.LIST_UTIL, LIST_FIND_NO_CASE);
div.visitNEQ();
adapter.push(-1);
div.visitEnd(bc);
cv.visitWhenAfterExprBeforeBody(bc);
BodyBase.writeOut(bc, tag.getBody());
//tag.getBody().writeOut(bc);
cv.visitWhenAfterBody(bc);
/*if(List.listFindNoCase(case.value,expression,delimiters)!=-1) {
<xsl:apply-templates select="./body/*"/>
}*/
}
}