Hello!
I'm using JXPath as part of a little DSL that is supposed to be maintained by
non-developers. Therefore, it would be handy if I could validate the JXPath
expressions against the interface of the object tree that they should match.
Ideally that should happen before the actual object instances are created.
I tried to get along setting lenient to false, thus evaluating the exceptions.
The problem with this approach that I can't distinguish whether I get a
JXPathNotFoundException due to a missing object instance or due to an invalid
property name, when the XPath expression steps across a null return value or an
empty list. The unit test below illustrates this behavior.
So my question is if, given the object tree interface, there is a possibility
to tell whether the JXPath expression describes a possible path along that
tree. It would be very helpful to detect typos or missing steps.
Thank you!
Heike
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathNotFoundException;
import org.junit.Test;
public class LenientJXPathTest
{
public static class MyBean
{
public String getValue()
{
return "Hello World!";
}
public MyOtherBean getNull()
{
return null;
}
public List<MyOtherBean> getList()
{
return Collections.<MyOtherBean> emptyList();
}
public List<MyOtherBean> getNonEmptyList()
{
final ArrayList<MyOtherBean> list = new ArrayList<MyOtherBean>();
list.add(new MyOtherBean());
return list;
}
public List<Object> getNullList()
{
return null;
}
}
public static class MyOtherBean
{
public String getValue()
{
return "Hello World!";
}
}
static final MyBean bean = new MyBean();
/* Can't distinguish the cause of the exception from the cause in the
following test case. */
@Test(expected = JXPathNotFoundException.class)
public void testExceptionBecauseOfMissingObjectWhenPathGoesAcrossEmptyList()
{
final JXPathContext context = JXPathContext.newContext(bean);
context.setLenient(false);
context.getValue("/list[@value='Hello World!']");
}
/* Can't distinguish the cause of the exception from the cause in the
preceding test case. */
@Test(expected = JXPathNotFoundException.class)
public void testExceptionDueToBadPropertyNameWhenPathGoesAcrossEmptyList()
{
final JXPathContext context = JXPathContext.newContext(bean);
context.setLenient(false);
context.getValue("/nonEmptyList[@dosentexist='Hello World!']");
}
/* Can't tell whether I get the exception due to a null instance or an
invalid property name. */
@Test(expected = JXPathNotFoundException.class)
public void testExceptionBecauseOfMissingObjectWhenPathGoesAcrossNull()
{
final JXPathContext context = JXPathContext.newContext(bean);
context.setLenient(false);
context.getValue("/null/doesnotexist");
}
}