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]

Reply via email to