foreachsupport.java
来自「jakarta-taglibs」· Java 代码 · 共 401 行 · 第 1/2 页
JAVA
401 行
/*
* 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.taglibs.standard.tag.common.core;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.jstl.core.LoopTagSupport;
import org.apache.taglibs.standard.resources.Resources;
/**
* <p>Support for tag handlers for <forEach>, the core iteration
* tag in JSTL 1.0. This class extends LoopTagSupport and provides
* ForEach-specific functionality. The rtexprvalue library and the
* expression-evaluating library each have handlers that extend this
* class.</p>
*
* <p>Localized here is the logic for handling the veritable smorgasbord
* of types supported by <forEach>, including arrays,
* Collections, and others. To see how the actual iteration is controlled,
* review the javax.servlet.jsp.jstl.core.LoopTagSupport class instead.
* </p>
*
* @see javax.servlet.jsp.jstl.core.LoopTagSupport
* @author Shawn Bayern
*/
public abstract class ForEachSupport extends LoopTagSupport {
//*********************************************************************
// Implementation overview
/*
* This particular handler is essentially a large switching mechanism
* to support the various types that the <forEach> tag handles. The
* class is organized around the private ForEachIterator interface,
* which serves as the basis for relaying information to the iteration
* implementation we inherit from LoopTagSupport.
*
* We expect to receive our 'items' from one of our subclasses
* (presumably from the rtexprvalue or expression-evaluating libraries).
* If 'items' is missing, we construct an Integer[] array representing
* iteration indices, in line with the spec draft. From doStartTag(),
* we analyze and 'digest' the data we're passed. Then, we simply
* relay items as necessary to the iteration implementation that
* we inherit from LoopTagSupport.
*/
//*********************************************************************
// Internal, supporting classes and interfaces
/*
* Acts as a focal point for converting the various types we support.
* It would have been ideal to use Iterator here except for one problem:
* Iterator.hasNext() and Iterator.next() can't throw the JspTagException
* we want to throw. So instead, we'll encapsulate the hasNext() and
* next() methods we want to provide inside this local class.
* (Other implementations are more than welcome to implement hasNext()
* and next() explicitly, not in terms of a back-end supporting class.
* For the forEach tag handler, however, this class acts as a convenient
* organizational mechanism, for we support so many different classes.
* This encapsulation makes it easier to localize implementations
* in support of particular types -- e.g., changing the implementation
* of primitive-array iteration to wrap primitives only on request,
* instead of in advance, would involve changing only those methods that
* handle primitive arrays.
*/
protected static interface ForEachIterator {
public boolean hasNext() throws JspTagException;
public Object next() throws JspTagException;
}
/*
* Simple implementation of ForEachIterator that adapts from
* an Iterator. This is appropriate for cases where hasNext() and
* next() don't need to throw JspTagException. Such cases are common.core.
*/
protected class SimpleForEachIterator implements ForEachIterator {
private Iterator i;
public SimpleForEachIterator(Iterator i) {
this.i = i;
}
public boolean hasNext() {
return i.hasNext();
}
public Object next() {
return i.next();
}
}
//*********************************************************************
// ForEach-specifc state (protected)
protected ForEachIterator items; // our 'digested' items
protected Object rawItems; // our 'raw' items
//*********************************************************************
// Iteration control methods (based on processed 'items' object)
// (We inherit semantics and Javadoc from LoopTagSupport.)
protected boolean hasNext() throws JspTagException {
return items.hasNext();
}
protected Object next() throws JspTagException {
return items.next();
}
protected void prepare() throws JspTagException {
// produce the right sort of ForEachIterator
if (rawItems != null) {
// extract an iterator over the 'items' we've got
items = supportedTypeForEachIterator(rawItems);
} else {
// no 'items', so use 'begin' and 'end'
items = beginEndForEachIterator();
}
/* ResultSet no more supported in <c:forEach>
// step must be 1 when ResultSet is passed in
if (rawItems instanceof ResultSet && step != 1)
throw new JspTagException(
Resources.getMessage("FOREACH_STEP_NO_RESULTSET"));
*/
}
//*********************************************************************
// Tag logic and lifecycle management
// Releases any resources we may have (or inherit)
public void release() {
super.release();
items = null;
rawItems = null;
}
//*********************************************************************
// Private generation methods for the ForEachIterators we produce
/* Extracts a ForEachIterator given an object of a supported type. */
protected ForEachIterator supportedTypeForEachIterator(Object o)
throws JspTagException {
/*
* This is, of necessity, just a big, simple chain, matching in
* order. Since we are passed on Object because of all the
* various types we support, we cannot rely on the language's
* mechanism for resolving overloaded methods. (Method overloading
* resolves via early binding, so the type of the 'o' reference,
* not the type of the eventual value that 'o' references, is
* all that's available.)
*
* Currently, we 'match' on the object we have through an
* if/else chain that picks the first interface (or class match)
* found for an Object.
*/
ForEachIterator items;
if (o instanceof Object[])
items = toForEachIterator((Object[]) o);
else if (o instanceof boolean[])
items = toForEachIterator((boolean[]) o);
else if (o instanceof byte[])
items = toForEachIterator((byte[]) o);
else if (o instanceof char[])
items = toForEachIterator((char[]) o);
else if (o instanceof short[])
items = toForEachIterator((short[]) o);
else if (o instanceof int[])
items = toForEachIterator((int[]) o);
else if (o instanceof long[])
items = toForEachIterator((long[]) o);
else if (o instanceof float[])
items = toForEachIterator((float[]) o);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?