-
Notifications
You must be signed in to change notification settings - Fork 56
Description
1. Description
Currently, the ODF Toolkit’s DOM classes directly extend implementation-specific classes (e.g., Apache Xerces). This creates significant technical debt and "Dependency Hell" for downstream projects that require different XML implementations or specific versions of Xerces that conflict with the Toolkit’s requirements.
As pointed out by Axel in Issue #54, the ODF Toolkit should not rely on a particular implementation. While the JDK includes a Xerces-based implementation by default, the internal classes are not exposed. Relying on external Xerces implementation classes prevents the Toolkit from being a truly portable library.
2. The Core Problem: Inheritance vs. Delegation
The current architecture uses an "is-a" relationship:
OdfElementextendsorg.apache.xerces.dom.ElementImpl
This makes it impossible to swap the underlying XML engine without a major rewrite. To achieve implementation independence, we must move to a "has-a" relationship (The Adapter/Delegation Pattern):
OdfElementimplementsorg.w3c.dom.Elementand wraps a generic JAXP-provided Node.
3. Proposed Solution: JAXP Abstraction Layer
We should rely exclusively on the interfaces defined in JAXP (Java API for XML Processing).
A. Configuration-Based Factory
Create a central factory to handle document creation. This allows the Toolkit to have a default (like Xerces) while allowing users to override it via configuration.
public class OdfXmlFactory {
/**
* Provides a DocumentBuilder based on:
* 1. A system property override
* 2. Standard JAXP discovery (META-INF/services)
* 3. A default fallback implementation
*/
public static DocumentBuilder getDocumentBuilder() throws Exception {
String customFactory = System.getProperty("odftoolkit.xml.factory");
if (customFactory != null) {
return DocumentBuilderFactory.newInstance(customFactory, null).newDocumentBuilder();
}
// Standard JAXP discovery mechanism
return DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
}