📄 valuestack.java
字号:
/*
* WebWork, Web Application Framework
*
* Distributable under Apache license.
* See terms of license at opensource.org
*/
package webwork.util;
import webwork.action.ActionContext;
import webwork.expr.Parser;
import java.beans.*;
import java.io.StringReader;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Value stack. A VS is used by the WebWork system as a way to make findInContext
* values available by using the push and pop methods. They can then
* be accessed by using the find* methods.
*
* @author Rickard 謆erg (rickard@middleware-company.com)
* @author Maurice C. Parker (maurice@vineyardenterprise.com)
* @version $Revision: 1.55 $
*/
public class ValueStack{
// Static -------------------------------------------------------
public static final String STACK_NAME = "webwork.result";
protected static Map classes = new HashMap(); // Method cache
private static Log log = LogFactory.getLog(ServletValueStack.class);
/**
* Clear the method cache. This must be called if the
* application is restarted.
*
*/
public static void clearMethods() {
classes = new HashMap();
}
// Attributes ----------------------------------------------------
private List valueList = Collections.EMPTY_LIST;
private Parser parser;
// Constructor ---------------------------------------------------
public ValueStack() {
}
// Public --------------------------------------------------------
/**
* Push a value onto the value stack.
*
* @param value the value
*/
public void pushValue(Object value) {
if (valueList == Collections.EMPTY_LIST) {
valueList = new ArrayList();
}
valueList.add(value);
// log.debug("Push to value stack:" + value);
// log.debug(toString());
// new Throwable().printStackTrace();
}
/**
* Pop a value from the value stack.
*
* @return the popped value
*/
public Object popValue() {
if (valueList == Collections.EMPTY_LIST)
return null;
try {
return valueList.remove(valueList.size() - 1);
} catch (IndexOutOfBoundsException e) {
return null;
} finally {
// log.debug("Pop from value stack:");
// log.debug(toString());
// new Throwable().printStackTrace();
}
}
public Iterator iterator() {
return valueList.iterator();
}
/**
* Returns the size of the value stack.
*
* @return size of value stack
*/
public int size() {
return valueList.size();
}
/**
* Returns TRUE is the value stack is empty.
*
* @return true is value stack is empty
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Resolve a WebWork expression statement.
*
* @param expression
* @return the boolean result of the expression
*/
public boolean test(String expression) {
if (expression==null) {
throw new NullPointerException("Expression cannot be null.");
}
boolean answer = false;
try
{
SimpleTest simpleTest = SimpleTest.getSimpleTest(expression);
if (simpleTest != null)
{
answer = simpleTest.test(this, null, null);
}
else
{
Parser p = getParser(expression);
answer = p.test();
}
} catch (Throwable pe) {
log.error("An error occurred while parsing the expression: \"" + expression + "\", throwable: ", pe);
throw new IllegalArgumentException("\n\nAn error occurred while parsing the expression: \n \"" +
expression + "\"\n" +
pe.getMessage());
}
return answer;
}
// SK
/** Find a value by id. This method can be overridden by subclasses to
* have some context concept to evaluate @identified expressions.
*/
protected Object findInContext(String id) {
return null;
}
/**
* Find a value for a given name.
*
* @param query
* @return the object corresponding to the query
*/
public Object findValue(String query)
throws IllegalArgumentException {
Query q;
if (query == null || query.length()==0 || (query.length()==1 && query.charAt(0)=='.'))
q = Query.CURRENT;
else
{
// The query segments and the current segment
q = Query.getQuery(query);
}
return findValue(q);
}
public Object findValue(Query q)
throws IllegalArgumentException {
// The query segments and the current segment
QuerySegment[] segments = q.getSegments();
// if (log.isDebugEnabled()) {
// log.debug("findValue() for: " + q);
// }
QuerySegment segment = segments[0];
int segmentIdx = 1;
// The current stack pointer, and the current object,
int stackIdx = 0;
Object value;
/////////////////////////////////////////////////////////////////////////
// evaluate the first element of the expression to see where to
// get the requested value. These should be quick and easy objects
// to find or create.
/////////////////////////////////////////////////////////////////////////
switch (segment.getType()) {
// get the top value off of the stack
case QuerySegment.CURRENT:
if (valueList.size() < 1)
return null;
// set up the stack, pointer, and current value
value = valueList.get(valueList.size()-1);
if (value instanceof ValueHolder)
value = ((ValueHolder) value).getValue();
// always have the next segment ready to go
segment = segments[segmentIdx++];
// if we don't need to get other values then return the value
if (segment == null)
return value;
// The stackIdx is already zero so we will not try to search the stack
break;
// return the id since it is the actual string
case QuerySegment.STRING:
return segment.getId();
// the integer is the first value and only value in the segment
case QuerySegment.NUMBER:
return segment.getValues().get(0);
// get an attribute
case QuerySegment.ATTRIBUTE:
// get the attribute
// SK
value=findInContext(segment.getId());
// /SK
if (value == null) {
// if (log.isDebugEnabled()) {
// log.debug("value for [" + q + "] is null.");
// }
return null;
//throw new IllegalArgumentException("No such attribute: " + token.image);
}
// get the real value
if (value instanceof ValueHolder)
value = ((ValueHolder) value).getValue();
// always have the next segment ready to go
segment = segments[segmentIdx++];
// if we don't need to search through this attribute simply return it
if (segment == null)
return value;
// The stackIdx is already zero so we will not try to search the stack
break;
// return the http request parameter
case QuerySegment.PARAMETER:
// SK
return getParameter(segment.getId());
// /SK
// the reserved keyword "true"
case QuerySegment.TRUE:
return Boolean.TRUE;
// the reserved keyword "false"
case QuerySegment.FALSE:
return Boolean.FALSE;
// the reserved keyword "null"
case QuerySegment.NULL:
return null;
// get the root object off of the bottom of the stack
case QuerySegment.ROOT:
if (valueList.size() < 1)
return null;
// The stackIdx is already zero so we will not try to search the stack
// set up the stack pointer, and current value
value = valueList.get(0);
// always have the next segment ready to go
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -