mirror of
https://github.com/moparisthebest/sxf4j
synced 2024-12-21 22:18:49 -05:00
First Commit
This commit is contained in:
commit
dbfb93c5ed
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
target/
|
||||||
|
out.xml
|
165
license.txt
Normal file
165
license.txt
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
67
pom.xml
Executable file
67
pom.xml
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.moparscape</groupId>
|
||||||
|
<artifactId>sxf4j</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>sxf4j</name>
|
||||||
|
<description>
|
||||||
|
The Simple XML Facade for Java or (SXF4J) serves as a simple facade or abstraction for various xml frameworks, e.g. org.w3c.dom, dom4j, xpp, xpp3 and xom, allowing the end user to plug in the desired xml framework at deployment time.
|
||||||
|
</description>
|
||||||
|
<url>https://github.com/moparisthebest/sxf4j</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- for Xpp3XmlElement -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.plexus</groupId>
|
||||||
|
<artifactId>plexus-utils</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- for XppXmlElement -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.thoughtworks.xstream</groupId>
|
||||||
|
<artifactId>xstream</artifactId>
|
||||||
|
<version>1.4.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- for Dom4jXmlElement-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>dom4j</groupId>
|
||||||
|
<artifactId>dom4j</artifactId>
|
||||||
|
<version>1.6.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- for XomXmlElement-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>xom</groupId>
|
||||||
|
<artifactId>xom</artifactId>
|
||||||
|
<version>1.2.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>Travis Burtrum</name>
|
||||||
|
<url>http://www.moparisthebest.com/</url>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>GNU LESSER GENERAL PUBLIC LICENSE, Version 3</name>
|
||||||
|
<url>http://www.gnu.org/licenses/lgpl.html</url>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<developerConnection>scm:git:git@github.com:moparisthebest/sxf4j.git</developerConnection>
|
||||||
|
<connection>scm:git:git@github.com:moparisthebest/sxf4j.git</connection>
|
||||||
|
<url>git@github.com:moparisthebest/sxf4j.git</url>
|
||||||
|
</scm>
|
||||||
|
</project>
|
20
readme.txt
Normal file
20
readme.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
SXF4J
|
||||||
|
|
||||||
|
This library provides a common interface for multiple different XML implementations, so they can be plugged in at runtime,
|
||||||
|
or programmatically selected by the programmer, allowing them to access the backing implementation for extra features,
|
||||||
|
and seamlessly convert between different implementations via a copy method.
|
||||||
|
|
||||||
|
Currently, and as a side project that may be separated from this in the near future, the class ClassXmlElement may be
|
||||||
|
extended by any class, which can be annotated with @Attribute or @Child annotations so it can be seamlessly dumped to an
|
||||||
|
XML file by calling the toXml() method of ClassXmlElement, this makes it easy to represent an XML file in java code without
|
||||||
|
any logic per class to dump it to XML. Functionality is planned to load the class from the XML file as well. After writing
|
||||||
|
this class, I discovered that a program called XStream offers similar (if more complex) functionality, but I still believe
|
||||||
|
this is simpler and easier to work with, and they still have different purposes. (XStream offers serialization, this class
|
||||||
|
simply aims to simplify the XML to Java Class and back process.)
|
||||||
|
|
||||||
|
Hopefully someone besides me will find this useful, I would be more than happy to accept feature requests, patches, and
|
||||||
|
pull requests.
|
||||||
|
|
||||||
|
SXF4J is currently licensed under the GNU/LGPLv3. If you need this under another license, let me know and I'll see what I can do.
|
||||||
|
|
||||||
|
Enjoy!
|
136
src/main/java/org/moparscape/XmlTest.java
Executable file
136
src/main/java/org/moparscape/XmlTest.java
Executable file
@ -0,0 +1,136 @@
|
|||||||
|
package org.moparscape;
|
||||||
|
|
||||||
|
import org.moparscape.xml.ClassXmlElement;
|
||||||
|
|
||||||
|
import org.moparscape.xml.ClassXmlElement.Root;
|
||||||
|
import org.moparscape.xml.impl.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Root(name = "xmltest1")
|
||||||
|
public class XmlTest extends ClassXmlElement {
|
||||||
|
|
||||||
|
private enum Bob {
|
||||||
|
TOM,
|
||||||
|
CHARLES,
|
||||||
|
EDWARD
|
||||||
|
}
|
||||||
|
|
||||||
|
@Child
|
||||||
|
private Bob bobenum = Bob.TOM;
|
||||||
|
|
||||||
|
@Child
|
||||||
|
private String bob = "tom";
|
||||||
|
|
||||||
|
@Attribute
|
||||||
|
private String xmlns_xsl = "http://www.w3.org/1999/XSL/Transform";
|
||||||
|
|
||||||
|
@Attribute
|
||||||
|
public String xmlns = "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
|
@Attribute
|
||||||
|
public static String xmlnsstatic = "http://www.w3.org/1999/xhtml";
|
||||||
|
|
||||||
|
@Attribute
|
||||||
|
private static String xmlns_xslstatic = "http://www.w3.org/1999/XSL/Transform";
|
||||||
|
|
||||||
|
@Child(children = {"dep", "subdep", "subsubdep"})
|
||||||
|
private static List<Object> deps = Arrays.asList((Object) "dep1", "dep2", "dep3"
|
||||||
|
, new Object[]{"subdep1", "subdep2"
|
||||||
|
, new Object[]{"subsubdep1", "subsubdep2"}
|
||||||
|
}
|
||||||
|
// , new XmlTest()
|
||||||
|
);
|
||||||
|
|
||||||
|
@Attribute
|
||||||
|
private String[] modules = new String[]{"mod1", "mod2"};
|
||||||
|
|
||||||
|
@Attribute()
|
||||||
|
private static Map<String, Object> map = new HashMap<String, Object>() {{
|
||||||
|
put("k1", "v1");
|
||||||
|
put("k2", "v2");
|
||||||
|
// put("k3", new XmlTest());
|
||||||
|
// put("k4", new Object[]{"mapsubdep1", "mapsubdep2"
|
||||||
|
// ,new Object[]{"mapsubsubdep1", "mapsubsubdep2"}
|
||||||
|
// });
|
||||||
|
}};
|
||||||
|
|
||||||
|
@Child
|
||||||
|
private static XmlTest childXmlTest = new XmlTest();
|
||||||
|
// @Attribute private static XmlTest childXmlTest = new XmlTest();
|
||||||
|
|
||||||
|
@Attribute
|
||||||
|
private String getCharley() {
|
||||||
|
return "charley content";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Child()
|
||||||
|
private String[] getdependencies() {
|
||||||
|
return new String[]{"dependency1", "dependency2", "dependency3"};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
System.setErr(System.out);
|
||||||
|
//testXmlElement();System.exit(0);
|
||||||
|
XmlElementFactory[] factories = new XmlElementFactory[]{
|
||||||
|
new XppXmlElement(),
|
||||||
|
new Xpp3XmlElement(),
|
||||||
|
new Dom4jXmlElement(),
|
||||||
|
new W3CXmlElement(),
|
||||||
|
new XomXmlElement(),
|
||||||
|
};
|
||||||
|
for(XmlElementFactory factory : factories)
|
||||||
|
testXmlElement(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testDynamicImpls() throws Exception {
|
||||||
|
|
||||||
|
String[] impls = new String[]{
|
||||||
|
AbstractXmlElement.XPP
|
||||||
|
, AbstractXmlElement.XPP3
|
||||||
|
, AbstractXmlElement.DOM4J
|
||||||
|
, AbstractXmlElement.XOM
|
||||||
|
, AbstractXmlElement.W3C
|
||||||
|
};
|
||||||
|
for (String impl : impls) {
|
||||||
|
System.setProperty(AbstractXmlElement.implProperty, impl);
|
||||||
|
testXmlElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testXmlElement() throws Exception {
|
||||||
|
testXmlElement(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testXmlElement(XmlElementFactory copyTo) throws Exception {
|
||||||
|
XmlElement xml = new XmlTest().toXml();
|
||||||
|
System.out.println(xml.getClass());
|
||||||
|
//nu.xom.Element e = xml.unwrap(nu.xom.Element.class);
|
||||||
|
//System.out.println("internal class: " + xml.unwrap(nu.xom.Element.class));
|
||||||
|
if (copyTo != null) {
|
||||||
|
xml = xml.copyTo(copyTo);
|
||||||
|
System.out.println("copied: " + xml.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
xml.writeToFile("./out.xml");
|
||||||
|
System.out.printf("child name: '%s' value: '%s'\nattribute xmlns: '%s'\n",
|
||||||
|
xml.getChild("bob").getName(),
|
||||||
|
xml.getChild("bob").getValue(),
|
||||||
|
// ""
|
||||||
|
xml.getAttribute("xmlns")
|
||||||
|
);
|
||||||
|
System.out.println("parent node (should be null): " + (xml.getParent() == null ? "null" : xml.getParent().getName()));
|
||||||
|
System.out.println("parent node of child (NOT null): " + (xml.getChildren()[0].getParent() == null ? "null" : xml.getChildren()[0].getParent().getName()));
|
||||||
|
|
||||||
|
System.out.println("attribute names:" + Arrays.toString(xml.getAttributeNames()));
|
||||||
|
|
||||||
|
System.out.println("children count:" + xml.getChildCount());
|
||||||
|
//System.out.println("children: "+Arrays.toString(xml.getChildren()));
|
||||||
|
for (XmlElement children : xml.getChildren()) {
|
||||||
|
System.out.print(children.getName() + ", ");
|
||||||
|
}
|
||||||
|
System.out.println("\n-----");
|
||||||
|
//System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
346
src/main/java/org/moparscape/xml/ClassXmlElement.java
Executable file
346
src/main/java/org/moparscape/xml/ClassXmlElement.java
Executable file
@ -0,0 +1,346 @@
|
|||||||
|
package org.moparscape.xml;
|
||||||
|
|
||||||
|
import org.moparscape.xml.impl.AbstractXmlElement;
|
||||||
|
import org.moparscape.xml.impl.XmlElement;
|
||||||
|
import org.moparscape.xml.impl.XmlElementFactory;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.AccessibleObject;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class ClassXmlElement {
|
||||||
|
|
||||||
|
public static final String[] errors = new String[]{
|
||||||
|
"ERROR GETTING VALUE"
|
||||||
|
, "ERROR: Cannot add " + ClassXmlElement.class.getSimpleName() + " without value as attribute!"
|
||||||
|
, "WARNING: INFINITE RECURSION DETECTED"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static boolean debug = false;
|
||||||
|
|
||||||
|
private final String uuid;
|
||||||
|
|
||||||
|
{
|
||||||
|
uuid = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target({ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Root {
|
||||||
|
String name() default "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Attribute {
|
||||||
|
String name() default "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Child {
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
String childName() default "";
|
||||||
|
|
||||||
|
String[] children() default {};
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getString(Object ret) {
|
||||||
|
if (ret == null)
|
||||||
|
ret = errors[0];
|
||||||
|
return ret.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addToDom(XmlElement addTo, Object key, Object val, boolean child) {
|
||||||
|
if (child)
|
||||||
|
addTo.getNewChildXmlElement(key.toString()).setValue(val.toString());
|
||||||
|
else
|
||||||
|
addTo.setAttribute(key.toString(), val.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private XmlElement getAddTo(XmlElement ret, String name, boolean child) {
|
||||||
|
if (!child) // if we are expecting an attribute, never create a subobject
|
||||||
|
return ret;
|
||||||
|
XmlElement addTo = ret;
|
||||||
|
if (!name.isEmpty())
|
||||||
|
addTo = ret.getNewChildXmlElement(name);
|
||||||
|
return addTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addValueToDom(Object value, MethodField field, XmlElement ret, String name, int childDepth, boolean child, final Set<String> recursionDetector, final XmlElementFactory factory) {
|
||||||
|
if (value == null)
|
||||||
|
value = field.getValue();
|
||||||
|
|
||||||
|
if (name == null)
|
||||||
|
name = field.getName();
|
||||||
|
|
||||||
|
// if it's an array, we convert it to a List
|
||||||
|
// so our List handling code can be re-used
|
||||||
|
if (value instanceof Object[])
|
||||||
|
value = Arrays.asList((Object[]) value);
|
||||||
|
if (value instanceof List) {
|
||||||
|
XmlElement addTo = getAddTo(ret, name, child);
|
||||||
|
String childName = field.getName(child, childDepth);
|
||||||
|
//System.out.printf("name: '%s', childName: '%s'\n", name, childName);
|
||||||
|
List list = (List) value;
|
||||||
|
if (child) {
|
||||||
|
++childDepth;
|
||||||
|
for (Object o : list)
|
||||||
|
addValueToDom(o, field, addTo, childName, childDepth, child, recursionDetector, factory);
|
||||||
|
} else {
|
||||||
|
// if we want an attribute, assume they want the list delimited by spaces
|
||||||
|
// don't bother recursing, attributes can only handle values of type String anyhow
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Object o : list)
|
||||||
|
sb.append(o.toString()).append(" ");
|
||||||
|
sb.delete(sb.length() - 1, sb.length());
|
||||||
|
addToDom(addTo, name, sb.toString(), false);
|
||||||
|
}
|
||||||
|
} else if (value instanceof Map) {
|
||||||
|
XmlElement addTo = getAddTo(ret, name, child);
|
||||||
|
Map<?, ?> map = (Map<?, ?>) value;
|
||||||
|
for (Map.Entry entry : map.entrySet()) {
|
||||||
|
// not sure how to handle this, I guess key would be name
|
||||||
|
addValueToDom(entry.getValue(), field, addTo, entry.getKey().toString(), childDepth, child, recursionDetector, factory);
|
||||||
|
//addToDom(addTo, entry.getKey(), entry.getValue(), child);
|
||||||
|
}
|
||||||
|
++childDepth;
|
||||||
|
} else if (value instanceof ClassXmlElement) {
|
||||||
|
ClassXmlElement other = ((ClassXmlElement) value);
|
||||||
|
if (child)
|
||||||
|
other.toXml(factory, getAddTo(ret, name, child), recursionDetector);
|
||||||
|
else {
|
||||||
|
XmlElement xmlChild = other.toXml(factory, null, recursionDetector);
|
||||||
|
String xmlChildValue = xmlChild.getValue();
|
||||||
|
if (xmlChildValue == null)
|
||||||
|
xmlChildValue = errors[1];
|
||||||
|
ret.setAttribute(xmlChild.getName(), xmlChildValue);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
addToDom(ret, name, getString(value), child);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMethodField(MethodField field, XmlElement ret, final Set<String> recursionDetector, final XmlElementFactory factory) {
|
||||||
|
if (debug)
|
||||||
|
System.out.println(field);
|
||||||
|
boolean accessible = field.isAccessible();
|
||||||
|
field.setAccessible(true);
|
||||||
|
if (field.isAnnotationPresent(Child.class) || field.isAnnotationPresent(Attribute.class))
|
||||||
|
addValueToDom(null, field, ret, null, 0, field.isChild(), recursionDetector, factory);
|
||||||
|
field.setAccessible(accessible);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final XmlElement toXml() {
|
||||||
|
return this.toXml(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final XmlElement toXml(final XmlElementFactory factory) {
|
||||||
|
return this.toXml(factory == null ? AbstractXmlElement.getFactory() : factory, null, new HashSet<String>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private XmlElement toXml(final XmlElementFactory factory, final XmlElement parent, final Set<String> recursionDetector) {
|
||||||
|
|
||||||
|
Class thisClass = this.getClass();
|
||||||
|
String rootName = thisClass.getSimpleName();
|
||||||
|
if (thisClass.isAnnotationPresent(Root.class)) {
|
||||||
|
String rootAnnotationName = this.getClass().getAnnotation(Root.class).name();
|
||||||
|
if (!rootAnnotationName.isEmpty())
|
||||||
|
rootName = rootAnnotationName;
|
||||||
|
}
|
||||||
|
XmlElement ret = parent != null ? parent.getNewChildXmlElement(rootName) : factory.getNewChildXmlElement(rootName);
|
||||||
|
|
||||||
|
if (recursionDetector.contains(this.uuid)) {
|
||||||
|
if (debug)
|
||||||
|
System.out.println("Infinite Recursion detected, returning...");
|
||||||
|
ret.setValue(errors[2]);
|
||||||
|
return ret;
|
||||||
|
//return E("WARNING", "INFINITE RECURSION DETECTED");
|
||||||
|
//return null;
|
||||||
|
}
|
||||||
|
recursionDetector.add(this.uuid);
|
||||||
|
|
||||||
|
List<MethodField> mfList = new LinkedList<MethodField>();
|
||||||
|
|
||||||
|
for (Field field : thisClass.getDeclaredFields())
|
||||||
|
mfList.add(new MethodField(this).setField(field));
|
||||||
|
for (Method method : thisClass.getDeclaredMethods())
|
||||||
|
mfList.add(new MethodField(this).setMethod(method));
|
||||||
|
|
||||||
|
// find and add xmlns first thing, some implementations require this (currently Dom4jXmlElement and XomXmlElement)
|
||||||
|
Iterator<MethodField> iter = mfList.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
MethodField mf = iter.next();
|
||||||
|
if(mf.isChild())
|
||||||
|
continue;
|
||||||
|
String name = mf.getName();
|
||||||
|
if(!name.equals("xmlns") && !name.startsWith("xmlns:"))
|
||||||
|
continue;
|
||||||
|
// otherwise, process the entry and remove it from the list
|
||||||
|
processMethodField(mf, ret, recursionDetector, factory);
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(MethodField mf : mfList)
|
||||||
|
processMethodField(mf, ret, recursionDetector, factory);
|
||||||
|
|
||||||
|
recursionDetector.remove(this.uuid);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MethodField extends java.lang.reflect.AccessibleObject {
|
||||||
|
private final Object container;
|
||||||
|
|
||||||
|
private Method m;
|
||||||
|
private Field f;
|
||||||
|
|
||||||
|
private AccessibleObject ao;
|
||||||
|
|
||||||
|
public MethodField(Object container) {
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodField setField(Field f) {
|
||||||
|
return setMethodField(null, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MethodField setMethod(Method m) {
|
||||||
|
return setMethodField(m, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MethodField setMethodField(Method m, Field f) {
|
||||||
|
if (m == null && f == null)
|
||||||
|
throw new Error("Method and field cannot be null!");
|
||||||
|
this.m = m;
|
||||||
|
if (m != null)
|
||||||
|
ao = m;
|
||||||
|
this.f = f;
|
||||||
|
if (f != null)
|
||||||
|
ao = f;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChild() {
|
||||||
|
return ao.isAnnotationPresent(Child.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return getName(false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName(boolean child, int childDepth) {
|
||||||
|
String name = "";
|
||||||
|
if (ao.isAnnotationPresent(Attribute.class))
|
||||||
|
name = ao.getAnnotation(Attribute.class).name();
|
||||||
|
else if (ao.isAnnotationPresent(Child.class)) {
|
||||||
|
name = ao.getAnnotation(Child.class).name();
|
||||||
|
if (child) {
|
||||||
|
String childName = ao.getAnnotation(Child.class).childName();
|
||||||
|
String[] childrenNames = ao.getAnnotation(Child.class).children();
|
||||||
|
if (childDepth < childrenNames.length)
|
||||||
|
childName = childrenNames[childDepth];
|
||||||
|
|
||||||
|
// if childName isn't set, but children is, then take the last valid child
|
||||||
|
if (childName.isEmpty() && childrenNames.length > 0)
|
||||||
|
childName = childrenNames[childrenNames.length - 1];
|
||||||
|
|
||||||
|
// if the above doesn't exist, then use name but stripS
|
||||||
|
if (childName.isEmpty())
|
||||||
|
name = stripS(name);
|
||||||
|
else
|
||||||
|
name = childName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name.isEmpty())
|
||||||
|
return name;
|
||||||
|
|
||||||
|
if (f != null)
|
||||||
|
name = f.getName();
|
||||||
|
else {
|
||||||
|
name = m.getName();
|
||||||
|
// if there is a leading get, strip it off
|
||||||
|
if (name.toLowerCase().startsWith("get") && name.length() > 3)
|
||||||
|
name = name.substring(3, name.length());
|
||||||
|
}
|
||||||
|
if (child)
|
||||||
|
name = stripS(name);
|
||||||
|
|
||||||
|
// then set it as the field name, replacing _ with :
|
||||||
|
name = name.replace('_', ':');
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String stripS(String name) {
|
||||||
|
String nameLower = name.toLowerCase();
|
||||||
|
if (name.length() < 2 || !nameLower.endsWith("s"))
|
||||||
|
return name;
|
||||||
|
if (name.length() > 3 && nameLower.endsWith("ies"))
|
||||||
|
name = name.substring(0, name.length() - 3) + "y";
|
||||||
|
else
|
||||||
|
name = name.substring(0, name.length() - 1);
|
||||||
|
return name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue() {
|
||||||
|
Object ret = null;
|
||||||
|
try {
|
||||||
|
if (f != null)
|
||||||
|
ret = f.get(container);
|
||||||
|
else
|
||||||
|
ret = m.invoke(container);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAccessible(boolean flag) throws SecurityException {
|
||||||
|
ao.setAccessible(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccessible() {
|
||||||
|
return ao.isAccessible();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
|
||||||
|
return ao.getAnnotation(annotationClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
|
||||||
|
return ao.isAnnotationPresent(annotationClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Annotation[] getAnnotations() {
|
||||||
|
return ao.getAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Annotation[] getDeclaredAnnotations() {
|
||||||
|
return ao.getDeclaredAnnotations();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return ao.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
return ao.equals(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return (f == null ? "method" : "field ") + "(" + (isChild() ? "child) " : "attribute)") + ": " + ao.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
241
src/main/java/org/moparscape/xml/impl/AbstractXmlElement.java
Executable file
241
src/main/java/org/moparscape/xml/impl/AbstractXmlElement.java
Executable file
@ -0,0 +1,241 @@
|
|||||||
|
package org.moparscape.xml.impl;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
|
public abstract class AbstractXmlElement implements XmlElement, XmlElementFactory {
|
||||||
|
|
||||||
|
public static final String implProperty = "xmlElementImpl";
|
||||||
|
|
||||||
|
// provided implementations
|
||||||
|
public static final String XPP3 = "Xpp3";
|
||||||
|
public static final String XPP = "Xpp";
|
||||||
|
public static final String DOM4J = "Dom4j";
|
||||||
|
public static final String XOM = "Xom";
|
||||||
|
public static final String W3C = "W3C";
|
||||||
|
|
||||||
|
public static XmlElementFactory getFactory() {
|
||||||
|
XmlElementFactory ret = null;
|
||||||
|
|
||||||
|
//ret = new org.moparscape.xml.impl.W3CXmlElement();
|
||||||
|
//ret = new org.moparscape.xml.impl.XppXmlElement();
|
||||||
|
//ret = new org.moparscape.xml.impl.Xpp3XmlElement();
|
||||||
|
//ret = new org.moparscape.xml.impl.Dom4jXmlElement();
|
||||||
|
//ret = new org.moparscape.xml.impl.XomXmlElement();
|
||||||
|
final String xmlDocType = System.getProperty(implProperty);
|
||||||
|
//System.out.println("xmlDocType: "+xmlDocType);
|
||||||
|
String implPkgClass = AbstractXmlElement.class.getPackage().getName() + "." + xmlDocType;
|
||||||
|
if (ret == null && xmlDocType != null)
|
||||||
|
ret = objectForName(implPkgClass + "XmlElement", null);
|
||||||
|
if (ret == null && xmlDocType != null)
|
||||||
|
ret = objectForName(implPkgClass, null);
|
||||||
|
if (ret == null && xmlDocType != null)
|
||||||
|
ret = objectForName(xmlDocType, null);
|
||||||
|
// try them in a defined default order
|
||||||
|
if (ret == null) {
|
||||||
|
Class[] xmlDocs = new Class[]{XppXmlElement.class, Xpp3XmlElement.class, Dom4jXmlElement.class, XomXmlElement.class};
|
||||||
|
for (Class xmlDoc : xmlDocs) {
|
||||||
|
ret = objectForName(null, xmlDoc);
|
||||||
|
if (ret != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// as a last resort, W3CXmlElement should ALWAYS be available
|
||||||
|
if (ret == null)
|
||||||
|
ret = new W3CXmlElement();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
private static <E> E objectForName(String name, Class clazz) {
|
||||||
|
try {
|
||||||
|
if (clazz == null)
|
||||||
|
clazz = Class.forName(name);
|
||||||
|
Constructor constructor = null;
|
||||||
|
try {
|
||||||
|
constructor = clazz.getDeclaredConstructor();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// we would only reach here if there is no default no-arg constructor
|
||||||
|
// we must use sun classes to get around this, unfortunately
|
||||||
|
sun.reflect.ReflectionFactory rf = sun.reflect.ReflectionFactory.getReflectionFactory();
|
||||||
|
constructor = rf.newConstructorForSerialization(clazz, Object.class.getDeclaredConstructor(new Class[0]));
|
||||||
|
}
|
||||||
|
if (!constructor.isAccessible())
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
return (E) constructor.newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Error e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String emptyForNull(String ret) {
|
||||||
|
return ret == null ? "" : ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeHeader(OutputStreamWriter osw, boolean newLine) throws IOException {
|
||||||
|
// only write the header if parent is null (top level)
|
||||||
|
if (getParent() != null)
|
||||||
|
return;
|
||||||
|
String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
||||||
|
if (newLine)
|
||||||
|
header += "\n";
|
||||||
|
osw.write(header, 0, header.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final XmlElement[] getChildren() {
|
||||||
|
return getChildren(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToFile(File file) throws Exception {
|
||||||
|
writeToStream(new FileOutputStream(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToFile(String fileName) throws Exception {
|
||||||
|
writeToFile(new File(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
writeToStream(bos);
|
||||||
|
return new String(bos.toByteArray(), "UTF-8");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return new String(bos.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toStringCompact() {
|
||||||
|
// this removes all whitespace between tags
|
||||||
|
String prettyXml = toString().replaceAll(">\\s+<", "><");
|
||||||
|
// now we have to remove all whitespace between attributes
|
||||||
|
StringBuilder compactXml = new StringBuilder(prettyXml.length());
|
||||||
|
boolean inTag = false;
|
||||||
|
boolean inAttribute = false;
|
||||||
|
boolean appendedWhitespace = false;
|
||||||
|
for (int x = 0; x < prettyXml.length(); ++x) {
|
||||||
|
char c = prettyXml.charAt(x);
|
||||||
|
if (c == '<')
|
||||||
|
inTag = true;
|
||||||
|
else if (c == '>')
|
||||||
|
inTag = false;
|
||||||
|
else if (c == '"') {
|
||||||
|
inAttribute = !inAttribute;
|
||||||
|
appendedWhitespace = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inTag && !inAttribute && Character.isWhitespace(c)) {
|
||||||
|
if (appendedWhitespace)
|
||||||
|
continue;
|
||||||
|
appendedWhitespace = true;
|
||||||
|
c = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
compactXml.append(c);
|
||||||
|
}
|
||||||
|
return compactXml.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int byteLength(String s) {
|
||||||
|
try {
|
||||||
|
return s.getBytes("UTF-8").length;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return s.getBytes().length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteLength() {
|
||||||
|
return byteLength(toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int byteLengthCompact() {
|
||||||
|
return byteLength(toStringCompact());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement readFromFile(File file) throws Exception {
|
||||||
|
return readFromStream(new FileInputStream(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement readFromFile(String file) throws Exception {
|
||||||
|
return readFromFile(new File(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement readFromString(String string) throws Exception {
|
||||||
|
return readFromStream(new ByteArrayInputStream(string.getBytes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWrapperFor(Class<?> iface) {
|
||||||
|
return iface != null && iface.isInstance(getInternal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T unwrap(Class<T> iface) {
|
||||||
|
if (!isWrapperFor(iface))
|
||||||
|
return null;
|
||||||
|
return iface.cast(getInternal());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For isWrapperFor and unwrap implementation
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected abstract Object getInternal();
|
||||||
|
|
||||||
|
protected XmlElement[] wrapArray(Object[] os) {
|
||||||
|
XmlElement[] ret = new XmlElement[os.length];
|
||||||
|
for (int x = 0; x < ret.length; ++x)
|
||||||
|
ret[x] = wrapObject(os[x]);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected XmlElement wrapParent(Object parent) {
|
||||||
|
return parent == null ? null : wrapObject(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract XmlElement wrapObject(Object o);
|
||||||
|
|
||||||
|
public XmlElement copyTo(XmlElementFactory factory) throws Exception {
|
||||||
|
if (factory == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return factory.readFromString(this.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** old way, read/write above probably better
|
||||||
|
public XmlElement copyTo(XmlElementFactory factory) {
|
||||||
|
if (factory == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
XmlElement ret = factory.getNewChildXmlElement(this.getName());
|
||||||
|
copyXmlElement(this, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyXmlElement(XmlElement src, XmlElement dst) {
|
||||||
|
// set the value
|
||||||
|
if (src.getValue() != null)
|
||||||
|
dst.setValue(src.getValue());
|
||||||
|
// set all the attributes
|
||||||
|
for (String attName : src.getAttributeNames())
|
||||||
|
dst.setAttribute(attName, src.getAttribute(attName));
|
||||||
|
// recursively set all the children
|
||||||
|
for (XmlElement child : src.getChildren())
|
||||||
|
copyXmlElement(child, dst.getNewChildXmlElement(child.getName()));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
150
src/main/java/org/moparscape/xml/impl/Dom4jXmlElement.java
Executable file
150
src/main/java/org/moparscape/xml/impl/Dom4jXmlElement.java
Executable file
@ -0,0 +1,150 @@
|
|||||||
|
package org.moparscape.xml.impl;
|
||||||
|
|
||||||
|
import org.dom4j.*;
|
||||||
|
import org.dom4j.Document;
|
||||||
|
import org.dom4j.Element;
|
||||||
|
import org.dom4j.io.OutputFormat;
|
||||||
|
import org.dom4j.io.SAXReader;
|
||||||
|
import org.dom4j.io.XMLWriter;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Dom4jXmlElement extends AbstractXmlElement {
|
||||||
|
|
||||||
|
private final Element internal;
|
||||||
|
|
||||||
|
public Dom4jXmlElement() {
|
||||||
|
internal = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dom4jXmlElement(String name, Element parent) {
|
||||||
|
if (parent == null) {
|
||||||
|
Document document = DocumentHelper.createDocument();
|
||||||
|
internal = document.addElement(name);
|
||||||
|
} else
|
||||||
|
internal = parent.addElement(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dom4jXmlElement(Element internal) {
|
||||||
|
this.internal = internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return internal.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return internal.getStringValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAttribute(String name) {
|
||||||
|
Attribute attr = internal.attribute(name);
|
||||||
|
return attr == null ? "" : attr.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getAttributeNames() {
|
||||||
|
String[] ret = new String[internal.attributeCount()];
|
||||||
|
for(int x = 0; x < ret.length; ++x)
|
||||||
|
ret[x] = internal.attribute(x).getQualifiedName();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getParent() {
|
||||||
|
return wrapParent(internal.getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildCount() {
|
||||||
|
return internal.elements().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
public XmlElement[] getChildren(String name){
|
||||||
|
List elements = name == null ? internal.elements() : internal.elements(name);
|
||||||
|
return wrapArray(elements.toArray(new Object[elements.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getChild(String name) {
|
||||||
|
return new Dom4jXmlElement(internal.element(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setAttribute(String name, String value) {
|
||||||
|
if (name.startsWith("xmlns"))
|
||||||
|
try {
|
||||||
|
String prefix = name.split(":")[1];
|
||||||
|
internal.add(new Namespace(prefix, value));
|
||||||
|
} catch (Exception e) {
|
||||||
|
if(name.equals("xmlns"))
|
||||||
|
internal.setQName(QName.get(internal.getName(), value));
|
||||||
|
}
|
||||||
|
internal.addAttribute(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setValue(String value) {
|
||||||
|
internal.setText(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getNewChildXmlElement(String name) {
|
||||||
|
return new Dom4jXmlElement(name, internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement addChild(XmlElement other) {
|
||||||
|
if (other instanceof Dom4jXmlElement) {
|
||||||
|
Dom4jXmlElement o = (Dom4jXmlElement) other;
|
||||||
|
internal.add(o.internal);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement readFromStream(InputStream is) throws Exception {
|
||||||
|
SAXReader reader = new SAXReader();
|
||||||
|
Document doc = reader.read(is);
|
||||||
|
Element root = doc.getRootElement();
|
||||||
|
if(root == null)
|
||||||
|
return null;
|
||||||
|
return new Dom4jXmlElement(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToStream(OutputStream os) throws Exception {
|
||||||
|
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
|
||||||
|
writeHeader(osw, false);
|
||||||
|
|
||||||
|
OutputFormat format = OutputFormat.createPrettyPrint();
|
||||||
|
//format = OutputFormat.createCompactFormat();
|
||||||
|
XMLWriter writer = new XMLWriter(osw, format);
|
||||||
|
writer.write(internal);
|
||||||
|
|
||||||
|
osw.close();
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getInternal() {
|
||||||
|
return this.internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected XmlElement wrapObject(Object internal) {
|
||||||
|
if(internal instanceof Element)
|
||||||
|
return new Dom4jXmlElement((Element)internal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
170
src/main/java/org/moparscape/xml/impl/W3CXmlElement.java
Executable file
170
src/main/java/org/moparscape/xml/impl/W3CXmlElement.java
Executable file
@ -0,0 +1,170 @@
|
|||||||
|
package org.moparscape.xml.impl;
|
||||||
|
|
||||||
|
import org.w3c.dom.*;
|
||||||
|
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.transform.OutputKeys;
|
||||||
|
import javax.xml.transform.Transformer;
|
||||||
|
import javax.xml.transform.TransformerFactory;
|
||||||
|
import javax.xml.transform.dom.DOMSource;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class W3CXmlElement extends AbstractXmlElement {
|
||||||
|
|
||||||
|
private final Element internal;
|
||||||
|
|
||||||
|
public W3CXmlElement(){
|
||||||
|
internal = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public W3CXmlElement(String name, Element parent) {
|
||||||
|
if(parent == null){
|
||||||
|
DocumentBuilder db = null;
|
||||||
|
try{
|
||||||
|
db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if(db == null){
|
||||||
|
internal = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Document doc = db.newDocument();
|
||||||
|
internal = doc.createElement(name);
|
||||||
|
doc.appendChild(internal);
|
||||||
|
}else{
|
||||||
|
internal = parent.getOwnerDocument().createElement(name);
|
||||||
|
parent.appendChild(internal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private W3CXmlElement(Element internal) {
|
||||||
|
this.internal = internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return internal.getNodeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return internal.getTextContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAttribute(String name) {
|
||||||
|
return internal.getAttributes().getNamedItem(name).getNodeValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getAttributeNames() {
|
||||||
|
NamedNodeMap nnm = internal.getAttributes();
|
||||||
|
if(nnm == null)
|
||||||
|
return new String[0];
|
||||||
|
String[] ret = new String[nnm.getLength()];
|
||||||
|
for(int x = 0; x < ret.length; ++x)
|
||||||
|
ret[x] = nnm.item(x).getNodeName();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getParent() {
|
||||||
|
return wrapParent(internal.getParentNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildCount() {
|
||||||
|
return internal.getChildNodes().getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement[] getChildren(String name){
|
||||||
|
NodeList nl = internal.getChildNodes();
|
||||||
|
List<XmlElement> ret = new ArrayList<XmlElement>(nl.getLength());
|
||||||
|
for(int x = 0; x < nl.getLength(); ++x){
|
||||||
|
Node n = nl.item(x);
|
||||||
|
if( n instanceof Element && (name == null || name.equals(n.getNodeName())) )
|
||||||
|
ret.add(new W3CXmlElement((Element)n));
|
||||||
|
}
|
||||||
|
return ret.toArray(new XmlElement[ret.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getChild(String name) {
|
||||||
|
return new W3CXmlElement((Element)internal.getElementsByTagName(name).item(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getNewChildXmlElement(String name) {
|
||||||
|
return new W3CXmlElement(name, this.internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement addChild(XmlElement other) {
|
||||||
|
if (other instanceof W3CXmlElement){
|
||||||
|
W3CXmlElement o = (W3CXmlElement) other;
|
||||||
|
internal.appendChild(o.internal);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setAttribute(String name, String value) {
|
||||||
|
internal.setAttribute(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setValue(String value) {
|
||||||
|
internal.setTextContent(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement readFromStream(InputStream is) throws Exception {
|
||||||
|
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
if(db == null)
|
||||||
|
return null;
|
||||||
|
Document doc = db.parse(is);
|
||||||
|
if(doc == null)
|
||||||
|
return null;
|
||||||
|
return new W3CXmlElement(doc.getDocumentElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToStream(OutputStream os) throws Exception {
|
||||||
|
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
|
||||||
|
|
||||||
|
// Use a Transformer for output
|
||||||
|
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||||
|
|
||||||
|
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, getParent() == null ? "no" : "yes");
|
||||||
|
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
|
||||||
|
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||||
|
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
||||||
|
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
||||||
|
|
||||||
|
transformer.transform(new DOMSource(internal), new StreamResult(osw));
|
||||||
|
|
||||||
|
osw.close();
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getInternal() {
|
||||||
|
return this.internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected XmlElement wrapObject(Object internal) {
|
||||||
|
if(internal instanceof Element)
|
||||||
|
return new W3CXmlElement((Element)internal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
51
src/main/java/org/moparscape/xml/impl/XmlElement.java
Executable file
51
src/main/java/org/moparscape/xml/impl/XmlElement.java
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
package org.moparscape.xml.impl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public interface XmlElement {
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
public String getValue();
|
||||||
|
|
||||||
|
public String getAttribute(String name);
|
||||||
|
|
||||||
|
public String[] getAttributeNames();
|
||||||
|
|
||||||
|
public XmlElement getParent();
|
||||||
|
|
||||||
|
public int getChildCount();
|
||||||
|
|
||||||
|
public XmlElement[] getChildren();
|
||||||
|
|
||||||
|
public XmlElement[] getChildren(String name);
|
||||||
|
|
||||||
|
public XmlElement getChild(String name);
|
||||||
|
|
||||||
|
public XmlElement setAttribute(String name, String value);
|
||||||
|
|
||||||
|
public XmlElement setValue(String value);
|
||||||
|
|
||||||
|
public XmlElement getNewChildXmlElement(String name);
|
||||||
|
|
||||||
|
public XmlElement addChild(XmlElement other);
|
||||||
|
|
||||||
|
public void writeToStream(OutputStream os) throws Exception;
|
||||||
|
|
||||||
|
public void writeToFile(File file) throws Exception;
|
||||||
|
|
||||||
|
public void writeToFile(String fileName) throws Exception;
|
||||||
|
|
||||||
|
public String toString();
|
||||||
|
|
||||||
|
public String toStringCompact();
|
||||||
|
|
||||||
|
public int byteLength();
|
||||||
|
|
||||||
|
public int byteLengthCompact();
|
||||||
|
|
||||||
|
public boolean isWrapperFor(Class<?> iface);
|
||||||
|
public <T> T unwrap(Class<T> iface);
|
||||||
|
|
||||||
|
public XmlElement copyTo(XmlElementFactory factory) throws Exception;
|
||||||
|
}
|
18
src/main/java/org/moparscape/xml/impl/XmlElementFactory.java
Executable file
18
src/main/java/org/moparscape/xml/impl/XmlElementFactory.java
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
package org.moparscape.xml.impl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public interface XmlElementFactory {
|
||||||
|
|
||||||
|
public XmlElement getNewChildXmlElement(String name);
|
||||||
|
|
||||||
|
public XmlElement readFromStream(InputStream is) throws Exception;
|
||||||
|
|
||||||
|
public XmlElement readFromFile(File file) throws Exception;
|
||||||
|
|
||||||
|
public XmlElement readFromFile(String file) throws Exception;
|
||||||
|
|
||||||
|
public XmlElement readFromString(String string) throws Exception;
|
||||||
|
|
||||||
|
}
|
192
src/main/java/org/moparscape/xml/impl/XomXmlElement.java
Executable file
192
src/main/java/org/moparscape/xml/impl/XomXmlElement.java
Executable file
@ -0,0 +1,192 @@
|
|||||||
|
package org.moparscape.xml.impl;
|
||||||
|
|
||||||
|
import nu.xom.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class XomXmlElement extends AbstractXmlElement {
|
||||||
|
|
||||||
|
private final Element internal;
|
||||||
|
|
||||||
|
public XomXmlElement() {
|
||||||
|
internal = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XomXmlElement(Element internal) {
|
||||||
|
this.internal = internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private XomXmlElement(String name, Element parent) {
|
||||||
|
internal = new Element(name);
|
||||||
|
if (parent == null)
|
||||||
|
return;
|
||||||
|
String nameSpaceUri = parent.getNamespaceURI();
|
||||||
|
if (nameSpaceUri != null)
|
||||||
|
internal.setNamespaceURI(nameSpaceUri);
|
||||||
|
parent.appendChild(internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return internal.getQualifiedName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return internal.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAttribute(String name) {
|
||||||
|
// Xom doesn't allow xmlns(:.*)? to be attributes, but we want them to be, so implement that here
|
||||||
|
if (name.equals("xmlns"))
|
||||||
|
return emptyForNull(internal.getNamespaceURI());
|
||||||
|
String nameSpaceStart = "xmlns:";
|
||||||
|
if (name.startsWith(nameSpaceStart) && name.length() > nameSpaceStart.length()) {
|
||||||
|
return emptyForNull(internal.getNamespaceURI(name.split(":")[1]));
|
||||||
|
}
|
||||||
|
// otherwise it's a regular attribute
|
||||||
|
Attribute attr = internal.getAttribute(name);
|
||||||
|
return attr == null ? null : attr.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getAttributeNames() {
|
||||||
|
String[] ret = new String[internal.getAttributeCount()+internal.getNamespaceDeclarationCount()];
|
||||||
|
int x = 0;
|
||||||
|
for(; x < internal.getAttributeCount(); ++x)
|
||||||
|
ret[x] = internal.getAttribute(x).getQualifiedName();
|
||||||
|
// special handling for xmlns, again...
|
||||||
|
for(int y = 0; y < internal.getNamespaceDeclarationCount(); ++y){
|
||||||
|
String name = internal.getNamespacePrefix(y);
|
||||||
|
name = name.isEmpty() ? "xmlns" : ("xmlns:"+name);
|
||||||
|
ret[x++] = name;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getParent() {
|
||||||
|
return wrapParent(internal.getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildCount() {
|
||||||
|
return internal.getChildCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement[] getChildren(String name){
|
||||||
|
Elements nl = internal.getChildElements();
|
||||||
|
List<XmlElement> ret = new ArrayList<XmlElement>(nl.size());
|
||||||
|
for(int x = 0; x < nl.size(); ++x){
|
||||||
|
Element n = nl.get(x);
|
||||||
|
if(name == null || name.equals(n.getQualifiedName()))
|
||||||
|
ret.add(new XomXmlElement(n));
|
||||||
|
}
|
||||||
|
return ret.toArray(new XmlElement[ret.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getChild(String name) {
|
||||||
|
if(name == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
//Element child = internal.getFirstChildElement(name, internal.getNamespaceURI());
|
||||||
|
//return child == null ? null : new XomXmlElement(child);
|
||||||
|
|
||||||
|
// in order to avoid namespace issues, we need to call getChildElements and find them ourselves...
|
||||||
|
Elements elements = internal.getChildElements();
|
||||||
|
for(int x = 0; x < elements.size(); ++x){
|
||||||
|
Element element = elements.get(x);
|
||||||
|
if(name.equals(element.getQualifiedName()))
|
||||||
|
return new XomXmlElement(element);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setAttribute(String name, String value) {
|
||||||
|
if (name.startsWith("xmlns"))
|
||||||
|
try {
|
||||||
|
String prefix = name.split(":")[1];
|
||||||
|
internal.addNamespaceDeclaration(prefix, value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (name.equals("xmlns"))
|
||||||
|
internal.setNamespaceURI(value);
|
||||||
|
else
|
||||||
|
internal.addAttribute(new Attribute(name, value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
internal.addAttribute(new Attribute(name, value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setValue(String value) {
|
||||||
|
internal.appendChild(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getNewChildXmlElement(String name) {
|
||||||
|
return new XomXmlElement(name, internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement addChild(XmlElement other) {
|
||||||
|
if (other instanceof XomXmlElement) {
|
||||||
|
XomXmlElement o = (XomXmlElement) other;
|
||||||
|
internal.appendChild(o.internal);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement readFromStream(InputStream is) throws Exception {
|
||||||
|
Builder parser = new Builder();
|
||||||
|
Document doc = parser.build(is);
|
||||||
|
if(doc == null)
|
||||||
|
return null;
|
||||||
|
return new XomXmlElement(doc.getRootElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToStream(OutputStream os) throws Exception {
|
||||||
|
final Serializer serializer;
|
||||||
|
Element toWrite = internal;
|
||||||
|
if(internal.getParent() != null){
|
||||||
|
// then we already have a parent, so can't create a new document, so print a copy of this object
|
||||||
|
toWrite = new Element(toWrite);
|
||||||
|
serializer = new Serializer(os, "UTF-8"){
|
||||||
|
@Override
|
||||||
|
protected void writeXMLDeclaration() throws IOException {
|
||||||
|
// we don't want this for a child
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}else
|
||||||
|
serializer = new Serializer(os, "UTF-8");
|
||||||
|
|
||||||
|
serializer.setIndent(2);
|
||||||
|
//serializer.setMaxLength(64); // line length
|
||||||
|
serializer.write(new Document(toWrite));
|
||||||
|
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getInternal() {
|
||||||
|
return this.internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected XmlElement wrapObject(Object internal) {
|
||||||
|
if(internal instanceof Element)
|
||||||
|
return new XomXmlElement((Element)internal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
119
src/main/java/org/moparscape/xml/impl/Xpp3XmlElement.java
Executable file
119
src/main/java/org/moparscape/xml/impl/Xpp3XmlElement.java
Executable file
@ -0,0 +1,119 @@
|
|||||||
|
package org.moparscape.xml.impl;
|
||||||
|
|
||||||
|
import org.codehaus.plexus.util.xml.XmlStreamReader;
|
||||||
|
import org.codehaus.plexus.util.xml.Xpp3Dom;
|
||||||
|
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
|
||||||
|
import org.codehaus.plexus.util.xml.Xpp3DomWriter;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class Xpp3XmlElement extends AbstractXmlElement {
|
||||||
|
|
||||||
|
private final Xpp3Dom internal;
|
||||||
|
|
||||||
|
public Xpp3XmlElement() {
|
||||||
|
internal = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Xpp3XmlElement(String name, Xpp3Dom parent) {
|
||||||
|
internal = new Xpp3Dom(name);
|
||||||
|
if(parent != null)
|
||||||
|
parent.addChild(internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Xpp3XmlElement(Xpp3Dom internal) {
|
||||||
|
this.internal = internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return internal.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return internal.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAttribute(String name) {
|
||||||
|
return internal.getAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getAttributeNames() {
|
||||||
|
return internal.getAttributeNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getParent() {
|
||||||
|
return wrapParent(internal.getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildCount() {
|
||||||
|
return internal.getChildCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement[] getChildren(String name){
|
||||||
|
return wrapArray(name == null ? internal.getChildren() : internal.getChildren(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getChild(String name) {
|
||||||
|
return new Xpp3XmlElement(internal.getChild(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getNewChildXmlElement(String name){
|
||||||
|
return new Xpp3XmlElement(name, internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement addChild(XmlElement other) {
|
||||||
|
if (other instanceof Xpp3XmlElement)
|
||||||
|
internal.addChild(((Xpp3XmlElement) other).internal);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setAttribute(String name, String value) {
|
||||||
|
internal.setAttribute(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setValue(String value) {
|
||||||
|
internal.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement readFromStream(InputStream is) throws Exception {
|
||||||
|
return new Xpp3XmlElement(Xpp3DomBuilder.build(new XmlStreamReader(is)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToStream(OutputStream os) throws IOException {
|
||||||
|
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
|
||||||
|
writeHeader(osw, true);
|
||||||
|
|
||||||
|
Xpp3DomWriter.write(osw, internal);
|
||||||
|
osw.close();
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getInternal() {
|
||||||
|
return this.internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected XmlElement wrapObject(Object internal) {
|
||||||
|
if(internal instanceof Xpp3Dom)
|
||||||
|
return new Xpp3XmlElement((Xpp3Dom)internal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
119
src/main/java/org/moparscape/xml/impl/XppXmlElement.java
Executable file
119
src/main/java/org/moparscape/xml/impl/XppXmlElement.java
Executable file
@ -0,0 +1,119 @@
|
|||||||
|
package org.moparscape.xml.impl;
|
||||||
|
|
||||||
|
import com.thoughtworks.xstream.io.copy.HierarchicalStreamCopier;
|
||||||
|
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
|
||||||
|
import com.thoughtworks.xstream.io.xml.XppDomReader;
|
||||||
|
import com.thoughtworks.xstream.io.xml.xppdom.XppDom;
|
||||||
|
import com.thoughtworks.xstream.io.xml.xppdom.XppFactory;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class XppXmlElement extends AbstractXmlElement {
|
||||||
|
|
||||||
|
private final XppDom internal;
|
||||||
|
|
||||||
|
public XppXmlElement() {
|
||||||
|
internal = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XppXmlElement(String name, XppDom parent) {
|
||||||
|
internal = new XppDom(name);
|
||||||
|
if(parent != null)
|
||||||
|
parent.addChild(internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private XppXmlElement(XppDom internal) {
|
||||||
|
this.internal = internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return internal.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return internal.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAttribute(String name) {
|
||||||
|
return internal.getAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getAttributeNames() {
|
||||||
|
return internal.getAttributeNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getParent() {
|
||||||
|
return wrapParent(internal.getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildCount() {
|
||||||
|
return internal.getChildCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement[] getChildren(String name){
|
||||||
|
return wrapArray(name == null ? internal.getChildren() : internal.getChildren(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getChild(String name) {
|
||||||
|
return new XppXmlElement(internal.getChild(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement getNewChildXmlElement(String name){
|
||||||
|
return new XppXmlElement(name, this.internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement addChild(XmlElement other) {
|
||||||
|
if (other instanceof XppXmlElement)
|
||||||
|
internal.addChild(((XppXmlElement) other).internal);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setAttribute(String name, String value) {
|
||||||
|
internal.setAttribute(name, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement setValue(String value) {
|
||||||
|
internal.setValue(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlElement readFromStream(InputStream is) throws Exception {
|
||||||
|
return new XppXmlElement(XppFactory.buildDom(is, "UTF-8")); // guess at encoding...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToStream(OutputStream os) throws IOException {
|
||||||
|
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
|
||||||
|
writeHeader(osw, true);
|
||||||
|
|
||||||
|
new HierarchicalStreamCopier().copy(new XppDomReader(internal), new PrettyPrintWriter(osw));
|
||||||
|
osw.close();
|
||||||
|
os.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getInternal() {
|
||||||
|
return this.internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected XmlElement wrapObject(Object internal) {
|
||||||
|
if(internal instanceof XppDom)
|
||||||
|
return new XppXmlElement((XppDom)internal);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user