1
2
3
4
5
6
7
8
9
10
11
12
13 package net.sf.oval.ogn;
14
15 import java.lang.reflect.AccessibleObject;
16 import java.util.Locale;
17
18 import net.sf.oval.exception.InvalidConfigurationException;
19 import net.sf.oval.internal.util.Assert;
20 import net.sf.oval.internal.util.ReflectionUtils;
21
22 import org.apache.commons.jxpath.JXPathBeanInfo;
23 import org.apache.commons.jxpath.JXPathContext;
24 import org.apache.commons.jxpath.JXPathIntrospector;
25 import org.apache.commons.jxpath.JXPathNotFoundException;
26 import org.apache.commons.jxpath.Pointer;
27 import org.apache.commons.jxpath.ri.JXPathContextReferenceImpl;
28 import org.apache.commons.jxpath.ri.QName;
29 import org.apache.commons.jxpath.ri.model.NodePointer;
30 import org.apache.commons.jxpath.ri.model.beans.BeanPointer;
31 import org.apache.commons.jxpath.ri.model.beans.BeanPointerFactory;
32 import org.apache.commons.jxpath.ri.model.beans.NullPointer;
33 import org.apache.commons.jxpath.ri.model.beans.NullPropertyPointer;
34 import org.apache.commons.jxpath.ri.model.beans.PropertyPointer;
35
36
37
38
39
40 public class ObjectGraphNavigatorJXPathImpl implements ObjectGraphNavigator
41 {
42 protected static final class BeanPointerEx extends BeanPointer
43 {
44 private static final long serialVersionUID = 1L;
45
46 private final JXPathBeanInfo beanInfo;
47
48 public BeanPointerEx(final NodePointer parent, final QName name, final Object bean, final JXPathBeanInfo beanInfo)
49 {
50 super(parent, name, bean, beanInfo);
51 this.beanInfo = beanInfo;
52 }
53
54 public BeanPointerEx(final QName name, final Object bean, final JXPathBeanInfo beanInfo, final Locale locale)
55 {
56 super(name, bean, beanInfo, locale);
57 this.beanInfo = beanInfo;
58 }
59
60 @Override
61 public boolean equals(final Object obj)
62 {
63 if (this == obj) return true;
64 if (!super.equals(obj)) return false;
65 if (getClass() != obj.getClass()) return false;
66 final BeanPointerEx other = (BeanPointerEx) obj;
67 if (beanInfo == null)
68 {
69 if (other.beanInfo != null) return false;
70 }
71 else if (!beanInfo.equals(other.beanInfo)) return false;
72 return true;
73 }
74
75 @Override
76 public boolean isValidProperty(final QName name)
77 {
78 if (!super.isValidProperty(name)) return false;
79
80
81 if (beanInfo.getPropertyDescriptor(name.getName()) == null)
82 throw new JXPathNotFoundException("No pointer for xpath: " + toString() + "/" + name);
83
84 return true;
85 }
86 }
87
88 protected static final class BeanPointerFactoryEx extends BeanPointerFactory
89 {
90 @Override
91 public NodePointer createNodePointer(final NodePointer parent, final QName name, final Object bean)
92 {
93 if (bean == null) return new NullPointer(parent, name);
94
95 final JXPathBeanInfo bi = JXPathIntrospector.getBeanInfo(bean.getClass());
96 return new BeanPointerEx(parent, name, bean, bi);
97 }
98
99 @Override
100 public NodePointer createNodePointer(final QName name, final Object bean, final Locale locale)
101 {
102 final JXPathBeanInfo bi = JXPathIntrospector.getBeanInfo(bean.getClass());
103 return new BeanPointerEx(name, bean, bi, locale);
104 }
105
106 @Override
107 public int getOrder()
108 {
109 return BeanPointerFactory.BEAN_POINTER_FACTORY_ORDER - 1;
110 }
111 }
112
113 static
114 {
115
116
117
118
119
120
121
122
123
124 JXPathContextReferenceImpl.addNodePointerFactory(new BeanPointerFactoryEx());
125 }
126
127 public ObjectGraphNavigationResult navigateTo(final Object root, final String xpath) throws InvalidConfigurationException
128 {
129 Assert.argumentNotNull("root", root);
130 Assert.argumentNotNull("xpath", xpath);
131
132 try
133 {
134 final JXPathContext ctx = JXPathContext.newContext(root);
135 ctx.setLenient(true);
136 final Pointer pointer = ctx.getPointer(xpath);
137
138 if (pointer instanceof NullPropertyPointer) return null;
139
140 if (pointer instanceof PropertyPointer)
141 {
142 final PropertyPointer pp = (PropertyPointer) pointer;
143 final Class< ? > beanClass = pp.getBean().getClass();
144 AccessibleObject accessor = ReflectionUtils.getField(beanClass, pp.getPropertyName());
145 if (accessor == null) accessor = ReflectionUtils.getGetter(beanClass, pp.getPropertyName());
146 return new ObjectGraphNavigationResult(root, xpath, pp.getBean(), accessor, pointer.getValue());
147 }
148
149 return new ObjectGraphNavigationResult(root, xpath, pointer.getNode(), null, pointer.getValue());
150 }
151 catch (final JXPathNotFoundException ex)
152 {
153
154 throw new InvalidConfigurationException(ex);
155 }
156 }
157 }