You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2015/11/24 20:45:00 UTC

svn commit: r1716237 - in /commons/proper/jxpath/trunk/src: changes/ main/java/org/apache/commons/jxpath/ test/java/org/apache/commons/jxpath/issues/

Author: britter
Date: Tue Nov 24 19:45:00 2015
New Revision: 1716237

URL: http://svn.apache.org/viewvc?rev=1716237&view=rev
Log:
JXPATH-172: Clarify JavaDoc of JXPathContext#getPointer. Thanks to Michele Vivoda. This also fixes #4 from github.

Added:
    commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java
    commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172Test.java
Modified:
    commons/proper/jxpath/trunk/src/changes/changes.xml
    commons/proper/jxpath/trunk/src/main/java/org/apache/commons/jxpath/JXPathContext.java

Modified: commons/proper/jxpath/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/jxpath/trunk/src/changes/changes.xml?rev=1716237&r1=1716236&r2=1716237&view=diff
==============================================================================
--- commons/proper/jxpath/trunk/src/changes/changes.xml (original)
+++ commons/proper/jxpath/trunk/src/changes/changes.xml Tue Nov 24 19:45:00 2015
@@ -47,6 +47,9 @@ The <action> type attribute can be add,u
   <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>

Modified: commons/proper/jxpath/trunk/src/main/java/org/apache/commons/jxpath/JXPathContext.java
URL: http://svn.apache.org/viewvc/commons/proper/jxpath/trunk/src/main/java/org/apache/commons/jxpath/JXPathContext.java?rev=1716237&r1=1716236&r2=1716237&view=diff
==============================================================================
--- commons/proper/jxpath/trunk/src/main/java/org/apache/commons/jxpath/JXPathContext.java (original)
+++ commons/proper/jxpath/trunk/src/main/java/org/apache/commons/jxpath/JXPathContext.java Tue Nov 24 19:45:00 2015
@@ -365,6 +365,29 @@ import org.apache.commons.jxpath.util.Ke
  * 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 abstract class JXPathContext {
     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);
 

Added: commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java
URL: http://svn.apache.org/viewvc/commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java?rev=1716237&view=auto
==============================================================================
--- commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java (added)
+++ commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172DynamicTest.java Tue Nov 24 19:45:00 2015
@@ -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;
+    }
+
+}

Added: commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172Test.java
URL: http://svn.apache.org/viewvc/commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172Test.java?rev=1716237&view=auto
==============================================================================
--- commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172Test.java (added)
+++ commons/proper/jxpath/trunk/src/test/java/org/apache/commons/jxpath/issues/JXPath172Test.java Tue Nov 24 19:45:00 2015
@@ -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;
+        }
+    }
+
+}