You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by "Matt Benson (JIRA)" <ji...@apache.org> on 2007/01/11 00:19:27 UTC
[jira] Resolved: (JXPATH-10) [jxpath] JXPath 1.1 code using custom
functions failing when run in 1.2 onwards
[ https://issues.apache.org/jira/browse/JXPATH-10?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Matt Benson resolved JXPATH-10.
-------------------------------
Resolution: Fixed
Hi Paul, I have committed to SVN HEAD a TypeConverter implementation that bypasses the Pointer conversions introduced in version 1.2 . In order to use it, you must first execute the following:
TypeUtils.setTypeConverter(new JXPath11CompatibleTypeConverter());
And I think that's the best I'll be able to do for you.
> [jxpath] JXPath 1.1 code using custom functions failing when run in 1.2 onwards
> -------------------------------------------------------------------------------
>
> Key: JXPATH-10
> URL: https://issues.apache.org/jira/browse/JXPATH-10
> Project: Commons JXPath
> Issue Type: Bug
> Affects Versions: 1.2 Final
> Environment: Operating System: other
> Platform: PC
> Reporter: Paul Parisi
> Priority: Blocker
> Fix For: 1.3
>
>
> We have recently attempted to upgrade from a 1.1 release of jxpath
> to 1.2 and found a great deal of our jxpath code fails to run correctly.
> We isolated the problem to relating to the use of Custom Extension
> Functions and have included sample junit test case snippets that should
> demonstrate the issue clearly.
> The background on what we are trying to do with jxpath is as follows
> (included so its clear on what we are trying to use jxpath to achieve):
> Within our project, we make extensive use of Custom Extension Functions in JXPath.
> We also use JXPath variables significantly, in combination with these functions,
> that often take a JXPath variable as an argument(s) to the function.
> We now rely heavily on the use of the ExpressionContext interface as the first
> argument to many of our functions. The reason for this is that we need a
> convienient way to obtain access to 'original' object references within the
> context invoked by the function (as you would expect).
> However, we have also begun using a very useful combination of features, which
> the API supports in version 1.1, where the first argument always defines the
> ExpressionContext interface (which isn't really part of the method signature -
> from a caller perspective), and a 2nd argument as 'Object' type. Within body of
> the function, we then cast the object of the 2nd argument as a NodeSet (or
> define the NodeSet type within the method signature - either appears to work),
> which provides us with access to the pointers for the object.
> As previously mentioned, a jxpath variable is passed from the caller of the
> function (received via the 2nd argument in the method signature), which is
> automatically resolved, by jxpath, to the object itself.
> The benefit of casting the object to NodeSet (interface) enables us to retrieve
> the first pointer in the NodeSet list. The first pointer concerns us, as it
> refers to the String value passed to the argument of the function which we need
> access to. The object reference itself is of little concern in this case, as
> once we have access to the variable name sent to the function, we can access the
> object via the ExpressionContext.
> This all works fine in jxpath 1.1, however, in version 1.2 this functionality is
> now broken, since our objects are no longer being cast to NodeSet (previously
> achieved via the internal implementation of jxpath NodeSet using a SimpleNodeSet
> - as per inspecting jxpath 1.1 source code).
> Note on the use of ExpressionContext: For those methods that declare the
> ExpressionContext interface (which must be the first argument, if used), as part
> of the argument list, the method signature from the caller perspective, excludes
> it from the argument list, as it is implied by jxpath. In other words, there
> will be one less argument from the caller when the interface is used. In the
> case where this interface was the only argument, which is common, then the
> caller would be invoking a zero-argument method. This is behaviour we expect.
> Here is a simplified example of one of our functions using the techniques
> discussed:-
> public static void deleteSomeObject(ExpressionContext expContext, Object obj) {
> // create a local jxpath context to retrieve values for jxpath variables
> JXPathContext localContext = expContext.getJXPathContext();
> // Nodeset of the object passed to method
> NodeSet nodeset = (NodeSet)obj;
> // Retrieve variable name passed to function
> String declaredVariable = nodeset.getPointers().get(0).toString();
> Object objectToDelete = null;
> // If this method was passed the $obj1 var to delete, then retrieve 'Object Type
> 1' via $obj1 variable
> if (declaredVariable.equals("$obj1")) {
> objectToDelete = (ObjectType1)localContext.getValue("$obj1");
> }
> // If this method was passed the $obj2 var to delete, then retrieve 'Object
> Type 2' via $obj2 variable
> if (declaredVariable.equals("$obj2")) {
> objectToDelete = (ObjectType2)localContext.getValue("$obj2");
> }
> collectionOfSomeObjects.delete(objectToDelete);
> }
> Which would be used (called) in the following way:-
> ...
> // add to collection
> ObjectType1 objectType1 = new ObjectType1();
> ObjectType2 objectType2 = new ObjectType2();
> CollectionOfSomeObjects.add(objectType1);
> CollectionOfSomeObjects.add(objectType2);
> // add collection to jxpath context
> JXPathContext context = JXPathContext.newContext(collectionOfSomeObjects);
> // define jxpath variables
> context.getVariables().declareVariable("obj1", objectType1);
> context.getVariables().declareVariable("obj2", objectType2);
> // call jxpath Custom Extension Function
> String method2Invoke;
> method2Invoke = "ftn:deleteSomeObject($obj1)"
> context.getValue(method2Invoke); // ß invoke function & return value (for
> non-void methods)
> method2Invoke = "ftn:deleteSomeObject($obj2)"
> context.getValue(method2Invoke); // ß invoke function & return value (for
> non-void methods)
> In addition to the above example, I have prepared a suite of JUnit tests (&
> functions) that work against JXPath version 1.1,
> but fail against version 1.2. These code snippets can simply be dropped into
> the appropriate classes and executed.
> Also, I would like to note that the JXPath user guide is a little unclear with
> respect to the use of NodeSet's.
> After looking at many of the existing JUnit tests for JXPath, many un-documented
> features became evident & existing features became a little obscure, such as
> 'Collections as NodeSets'.
> The code examples provided should give you our perspective on it's use.
> CODE SNIPPETS BELOW TO INSERT INTO EXISTING JXPATH TEST SUITE:
> Below you will find two sections:-
> (1) JUnit Tests to test Extension Functions
> (2) Additional Extension Functions for these new tests
> ---------------------------------------------------------------------------------------------------------
> 3 JUnit Tests to add to 'ExtensionFunctionTest.java" (in package
> org.apache.commons.jxpath.ri.compiler) :
> /**
> * To test the use of NodeSet to retrieve String value passed to argument of
> method
> */
> public void testMyTestNodeSetOnly() {
>
> context.getVariables().declareVariable("obj1", new String("$12345.00"));
> assertXPathValue(
> context,
> "test:myTestNodeSetOnly($obj1)",
> "$obj1");
>
> }
> /**
> * To test the use of ContextExpression & NodeSet Combined
> */
> public void testMyTestContextExpressionAndNodeSetCombined() {
> HashMap map = new HashMap();
> map.put("1",new String("Item 1"));
> map.put("2",new String("Item 2"));
> map.put("3",new String("Item 3"));
>
> context.getVariables().declareVariable("obj2", map);
> assertXPathValue(
> context,
> "test:myTestContextExpressionAndNodeSetCombined($obj2)",
> "$obj2");
>
> }
>
> /**
> * To test the use of ContextExpression & NodeSet Combined with additional
> arguments
> */
> public void testMyTestContextExpressionAndNodeSetCombinedExtraArgs() {
> HashMap map = new HashMap();
> map.put("1",new String("Item 1"));
> map.put("2",new String("Item 2"));
> map.put("3",new String("Item 3"));
> HashMap map2 = new HashMap();
> map2.put("another collection",map);
> map2.put("a bean",new TestBean());
> TestBean testBean = new TestBean();
> Map beanMap = testBean.getMap();
> context.getVariables().declareVariable("obj1", beanMap);
> context.getVariables().declareVariable("obj2", map2);
> context.getVariables().declareVariable("obj3", testBean);
> context.getVariables().declareVariable("obj4", new Integer(10));
> assertXPathValue(
> context,
> "test:myTestContextExpressionAndNodeSetCombinedExtraArgs($obj1,
> $obj2, $obj3, $obj4)",
> "$obj1");
>
> }
>
> ---------------------------------------------------------------------------------------------------------
> 3 Additional Functions to add to 'TestFunctions.java' (in package
> org.apache.commons.jxpath.ri.compiler) :
>
>
> public static String myTestNodeSetOnly(NodeSet obj) {
> // Nodeset of the object passed to method
> NodeSet nodeset = (NodeSet)obj;
>
> // Retrieve variable name passed to function
> String declaredVariable = "";
> declaredVariable = nodeset.getPointers().get(0).toString();
>
> // for (int i=0; i < nodeset.getPointers().size();i++ ) {
> // declaredVariable = nodeset.getPointers().get(i).toString();
> // System.out.println(" declaredVariable Name = "+declaredVariable+"
> value ="+nodeset.getNodes().get(i));
> //
> // }
> // System.out.println(" declaredVariable Name = "+declaredVariable);
>
> return declaredVariable;
> }
> public static String
> myTestContextExpressionAndNodeSetCombined(ExpressionContext expContext, Object
> obj) {
> // create a local jxpath context to retrieve values for jxpath variables
> JXPathContext localContext = expContext.getJXPathContext();
> // Nodeset of the object passed to method
> NodeSet nodeset = (NodeSet)obj;
>
> // Retrieve variable name passed to function
> String declaredVariable = nodeset.getPointers().get(0).toString();
>
> // System.out.println(" declaredVariable Name = "+declaredVariable);
> HashMap object = (HashMap)localContext.getValue(declaredVariable);
> // System.out.println(" declaredVariable reference to object via context
> = "+object);
>
>
> return declaredVariable;
> }
> public static String
> myTestContextExpressionAndNodeSetCombinedExtraArgs(ExpressionContext expContext,
> Object obj1, Object obj2, Object obj3, Object obj4 ) {
> // create a local jxpath context to retrieve values for jxpath variables
> JXPathContext localContext = expContext.getJXPathContext();
> // Nodesets of the object(s) passed to method
> NodeSet nodeset1 = (NodeSet)obj1;
> NodeSet nodeset2 = (NodeSet)obj2;
> NodeSet nodeset3 = (NodeSet)obj3;
> NodeSet nodeset4 = (NodeSet)obj4;
>
> // Retrieve variable name passed to function
> String declaredVariable = nodeset1.getPointers().get(0).toString();
>
> // System.out.println(" declaredVariable 1 Name = "+declaredVariable);
> HashMap object = (HashMap)localContext.getValue(declaredVariable);
> // System.out.println(" declaredVariable reference to object via context
> = "+object);
>
> return declaredVariable;
> }
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org