Quick potential suggestions: - Set some property on the parent, and query it in your factory - Subclass TheObject and override the dataArray accessors to TheChild[] - Use a different factory instance that does what you want
Matt On Fri, Jul 29, 2011 at 6:17 PM, Hippo Man <[email protected]> wrote: > I'm fairly new to JXPath and I have a question for which I was unable to find > an answer in any of the places I searched for on line. I ask you in advance to > please forgive me if the answer to my question can be found in some > easy-to-locate > place that I happened to overlook. > > Is there a way to do casting within a path-based JXPath setter? I'd like to be > able to optionally specify that the setting of an item gets done via a > subclass that > has more attributes than the parent, but I couldn't find out how to do this. > > I'm sure that my question is not completely clear, so as you read this > discussion, please look at the Java fragments at the bottom of this message > to see an illustration of what I'm trying to do. > > Consider the sample class (below) called TheObject. It has two attributes: > a String called "name", and an array of TheData objects. > > The TheData class (below) contains a single String attribute called "item". > > There is a subclass of TheData called TheChild, and it contains a String > attribute called "varString", a Long attribute called "varLong", and a Double > attribute called "varDouble". > > I want to use JXPath path-based setters to set the attributes within > TheObject. > I have implemented an extension of AbstractFactory called ObjectFactory > to aid in this procedure. ObjectFactory also appears below. > > In the "main" method of TheObject, I instantiate my JXPath context and attach > my ObjectFactory, after which I set some attributes. As you can see in my > example, this works fine as long as I want my "dataArray" to be instantiated > as an array of TheData objects and then set the "item" attribute of one of > these instances. > > But sometimes, I might want to instantiate "dataArray" with an array of > TheChild > objects. I would like this instantiation to take place within > "createObject", and I'd > like it to be able to determine at runtime via some sort of syntax in > the path setter > that "createObject" should instantiate with TheChild objects instead of > TheData > objects. > > In other words, is there some sort of "casting" syntax that I can pass into > the > path setter which I can then see within the "name" or "pointer" parameters to > "createObject" which can tell me that I have to instantiate that array with > TheChild objects instead of TheData objects? > > For the purpose of illustration, I gave an unworkable example of casting > syntax within the "main" method of TheObject, below. That example shows > exactly what I'm trying to do. > > Thanks in advance for any pointers to documentation or any other help that > any of you might be able to give me. > > Here are the Java code fragments that I mentioned above ... > > public class TheObject { > protected String name = null; > protected TheData[] dataArray = null; > // constructor, getters, setters, and toString have been left out > > public static void main(String[] argv) { > TheObject obj = new TheObject(); > JXPathContext context = JXPathContext.newContext(obj); > context.setFactory(new ObjectFactory()); > > context.createPathAndSetValue("/name", "foo"); // this works > context.createPathAndSetValue("/dataArray[1]/item", "bar"); > // this works > > // But instead of setting "item" as I did above, is there something > // I can do syntactically in the path that I can see within the "name" > // or "pointer" arguments that are passed to the createObject() method > // of ObjectFactory, which would specify that "dataArray" should be > // instantiated as an array of TheChild objects instead of as an array > // of TheData objects? Something analogous to this (I know this > doesn't > // work; it's just for illustration) ... > > context.createPathAndSetValue("/{cast to > TheChild}dataArray[1]/varString", "quack"); > > System.out.println(obj); > > System.exit(0); > } > } > > public class TheData { > protected String item = null; > // constructor, getters, setters, and toString have been left out > } > > public class TheChild extends TheData { > protected String varString = null; > protected Long varLong = null; > protected Double varDouble = null; > // constructor, getters, setters, and toString have been left out > } > > public class ObjectFactory extends AbstractFactory { > > @Override > public boolean createObject(JXPathContext context, Pointer > pointer, Object parent, String name, int index) { > System.out.println("createObject: pointer: " + pointer + ", > parent: " + parent.getClass().getName() + ", name: " + name + ", > index: " + index); > > if (parent instanceof TheObject) { > > // Is there something I can pass in via the path setter or that > // I can access via "pointer" which will tell me that I > want to instantiate > // the data array with instances of TheChild instead of TheData? > > if (name.equalsIgnoreCase("dataArray")) { > TheData[] data = new TheData[index + 1]; > TheData[] oldData = ((TheObject) parent).getDataArray(); > int nold = (oldData == null ? 0 : oldData.length); > for (int n = 0; n <= index; n++) { > if (n < nold) { > data[n] = oldData[n]; > } > else { > data[n] = new TheData(); > } > } > for (int n = index + 1; n < nold; n++) { > data[n] = oldData[n]; > } > ((TheObject) parent).setDataArray(data); > } > return (true); > } > return (false); > } > } > > -- > [email protected] > > --------------------------------------------------------------------- > 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]
