Re: JXPath over Generic Collection?, How?
A whirl and a win! I'm very close to a complete solution here (with loads of assistance from Matt, THANK YOU) based on Dyna Beans however there is one remaining problem (since we have duplicate elements). According to: http://www.w3.org/TR/xpath#path-abbrev http://www.w3.org/TR/xpath#path-abbrev * selects all element children of the context node Expression: '/root/animal/dog/*' should return all dog's, instead it returns the first() dog (BOXER) only. I am unsure if this in an unrealistic requirement of JXPath and also where should I look to possibly 'fix' this if it indeed would compliment the current features? Thanks HEAPS! On Thu, Mar 5, 2009 at 3:05 AM, Matt Benson gudnabr...@yahoo.com wrote: Apparently the reason I was so ready to agree this was a bug that should be fixed is that I already fixed it as http://issues.apache.org/jira/browse/JXPATH-128 . So since you're already experienced with building JXPath now you should be able to build from svn trunk and give that a whirl. -Matt --- On Wed, 3/4/09, Matt Benson gudnabr...@yahoo.com wrote: From: Matt Benson gudnabr...@yahoo.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, March 4, 2009, 7:57 AM Hi Andrew, I agree that going through the list of properties should avoid the explicit class check problem (I think this is because you are using LazyDynaBeans instead of regular DynaBeans). As for returning all matches vs. the first match, rather than selectValue(...) you need to selectNodes(...), or iterate(...). There are other useful methods, e.g. those dealing with pointers, also available on JXPathContext. So as for your bug, yes it can/should be fixed, but you might also consider whether you can use non-lazy DynaBeans instead. Regards, Matt --- On Tue, 3/3/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, March 3, 2009, 5:37 PM For efficiency reasons I can see why you are using String[] here and not List.add()... Anyway, I have a fix (sort of) for this bug. The number of names needs to be calculated a little differently to what it currently is... public String[] getPropertyNames() { /* @todo do something about the sorting - LIKE WHAT? - MJB */ if (names == null) { DynaClass dynaClass = dynaBean.getDynaClass(); DynaProperty[] properties = dynaClass.getDynaProperties(); int count = properties.length; boolean hasClass = dynaClass.getDynaProperty(class) != null; //count the number of property names we have count = 0; for (int i = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { count++; //it's only a property is it's not a class and doesn't just have a class property. } } //read the property names into a String[] to return names = new String[count]; for (int i = 0, j = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { names[j++] = name; } } Arrays.sort(names); } return names; } Now I can sort of sucessfully run all my expressions, yippee!! However, I now have a problem with multiple deep results. Queries like //dog/* I would expect to return all dog's[] but this just returns the first one it finds. Maybe this is asking a little too much of JXPath and child/node step-up/step-down traversal? Matt can probably tell me if this is or is not the case plase :) On Wed, Mar 4, 2009 at 9:38 AM, Andrew Hughes ahhug...@gmail.com wrote: Pretty sure this is a bug in JXPath - and it is not tested by the current unit tests. I can't quite work out 100% of what's going on here... but it has to do with gathering the property names from a DynaBean child member of a (parent) DynaBean. Especially, when it try's to deal with the property named 'name' and 'class'. The problem with query '//dog' etc's 'ArrayOutOfBoundsException 0' occurs below. And rightfully so, names[] is a zero length array and for some reason JXPath is trying to set a value for the first entry of a zero length array. That aint ever going to work! But why is the array length zero? Because the properties.length==1, however the 'hasClass==true' and it's count-- then negates the correct count calculated from
Re: JXPath over Generic Collection?, How?
For me: context.selectNodes(/root/animal/dog/*[name]) selects [LazyDynaBean {name=(BOXER)}, LazyDynaBean {name=(LABRADOR)}] --- On Wed, 3/11/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, March 11, 2009, 1:12 AM A whirl and a win! I'm very close to a complete solution here (with loads of assistance from Matt, THANK YOU) based on Dyna Beans however there is one remaining problem (since we have duplicate elements). According to: http://www.w3.org/TR/xpath#path-abbrev http://www.w3.org/TR/xpath#path-abbrev * selects all element children of the context node Expression: '/root/animal/dog/*' should return all dog's, instead it returns the first() dog (BOXER) only. I am unsure if this in an unrealistic requirement of JXPath and also where should I look to possibly 'fix' this if it indeed would compliment the current features? Thanks HEAPS! On Thu, Mar 5, 2009 at 3:05 AM, Matt Benson gudnabr...@yahoo.com wrote: Apparently the reason I was so ready to agree this was a bug that should be fixed is that I already fixed it as http://issues.apache.org/jira/browse/JXPATH-128 . So since you're already experienced with building JXPath now you should be able to build from svn trunk and give that a whirl. -Matt --- On Wed, 3/4/09, Matt Benson gudnabr...@yahoo.com wrote: From: Matt Benson gudnabr...@yahoo.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, March 4, 2009, 7:57 AM Hi Andrew, I agree that going through the list of properties should avoid the explicit class check problem (I think this is because you are using LazyDynaBeans instead of regular DynaBeans). As for returning all matches vs. the first match, rather than selectValue(...) you need to selectNodes(...), or iterate(...). There are other useful methods, e.g. those dealing with pointers, also available on JXPathContext. So as for your bug, yes it can/should be fixed, but you might also consider whether you can use non-lazy DynaBeans instead. Regards, Matt --- On Tue, 3/3/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, March 3, 2009, 5:37 PM For efficiency reasons I can see why you are using String[] here and not List.add()... Anyway, I have a fix (sort of) for this bug. The number of names needs to be calculated a little differently to what it currently is... public String[] getPropertyNames() { /* @todo do something about the sorting - LIKE WHAT? - MJB */ if (names == null) { DynaClass dynaClass = dynaBean.getDynaClass(); DynaProperty[] properties = dynaClass.getDynaProperties(); int count = properties.length; boolean hasClass = dynaClass.getDynaProperty(class) != null; //count the number of property names we have count = 0; for (int i = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { count++; //it's only a property is it's not a class and doesn't just have a class property. } } //read the property names into a String[] to return names = new String[count]; for (int i = 0, j = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { names[j++] = name; } } Arrays.sort(names); } return names; } Now I can sort of sucessfully run all my expressions, yippee!! However, I now have a problem with multiple deep results. Queries like //dog/* I would expect to return all dog's[] but this just returns the first one it finds. Maybe this is asking a little too much of JXPath and child/node step-up/step-down traversal? Matt can probably tell me if this is or is not the case plase :) On Wed, Mar 4, 2009 at 9:38 AM, Andrew Hughes ahhug...@gmail.com wrote: Pretty sure this is a bug in JXPath - and it is not tested by the current unit tests. I can't quite work out 100% of what's going on here... but it has to do with gathering the property names from a DynaBean child member of a (parent
Re: JXPath over Generic Collection?, How?
Hi Andrew, I agree that going through the list of properties should avoid the explicit class check problem (I think this is because you are using LazyDynaBeans instead of regular DynaBeans). As for returning all matches vs. the first match, rather than selectValue(...) you need to selectNodes(...), or iterate(...). There are other useful methods, e.g. those dealing with pointers, also available on JXPathContext. So as for your bug, yes it can/should be fixed, but you might also consider whether you can use non-lazy DynaBeans instead. Regards, Matt --- On Tue, 3/3/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, March 3, 2009, 5:37 PM For efficiency reasons I can see why you are using String[] here and not List.add()... Anyway, I have a fix (sort of) for this bug. The number of names needs to be calculated a little differently to what it currently is... public String[] getPropertyNames() { /* @todo do something about the sorting - LIKE WHAT? - MJB */ if (names == null) { DynaClass dynaClass = dynaBean.getDynaClass(); DynaProperty[] properties = dynaClass.getDynaProperties(); int count = properties.length; boolean hasClass = dynaClass.getDynaProperty(class) != null; //count the number of property names we have count = 0; for (int i = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { count++; //it's only a property is it's not a class and doesn't just have a class property. } } //read the property names into a String[] to return names = new String[count]; for (int i = 0, j = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { names[j++] = name; } } Arrays.sort(names); } return names; } Now I can sort of sucessfully run all my expressions, yippee!! However, I now have a problem with multiple deep results. Queries like //dog/* I would expect to return all dog's[] but this just returns the first one it finds. Maybe this is asking a little too much of JXPath and child/node step-up/step-down traversal? Matt can probably tell me if this is or is not the case plase :) On Wed, Mar 4, 2009 at 9:38 AM, Andrew Hughes ahhug...@gmail.com wrote: Pretty sure this is a bug in JXPath - and it is not tested by the current unit tests. I can't quite work out 100% of what's going on here... but it has to do with gathering the property names from a DynaBean child member of a (parent) DynaBean. Especially, when it try's to deal with the property named 'name' and 'class'. The problem with query '//dog' etc's 'ArrayOutOfBoundsException 0' occurs below. And rightfully so, names[] is a zero length array and for some reason JXPath is trying to set a value for the first entry of a zero length array. That aint ever going to work! But why is the array length zero? Because the properties.length==1, however the 'hasClass==true' and it's count-- then negates the correct count calculated from properties.length. I think the problem is in the hasClass calculation... 'boolean hasClass = dynaClass.getDynaProperty(class) != null;' or the conditional 'if' statement. I don't understand the JXPath logic here completely, but I know it doesn't deal with the way I am using it and I genuinely feel this is a bug we can fix :'( public String[] getPropertyNames() { /* @todo do something about the sorting - LIKE WHAT? - MJB */ if (names == null) { DynaClass dynaClass = dynaBean.getDynaClass(); DynaProperty[] properties = dynaClass.getDynaProperties(); //returns one property 'name=root' (correct) int count = properties.length; //returns/set's '1' (correct) boolean hasClass = dynaClass.getDynaProperty(class) != null; //returns/sets 'true' (?unknown?) if (hasClass) { //this is true and executes count--; // Exclude class from properties } names = new String[count]; //names is a zero length array. WRONG!!! I do have at least 1 property called 'name' for (int i = 0, j = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { names[j++] = name; //it breaks here ArrayOutOfBoundsException 0! WRONG
Re: JXPath over Generic Collection?, How?
Apparently the reason I was so ready to agree this was a bug that should be fixed is that I already fixed it as http://issues.apache.org/jira/browse/JXPATH-128 . So since you're already experienced with building JXPath now you should be able to build from svn trunk and give that a whirl. -Matt --- On Wed, 3/4/09, Matt Benson gudnabr...@yahoo.com wrote: From: Matt Benson gudnabr...@yahoo.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, March 4, 2009, 7:57 AM Hi Andrew, I agree that going through the list of properties should avoid the explicit class check problem (I think this is because you are using LazyDynaBeans instead of regular DynaBeans). As for returning all matches vs. the first match, rather than selectValue(...) you need to selectNodes(...), or iterate(...). There are other useful methods, e.g. those dealing with pointers, also available on JXPathContext. So as for your bug, yes it can/should be fixed, but you might also consider whether you can use non-lazy DynaBeans instead. Regards, Matt --- On Tue, 3/3/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, March 3, 2009, 5:37 PM For efficiency reasons I can see why you are using String[] here and not List.add()... Anyway, I have a fix (sort of) for this bug. The number of names needs to be calculated a little differently to what it currently is... public String[] getPropertyNames() { /* @todo do something about the sorting - LIKE WHAT? - MJB */ if (names == null) { DynaClass dynaClass = dynaBean.getDynaClass(); DynaProperty[] properties = dynaClass.getDynaProperties(); int count = properties.length; boolean hasClass = dynaClass.getDynaProperty(class) != null; //count the number of property names we have count = 0; for (int i = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { count++; //it's only a property is it's not a class and doesn't just have a class property. } } //read the property names into a String[] to return names = new String[count]; for (int i = 0, j = 0; i properties.length; i++) { String name = properties[i].getName(); if (!hasClass || !name.equals(class)) { names[j++] = name; } } Arrays.sort(names); } return names; } Now I can sort of sucessfully run all my expressions, yippee!! However, I now have a problem with multiple deep results. Queries like //dog/* I would expect to return all dog's[] but this just returns the first one it finds. Maybe this is asking a little too much of JXPath and child/node step-up/step-down traversal? Matt can probably tell me if this is or is not the case plase :) On Wed, Mar 4, 2009 at 9:38 AM, Andrew Hughes ahhug...@gmail.com wrote: Pretty sure this is a bug in JXPath - and it is not tested by the current unit tests. I can't quite work out 100% of what's going on here... but it has to do with gathering the property names from a DynaBean child member of a (parent) DynaBean. Especially, when it try's to deal with the property named 'name' and 'class'. The problem with query '//dog' etc's 'ArrayOutOfBoundsException 0' occurs below. And rightfully so, names[] is a zero length array and for some reason JXPath is trying to set a value for the first entry of a zero length array. That aint ever going to work! But why is the array length zero? Because the properties.length==1, however the 'hasClass==true' and it's count-- then negates the correct count calculated from properties.length. I think the problem is in the hasClass calculation... 'boolean hasClass = dynaClass.getDynaProperty(class) != null;' or the conditional 'if' statement. I don't understand the JXPath logic here completely, but I know it doesn't deal with the way I am using it and I genuinely feel this is a bug we can fix :'( public String[] getPropertyNames() { /* @todo do something about the sorting - LIKE WHAT? - MJB */ if (names == null) { DynaClass dynaClass = dynaBean.getDynaClass(); DynaProperty[] properties = dynaClass.getDynaProperties(); //returns one property 'name=root' (correct) int count = properties.length; //returns/set's
Re: JXPath over Generic Collection?, How?
); //absolute single runEvaluation(/root/animal/cat/tiger, context); //absolute multiple //everything below fails runEvaluation(/root/animal/cat/tiger[last()], context); //absolute single runEvaluation(/root/animal/dog/*, context); //absolute multiple runEvaluation(//dog, context); //deep search runEvaluation(//dog/*, context);//deep multiple runEvaluation(//cat/*[objectName='LION'], context);//deep filter } public static void runEvaluation(String expression,JXPathContext context){ log.info(About to evaulate the expression: +expression); try { Object value = context.getValue(expression); //we got a single result. if (value instanceof LazyDynaBean) { LazyDynaBean r = (LazyDynaBean)context.getValue(expression); log.info(Ran ' + expression + ' and got objectName=' + r.get(objectName) + '); } //we got multiple results else if (value instanceof ArrayList) { String titles = ; for (LazyDynaBean bean : ((ArrayListLazyDynaBean) value )){ titles += (bean.get(objectName)+,); } log.info(Ran + expression + and got +((ArrayList)value).size()+ results: +titles); } //we got a non-dyna bean. else { log.info(Ran ' + expression + ' and got a class ' + value.getClass().getName() + ' with toString() ' +value.toString() + '); } } catch (Exception e) { // TODO Auto-generated catch block log.error(Failed to evaluate +expression,e); } } } On Fri, Feb 27, 2009 at 3:56 AM, Matt Benson gudnabr...@yahoo.comwrote: Those paths work for me. Maybe something else is going awry? -Matt --- On Thu, 2/26/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Thursday, February 26, 2009, 12:53 AM Many queries don't work, I can't get any results for the following (code taken from previous email)... runEvaluation(/root/animal/cat/tiger[last()], context); //absolute single runEvaluation(/root/animal/dog/*, context); //absolute multiple runEvaluation(//dog, context); //deep search runEvaluation(//dog/*, context);//deep multiple runEvaluation(//cat/*[objectName='LION'], context);//deep filter These are the really interesting benefits on xpath that I would dearly like to have. A Huge Thanks once again for your reply Matt!!! :) On Thu, Feb 26, 2009 at 10:55 AM, Matt Benson gudnabr...@yahoo.com wrote: How so? If you simply treat the name property as an element rather than an attribute, you're done, no? -Matt --- On Wed, 2/25/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, February 25, 2009, 6:22 PM Indeed Matt, you are correct and I do apologize... but I must say I find your emailed explanation much better. Kudos Thanks! I'll (finally) get a chance to work on this tomorrow, but I think I am still stuck :'( Cheers for everything so far On Tue, Feb 24, 2009 at 1:43 PM, Matt Benson gudnabr...@yahoo.com wrote: I won't get to look at this again at least before tomorrow (9PM for me now and still have some late-night $work to look at), but I thought I would mention straight off that the @name feature actually IS mentioned in the userguide under the section about working with (java.util.)Maps. If you have a suggestion of where in the guide would be another good place to mention it as a caveat and/or even the wording to use, feel free to open a documentation issue in JIRA for it. TBC, Matt --- On Mon, 2/23/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Monday, February 23, 2009, 6:24 PM Hi Matt, Thanks HEAPS for you reply, I am really really really grateful. I think that I have progressed just a little with this but there are still some BIG shortfalls with this. I've attached code that should run out the box and is based on previous emails. If I can get the expressions below to correctly evaluate I would be heaps happy. Thanks heaps again, hopefully this will work soon enough. p.s. I can understand the 'name' vs '@name', perhaps the userguide could mention this is about all I can add. code... package rnd; import java.util.ArrayList; import org.apache.commons.beanutils.LazyDynaBean
Re: JXPath over Generic Collection?, How?
OK, email #19 to the list. I'm both incredibly patient and skeptical that this will ever work. I might try and run this in a debugger and track down how JXPath traverses the DynaBean but given the reflection involved that might be a painful task. --AH On Tue, Feb 17, 2009 at 1:11 PM, Andrew Hughes ahhug...@gmail.com wrote: Ping... if anyone can help with this JXPath DynaBeans problem I'd be REALLY THANKFUL :) On Fri, Feb 13, 2009 at 1:55 PM, Andrew Hughes ahhug...@gmail.com wrote: Howdy, I've taken Matt's suggestion onboard and I have investigated DynaBeans. These look pretty good for all intestive purposes and there's a code examples below how to build the data structure: + root [...@name=ROOT] + animal [...@name=ANIMAL] + dog [...@name=DOG] + boxer [...@name=BOXER] + labrador [...@name=LABRADOR] + cat [...@name=CAT] + tiger [...@name=TIGER-ONE] + tiger [...@name=TIGER-TWO] + tiger [...@name=TIGER-THREE] + lion [...@name=LION] And the code looks like... LazyDynaBean lazyDynaBean = new LazyDynaBean(); //the transparent root. LazyDynaBean root = new LazyDynaBean(); LazyDynaBean animal = new LazyDynaBean(); LazyDynaBean dog = new LazyDynaBean(); LazyDynaBean cat = new LazyDynaBean(); LazyDynaBean boxer = new LazyDynaBean(); LazyDynaBean labrador = new LazyDynaBean(); LazyDynaBean tiger1 = new LazyDynaBean(); LazyDynaBean tiger2 = new LazyDynaBean(); LazyDynaBean tiger3 = new LazyDynaBean(); LazyDynaBean lion = new LazyDynaBean(); //set the @name property of each bean, user UPPER to make them distinct for examples. root.set(name,ROOT); animal.set(name,ANIMAL); dog.set(name,DOG); cat.set(name,CAT); boxer.set(name,BOXER); labrador.set(name,LABRADOR); tiger1.set(name,TIGER-ONE); tiger2.set(name,TIGER-TWO); tiger3.set(name,TIGER-THREE); lion.set(name,LION); //build the bean hierarchy. lazyDynaBean.set(root,0, root); root.set(animal,0, animal); animal.set(dog,0,dog); animal.set(cat,0,cat); dog.set(labrador,0,labrador); dog.set(boxer,0, boxer); cat.set(tiger,0,tiger1);//duplicate cat.set(tiger,1,tiger2);//duplicate cat.set(tiger,1,tiger3);//duplicate cat.set(lion,0,lion); JXPathContext context = JXPathContext.newContext(lazyDynaBean); String query = /root/animal/cat/tiger; Object value = context.getValue(query); But there's a problem with JXPath querying this also. Absolute Paths like '/root/animal/cat/tiger' or '/root/animal/cat/tiger'[2]' work perfectly. But I don't have anyluck doing deep searches. For examples the following just won't work. '//cat' //*...@name='LION'] /root/animal/cat/tig...@name='TIGER-TWO'] Things are looking up, but is this behavior to be expected? Cheers, --AH On Thu, Feb 12, 2009 at 6:43 AM, Matt Benson gudnabr...@yahoo.comwrote: --- On Wed, 2/11/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, February 11, 2009, 4:19 AM Still No Luck, I have removed recursive generic collections and have tried the following code... this is becoming a marathon effort :'( public class Thing { public Thing(String name) { this.name = name; } private String name = ; public String getName() { return name; } private ArrayListThing children = new ArrayListThing(); public ArrayListThing getChildren() { return children; } } public static void main(String[] args) { //get some same data Thing animal = new Thing(Animal); //Animal.Dog.* Thing dog = new Thing(Dog); dog.getChildren().add(new Thing(Labrador)); dog.getChildren().add(new Thing(Boxer)); animal.getChildren().add(dog); //Animal.Cat.* Thing cat = new Thing(Cat); cat.getChildren().add(new Thing(Lion)); cat.getChildren().add(new Thing(Tiger)); animal.getChildren().add(cat); //run a query on it JXPathContext context = JXPathContext.newContext(animal); String query = /Animal; Thing result = (Thing) context.getValue(query); String path = context.getPointer(query).asPath(); System.out.println(Ran ' + query + ' and got ' + result.getName() + ' on path ' + path + '.); } What would you be trying to select? If you want to know how to look for a given Thing in this graph, I can probably help. If you want to know what graph will allow you to use a preconceived notion of the xpath you want to use, that will be harder. You might use [beanutils] dynabeans in conjunction with [jxpath] to try and achieve the latter. -Matt On Wed, Feb 11, 2009 at 3:08 PM, Andrew Hughes
Re: JXPath over Generic Collection?, How?
Andrew, I've been meaning to look into this but haven't yet. If you have any ready-to-run code you can send to the list, that wouldn't hurt... -Matt --- On Mon, 2/23/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Monday, February 23, 2009, 5:42 AM OK, email #19 to the list. I'm both incredibly patient and skeptical that this will ever work. I might try and run this in a debugger and track down how JXPath traverses the DynaBean but given the reflection involved that might be a painful task. --AH On Tue, Feb 17, 2009 at 1:11 PM, Andrew Hughes ahhug...@gmail.com wrote: Ping... if anyone can help with this JXPath DynaBeans problem I'd be REALLY THANKFUL :) On Fri, Feb 13, 2009 at 1:55 PM, Andrew Hughes ahhug...@gmail.com wrote: Howdy, I've taken Matt's suggestion onboard and I have investigated DynaBeans. These look pretty good for all intestive purposes and there's a code examples below how to build the data structure: + root [...@name=ROOT] + animal [...@name=ANIMAL] + dog [...@name=DOG] + boxer [...@name=BOXER] + labrador [...@name=LABRADOR] + cat [...@name=CAT] + tiger [...@name=TIGER-ONE] + tiger [...@name=TIGER-TWO] + tiger [...@name=TIGER-THREE] + lion [...@name=LION] And the code looks like... LazyDynaBean lazyDynaBean = new LazyDynaBean(); //the transparent root. LazyDynaBean root = new LazyDynaBean(); LazyDynaBean animal = new LazyDynaBean(); LazyDynaBean dog = new LazyDynaBean(); LazyDynaBean cat = new LazyDynaBean(); LazyDynaBean boxer = new LazyDynaBean(); LazyDynaBean labrador = new LazyDynaBean(); LazyDynaBean tiger1 = new LazyDynaBean(); LazyDynaBean tiger2 = new LazyDynaBean(); LazyDynaBean tiger3 = new LazyDynaBean(); LazyDynaBean lion = new LazyDynaBean(); //set the @name property of each bean, user UPPER to make them distinct for examples. root.set(name,ROOT); animal.set(name,ANIMAL); dog.set(name,DOG); cat.set(name,CAT); boxer.set(name,BOXER); labrador.set(name,LABRADOR); tiger1.set(name,TIGER-ONE); tiger2.set(name,TIGER-TWO); tiger3.set(name,TIGER-THREE); lion.set(name,LION); //build the bean hierarchy. lazyDynaBean.set(root,0, root); root.set(animal,0, animal); animal.set(dog,0,dog); animal.set(cat,0,cat); dog.set(labrador,0,labrador); dog.set(boxer,0, boxer); cat.set(tiger,0,tiger1);//duplicate cat.set(tiger,1,tiger2);//duplicate cat.set(tiger,1,tiger3);//duplicate cat.set(lion,0,lion); JXPathContext context = JXPathContext.newContext(lazyDynaBean); String query = /root/animal/cat/tiger; Object value = context.getValue(query); But there's a problem with JXPath querying this also. Absolute Paths like '/root/animal/cat/tiger' or '/root/animal/cat/tiger'[2]' work perfectly. But I don't have anyluck doing deep searches. For examples the following just won't work. '//cat' //*...@name='LION'] /root/animal/cat/tig...@name='TIGER-TWO'] Things are looking up, but is this behavior to be expected? Cheers, --AH On Thu, Feb 12, 2009 at 6:43 AM, Matt Benson gudnabr...@yahoo.comwrote: --- On Wed, 2/11/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, February 11, 2009, 4:19 AM Still No Luck, I have removed recursive generic collections and have tried the following code... this is becoming a marathon effort :'( public class Thing { public Thing(String name) { this.name = name; } private String name = ; public String getName() { return name; } private ArrayListThing children = new ArrayListThing(); public ArrayListThing getChildren() { return children; } } public static void main(String[] args) { //get some same data Thing animal = new Thing(Animal); //Animal.Dog.* Thing dog = new Thing(Dog); dog.getChildren().add(new Thing(Labrador)); dog.getChildren().add(new Thing(Boxer)); animal.getChildren().add(dog); //Animal.Cat.* Thing cat = new Thing(Cat); cat.getChildren().add(new Thing(Lion)); cat.getChildren().add(new Thing(Tiger)); animal.getChildren().add(cat); //run a query on it JXPathContext context = JXPathContext.newContext(animal); String query = /Animal; Thing result = (Thing) context.getValue
Re: JXPath over Generic Collection?, How?
And the answer is: In JXPath, a decision was made to overload the name attribute to refer to an element's property name WRT its parent. The reason this was done was to support query maps with non-String keys in JXPath. This means that anytime you actually want to refer to a property whose name literally is name, you must treat it as a child element rather than an attribute. So in your case you could either change name to title and query [...@title='foo'] or simply use [name='foo']. Regards, Matt --- On Mon, 2/23/09, Matt Benson gudnabr...@yahoo.com wrote: From: Matt Benson gudnabr...@yahoo.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Monday, February 23, 2009, 2:58 PM To follow up, the 'name' attribute in particular is what doesn't seem to be working here (change it to e.g. 'game' and it works fine)... if you could file a bug it would help me remember as I don't have time to do it myself right this minute. -Matt --- On Mon, 2/23/09, Matt Benson gudnabr...@yahoo.com wrote: From: Matt Benson gudnabr...@yahoo.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Monday, February 23, 2009, 12:27 PM Andrew, I've been meaning to look into this but haven't yet. If you have any ready-to-run code you can send to the list, that wouldn't hurt... -Matt --- On Mon, 2/23/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Monday, February 23, 2009, 5:42 AM OK, email #19 to the list. I'm both incredibly patient and skeptical that this will ever work. I might try and run this in a debugger and track down how JXPath traverses the DynaBean but given the reflection involved that might be a painful task. --AH On Tue, Feb 17, 2009 at 1:11 PM, Andrew Hughes ahhug...@gmail.com wrote: Ping... if anyone can help with this JXPath DynaBeans problem I'd be REALLY THANKFUL :) On Fri, Feb 13, 2009 at 1:55 PM, Andrew Hughes ahhug...@gmail.com wrote: Howdy, I've taken Matt's suggestion onboard and I have investigated DynaBeans. These look pretty good for all intestive purposes and there's a code examples below how to build the data structure: + root [...@name=ROOT] + animal [...@name=ANIMAL] + dog [...@name=DOG] + boxer [...@name=BOXER] + labrador [...@name=LABRADOR] + cat [...@name=CAT] + tiger [...@name=TIGER-ONE] + tiger [...@name=TIGER-TWO] + tiger [...@name=TIGER-THREE] + lion [...@name=LION] And the code looks like... LazyDynaBean lazyDynaBean = new LazyDynaBean(); //the transparent root. LazyDynaBean root = new LazyDynaBean(); LazyDynaBean animal = new LazyDynaBean(); LazyDynaBean dog = new LazyDynaBean(); LazyDynaBean cat = new LazyDynaBean(); LazyDynaBean boxer = new LazyDynaBean(); LazyDynaBean labrador = new LazyDynaBean(); LazyDynaBean tiger1 = new LazyDynaBean(); LazyDynaBean tiger2 = new LazyDynaBean(); LazyDynaBean tiger3 = new LazyDynaBean(); LazyDynaBean lion = new LazyDynaBean(); //set the @name property of each bean, user UPPER to make them distinct for examples. root.set(name,ROOT); animal.set(name,ANIMAL); dog.set(name,DOG); cat.set(name,CAT); boxer.set(name,BOXER); labrador.set(name,LABRADOR); tiger1.set(name,TIGER-ONE); tiger2.set(name,TIGER-TWO); tiger3.set(name,TIGER-THREE); lion.set(name,LION); //build the bean hierarchy. lazyDynaBean.set(root,0, root); root.set(animal,0, animal); animal.set(dog,0,dog); animal.set(cat,0,cat); dog.set(labrador,0,labrador); dog.set(boxer,0, boxer); cat.set(tiger,0,tiger1);//duplicate cat.set(tiger,1,tiger2);//duplicate cat.set(tiger,1,tiger3);//duplicate cat.set(lion,0,lion); JXPathContext context = JXPathContext.newContext(lazyDynaBean); String query = /root/animal/cat/tiger; Object value = context.getValue(query); But there's a problem with JXPath querying this also. Absolute Paths like '/root/animal/cat/tiger' or '/root/animal/cat/tiger'[2]' work perfectly. But I don't have anyluck doing deep searches. For examples the following just won't work. '//cat' //*...@name='LION'] /root/animal/cat/tig...@name='TIGER-TWO'] Things are looking up, but is this behavior to be expected? Cheers, --AH On Thu, Feb 12, 2009 at 6:43 AM, Matt Benson gudnabr
Re: JXPath over Generic Collection?, How?
I won't get to look at this again at least before tomorrow (9PM for me now and still have some late-night $work to look at), but I thought I would mention straight off that the @name feature actually IS mentioned in the userguide under the section about working with (java.util.)Maps. If you have a suggestion of where in the guide would be another good place to mention it as a caveat and/or even the wording to use, feel free to open a documentation issue in JIRA for it. TBC, Matt --- On Mon, 2/23/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Monday, February 23, 2009, 6:24 PM Hi Matt, Thanks HEAPS for you reply, I am really really really grateful. I think that I have progressed just a little with this but there are still some BIG shortfalls with this. I've attached code that should run out the box and is based on previous emails. If I can get the expressions below to correctly evaluate I would be heaps happy. Thanks heaps again, hopefully this will work soon enough. p.s. I can understand the 'name' vs '@name', perhaps the userguide could mention this is about all I can add. code... package rnd; import java.util.ArrayList; import org.apache.commons.beanutils.LazyDynaBean; import org.apache.commons.jxpath.JXPathContext; import org.apache.log4j.Logger; public class Main { private static final Logger log = Logger.getLogger(Main.class); public static void main(String[] args) { log.info(Starting...); LazyDynaBean lazyDynaBean = new LazyDynaBean(); //the transparent root. LazyDynaBean root = new LazyDynaBean(); LazyDynaBean animal = new LazyDynaBean(); LazyDynaBean dog = new LazyDynaBean(); LazyDynaBean cat = new LazyDynaBean(); LazyDynaBean boxer = new LazyDynaBean(); LazyDynaBean labrador = new LazyDynaBean(); LazyDynaBean tiger1 = new LazyDynaBean(); LazyDynaBean tiger2 = new LazyDynaBean(); LazyDynaBean tiger3 = new LazyDynaBean(); LazyDynaBean lion = new LazyDynaBean(); //set the @objectName property of each bean, user UPPER to make them distinct for examples. root.set(objectName,ROOT); animal.set(objectName,ANIMAL); dog.set(objectName,DOG); cat.set(objectName,CAT); boxer.set(objectName,BOXER); labrador.set(objectName,LABRADOR); tiger1.set(objectName,TIGER-ONE); tiger2.set(objectName,TIGER-TWO); tiger3.set(objectName,TIGER-THREE); lion.set(objectName,LION); //build the bean hierarchy. lazyDynaBean.set(root,0, root); root.set(animal,0, animal); animal.set(dog,0,dog); animal.set(cat,0,cat); dog.set(labrador,0,labrador); dog.set(boxer,0, boxer); cat.set(tiger,0,tiger1);//duplicate cat.set(tiger,1,tiger2);//duplicate cat.set(tiger,2,tiger3);//duplicate cat.set(lion,0,lion); JXPathContext context = JXPathContext.newContext(lazyDynaBean); //these all work runEvaluation(/root/animal/dog, context); //absolute single runEvaluation(/root/animal/cat/tiger[2], context); //absolute single runEvaluation(/root/animal/cat/tiger, context); //absolute multiple //everything below fails runEvaluation(/root/animal/cat/tiger[last()], context); //absolute single runEvaluation(/root/animal/dog/*, context); //absolute multiple runEvaluation(//dog, context); //deep search runEvaluation(//dog/*, context);//deep multiple runEvaluation(//cat/*[objectName='LION'], context);//deep filter } public static void runEvaluation(String expression,JXPathContext context){ log.info(About to evaulate the expression: +expression); try { Object value = context.getValue(expression); //we got a single result. if (value instanceof LazyDynaBean) { LazyDynaBean r = (LazyDynaBean)context.getValue(expression); log.info(Ran ' + expression + ' and got objectName=' + r.get(objectName) + '); } //we got multiple results else if (value instanceof ArrayList) { String titles = ; for (LazyDynaBean bean : ((ArrayListLazyDynaBean) value )){ titles += (bean.get(objectName)+,); } log.info(Ran + expression + and got +((ArrayList)value).size()+ results: +titles); } //we got a non-dyna bean. else { log.info(Ran ' + expression + ' and got a class ' + value.getClass().getName() + ' with toString() ' +value.toString() + '); } } catch (Exception e) { log.error(e); } } } On Tue, Feb 24, 2009 at 8:58 AM, Matt Benson gudnabr...@yahoo.com wrote: And the answer is: In JXPath, a decision was made to overload the name attribute to refer to an element's property name WRT its parent. The reason this was done was to support query maps with non-String keys in JXPath. This means that anytime you actually want to refer to a property whose name literally is name, you must treat it as a child element rather than an attribute. So in your case you
Re: JXPath over Generic Collection?, How?
Ping... if anyone can help with this JXPath DynaBeans problem I'd be REALLY THANKFUL :) On Fri, Feb 13, 2009 at 1:55 PM, Andrew Hughes ahhug...@gmail.com wrote: Howdy, I've taken Matt's suggestion onboard and I have investigated DynaBeans. These look pretty good for all intestive purposes and there's a code examples below how to build the data structure: + root [...@name=ROOT] + animal [...@name=ANIMAL] + dog [...@name=DOG] + boxer [...@name=BOXER] + labrador [...@name=LABRADOR] + cat [...@name=CAT] + tiger [...@name=TIGER-ONE] + tiger [...@name=TIGER-TWO] + tiger [...@name=TIGER-THREE] + lion [...@name=LION] And the code looks like... LazyDynaBean lazyDynaBean = new LazyDynaBean(); //the transparent root. LazyDynaBean root = new LazyDynaBean(); LazyDynaBean animal = new LazyDynaBean(); LazyDynaBean dog = new LazyDynaBean(); LazyDynaBean cat = new LazyDynaBean(); LazyDynaBean boxer = new LazyDynaBean(); LazyDynaBean labrador = new LazyDynaBean(); LazyDynaBean tiger1 = new LazyDynaBean(); LazyDynaBean tiger2 = new LazyDynaBean(); LazyDynaBean tiger3 = new LazyDynaBean(); LazyDynaBean lion = new LazyDynaBean(); //set the @name property of each bean, user UPPER to make them distinct for examples. root.set(name,ROOT); animal.set(name,ANIMAL); dog.set(name,DOG); cat.set(name,CAT); boxer.set(name,BOXER); labrador.set(name,LABRADOR); tiger1.set(name,TIGER-ONE); tiger2.set(name,TIGER-TWO); tiger3.set(name,TIGER-THREE); lion.set(name,LION); //build the bean hierarchy. lazyDynaBean.set(root,0, root); root.set(animal,0, animal); animal.set(dog,0,dog); animal.set(cat,0,cat); dog.set(labrador,0,labrador); dog.set(boxer,0, boxer); cat.set(tiger,0,tiger1);//duplicate cat.set(tiger,1,tiger2);//duplicate cat.set(tiger,1,tiger3);//duplicate cat.set(lion,0,lion); JXPathContext context = JXPathContext.newContext(lazyDynaBean); String query = /root/animal/cat/tiger; Object value = context.getValue(query); But there's a problem with JXPath querying this also. Absolute Paths like '/root/animal/cat/tiger' or '/root/animal/cat/tiger'[2]' work perfectly. But I don't have anyluck doing deep searches. For examples the following just won't work. '//cat' //*...@name='LION'] /root/animal/cat/tig...@name='TIGER-TWO'] Things are looking up, but is this behavior to be expected? Cheers, --AH On Thu, Feb 12, 2009 at 6:43 AM, Matt Benson gudnabr...@yahoo.com wrote: --- On Wed, 2/11/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, February 11, 2009, 4:19 AM Still No Luck, I have removed recursive generic collections and have tried the following code... this is becoming a marathon effort :'( public class Thing { public Thing(String name) { this.name = name; } private String name = ; public String getName() { return name; } private ArrayListThing children = new ArrayListThing(); public ArrayListThing getChildren() { return children; } } public static void main(String[] args) { //get some same data Thing animal = new Thing(Animal); //Animal.Dog.* Thing dog = new Thing(Dog); dog.getChildren().add(new Thing(Labrador)); dog.getChildren().add(new Thing(Boxer)); animal.getChildren().add(dog); //Animal.Cat.* Thing cat = new Thing(Cat); cat.getChildren().add(new Thing(Lion)); cat.getChildren().add(new Thing(Tiger)); animal.getChildren().add(cat); //run a query on it JXPathContext context = JXPathContext.newContext(animal); String query = /Animal; Thing result = (Thing) context.getValue(query); String path = context.getPointer(query).asPath(); System.out.println(Ran ' + query + ' and got ' + result.getName() + ' on path ' + path + '.); } What would you be trying to select? If you want to know how to look for a given Thing in this graph, I can probably help. If you want to know what graph will allow you to use a preconceived notion of the xpath you want to use, that will be harder. You might use [beanutils] dynabeans in conjunction with [jxpath] to try and achieve the latter. -Matt On Wed, Feb 11, 2009 at 3:08 PM, Andrew Hughes ahhug...@gmail.com wrote: Yeah, that makes sense. The part that was confusing me is that if I have... public class Thing { private ListThing children; } I was assuming I would need to prefix all of my expressions steps with '/children'. From what you said earlier this is not the case
Re: JXPath over Generic Collection?, How?
--- On Wed, 2/11/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Wednesday, February 11, 2009, 4:19 AM Still No Luck, I have removed recursive generic collections and have tried the following code... this is becoming a marathon effort :'( public class Thing { public Thing(String name) { this.name = name; } private String name = ; public String getName() { return name; } private ArrayListThing children = new ArrayListThing(); public ArrayListThing getChildren() { return children; } } public static void main(String[] args) { //get some same data Thing animal = new Thing(Animal); //Animal.Dog.* Thing dog = new Thing(Dog); dog.getChildren().add(new Thing(Labrador)); dog.getChildren().add(new Thing(Boxer)); animal.getChildren().add(dog); //Animal.Cat.* Thing cat = new Thing(Cat); cat.getChildren().add(new Thing(Lion)); cat.getChildren().add(new Thing(Tiger)); animal.getChildren().add(cat); //run a query on it JXPathContext context = JXPathContext.newContext(animal); String query = /Animal; Thing result = (Thing) context.getValue(query); String path = context.getPointer(query).asPath(); System.out.println(Ran ' + query + ' and got ' + result.getName() + ' on path ' + path + '.); } What would you be trying to select? If you want to know how to look for a given Thing in this graph, I can probably help. If you want to know what graph will allow you to use a preconceived notion of the xpath you want to use, that will be harder. You might use [beanutils] dynabeans in conjunction with [jxpath] to try and achieve the latter. -Matt On Wed, Feb 11, 2009 at 3:08 PM, Andrew Hughes ahhug...@gmail.com wrote: Yeah, that makes sense. The part that was confusing me is that if I have... public class Thing { private ListThing children; } I was assuming I would need to prefix all of my expressions steps with '/children'. From what you said earlier this is not the case as collections are auto traversed/loaded. Thanks again matt! I won't get to test this out til later tonight be look foward to seeing it working!!! Andrew On Wed, Feb 11, 2009 at 2:57 PM, Matt Benson gudnabr...@yahoo.com wrote: It should be as simple as Thing _containing_ a ListThing rather than _being_ a ListThing. Composition over inheritance, do you see? HTH, Matt --- On Tue, 2/10/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org, gudnabr...@yahoo.com Date: Tuesday, February 10, 2009, 7:06 PM Matt, Thank You. Is there any other data structure I can use that would work with JXPath? My requirement is that... a Thing can have contain multiple child Thing(s) (and the children are allowed to be non-unique). This is equivalent to an XML element as it can contain multiple child elements, how do these guy's handle it I wonder? --Andrew On Wed, Feb 11, 2009 at 9:09 AM, Matt Benson gudnabr...@yahoo.com wrote: I admit I hadn't looked at this with a highly critical eye, but this business of Thing extending ArrayListThing seems quite strange to me. JXPath basically functions by opening up collections automatically, so the very fact that Thing is itself a Collection implies that a Thing will be opened up, and its children will be searched... but in this example, either there are no children, at the leaves, or the children themselves are (possibly empty) collections. It looks as though you're trying to represent a tree structure. This may be a good example of a reason for the idea of composition over inheritance. I don't think you're going to get any traction using JXPath with this object model. Sorry for the bad news, Matt --- On Tue, 2/10/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, February 10, 2009, 7:16 AM Still busted. Example is now simplified. As soon as a generic Collection becomes involved BOOM! The Main Method to exec: public class App { public static void main( String[] args ){ JXPathContext context = JXPathContext.newContext(new ThingRoot()); System.out.println(((Thing)context.getValue(/root
Re: JXPath over Generic Collection?, How?
I admit I hadn't looked at this with a highly critical eye, but this business of Thing extending ArrayListThing seems quite strange to me. JXPath basically functions by opening up collections automatically, so the very fact that Thing is itself a Collection implies that a Thing will be opened up, and its children will be searched... but in this example, either there are no children, at the leaves, or the children themselves are (possibly empty) collections. It looks as though you're trying to represent a tree structure. This may be a good example of a reason for the idea of composition over inheritance. I don't think you're going to get any traction using JXPath with this object model. Sorry for the bad news, Matt --- On Tue, 2/10/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, February 10, 2009, 7:16 AM Still busted. Example is now simplified. As soon as a generic Collection becomes involved BOOM! The Main Method to exec: public class App { public static void main( String[] args ){ JXPathContext context = JXPathContext.newContext(new ThingRoot()); System.out.println(((Thing)context.getValue(/root)).getName()); } } The (populated) context root I am using, where root is a single object holding a List of Thing's. package jxpathresearch; import java.util.ArrayList; import java.util.List; public class ThingRoot { private ListThing root new ArrayList(); //this will serve as the root. public ThingRoot() { Thing animal = new Thing(Animal); root.add(animal);//Animal Thing dog = new Thing(Dog); animal.add(dog);//Animal.Dog dog.add(new Thing(Labrador));//Animal.Dog.Labrador dog.add(new Thing(Boxer));//Animal.Dog.Boxer } public ListThing getRoot() { return root; } } Finally here's a very simple 'Thing' that contains a List of Thing(s): public class Thing extends ArrayListThing { public Thing(String name){this.name = name;} private String name = ; public String getName() {return name;} } I can't query anything beyond /root, it doesn't seem to ever get traversed. I would expect results for //Thing and //thi...@name='Labrador'] etc but I get no results only exceptions. My brain is hurting. On Tue, Feb 10, 2009 at 12:22 AM, Andrew Hughes ahhug...@gmail.com wrote: I've noew tested a whole heap of expressions even //name='Tiger' nothing works. On Tue, Feb 10, 2009 at 12:01 AM, Andrew Hughes ahhug...@gmail.comwrote: I got cracking on testing this out... no luck (yet). Here's my testing code if some kind person could please take a look First my generic collection hierarchy (which only contains a name and children)... package jxpathresearch; import java.util.ArrayList; public class HierarchyPojo extends ArrayListHierarchyPojo { public HierarchyPojo(String name){ this.setName(name); } private String name = ; public String getName() { return name; } public void setName(String name) { this.name = name; } } Next, the wrapper for the root context (as Matt suggested) and populated with animals... package jxpathresearch; public class CollectionRoot { private HierarchyPojo hierarchyPojo; public CollectionRoot(){ //Animal hierarchyPojo = new HierarchyPojo(Animal); //Animal.Dog HierarchyPojo dog = new HierarchyPojo(Dog); //Animal.Dog.Labrador dog.add(new HierarchyPojo(Labrador)); //Animal.Dog.Boxer dog.add(new HierarchyPojo(Boxer)); //Animal.Dog.Mastiff dog.add(new HierarchyPojo(Mastiff)); //Animal.Cat HierarchyPojo cat = new HierarchyPojo(Cat); //Animal.Cat.Tiger cat.add(new HierarchyPojo(Tiger)); //Animal.Cat.Cougar cat.add(new HierarchyPojo(Cougar)); //Animal.Cat.Leopard cat.add(new HierarchyPojo(Leopard)); //Add Animal.Dog Animal.Cat hierarchyPojo.add(dog); hierarchyPojo.add(cat); } public HierarchyPojo getHierarchyPojo() {return hierarchyPojo;} public void setHierarchyPojo(HierarchyPojo hierarchyPojo) {this.hierarchyPojo = hierarchyPojo;} } Finally invoke and test... public class App { public static void main( String[] args ) { JXPathContext context = JXPathContext.newContext(new CollectionRoot()); String query = //hierarchypo...@name='Tiger']; String fName = context.getValue(query).toString(); System.out.println(Ran '+query+' and got '+fName
Re: JXPath over Generic Collection?, How?
Matt, Thank You. Is there any other data structure I can use that would work with JXPath? My requirement is that... a Thing can have contain multiple child Thing(s) (and the children are allowed to be non-unique). This is equivalent to an XML element as it can contain multiple child elements, how do these guy's handle it I wonder? --Andrew On Wed, Feb 11, 2009 at 9:09 AM, Matt Benson gudnabr...@yahoo.com wrote: I admit I hadn't looked at this with a highly critical eye, but this business of Thing extending ArrayListThing seems quite strange to me. JXPath basically functions by opening up collections automatically, so the very fact that Thing is itself a Collection implies that a Thing will be opened up, and its children will be searched... but in this example, either there are no children, at the leaves, or the children themselves are (possibly empty) collections. It looks as though you're trying to represent a tree structure. This may be a good example of a reason for the idea of composition over inheritance. I don't think you're going to get any traction using JXPath with this object model. Sorry for the bad news, Matt --- On Tue, 2/10/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, February 10, 2009, 7:16 AM Still busted. Example is now simplified. As soon as a generic Collection becomes involved BOOM! The Main Method to exec: public class App { public static void main( String[] args ){ JXPathContext context = JXPathContext.newContext(new ThingRoot()); System.out.println(((Thing)context.getValue(/root)).getName()); } } The (populated) context root I am using, where root is a single object holding a List of Thing's. package jxpathresearch; import java.util.ArrayList; import java.util.List; public class ThingRoot { private ListThing root new ArrayList(); //this will serve as the root. public ThingRoot() { Thing animal = new Thing(Animal); root.add(animal);//Animal Thing dog = new Thing(Dog); animal.add(dog);//Animal.Dog dog.add(new Thing(Labrador));//Animal.Dog.Labrador dog.add(new Thing(Boxer));//Animal.Dog.Boxer } public ListThing getRoot() { return root; } } Finally here's a very simple 'Thing' that contains a List of Thing(s): public class Thing extends ArrayListThing { public Thing(String name){this.name = name;} private String name = ; public String getName() {return name;} } I can't query anything beyond /root, it doesn't seem to ever get traversed. I would expect results for //Thing and //thi...@name='Labrador'] etc but I get no results only exceptions. My brain is hurting. On Tue, Feb 10, 2009 at 12:22 AM, Andrew Hughes ahhug...@gmail.com wrote: I've noew tested a whole heap of expressions even //name='Tiger' nothing works. On Tue, Feb 10, 2009 at 12:01 AM, Andrew Hughes ahhug...@gmail.comwrote: I got cracking on testing this out... no luck (yet). Here's my testing code if some kind person could please take a look First my generic collection hierarchy (which only contains a name and children)... package jxpathresearch; import java.util.ArrayList; public class HierarchyPojo extends ArrayListHierarchyPojo { public HierarchyPojo(String name){ this.setName(name); } private String name = ; public String getName() { return name; } public void setName(String name) { this.name = name; } } Next, the wrapper for the root context (as Matt suggested) and populated with animals... package jxpathresearch; public class CollectionRoot { private HierarchyPojo hierarchyPojo; public CollectionRoot(){ //Animal hierarchyPojo = new HierarchyPojo(Animal); //Animal.Dog HierarchyPojo dog = new HierarchyPojo(Dog); //Animal.Dog.Labrador dog.add(new HierarchyPojo(Labrador)); //Animal.Dog.Boxer dog.add(new HierarchyPojo(Boxer)); //Animal.Dog.Mastiff dog.add(new HierarchyPojo(Mastiff)); //Animal.Cat HierarchyPojo cat = new HierarchyPojo(Cat); //Animal.Cat.Tiger cat.add(new HierarchyPojo(Tiger)); //Animal.Cat.Cougar cat.add(new HierarchyPojo(Cougar)); //Animal.Cat.Leopard cat.add(new HierarchyPojo(Leopard)); //Add Animal.Dog Animal.Cat hierarchyPojo.add(dog); hierarchyPojo.add(cat); } public
Re: JXPath over Generic Collection?, How?
It should be as simple as Thing _containing_ a ListThing rather than _being_ a ListThing. Composition over inheritance, do you see? HTH, Matt --- On Tue, 2/10/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org, gudnabr...@yahoo.com Date: Tuesday, February 10, 2009, 7:06 PM Matt, Thank You. Is there any other data structure I can use that would work with JXPath? My requirement is that... a Thing can have contain multiple child Thing(s) (and the children are allowed to be non-unique). This is equivalent to an XML element as it can contain multiple child elements, how do these guy's handle it I wonder? --Andrew On Wed, Feb 11, 2009 at 9:09 AM, Matt Benson gudnabr...@yahoo.com wrote: I admit I hadn't looked at this with a highly critical eye, but this business of Thing extending ArrayListThing seems quite strange to me. JXPath basically functions by opening up collections automatically, so the very fact that Thing is itself a Collection implies that a Thing will be opened up, and its children will be searched... but in this example, either there are no children, at the leaves, or the children themselves are (possibly empty) collections. It looks as though you're trying to represent a tree structure. This may be a good example of a reason for the idea of composition over inheritance. I don't think you're going to get any traction using JXPath with this object model. Sorry for the bad news, Matt --- On Tue, 2/10/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, February 10, 2009, 7:16 AM Still busted. Example is now simplified. As soon as a generic Collection becomes involved BOOM! The Main Method to exec: public class App { public static void main( String[] args ){ JXPathContext context = JXPathContext.newContext(new ThingRoot()); System.out.println(((Thing)context.getValue(/root)).getName()); } } The (populated) context root I am using, where root is a single object holding a List of Thing's. package jxpathresearch; import java.util.ArrayList; import java.util.List; public class ThingRoot { private ListThing root new ArrayList(); //this will serve as the root. public ThingRoot() { Thing animal = new Thing(Animal); root.add(animal);//Animal Thing dog = new Thing(Dog); animal.add(dog);//Animal.Dog dog.add(new Thing(Labrador));//Animal.Dog.Labrador dog.add(new Thing(Boxer));//Animal.Dog.Boxer } public ListThing getRoot() { return root; } } Finally here's a very simple 'Thing' that contains a List of Thing(s): public class Thing extends ArrayListThing { public Thing(String name){this.name = name;} private String name = ; public String getName() {return name;} } I can't query anything beyond /root, it doesn't seem to ever get traversed. I would expect results for //Thing and //thi...@name='Labrador'] etc but I get no results only exceptions. My brain is hurting. On Tue, Feb 10, 2009 at 12:22 AM, Andrew Hughes ahhug...@gmail.com wrote: I've noew tested a whole heap of expressions even //name='Tiger' nothing works. On Tue, Feb 10, 2009 at 12:01 AM, Andrew Hughes ahhug...@gmail.comwrote: I got cracking on testing this out... no luck (yet). Here's my testing code if some kind person could please take a look First my generic collection hierarchy (which only contains a name and children)... package jxpathresearch; import java.util.ArrayList; public class HierarchyPojo extends ArrayListHierarchyPojo { public HierarchyPojo(String name){ this.setName(name); } private String name = ; public String getName() { return name; } public void setName(String name) { this.name = name; } } Next, the wrapper for the root context (as Matt suggested) and populated with animals... package jxpathresearch; public class CollectionRoot { private HierarchyPojo hierarchyPojo; public CollectionRoot(){ //Animal hierarchyPojo = new HierarchyPojo(Animal); //Animal.Dog HierarchyPojo dog = new HierarchyPojo(Dog); //Animal.Dog.Labrador dog.add(new HierarchyPojo(Labrador)); //Animal.Dog.Boxer dog.add(new
Re: JXPath over Generic Collection?, How?
Yeah, that makes sense. The part that was confusing me is that if I have... public class Thing { private ListThing children; } I was assuming I would need to prefix all of my expressions steps with '/children'. From what you said earlier this is not the case as collections are auto traversed/loaded. Thanks again matt! I won't get to test this out til later tonight be look foward to seeing it working!!! Andrew On Wed, Feb 11, 2009 at 2:57 PM, Matt Benson gudnabr...@yahoo.com wrote: It should be as simple as Thing _containing_ a ListThing rather than _being_ a ListThing. Composition over inheritance, do you see? HTH, Matt --- On Tue, 2/10/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org, gudnabr...@yahoo.com Date: Tuesday, February 10, 2009, 7:06 PM Matt, Thank You. Is there any other data structure I can use that would work with JXPath? My requirement is that... a Thing can have contain multiple child Thing(s) (and the children are allowed to be non-unique). This is equivalent to an XML element as it can contain multiple child elements, how do these guy's handle it I wonder? --Andrew On Wed, Feb 11, 2009 at 9:09 AM, Matt Benson gudnabr...@yahoo.com wrote: I admit I hadn't looked at this with a highly critical eye, but this business of Thing extending ArrayListThing seems quite strange to me. JXPath basically functions by opening up collections automatically, so the very fact that Thing is itself a Collection implies that a Thing will be opened up, and its children will be searched... but in this example, either there are no children, at the leaves, or the children themselves are (possibly empty) collections. It looks as though you're trying to represent a tree structure. This may be a good example of a reason for the idea of composition over inheritance. I don't think you're going to get any traction using JXPath with this object model. Sorry for the bad news, Matt --- On Tue, 2/10/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: Re: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Tuesday, February 10, 2009, 7:16 AM Still busted. Example is now simplified. As soon as a generic Collection becomes involved BOOM! The Main Method to exec: public class App { public static void main( String[] args ){ JXPathContext context = JXPathContext.newContext(new ThingRoot()); System.out.println(((Thing)context.getValue(/root)).getName()); } } The (populated) context root I am using, where root is a single object holding a List of Thing's. package jxpathresearch; import java.util.ArrayList; import java.util.List; public class ThingRoot { private ListThing root new ArrayList(); //this will serve as the root. public ThingRoot() { Thing animal = new Thing(Animal); root.add(animal);//Animal Thing dog = new Thing(Dog); animal.add(dog);//Animal.Dog dog.add(new Thing(Labrador));//Animal.Dog.Labrador dog.add(new Thing(Boxer));//Animal.Dog.Boxer } public ListThing getRoot() { return root; } } Finally here's a very simple 'Thing' that contains a List of Thing(s): public class Thing extends ArrayListThing { public Thing(String name){this.name = name;} private String name = ; public String getName() {return name;} } I can't query anything beyond /root, it doesn't seem to ever get traversed. I would expect results for //Thing and //thi...@name='Labrador'] etc but I get no results only exceptions. My brain is hurting. On Tue, Feb 10, 2009 at 12:22 AM, Andrew Hughes ahhug...@gmail.com wrote: I've noew tested a whole heap of expressions even //name='Tiger' nothing works. On Tue, Feb 10, 2009 at 12:01 AM, Andrew Hughes ahhug...@gmail.comwrote: I got cracking on testing this out... no luck (yet). Here's my testing code if some kind person could please take a look First my generic collection hierarchy (which only contains a name and children)... package jxpathresearch; import java.util.ArrayList; public class HierarchyPojo extends ArrayListHierarchyPojo { public HierarchyPojo(String name){ this.setName(name); } private String name = ; public String getName() { return name; } public void setName(String name
Re: JXPath over Generic Collection?, How?
I got cracking on testing this out... no luck (yet). Here's my testing code if some kind person could please take a look First my generic collection hierarchy (which only contains a name and children)... package jxpathresearch; import java.util.ArrayList; public class HierarchyPojo extends ArrayListHierarchyPojo { public HierarchyPojo(String name){ this.setName(name); } private String name = ; public String getName() { return name; } public void setName(String name) { this.name = name; } } Next, the wrapper for the root context (as Matt suggested) and populated with animals... package jxpathresearch; public class CollectionRoot { private HierarchyPojo hierarchyPojo; public CollectionRoot(){ //Animal hierarchyPojo = new HierarchyPojo(Animal); //Animal.Dog HierarchyPojo dog = new HierarchyPojo(Dog); //Animal.Dog.Labrador dog.add(new HierarchyPojo(Labrador)); //Animal.Dog.Boxer dog.add(new HierarchyPojo(Boxer)); //Animal.Dog.Mastiff dog.add(new HierarchyPojo(Mastiff)); //Animal.Cat HierarchyPojo cat = new HierarchyPojo(Cat); //Animal.Cat.Tiger cat.add(new HierarchyPojo(Tiger)); //Animal.Cat.Cougar cat.add(new HierarchyPojo(Cougar)); //Animal.Cat.Leopard cat.add(new HierarchyPojo(Leopard)); //Add Animal.Dog Animal.Cat hierarchyPojo.add(dog); hierarchyPojo.add(cat); } public HierarchyPojo getHierarchyPojo() {return hierarchyPojo;} public void setHierarchyPojo(HierarchyPojo hierarchyPojo) {this.hierarchyPojo = hierarchyPojo;} } Finally invoke and test... public class App { public static void main( String[] args ) { JXPathContext context = JXPathContext.newContext(new CollectionRoot()); String query = //hierarchypo...@name='Tiger']; String fName = context.getValue(query).toString(); System.out.println(Ran '+query+' and got '+fName+'); } } Above, should find one entry for 'name=Tiger' but it does not, I get an exception. This still doesn't seem to traverse the Collection correctly. Any help would be most welcome. Exception in thread main org.apache.commons.jxpath.JXPathNotFoundException: No value for xpath: //hierarchypo...@name='Tiger'] Thanks for reading, Andrew On Mon, Feb 9, 2009 at 10:24 PM, Andrew Hughes ahhug...@gmail.com wrote: Thanks Matt - I will test this out tomorrow when I am back in the office... Being constructive... Surely this should at least be a precondition check and throw a specific exception if it's not supported? Thank You --Andrew On Mon, Feb 9, 2009 at 2:27 PM, Matt Benson gudnabr...@yahoo.com wrote: Most likely your problem is not with generics, but simply with the fact that JXPath has a hard time using a collection as its root. The easiest workaround is to use some parent object to hold a reference to your container. HTH, Matt --- On Sun, 2/8/09, Andrew Hughes ahhug...@gmail.com wrote: From: Andrew Hughes ahhug...@gmail.com Subject: JXPath over Generic Collection?, How? To: Commons Users List user@commons.apache.org Date: Sunday, February 8, 2009, 5:09 PM Hi All, Hopefully the solution is as easy as the question. I would like to perform evaluation on a (very simple) generic collection... as you can see below (HeirarchyPojo). I should be able to ask for a HeirarchyPojo's with name='Bill' or the 3rd Child... The problem is that nothing ever evaluate on this data structure. What's the deal with Generic Collections and JXPath? p.s this is not in the userguide and would be a most welcomed addition (if we can nut this out with your help). Cheers. package xpath.and.generics; import java.util.ArrayList; public class HeirarchyPojo extends ArrayListHeirarchyPojo{ public HeirarchyPojo(){} private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } - To unsubscribe, e-mail: user-unsubscr...@commons.apache.org For additional commands, e-mail: user-h...@commons.apache.org
JXPath over Generic Collection?, How?
Hi All, Hopefully the solution is as easy as the question. I would like to perform evaluation on a (very simple) generic collection... as you can see below (HeirarchyPojo). I should be able to ask for a HeirarchyPojo's with name='Bill' or the 3rd Child... The problem is that nothing ever evaluate on this data structure. What's the deal with Generic Collections and JXPath? p.s this is not in the userguide and would be a most welcomed addition (if we can nut this out with your help). Cheers. package xpath.and.generics; import java.util.ArrayList; public class HeirarchyPojo extends ArrayListHeirarchyPojo{ public HeirarchyPojo(){} private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }