📄 valuestack.java
字号:
segment = segments[segmentIdx++];
// if we don't need to search through the stack then return the value
// this is very unlikely to happen, but we have account for it anyway
if (segment == null)
return value;
break;
default:
if (valueList.size() < 1)
return null;
// set up the stack pointer, and current value
stackIdx = valueList.size() - 1;
try {
value = valueList.get(stackIdx);
} catch (IndexOutOfBoundsException e) {
return null;
//throw new IllegalArgumentException("Illegal valuestack query:"+q);
}
break;
}
//log.debug( "first segment id: '" + segment.getId() + "' segment type: '" + segment.getType() + "'" );
/////////////////////////////////////////////////////////////////////////
// Now that stack has been set up and the context set (valueIdx) we will
// begin parsing the rest of the expression and drilling down through
// the object properties, collection elements, and method calls.
/////////////////////////////////////////////////////////////////////////
int saveSegmentIdx = segmentIdx;
while (true) {
//log.debug("beginning valuestack search at level: '" + stackIdx);
int workStackIdx = stackIdx;
if (value != null) {
objectWalk: do {
switch (segment.getType()) {
// access a classes property
case QuerySegment.PROPERTY:
// get the real value
if (value instanceof ValueHolder)
value = ((ValueHolder) value).getValue();
// If the value is null we break out now since it
// would only result in an exception anyway
if (value == null)
break objectWalk;
//log.debug( "PROPERTY: attempting to get: " + segment.getId() );
try {
MethodInfo[] methods = getMethod(value.getClass(), segment.getId());
if (methods == null) {
//log.debug( "PROPERTY: method not found: '" + segment.getId() + "' current value: '" + value + "' (" + value.getClass() + ")");
value = null;
break objectWalk;
} else {
value = methods[0].getMethod().invoke(value, null);
//log.debug( "PROPERTY: found property value: " + value + " (" + value.getClass() + ")");
}
} catch (Exception e) {
//log.debug( "PROPERTY: method called failed: " + e.getMessage() );
value = null;
break objectWalk;
}
break;
// access a class method
case QuerySegment.METHOD:
// get the real value
if (value instanceof ValueHolder)
value = ((ValueHolder) value).getValue();
// If the value is null we break out now since it
// would only result in an exception anyway
if (value == null)
break objectWalk;
//log.debug( "going after method: " + segment.getId() );
Object[] params = null;
MethodInfo target = null;
try {
MethodInfo[] methods = getMethod(value.getClass(), segment.getId());
if (methods == null) {
//log.debug( "METHOD: " + segment.getId() + " was not found." );
value = null;
break objectWalk;
}
List pValueList = segment.getValues();
int vsize = pValueList.size();
params = new Object[vsize];
for(int i=0; i < vsize; i++)
{
Object param = findValue((Query) pValueList.get(i));
params[i] = param;
}
target = findMethod(methods, params);
if(target==null)
{
log.error("No method found for " + segment.getId() + " with parameters " + Arrays.asList(getParameterClasses(params)) + " in class " + value.getClass());
value = null;
break objectWalk;
}
// Convert if necessary
Class[] parameterTypes = target.getParameterTypes();
int paramCount = parameterTypes.length;
for (int i = 0; i < paramCount; i++) {
Class parameterClass = parameterTypes[i];
Object parami = params[i];
//log.debug(paramCount + ": " + parameterClass.getName());
// If the parameter is not a String then we might try converting it
if (!parameterClass.equals(String.class))
{
// If the parameter is null we will not try a conversion
if (parami == null)
{
// If the parameterClass is primitive then null is not an acceptable argument
if (parameterClass.isPrimitive())
{
value = null;
break objectWalk;
}
}
else if (!parameterClass.equals(parami.getClass()) && !parameterClass.isAssignableFrom(parami.getClass())) {
// Get property editor
PropertyEditor pe = BeanUtil.getPropertyEditor(parameterClass);
// Convert value
if (pe != null) {
Object param = BeanUtil.getAsValue(pe, parami.toString());
//replace with the converted value
params[i] = param;
}
}
}
}
value = target.getMethod().invoke(value, params);
} catch (IllegalArgumentException e) {
log.error("Illegal parameters invoking " + value.getClass() + "." + target.getMethod().getName() + "(" +Arrays.asList(getParameterClasses(params)) + ")");
} catch (Exception e) {
log.error("METHOD: \"" + segment.getId() + "\", exception: ", e);
value = null;
break objectWalk;
//throw new IllegalArgumentException("Invalid single method access. " +
// "Error accessing method \"" + token.image +
// "\" using parameter: \"" + param + "\"");
}
break;
// access the current value as a collection
case QuerySegment.COLLECTION:
// get the real value
if (value instanceof ValueHolder)
value = ((ValueHolder) value).getValue();
// If the value is null we break out now since it
// would result in an uncaught exception otherwise
if (value == null)
break objectWalk;
Object key = findValue(segment.getQuery());
if (key == null) {
value = null;
break objectWalk;
}
// Map
if (Map.class.isAssignableFrom(value.getClass())) {
value = ((Map) value).get(key);
break;
}
// Resource Bundle
else if (ResourceBundle.class.isAssignableFrom(value.getClass())) {
value = ((ResourceBundle) value).getObject(key.toString());
break;
}
// Array
else if (value.getClass().isArray()) {
value = ((Object[]) value)[((Integer) key).intValue()];
break;
}
// List
else if (List.class.isAssignableFrom(value.getClass())) {
value = ((List) value).get(((Integer) key).intValue());
break;
}
// Collection
else if (Collection.class.isAssignableFrom(value.getClass())) {
// Not very efficient, but at least it works
value = ((Collection) value).toArray()[((Integer) key).intValue()];
break;
}
// fail if the user tries to access something other than a Collection
value = null;
break objectWalk;
// access the parent by going up one level on the stack
case QuerySegment.PARENT:
workStackIdx--;
if (workStackIdx < 0) {
value = null;
break objectWalk;
//throw new IllegalArgumentException("Parent object not available.");
} else {
value = valueList.get(workStackIdx);
}
break;
// currently we only allow to expand properties (no parameter methods)
case QuerySegment.EXPAND:
//log.debug( "EXPAND: going after: " + segment.getId() );
try {
Object methodName = findValue(segment.getQuery());
if (methodName == null) {
value = null;
break objectWalk;
}
value = findValue(methodName.toString());
} catch (Exception e) {
value = null;
break objectWalk;
}
break;
}
//log.debug( "finished case statement" );
// always have the next segment ready to go
segment = segments[segmentIdx++];
} while (segment != null);
}
// if we didn't find the value, then move one down the stack and
// try again.
if (value == null && stackIdx > 0) {
stackIdx--;
value = valueList.get(stackIdx);
// reset the segment index to reset the search
segmentIdx = saveSegmentIdx;
segment = segments[segmentIdx - 1];
} else {
break;
}
}
// get the real value
if (value instanceof ValueHolder)
value = ((ValueHolder) value).getValue();
// if (value == null && log.isDebugEnabled())
// log.debug("value for [" + q + "] is null.");
return value;
}
private Object[] getParameterClasses(Object[] params) {
Object[] classes = new Object[params.length];
for(int i = 0; i < params.length; i++) {
classes[i] = params[i]!=null ? params[i].getClass() : null;
}
return classes;
}
/**
* Return a string representation of the Stack
*
* @return the stack as a String
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -