1
2
3
4 package net.sourceforge.pmd.lang.java.xpath;
5
6 import java.util.Arrays;
7 import java.util.List;
8
9 import net.sourceforge.pmd.lang.ast.Node;
10 import net.sourceforge.pmd.lang.ast.xpath.Attribute;
11 import net.sourceforge.pmd.lang.java.ast.TypeNode;
12
13 import org.jaxen.Context;
14 import org.jaxen.Function;
15 import org.jaxen.FunctionCallException;
16 import org.jaxen.SimpleFunctionContext;
17 import org.jaxen.XPathFunctionContext;
18
19 public class TypeOfFunction implements Function {
20
21 public static void registerSelfInSimpleContext() {
22 ((SimpleFunctionContext) XPathFunctionContext.getInstance()).registerFunction(null, "typeof",
23 new TypeOfFunction());
24 }
25
26 public Object call(Context context, List args) throws FunctionCallException {
27
28 String nodeTypeName = null;
29 String fullTypeName = null;
30 String shortTypeName = null;
31 Attribute attr = null;
32 for (int i = 0; i < args.size(); i++) {
33 if (args.get(i) instanceof List) {
34 if (attr == null) {
35 attr = (Attribute) ((List) args.get(i)).get(0);
36 nodeTypeName = attr.getStringValue();
37 } else {
38 throw new IllegalArgumentException(
39 "typeof function can take only a single argument which is an Attribute.");
40 }
41 } else {
42 if (fullTypeName == null) {
43 fullTypeName = (String) args.get(i);
44 } else if (shortTypeName == null) {
45 shortTypeName = (String) args.get(i);
46 } else {
47 break;
48 }
49 }
50 }
51 if (fullTypeName == null) {
52 throw new IllegalArgumentException(
53 "typeof function must be given at least one String argument for the fully qualified type name.");
54 }
55 Node n = (Node) context.getNodeSet().get(0);
56 return typeof(n, nodeTypeName, fullTypeName, shortTypeName);
57 }
58
59
60 public static boolean typeof(Node n, String nodeTypeName, String fullTypeName, String shortTypeName) {
61 if (n instanceof TypeNode) {
62 Class type = ((TypeNode) n).getType();
63 if (type == null) {
64 return nodeTypeName != null
65 && (nodeTypeName.equals(fullTypeName) || nodeTypeName.equals(shortTypeName));
66 }
67 if (type.getName().equals(fullTypeName)) {
68 return true;
69 }
70 List<Class> implementors = Arrays.asList(type.getInterfaces());
71 if (implementors.contains(type)) {
72 return true;
73 }
74 Class<?> superC = type.getSuperclass();
75 while (superC != null && !superC.equals(Object.class)) {
76 if (superC.getName().equals(fullTypeName)) {
77 return true;
78 }
79 superC = superC.getSuperclass();
80 }
81 } else {
82 throw new IllegalArgumentException("typeof function may only be called on a TypeNode.");
83 }
84 return false;
85 }
86 }