Hi all, Just thought I'd throw in my two cents on this issue.
I agree that the structure connecting object models with Navigator implementations should change somewhat. As I see it, we could go one of two ways (there may be more - please suggest them if you have any). 1. Similar to the current structure, but with the following changes: * org.jaxen.JaXPath combined with BaseXPath and renamed to org.jaxen.XPath * org.jaxen.dom.XPath renamed to org.jaxen.dom.DomXPath * org.jaxen.dom4j.XPath renamed to org.jaxen.dom4j.Dom4jXPath * etc... This would then be used in the following manner: org.jaxen.XPath xpath = new org.jaxen.jdom.JdomXPath("//foo/bar"); List nodes = xpath.selectNodes( myJdomDocument ); This is similar to the pattern used by the Collections API, were you will generally have the local variable as one of the super-types (List, Map, Set) which are initialised to a specific implementation (ArrayList, HashMap, HashSet). Advantages: * No reflection, leading to slightly better performance and (depending on your opinion) better readability. * Fairly simple to implement - it's basically already done. * Object model support is completely decoupled from the core engine Disadvantages: * Requires an almost-empty subclass that simply overrides one method. Seems wasteful. OR 2. Have a single XPath implementation that uses reflection to determine which Navigator implementation to use. * org.jaxen.JaXPath combined with BaseXPath and renamed to org.jaxen.XPath * org.jaxen.dom.XPath removed. * etc... The new org.jaxen.XPath would examine the class type of the object being passed in to it's 'selectNodes()' or 'selectSingleNode()' or other methods and use reflection to determine which Navigator implementation supports it. It would then be used in the following manner: org.jaxen.XPath xpath = new org.jaxen.XPath("//foo/bar"); List nodes = xpath.selectNodes( myXmlDocumentModel ); It would also have to support adding extra (non-standard) object models. This could be done in a couple of ways. One would be to have a static registry of navigators that can be added to by users of custom object models. Eg: // Register my custom object model XPath.registerNavigator("org.myxml.jaxen.DocumentNavigator", "org.myxml"); org.jaxen.XPath xpath = new org.jaxen.XPath("//foo/bar"); List nodes = xpath.selectNodes( myXmlDocument ); ...where "org.myxml" being passed in indicates that all objects that are in the "org.myxml" package (or it's descendants) should use the "org.myxml.jaxen.DocumentNavigator" navigator implementation. Alternately, the Navigator instance could be passed in, either to the XPath constructor or the selectNodes() method. Eg: Navigator nav = new org.myxml.jaxen.DocumentNavigator(); org.jaxen.XPath = new XPath("//foo/bar"); List nodes = xpath.selectNodes( myXmlDocument, nav ); Advantages: * Simple to use in the common case: just create the same XPath object every time and it works for most models. * Allows changing of the XML object model without changing the XPath code. Disadvantages: * Uses reflection. * Requires some hard-coded links somewhere (be they Strings or otherwise) that map object types to a Navigator implementation. Conclusion: ----------- At first, I was quite attracted to the reflection structure. It would mean you have a single class (org.jaxen.XPath) that can be used everywhere, no matter what object model you are using. On further reflection however, the model doesn't have that many advantages and has several significant disadvantages. Firstly, the first structure suggested above isn't that arduous. If you use the abstract base class (org.jaxen.XPath) everywhere in your code other than when constructing, switching between object models is trivial. If you change your object model from JDOM to Dom4J, it requires changes to a single line of code for each XPath instance. And chances are that if you're switching between two models, those line changes will be the simplest changes you have to make. Secondly, using the reflection structure requires more work that previously for non-standard object models. You have to either register your Navigator somewhere, or pass it around all over the place. Thirdly, and perhaps most critically, using reflection is not that simple, and it means there are concrete (or at least masking-tape) links between the core engine and the standard XML object models. To use reflection, something will either have to map each specific Object in the XML object model (eg. org.jdom.Document, org.jdom.Element, etc...) to it's appropriate Navigator, or use the short-cut of mapping to the package name rather than the specific classes (eg "org.jdom", "org.w3.dom", etc). The former method is tedious, the latter dangerous (it will allow inserting of other objects such as "org.jdom.JDOMException"), and both are more inefficient. I definitely believe that whatever scenario you decide on, "org.jaxen.XPath" should be the standard variable type, something I'm not comfortable doing with JaXPath or BaseXPath at the moment. But I don't think it is necessary or even advantagious to change to a reflection model. If you're really keen, you could make "org.jaxen.XPath" an interface (except that you also have an interface called "org.jaxen.expr.XPath" - could/should that be changed also?) and have BaseXPath as the abstract base class implementing org.jaxen.XPath. Anyway, sorry for the length and thanks for your attention... David Peterson _______________________________________________ Jaxen-interest mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jaxen-interest