Skip to content
Permalink
Browse files
JXPATH-172: Clarify JavaDoc of JXPathContext#getPointer. Thanks to Mi…
…chele Vivoda. This also fixes #4 from github.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/jxpath/trunk@1716237 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
britter committed Nov 24, 2015
1 parent 96c4ad9 commit 99d8699abf36807b6d1745e4d6515a58015e0bee
Showing 4 changed files with 327 additions and 5 deletions.
@@ -47,6 +47,9 @@ The <action> type attribute can be add,update,fix,remove.
<body>
<!-- The release date is the date RC is cut -->
<release version="1.4" date="2014-??-??" description="New features and bug fixes.">
<action issue="JXPATH-172" dev="britter" type="update" due-to="Michele Vivoda">
Clarify JavaDoc of JXPathContext#getPointer
</action>
<action issue="JXPATH-113" dev="britter" type="fix" due-to="Michele Vivoda">
NullPointerException in ChildContext when document only contains an empty root node
</action>
@@ -365,6 +365,29 @@
* XPaths like "para[@type='warning']" are legitimate, they will always produce
* empty results. The only attribute supported for JavaBeans is "name". The
* XPath "foo/bar" is equivalent to "foo[@name='bar']".
*
* <li id='matches_no_property_in_the_graph'>The term <b>matches no property in
* the graph</b> is used throughout the documentation. It describes a property or
* path that can be determined as not belonging to the graph. Determining
* whether a property or path belongs to the graph depends on the type of object
* being used as {@code cotextBean} (see {@link #newContext(Object)}).
* It is only possible strongly typed models where a specific Java model is used
* as context. It is not possible with dynamic models such Maps or DOM
* implementations.
* <p>When a XPath does not match a property in the graph, the methods of this
* class that retrieve a pointer will generally behave in the following way,
* depending on the last value configured with {@link #setLenient(boolean)}:</p>
*
* <ol style='list-style:upper-alpha'>
* <li>If <code>lenient</code> is <code>false</code> (default) - methods
* will throw {@link JXPathNotFoundException}.
* <li>If <code>lenient</code> is <code>true</code> - methods will throw
* no exception and return a value appropriate for that method to
* express the absence: might be a Java <code>null</code> or a
* {@link Pointer} whose {@link Pointer#getValue()} returns
* <code>null</code>, depends on the method.
* </ol>
* </li>
* </ul>
*
* See <a href="http://www.w3schools.com/xpath">XPath Tutorial by
@@ -772,12 +795,22 @@ public List selectNodes(String xpath) {
public abstract Iterator iterate(String xpath);

/**
* Traverses the xpath and returns a Pointer.
* A Pointer provides easy access to a property.
* If the xpath matches no properties
* in the graph, the pointer will be null.
* Traverses the xpath and returns a Pointer. A Pointer provides easy access
* to a property.
* <p>
* If the xpath <a href='#matches_no_property_in_the_graph'>matches no
* properties in the graph</a> the behavior depends on the value that has
* been configured with {@link #setLenient(boolean)}:</p>
* <ul>
* <li> <code>false</code> (default) the method will throw a
* {@link JXPathNotFoundException}.
* <li> <code>true</code> the method returns a pointer whose
* {@link Pointer#getValue()} method will always return null.
* </ul>
*
* @param xpath desired
* @return Pointer
* @return Pointer A {@link Pointer}, never <code>null</code>.
* @throws JXPathNotFoundException see method description.
*/
public abstract Pointer getPointer(String xpath);

@@ -0,0 +1,130 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jxpath.issues;

import java.util.HashMap;

import junit.framework.TestSuite;

import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathTestCase;
import org.apache.commons.jxpath.Pointer;
import org.apache.commons.jxpath.ri.model.dynamic.DynamicPropertyPointer;

public class JXPath172DynamicTest extends JXPathTestCase
{

/**
* Return the tests included in this test suite.
*/
public static TestSuite suite()
{
return (new TestSuite(JXPath172DynamicTest.class));
}

public void testIssue172_propertyExistAndIsNotNull()
{
final JXPathContext context = getContext("ciao", false);
final Object bRet = context.selectSingleNode("value");
assertNotNull("null!!", bRet);
assertEquals("Is " + bRet.getClass(), "ciao", bRet);

final Pointer pointer = context.getPointer("value");
assertNotNull(pointer);
assertEquals(DynamicPropertyPointer.class, pointer.getClass());
assertEquals("ciao", pointer.getValue());
}

public void testIssue172_propertyExistAndIsNull()
{
final JXPathContext context = getContext(null, false);
final Object bRet = context.selectSingleNode("value");
assertNull("not null!!", bRet);

final Pointer pointer = context.getPointer("value");
assertNotNull(pointer);
assertEquals(DynamicPropertyPointer.class, pointer.getClass());
assertNull(pointer.getValue());
}

public void testIssue172_propertyDoesNotExist()
{
final JXPathContext context = getContext(null, false);
final Object bRet = context.selectSingleNode("unexisting");
assertNull(bRet);

final Pointer pointer = context.getPointer("unexisting");
assertEquals(DynamicPropertyPointer.class, pointer.getClass());
assertNull(pointer.getValue());

}

public void testIssue172_propertyDoesNotExist_Lenient()
{
final JXPathContext context = getContext(null, true);
final Object bRet = context.selectSingleNode("unexisting");
assertNull(bRet);

final Pointer pointer = context.getPointer("unexisting");
assertEquals(DynamicPropertyPointer.class, pointer.getClass());
assertNull(pointer.getValue());

}

public void testIssue172_nestedpropertyDoesNotExist_Lenient()
{
final JXPathContext context = getContext(null, true);
final Object bRet = context.selectSingleNode("value.unexisting");
assertNull(bRet);

final Pointer pointer = context.getPointer("value.unexisting");
assertEquals(DynamicPropertyPointer.class, pointer.getClass());
assertNull(pointer.getValue());

}

public void testIssue172_nestedpropertyDoesNotExist_NotLenient()
{
final JXPathContext context = getContext(null, false);
final Object bRet = context.selectSingleNode("value.unexisting");
assertNull(bRet);

final Pointer pointer = context.getPointer("value.unexisting");
assertEquals(DynamicPropertyPointer.class, pointer.getClass());
assertNull(pointer.getValue());

}

/**
* Helper, returns a {@link JXPathContext} filled with a Map whose "value"
* key is associated to the passed <code>val</code> value.
*
* @param val
* @return A {@link JXPathContext}, never <code>null</code>.
*/
private JXPathContext getContext(final String val, boolean lenient)
{
final HashMap map = new HashMap();
// if (val!=null) // no diffs
map.put("value", val);
final Object target = map;
final JXPathContext context = JXPathContext.newContext(null, target);
context.setLenient(lenient);
return context;
}

}
@@ -0,0 +1,156 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jxpath.issues;

import junit.framework.TestSuite;

import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathNotFoundException;
import org.apache.commons.jxpath.JXPathTestCase;
import org.apache.commons.jxpath.Pointer;
import org.apache.commons.jxpath.ri.model.beans.BeanPropertyPointer;
import org.apache.commons.jxpath.ri.model.beans.NullPropertyPointer;

public class JXPath172Test extends JXPathTestCase
{

/**
* Return the tests included in this test suite.
*/
public static TestSuite suite()
{
return (new TestSuite(JXPath172Test.class));
}

public void testIssue172_propertyExistAndIsNotNull()
{
final JXPathContext context = getContext("ciao", false);
final Object bRet = context.selectSingleNode("value");
assertNotNull("null!!", bRet);
assertEquals("Is " + bRet.getClass(), "ciao", bRet);

final Pointer pointer = context.getPointer("value");
assertNotNull(pointer);
assertEquals(BeanPropertyPointer.class, pointer.getClass());
assertEquals("ciao", pointer.getValue());
}

public void testIssue172_propertyExistAndIsNull()
{
final JXPathContext context = getContext(null, false);
final Object bRet = context.selectSingleNode("value");
assertNull("not null!!", bRet);

final Pointer pointer = context.getPointer("value");
assertNotNull(pointer);
assertEquals(BeanPropertyPointer.class, pointer.getClass());
assertNull(pointer.getValue());
}

public void testIssue172_PropertyUnexisting()
{
final JXPathContext context = getContext(null, true);
final Object bRet = context.selectSingleNode("unexisting");
assertNull("not null!!", bRet);

final Pointer pointer = context.getPointer("unexisting");
assertNotNull(pointer);
assertEquals(NullPropertyPointer.class, pointer.getClass());
assertNull(pointer.getValue());
}

public void testIssue172_NestedPropertyUnexisting()
{
final JXPathContext context = getContext(null, true);
final Object bRet = context.selectSingleNode("value.child");
assertNull("not null!!", bRet);

final Pointer pointer = context.getPointer("value.child");
assertNotNull(pointer);
assertEquals(NullPropertyPointer.class, pointer.getClass());
assertNull(pointer.getValue());
}

public void testIssue172_propertyDoesNotExist_NotLenient()
{
final JXPathContext context = getContext(null, false);
try
{
final Object bRet = context.selectSingleNode("unexisting");
fail(" " + bRet);
}
catch (JXPathNotFoundException e)
{

}

try
{
final Pointer pointer = context.getPointer("unexisting");
fail(" " + pointer);
}
catch (JXPathNotFoundException e)
{

}

try
{
final Pointer pointer = context.getPointer("value.unexisting");
fail(" " + pointer);
}
catch (JXPathNotFoundException e)
{

}

}

/**
* Helper, returns a {@link JXPathContext} filled with {@link TestBean172}
* whose {@link TestBean172#getValue()} method returns the passed
* <code>val</code> value.
*
* @param val
* @return A {@link JXPathContext}, never <code>null</code>.
*/
private JXPathContext getContext(final String val, boolean lenient)
{
final TestBean172 b = new TestBean172();
b.setValue(val);
final Object target = b;
final JXPathContext context = JXPathContext.newContext(null, target);
context.setLenient(lenient);
return context;
}

public static class TestBean172
{
String value;

public String getValue()
{
return value;
}

public void setValue(String value)
{
this.value = value;
}
}

}

0 comments on commit 99d8699

Please sign in to comment.