Dmitri, Thanks for your reply.
I understand about the backward compatibility issue, no problem. (Although it does strike me as a bit strange that someone would require an index of zero if the target is not an indexed one, I guess you're fighting a losing battle if you are trying to satisfy everyones different requirements :) Answer: I'm not sure I understand your question. Is it not the case that my Factory will only be invoked when the sequence needs to be created? In fact, I just realised, unless I am mistaken, that my factory will be useless if I want to add objects to a sequence that isn't null, because if I execute this line: context.createPathAndSetValue("/myList", new sequence() ); before this one: context.createPathAndSetValue("/myList[2]/name", "harry"); the Factory will not get invoked (to create the sequence) and therefore I will get an IndexOutOfBoundsException when JXPath trys to retrieve the second element of the list. Oh well, it's all useful learning. As I said, I am still just playing with ideas. I will check out the Clazz stuff. Thanks. The main problem with Castor intergration, as I see it, is that Castor doesn't support Collections as much as it could. The generated classes, even for sequences, do not implement List, which could be an issue. I may end up ditching Castor in favour of Betwixt. I haven't really looked at it yet, but it might provide for better intergration, although I do like working from an XML Schema (with castor). I guess I can't have my cake AND eat it 8]. Adam. ----- Original Message ----- From: "Dmitri Plotnikov" <[EMAIL PROTECTED]> To: "Jakarta Commons Developers List" <[EMAIL PROTECTED]> Sent: Tuesday, February 04, 2003 3:20 PM Subject: Re: [JXPath] creating sequences > Adam, > > Thank you for your kind words. > > The PropertyPointer used to work just like you are suggesting, but then > somebody complained and I changed it to always pass a legitimate index. > So now it is a backward compatibility issue. > > Question: can't you determine whether you need to create the collection > by simply checking if it exists? With Castor it would not make sense > to create a collection and leave it empty anyway, right? > > Your GenericFactory is quite impressive. BTW, check out our new > sandbox "clazz" project. It standardizes the introspection of those > "add" methods, plural property names and does many other fun things. If > clazz ever climbs out of the sandbox, we will integrate it with jxpath > and provide a customization of Castor. So the application of jxpath to > Castor will become more natural. > > Best regards, > > - Dmitri > > > --- Adam J Chesney <[EMAIL PROTECTED]> wrote: > > Hi, > > > > I am new to JXPath but it looks great, thanks for all your hard work. > > I have just been playing around with it a little as I would like to > > use it in a new project that I am working on. I wanted to implement a > > generic Factory to create objects and I ran into a small snag. I just > > wanted to run this by you. My GenericFactory (attached) is a bit > > rough around the edges but it automatically creates properties using > > reflection to find the appropriate set method on the parent object, > > and then instantiates an instance of the appropriate class (parameter > > type). This works fine for straight beans but using the same method > > for sequences causes a problem because atm it is not possible to > > determine whether or not the target property is a sequence or not. If > > you can determine that you are creating a sequence then it is > > possible (in some circumstances) to determine the type of the objects > > to be added to the newly created sequence, and to add them during the > > construction of the sequence property. This won't work for generic > > Collections, but it will work for custom sequences that implement > > List, which is what I am using (Castor based beans). > > > > By changing line 178 in > > > > org.apache.commons.jxpath.ri.model.beans.PropertyPointer.java > > > > from > > > > int inx = (index == WHOLE_COLLECTION ? 0 : index); > > > > to > > > > int inx = (index == WHOLE_COLLECTION ? -1 : index); > > > > I am now able to determine whether or not the target property for > > construction is a sequence and is accessed using an index and I can > > therefore, in the factory, create the required number of objects. > > Previously, it was impossible to tell the difference between /myList > > and /myList[1] because the index passed to the Factory in both cases > > is 0. > > > > So I can now execute calls like: > > > > context.createPathAndSetValue("/myList[2]/name", "harry"); > > > > Even though myList is null to start with, the GenericFactory can > > determine that myList is a sequence and it can create 2 objects to > > add into it after creating and sequence and assigning it to the root > > context. > > > > Anyway, I don't think this change should negatively effect anyone and > > so I thought that maybe you could add it to the main tree. If it's > > not possible, then no problem, I can maintain my own version. I guess > > a change like this could potentially cause problems if the Factory > > coding was a bit "lazy". > > > > Anyway, once agin, thanks for this kewl tool. > > > > Warm regards, > > > > Adam Chesney. > > > > > > ===================================================== > > > > Tel: (+44) 117 908 1254 (Direct) > > Mobile (+44) 7780 962 961 > > email: [EMAIL PROTECTED] > > > > 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.lang.reflect.*; > > > > /** > > * <p>Title: </p> > > * <p>Description: </p> > > * <p>Copyright: Copyright (c) 2003</p> > > * <p>Company: </p> > > * @author Adam J Chesney > > * @version 1.0 > > */ > > > > public class GenericFactory extends AbstractFactory > > { > > > > public boolean createObject(JXPathContext context, Pointer pointer, > > Object parent, String name, int index) > > { > > try > > { > > // grab the parents class > > Class parent_cls = parent.getClass(); > > > > // grab the list of methods for the parent class > > Method[] methods = parent_cls.getMethods(); > > > > // iterate backwards through the methods until we find the > > first > > // 'set' or 'add' method which matches the name property and > > that has just > > // one parameter > > for (int i = methods.length-1; i > -1; i--) > > { > > String mName = methods[i].getName(); > > if ( mName.startsWith("set") || mName.startsWith("add") ) > > { > > if ( mName.substring(3).equals( name.substring(0,1).toUpperCase() > > + name.substring(1) ) ) > > { > > if ( methods[i].getParameterTypes().length == 1 ) > > { > > // we found a matching method, so we grab the class of the > > parameter > > Class target_cls = methods[i].getParameterTypes()[0]; > > > > // create new one (must have a null constructor) > > Object obj = target_cls.newInstance(); > > > > // invoke the add or set method with the new property on the > > parent > > methods[i].invoke( parent, new Object[]{obj} ); > > > > // if the index is 0 or greater then this must be a sequence > > if ( index > -1 ) > > { > > // grab the methods of the property > > Method[] meth = target_cls.getMethods(); > > > > // again iterate backwards through the methods looking for the > > first > > // add method with one parameter > > // note: we iterate backwards becuase we are more likely to > > encounter > > // a specialized bean method sooner > > for (int j = meth.length-1; j >-1; j--) > > { > > String mn = meth[j].getName(); > > if (mn.startsWith("add") && meth[j].getParameterTypes().length == > > 1 ) > > { > > // found an add method, so we grab the parameter type > > Class new_cls = meth[j].getParameterTypes()[0]; > > for (int k = 0; k <= index; k++) > > { > > // and we add enough new objects to the collection to satisfy > > the index > > meth[j].invoke( obj, new Object[]{new_cls.newInstance()} ); > > } > > break; > > } > > } > > } > > > > return true; > > } > > } > > } > > } > > } > > catch (Exception e1) > > { > > e1.printStackTrace(); > > } > > return false; > > } > > } > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > > __________________________________________________ > Do you Yahoo!? > Yahoo! Mail Plus - Powerful. Affordable. Sign up now. > http://mailplus.yahoo.com > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]