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