View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
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 = ((List<Attribute>) 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      // TEST //ClassOrInterfaceType[typeof(@Image, 'java.lang.String')]
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  }