abdera-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Garrett Rooney" <roo...@electricjellyfish.net>
Subject Re: Extensions
Date Mon, 30 Oct 2006 01:07:50 GMT
On 10/28/06, James M Snell <jasnell@gmail.com> wrote:
> Ok, so I've spent some time this morning implementing a way of
> separating extensions from the underlying Axiom implementation.  The
> mechanism is surprisingly simple.  I haven't checked this in yet but
> will do so if no one cries Stop!
>
> I've attached the patch for review.
>
> To create an extension element, a developer would extend either
> ElementWrapper or ExtensibleElementWrapper.
>
>   public class FooElement extends ElementWrapper {
>     protected FooElement(Element internal) {
>       super(internal);
>     }
>     protected FooElement(Factory factory) {
>       super(factory, TestExtensionFactory.FOO);
>     }
>     public String getFoo() {
>       return getText();
>     }
>     public void setFoo(String foo) {
>       setText(foo);
>     }
>   }
>
> Then register an ExtensionFactory like before, but the methods have
> changed a bit:
>
>   public class TestExtensionFactory implements ExtensionFactory {
>
>     public static final QName FOO = new QName("urn:foo", "foo");
>
>     @SuppressWarnings("unchecked")
>     public <T extends Element> T getElementWrapper(Element internal) {
>       QName qname = internal.getQName();
>       if (qname.equals(FOO)) return (T)new FooElement(internal);
>       return (T) internal;
>     }
>     public List<String> getNamespaces() {
>       return java.util.Arrays.asList(new String[] {"urn:foo"});
>     }
>     public boolean handlesNamespace(String namespace) {
>       return namespace.equals("urn:foo");
>     }
>   }
>
> We can then use FooElement seamlessly with the core API
>
>     Abdera abdera = new Abdera();
>     Factory factory = abdera.getFactory();
>     factory.registerExtension(new TestExtensionFactory());
>     Entry entry = factory.newEntry();
>     FooElement foo = entry.addExtension(TestExtensionFactory.FOO);
>     foo.setFoo("testing");
>
> Or...
>
>     Abdera abdera = new Abdera();
>     Factory factory = abdera.getFactory();
>     factory.registerExtension(new TestExtensionFactory());
>
>     String s = "<foo xmlns='urn:foo'>testing</foo>";
>     ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes());
>
>     Parser parser = abdera.getParser();
>     ParserOptions options = parser.getDefaultParserOptions();
>     options.setFactory(factory);
>
>     Document<FooElement> doc = parser.parse(in, null, options);
>     FooElement foo = doc.getRoot();
>     System.out.println(foo.getFoo());
>
> Thoughts?

In concept I like this a lot.  It's very similar to what I did when I
was playing with decoupling the extension mechanism from the parser
around ApacheCon, with the key difference being that James knows
enough about the FOM code to make the idea actually work ;-)

One thing that makes me pause as I read over the actual diff is the
ExtensionFactoryMap stuff.  It's storing the mapping between elements
and their wrapper class, so when we have an underlying OMElement
instance we can go back to the wrapper object and pass that back to
the user.  Ok, that seems like a fine solution, but I wonder if we're
going to be setting ourselves up for memory leaks by storing
references to all the wrapper elements a factory creates in that map.
Should this be using some sort of weak reference type thing here to
avoid that?

In general though, I'm very +1 on this, and if the patch is done (and
the extensions converted) I'd love to get it in before our proposed
release.

-garrett

Mime
View raw message