/* | |
* Licensed to the Apache Software Foundation (ASF) under one or more | |
* contributor license agreements. See the NOTICE file distributed with | |
* this work for additional information regarding copyright ownership. | |
* The ASF licenses this file to You 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.struts2.jasper.tagplugins.jstl.core; | |
import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin; | |
import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext; | |
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" + | |
"}" | |
); | |
} | |
} |