package railo.transformer.bytecode.statement.tag;
import java.util.Iterator;
import java.util.List;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import railo.transformer.bytecode.BytecodeContext;
import railo.transformer.bytecode.BytecodeException;
import railo.transformer.bytecode.Position;
import railo.transformer.bytecode.Statement;
import railo.transformer.bytecode.expression.Expression;
import railo.transformer.bytecode.util.Types;
import railo.transformer.bytecode.visitor.ConditionVisitor;
import railo.transformer.bytecode.visitor.DecisionIntVisitor;
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(Position start,Position end) {
super(start,end);
}
/**
*
* @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter)
*/
public void _writeOut(BytecodeContext bc) throws BytecodeException {
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().getTagClassName().equals("railo.runtime.tag.Case")) {
addCase(bc,cv,tag,expression);
continue;
}
else if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Defaultcase")) {
if(def!=null)
throw new BytecodeException("multiple defaultcases are not allowed",getStart());
def=tag;
//setDefaultCase(bc,cv,tag);
//break;
}
}
}
// default
if(def!=null)setDefaultCase(bc,cv,def);
cv.visitAfter(bc);
/*
<!-- cases -->
<xsl:for-each select="./body/tag[@name='case']">
if(List.listFindNoCase(case.value,expression,
<xsl:if test="./attribute[@name='delimiters']">,delimiters)!=-1) {
<xsl:apply-templates select="./body/*"/>
}
</xsl:for-each>
<!-- default -->
<xsl:if test="./body/tag[@name='defaultcase']">
<xsl:if test="count(./body/tag[@name='case'])>0">else </xsl:if> {
<xsl:apply-templates select="./body/tag[@name='defaultcase']/body/*"/>
}
</xsl:if>
</xsl:template>*/
}
private void setDefaultCase(BytecodeContext bc, ConditionVisitor cv, Tag tag) throws BytecodeException {
cv.visitOtherviseBeforeBody();
tag.getBody().writeOut(bc);
cv.visitOtherviseAfterBody();
}
private void addCase(BytecodeContext bc, ConditionVisitor cv, Tag tag, int expression) throws BytecodeException {
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);
tag.getBody().writeOut(bc);
cv.visitWhenAfterBody(bc);
/*if(List.listFindNoCase(case.value,expression,delimiters)!=-1) {
<xsl:apply-templates select="./body/*"/>
}*/
}
}