Hi all guys, during the weekend, taking inspiration from a builder idea proposed by James Carman[1] time ago, I spent some spare time on doing a local experiment (complete at 75% with running tests copied and adapted from trunk) on my beloved component, at the end of wich I realized it would be a good time to propose a 3.0 version of Digester APIs and offer to our users a new Digester experience, with new, fresh, *simplified* APIs.
Existing Digester is mature and stable enough, but what I found points of improvement are: * configuration APIs, I propose a unique point of configuration - at this stage, users can configure the Digester instance by * the Digester itself; * the Rules; * the RuleSet; * the Loader; * too many loaders: one loader is enough, what it can do is loading different digester modules/extensions; * there are configurations tasks that can be delegated to a Loader instead of the Digester, such * SAX Parser settings; * ClassLoader settings; * ... * the Digester contains some features that IMHO can be dropped: * the StackAction listener - I wonder who used that in production; * the custom ContentHandler - it intercepts the default Digester behavior that makes the Digester use == default SAX APIs Being a Google-Guice user (I've been integrating it with many frameworks such apache bval and mybatis on top, and I like how they designed the Injector modularization) I took inspiration also from their APIs so that's an overview of my proposal: * Users can configure digester rules by implementing RulesModule interface: +-----------------------------------------------------------------------------+ class MyRuleModule implements RulesModule { public void configure(RulesBinder rulesBinder) { rulesBinder.when("employee") .objectCreate(Employee.class) .setProperties(); rulesBinder.when("employee/address") .objectCreate("org.apache.commons.digester3.Address") .setProperties() .setNext("addAddress"); } } +-----------------------------------------------------------------------------+ or, according to DRY principles, extending a provided AbstractRulesModules +-----------------------------------------------------------------------------+ class MyRuleModule extends AbstractRulesModules { @Override public void configure() { when("employee") .objectCreate(Employee.class) .setProperties(); when("employee/address") .objectCreate("org.apache.commons.digester3.Address") .setProperties() .setNext("addAddress"); } } +-----------------------------------------------------------------------------+ * users can obtain a Digester instances - Digester is not thread safety so for each parsing operation a new one has to be created! - using a DigesterLoader (methods can be chained using a Builder APIs) +-----------------------------------------------------------------------------+ DigesterLoader loader = DigesterLoader.newLoader(new MyRuleModule()) .setNamespaceAware(true) .setClassLoader(myClassLoader); ... Digester digester = loader.newDigester(); OR digester = loader.newDigester(SAXParser mySaxParser); OR digester = loader.newDigester(XMLReader myXMLReader); +-----------------------------------------------------------------------------+ then parse documents +-----------------------------------------------------------------------------+ Object myObject = digester.parse(new URL("http://my-rest.server/service.xml")); +-----------------------------------------------------------------------------+ * Users can still load rules from XML using provided modules: +-----------------------------------------------------------------------------+ DigesterLoader loader = DigesterLoader.newLoader(new MyRuleModule(), new org.apache.commons.digester3.xmlrules.FromXMLRulesModule(new URL("http://my.host/my-shared-config.xml"))) .setNamespaceAware(true) .setClassLoader(myClassLoader); +-----------------------------------------------------------------------------+ or from Annotations +-----------------------------------------------------------------------------+ DigesterLoader loader = DigesterLoader.newLoader(new MyRuleModule(), new org.apache.commons.digester3.annotations.FromAnnotationsRulesModule(Employee.class)) .setNamespaceAware(true) .setClassLoader(myClassLoader); +-----------------------------------------------------------------------------+ So now to show you the potential of new APIs, I would like to start committing the stuff I realized locally - before they will be lost! :P - but I don't know how would be the better way to start. Which one fits better, a 3.X branch or the sandbox? I'm open to your feedbacks, thoughts, suggestions, constructive criticism. I estimated to complete this work in 2-3 weeks, documentation included, depending on requested effort by my main job. I'm confident on your help, please let me know!!! All the best, have a nice day, Simo [1] https://issues.apache.org/jira/browse/DIGESTER-135 http://people.apache.org/~simonetripodi/ http://www.99soft.org/ --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org