blob: 024ccceb813f0f5004befc19942e38c5ce197eb4 [file] [log] [blame]
/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jasper.tagplugins.jstl;
import org.apache.jasper.compiler.tagplugin.*;
public final class ForEach implements TagPlugin {
private boolean hasVar, hasBegin, hasEnd, hasStep;
public void doTag(TagPluginContext ctxt) {
String index = null;
boolean hasVarStatus = ctxt.isAttributeSpecified("varStatus");
if (hasVarStatus) {
ctxt.dontUseTagPlugin();
return;
}
hasVar = ctxt.isAttributeSpecified("var");
hasBegin = ctxt.isAttributeSpecified("begin");
hasEnd = ctxt.isAttributeSpecified("end");
hasStep = ctxt.isAttributeSpecified("step");
boolean hasItems = ctxt.isAttributeSpecified("items");
if (hasItems) {
doCollection(ctxt);
return;
}
// We must have a begin and end attributes
index = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("for (int " + index + " = ");
ctxt.generateAttribute("begin");
ctxt.generateJavaSource("; " + index + " <= ");
ctxt.generateAttribute("end");
if (hasStep) {
ctxt.generateJavaSource("; " + index + "+=");
ctxt.generateAttribute("step");
ctxt.generateJavaSource(") {");
}
else {
ctxt.generateJavaSource("; " + index + "++) {");
}
// If var is specified and the body contains an EL, then sycn
// the var attribute
if (hasVar /* && ctxt.hasEL() */) {
ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
ctxt.generateAttribute("var");
ctxt.generateJavaSource(", String.valueOf(" + index + "));");
}
ctxt.generateBody();
ctxt.generateJavaSource("}");
}
/**
* Generate codes for Collections
* The pseudo code is:
*/
private void doCollection(TagPluginContext ctxt) {
ctxt.generateImport("java.util.*");
generateIterators(ctxt);
String itemsV = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("Object " + itemsV + "= ");
ctxt.generateAttribute("items");
ctxt.generateJavaSource(";");
String indexV=null, beginV=null, endV=null, stepV=null;
if (hasBegin) {
beginV = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("int " + beginV + " = ");
ctxt.generateAttribute("begin");
ctxt.generateJavaSource(";");
}
if (hasEnd) {
indexV = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("int " + indexV + " = 0;");
endV = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("int " + endV + " = ");
ctxt.generateAttribute("end");
ctxt.generateJavaSource(";");
}
if (hasStep) {
stepV = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("int " + stepV + " = ");
ctxt.generateAttribute("step");
ctxt.generateJavaSource(";");
}
String iterV = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("Iterator " + iterV + " = null;");
// Object[]
ctxt.generateJavaSource("if (" + itemsV + " instanceof Object[])");
ctxt.generateJavaSource(iterV + "=toIterator((Object[])" + itemsV + ");");
// boolean[]
ctxt.generateJavaSource("else if (" + itemsV + " instanceof boolean[])");
ctxt.generateJavaSource(iterV + "=toIterator((boolean[])" + itemsV + ");");
// byte[]
ctxt.generateJavaSource("else if (" + itemsV + " instanceof byte[])");
ctxt.generateJavaSource(iterV + "=toIterator((byte[])" + itemsV + ");");
// char[]
ctxt.generateJavaSource("else if (" + itemsV + " instanceof char[])");
ctxt.generateJavaSource(iterV + "=toIterator((char[])" + itemsV + ");");
// short[]
ctxt.generateJavaSource("else if (" + itemsV + " instanceof short[])");
ctxt.generateJavaSource(iterV + "=toIterator((short[])" + itemsV + ");");
// int[]
ctxt.generateJavaSource("else if (" + itemsV + " instanceof int[])");
ctxt.generateJavaSource(iterV + "=toIterator((int[])" + itemsV + ");");
// long[]
ctxt.generateJavaSource("else if (" + itemsV + " instanceof long[])");
ctxt.generateJavaSource(iterV + "=toIterator((long[])" + itemsV + ");");
// float[]
ctxt.generateJavaSource("else if (" + itemsV + " instanceof float[])");
ctxt.generateJavaSource(iterV + "=toIterator((float[])" + itemsV + ");");
// double[]
ctxt.generateJavaSource("else if (" + itemsV + " instanceof double[])");
ctxt.generateJavaSource(iterV + "=toIterator((double[])" + itemsV + ");");
// Collection
ctxt.generateJavaSource("else if (" + itemsV + " instanceof Collection)");
ctxt.generateJavaSource(iterV + "=((Collection)" + itemsV + ").iterator();");
// Iterator
ctxt.generateJavaSource("else if (" + itemsV + " instanceof Iterator)");
ctxt.generateJavaSource(iterV + "=(Iterator)" + itemsV + ";");
// Enumeration
ctxt.generateJavaSource("else if (" + itemsV + " instanceof Enumeration)");
ctxt.generateJavaSource(iterV + "=toIterator((Enumeration)" + itemsV + ");");
// Map
ctxt.generateJavaSource("else if (" + itemsV + " instanceof Map)");
ctxt.generateJavaSource(iterV + "=((Map)" + itemsV + ").entrySet().iterator();");
if (hasBegin) {
String tV = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("for (int " + tV + "=" + beginV + ";" +
tV + ">0 && " + iterV + ".hasNext(); " +
tV + "--)");
ctxt.generateJavaSource(iterV + ".next();");
}
ctxt.generateJavaSource("while (" + iterV + ".hasNext()){");
if (hasVar) {
ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
ctxt.generateAttribute("var");
ctxt.generateJavaSource(", " + iterV + ".next());");
}
ctxt.generateBody();
if (hasStep) {
String tV = ctxt.getTemporaryVariableName();
ctxt.generateJavaSource("for (int " + tV + "=" + stepV + "-1;" +
tV + ">0 && " + iterV + ".hasNext(); " +
tV + "--)");
ctxt.generateJavaSource(iterV + ".next();");
}
if (hasEnd) {
if (hasStep) {
ctxt.generateJavaSource(indexV + "+=" + stepV + ";");
}
else {
ctxt.generateJavaSource(indexV + "++;");
}
if (hasBegin) {
ctxt.generateJavaSource("if(" + beginV + "+" + indexV +
">"+ endV + ")");
}
else {
ctxt.generateJavaSource("if(" + indexV + ">" + endV + ")");
}
ctxt.generateJavaSource("break;");
}
ctxt.generateJavaSource("}"); // while
}
/**
* Generate iterators for data types supported in items
*/
private void generateIterators(TagPluginContext ctxt) {
// Object[]
ctxt.generateDeclaration("ObjectArrayIterator",
"private Iterator toIterator(final Object[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return a[index++];}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// boolean[]
ctxt.generateDeclaration("booleanArrayIterator",
"private Iterator toIterator(final boolean[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return new Boolean(a[index++]);}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// byte[]
ctxt.generateDeclaration("byteArrayIterator",
"private Iterator toIterator(final byte[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return new Byte(a[index++]);}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// char[]
ctxt.generateDeclaration("charArrayIterator",
"private Iterator toIterator(final char[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return new Character(a[index++]);}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// short[]
ctxt.generateDeclaration("shortArrayIterator",
"private Iterator toIterator(final short[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return new Short(a[index++]);}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// int[]
ctxt.generateDeclaration("intArrayIterator",
"private Iterator toIterator(final int[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return new Integer(a[index++]);}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// long[]
ctxt.generateDeclaration("longArrayIterator",
"private Iterator toIterator(final long[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return new Long(a[index++]);}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// float[]
ctxt.generateDeclaration("floatArrayIterator",
"private Iterator toIterator(final float[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return new Float(a[index++]);}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// double[]
ctxt.generateDeclaration("doubleArrayIterator",
"private Iterator toIterator(final double[] a){\n" +
" return (new Iterator() {\n" +
" int index=0;\n" +
" public boolean hasNext() {\n" +
" return index < a.length;}\n" +
" public Object next() {\n" +
" return new Double(a[index++]);}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
// Enumeration
ctxt.generateDeclaration("enumIterator",
"private Iterator toIterator(final Enumeration e){\n" +
" return (new Iterator() {\n" +
" public boolean hasNext() {\n" +
" return e.hasMoreElements();}\n" +
" public Object next() {\n" +
" return e.nextElement();}\n" +
" public void remove() {}\n" +
" });\n" +
"}"
);
}
}