1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.jaxen;
5
6 import net.sourceforge.pmd.ast.Node;
7
8 import java.lang.reflect.InvocationTargetException;
9 import java.lang.reflect.Method;
10 import java.util.Iterator;
11 import java.util.Map;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.ArrayList;
15 import java.util.LinkedList;
16
17
18
19
20 public class AttributeAxisIterator implements Iterator {
21
22 private static class MethodWrapper {
23 public Method method;
24 public String name;
25 public MethodWrapper(Method m) {
26 this.method = m;
27 this.name = truncateMethodName(m.getName());
28 }
29 private String truncateMethodName(String n) {
30
31 if (n.startsWith("get")) {
32 n = n.substring("get".length());
33 } else if (n.startsWith("is")) {
34 n = n.substring("is".length());
35 } else if (n.startsWith("has")) {
36 n = n.substring("has".length());
37 } else if (n.startsWith("uses")) {
38 n = n.substring("uses".length());
39 }
40 return n;
41 }
42 }
43
44 private Object currObj;
45 private MethodWrapper[] methodWrappers;
46 private int position;
47 private Node node;
48
49 private static Map methodCache = new HashMap();
50
51 public AttributeAxisIterator(Node contextNode) {
52 this.node = contextNode;
53 if (!methodCache.containsKey(contextNode.getClass())) {
54 Method[] preFilter = contextNode.getClass().getMethods();
55 List postFilter = new ArrayList();
56 for (int i = 0; i<preFilter.length; i++) {
57 if (isAttribute(preFilter[i])) {
58 postFilter.add(new MethodWrapper(preFilter[i]));
59 }
60 }
61 methodCache.put(contextNode.getClass(), (MethodWrapper[])postFilter.toArray(new MethodWrapper[postFilter.size()]));
62 }
63 this.methodWrappers = (MethodWrapper[])methodCache.get(contextNode.getClass());
64
65 this.position = 0;
66 this.currObj = getNextAttribute();
67 }
68
69 public Object next() {
70 if (currObj == null) {
71 throw new IndexOutOfBoundsException();
72 }
73 Object ret = currObj;
74 currObj = getNextAttribute();
75 return ret;
76 }
77
78 public boolean hasNext() {
79 return currObj != null;
80 }
81
82 public void remove() {
83 throw new UnsupportedOperationException();
84 }
85
86 private Attribute getNextAttribute() {
87 if (position == methodWrappers.length) {
88 return null;
89 }
90 MethodWrapper m = methodWrappers[position];
91 position++;
92 return new Attribute(node, m.name, m.method);
93 }
94
95 protected boolean isAttribute(Method method) {
96 return (Integer.TYPE == method.getReturnType() || Boolean.TYPE == method.getReturnType() || String.class == method.getReturnType())
97 && (method.getParameterTypes().length == 0)
98 && (Void.TYPE != method.getReturnType())
99 && !method.getName().startsWith("jjt")
100 && !method.getName().equals("toString")
101 && !method.getName().equals("getScope")
102 && !method.getName().equals("getClass")
103 && !method.getName().equals("getTypeNameNode")
104 && !method.getName().equals("getImportedNameNode")
105 && !method.getName().equals("hashCode");
106 }
107 }