On 10/28/06, James M Snell <[EMAIL PROTECTED]> 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
