/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.xpath;
import java.util.Arrays;
import java.util.List;
import org.jaxen.Context;
import org.jaxen.Function;
import org.jaxen.FunctionCallException;
import org.jaxen.SimpleFunctionContext;
import org.jaxen.XPathFunctionContext;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.xpath.Attribute;
import net.sourceforge.pmd.lang.java.ast.TypeNode;
public class TypeOfFunction implements Function {
public static void registerSelfInSimpleContext() {
((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "typeof",
new TypeOfFunction());
}
public Object call(Context context, List args) throws FunctionCallException {
String nodeTypeName = null;
String fullTypeName = null;
String shortTypeName = null;
Attribute attr = null;
for (int i = 0; i < args.size(); i++) {
if (args.get(i) instanceof List) {
if (attr == null) {
attr = ((List<Attribute>) args.get(i)).get(0);
nodeTypeName = attr.getStringValue();
} else {
throw new IllegalArgumentException(
"typeof function can take only a single argument which is an Attribute.");
}
} else {
if (fullTypeName == null) {
fullTypeName = (String) args.get(i);
} else if (shortTypeName == null) {
shortTypeName = (String) args.get(i);
} else {
break;
}
}
}
if (fullTypeName == null) {
throw new IllegalArgumentException(
"typeof function must be given at least one String argument for the fully qualified type name.");
}
Node n = (Node) context.getNodeSet().get(0);
return typeof(n, nodeTypeName, fullTypeName, shortTypeName);
}
// TEST //ClassOrInterfaceType[typeof(@Image, 'java.lang.String')]
public static boolean typeof(Node n, String nodeTypeName, String fullTypeName, String shortTypeName) {
if (n instanceof TypeNode) {
Class<?> type = ((TypeNode) n).getType();
if (type == null) {
return nodeTypeName != null
&& (nodeTypeName.equals(fullTypeName) || nodeTypeName.equals(shortTypeName));
}
if (type.getName().equals(fullTypeName)) {
return true;
}
List<Class<?>> implementors = Arrays.asList(type.getInterfaces());
if (implementors.contains(type)) {
return true;
}
Class<?> superC = type.getSuperclass();
while (superC != null && !superC.equals(Object.class)) {
if (superC.getName().equals(fullTypeName)) {
return true;
}
superC = superC.getSuperclass();
}
} else {
throw new IllegalArgumentException("typeof function may only be called on a TypeNode.");
}
return false;
}
}