commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Adam J Chesney" <a...@multicom.co.uk>
Subject Re: [JXPath] Problem adding objects to an ArrayList Variable
Date Fri, 07 Feb 2003 15:59:21 GMT
Dimitri,

<snip>
> > Hmmm. This seems a bit strange to me. It works for Maps (using put
instead
> > of add).
> Sure, a Map is not a Collection.
>

Good point. :)

<snip>
> > So you can see that the Map is mutable. I'm not sure how difficult it is
> to
> > allow for mutable Lists, but if I can't do things like:
> >
> > getValue("list:add($myList, 'hello')") returns: true
> >
> There is a sort-of round about way of getting to a list by reference.
> Create a wrapper for it and pass that wrapper to your own custom extension
> function, which would then add an element to the list.

Yes, that is a possibility.

>
> > I think it might be a show stopper for me. I am almost certainly trying
to
> > use JXPath in a way that was not intended. I am trying to build a 2 way
> data
> > binding mapping structure which I think JXPath is excellent for, but I
> would
> > also like to add some easy micro-scripting, which is maybe not possible
> with
> > JXPath.
> Right, I think you might be stretching JXPath's capabilities.  The
> getValue() method is supposed to be a query, that is a request without
side
> effects.

Thought so. However, it would make it a very cool tool indeed if it could be
used like that, no? It seems that JXPath is very close to allowing me to do
this.

>
> > One other thing, can you explain to me why the returned collections
should
> > be immutable? Is it necessary to enforce that behaviour?
> I make the collection immutable simply to get it to throw an exception. If
> the collection is mutable, operations changing it are successful, but
since
> the changes are made to some temporary collection, not the original one
you
> want to change.

I understand that if you are performing a query or a slice or something
(within an XPath) that you must have to create a temporary collection to
hold the result, however I still don't see why, if you are referencing a
whole collection (i.e. $myList), a copy is made before operating on it. I
still don't see the fundemental difference between this:

getValue("map:put($myMap, 'key', 'value')") returns: null

which calls 'put' on my original Map:

and this:

getValue("list:add($myList, 'hello')") returns: true

which calls 'add' on a temporary copy of my original list,

Why do we create a temporary structure just because the target  of the
ExtensionFunction is a Collection? Is it just because of the implementation
details, or is it by design?

Sorry for being a pain! :)


BTW - I have hacked a patch that allows XPaths like this:

context.createPathAndSetValue("$myList[-1]", "'hello'");

which now adds to the List. I had to do this because when I tried this:

context.createPathAndSetValue("$myList[last()+1]", "'hello'");

I got an exception:

org.apache.commons.jxpath.JXPathException: Cannot set value for xpath:
$myList[last()+1]

 at
org.apache.commons.jxpath.ri.JXPathContextReferenceImpl.setValue(JXPathConte
xtReferenceImpl.java:412)


I would have expected that my Factory would have been invoked in order to
expand the List, but it never got called.

Cheers,

Adam.







