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: [email protected]
For additional commands, e-mail: [email protected]