>
> > Thanks for your help,
>
> >
> > Adam.
>
> I hope this does not make jxpath completely unusable for you.
>
> - Dmitri
> >
> >
> >
> >
> > ----- Original Message -----
> > From: "Dmitri Plotnikov" <dplotnik@yahoo.com>
> > To: "Jakarta Commons Developers List" <commons-dev@jakarta.apache.org>
> > Sent: Thursday, February 06, 2003 9:47 PM
> > Subject: Re: [JXPath] Problem adding objects to an ArrayList Variable
> >
> >
> > > Adam,
> > >
> > > JXPath is in fact incapable of doing what you want it to do.  Before a
> > > collection is passed to an extension function, it undergoes some
> > > conversions, which make it unmodifiable.  JXPath should of course
throw
> > > an exception in this case.  I have added that exception and will check
> > > that new code in tonight.
> > >
> > > The rationale for this behavior is that from JXPath's perspective an
> > > extension function cannot take a collection by reference. Arguments of
> > > an extension function are either primitive values or "node sets",
which
> > > are really results of search.  JXPath finds all nodes matching the
> > > path, loads them into a list and then passes the list to the function.
> > > Consider for example this:
> > >
> > >    context.getValue("size(//foo[bar = 3])")
> > >
> > > From this example it should be clear that the argument of the function
> > > is in fact an unmodifiable collection - results of search.
> > >
> > > We could of course do something special for variables, but then the
> > > extension function's code would have to be aware of the difference
> > > between variables and general node sets.  I think we should avoid this
> > > implicit difference.
> > >
> > > What you could do to add a node to the collection is call
> > > createPathAndSetValue() with a path like "$myList[24]".
> > >
> > > Thanks for bringing this issue up - I should document it.
> > >
> > > - Dmitri
> > >
> > >
> > > --- Adam J Chesney <adam@multicom.co.uk> wrote:
> > > > Hi,
> > > >
> > > > Attached is a small test program that simply defines a Context like
> > > > this:
> > > >
> > > >  Object o = new Object ();
> > > >  JXPathContext context = JXPathContext.newContext( o );
> > > >  context.getVariables().declareVariable("myList", new ArrayList() );
> > > >
> > > >  FunctionLibrary library = new FunctionLibrary ();
> > > >  library.addFunctions( new ClassFunctions ( List.class, "list" ) );
> > > >  context.setFunctions( library );
> > > >
> > > > The output from executing several XPath expressions on it is thus:
> > > >
> > > > getValue("list:size($myList)") returns: 0
> > > >
> > > > getValue("list:add($myList, 'hello')") returns: true
> > > >
> > > > getValue("list:size($myList)") returns: 0
> > > >
> > > > getValue("$myList") returns: []
> > > >
> > > > I would expect the String 'hello' to be added to the list, and
> > > > therefore the second call to size should return 1.
> > > >
> > > > Am I doing something wrong here?
> > > >
> > > > Cheers,
> > > >
> > > > Adam
> > > >
> > > > =====================================================
> > > >
> > > > Tel:   (+44) 117 908 1254 (Direct)
> > > > Mobile (+44) 7780 962 961
> > > > email: adam@multicom.co.uk
> > > >
> > > > This communication is intended solely for the addressee and is
> > > > confidential.
> > > > If you are not the intended recipient, any disclosure, copying,
> > > > distribution
> > > > or any action taken or omitted to be taken in reliance on it, is
> > > > prohibited
> > > > and may be unlawful.
> > > >
> > > > Although this e-mail and any attachments are believed to be free of
> > > > any
> > > > virus, or any other defect which might affect any computer or IT
> > > > system into
> > > > which they are received and opened, it is the responsibility of the
> > > > recipient to ensure that they are virus free and no responsibility
is
> > > > accepted by Multicom Products Limited for any loss or damage arising
> > > > in any
> > > > way from receipt or use thereof.
> > > > > package test;
> > > >
> > > > import org.apache.commons.jxpath.*;
> > > > import java.util.*;
> > > >
> > > > /**
> > > >  * <p>Title: </p>
> > > >  * <p>Description: </p>
> > > >  * <p>Copyright: Copyright (c) 2003</p>
> > > >  * <p>Company: </p>
> > > >  * @author unascribed
> > > >  * @version 1.0
> > > >  */
> > > >
> > > > public class Test2
> > > > {
> > > >
> > > >   public static void main(String[] args)
> > > >     {
> > > >       try
> > > >       {
> > > > Object o = new Object ();
> > > > JXPathContext context = JXPathContext.newContext( o );
> > > > context.getVariables().declareVariable("myList", new ArrayList() );
> > > >
> > > > FunctionLibrary library = new FunctionLibrary ();
> > > > library.addFunctions( new ClassFunctions ( List.class, "list" ) );
> > > > context.setFunctions( library );
> > > >
> > > > getValue (context, "list:size($myList)");
> > > > getValue (context, "list:add($myList, 'hello')");
> > > > getValue (context, "list:size($myList)");
> > > > getValue (context, "$myList");
> > > >       }
> > > >       catch (Exception e1)
> > > >       {
> > > > e1.printStackTrace();
> > > >       }
> > > >   }
> > > >
> > > >   public static Object getValue ( JXPathContext context, String
xpath
> > > > )
> > > >   {
> > > >     Object obj = context.getValue( xpath );
> > > >     System.out.println("getValue(\"" + xpath + "\") returns: " +
obj
> > > > );
> > > >     return obj;
> > > >   }
> > > >
> > > > }
> > > > >
> > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> > > > For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> > >
> > >
> > > __________________________________________________
> > > Do you Yahoo!?
> > > Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
> > > http://mailplus.yahoo.com
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> > > For additional commands, e-mail: commons-dev-help@jakarta.apache.org
> >
>
>
> --------------------------------------------------------------------------
--
> ----
>
>
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message