practicalxml-commits Mailing List for Practical XML (Page 8)
Brought to you by:
kdgregory
You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(6) |
Nov
(4) |
Dec
(35) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(5) |
Feb
|
Mar
|
Apr
(7) |
May
|
Jun
|
Jul
(12) |
Aug
(24) |
Sep
(39) |
Oct
(16) |
Nov
(4) |
Dec
(7) |
2010 |
Jan
(10) |
Feb
|
Mar
(2) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
(4) |
Dec
(3) |
2011 |
Jan
(1) |
Feb
|
Mar
(1) |
Apr
(1) |
May
(3) |
Jun
|
Jul
|
Aug
(1) |
Sep
(10) |
Oct
(1) |
Nov
(1) |
Dec
(7) |
2012 |
Jan
(1) |
Feb
|
Mar
|
Apr
(1) |
May
(9) |
Jun
|
Jul
(5) |
Aug
(6) |
Sep
|
Oct
(1) |
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(16) |
Jul
|
Aug
(6) |
Sep
(10) |
Oct
|
Nov
(2) |
Dec
|
2014 |
Jan
(5) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
(6) |
Nov
|
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(5) |
2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-16 21:31:11
|
Revision: 135 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=135&view=rev Author: kdgregory Date: 2009-09-16 21:31:05 +0000 (Wed, 16 Sep 2009) Log Message: ----------- fix invalid @returns JavaDoc directive Modified Paths: -------------- trunk/src/main/java/net/sf/practicalxml/XmlUtil.java Modified: trunk/src/main/java/net/sf/practicalxml/XmlUtil.java =================================================================== --- trunk/src/main/java/net/sf/practicalxml/XmlUtil.java 2009-09-16 21:29:12 UTC (rev 134) +++ trunk/src/main/java/net/sf/practicalxml/XmlUtil.java 2009-09-16 21:31:05 UTC (rev 135) @@ -47,8 +47,8 @@ * the BMP, you probably don't have ASCII control characters in your * text, and don't need this method at all. * - * @returns true if this string does <em>not</em> contain any illegal - * characters. + * @return true if this string does <em>not</em> contain any illegal + * characters. */ public static boolean isLegal(String s) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-16 21:29:23
|
Revision: 134 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=134&view=rev Author: kdgregory Date: 2009-09-16 21:29:12 +0000 (Wed, 16 Sep 2009) Log Message: ----------- DomUtil: getChildren(), getChild(), trimTextRecursive(), and removeEmptyTextRecursive() now take any Node (so you can pass Document as well as Element) Modified Paths: -------------- trunk/src/main/java/net/sf/practicalxml/DomUtil.java trunk/src/site/changes.xml trunk/src/test/java/net/sf/practicalxml/TestDomUtil.java Modified: trunk/src/main/java/net/sf/practicalxml/DomUtil.java =================================================================== --- trunk/src/main/java/net/sf/practicalxml/DomUtil.java 2009-09-16 20:46:30 UTC (rev 133) +++ trunk/src/main/java/net/sf/practicalxml/DomUtil.java 2009-09-16 21:29:12 UTC (rev 134) @@ -29,6 +29,7 @@ import org.w3c.dom.Text; import net.sf.practicalxml.internal.StringUtils; +import net.sf.practicalxml.util.NodeListIterator; import net.sf.practicalxml.xpath.NamespaceResolver; @@ -193,10 +194,11 @@ /** - * Returns all <code>Element</code> children of the passed element, in - * document order. + * Returns all <code>Element</code> children of the passed node, in + * document order. Will accept any node type, although only <code>Document + * </code> and <code>Element</code> make sense. */ - public static List<Element> getChildren(Element parent) + public static List<Element> getChildren(Node parent) { return filter(parent.getChildNodes(), Element.class); } @@ -209,7 +211,7 @@ * Returns the children in document order. Returns an empty list if * there are no children matching the specified namespace/name. */ - public static List<Element> getChildren(Element parent, String lclName) + public static List<Element> getChildren(Node parent, String lclName) { List<Element> ret = getChildren(parent); Iterator<Element> itx = ret.iterator(); @@ -231,7 +233,7 @@ * Returns the children in document order. Returns an empty list if * there are no children matching the specified namespace/name. */ - public static List<Element> getChildren(Element parent, String nsUri, String lclName) + public static List<Element> getChildren(Node parent, String nsUri, String lclName) { List<Element> ret = getChildren(parent); Iterator<Element> itx = ret.iterator(); @@ -249,7 +251,7 @@ * Returns the first child element with the given <em>localname</em>, * null if there are no such nodes. */ - public static Element getChild(Element parent, String lclName) + public static Element getChild(Node parent, String lclName) { List<Element> children = getChildren(parent, lclName); return (children.size() > 0) ? children.get(0) : null; @@ -260,7 +262,7 @@ * Returns the first child element with the given namespace and * local name, null if there are no such elements. */ - public static Element getChild(Element parent, String nsUri, String lclName) + public static Element getChild(Node parent, String nsUri, String lclName) { List<Element> children = getChildren(parent, nsUri, lclName); return (children.size() > 0) ? children.get(0) : null; @@ -346,12 +348,12 @@ * Removes leading and trailing whitespace from all descendent text * nodes. Will remove text nodes that trim to an empty string. */ - public static void trimTextRecursive(Element elem) + public static void trimTextRecursive(Node node) { - NodeList children = elem.getChildNodes(); - for (int ii = children.getLength() - 1 ; ii >= 0 ; ii--) + Iterator<Node> itx = new NodeListIterator(node.getChildNodes()); + while (itx.hasNext()) { - Node child = children.item(ii); + Node child = itx.next(); switch (child.getNodeType()) { case Node.ELEMENT_NODE : @@ -361,7 +363,7 @@ case Node.TEXT_NODE : String value = StringUtils.trimToEmpty(((Text)child).getData()); if (StringUtils.isEmpty(value)) - elem.removeChild(child); + itx.remove(); else ((Text)child).setData(value); break; @@ -378,12 +380,12 @@ * could be removed by by the parser if you had a DTD that specified * element-only content. */ - public static void removeEmptyTextRecursive(Element elem) + public static void removeEmptyTextRecursive(Node node) { - NodeList children = elem.getChildNodes(); - for (int ii = children.getLength() - 1 ; ii >= 0 ; ii--) + Iterator<Node> itx = new NodeListIterator(node.getChildNodes()); + while (itx.hasNext()) { - Node child = children.item(ii); + Node child = itx.next(); switch (child.getNodeType()) { case Node.ELEMENT_NODE : @@ -392,7 +394,7 @@ case Node.CDATA_SECTION_NODE : case Node.TEXT_NODE : if (StringUtils.isBlank(child.getNodeValue())) - elem.removeChild(child); + itx.remove(); break; default : // do nothing Modified: trunk/src/site/changes.xml =================================================================== --- trunk/src/site/changes.xml 2009-09-16 20:46:30 UTC (rev 133) +++ trunk/src/site/changes.xml 2009-09-16 21:29:12 UTC (rev 134) @@ -11,11 +11,16 @@ initial context </action> <action dev='kdgregory' type='add'> - DomUtil: Add filter(NodeList) + DomUtil: Add filter() </action> <action dev='kdgregory' type='update'> DomUtil: appendText() now returns the created node </action> + <action dev='kdgregory' type='update'> + DomUtil: getChildren(), getChild(), trimTextRecursive(), + and removeEmptyTextRecursive() now take any Node (so you + can pass Document as well as Element) + </action> </release> <release version="1.0.4" date="2009-09-10" Modified: trunk/src/test/java/net/sf/practicalxml/TestDomUtil.java =================================================================== --- trunk/src/test/java/net/sf/practicalxml/TestDomUtil.java 2009-09-16 20:46:30 UTC (rev 133) +++ trunk/src/test/java/net/sf/practicalxml/TestDomUtil.java 2009-09-16 21:29:12 UTC (rev 134) @@ -162,7 +162,7 @@ } - public void testGetChildren() throws Exception + public void testGetChildrenOfElement() throws Exception { Element root = DomUtil.newDocument("foo"); DomUtil.appendText(root, "bar"); @@ -197,6 +197,62 @@ } + + public void testGetChildrenOfDocument() throws Exception + { + Element root1 = DomUtil.newDocument("foo"); + Document dom1 = root1.getOwnerDocument(); + + assertSame(root1, DomUtil.getChild(dom1, "foo")); + assertNull(DomUtil.getChild(dom1, "bar")); + + List<Element> rslt1a = DomUtil.getChildren(dom1); + assertEquals(1, rslt1a.size()); + assertSame(root1, rslt1a.get(0)); + + List<Element> rslt1b = DomUtil.getChildren(dom1, "foo"); + assertEquals(1, rslt1b.size()); + assertSame(root1, rslt1b.get(0)); + + List<Element> rslt1c = DomUtil.getChildren(dom1, "bar"); + assertEquals(0, rslt1c.size()); + + // and now with namespaces + + Element root2 = DomUtil.newDocument("urn:bar", "foo"); + Document dom2 = root2.getOwnerDocument(); + + assertSame(root2, DomUtil.getChild(dom2, "urn:bar", "foo")); + assertNull(DomUtil.getChild(dom2, "urn:bar", "bar")); + + List<Element> rslt2a = DomUtil.getChildren(dom2); + assertEquals(1, rslt2a.size()); + assertSame(root2, rslt2a.get(0)); + + List<Element> rslt2b = DomUtil.getChildren(dom2, "urn:bar", "foo"); + assertEquals(1, rslt2b.size()); + assertSame(root2, rslt2b.get(0)); + + List<Element> rslt2c = DomUtil.getChildren(dom2, "urn:bar", "bar"); + assertEquals(0, rslt2c.size()); + + List<Element> rslt2d = DomUtil.getChildren(dom2, "bar"); + assertEquals(0, rslt2d.size()); + } + + + // ensure that we don't throw if we pass something dumb + public void testGetChildrenOfComment() throws Exception + { + Element root = DomUtil.newDocument("foo"); + Comment comment = root.getOwnerDocument().createComment("blah blah blah"); + root.appendChild(comment); + + List<Element> result = DomUtil.getChildren(comment); + assertEquals(0, result.size()); + } + + public void testAppendText() throws Exception { Element root = DomUtil.newDocument("root"); @@ -284,7 +340,7 @@ assertEquals(TEXT1, child1.getTextContent()); assertEquals(TEXT2_WS, child2.getTextContent()); - DomUtil.trimTextRecursive(root); + DomUtil.trimTextRecursive(root.getOwnerDocument()); assertEquals(TEXT1, child1.getTextContent()); assertEquals("", child2.getTextContent()); assertEquals(0, child2.getChildNodes().getLength()); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-16 20:46:44
|
Revision: 133 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=133&view=rev Author: kdgregory Date: 2009-09-16 20:46:30 +0000 (Wed, 16 Sep 2009) Log Message: ----------- DomUtil: - added filter(), use it internally - appendText() now returns the created node Modified Paths: -------------- trunk/src/main/java/net/sf/practicalxml/DomUtil.java trunk/src/site/changes.xml trunk/src/test/java/net/sf/practicalxml/TestDomUtil.java Modified: trunk/src/main/java/net/sf/practicalxml/DomUtil.java =================================================================== --- trunk/src/main/java/net/sf/practicalxml/DomUtil.java 2009-09-15 18:37:09 UTC (rev 132) +++ trunk/src/main/java/net/sf/practicalxml/DomUtil.java 2009-09-16 20:46:30 UTC (rev 133) @@ -15,6 +15,7 @@ package net.sf.practicalxml; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilder; @@ -197,17 +198,7 @@ */ public static List<Element> getChildren(Element parent) { - List<Element> ret = new ArrayList<Element>(); - NodeList children = parent.getChildNodes(); - for (int ii = 0 ; ii < children.getLength() ; ii++) - { - Node child = children.item(ii); - if (child instanceof Element) - { - ret.add((Element)child); - } - } - return ret; + return filter(parent.getChildNodes(), Element.class); } @@ -216,45 +207,39 @@ * <em>localname</em>, ignoring namespace. * <p> * Returns the children in document order. Returns an empty list if - * there are no children matching the specified name. + * there are no children matching the specified namespace/name. */ public static List<Element> getChildren(Element parent, String lclName) { - List<Element> ret = new ArrayList<Element>(); - NodeList children = parent.getChildNodes(); - for (int ii = 0 ; ii < children.getLength() ; ii++) + List<Element> ret = getChildren(parent); + Iterator<Element> itx = ret.iterator(); + while (itx.hasNext()) { - Node child = children.item(ii); - if ((child instanceof Element) - && (lclName.equals(getLocalName((Element)child)))) - { - ret.add((Element)child); - } + Element child = itx.next(); + if (!lclName.equals(getLocalName((Element)child))) + itx.remove(); } return ret; } /** - * Returns the children of the passed element that have the given - * namespace and <em>localname</em> (ignoring prefix). Namespace may - * be <code>null</code>, in which case the child element must not - * have a namespace. + * Returns the children of the passed element that have the given namespace + * and localname (ignoring prefix). Namespace may be <code>null</code>, in + * which case the child element must not have a namespace. * <p> * Returns the children in document order. Returns an empty list if * there are no children matching the specified namespace/name. */ public static List<Element> getChildren(Element parent, String nsUri, String lclName) { - List<Element> ret = new ArrayList<Element>(); - NodeList children = parent.getChildNodes(); - for (int ii = 0 ; ii < children.getLength() ; ii++) + List<Element> ret = getChildren(parent); + Iterator<Element> itx = ret.iterator(); + while (itx.hasNext()) { - Node child = children.item(ii); - if ((child instanceof Element) && isNamed((Element)child, nsUri, lclName)) - { - ret.add((Element)child); - } + Element child = itx.next(); + if (!isNamed(child, nsUri, lclName)) + itx.remove(); } return ret; } @@ -283,13 +268,13 @@ /** - * Returns text that is an immediate child of this node. This is - * unlike <code>Node.getTextContent()</code>, which returns all - * descendent text for the element. + * Returns the concatenation of all text and CDATA nodes that are immediate + * children of the passed node. If there are no text/CDATA nodes, returns + * <code>null</code>. * <p> - * Concatenates all text and CDATA nodes, does not trim whitespace. - * If there are no text nodes, returns <code>null</code>; if all - * text nodes contain empty strings, returns an empty string. + * This method differs from <code>Node.getTextContent()</code> in two ways: + * the latter concatenates all descendent text nodes, and will return an + * empty string (rather than <code>null</code>) if there are none. */ public static String getText(Element elem) { @@ -309,7 +294,6 @@ break; default : // do nothing - } } @@ -321,10 +305,11 @@ * Appends the specified text as a new text node on the specified * element. */ - public static void appendText(Element elem, String text) + public static Text appendText(Element elem, String text) { Text child = elem.getOwnerDocument().createTextNode(text); elem.appendChild(child); + return child; } @@ -453,7 +438,7 @@ /** - * Creates a paramaterized list from a <code>NodeList</code>, making it + * Creates a parameterized list from a <code>NodeList</code>, making it * usable within the Java coding idiom. * * @param nodelist The list of nodes to convert. @@ -475,6 +460,26 @@ /** + * Extracts all nodes of a given type from the passed NodeList, creating + * a Java list of the nodes in document order. + * + * @param list The source list, which may contain any node type. + * @param klass The desired node type to extract from this list. + */ + public static <T> List<T> filter(NodeList list, Class<T> klass) + { + ArrayList<T> result = new ArrayList<T>(); + for (int ii = 0 ; ii < list.getLength() ; ii++) + { + Node node = list.item(ii); + if (klass.isInstance(node)) + result.add(klass.cast(node)); + } + return result; + } + + + /** * Returns the path from the root of the document to the specified * element, consisting of each node's qualified name, separated by * slashes. Accepts an arbitrary number of attribute names, and Modified: trunk/src/site/changes.xml =================================================================== --- trunk/src/site/changes.xml 2009-09-15 18:37:09 UTC (rev 132) +++ trunk/src/site/changes.xml 2009-09-16 20:46:30 UTC (rev 133) @@ -5,11 +5,17 @@ <body> <release version="1.0.5" date="2009-09-15" - description="DomAsserts"> + description="DomAsserts, DomUtil"> <action dev='kdgregory' type='update'> DomAsserts: XPath assertions now take any node as initial context </action> + <action dev='kdgregory' type='add'> + DomUtil: Add filter(NodeList) + </action> + <action dev='kdgregory' type='update'> + DomUtil: appendText() now returns the created node + </action> </release> <release version="1.0.4" date="2009-09-10" Modified: trunk/src/test/java/net/sf/practicalxml/TestDomUtil.java =================================================================== --- trunk/src/test/java/net/sf/practicalxml/TestDomUtil.java 2009-09-15 18:37:09 UTC (rev 132) +++ trunk/src/test/java/net/sf/practicalxml/TestDomUtil.java 2009-09-16 20:46:30 UTC (rev 133) @@ -16,8 +16,11 @@ import java.util.List; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NodeList; import org.w3c.dom.Text; @@ -107,33 +110,6 @@ } - public void testGetSetAppendText() throws Exception - { - String t1 = "argle"; - String t2 = "bargle"; - String t3 = "wargle"; - - Element root = DomUtil.newDocument("foo"); - assertNull(DomUtil.getText(root)); - - DomUtil.setText(root, t1); - assertEquals(t1, DomUtil.getText(root)); - - DomUtil.appendText(root, t2); - assertEquals(t1 + t2, DomUtil.getText(root)); - - DomUtil.setText(root, t3); - assertEquals(t3, DomUtil.getText(root)); - - Element child = DomUtil.appendChildInheritNamespace(root, "bar"); - assertNull(DomUtil.getText(child)); - - DomUtil.appendText(child, t1); - assertEquals(t1, DomUtil.getText(child)); - assertEquals(t3, DomUtil.getText(root)); - } - - public void testGetLocalName() throws Exception { Element root = DomUtil.newDocument("foo"); @@ -221,39 +197,70 @@ } + public void testAppendText() throws Exception + { + Element root = DomUtil.newDocument("root"); + Text text = DomUtil.appendText(root, "blah blah"); + assertSame(text, root.getChildNodes().item(0)); + } + + public void testGetText() throws Exception { + String t1 = "argle"; + String t2 = "bargle"; + String t3 = "wargle"; + Element root = DomUtil.newDocument("foo"); - Text rootText1 = root.getOwnerDocument().createTextNode("argle"); - root.appendChild(rootText1); - Element child = root.getOwnerDocument().createElement("bargle"); - root.appendChild(child); - Text rootText2 = root.getOwnerDocument().createTextNode("wargle"); - root.appendChild(rootText2); - Text childText = root.getOwnerDocument().createTextNode("zippy"); - child.appendChild(childText); + assertNull(DomUtil.getText(root)); - assertEquals("arglewargle", DomUtil.getText(root)); + DomUtil.appendText(root, t1); + DomUtil.appendText(root, t2); + assertEquals(t1 + t2, DomUtil.getText(root)); + + Element child = DomUtil.appendChild(root, "bar"); + DomUtil.appendText(child, t3); + assertEquals(t1 + t2 + t3, root.getTextContent()); + assertEquals(t1 + t2, DomUtil.getText(root)); + assertEquals(t3, DomUtil.getText(child)); } + // this test is just here for coverage + public void testGetSetTextWithCData() throws Exception + { + String t1 = "argle"; + String t2 = "bargle"; + + Element root = DomUtil.newDocument("root"); + Document dom = root.getOwnerDocument(); + CDATASection cdata = dom.createCDATASection(t1); + root.appendChild(cdata); + + assertEquals(t1, DomUtil.getText(root)); + assertEquals(t1, root.getTextContent()); + + DomUtil.setText(root, t2); + assertEquals(t2, DomUtil.getText(root)); + assertEquals(t2, root.getTextContent()); + } + + public void testSetText() throws Exception { + String t1 = "argle"; + String t2 = "bargle"; + String t3 = "wargle"; + Element root = DomUtil.newDocument("foo"); - Text rootText1 = root.getOwnerDocument().createTextNode("argle"); - root.appendChild(rootText1); - Element child = root.getOwnerDocument().createElement("bargle"); - root.appendChild(child); - Text rootText2 = root.getOwnerDocument().createTextNode("wargle"); - root.appendChild(rootText2); - Text childText = root.getOwnerDocument().createTextNode("zippy"); - child.appendChild(childText); + Element child = DomUtil.appendChild(root, "bar"); + DomUtil.appendText(root, t1); + DomUtil.appendText(child, t2); - DomUtil.setText(root, "bar"); - assertEquals(2, root.getChildNodes().getLength()); - assertSame(child, root.getChildNodes().item(0)); - assertEquals("bar", root.getChildNodes().item(1).getTextContent()); - assertEquals("zippy", child.getTextContent()); + DomUtil.setText(root, t3); + assertEquals(t3, DomUtil.getText(root)); + assertEquals(t2, DomUtil.getText(child)); + assertEquals(t2 + t3, root.getTextContent()); } @@ -337,4 +344,40 @@ assertSame(child1, result.get(0)); assertSame(child2, result.get(1)); } + + + public void testFilterNodeList() throws Exception + { + Element root = DomUtil.newDocument("foo"); + Document dom = root.getOwnerDocument(); + Text child1 = dom.createTextNode("argle"); + root.appendChild(child1); + Element child2 = dom.createElement("bar"); + root.appendChild(child2); + Comment child3 = dom.createComment("blah blah blah"); + root.appendChild(child3); + Text child4 = dom.createTextNode("wargle"); + root.appendChild(child4); + Element child5 = dom.createElement("baz"); + root.appendChild(child5); + NodeList list = root.getChildNodes(); + + List<Element> elems = DomUtil.filter(list, Element.class); + assertEquals(2, elems.size()); + assertSame(child2, elems.get(0)); + assertSame(child5, elems.get(1)); + + List<Text> texts = DomUtil.filter(list, Text.class); + assertEquals(2, texts.size()); + assertSame(child1, texts.get(0)); + assertSame(child4, texts.get(1)); + + List<Comment> comments = DomUtil.filter(list, Comment.class); + assertEquals(1, comments.size()); + assertSame(child3, comments.get(0)); + + List<Document> docs = DomUtil.filter(list, Document.class); + assertEquals(0, docs.size()); + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-15 18:37:16
|
Revision: 132 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=132&view=rev Author: kdgregory Date: 2009-09-15 18:37:09 +0000 (Tue, 15 Sep 2009) Log Message: ----------- add changelog report Modified Paths: -------------- trunk/pom.xml Added Paths: ----------- trunk/src/site/changes.xml Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2009-09-15 00:56:23 UTC (rev 131) +++ trunk/pom.xml 2009-09-15 18:37:09 UTC (rev 132) @@ -82,11 +82,13 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <configuration> - <bottom> - <a href="http://sourceforge.net/projects/practicalxml/"> - <img src="http://sflogo.sourceforge.net/sflogo.php?group_id=234884&type=3"> + <bottom> + <a + href="http://sourceforge.net/projects/practicalxml/"> + <img + src="http://sflogo.sourceforge.net/sflogo.php?group_id=234884&type=3"> </a> - </bottom> + </bottom> </configuration> </plugin> <plugin> @@ -117,6 +119,20 @@ </executions> </configuration> </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-changes-plugin</artifactId> + <configuration> + <xmlPath>${basedir}/src/site/changes.xml</xmlPath> + </configuration> + <reportSets> + <reportSet> + <reports> + <report>changes-report</report> + </reports> + </reportSet> + </reportSets> + </plugin> </plugins> </reporting> Added: trunk/src/site/changes.xml =================================================================== --- trunk/src/site/changes.xml (rev 0) +++ trunk/src/site/changes.xml 2009-09-15 18:37:09 UTC (rev 132) @@ -0,0 +1,49 @@ +<document xmlns="http://maven.apache.org/changes/1.0.0"> + <properties> + <title>PracticalXML Change Log</title> + </properties> + + <body> + <release version="1.0.5" date="2009-09-15" + description="DomAsserts"> + <action dev='kdgregory' type='update'> + DomAsserts: XPath assertions now take any node as + initial context + </action> + </release> + + <release version="1.0.4" date="2009-09-10" + description="NodeListIterator"> + <action dev='kdgregory' type='add'> + NodeListIterator: wrapper for a NodeList that provides + full iterator functionality + </action> + </release> + + <release version="1.0.3" date="2009-07-14" description="XmlUtil"> + <action dev='kdgregory' type='add'> + XmlUtil: add formatXsdDecimal() + </action> + </release> + + <release version="1.0.2" date="2009-04-27" description="OutputUtil, XmlBuilder"> + <action dev='kdgregory' type='add'> + OutputUtil: added support for XMLReader as input source + </action> + <action dev='kdgregory' type='update'> + XmlBuilder: use SAX for text output; support PI nodes + </action> + </release> + + <release version="1.0.1" date="2009-04-25" description="XmlUtil"> + <action dev='kdgregory' type='add'> + XmlUtil: add .scape(), unescape() + </action> + <action /> + </release> + + <release version="1.0.0" date="2009-01-14" description="First production release"/> + </body> +</document> + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-15 00:56:30
|
Revision: 131 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=131&view=rev Author: kdgregory Date: 2009-09-15 00:56:23 +0000 (Tue, 15 Sep 2009) Log Message: ----------- historical tag Added Paths: ----------- tags/rel-1.0.4/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-14 23:52:28
|
Revision: 130 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=130&view=rev Author: kdgregory Date: 2009-09-14 23:52:20 +0000 (Mon, 14 Sep 2009) Log Message: ----------- BeanConverter: convert to Document, not Element Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java Property Changed: ---------------- branches/dev-1.1/ Property changes on: branches/dev-1.1 ___________________________________________________________________ Added: svn:mergeinfo + /trunk:128 Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-09-14 23:38:49 UTC (rev 129) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-09-14 23:52:20 UTC (rev 130) @@ -174,6 +174,7 @@ _inputDriver = new Xml2BeanDriver(); } + /** * Creates an instance to be used for XML -> Bean conversion. */ @@ -197,9 +198,10 @@ * generated document. If a qualified name, all child * elements will inherit its prefix. */ - public Element convertToXml(Object bean, String nsUri, String rootName) + public Document convertToXml(Object bean, String nsUri, String rootName) { - return _outputDriver.convert(bean, nsUri, rootName); + return _outputDriver.convert(bean, nsUri, rootName) + .getOwnerDocument(); } @@ -211,9 +213,10 @@ * @param rootName The name given to the root element of the produced * document. */ - public Element convertToXml(Object bean, String rootName) + public Document convertToXml(Object bean, String rootName) { - return _outputDriver.convert(bean, rootName); + return _outputDriver.convert(bean, rootName) + .getOwnerDocument(); } @@ -232,7 +235,9 @@ /** - * Creates a new Java object from the the passed DOM <code>Element</code>. + * Creates a new Java object from the the passed <code>Element</code>. + * This is useful when a DOM contains a tree of objects and you just + * want to convert one of them. * * @param dom The source element -- this may or may not be the * root element of its document. Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java 2009-09-14 23:38:49 UTC (rev 129) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java 2009-09-14 23:52:20 UTC (rev 130) @@ -60,11 +60,12 @@ //---------------------------------------------------------------------------- private static void assertConversionFailure( - String message, BeanConverter converter, Element elem, Class<?> klass) + String message, BeanConverter converter, + Document dom, Class<?> klass) { try { - converter.convertToJava(elem, klass); + converter.convertToJava(dom, klass); fail(message); } catch (ConversionException ee) @@ -84,11 +85,12 @@ BeanConverter inConverter = new BeanConverter(); String obj = "this is a test"; - Element root = outConverter.convertToXml(obj, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(dom)); + Element root = dom.getDocumentElement(); assertEquals("test", DomUtil.getLocalName(root)); - Object result = inConverter.convertToJava(root, String.class); + Object result = inConverter.convertToJava(dom, String.class); assertEquals(obj, result); } @@ -101,10 +103,10 @@ for (PrimitiveValue value : PRIMITIVE_VALUES) { Object obj = value.getValue(); - Element root = outConverter.convertToXml(obj, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(dom)); - Object result = inConverter.convertToJava(root, value.getKlass()); + Object result = inConverter.convertToJava(dom, value.getKlass()); assertEquals(obj, result); } } @@ -118,10 +120,10 @@ for (PrimitiveValue value : PRIMITIVE_VALUES) { Object obj = value.getValue(); - Element root = outConverter.convertToXml(obj, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(dom)); - Object result = inConverter.convertToJava(root, value.getKlass()); + Object result = inConverter.convertToJava(dom, value.getKlass()); assertEquals(obj, result); } } @@ -132,10 +134,10 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(null, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(dom)); - Object result = inConverter.convertToJava(root, String.class); + Object result = inConverter.convertToJava(dom, String.class); assertNull(result); } @@ -145,10 +147,10 @@ BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSI_NIL); BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_NIL); - Element root = outConverter.convertToXml(null, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(dom)); - Object result = inConverter.convertToJava(root, String.class); + Object result = inConverter.convertToJava(dom, String.class); assertNull(result); } @@ -158,11 +160,12 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_NIL); - Element root = outConverter.convertToXml(null, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(dom)); - assertConversionFailure("accepted DOM with null entry but no xsi:nil", - inConverter, root, String.class); + assertConversionFailure( + "accepted DOM with null entry but no xsi:nil", + inConverter, dom, String.class); } @@ -173,10 +176,10 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - int[] result = inConverter.convertToJava(root, int[].class); + int[] result = inConverter.convertToJava(dom, int[].class); assertTrue(Arrays.equals(data, result)); } @@ -188,10 +191,10 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - List<String> result = inConverter.convertToJava(root, List.class); + List<String> result = inConverter.convertToJava(dom, List.class); assertEquals(data, result); } @@ -206,10 +209,10 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - List<?> result = inConverter.convertToJava(root, List.class); + List<?> result = inConverter.convertToJava(dom, List.class); assertTrue(result instanceof List); assertTrue(result.get(0) instanceof String); } @@ -224,10 +227,10 @@ BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - List<?> result = inConverter.convertToJava(root, List.class); + List<?> result = inConverter.convertToJava(dom, List.class); assertEquals(data, result); } @@ -240,10 +243,10 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - Set<?> result = inConverter.convertToJava(root, SortedSet.class); + Set<?> result = inConverter.convertToJava(dom, SortedSet.class); Iterator<?> itx = result.iterator(); assertEquals("bar", itx.next()); assertEquals("baz", itx.next()); @@ -262,14 +265,14 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - DomAsserts.assertCount(3, root, "/test/data"); - DomAsserts.assertCount(1, root, "/test/data[@key='foo']"); - DomAsserts.assertEquals("argle", root, "/test/data[@key='foo']"); + DomAsserts.assertCount(3, dom, "/test/data"); + DomAsserts.assertCount(1, dom, "/test/data[@key='foo']"); + DomAsserts.assertEquals("argle", dom, "/test/data[@key='foo']"); - Map<?,?> result = inConverter.convertToJava(root, Map.class); + Map<?,?> result = inConverter.convertToJava(dom, Map.class); assertEquals(data, result); } @@ -285,14 +288,14 @@ BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.INTROSPECT_MAPS); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - DomAsserts.assertCount(0, root, "/test/data"); - DomAsserts.assertCount(1, root, "/test/foo"); - DomAsserts.assertEquals("argle", root, "/test/foo"); + DomAsserts.assertCount(0, dom, "/test/data"); + DomAsserts.assertCount(1, dom, "/test/foo"); + DomAsserts.assertEquals("argle", dom, "/test/foo"); - Map<?,?> result = inConverter.convertToJava(root, Map.class); + Map<?,?> result = inConverter.convertToJava(dom, Map.class); assertEquals(data, result); } @@ -304,10 +307,10 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - SimpleBean result = inConverter.convertToJava(root, SimpleBean.class); + SimpleBean result = inConverter.convertToJava(dom, SimpleBean.class); data.assertEquals(result); } @@ -320,17 +323,18 @@ BeanConverter outconverter2 = new BeanConverter(); BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_TYPE); - Element valid = outconverter1.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(valid.getOwnerDocument())); + Document valid = outconverter1.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(valid)); SimpleBean result = inConverter.convertToJava(valid, SimpleBean.class); data.assertEquals(result); - Element invalid = outconverter2.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(invalid.getOwnerDocument())); + Document invalid = outconverter2.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(invalid)); - assertConversionFailure("converter requiring xsi:type accepted XML without", - inConverter, invalid, SimpleBean.class); + assertConversionFailure( + "converter requiring xsi:type accepted XML without", + inConverter, invalid, SimpleBean.class); } @@ -343,10 +347,10 @@ BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - List<SimpleBean> result = inConverter.convertToJava(root, List.class); + List<SimpleBean> result = inConverter.convertToJava(dom, List.class); assertEquals(2, result.size()); bean1.assertEquals(result.get(0)); bean2.assertEquals(result.get(1)); @@ -364,10 +368,10 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - SimpleBean[] result = inConverter.convertToJava(root, SimpleBean[].class); + SimpleBean[] result = inConverter.convertToJava(dom, SimpleBean[].class); assertEquals(2, result.length); bean1.assertEquals(result[0]); bean2.assertEquals(result[1]); @@ -384,10 +388,10 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(dom)); - CompoundBean result = inConverter.convertToJava(root, CompoundBean.class); + CompoundBean result = inConverter.convertToJava(dom, CompoundBean.class); data.assertEquals(result); } @@ -399,29 +403,14 @@ BeanConverter outConverter = new BeanConverter(); BeanConverter inConverter = new BeanConverter(); - Element root = outConverter.convertToXml(data, "urn:foo", "bar:test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + Document dom = outConverter.convertToXml(data, "urn:foo", "bar:test"); +// System.out.println(OutputUtil.compactString(dom)); + Element root = dom.getDocumentElement(); Element child = DomUtil.getChild(root, "sval"); assertEquals("urn:foo", child.getNamespaceURI()); assertEquals("bar", child.getPrefix()); - SimpleBean result = inConverter.convertToJava(root, SimpleBean.class); - data.assertEquals(result); - } - - - // this one is here just for coverage - public void testSimpleBeanFromDocument() throws Exception - { - SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Document dom = outConverter.convertToXml(data, "test").getOwnerDocument(); -// System.out.println(OutputUtil.compactString(dom)); - SimpleBean result = inConverter.convertToJava(dom, SimpleBean.class); data.assertEquals(result); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-14 23:39:11
|
Revision: 129 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=129&view=rev Author: kdgregory Date: 2009-09-14 23:38:49 +0000 (Mon, 14 Sep 2009) Log Message: ----------- merge DomAsserts from trunk Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/junit/DomAsserts.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/junit/DomAsserts.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/junit/DomAsserts.java 2009-09-14 23:30:45 UTC (rev 128) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/junit/DomAsserts.java 2009-09-14 23:38:49 UTC (rev 129) @@ -38,10 +38,10 @@ public class DomAsserts { /** - * Asserts that an element has the given name, ignoring namespace. + * Asserts that an element has the given localname. * - * @param expected The expected name. - * @param elem The element to assert. + * @param expected The expected name, sans prefix. + * @param elem The element on which to assert this name. */ public static void assertName(String expected, Element elem) { @@ -49,11 +49,11 @@ } /** - * Asserts that an element has the given name, ignoring namespace. + * Asserts that an element has the given localname. * * @param message Message to display if assertion fails. - * @param expected The expected name. - * @param elem The element to assert. + * @param expected The expected name, sans prefix. + * @param elem The element on which to assert this name. */ public static void assertName(String message, String expected, Element elem) { @@ -71,7 +71,7 @@ * </code> to assert that the element does not * have a namespace. * @param expectedName The expected name. - * @param elem The element to assert. + * @param elem The element on which to assert this name. */ public static void assertNamespaceAndName( String expectedNSUri, String expectedName, Element elem) @@ -89,7 +89,7 @@ * </code> to assert that the element does not * have a namespace. * @param expectedName The expected name. - * @param elem The element to assert. + * @param elem The element on which to assert this name. */ public static void assertNamespaceAndName( String message, String expectedNSUri, String expectedName, Element elem) @@ -100,189 +100,184 @@ /** - * Asserts that the specified XPath selects at least one node. - * <p> - * Will display the XPath if assertion fails. + * Asserts that the specified XPath selects at least one node. Uses the + * path as a failed-assertion message. * - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertExists(Element elem, String xpath) + public static void assertExists(Node node, String xpath) { - assertExists(xpath, elem, xpath); + assertExists(xpath, node, xpath); } /** - * Asserts that the specified XPath selects at least one node. + * Asserts that the specified XPath selects at least one node, using + * the specified message if the assertion fails. * - * @param message Message to display if assertion fails. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertExists(String message, Element elem, String xpath) + public static void assertExists(String message, Node node, String xpath) { - assertExists(message, elem, new XPathWrapper(xpath)); + assertExists(message, node, new XPathWrapper(xpath)); } /** - * Asserts that the specified XPath selects at least one node. Uses the - * <code>XPathWrapper</code> class to allow more complex paths, including - * namespace bindings. - * <p> - * Will display the XPath if assertion fails. + * Asserts that the specified XPath selects at least one node. Uses + * {@link net.sf.practicalxml.xpath.XPathWrapper} to allow complex + * paths, including namespace bindings. Uses the path as a failed- + * assertion message. * - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertExists(Element elem, XPathWrapper xpath) + public static void assertExists(Node node, XPathWrapper xpath) { - assertExists(xpath.toString(), elem, xpath); + assertExists(xpath.toString(), node, xpath); } /** - * Asserts that the specified XPath selects at least one node. Uses the - * <code>XPathWrapper</code> class to allow more complex paths, including - * namespace bindings. + * Asserts that the specified XPath selects at least one node. Uses + * {@link net.sf.practicalxml.xpath.XPathWrapper} to allow complex + * paths, including namespace bindings. * - * @param message Message to display if assertion fails. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertExists(String message, Element elem, XPathWrapper xpath) + public static void assertExists(String message, Node node, XPathWrapper xpath) { - List<Node> result = xpath.evaluate(elem); + List<Node> result = xpath.evaluate(node); assertTrue(message, result.size() > 0); } /** * Asserts that the specified XPath selects a specified number of nodes. - * <p> - * Will display the XPath if assertion fails. + * Uses the path as a failed-assertion message. * - * @param expected The expected number of nodes selected. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param expected The expected number of nodes selected. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertCount(int expected, Element elem, String xpath) + public static void assertCount(int expected, Node node, String xpath) { - assertCount(xpath, expected, elem, xpath); + assertCount(xpath, expected, node, xpath); } /** * Asserts that the specified XPath selects a specified number of nodes. * - * @param message Message to display if assertion fails. - * @param expected The expected number of nodes selected. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param expected The expected number of nodes selected. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ public static void assertCount( - String message, int expected, Element elem, String xpath) + String message, int expected, Node node, String xpath) { - assertCount(message, expected, elem, new XPathWrapper(xpath)); + assertCount(message, expected, node, new XPathWrapper(xpath)); } /** * Asserts that the specified XPath selects a specified number of nodes. - * Uses the <code>XPathWrapper</code> class to allow more complex paths, - * including namespace bindings. - * <p> - * Will display the XPath if assertion fails. + * Uses {@link net.sf.practicalxml.xpath.XPathWrapper} to allow complex + * paths, including namespace bindings. Uses the path as a failed-assertion + * message. * - * @param expected The expected number of nodes selected. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param expected The expected number of nodes selected. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertCount(int expected, Element elem, XPathWrapper xpath) + public static void assertCount(int expected, Node node, XPathWrapper xpath) { - assertCount(xpath.toString(), expected, elem, xpath); + assertCount(xpath.toString(), expected, node, xpath); } /** * Asserts that the specified XPath selects a specified number of nodes. - * Uses the <code>XPathWrapper</code> class to allow more complex paths, - * including namespace bindings. + * Uses {@link net.sf.practicalxml.xpath.XPathWrapper} to allow complex + * paths, including namespace bindings. * - * @param message Message to display if assertion fails. - * @param expected The expected number of nodes selected. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param expected The expected number of nodes selected. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ public static void assertCount( - String message, int expected, Element elem, XPathWrapper xpath) + String message, int expected, Node node, XPathWrapper xpath) { - List<Node> result = xpath.evaluate(elem); + List<Node> result = xpath.evaluate(node); Assert.assertEquals(message, expected, result.size()); } /** * Asserts that the specified XPath selects a particular String value. - * <p> - * Will display the XPath if assertion fails. + * Uses the path as a failed-assertion message. * - * @param expected The expected value. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param expected The expected value. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertEquals(String expected, Element elem, String xpath) + public static void assertEquals(String expected, Node node, String xpath) { - assertEquals(xpath, expected, elem, new XPathWrapper(xpath)); + assertEquals(xpath, expected, node, new XPathWrapper(xpath)); } /** * Asserts that the specified XPath selects a particular String value. * - * @param message Message to display if assertion fails. - * @param expected The expected value. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param expected The expected value. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ public static void assertEquals( - String message, String expected, Element elem, String xpath) + String message, String expected, Node node, String xpath) { - assertEquals(message, expected, elem, new XPathWrapper(xpath)); + assertEquals(message, expected, node, new XPathWrapper(xpath)); } /** * Asserts that the specified XPath selects a particular String value. - * This variant uses the <code>XPathWrapper</code> class to allow - * more complex paths, including namespace bindings. - * <p> - * Will display the XPath if assertion fails. + * This variant uses {@link net.sf.practicalxml.xpath.XPathWrapper} to + * allow complex paths, including namespace bindings. Uses the path as + * a failed-assertion message. * - * @param expected The expected value. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param expected The expected value. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertEquals(String expected, Element elem, XPathWrapper xpath) + public static void assertEquals(String expected, Node node, XPathWrapper xpath) { - assertEquals(xpath.toString(), expected, elem, xpath); + assertEquals(xpath.toString(), expected, node, xpath); } /** * Asserts that the specified XPath selects a particular String value. - * This variant uses the <code>XPathWrapper</code> class to allow - * more complex paths, including namespace bindings. + * This variant uses {@link net.sf.practicalxml.xpath.XPathWrapper} to + * allow complex paths, including namespace bindings. * - * @param message Message to display if assertion fails. - * @param expected The expected value. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param expected The expected value. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ public static void assertEquals( - String message, String expected, Element elem, XPathWrapper xpath) + String message, String expected, Node node, XPathWrapper xpath) { - Assert.assertEquals(message, expected, xpath.evaluateAsString(elem)); + Assert.assertEquals(message, expected, xpath.evaluateAsString(node)); } -} +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-14 23:30:53
|
Revision: 128 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=128&view=rev Author: kdgregory Date: 2009-09-14 23:30:45 +0000 (Mon, 14 Sep 2009) Log Message: ----------- DomAsserts: XPath assertions now take any node as initial context Modified Paths: -------------- trunk/pom.xml trunk/src/main/java/net/sf/practicalxml/junit/DomAsserts.java Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2009-09-11 18:30:39 UTC (rev 127) +++ trunk/pom.xml 2009-09-14 23:30:45 UTC (rev 128) @@ -5,7 +5,7 @@ <groupId>net.sf.practicalxml</groupId> <artifactId>practicalxml</artifactId> <packaging>jar</packaging> - <version>1.0.4</version> + <version>1.0.5-SNAPSHOT</version> <name>practicalxml</name> <url>http://sourceforge.net/projects/practicalxml/</url> Modified: trunk/src/main/java/net/sf/practicalxml/junit/DomAsserts.java =================================================================== --- trunk/src/main/java/net/sf/practicalxml/junit/DomAsserts.java 2009-09-11 18:30:39 UTC (rev 127) +++ trunk/src/main/java/net/sf/practicalxml/junit/DomAsserts.java 2009-09-14 23:30:45 UTC (rev 128) @@ -38,10 +38,10 @@ public class DomAsserts { /** - * Asserts that an element has the given name, ignoring namespace. + * Asserts that an element has the given localname. * - * @param expected The expected name. - * @param elem The element to assert. + * @param expected The expected name, sans prefix. + * @param elem The element on which to assert this name. */ public static void assertName(String expected, Element elem) { @@ -49,11 +49,11 @@ } /** - * Asserts that an element has the given name, ignoring namespace. + * Asserts that an element has the given localname. * * @param message Message to display if assertion fails. - * @param expected The expected name. - * @param elem The element to assert. + * @param expected The expected name, sans prefix. + * @param elem The element on which to assert this name. */ public static void assertName(String message, String expected, Element elem) { @@ -71,7 +71,7 @@ * </code> to assert that the element does not * have a namespace. * @param localName The expected name, sans prefix - * @param elem The element to assert. + * @param elem The element on which to assert this name. */ public static void assertNamespaceAndName( String expectedNSUri, String localName, Element elem) @@ -89,7 +89,7 @@ * </code> to assert that the element does not * have a namespace. * @param localName The expected name, sans prefix - * @param elem The element to assert. + * @param elem The element on which to assert this name. */ public static void assertNamespaceAndName( String message, String expectedNSUri, String localName, Element elem) @@ -100,189 +100,184 @@ /** - * Asserts that the specified XPath selects at least one node. - * <p> - * Will display the XPath if assertion fails. + * Asserts that the specified XPath selects at least one node. Uses the + * path as a failed-assertion message. * - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertExists(Element elem, String xpath) + public static void assertExists(Node node, String xpath) { - assertExists(xpath, elem, xpath); + assertExists(xpath, node, xpath); } /** - * Asserts that the specified XPath selects at least one node. + * Asserts that the specified XPath selects at least one node, using + * the specified message if the assertion fails. * - * @param message Message to display if assertion fails. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertExists(String message, Element elem, String xpath) + public static void assertExists(String message, Node node, String xpath) { - assertExists(message, elem, new XPathWrapper(xpath)); + assertExists(message, node, new XPathWrapper(xpath)); } /** - * Asserts that the specified XPath selects at least one node. Uses the - * <code>XPathWrapper</code> class to allow more complex paths, including - * namespace bindings. - * <p> - * Will display the XPath if assertion fails. + * Asserts that the specified XPath selects at least one node. Uses + * {@link net.sf.practicalxml.xpath.XPathWrapper} to allow complex + * paths, including namespace bindings. Uses the path as a failed- + * assertion message. * - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertExists(Element elem, XPathWrapper xpath) + public static void assertExists(Node node, XPathWrapper xpath) { - assertExists(xpath.toString(), elem, xpath); + assertExists(xpath.toString(), node, xpath); } /** - * Asserts that the specified XPath selects at least one node. Uses the - * <code>XPathWrapper</code> class to allow more complex paths, including - * namespace bindings. + * Asserts that the specified XPath selects at least one node. Uses + * {@link net.sf.practicalxml.xpath.XPathWrapper} to allow complex + * paths, including namespace bindings. * - * @param message Message to display if assertion fails. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertExists(String message, Element elem, XPathWrapper xpath) + public static void assertExists(String message, Node node, XPathWrapper xpath) { - List<Node> result = xpath.evaluate(elem); + List<Node> result = xpath.evaluate(node); assertTrue(message, result.size() > 0); } /** * Asserts that the specified XPath selects a specified number of nodes. - * <p> - * Will display the XPath if assertion fails. + * Uses the path as a failed-assertion message. * - * @param expected The expected number of nodes selected. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param expected The expected number of nodes selected. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertCount(int expected, Element elem, String xpath) + public static void assertCount(int expected, Node node, String xpath) { - assertCount(xpath, expected, elem, xpath); + assertCount(xpath, expected, node, xpath); } /** * Asserts that the specified XPath selects a specified number of nodes. * - * @param message Message to display if assertion fails. - * @param expected The expected number of nodes selected. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param expected The expected number of nodes selected. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ public static void assertCount( - String message, int expected, Element elem, String xpath) + String message, int expected, Node node, String xpath) { - assertCount(message, expected, elem, new XPathWrapper(xpath)); + assertCount(message, expected, node, new XPathWrapper(xpath)); } /** * Asserts that the specified XPath selects a specified number of nodes. - * Uses the <code>XPathWrapper</code> class to allow more complex paths, - * including namespace bindings. - * <p> - * Will display the XPath if assertion fails. + * Uses {@link net.sf.practicalxml.xpath.XPathWrapper} to allow complex + * paths, including namespace bindings. Uses the path as a failed-assertion + * message. * - * @param expected The expected number of nodes selected. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param expected The expected number of nodes selected. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertCount(int expected, Element elem, XPathWrapper xpath) + public static void assertCount(int expected, Node node, XPathWrapper xpath) { - assertCount(xpath.toString(), expected, elem, xpath); + assertCount(xpath.toString(), expected, node, xpath); } /** * Asserts that the specified XPath selects a specified number of nodes. - * Uses the <code>XPathWrapper</code> class to allow more complex paths, - * including namespace bindings. + * Uses {@link net.sf.practicalxml.xpath.XPathWrapper} to allow complex + * paths, including namespace bindings. * - * @param message Message to display if assertion fails. - * @param expected The expected number of nodes selected. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param expected The expected number of nodes selected. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ public static void assertCount( - String message, int expected, Element elem, XPathWrapper xpath) + String message, int expected, Node node, XPathWrapper xpath) { - List<Node> result = xpath.evaluate(elem); + List<Node> result = xpath.evaluate(node); Assert.assertEquals(message, expected, result.size()); } /** * Asserts that the specified XPath selects a particular String value. - * <p> - * Will display the XPath if assertion fails. + * Uses the path as a failed-assertion message. * - * @param expected The expected value. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param expected The expected value. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertEquals(String expected, Element elem, String xpath) + public static void assertEquals(String expected, Node node, String xpath) { - assertEquals(xpath, expected, elem, new XPathWrapper(xpath)); + assertEquals(xpath, expected, node, new XPathWrapper(xpath)); } /** * Asserts that the specified XPath selects a particular String value. * - * @param message Message to display if assertion fails. - * @param expected The expected value. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param expected The expected value. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ public static void assertEquals( - String message, String expected, Element elem, String xpath) + String message, String expected, Node node, String xpath) { - assertEquals(message, expected, elem, new XPathWrapper(xpath)); + assertEquals(message, expected, node, new XPathWrapper(xpath)); } /** * Asserts that the specified XPath selects a particular String value. - * This variant uses the <code>XPathWrapper</code> class to allow - * more complex paths, including namespace bindings. - * <p> - * Will display the XPath if assertion fails. + * This variant uses {@link net.sf.practicalxml.xpath.XPathWrapper} to + * allow complex paths, including namespace bindings. Uses the path as + * a failed-assertion message. * - * @param expected The expected value. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param expected The expected value. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ - public static void assertEquals(String expected, Element elem, XPathWrapper xpath) + public static void assertEquals(String expected, Node node, XPathWrapper xpath) { - assertEquals(xpath.toString(), expected, elem, xpath); + assertEquals(xpath.toString(), expected, node, xpath); } /** * Asserts that the specified XPath selects a particular String value. - * This variant uses the <code>XPathWrapper</code> class to allow - * more complex paths, including namespace bindings. + * This variant uses {@link net.sf.practicalxml.xpath.XPathWrapper} to + * allow complex paths, including namespace bindings. * - * @param message Message to display if assertion fails. - * @param expected The expected value. - * @param elem The element to serve as initial context. - * @param xpath The path expression. + * @param message Message to display if assertion fails. + * @param expected The expected value. + * @param node Initial context for expression evaluation. + * @param xpath Path expression to assert. */ public static void assertEquals( - String message, String expected, Element elem, XPathWrapper xpath) + String message, String expected, Node node, XPathWrapper xpath) { - Assert.assertEquals(message, expected, xpath.evaluateAsString(elem)); + Assert.assertEquals(message, expected, xpath.evaluateAsString(node)); } -} +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-11 18:30:46
|
Revision: 127 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=127&view=rev Author: kdgregory Date: 2009-09-11 18:30:39 +0000 (Fri, 11 Sep 2009) Log Message: ----------- Xml2JsonConverter now escapes strings Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/JsonUtil.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJsonUtil.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/JsonUtil.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/JsonUtil.java 2009-09-11 17:43:24 UTC (rev 126) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/JsonUtil.java 2009-09-11 18:30:39 UTC (rev 127) @@ -24,6 +24,53 @@ public class JsonUtil { /** + * Escapes a string, replacing quotes, backslashes, non-printable and + * non-ASCII characters by a defined set of single-character or 4-digit + * unicode escapes. + */ + public static String escape(String src) + { + if (src == null) + return ""; + + StringBuffer buf = new StringBuffer(src.length() + 20); + for (int ii = 0 ; ii < src.length() ; ii++) + { + char c = src.charAt(ii); + switch (c) + { + case '"' : + case '\\' : + case '/' : + buf.append('\\').append(c); + break; + case '\b' : + buf.append("\\b"); + break; + case '\f' : + buf.append("\\f"); + break; + case '\n' : + buf.append("\\n"); + break; + case '\r' : + buf.append("\\r"); + break; + case '\t' : + buf.append("\\t"); + break; + default : + if ((c >= 32) && (c <= 127)) + buf.append(c); + else + buf.append(escapeUnicode(c)); + } + } + return buf.toString(); + } + + + /** * Unescapes a string, replacing "slash-sequences" by actual characters. * Null is converted to empty string. * @@ -100,4 +147,18 @@ } return (char)value; } + + + private static String escapeUnicode(char c) + { + char[] buf = new char[] { '\\', 'u', '0', '0', '0', '0' }; + int value = c & 0xFFFF; + for (int ii = 5 ; ii > 1 ; ii--) + { + int digit = value % 16; + value /= 16; + buf[ii] = Character.forDigit(digit, 16); + } + return new String(buf); + } } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java 2009-09-11 17:43:24 UTC (rev 126) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java 2009-09-11 18:30:39 UTC (rev 127) @@ -48,7 +48,7 @@ private StringBuffer appendText(String text, StringBuffer buf) { buf.append('"') - .append(text) + .append(JsonUtil.escape(text)) .append('"'); return buf; } Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJsonUtil.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJsonUtil.java 2009-09-11 17:43:24 UTC (rev 126) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJsonUtil.java 2009-09-11 18:30:39 UTC (rev 127) @@ -18,6 +18,45 @@ public class TestJsonUtil extends TestCase { + public void testEscapeNullAndEmpty() throws Exception + { + assertEquals("", JsonUtil.escape(null)); + assertEquals("", JsonUtil.escape("")); + } + + + public void testEscapeNormalString() throws Exception + { + assertEquals("f", JsonUtil.unescape("f")); + assertEquals("fo", JsonUtil.unescape("fo")); + assertEquals("foo", JsonUtil.unescape("foo")); + } + + + public void testEescapeSingleChar() throws Exception + { + assertEquals("\\\"", JsonUtil.escape("\"")); + assertEquals("\\\\", JsonUtil.escape("\\")); + assertEquals("\\/", JsonUtil.escape("/")); + assertEquals("\\b", JsonUtil.escape("\b")); + assertEquals("\\f", JsonUtil.escape("\f")); + assertEquals("\\n", JsonUtil.escape("\n")); + assertEquals("\\r", JsonUtil.escape("\r")); + assertEquals("\\t", JsonUtil.escape("\t")); + + // and a couple of tests to ensure that we don't overstep + assertEquals("ba\\rbaz", JsonUtil.escape("ba\rbaz")); + assertEquals("\\r\\n", JsonUtil.escape("\r\n")); + } + + + public void testEscapeUnicode() throws Exception + { + assertEquals("\\u0019", JsonUtil.escape("\u0019")); + assertEquals("\\u1bcd", JsonUtil.escape("\u1bcd")); + } + + public void testUnescapeNullAndEmpty() throws Exception { assertEquals("", JsonUtil.unescape(null)); @@ -33,7 +72,7 @@ } - public void testUnescapeSingleCharSlashes() throws Exception + public void testUnescapeSingleChar() throws Exception { assertEquals("\"", JsonUtil.unescape("\\\"")); assertEquals("\\", JsonUtil.unescape("\\\\")); Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java 2009-09-11 17:43:24 UTC (rev 126) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java 2009-09-11 18:30:39 UTC (rev 127) @@ -84,4 +84,19 @@ element("biz", text("baz")), element("fizz", text("buzz"))))); } + + + public void testStringEscaping() throws Exception + { + convertAndAssert( + "{backslash: \"\\\\\", " + + "quote: \"\\\"\", " + + "nonprint: \"\\b\\f\\n\\r\\t\", " + + "unicode: \"b\\u00e4r\"}", + element("data", + element("backslash", text("\\")), + element("quote", text("\"")), + element("nonprint", text("\b\f\n\r\t")), + element("unicode", text("b\u00e4r")))); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-11 17:43:40
|
Revision: 126 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=126&view=rev Author: kdgregory Date: 2009-09-11 17:43:24 +0000 (Fri, 11 Sep 2009) Log Message: ----------- implement JSON -> XML conversion Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/JsonUtil.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJson2XmlConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJsonUtil.java Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java 2009-09-11 17:43:24 UTC (rev 126) @@ -0,0 +1,262 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.json; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.ConversionException; + + +/** + * This class contains a hand-written recursive-descent parser for JSON + * strings. Instances are constructed around a source string, and used + * only once (thus thread-safety is not an issue). + * <p> + * See <a href="http://www.json.org/">json.org</a> for the JSON grammar. + * <p> + * The current implementation creates a child element for each element + * of an array, producing output similar to that from the Bean->XML + * conversion. + */ +public class Json2XmlConverter +{ + private String _src; // we pull substrings from the base string + private int _curPos; // position of current token (start of substring) + private int _nextPos; // position of next token (end of substring) + + + public Json2XmlConverter(String src) + { + _src = src; + } + + + /** + * Creates a new XML <code>Document</code> from the passed JSON string + * (which must contain an object definition and nothing else). The root + * element will be named "data". + */ + public Element convert() + { + Element root = DomUtil.newDocument("data"); + parse(root); + return root; + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + /** + * Top-level parser entry: expects the string to be a single object + * definition, without anything before or after the outer brace pair. + */ + private void parse(Element parent) + { + expect("{"); + parseObject(parent); + if (nextToken().length() > 0) + throw new ConversionException(commonExceptionText( + "unexpected content after closing brace")); + } + + + /** + * Called when the next token is expected to represent a value (of + * any type), to dispatch and append that value to the parent element. + * Returns the subsequent token. + */ + private String valueDispatch(String next, Element parent) + { + if (next.equals("{")) + parseObject(parent); + else if (next.equals("[")) + parseArray(parent); + else if (next.equals("\"")) + DomUtil.setText(parent, parseString()); + else + DomUtil.setText(parent, next); + + return nextToken(); + } + + + private void parseObject(Element parent) + { + String next = nextToken(); + if (atEndOfSequence(next, "}", false)) + return; + + while (true) + { + Element child = appendChild(parent, next); + expect(":"); + + next = valueDispatch(nextToken(), child); + if (atEndOfSequence(next, "}", true)) + return; + next = nextToken(); + } + } + + + private void parseArray(Element parent) + { + String next = nextToken(); + if (atEndOfSequence(next, "]", false)) + return; + + while (true) + { + Element child = DomUtil.appendChild(parent, "data"); + next = valueDispatch(next, child); + if (atEndOfSequence(next, "]", true)) + return; + next = nextToken(); + } + } + + + private String parseString() + { + try + { + for (_curPos = _nextPos ; _nextPos < _src.length() ; _nextPos++) + { + char c = _src.charAt(_nextPos); + if (c == '"') + return JsonUtil.unescape(_src.substring(_curPos, _nextPos++)); + if (c == '\\') + _nextPos++; + } + throw new ConversionException(commonExceptionText("unterminated string")); + } + catch (IllegalArgumentException ee) + { + throw new ConversionException(commonExceptionText("invalid string"), ee); + } + } + + + /** + * Reads the next token and verifies that it contains the expected value. + */ + private String expect(String expected) + { + String next = nextToken(); + if (next.equals(expected)) + return next; + + throw new ConversionException(commonExceptionText("unexpected token")); + } + + + /** + * Checks the next token (passed) to see if it represents the end of a + * sequence, a contination (","), or something unexpected. + */ + private boolean atEndOfSequence(String next, String expectedEnd, boolean throwIfSomethingElse) + { + if (next.equals(expectedEnd)) + return true; + else if (next.equals(",")) + return false; + else if (next.equals("")) + throw new ConversionException(commonExceptionText("unexpected end of input")); + else if (throwIfSomethingElse) + throw new ConversionException(commonExceptionText("unexpected token")); + return false; + } + + + /** + * Extracts the next token from the string, skipping any initial whitespace. + * Tokens consist of a set of specific single-character strings, or any other + * sequence of non-whitespace characters. + */ + private String nextToken() + { + final int len = _src.length(); + + _curPos = _nextPos; + while ((_curPos < len) && Character.isWhitespace(_src.charAt(_curPos))) + _curPos++; + + if (_curPos == len) + return ""; + + _nextPos = _curPos + 1; + if (!isDelimiter(_src.charAt(_curPos))) + { + while ((_nextPos < len) + && !Character.isWhitespace(_src.charAt(_nextPos)) + && !isDelimiter(_src.charAt(_nextPos))) + _nextPos++; + } + + return _src.substring(_curPos, _nextPos); + } + + + private boolean isDelimiter(char c) + { + switch (c) + { + case '{' : + case '}' : + case '[' : + case ']' : + case ':' : + case ',' : + case '"' : + return true; + default : + return false; + } + } + + + private String commonExceptionText(String preamble) + { + String excerpt = (_curPos + 20) > _src.length() + ? _src.substring(_curPos) + : _src.substring(_curPos, _curPos + 20) + "[...]"; + return preamble + " at position " + _curPos + ": \"" + excerpt + "\""; + } + + + /** + * A wrapper around DomUtil.appendChild() that applies some validation + * on the name, and replaces the DOM exception with ConversionException. + */ + private Element appendChild(Element parent, String name) + { + if (name.equals("")) + throw new ConversionException(commonExceptionText("unexpected end of input")); + if (isDelimiter(name.charAt(0))) + throw new ConversionException(commonExceptionText("invalid token")); + try + { + return DomUtil.appendChild(parent, name); + } + catch (Exception e) + { + throw new ConversionException(commonExceptionText("invalid element name"), e); + } + } + +} Property changes on: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Json2XmlConverter.java ___________________________________________________________________ Added: svn:executable + * Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/JsonUtil.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/JsonUtil.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/JsonUtil.java 2009-09-11 17:43:24 UTC (rev 126) @@ -0,0 +1,103 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.json; + +import net.sf.practicalxml.internal.StringUtils; + + +/** + * Static utility methods for working with JSON content. Mostly duplicates + * methods from Jakarta Commons. + */ +public class JsonUtil +{ + /** + * Unescapes a string, replacing "slash-sequences" by actual characters. + * Null is converted to empty string. + * + * @throws IllegalArgumentException on any failure + */ + public static String unescape(String src) + { + if (src == null) + return ""; + + StringBuffer buf = new StringBuffer(src.length()); + for (int ii = 0 ; ii < src.length() ; ) + { + char c = src.charAt(ii++); + if (c == '\\') + { + if (ii == src.length()) + throw new IllegalArgumentException("escape extends past end of string"); + c = src.charAt(ii++); + switch (c) + { + case '"' : + case '\\' : + case '/' : + // do nothing, simple escape + break; + case 'b' : + c = '\b'; + break; + case 'f' : + c = '\f'; + break; + case 'n' : + c = '\n'; + break; + case 'r' : + c = '\r'; + break; + case 't' : + c = '\t'; + break; + case 'U' : + case 'u' : + c = unescapeUnicode(src, ii); + ii += 4; + break; + default : + throw new IllegalArgumentException("invalid escape character: " + c); + } + } + buf.append(c); + } + return buf.toString(); + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + private static char unescapeUnicode(String src, int idx) + { + if (idx + 4 > src.length()) + throw new IllegalArgumentException("unicode escape extends past end of string"); + + int value = 0; + for (int ii = 0 ; ii < 4 ; ii++) + { + int digit = StringUtils.parseDigit(src.charAt(idx + ii), 16); + if (digit < 0) + throw new IllegalArgumentException( + "invalid unicode escape: " + src.substring(idx, idx + 4)); + value = value * 16 + digit; + } + return (char)value; + } +} Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJson2XmlConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJson2XmlConverter.java (rev 0) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJson2XmlConverter.java 2009-09-11 17:43:24 UTC (rev 126) @@ -0,0 +1,435 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.json; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.AbstractConversionTestCase; +import net.sf.practicalxml.converter.ConversionException; + + +public class TestJson2XmlConverter +extends AbstractConversionTestCase +{ + public TestJson2XmlConverter(String testName) + { + super(testName); + } + + +//---------------------------------------------------------------------------- +// Test Cases +// ---- +// Note that in some place we call Node.getChildNodes(), in others we call +// DomUtil.getChildren. This is intentional: in the former case we want to +// ensure that the converter isn't inserting extraneous text, in the latter +// we want to ensure it isn't inserting extraneous elements (but we don't +// care how many nodes it uses to build the text content). +//---------------------------------------------------------------------------- + + public void testConvertEmpty() throws Exception + { + String src = "{}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(0, root.getChildNodes().getLength()); + } + + + public void testConvertEmptyWithWhitespace() throws Exception + { + String src = " {\t}\n"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(0, root.getChildNodes().getLength()); + } + + + public void testFailContentBeforeInitialBrace() throws Exception + { + String src = "test = {}"; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException ee) + { + // success + } + } + + + public void testFailContentAfterTerminalBrace() throws Exception + { + String src = "{};"; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException ee) + { + // success + } + } + + + public void testFailMissingTerminalBrace() throws Exception + { + String src = " { "; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException ee) + { + // success + } + } + + + public void testConvertSingleElementNumeric() throws Exception + { + String src = "{foo: 123}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertEquals("123", DomUtil.getText(child)); + assertEquals(0, DomUtil.getChildren(child).size()); + } + + + public void testConvertSingleElementString() throws Exception + { + String src = "{foo: \"bar\"}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertEquals("bar", DomUtil.getText(child)); + assertEquals(0, DomUtil.getChildren(child).size()); + } + + + public void testConvertEmptyString() throws Exception + { + String src = "{foo: \"\"}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertEquals("", DomUtil.getText(child)); + assertEquals(0, DomUtil.getChildren(child).size()); + } + + + public void testConvertStringWithEmbeddedEscape() throws Exception + { + String src = "{foo: \"b\\\"\\u0061r\"}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertEquals("b\"ar", DomUtil.getText(child)); + assertEquals(0, DomUtil.getChildren(child).size()); + } + + + public void testFailUnterminatedString() throws Exception + { + String src = "{foo: \"bar}"; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException ee) + { + // success + } + } + + + public void testFailInvalidEscapeAtEndOfString() throws Exception + { + String src = "{foo: \"bar\\u123\"}"; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException ee) + { + // success + } + } + + + public void testConvertTwoElementNumeric() throws Exception + { + String src = "{foo: 123, bar: 456}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(2, root.getChildNodes().getLength()); + + Element child1 = (Element)root.getFirstChild(); + assertEquals("foo", child1.getNodeName()); + assertEquals("123", DomUtil.getText(child1)); + assertEquals(0, DomUtil.getChildren(child1).size()); + + Element child2 = (Element)child1.getNextSibling(); + assertEquals("bar", child2.getNodeName()); + assertEquals("456", DomUtil.getText(child2)); + assertEquals(0, DomUtil.getChildren(child2).size()); + } + + + public void testConvertTwoElementStringWithWhitespace() throws Exception + { + String src = "{foo : \"123\" , bar\t: \"456\" }"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(2, root.getChildNodes().getLength()); + + Element child1 = (Element)root.getFirstChild(); + assertEquals("foo", child1.getNodeName()); + assertEquals("123", DomUtil.getText(child1)); + assertEquals(0, DomUtil.getChildren(child1).size()); + + Element child2 = (Element)child1.getNextSibling(); + assertEquals("bar", child2.getNodeName()); + assertEquals("456", DomUtil.getText(child2)); + assertEquals(0, DomUtil.getChildren(child2).size()); + } + + + public void testFailObjectMissingCommaBetweenTerms() throws Exception + { + String src = "{foo: 123 bar: 456}"; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException e) + { + // success + } + } + + + public void testFailObjectMissingElement() throws Exception + { + String src = "{foo: 123, , bar: 456}"; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException ee) + { + // success + } + } + + + public void testConvertNested() throws Exception + { + String src = "{foo: {bar: 123, baz:456}}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertNull(DomUtil.getText(child)); + assertEquals(2, child.getChildNodes().getLength()); + + Element grandchild1 = (Element)child.getFirstChild(); + assertEquals("bar", grandchild1.getNodeName()); + assertEquals("123", DomUtil.getText(grandchild1)); + assertEquals(0, DomUtil.getChildren(grandchild1).size()); + + Element grandchild2 = (Element)grandchild1.getNextSibling(); + assertEquals("baz", grandchild2.getNodeName()); + assertEquals("456", DomUtil.getText(grandchild2)); + assertEquals(0, DomUtil.getChildren(grandchild2).size()); + } + + + public void testConvertNestedEmpty() throws Exception + { + String src = "{foo: {}}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertNull(DomUtil.getText(child)); + assertEquals(0, child.getChildNodes().getLength()); + } + + + public void testConvertEmptyArray() throws Exception + { + String src = "{foo: []}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertNull(DomUtil.getText(child)); + assertEquals(0, child.getChildNodes().getLength()); + } + + + public void testConvertSingleElementNumericArray() throws Exception + { + String src = "{foo: [123]}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertNull(DomUtil.getText(child)); + assertEquals(1, child.getChildNodes().getLength()); + + Element grandchild = (Element)child.getFirstChild(); + assertEquals("data", grandchild.getNodeName()); + assertEquals("123", DomUtil.getText(grandchild)); + assertEquals(0, DomUtil.getChildren(grandchild).size()); + } + + + public void testConvertMultiElementNumericArray() throws Exception + { + String src = "{foo: [123, 456]}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertNull(DomUtil.getText(child)); + assertEquals(2, child.getChildNodes().getLength()); + + Element grandchild1 = (Element)child.getFirstChild(); + assertEquals("data", grandchild1.getNodeName()); + assertEquals("123", DomUtil.getText(grandchild1)); + assertEquals(0, DomUtil.getChildren(grandchild1).size()); + + Element grandchild2 = (Element)grandchild1.getNextSibling(); + assertEquals("data", grandchild2.getNodeName()); + assertEquals("456", DomUtil.getText(grandchild2)); + assertEquals(0, DomUtil.getChildren(grandchild2).size()); + } + + + public void testConvertMultiElementMixedArray() throws Exception + { + String src = "{foo: [123, \"bar\", 456]}"; + + Element root = new Json2XmlConverter(src).convert(); + assertEquals("data", root.getNodeName()); + assertEquals(1, root.getChildNodes().getLength()); + + Element child = (Element)root.getFirstChild(); + assertEquals("foo", child.getNodeName()); + assertNull(DomUtil.getText(child)); + assertEquals(3, child.getChildNodes().getLength()); + + Element grandchild1 = (Element)child.getFirstChild(); + assertEquals("data", grandchild1.getNodeName()); + assertEquals("123", DomUtil.getText(grandchild1)); + assertEquals(0, DomUtil.getChildren(grandchild1).size()); + + Element grandchild2 = (Element)grandchild1.getNextSibling(); + assertEquals("data", grandchild2.getNodeName()); + assertEquals("bar", DomUtil.getText(grandchild2)); + assertEquals(0, DomUtil.getChildren(grandchild2).size()); + + Element grandchild3 = (Element)grandchild2.getNextSibling(); + assertEquals("data", grandchild3.getNodeName()); + assertEquals("456", DomUtil.getText(grandchild3)); + assertEquals(0, DomUtil.getChildren(grandchild3).size()); + } + + + public void testFailConvertUnterminatedArray() throws Exception + { + String src = "{foo: [123, 456"; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException ee) + { + // success + } + } + + + public void testFailConvertArrayMissingElement() throws Exception + { + String src = "{foo: [123 , , 456]}"; + + try + { + new Json2XmlConverter(src).convert(); + fail(); + } + catch (ConversionException ee) + { + // success + } + } +} Property changes on: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJson2XmlConverter.java ___________________________________________________________________ Added: svn:executable + * Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJsonUtil.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJsonUtil.java (rev 0) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestJsonUtil.java 2009-09-11 17:43:24 UTC (rev 126) @@ -0,0 +1,118 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.json; + +import junit.framework.TestCase; + +public class TestJsonUtil extends TestCase +{ + public void testUnescapeNullAndEmpty() throws Exception + { + assertEquals("", JsonUtil.unescape(null)); + assertEquals("", JsonUtil.unescape("")); + } + + + public void testUnescapeNormalString() throws Exception + { + assertEquals("f", JsonUtil.unescape("f")); + assertEquals("fo", JsonUtil.unescape("fo")); + assertEquals("foo", JsonUtil.unescape("foo")); + } + + + public void testUnescapeSingleCharSlashes() throws Exception + { + assertEquals("\"", JsonUtil.unescape("\\\"")); + assertEquals("\\", JsonUtil.unescape("\\\\")); + assertEquals("/", JsonUtil.unescape("\\/")); + assertEquals("\b", JsonUtil.unescape("\\b")); + assertEquals("\f", JsonUtil.unescape("\\f")); + assertEquals("\n", JsonUtil.unescape("\\n")); + assertEquals("\r", JsonUtil.unescape("\\r")); + assertEquals("\t", JsonUtil.unescape("\\t")); + + // and a couple of tests to ensure that we don't overstep + assertEquals("ba\rbaz", JsonUtil.unescape("ba\\rbaz")); + assertEquals("\r\n", JsonUtil.unescape("\\r\\n")); + } + + + public void testUnescapeUnicode() throws Exception + { + assertEquals("A", JsonUtil.unescape("\\u0041")); + assertEquals("A", JsonUtil.unescape("\\U0041")); + + // verify that we correctly index subsequent chars + assertEquals("BAR", JsonUtil.unescape("B\\U0041R")); + } + + + public void testUnescapeFailEndOfString() throws Exception + { + try + { + JsonUtil.unescape("foo\\"); + fail("completed for escape at end of string"); + } + catch (IllegalArgumentException e) + { + // success + } + } + + + public void testUnescapeFailInvalidChar() throws Exception + { + try + { + JsonUtil.unescape("foo\\q"); + fail("completed for invalid escape sequence"); + } + catch (IllegalArgumentException e) + { + // success + } + } + + + public void testUnescapeFailIncompleteUnicodeEscape() throws Exception + { + try + { + JsonUtil.unescape("foo\\u12"); + fail("completed for invalid escape sequence"); + } + catch (IllegalArgumentException e) + { + // success + } + } + + + public void testUnescapeFailInvalidUnicodeEscape() throws Exception + { + try + { + JsonUtil.unescape("\\u0foo"); + fail("completed for invalid escape sequence"); + } + catch (IllegalArgumentException e) + { + // success + } + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-10 13:39:29
|
Revision: 125 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=125&view=rev Author: kdgregory Date: 2009-09-10 13:39:16 +0000 (Thu, 10 Sep 2009) Log Message: ----------- add NodeListIterator Modified Paths: -------------- trunk/pom.xml trunk/src/main/java/net/sf/practicalxml/util/NodeListIterable.java Added Paths: ----------- trunk/src/main/java/net/sf/practicalxml/util/NodeListIterator.java trunk/src/test/java/net/sf/practicalxml/util/TestNodeListIterator.java Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2009-09-08 16:06:13 UTC (rev 124) +++ trunk/pom.xml 2009-09-10 13:39:16 UTC (rev 125) @@ -5,7 +5,7 @@ <groupId>net.sf.practicalxml</groupId> <artifactId>practicalxml</artifactId> <packaging>jar</packaging> - <version>1.0.3</version> + <version>1.0.4</version> <name>practicalxml</name> <url>http://sourceforge.net/projects/practicalxml/</url> Modified: trunk/src/main/java/net/sf/practicalxml/util/NodeListIterable.java =================================================================== --- trunk/src/main/java/net/sf/practicalxml/util/NodeListIterable.java 2009-09-08 16:06:13 UTC (rev 124) +++ trunk/src/main/java/net/sf/practicalxml/util/NodeListIterable.java 2009-09-10 13:39:16 UTC (rev 125) @@ -15,15 +15,15 @@ package net.sf.practicalxml.util; import java.util.Iterator; -import java.util.NoSuchElementException; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** - * A wrapper for a DOM <code>NodeList</code> that allows it to be used in - * a JDK 1.5 for-each loop. + * A wrapper for a DOM <code>NodeList</code> that allows it to be used in a + * JDK 1.5 for-each loop. See {@link net.sf.practicalxml.util.NodeListIterator} + * if you want full iterator operation. */ public class NodeListIterable implements Iterable<Node> @@ -37,30 +37,6 @@ public Iterator<Node> iterator() { - return new MyIterator(); + return new NodeListIterator(_list); } - - - private class MyIterator - implements Iterator<Node> - { - int _position = 0; - - public boolean hasNext() - { - return _position < _list.getLength(); - } - - public Node next() - { - if (!hasNext()) - throw new NoSuchElementException(); - return _list.item(_position++); - } - - public void remove() - { - throw new UnsupportedOperationException("unable to remove from NodeList"); - } - } } Added: trunk/src/main/java/net/sf/practicalxml/util/NodeListIterator.java =================================================================== --- trunk/src/main/java/net/sf/practicalxml/util/NodeListIterator.java (rev 0) +++ trunk/src/main/java/net/sf/practicalxml/util/NodeListIterator.java 2009-09-10 13:39:16 UTC (rev 125) @@ -0,0 +1,79 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.util; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + + +/** + * A wrapper for {@link org.w3c.dom.NodeList} that provides full iterator + * behavior. See {@link net.sf.practicalxml.util.NodeListIterable} if all + * you want to do is use the NodeList in a JDK 1.5 <code>for</code> loop. + * <p> + * Because a <code>NodeList</code> is a view on a DOM tree, this iterator has + * slightly different semantics than a typical <code>java.util</code> iterator. + * First, it is not "fail fast": the DOM consists of independent nodes, and we + * have no way to track when changes to the DOM may have made the nodelist + * invalid. + * <p> + * Second, and more important, removal via the iterator changes the DOM, not + * just the underlying list. + */ +public class NodeListIterator +implements Iterator<Node> +{ + private NodeList _list; + private int _pos; + private Node _current; + + + public NodeListIterator(NodeList nodelist) + { + _list = nodelist; + } + + + public boolean hasNext() + { + return _pos < _list.getLength(); + } + + + public Node next() + { + if (hasNext()) + { + _current = _list.item(_pos++); + return _current; + } + throw new NoSuchElementException("invalid index: " + _pos); + } + + + public void remove() + { + if (_current == null) + throw new IllegalStateException("no current node"); + + Node _parent = _current.getParentNode(); + _parent.removeChild(_current); + _pos--; + _current = null; + } +} Added: trunk/src/test/java/net/sf/practicalxml/util/TestNodeListIterator.java =================================================================== --- trunk/src/test/java/net/sf/practicalxml/util/TestNodeListIterator.java (rev 0) +++ trunk/src/test/java/net/sf/practicalxml/util/TestNodeListIterator.java 2009-09-10 13:39:16 UTC (rev 125) @@ -0,0 +1,179 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.util; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +import junit.framework.TestCase; + +import static net.sf.practicalxml.builder.XmlBuilder.*; + + +public class TestNodeListIterator +extends TestCase +{ + public final static String EL_CHILD1 = "child1"; + public final static String EL_CHILD2 = "child2"; + public final static String TXT1 = "some text"; + + private Element _testData + = element("root", + element(EL_CHILD1), + text(TXT1), + element(EL_CHILD2)) + .toDOM().getDocumentElement(); + +//---------------------------------------------------------------------------- +// Test Cases +//---------------------------------------------------------------------------- + + public void testBasicIteration() throws Exception + { + Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes()); + + assertTrue(itx.hasNext()); + Node node1 = itx.next(); + assertTrue(node1 instanceof Element); + assertEquals(EL_CHILD1, node1.getNodeName()); + + assertTrue(itx.hasNext()); + Node node2 = itx.next(); + assertTrue(node2 instanceof Text); + assertEquals(TXT1, node2.getNodeValue()); + + assertTrue(itx.hasNext()); + Node node3 = itx.next(); + assertTrue(node3 instanceof Element); + assertEquals(EL_CHILD2, node3.getNodeName()); + + assertFalse(itx.hasNext()); + } + + + public void testIterationOffTheEnd() throws Exception + { + Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes()); + while (itx.hasNext()) + itx.next(); + + try + { + itx.next(); + fail("able to iterate off end of list"); + } + catch (NoSuchElementException ee) + { + // success + } + } + + + public void testRemove() throws Exception + { + Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes()); + + itx.next(); + itx.next(); + itx.remove(); + + assertTrue(itx.hasNext()); + Node node = itx.next(); + assertTrue(node instanceof Element); + assertEquals(EL_CHILD2, node.getNodeName()); + + assertFalse(itx.hasNext()); + + // verify that DOM was changed + + NodeList list = _testData.getChildNodes(); + assertEquals(2, list.getLength()); + + Node node1 = list.item(0); + assertTrue(node1 instanceof Element); + assertEquals(EL_CHILD1, node1.getNodeName()); + + Node node2 = list.item(1); + assertTrue(node2 instanceof Element); + assertEquals(EL_CHILD2, node2.getNodeName()); + } + + + public void testRemoveAtEndOfIteration() throws Exception + { + Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes()); + + itx.next(); + itx.next(); + itx.next(); + assertFalse(itx.hasNext()); + + itx.remove(); + + // verify that DOM was changed + + NodeList list = _testData.getChildNodes(); + assertEquals(2, list.getLength()); + + Node node1 = list.item(0); + assertTrue(node1 instanceof Element); + assertEquals(EL_CHILD1, node1.getNodeName()); + + Node node2 = list.item(1); + assertTrue(node2 instanceof Text); + assertEquals(TXT1, node2.getNodeValue()); + } + + + public void testRemoveFailsIfNextNotCalled() throws Exception + { + Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes()); + + try + { + itx.remove(); + fail("remove() succeeded without initial next()"); + } + catch (IllegalStateException ee) + { + // success + } + } + + + public void testRemoveFailsIfCalledTwice() throws Exception + { + Iterator<Node> itx = new NodeListIterator(_testData.getChildNodes()); + + itx.next(); + itx.next(); + itx.remove(); + + try + { + itx.remove(); + fail("remove() succeeded without intervening next()"); + } + catch (IllegalStateException ee) + { + // success + } + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-08 16:06:23
|
Revision: 124 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=124&view=rev Author: kdgregory Date: 2009-09-08 16:06:13 +0000 (Tue, 08 Sep 2009) Log Message: ----------- implement Xml2Json conversion Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java 2009-09-08 16:06:13 UTC (rev 124) @@ -0,0 +1,73 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.json; + +import java.util.Iterator; +import java.util.List; + +import net.sf.practicalxml.DomUtil; + +import org.w3c.dom.Element; + + +/** + * Handles the actual work of converting XML to JSON. + */ +public class Xml2JsonConverter +{ + /** + * Appends the contents of the specified element to an existing buffer. + * Returns the buffer as a convenience. + */ + public StringBuffer convert(Element elem, StringBuffer buf) + { + String text = DomUtil.getText(elem); + if (text != null) + return appendText(text, buf); + else + return appendChildren(elem, buf); + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + private StringBuffer appendText(String text, StringBuffer buf) + { + buf.append('"') + .append(text) + .append('"'); + return buf; + } + + + private StringBuffer appendChildren(Element elem, StringBuffer buf) + { + buf.append("{"); + List<Element> children = DomUtil.getChildren(elem); + for (Iterator<Element> childItx = children.iterator() ; childItx.hasNext() ; ) + { + Element child = childItx.next(); + buf.append(DomUtil.getLocalName(child)) + .append(": "); + convert(child, buf); + if (childItx.hasNext()) + buf.append(", "); + } + buf.append("}"); + return buf; + } +} Property changes on: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/json/Xml2JsonConverter.java ___________________________________________________________________ Added: svn:executable + * Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java (rev 0) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java 2009-09-08 16:06:13 UTC (rev 124) @@ -0,0 +1,87 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package net.sf.practicalxml.converter.json; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.builder.ElementNode; +import net.sf.practicalxml.converter.AbstractConversionTestCase; + +import static net.sf.practicalxml.builder.XmlBuilder.*; + + +public class TestXml2JsonConverter +extends AbstractConversionTestCase +{ + public TestXml2JsonConverter(String testName) + { + super(testName); + } + + +//---------------------------------------------------------------------------- +// Support Code +//---------------------------------------------------------------------------- + + public void convertAndAssert(String expected, ElementNode rootNode) + { + Element root = rootNode.toDOM().getDocumentElement(); + StringBuffer buf = new Xml2JsonConverter() + .convert(root, new StringBuffer()); + assertEquals(expected, buf.toString()); + } + + +//---------------------------------------------------------------------------- +// Test Cases +//---------------------------------------------------------------------------- + + public void testEmptyConversion() throws Exception + { + convertAndAssert( + "{}", + element("data")); + } + + + public void testSingleChild() throws Exception + { + convertAndAssert( + "{foo: \"bar\"}", + element("data", + element("foo", text("bar")))); + } + + + public void testTwoChildren() throws Exception + { + convertAndAssert( + "{foo: \"bar\", argle: \"bargle\"}", + element("data", + element("foo", text("bar")), + element("argle", text("bargle")))); + } + + + public void testChildAndGrandchildren() throws Exception + { + convertAndAssert( + "{foo: \"bar\", argle: {biz: \"baz\", fizz: \"buzz\"}}", + element("data", + element("foo", text("bar")), + element("argle", + element("biz", text("baz")), + element("fizz", text("buzz"))))); + } +} Property changes on: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/json/TestXml2JsonConverter.java ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-08 15:10:27
|
Revision: 123 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=123&view=rev Author: kdgregory Date: 2009-09-08 15:10:15 +0000 (Tue, 08 Sep 2009) Log Message: ----------- more testcase repackaging Added Paths: ----------- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java Removed Paths: ------------- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java Deleted: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-09-08 14:55:08 UTC (rev 122) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-09-08 15:10:15 UTC (rev 123) @@ -1,426 +0,0 @@ -// Copyright 2008-2009 severally by the contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package net.sf.practicalxml.converter; - -import java.math.BigDecimal; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import net.sf.practicalxml.DomUtil; -import net.sf.practicalxml.OutputUtil; -import net.sf.practicalxml.converter.bean.AbstractBeanConverterTestCase; -import net.sf.practicalxml.converter.bean.Bean2XmlOptions; -import net.sf.practicalxml.converter.bean.Xml2BeanOptions; -import net.sf.practicalxml.junit.DomAsserts; - - -/** - * Tests for the top-level <code>BeanConverter</code> methods. These are all - * "out and back" tests to verify that we can read the XML that we produce - * (and to show cases where we can't). Detailed tests (verifying specific - * output) are in {@link TestBean2XmlDriver} and {@link TestXml2BeanDriver}. - * <p> - * Note that each conversion has a commented-out line that will print the - * generated XML. Uncommenting these lines may help you understand how - * conversion works in particular cases. - */ -public class TestBeanConverter -extends AbstractBeanConverterTestCase -{ - public TestBeanConverter(String name) - { - super(name); - } - - -//---------------------------------------------------------------------------- -// Support Code -//---------------------------------------------------------------------------- - - private static void assertConversionFailure( - String message, BeanConverter converter, Element elem, Class<?> klass) - { - try - { - converter.convertToJava(elem, klass); - fail(message); - } - catch (ConversionException ee) - { -// System.out.println(ee); - } - } - -//---------------------------------------------------------------------------- -// Test Cases -//---------------------------------------------------------------------------- - - // an initial test to verify everything works - public void testConvertStringDefault() throws Exception - { - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - String obj = "this is a test"; - Element root = outConverter.convertToXml(obj, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - assertEquals("test", DomUtil.getLocalName(root)); - - Object result = inConverter.convertToJava(root, String.class); - assertEquals(obj, result); - } - - - public void testConvertPrimitiveDefault() throws Exception - { - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - for (PrimitiveValue value : PRIMITIVE_VALUES) - { - Object obj = value.getValue(); - Element root = outConverter.convertToXml(obj, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - Object result = inConverter.convertToJava(root, value.getKlass()); - assertEquals(obj, result); - } - } - - - public void testConvertPrimitiveFormatXsd() throws Exception - { - BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSD_FORMAT); - BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.EXPECT_XSD_FORMAT); - - for (PrimitiveValue value : PRIMITIVE_VALUES) - { - Object obj = value.getValue(); - Element root = outConverter.convertToXml(obj, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - Object result = inConverter.convertToJava(root, value.getKlass()); - assertEquals(obj, result); - } - } - - - public void testConvertNullDefault() throws Exception - { - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(null, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - Object result = inConverter.convertToJava(root, String.class); - assertNull(result); - } - - - public void testConvertNullUseAndRequireXsiNil() throws Exception - { - BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSI_NIL); - BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_NIL); - - Element root = outConverter.convertToXml(null, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - Object result = inConverter.convertToJava(root, String.class); - assertNull(result); - } - - - public void testConvertNullFailureRequireXsiNil() throws Exception - { - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_NIL); - - Element root = outConverter.convertToXml(null, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - assertConversionFailure("accepted DOM with null entry but no xsi:nil", - inConverter, root, String.class); - } - - - public void testPrimitiveArrayDefault() throws Exception - { - int[] data = new int[] { 1, 2, 4, 5 }; - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - int[] result = inConverter.convertToJava(root, int[].class); - assertTrue(Arrays.equals(data, result)); - } - - - public void testStringListDefault() throws Exception - { - List<String> data = Arrays.asList("foo", "bar", "baz"); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - List<String> result = inConverter.convertToJava(root, List.class); - assertEquals(data, result); - } - - - // demonstrates that the list will be read as List<String> even though - // it was written as List<Integer> - public void testIntegerListDefault() throws Exception - { - List<Integer> data = Arrays.asList(1, 2, 3); - assert(data.get(0) instanceof Integer); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - List<?> result = inConverter.convertToJava(root, List.class); - assertTrue(result instanceof List); - assertTrue(result.get(0) instanceof String); - } - - - // demonstrates that you don't need to require xsi:type to use it - public void testIntegerListWithXsiType() throws Exception - { - List<Integer> data = Arrays.asList(1, 2, 3); - assert(data.get(0) instanceof Integer); - - BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - List<?> result = inConverter.convertToJava(root, List.class); - assertEquals(data, result); - } - - - // demonstrates that the caller drives the inbound conversion - public void testConvertListToSortedSet() throws Exception - { - List<String> data = Arrays.asList("foo", "bar", "baz", "bar"); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - Set<?> result = inConverter.convertToJava(root, SortedSet.class); - Iterator<?> itx = result.iterator(); - assertEquals("bar", itx.next()); - assertEquals("baz", itx.next()); - assertEquals("foo", itx.next()); - assertFalse(itx.hasNext()); - } - - - public void testMapDefault() throws Exception - { - Map<String,String> data = new HashMap<String,String>(); - data.put("foo", "argle"); - data.put("bar", "bargle"); - data.put("baz", "bazgle"); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - DomAsserts.assertCount(3, root, "/test/data"); - DomAsserts.assertCount(1, root, "/test/data[@key='foo']"); - DomAsserts.assertEquals("argle", root, "/test/data[@key='foo']"); - - Map<?,?> result = inConverter.convertToJava(root, Map.class); - assertEquals(data, result); - } - - - // demonstrates that the input converter handles either format by default - public void testMapIntrospected() throws Exception - { - Map<String,String> data = new HashMap<String,String>(); - data.put("foo", "argle"); - data.put("bar", "bargle"); - data.put("baz", "bazgle"); - - BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.INTROSPECT_MAPS); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - DomAsserts.assertCount(0, root, "/test/data"); - DomAsserts.assertCount(1, root, "/test/foo"); - DomAsserts.assertEquals("argle", root, "/test/foo"); - - Map<?,?> result = inConverter.convertToJava(root, Map.class); - assertEquals(data, result); - } - - - public void testSimpleBeanDefault() throws Exception - { - SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - SimpleBean result = inConverter.convertToJava(root, SimpleBean.class); - data.assertEquals(result); - } - - - public void testSimpleBeanRequireXsiType() throws Exception - { - SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); - - BeanConverter outconverter1 = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); - BeanConverter outconverter2 = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_TYPE); - - Element valid = outconverter1.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(valid.getOwnerDocument())); - - SimpleBean result = inConverter.convertToJava(valid, SimpleBean.class); - data.assertEquals(result); - - Element invalid = outconverter2.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(invalid.getOwnerDocument())); - - assertConversionFailure("converter requiring xsi:type accepted XML without", - inConverter, invalid, SimpleBean.class); - } - - - public void testListOfSimpleBeanWithXsiTypeAndNulls() throws Exception - { - SimpleBean bean1 = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); - SimpleBean bean2 = new SimpleBean("zyx", 987, null, false); - List<SimpleBean> data = Arrays.asList(bean1, bean2); - - BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - List<SimpleBean> result = inConverter.convertToJava(root, List.class); - assertEquals(2, result.size()); - bean1.assertEquals(result.get(0)); - bean2.assertEquals(result.get(1)); - } - - - // another demonstration that caller drives input conversion - // ... and note that we don't care about xsi:type in this case - public void testListOfSimpleBeanToArrayOfSame() throws Exception - { - SimpleBean bean1 = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); - SimpleBean bean2 = new SimpleBean("zyx", 987, null, false); - List<SimpleBean> data = Arrays.asList(bean1, bean2); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - SimpleBean[] result = inConverter.convertToJava(root, SimpleBean[].class); - assertEquals(2, result.length); - bean1.assertEquals(result[0]); - bean2.assertEquals(result[1]); - } - - - public void testCompoundBeanDefault() throws Exception - { - CompoundBean data = new CompoundBean( - new SimpleBean("abc", 123, new BigDecimal("456.789"), true), - new int[] { 1, 5, 7, 9 }, - Arrays.asList("foo", "bar", "baz")); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - CompoundBean result = inConverter.convertToJava(root, CompoundBean.class); - data.assertEquals(result); - } - - - public void testSimpleBeanWithNamespace() throws Exception - { - SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Element root = outConverter.convertToXml(data, "urn:foo", "bar:test"); -// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - - Element child = DomUtil.getChild(root, "sval"); - assertEquals("urn:foo", child.getNamespaceURI()); - assertEquals("bar", child.getPrefix()); - - SimpleBean result = inConverter.convertToJava(root, SimpleBean.class); - data.assertEquals(result); - } - - - // this one is here just for coverage - public void testSimpleBeanFromDocument() throws Exception - { - SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); - - BeanConverter outConverter = new BeanConverter(); - BeanConverter inConverter = new BeanConverter(); - - Document dom = outConverter.convertToXml(data, "test").getOwnerDocument(); -// System.out.println(OutputUtil.compactString(dom)); - - SimpleBean result = inConverter.convertToJava(dom, SimpleBean.class); - data.assertEquals(result); - } -} \ No newline at end of file Copied: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java (from rev 121, branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java) =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java (rev 0) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/TestBeanConverter.java 2009-09-08 15:10:15 UTC (rev 123) @@ -0,0 +1,428 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.bean; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.OutputUtil; +import net.sf.practicalxml.converter.BeanConverter; +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.bean.AbstractBeanConverterTestCase; +import net.sf.practicalxml.converter.bean.Bean2XmlOptions; +import net.sf.practicalxml.converter.bean.Xml2BeanOptions; +import net.sf.practicalxml.junit.DomAsserts; + + +/** + * Tests for the top-level <code>BeanConverter</code> methods. These are all + * "out and back" tests to verify that we can read the XML that we produce + * (and to show cases where we can't). Detailed tests (verifying specific + * output) are in {@link TestBean2XmlDriver} and {@link TestXml2BeanDriver}. + * <p> + * Note that each conversion has a commented-out line that will print the + * generated XML. Uncommenting these lines may help you understand how + * conversion works in particular cases. + */ +public class TestBeanConverter +extends AbstractBeanConverterTestCase +{ + public TestBeanConverter(String name) + { + super(name); + } + + +//---------------------------------------------------------------------------- +// Support Code +//---------------------------------------------------------------------------- + + private static void assertConversionFailure( + String message, BeanConverter converter, Element elem, Class<?> klass) + { + try + { + converter.convertToJava(elem, klass); + fail(message); + } + catch (ConversionException ee) + { +// System.out.println(ee); + } + } + +//---------------------------------------------------------------------------- +// Test Cases +//---------------------------------------------------------------------------- + + // an initial test to verify everything works + public void testConvertStringDefault() throws Exception + { + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + String obj = "this is a test"; + Element root = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + assertEquals("test", DomUtil.getLocalName(root)); + + Object result = inConverter.convertToJava(root, String.class); + assertEquals(obj, result); + } + + + public void testConvertPrimitiveDefault() throws Exception + { + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + for (PrimitiveValue value : PRIMITIVE_VALUES) + { + Object obj = value.getValue(); + Element root = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Object result = inConverter.convertToJava(root, value.getKlass()); + assertEquals(obj, result); + } + } + + + public void testConvertPrimitiveFormatXsd() throws Exception + { + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSD_FORMAT); + BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.EXPECT_XSD_FORMAT); + + for (PrimitiveValue value : PRIMITIVE_VALUES) + { + Object obj = value.getValue(); + Element root = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Object result = inConverter.convertToJava(root, value.getKlass()); + assertEquals(obj, result); + } + } + + + public void testConvertNullDefault() throws Exception + { + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Object result = inConverter.convertToJava(root, String.class); + assertNull(result); + } + + + public void testConvertNullUseAndRequireXsiNil() throws Exception + { + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSI_NIL); + BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_NIL); + + Element root = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Object result = inConverter.convertToJava(root, String.class); + assertNull(result); + } + + + public void testConvertNullFailureRequireXsiNil() throws Exception + { + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_NIL); + + Element root = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + assertConversionFailure("accepted DOM with null entry but no xsi:nil", + inConverter, root, String.class); + } + + + public void testPrimitiveArrayDefault() throws Exception + { + int[] data = new int[] { 1, 2, 4, 5 }; + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + int[] result = inConverter.convertToJava(root, int[].class); + assertTrue(Arrays.equals(data, result)); + } + + + public void testStringListDefault() throws Exception + { + List<String> data = Arrays.asList("foo", "bar", "baz"); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + List<String> result = inConverter.convertToJava(root, List.class); + assertEquals(data, result); + } + + + // demonstrates that the list will be read as List<String> even though + // it was written as List<Integer> + public void testIntegerListDefault() throws Exception + { + List<Integer> data = Arrays.asList(1, 2, 3); + assert(data.get(0) instanceof Integer); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + List<?> result = inConverter.convertToJava(root, List.class); + assertTrue(result instanceof List); + assertTrue(result.get(0) instanceof String); + } + + + // demonstrates that you don't need to require xsi:type to use it + public void testIntegerListWithXsiType() throws Exception + { + List<Integer> data = Arrays.asList(1, 2, 3); + assert(data.get(0) instanceof Integer); + + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + List<?> result = inConverter.convertToJava(root, List.class); + assertEquals(data, result); + } + + + // demonstrates that the caller drives the inbound conversion + public void testConvertListToSortedSet() throws Exception + { + List<String> data = Arrays.asList("foo", "bar", "baz", "bar"); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Set<?> result = inConverter.convertToJava(root, SortedSet.class); + Iterator<?> itx = result.iterator(); + assertEquals("bar", itx.next()); + assertEquals("baz", itx.next()); + assertEquals("foo", itx.next()); + assertFalse(itx.hasNext()); + } + + + public void testMapDefault() throws Exception + { + Map<String,String> data = new HashMap<String,String>(); + data.put("foo", "argle"); + data.put("bar", "bargle"); + data.put("baz", "bazgle"); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + DomAsserts.assertCount(3, root, "/test/data"); + DomAsserts.assertCount(1, root, "/test/data[@key='foo']"); + DomAsserts.assertEquals("argle", root, "/test/data[@key='foo']"); + + Map<?,?> result = inConverter.convertToJava(root, Map.class); + assertEquals(data, result); + } + + + // demonstrates that the input converter handles either format by default + public void testMapIntrospected() throws Exception + { + Map<String,String> data = new HashMap<String,String>(); + data.put("foo", "argle"); + data.put("bar", "bargle"); + data.put("baz", "bazgle"); + + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.INTROSPECT_MAPS); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + DomAsserts.assertCount(0, root, "/test/data"); + DomAsserts.assertCount(1, root, "/test/foo"); + DomAsserts.assertEquals("argle", root, "/test/foo"); + + Map<?,?> result = inConverter.convertToJava(root, Map.class); + assertEquals(data, result); + } + + + public void testSimpleBeanDefault() throws Exception + { + SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + SimpleBean result = inConverter.convertToJava(root, SimpleBean.class); + data.assertEquals(result); + } + + + public void testSimpleBeanRequireXsiType() throws Exception + { + SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + + BeanConverter outconverter1 = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); + BeanConverter outconverter2 = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_TYPE); + + Element valid = outconverter1.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(valid.getOwnerDocument())); + + SimpleBean result = inConverter.convertToJava(valid, SimpleBean.class); + data.assertEquals(result); + + Element invalid = outconverter2.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(invalid.getOwnerDocument())); + + assertConversionFailure("converter requiring xsi:type accepted XML without", + inConverter, invalid, SimpleBean.class); + } + + + public void testListOfSimpleBeanWithXsiTypeAndNulls() throws Exception + { + SimpleBean bean1 = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + SimpleBean bean2 = new SimpleBean("zyx", 987, null, false); + List<SimpleBean> data = Arrays.asList(bean1, bean2); + + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + List<SimpleBean> result = inConverter.convertToJava(root, List.class); + assertEquals(2, result.size()); + bean1.assertEquals(result.get(0)); + bean2.assertEquals(result.get(1)); + } + + + // another demonstration that caller drives input conversion + // ... and note that we don't care about xsi:type in this case + public void testListOfSimpleBeanToArrayOfSame() throws Exception + { + SimpleBean bean1 = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + SimpleBean bean2 = new SimpleBean("zyx", 987, null, false); + List<SimpleBean> data = Arrays.asList(bean1, bean2); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + SimpleBean[] result = inConverter.convertToJava(root, SimpleBean[].class); + assertEquals(2, result.length); + bean1.assertEquals(result[0]); + bean2.assertEquals(result[1]); + } + + + public void testCompoundBeanDefault() throws Exception + { + CompoundBean data = new CompoundBean( + new SimpleBean("abc", 123, new BigDecimal("456.789"), true), + new int[] { 1, 5, 7, 9 }, + Arrays.asList("foo", "bar", "baz")); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + CompoundBean result = inConverter.convertToJava(root, CompoundBean.class); + data.assertEquals(result); + } + + + public void testSimpleBeanWithNamespace() throws Exception + { + SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "urn:foo", "bar:test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Element child = DomUtil.getChild(root, "sval"); + assertEquals("urn:foo", child.getNamespaceURI()); + assertEquals("bar", child.getPrefix()); + + SimpleBean result = inConverter.convertToJava(root, SimpleBean.class); + data.assertEquals(result); + } + + + // this one is here just for coverage + public void testSimpleBeanFromDocument() throws Exception + { + SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Document dom = outConverter.convertToXml(data, "test").getOwnerDocument(); +// System.out.println(OutputUtil.compactString(dom)); + + SimpleBean result = inConverter.convertToJava(dom, SimpleBean.class); + data.assertEquals(result); + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-09-08 14:55:40
|
Revision: 122 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=122&view=rev Author: kdgregory Date: 2009-09-08 14:55:08 +0000 (Tue, 08 Sep 2009) Log Message: ----------- introduce AbstractConversionTestCase Modified Paths: -------------- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/AbstractBeanConverterTestCase.java Added Paths: ----------- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java Added: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java (rev 0) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java 2009-09-08 14:55:08 UTC (rev 122) @@ -0,0 +1,39 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter; + +import net.sf.practicalxml.AbstractTestCase; + + +/** + * A place to put common code for the conversion tests. + */ +public class AbstractConversionTestCase +extends AbstractTestCase +{ + public AbstractConversionTestCase(String testName) + { + super(testName); + } + +//---------------------------------------------------------------------------- +// Support Code +//---------------------------------------------------------------------------- + + +//---------------------------------------------------------------------------- +// Assertions +//---------------------------------------------------------------------------- +} Property changes on: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractConversionTestCase.java ___________________________________________________________________ Added: svn:executable + * Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/AbstractBeanConverterTestCase.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/AbstractBeanConverterTestCase.java 2009-09-08 14:43:34 UTC (rev 121) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/bean/AbstractBeanConverterTestCase.java 2009-09-08 14:55:08 UTC (rev 122) @@ -26,8 +26,8 @@ import junit.framework.Assert; -import net.sf.practicalxml.AbstractTestCase; import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.AbstractConversionTestCase; /** @@ -36,7 +36,7 @@ * instrospected. */ public abstract class AbstractBeanConverterTestCase -extends AbstractTestCase +extends AbstractConversionTestCase { protected AbstractBeanConverterTestCase(String name) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 20:25:55
|
Revision: 120 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=120&view=rev Author: kdgregory Date: 2009-08-18 20:25:47 +0000 (Tue, 18 Aug 2009) Log Message: ----------- refactoring - introduce ConversionStrings Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/DomUtilToo.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionStrings.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 19:54:24 UTC (rev 119) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 20:25:47 UTC (rev 120) @@ -19,6 +19,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.internal.ConversionStrings; import net.sf.practicalxml.converter.internal.DomUtilToo; @@ -168,7 +169,7 @@ { Element child = super.appendValue(name, type, value); if (child != null) - child.setAttribute("index", String.valueOf(_index++)); + child.setAttribute(ConversionStrings.AT_ARRAY_INDEX, String.valueOf(_index++)); return child; } } @@ -198,9 +199,9 @@ } else { - child = super.appendValue("data", type, value); + child = super.appendValue(ConversionStrings.EL_COLLECTION_ITEM, type, value); if (child != null) - child.setAttribute("key", name); + child.setAttribute(ConversionStrings.AT_MAP_KEY, name); } return child; } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 19:54:24 UTC (rev 119) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 20:25:47 UTC (rev 120) @@ -29,6 +29,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; import net.sf.practicalxml.converter.bean.Bean2XmlAppenders.*; +import net.sf.practicalxml.converter.internal.ConversionStrings; import net.sf.practicalxml.converter.internal.DomUtilToo; import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; @@ -117,12 +118,6 @@ } - private String getJavaXsiType(Object obj) - { - return "java:" + obj.getClass().getName(); - } - - /** * Introduces the XML Schema Instance namespace into the DOM tree using a * meaningless attribute. The Xerces serializer does not attempt to promote @@ -171,13 +166,13 @@ if (!array.getClass().isArray()) return false; - Element parent = appender.appendContainer(name, getJavaXsiType(array)); + Element parent = appender.appendContainer(name, DomUtilToo.getXsiTypeForJavaObject(array)); Appender childAppender = new IndexedAppender(parent, _options); int length = Array.getLength(array); for (int idx = 0 ; idx < length ; idx++) { Object value = Array.get(array, idx); - convert(value, "data", childAppender); + convert(value, ConversionStrings.EL_COLLECTION_ITEM, childAppender); } return true; } @@ -188,7 +183,7 @@ if (!(obj instanceof Map)) return false; - Element parent = appender.appendContainer(name, getJavaXsiType(obj)); + Element parent = appender.appendContainer(name, DomUtilToo.getXsiTypeForJavaObject(obj)); Appender childAppender = new MapAppender(parent, _options); for (Map.Entry<?,?> entry : ((Map<?,?>)obj).entrySet()) { @@ -203,11 +198,11 @@ if (!(obj instanceof Collection)) return false; - Element parent = appender.appendContainer(name, getJavaXsiType(obj)); + Element parent = appender.appendContainer(name, DomUtilToo.getXsiTypeForJavaObject(obj)); Appender childAppender = new IndexedAppender(parent, _options); for (Object value : (Collection<?>)obj) { - convert(value, "data", childAppender); + convert(value, ConversionStrings.EL_COLLECTION_ITEM, childAppender); } return true; } @@ -215,7 +210,7 @@ private boolean tryToConvertAsBean(Object bean, String name, Appender appender) { - Element parent = appender.appendContainer(name, getJavaXsiType(bean)); + Element parent = appender.appendContainer(name, DomUtilToo.getXsiTypeForJavaObject(bean)); Appender childAppender = new BasicAppender(parent, _options); try { Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 19:54:24 UTC (rev 119) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 20:25:47 UTC (rev 120) @@ -35,6 +35,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.internal.ConversionStrings; import net.sf.practicalxml.converter.internal.DomUtilToo; import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; import net.sf.practicalxml.internal.StringUtils; @@ -84,8 +85,6 @@ // Internal Conversion Methods //---------------------------------------------------------------------------- - - /** * Attempts to convert the passed DOM subtree into an object of the * specified class. Note that this version does not use generics, @@ -184,7 +183,7 @@ List<Element> children = DomUtil.getChildren(elem); for (Element child : children) { - String key = child.getAttribute("key"); + String key = child.getAttribute(ConversionStrings.AT_MAP_KEY); if (StringUtils.isEmpty(key)) key = DomUtil.getLocalName(child); Class<?> childClass = getClassFromXsiType(child); @@ -244,9 +243,9 @@ if (xsiType == null) return null; - if (xsiType.startsWith("java:")) + String javaType = DomUtilToo.getJavaClassFromXsiType(xsiType); + if (javaType != null) { - String javaType = xsiType.substring(5); try { return Class.forName(javaType); @@ -257,6 +256,7 @@ "invalid Java type specification: " + javaType, elem, ee); } } + return _helper.getJavaType(xsiType); } Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionStrings.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionStrings.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionStrings.java 2009-08-18 20:25:47 UTC (rev 120) @@ -0,0 +1,47 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.internal; + + +/** + * Contains constants for various string values used by the conversion + * routines. The goal is to have all converters use the same strings + * (without typos) in the same location. + */ +public class ConversionStrings +{ + /** + * Element name used to hold unnamed items from collections and arrays. + */ + public final static String EL_COLLECTION_ITEM = "data"; + + + /** + * Attribute used to hold the element index number for collections and arrays. + */ + public final static String AT_ARRAY_INDEX = "index"; + + + /** + * Attribute used to hold the item key value for maps. + */ + public final static String AT_MAP_KEY = "key"; + + + /** + * Used to prefix Java type names in an <code>xsi:type</code> attribute. + */ + public final static String JAVA_TYPE_PREFIX = "java:"; +} Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/DomUtilToo.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/DomUtilToo.java 2009-08-18 19:54:24 UTC (rev 119) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/DomUtilToo.java 2009-08-18 20:25:47 UTC (rev 120) @@ -27,7 +27,7 @@ * are not generally useful to anyone who isn't writing a converter. But if you * are writing a converter, you'll probably use them a lot ... * <p> - * Note: where methods in this class reference a namespaced element or attribute + * Note: where methods in this class reference a namespaced element or attribute * (eg, <code>xsi:type</code>), they do not use a prefix unless explicitly noted. * This prevents the possibility of collisions, where the same prefix is used * elsewhere in the DOM for elements not managed by the converter. A serializer @@ -36,44 +36,80 @@ public class DomUtilToo { /** + * Sets the <code>xsi:nil</code> attribute to the passed value. + */ + public static void setXsiNil(Element elem, boolean isNil) + { + String value = isNil ? "true" : "false"; + elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", value); + } + + + /** + * Returns the value of the <code>xsi:nil</code> attribute on the passed + * element, <code>false</code> if the attribute is not set. + */ + public static boolean getXsiNil(Element elem) + { + String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); + return attr.equals("true"); + } + + + /** * Sets the <code>xsi:type</code> attribute to the passed value. */ public static void setXsiType(Element elem, String xsiType) { elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", xsiType); } - - + + /** * Returns the value of the <code>xsi:type</code> attribute on the passed * element, <code>null</code> if the attribute is not set. */ public static String getXsiType(Element elem) - { + { String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); return StringUtils.isEmpty(xsiType) ? null : xsiType; } - - + + /** - * Sets the <code>xsi:nil</code> attribute to the passed value. + * Returns the Java classname corresponding to an <code>xsi:type</code> + * value, <code>null</code> if the attribute is missing or doesn't follow + * the pattern for Java type names. */ - public static void setXsiNil(Element elem, boolean isNil) + public static String getJavaClassFromXsiType(String xsiType) { - String value = isNil ? "true" : "false"; - elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", value); + if (!xsiType.startsWith(ConversionStrings.JAVA_TYPE_PREFIX)) + return null; + return xsiType.substring(ConversionStrings.JAVA_TYPE_PREFIX.length()); } - - + + /** - * Returns the value of the <code>xsi:nil</code> attribute on the passed - * element, <code>false</code> if the attribute is not set. + * Returns the type name to be stored in <code>xsi:type</code> for a Java + * class (this is a companion to {@link #getJavaClassFromXsiType}). */ - public static boolean getXsiNil(Element elem) + public static String getXsiTypeForJavaObject(Class<?> klass) { - String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); - return attr.equals("true"); + return ConversionStrings.JAVA_TYPE_PREFIX + klass.getName(); } + + + /** + * Returns the type name to be stored in <code>xsi:type</code> for a Java + * object (this is actually used more than the alternate version). Will + * return empty string if passed <code>null</code>. + */ + public static String getXsiTypeForJavaObject(Object obj) + { + return (obj == null) + ? "" + : getXsiTypeForJavaObject(obj.getClass()); + } } Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java 2009-08-18 19:54:24 UTC (rev 119) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java 2009-08-18 20:25:47 UTC (rev 120) @@ -700,10 +700,9 @@ public void testReadOnlyBean() throws Exception { - Xml2BeanDriver driver = new Xml2BeanDriver(); Element data = createTestData( element("sval", text("foo"))); - + Xml2BeanDriver driver = new Xml2BeanDriver(); assertConversionFailure("converted bean without setter", driver, data, ReadOnlyBean.class); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 19:54:39
|
Revision: 119 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=119&view=rev Author: kdgregory Date: 2009-08-18 19:54:24 +0000 (Tue, 18 Aug 2009) Log Message: ----------- remove unused file Removed Paths: ------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-18 19:50:39 UTC (rev 118) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-18 19:54:24 UTC (rev 119) @@ -1,190 +0,0 @@ -// Copyright 2008-2009 severally by the contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package net.sf.practicalxml.converter.bean; - -import java.util.Date; -import java.util.EnumSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.xml.XMLConstants; - -import org.w3c.dom.Element; - -import net.sf.practicalxml.DomUtil; -import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; -import net.sf.practicalxml.internal.StringUtils; - - -/** - * Invoked by {@link Xml2BeanDriver} to convert a DOM <code>Element</code> - * into the appropriate Java object. Unlike {@link Bean2XmlHandler}, there - * will only be one instance of this object created during conversion; all - * intermediate data can be held on the stack. - */ -public class Xml2BeanHandler -{ - private EnumSet<Xml2BeanOptions> _options; - private PrimitiveConversionHelper _primitiveHelper; - - - /** - * Public constructor, allowing various options specifications. - */ - public Xml2BeanHandler(Xml2BeanOptions... options) - { - _options = EnumSet.noneOf(Xml2BeanOptions.class); - for (Xml2BeanOptions option : options) - _options.add(option); - - _primitiveHelper = new PrimitiveConversionHelper(true); - } - - -//---------------------------------------------------------------------------- -// Public Methods -//---------------------------------------------------------------------------- - - public Boolean convertBoolean(Element elem) - { - return (Boolean)_primitiveHelper.parse(getText(elem), Boolean.class); - } - - - public Byte convertByte(Element elem) - { - return (Byte)_primitiveHelper.parse(getText(elem), Byte.class); - } - - - public Character convertCharacter(Element elem) - { - return (Character)_primitiveHelper.parse(getText(elem), Character.class); - } - - - public Date convertDate(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Double convertDouble(Element elem) - { - return (Double)_primitiveHelper.parse(getText(elem), Double.class); - } - - - public Float convertFloat(Element elem) - { - return (Float)_primitiveHelper.parse(getText(elem), Float.class); - } - - - public Integer convertInteger(Element elem) - { - return (Integer)_primitiveHelper.parse(getText(elem), Integer.class); - } - - - public Long convertLong(Element elem) - { - return (Long)_primitiveHelper.parse(getText(elem), Long.class); - } - - - public Number convertNumber(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Short convertShort(Element elem) - { - return (Short)_primitiveHelper.parse(getText(elem), Short.class); - } - - - public String convertString(Element elem) - { - return (String)_primitiveHelper.parse(getText(elem), String.class); - } - - - public List<?> convertList(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Set<?> convertSet(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Map<?,?> convertMap(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Object convertObject(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - - public Object[] convertObjectArray(Element elem) - { - throw new UnsupportedOperationException("not implemented yet"); - } - - -//---------------------------------------------------------------------------- -// Internals -//---------------------------------------------------------------------------- - - /** - * Returns the text from a passed element, applying any low-level options - * along the way. - */ - private String getText(Element elem) - { - String text = DomUtil.getText(elem); - if (_options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL) && StringUtils.isBlank(text)) - text = null; - validateXsiNil(elem, text); - return text; - } - - - /** - * Checks for elements that require <code>xsi:nil</code>, and throws if missing. - */ - private void validateXsiNil(Element elem, String text) - { - if (text != null) - return; - if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL)) - return; - - String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); - if ((attr == null) || !attr.equals("true")) - throw new ConversionException("empty element without required xsi:nil"); - } - -} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 19:50:47
|
Revision: 118 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=118&view=rev Author: kdgregory Date: 2009-08-18 19:50:39 +0000 (Tue, 18 Aug 2009) Log Message: ----------- refactoring Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/DomUtilToo.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 19:16:50 UTC (rev 117) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 19:50:39 UTC (rev 118) @@ -15,13 +15,11 @@ package net.sf.practicalxml.converter.bean; import java.util.EnumSet; - -import javax.xml.XMLConstants; - import org.w3c.dom.Element; import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.internal.DomUtilToo; /** @@ -95,7 +93,7 @@ protected void setType(Element elem, String type) { if (isOptionSet(Bean2XmlOptions.ADD_XSI_TYPE)) - elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", type); + DomUtilToo.setXsiType(elem, type); } protected void setValue(Element elem, String value) @@ -103,7 +101,7 @@ if (value != null) DomUtil.setText(elem, value); else if (isOptionSet(Bean2XmlOptions.XSI_NIL)) - elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "true"); + DomUtilToo.setXsiNil(elem, true); } } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 19:16:50 UTC (rev 117) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 19:50:39 UTC (rev 118) @@ -24,13 +24,12 @@ import java.util.EnumSet; import java.util.Map; -import javax.xml.XMLConstants; - import org.w3c.dom.Element; import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; import net.sf.practicalxml.converter.bean.Bean2XmlAppenders.*; +import net.sf.practicalxml.converter.internal.DomUtilToo; import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; @@ -145,7 +144,7 @@ if (_options.contains(Bean2XmlOptions.XSI_NIL) && !_options.contains(Bean2XmlOptions.ADD_XSI_TYPE)) { - root.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "false"); + DomUtilToo.setXsiNil(root, false); } } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 19:16:50 UTC (rev 117) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 19:50:39 UTC (rev 118) @@ -33,10 +33,9 @@ import java.util.TreeMap; import java.util.TreeSet; -import javax.xml.XMLConstants; - import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.internal.DomUtilToo; import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; import net.sf.practicalxml.internal.StringUtils; @@ -121,9 +120,8 @@ if (_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL)) { - String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); - if (!attr.equals("true")) - throw new ConversionException("missing xsi:nil", elem); + if (!DomUtilToo.getXsiNil(elem)) + throw new ConversionException("missing/false xsi:nil", elem); } return true; @@ -235,19 +233,6 @@ /** - * Returns the <code>xsi:type</code> attribute value, <code>null</code> if - * it's not set. - */ - private String getXsiType(Element elem) - { - String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); - return StringUtils.isEmpty(xsiType) - ? null - : xsiType; - } - - - /** * Examines an element's <code>xsi:type</code> attribute, if any, and * returns the Java class corresponding to it. Used when converting * collection types, which don't have type information that can be @@ -255,7 +240,7 @@ */ private Class<?> getClassFromXsiType(Element elem) { - String xsiType = getXsiType(elem); + String xsiType = DomUtilToo.getXsiType(elem); if (xsiType == null) return null; @@ -281,8 +266,8 @@ if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_TYPE)) return; - String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); - if (StringUtils.isEmpty(xsiType)) + String xsiType = DomUtilToo.getXsiType(elem); + if (xsiType == null) throw new ConversionException("missing xsi:type", elem); if (xsiType.equals(_helper.getXsdType(klass))) Added: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/DomUtilToo.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/DomUtilToo.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/DomUtilToo.java 2009-08-18 19:50:39 UTC (rev 118) @@ -0,0 +1,79 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.internal; + +import javax.xml.XMLConstants; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.internal.StringUtils; + + +/** + * Contains static utility methods and constants used by the conversion routines. + * These are way too specific to go into the top-level <code>DomUtil</code>, and + * are not generally useful to anyone who isn't writing a converter. But if you + * are writing a converter, you'll probably use them a lot ... + * <p> + * Note: where methods in this class reference a namespaced element or attribute + * (eg, <code>xsi:type</code>), they do not use a prefix unless explicitly noted. + * This prevents the possibility of collisions, where the same prefix is used + * elsewhere in the DOM for elements not managed by the converter. A serializer + * will pick an appropriate prefix for output. + */ +public class DomUtilToo +{ + /** + * Sets the <code>xsi:type</code> attribute to the passed value. + */ + public static void setXsiType(Element elem, String xsiType) + { + elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", xsiType); + } + + + /** + * Returns the value of the <code>xsi:type</code> attribute on the passed + * element, <code>null</code> if the attribute is not set. + */ + public static String getXsiType(Element elem) + { + String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); + return StringUtils.isEmpty(xsiType) + ? null + : xsiType; + } + + + /** + * Sets the <code>xsi:nil</code> attribute to the passed value. + */ + public static void setXsiNil(Element elem, boolean isNil) + { + String value = isNil ? "true" : "false"; + elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", value); + } + + + /** + * Returns the value of the <code>xsi:nil</code> attribute on the passed + * element, <code>false</code> if the attribute is not set. + */ + public static boolean getXsiNil(Element elem) + { + String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); + return attr.equals("true"); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 19:16:56
|
Revision: 117 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=117&view=rev Author: kdgregory Date: 2009-08-18 19:16:50 +0000 (Tue, 18 Aug 2009) Log Message: ----------- another class rename: ConversionHelper back to PrimitiveConversionHelper Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/PrimitiveConversionHelper.java Removed Paths: ------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 18:52:26 UTC (rev 116) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 19:16:50 UTC (rev 117) @@ -31,7 +31,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; import net.sf.practicalxml.converter.bean.Bean2XmlAppenders.*; -import net.sf.practicalxml.converter.internal.ConversionHelper; +import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; /** @@ -41,14 +41,14 @@ */ public class Bean2XmlDriver { - private ConversionHelper _helper; + private PrimitiveConversionHelper _helper; private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class); public Bean2XmlDriver(Bean2XmlOptions... options) { for (Bean2XmlOptions option : options) _options.add(option); - _helper = new ConversionHelper(shouldUseXsdFormatting()); + _helper = new PrimitiveConversionHelper(shouldUseXsdFormatting()); } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 18:52:26 UTC (rev 116) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 19:16:50 UTC (rev 117) @@ -37,7 +37,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.converter.internal.ConversionHelper; +import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; import net.sf.practicalxml.internal.StringUtils; import org.w3c.dom.Element; @@ -52,7 +52,7 @@ public class Xml2BeanDriver { private EnumSet<Xml2BeanOptions> _options; - private ConversionHelper _helper; + private PrimitiveConversionHelper _helper; private Map<Class<?>,Map<String,Method>> _introspectedClasses; @@ -62,7 +62,7 @@ for (Xml2BeanOptions option : options) _options.add(option); - _helper = new ConversionHelper(_options.contains(Xml2BeanOptions.EXPECT_XSD_FORMAT)); + _helper = new PrimitiveConversionHelper(_options.contains(Xml2BeanOptions.EXPECT_XSD_FORMAT)); _introspectedClasses = new HashMap<Class<?>,Map<String,Method>>(); } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-18 18:52:26 UTC (rev 116) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-18 19:16:50 UTC (rev 117) @@ -25,7 +25,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.converter.internal.ConversionHelper; +import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; import net.sf.practicalxml.internal.StringUtils; @@ -38,7 +38,7 @@ public class Xml2BeanHandler { private EnumSet<Xml2BeanOptions> _options; - private ConversionHelper _primitiveHelper; + private PrimitiveConversionHelper _primitiveHelper; /** @@ -50,7 +50,7 @@ for (Xml2BeanOptions option : options) _options.add(option); - _primitiveHelper = new ConversionHelper(true); + _primitiveHelper = new PrimitiveConversionHelper(true); } Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java 2009-08-18 18:52:26 UTC (rev 116) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java 2009-08-18 19:16:50 UTC (rev 117) @@ -1,480 +0,0 @@ -// Copyright 2008-2009 severally by the contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package net.sf.practicalxml.converter.internal; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import net.sf.practicalxml.XmlUtil; -import net.sf.practicalxml.converter.ConversionException; - - -/** - * Responsible for converting "primitive" types -- those with unambiguous - * string representations -- to/from such a representation. - */ -public class ConversionHelper -{ - private static Map<String,Class<?>> XSD_TYPE_TO_JAVA_CLASS - = new HashMap<String,Class<?>>(); - static - { - XSD_TYPE_TO_JAVA_CLASS.put("xsd:string", String.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:boolean", Boolean.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:byte", Byte.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:short", Short.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:int", Integer.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:long", Long.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:decimal", BigDecimal.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:dateTime", Date.class); - } - - - // this is not static because the helpers are inner classes - private Map<Class<?>,ConversionHandler<?>> _helpers - = new HashMap<Class<?>,ConversionHandler<?>>(); - { - _helpers.put(String.class, new StringConversionHandler()); - _helpers.put(Character.class, new CharacterConversionHandler()); - _helpers.put(Boolean.class, new BooleanConversionHandler()); - _helpers.put(Byte.class, new ByteConversionHandler()); - _helpers.put(Short.class, new ShortConversionHandler()); - _helpers.put(Integer.class, new IntegerConversionHandler()); - _helpers.put(Long.class, new LongConversionHandler()); - _helpers.put(Float.class, new FloatConversionHandler()); - _helpers.put(Double.class, new DoubleConversionHandler()); - _helpers.put(BigInteger.class, new BigIntegerConversionHandler()); - _helpers.put(BigDecimal.class, new BigDecimalConversionHandler()); - _helpers.put(Date.class, new DateConversionHandler()); - - _helpers.put(Boolean.TYPE, new BooleanConversionHandler()); - _helpers.put(Byte.TYPE, new ByteConversionHandler()); - _helpers.put(Short.TYPE, new ShortConversionHandler()); - _helpers.put(Integer.TYPE, new IntegerConversionHandler()); - _helpers.put(Long.TYPE, new LongConversionHandler()); - _helpers.put(Float.TYPE, new FloatConversionHandler()); - _helpers.put(Double.TYPE, new DoubleConversionHandler()); - } - - private boolean _useXsdFormatting; - - - /** - * Default constructor, which uses Java formatting. - */ - public ConversionHelper() - { - // nothing to see here - } - - - /** - * Constructor that allows selection of Java or XSD formatting. - */ - public ConversionHelper(boolean useXsdFormatting) - { - _useXsdFormatting = useXsdFormatting; - } - - -//---------------------------------------------------------------------------- -// Public Methods -//---------------------------------------------------------------------------- - - /** - * Returns the XSD type name to use for stringified objects of the - * specified class, <code>null</code> if this converter can't convert - * instances of the class. - */ - public String getXsdType(Class<?> klass) - { - ConversionHandler<?> helper = _helpers.get(klass); - return (helper == null) ? null : helper.getXsiType(); - } - - - /** - * Returns the Java type that best matches the given Schema type name, - * <code>null</code> if we do not have an appropriate mapping. - */ - public Class<?> getJavaType(String xsdTypename) - { - return XSD_TYPE_TO_JAVA_CLASS.get(xsdTypename); - } - - - /** - * Converts the passed object into its string representation, according - * to the options currently in effect. Passing <code>null</code> will - * return <code>null</code>. Throws {@link ConversionException} if - * unable to convert the passed object. - */ - public String stringify(Object obj) - { - if (obj == null) - return null; - - try - { - return getHelper(obj.getClass()).stringify(obj); - } - catch (Exception ee) - { - if (ee instanceof ConversionException) - throw (ConversionException)ee; - throw new ConversionException("unable to convert: " + obj, ee); - } - } - - - /** - * Parses the passed string into an object of the desired class. Passing - * <code>null</code> will return <code>null</code>, passing an empty - * string will typically throw a {@link ConversionException}. - */ - public Object parse(String str, Class<?> klass) - { - if (str == null) - return null; - - try - { - return getHelper(klass).parse(str); - } - catch (Exception ee) - { - if (ee instanceof ConversionException) - throw (ConversionException)ee; - throw new ConversionException("unable to parse: " + str, ee); - } - } - - -//---------------------------------------------------------------------------- -// Internals -//---------------------------------------------------------------------------- - - /** - * Returns the appropriate conversion helper or throws. - */ - @SuppressWarnings(value="unchecked") - private ConversionHandler getHelper(Class<?> klass) - { - ConversionHandler<?> helper = _helpers.get(klass); - if (helper == null) - throw new ConversionException("unable to get helper: " + klass.getName()); - return helper; - } - - - /** - * Each primitive class has its own conversion handler that is responsible - * for converting to/from a string representation. Handlers are guaranteed - * to receive non-null objects/strings. - * <p> - * This interface is parameterized so that the compiler will generate - * bridge methods for implementation classes. Elsewhere, we don't care - * about parameterization, so wildcard or drop it (see {@link #getHelper}). - * <p> - * Implementation classes are expected to be inner classes, so that they - * have access to configuration information (such as formatting rules). - * <p> - * Implementation classes are permitted to throw any exception; caller is - * expected to catch them and translate to a {@link ConversionException}. - */ - private static interface ConversionHandler<T> - { - public String getXsiType(); - public String stringify(T obj) throws Exception; - public T parse(String str) throws Exception; - } - - - private class StringConversionHandler - implements ConversionHandler<String> - { - public String getXsiType() - { - return "xsd:string"; - } - - public String stringify(String obj) - { - return String.valueOf(obj); - } - - public String parse(String str) - { - return str; - } - } - - - private class CharacterConversionHandler - implements ConversionHandler<Character> - { - private final Character NUL = Character.valueOf('\0'); - - public String getXsiType() - { - return "xsd:string"; - } - - public String stringify(Character obj) - { - if (obj.equals(NUL)) - return ""; - return obj.toString(); - } - - public Character parse(String str) - { - if (str.length() == 0) - return NUL; - if (str.length() > 1) - throw new ConversionException( - "attempted to convert multi-character string: \"" + str + "\""); - return Character.valueOf(str.charAt(0)); - } - } - - - private class BooleanConversionHandler - implements ConversionHandler<Boolean> - { - public String getXsiType() - { - return "xsd:boolean"; - } - - public String stringify(Boolean obj) - { - return _useXsdFormatting - ? XmlUtil.formatXsdBoolean(obj.booleanValue()) - : obj.toString(); - } - - public Boolean parse(String str) - { - return _useXsdFormatting - ? XmlUtil.parseXsdBoolean(str) - : Boolean.parseBoolean(str); - } - } - - - private class ByteConversionHandler - implements ConversionHandler<Byte> - { - public String getXsiType() - { - return "xsd:byte"; - } - - public String stringify(Byte obj) - { - return obj.toString(); - } - - public Byte parse(String str) - { - return Byte.valueOf(str.trim()); - } - } - - - private class ShortConversionHandler - implements ConversionHandler<Short> - { - public String getXsiType() - { - return "xsd:short"; - } - - public String stringify(Short obj) - { - return obj.toString(); - } - - public Short parse(String str) - { - return Short.valueOf(str.trim()); - } - } - - - private class IntegerConversionHandler - implements ConversionHandler<Integer> - { - public String getXsiType() - { - return "xsd:int"; - } - - public String stringify(Integer obj) - { - return obj.toString(); - } - - public Integer parse(String str) - { - return Integer.valueOf(str.trim()); - } - } - - - private class LongConversionHandler - implements ConversionHandler<Long> - { - public String getXsiType() - { - return "xsd:long"; - } - - public String stringify(Long obj) - { - return obj.toString(); - } - - public Long parse(String str) - { - return Long.valueOf(str.trim()); - } - } - - - private class FloatConversionHandler - implements ConversionHandler<Float> - { - public String getXsiType() - { - return "xsd:decimal"; - } - - public String stringify(Float obj) - { - return _useXsdFormatting - ? XmlUtil.formatXsdDecimal(obj) - : obj.toString(); - } - - public Float parse(String str) - { - return Float.valueOf(str.trim()); - } - } - - - private class DoubleConversionHandler - implements ConversionHandler<Double> - { - public String getXsiType() - { - return "xsd:decimal"; - } - - public String stringify(Double obj) - { - return _useXsdFormatting - ? XmlUtil.formatXsdDecimal(obj) - : obj.toString(); - } - - public Double parse(String str) - { - return Double.valueOf(str.trim()); - } - } - - - private class BigIntegerConversionHandler - implements ConversionHandler<BigInteger> - { - public String getXsiType() - { - return "xsd:decimal"; - } - - public String stringify(BigInteger obj) - { - return obj.toString(); - } - - public BigInteger parse(String str) - { - return new BigInteger(str.trim()); - } - } - - - private class BigDecimalConversionHandler - implements ConversionHandler<BigDecimal> - { - public String getXsiType() - { - return "xsd:decimal"; - } - - public String stringify(BigDecimal obj) - { - return obj.toString(); - } - - public BigDecimal parse(String str) - { - return new BigDecimal(str.trim()); - } - } - - - private class DateConversionHandler - implements ConversionHandler<Date> - { - // format as specified by Date.toString() JavaDoc - private DateFormat _defaultFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); - - public String getXsiType() - { - return "xsd:dateTime"; - } - - public String stringify(Date obj) - { - return _useXsdFormatting - ? XmlUtil.formatXsdDatetime(obj) - : obj.toString(); - } - - public Date parse(String str) - throws ParseException - { - if (_useXsdFormatting) - return XmlUtil.parseXsdDatetime(str); - else - { - synchronized (_defaultFormat) - { - return _defaultFormat.parse(str); - } - } - } - } -} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/PrimitiveConversionHelper.java (from rev 116, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/PrimitiveConversionHelper.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/PrimitiveConversionHelper.java 2009-08-18 19:16:50 UTC (rev 117) @@ -0,0 +1,480 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.internal; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import net.sf.practicalxml.XmlUtil; +import net.sf.practicalxml.converter.ConversionException; + + +/** + * Responsible for converting "primitive" types -- those with unambiguous + * string representations -- to/from such a representation. + */ +public class PrimitiveConversionHelper +{ + private static Map<String,Class<?>> XSD_TYPE_TO_JAVA_CLASS + = new HashMap<String,Class<?>>(); + static + { + XSD_TYPE_TO_JAVA_CLASS.put("xsd:string", String.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:boolean", Boolean.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:byte", Byte.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:short", Short.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:int", Integer.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:long", Long.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:decimal", BigDecimal.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:dateTime", Date.class); + } + + + // this is not static because the helpers are inner classes + private Map<Class<?>,ConversionHandler<?>> _helpers + = new HashMap<Class<?>,ConversionHandler<?>>(); + { + _helpers.put(String.class, new StringConversionHandler()); + _helpers.put(Character.class, new CharacterConversionHandler()); + _helpers.put(Boolean.class, new BooleanConversionHandler()); + _helpers.put(Byte.class, new ByteConversionHandler()); + _helpers.put(Short.class, new ShortConversionHandler()); + _helpers.put(Integer.class, new IntegerConversionHandler()); + _helpers.put(Long.class, new LongConversionHandler()); + _helpers.put(Float.class, new FloatConversionHandler()); + _helpers.put(Double.class, new DoubleConversionHandler()); + _helpers.put(BigInteger.class, new BigIntegerConversionHandler()); + _helpers.put(BigDecimal.class, new BigDecimalConversionHandler()); + _helpers.put(Date.class, new DateConversionHandler()); + + _helpers.put(Boolean.TYPE, new BooleanConversionHandler()); + _helpers.put(Byte.TYPE, new ByteConversionHandler()); + _helpers.put(Short.TYPE, new ShortConversionHandler()); + _helpers.put(Integer.TYPE, new IntegerConversionHandler()); + _helpers.put(Long.TYPE, new LongConversionHandler()); + _helpers.put(Float.TYPE, new FloatConversionHandler()); + _helpers.put(Double.TYPE, new DoubleConversionHandler()); + } + + private boolean _useXsdFormatting; + + + /** + * Default constructor, which uses Java formatting. + */ + public PrimitiveConversionHelper() + { + // nothing to see here + } + + + /** + * Constructor that allows selection of Java or XSD formatting. + */ + public PrimitiveConversionHelper(boolean useXsdFormatting) + { + _useXsdFormatting = useXsdFormatting; + } + + +//---------------------------------------------------------------------------- +// Public Methods +//---------------------------------------------------------------------------- + + /** + * Returns the XSD type name to use for stringified objects of the + * specified class, <code>null</code> if this converter can't convert + * instances of the class. + */ + public String getXsdType(Class<?> klass) + { + ConversionHandler<?> helper = _helpers.get(klass); + return (helper == null) ? null : helper.getXsiType(); + } + + + /** + * Returns the Java type that best matches the given Schema type name, + * <code>null</code> if we do not have an appropriate mapping. + */ + public Class<?> getJavaType(String xsdTypename) + { + return XSD_TYPE_TO_JAVA_CLASS.get(xsdTypename); + } + + + /** + * Converts the passed object into its string representation, according + * to the options currently in effect. Passing <code>null</code> will + * return <code>null</code>. Throws {@link ConversionException} if + * unable to convert the passed object. + */ + public String stringify(Object obj) + { + if (obj == null) + return null; + + try + { + return getHelper(obj.getClass()).stringify(obj); + } + catch (Exception ee) + { + if (ee instanceof ConversionException) + throw (ConversionException)ee; + throw new ConversionException("unable to convert: " + obj, ee); + } + } + + + /** + * Parses the passed string into an object of the desired class. Passing + * <code>null</code> will return <code>null</code>, passing an empty + * string will typically throw a {@link ConversionException}. + */ + public Object parse(String str, Class<?> klass) + { + if (str == null) + return null; + + try + { + return getHelper(klass).parse(str); + } + catch (Exception ee) + { + if (ee instanceof ConversionException) + throw (ConversionException)ee; + throw new ConversionException("unable to parse: " + str, ee); + } + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + /** + * Returns the appropriate conversion helper or throws. + */ + @SuppressWarnings(value="unchecked") + private ConversionHandler getHelper(Class<?> klass) + { + ConversionHandler<?> helper = _helpers.get(klass); + if (helper == null) + throw new ConversionException("unable to get helper: " + klass.getName()); + return helper; + } + + + /** + * Each primitive class has its own conversion handler that is responsible + * for converting to/from a string representation. Handlers are guaranteed + * to receive non-null objects/strings. + * <p> + * This interface is parameterized so that the compiler will generate + * bridge methods for implementation classes. Elsewhere, we don't care + * about parameterization, so wildcard or drop it (see {@link #getHelper}). + * <p> + * Implementation classes are expected to be inner classes, so that they + * have access to configuration information (such as formatting rules). + * <p> + * Implementation classes are permitted to throw any exception; caller is + * expected to catch them and translate to a {@link ConversionException}. + */ + private static interface ConversionHandler<T> + { + public String getXsiType(); + public String stringify(T obj) throws Exception; + public T parse(String str) throws Exception; + } + + + private class StringConversionHandler + implements ConversionHandler<String> + { + public String getXsiType() + { + return "xsd:string"; + } + + public String stringify(String obj) + { + return String.valueOf(obj); + } + + public String parse(String str) + { + return str; + } + } + + + private class CharacterConversionHandler + implements ConversionHandler<Character> + { + private final Character NUL = Character.valueOf('\0'); + + public String getXsiType() + { + return "xsd:string"; + } + + public String stringify(Character obj) + { + if (obj.equals(NUL)) + return ""; + return obj.toString(); + } + + public Character parse(String str) + { + if (str.length() == 0) + return NUL; + if (str.length() > 1) + throw new ConversionException( + "attempted to convert multi-character string: \"" + str + "\""); + return Character.valueOf(str.charAt(0)); + } + } + + + private class BooleanConversionHandler + implements ConversionHandler<Boolean> + { + public String getXsiType() + { + return "xsd:boolean"; + } + + public String stringify(Boolean obj) + { + return _useXsdFormatting + ? XmlUtil.formatXsdBoolean(obj.booleanValue()) + : obj.toString(); + } + + public Boolean parse(String str) + { + return _useXsdFormatting + ? XmlUtil.parseXsdBoolean(str) + : Boolean.parseBoolean(str); + } + } + + + private class ByteConversionHandler + implements ConversionHandler<Byte> + { + public String getXsiType() + { + return "xsd:byte"; + } + + public String stringify(Byte obj) + { + return obj.toString(); + } + + public Byte parse(String str) + { + return Byte.valueOf(str.trim()); + } + } + + + private class ShortConversionHandler + implements ConversionHandler<Short> + { + public String getXsiType() + { + return "xsd:short"; + } + + public String stringify(Short obj) + { + return obj.toString(); + } + + public Short parse(String str) + { + return Short.valueOf(str.trim()); + } + } + + + private class IntegerConversionHandler + implements ConversionHandler<Integer> + { + public String getXsiType() + { + return "xsd:int"; + } + + public String stringify(Integer obj) + { + return obj.toString(); + } + + public Integer parse(String str) + { + return Integer.valueOf(str.trim()); + } + } + + + private class LongConversionHandler + implements ConversionHandler<Long> + { + public String getXsiType() + { + return "xsd:long"; + } + + public String stringify(Long obj) + { + return obj.toString(); + } + + public Long parse(String str) + { + return Long.valueOf(str.trim()); + } + } + + + private class FloatConversionHandler + implements ConversionHandler<Float> + { + public String getXsiType() + { + return "xsd:decimal"; + } + + public String stringify(Float obj) + { + return _useXsdFormatting + ? XmlUtil.formatXsdDecimal(obj) + : obj.toString(); + } + + public Float parse(String str) + { + return Float.valueOf(str.trim()); + } + } + + + private class DoubleConversionHandler + implements ConversionHandler<Double> + { + public String getXsiType() + { + return "xsd:decimal"; + } + + public String stringify(Double obj) + { + return _useXsdFormatting + ? XmlUtil.formatXsdDecimal(obj) + : obj.toString(); + } + + public Double parse(String str) + { + return Double.valueOf(str.trim()); + } + } + + + private class BigIntegerConversionHandler + implements ConversionHandler<BigInteger> + { + public String getXsiType() + { + return "xsd:decimal"; + } + + public String stringify(BigInteger obj) + { + return obj.toString(); + } + + public BigInteger parse(String str) + { + return new BigInteger(str.trim()); + } + } + + + private class BigDecimalConversionHandler + implements ConversionHandler<BigDecimal> + { + public String getXsiType() + { + return "xsd:decimal"; + } + + public String stringify(BigDecimal obj) + { + return obj.toString(); + } + + public BigDecimal parse(String str) + { + return new BigDecimal(str.trim()); + } + } + + + private class DateConversionHandler + implements ConversionHandler<Date> + { + // format as specified by Date.toString() JavaDoc + private DateFormat _defaultFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); + + public String getXsiType() + { + return "xsd:dateTime"; + } + + public String stringify(Date obj) + { + return _useXsdFormatting + ? XmlUtil.formatXsdDatetime(obj) + : obj.toString(); + } + + public Date parse(String str) + throws ParseException + { + if (_useXsdFormatting) + return XmlUtil.parseXsdDatetime(str); + else + { + synchronized (_defaultFormat) + { + return _defaultFormat.parse(str); + } + } + } + } +} Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java 2009-08-18 18:52:26 UTC (rev 116) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java 2009-08-18 19:16:50 UTC (rev 117) @@ -18,7 +18,7 @@ import java.math.BigInteger; import java.util.Date; -import net.sf.practicalxml.converter.internal.ConversionHelper; +import net.sf.practicalxml.converter.internal.PrimitiveConversionHelper; public class TestConversionHelper @@ -36,7 +36,7 @@ private void assertFailsConversionToObject( String message, - ConversionHelper helper, + PrimitiveConversionHelper helper, String str, Class<?> klass) { @@ -58,7 +58,7 @@ public void testClassToXsdType() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:string", helper.getXsdType(String.class)); assertEquals("xsd:string", helper.getXsdType(Character.class)); @@ -72,7 +72,7 @@ public void testUnknownClass() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertNull(helper.getXsdType(Class.class)); } @@ -80,7 +80,7 @@ public void testConvertNull() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertNull(helper.stringify(null)); assertNull(helper.parse(null, Object.class)); @@ -89,7 +89,7 @@ public void testConvertString() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:string", helper.getXsdType(String.class)); @@ -103,7 +103,7 @@ public void testConvertCharacter() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:string", helper.getXsdType(Character.class)); @@ -123,7 +123,7 @@ public void testConvertBooleanDefault() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); // default boolean conversion is compatible with XSD type def assertEquals("xsd:boolean", helper.getXsdType(Boolean.class)); @@ -143,7 +143,7 @@ public void testConvertBooleanXsd() throws Exception { - ConversionHelper helper = new ConversionHelper(true); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true); assertEquals("xsd:boolean", helper.getXsdType(Boolean.class)); @@ -167,7 +167,7 @@ public void testConvertByte() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:byte", helper.getXsdType(Byte.class)); @@ -205,7 +205,7 @@ public void testConvertShort() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:short", helper.getXsdType(Short.class)); @@ -243,7 +243,7 @@ public void testConvertInteger() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:int", helper.getXsdType(Integer.class)); @@ -281,7 +281,7 @@ public void testConvertLong() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:long", helper.getXsdType(Long.class)); @@ -319,7 +319,7 @@ public void testConvertFloatDefault() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); // default float conversion is compatible with XSD type def assertEquals("xsd:decimal", helper.getXsdType(Float.class)); @@ -351,7 +351,7 @@ public void testConvertFloatXsd() throws Exception { - ConversionHelper helper = new ConversionHelper(true); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true); assertEquals("xsd:decimal", helper.getXsdType(Float.class)); @@ -381,7 +381,7 @@ public void testConvertDoubleDefault() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); // default double conversion is compatible with XSD type def assertEquals("xsd:decimal", helper.getXsdType(Double.class)); @@ -413,7 +413,7 @@ public void testConvertDoubleXsd() throws Exception { - ConversionHelper helper = new ConversionHelper(true); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true); assertEquals("xsd:decimal", helper.getXsdType(Double.class)); @@ -444,7 +444,7 @@ public void testConvertBigInteger() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:decimal", helper.getXsdType(BigInteger.class)); @@ -474,7 +474,7 @@ public void testConvertBigDecimal() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); assertEquals("xsd:decimal", helper.getXsdType(BigDecimal.class)); @@ -500,7 +500,7 @@ public void testConvertDateDefault() throws Exception { - ConversionHelper helper = new ConversionHelper(); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(); // default date conversion is NOT compatible with XSD type def, // so this is misleading @@ -525,7 +525,7 @@ public void testConvertDateXsd() throws Exception { - ConversionHelper helper = new ConversionHelper(true); + PrimitiveConversionHelper helper = new PrimitiveConversionHelper(true); assertEquals("xsd:dateTime", helper.getXsdType(Date.class)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 18:52:34
|
Revision: 116 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=116&view=rev Author: kdgregory Date: 2009-08-18 18:52:26 +0000 (Tue, 18 Aug 2009) Log Message: ----------- add xpath into ConversionException Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionException.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionException.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionException.java 2009-08-18 18:19:50 UTC (rev 115) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionException.java 2009-08-18 18:52:26 UTC (rev 116) @@ -14,16 +14,38 @@ package net.sf.practicalxml.converter; +import org.w3c.dom.Element; +import net.sf.practicalxml.DomUtil; + + /** * A runtime exception thrown for any conversion error. Will always have a - * message, and typically contains a wrapped exception. + * message, and typically contains a wrapped exception. If thrown during + * a conversion <code>from</code> XML, should also have the absolute XPath + * of the node that caused the problem, and this is appended to the message. */ public class ConversionException extends RuntimeException { private static final long serialVersionUID = 1L; + private String _xpath; + + + public ConversionException(String message, Element elem, Throwable cause) + { + super(message, cause); + _xpath = DomUtil.getAbsolutePath(elem); + } + + public ConversionException(String message, Element elem) + { + super(message); + _xpath = DomUtil.getAbsolutePath(elem); + } + + public ConversionException(String message, Throwable cause) { super(message, cause); @@ -33,4 +55,13 @@ { super(message); } + + + @Override + public String toString() + { + return (_xpath != null) + ? super.getMessage() + " (" + _xpath + ")" + : super.getMessage(); + } } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 18:19:50 UTC (rev 115) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 18:52:26 UTC (rev 116) @@ -136,7 +136,7 @@ } catch (Exception ee) { - throw new ConversionException("unable to append child", ee); + throw new ConversionException("unable to append child: " + name, _parent, ee); } } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 18:19:50 UTC (rev 115) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 18:52:26 UTC (rev 116) @@ -123,8 +123,7 @@ { String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); if (!attr.equals("true")) - throw new ConversionException( - "missing xsi:nil: " + DomUtil.getAbsolutePath(elem)); + throw new ConversionException("missing xsi:nil", elem); } return true; @@ -137,8 +136,7 @@ return null; if (hasElementChildren(elem)) - throw new ConversionException( - "expecting primitive; has children: " + DomUtil.getAbsolutePath(elem)); + throw new ConversionException("expecting primitive; has children", elem); return _helper.parse(getText(elem), klass); } @@ -271,9 +269,7 @@ catch (ClassNotFoundException ee) { throw new ConversionException( - "invalid Java type specification (" + javaType + "): " - + DomUtil.getAbsolutePath(elem), - ee); + "invalid Java type specification: " + javaType, elem, ee); } } return _helper.getJavaType(xsiType); @@ -287,8 +283,7 @@ String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); if (StringUtils.isEmpty(xsiType)) - throw new ConversionException( - "missing xsi:type: " + DomUtil.getAbsolutePath(elem)); + throw new ConversionException("missing xsi:type", elem); if (xsiType.equals(_helper.getXsdType(klass))) return; @@ -298,8 +293,8 @@ return; throw new ConversionException( - "invalid xsi:type (\"" + xsiType + "\" for " + klass.getName() + "): " - + DomUtil.getAbsolutePath(elem)); + "invalid xsi:type: \"" + xsiType + "\" for " + klass.getName(), + elem); } @@ -325,9 +320,7 @@ Method setter = methodMap.get(DomUtil.getLocalName(child)); if ((setter == null) && !_options.contains(Xml2BeanOptions.IGNORE_MISSING_PROPERTIES)) { - throw new ConversionException( - "can't find property setter in " + beanKlass.getName() + ": " - + DomUtil.getAbsolutePath(child)); + throw new ConversionException("can't find property setter", child); } return setter; @@ -347,9 +340,9 @@ methodMap.put(propDesc.getName(), setter); } } - catch (IntrospectionException e) + catch (IntrospectionException ee) { - throw new ConversionException("unable to introspect", e); + throw new ConversionException("unable to introspect", ee); } _introspectedClasses.put(klass, methodMap); @@ -399,9 +392,7 @@ } catch (Exception ee) { - throw new ConversionException( - "unable to instantiate bean: " + DomUtil.getAbsolutePath(elem), - ee); + throw new ConversionException("unable to instantiate bean", elem, ee); } } @@ -414,9 +405,7 @@ } catch (Exception ee) { - throw new ConversionException( - "unable to set property: " + DomUtil.getAbsolutePath(elem), - ee); + throw new ConversionException("unable to set property", elem, ee); } } } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-18 18:19:50 UTC (rev 115) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-18 18:52:26 UTC (rev 116) @@ -14,17 +14,8 @@ package net.sf.practicalxml.converter.bean; -import net.sf.practicalxml.DomUtil; -import net.sf.practicalxml.XmlException; -import net.sf.practicalxml.XmlUtil; -import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.converter.internal.ConversionHelper; -import net.sf.practicalxml.internal.StringUtils; - -import java.util.Arrays; import java.util.Date; import java.util.EnumSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -32,7 +23,12 @@ import org.w3c.dom.Element; +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.internal.ConversionHelper; +import net.sf.practicalxml.internal.StringUtils; + /** * Invoked by {@link Xml2BeanDriver} to convert a DOM <code>Element</code> * into the appropriate Java object. Unlike {@link Bean2XmlHandler}, there Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java 2009-08-18 18:19:50 UTC (rev 115) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java 2009-08-18 18:52:26 UTC (rev 116) @@ -33,7 +33,7 @@ */ public class ConversionHelper { - private static Map<String,Class<?>> XSD_TYPE_TO_JAVA_CLASS + private static Map<String,Class<?>> XSD_TYPE_TO_JAVA_CLASS = new HashMap<String,Class<?>>(); static { @@ -46,8 +46,8 @@ XSD_TYPE_TO_JAVA_CLASS.put("xsd:decimal", BigDecimal.class); XSD_TYPE_TO_JAVA_CLASS.put("xsd:dateTime", Date.class); } - - + + // this is not static because the helpers are inner classes private Map<Class<?>,ConversionHandler<?>> _helpers = new HashMap<Class<?>,ConversionHandler<?>>(); @@ -64,7 +64,7 @@ _helpers.put(BigInteger.class, new BigIntegerConversionHandler()); _helpers.put(BigDecimal.class, new BigDecimalConversionHandler()); _helpers.put(Date.class, new DateConversionHandler()); - + _helpers.put(Boolean.TYPE, new BooleanConversionHandler()); _helpers.put(Byte.TYPE, new ByteConversionHandler()); _helpers.put(Short.TYPE, new ShortConversionHandler()); @@ -109,8 +109,8 @@ ConversionHandler<?> helper = _helpers.get(klass); return (helper == null) ? null : helper.getXsiType(); } - - + + /** * Returns the Java type that best matches the given Schema type name, * <code>null</code> if we do not have an appropriate mapping. Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java 2009-08-18 18:19:50 UTC (rev 115) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java 2009-08-18 18:52:26 UTC (rev 116) @@ -66,7 +66,7 @@ } - private void assertConversionException(String message, Bean2XmlDriver driver, Object data) + private void assertConversionFailure(String message, Bean2XmlDriver driver, Object data) { try { @@ -74,7 +74,9 @@ fail(message); } catch (ConversionException ee) - { /* success */ } + { +// System.out.println(ee); + } } @@ -337,8 +339,8 @@ data.put("%key1%", new Integer(123)); data.put("%key2%", new Integer(456)); - assertConversionException("converted map with invalid key under INTROSPECT_MAPS", - driver, data); + assertConversionFailure("converted map with invalid key under INTROSPECT_MAPS", + driver, data); } Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-08-18 18:19:50 UTC (rev 115) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-08-18 18:52:26 UTC (rev 116) @@ -56,7 +56,7 @@ // Support Code //---------------------------------------------------------------------------- - private static void assertConversionError( + private static void assertConversionFailure( String message, BeanConverter converter, Element elem, Class<?> klass) { try @@ -65,7 +65,9 @@ fail(message); } catch (ConversionException ee) - { /* success */ } + { +// System.out.println(ee); + } } //---------------------------------------------------------------------------- @@ -156,7 +158,7 @@ Element root = outConverter.convertToXml(null, "test"); // System.out.println(OutputUtil.compactString(root.getOwnerDocument())); - assertConversionError("accepted DOM with null entry but no xsi:nil", + assertConversionFailure("accepted DOM with null entry but no xsi:nil", inConverter, root, String.class); } @@ -324,7 +326,7 @@ Element invalid = outconverter2.convertToXml(data, "test"); // System.out.println(OutputUtil.compactString(invalid.getOwnerDocument())); - assertConversionError("converter requiring xsi:type accepted XML without", + assertConversionFailure("converter requiring xsi:type accepted XML without", inConverter, invalid, SimpleBean.class); } Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java 2009-08-18 18:19:50 UTC (rev 115) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java 2009-08-18 18:52:26 UTC (rev 116) @@ -70,7 +70,7 @@ } - private static void assertConversionError( + private static void assertConversionFailure( String message, Xml2BeanDriver driver, Element elem, Class<?> klass) { try @@ -79,7 +79,9 @@ fail(message); } catch (ConversionException ee) - { /* success */ } + { +// System.out.println(ee); + } } @@ -133,8 +135,8 @@ assertEquals("foo", dst); Element invalid = createTestData(text("foo")); - assertConversionError("converted element missing xsi:type", - driver, invalid, String.class); + assertConversionFailure("converted element missing xsi:type", + driver, invalid, String.class); } @@ -143,8 +145,8 @@ Xml2BeanDriver driver = new Xml2BeanDriver(Xml2BeanOptions.REQUIRE_XSI_TYPE); Element invalid = createTestData(text("foo"), xsiType("xsd:int")); - assertConversionError("converted element with incorrect xsi:type", - driver, invalid, String.class); + assertConversionFailure("converted element with incorrect xsi:type", + driver, invalid, String.class); } @@ -153,8 +155,8 @@ Xml2BeanDriver driver = new Xml2BeanDriver(); Element invalid = createTestData(text("foo"), element("bar")); - assertConversionError("converted primitive with element content", - driver, invalid, String.class); + assertConversionFailure("converted primitive with element content", + driver, invalid, String.class); } @@ -175,8 +177,8 @@ assertNull(driver.convert(valid, String.class)); Element invalid = createTestData(); - assertConversionError("able to convert null data with REQUIRE_XSI_NIL set", - driver, invalid, String.class); + assertConversionFailure("able to convert null data with REQUIRE_XSI_NIL set", + driver, invalid, String.class); } @@ -210,8 +212,8 @@ assertNull(driver.convert(valid, String.class)); Element invalid = createTestData(text(" \t ")); - assertConversionError("able to convert blank data with CONVERT_BLANK_AS_NULL and REQUIRE_XSI_NIL set", - driver, invalid, String.class); + assertConversionFailure("able to convert blank data with CONVERT_BLANK_AS_NULL and REQUIRE_XSI_NIL set", + driver, invalid, String.class); } @@ -249,8 +251,8 @@ Element invalid = createTestData( element("foo", text("12"), xsiType("xsd:int"))); - assertConversionError("able to convert with REQUIRE_XSI_TYPE set", - driver, invalid, int[].class); + assertConversionFailure("able to convert with REQUIRE_XSI_TYPE set", + driver, invalid, int[].class); } @@ -319,8 +321,8 @@ Element data = createTestData( element("a", text("foo"), xsiType("java:foo"))); - assertConversionError("converted unknown type", - driver, data, List.class); + assertConversionFailure("converted unknown type", + driver, data, List.class); } @@ -557,8 +559,8 @@ element("ival", text("123"), xsiType("xsd:int")), element("dval", text("123.456"),xsiType("xsd:decimal")), element("bval", text("true"), xsiType("xsd:boolean"))); - assertConversionError("didn't throw when missing xsi:type on top level", - driver, invalid1, SimpleBean.class); + assertConversionFailure("didn't throw when missing xsi:type on top level", + driver, invalid1, SimpleBean.class); Element invalid2 = createTestData( xsiType("java:" + SimpleBean.class.getName()), @@ -566,8 +568,8 @@ element("ival", text("123")), element("dval", text("123.456")), element("bval", text("true"))); - assertConversionError("didn't throw when missing xsi:type on component level", - driver, invalid2, SimpleBean.class); + assertConversionFailure("didn't throw when missing xsi:type on component level", + driver, invalid2, SimpleBean.class); } @@ -580,7 +582,7 @@ Xml2BeanDriver driver1 = new Xml2BeanDriver(); - assertConversionError("converted bean when extra fields present in XML", + assertConversionFailure("converted bean when extra fields present in XML", driver1, data, SimpleBean.class); Xml2BeanDriver driver2 = new Xml2BeanDriver(Xml2BeanOptions.IGNORE_MISSING_PROPERTIES); @@ -702,7 +704,7 @@ Element data = createTestData( element("sval", text("foo"))); - assertConversionError("converted bean without setter", - driver, data, ReadOnlyBean.class); + assertConversionFailure("converted bean without setter", + driver, data, ReadOnlyBean.class); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 18:19:58
|
Revision: 115 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=115&view=rev Author: kdgregory Date: 2009-08-18 18:19:50 +0000 (Tue, 18 Aug 2009) Log Message: ----------- bugfix: introspected maps with invalid keys Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 18:10:39 UTC (rev 114) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 18:19:50 UTC (rev 115) @@ -21,6 +21,7 @@ import org.w3c.dom.Element; import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.ConversionException; /** @@ -126,10 +127,17 @@ if (shouldSkip(value)) return null; - Element child = DomUtil.appendChildInheritNamespace(_parent, name); - setType(child, type); - setValue(child, value); - return child; + try + { + Element child = DomUtil.appendChildInheritNamespace(_parent, name); + setType(child, type); + setValue(child, value); + return child; + } + catch (Exception ee) + { + throw new ConversionException("unable to append child", ee); + } } public Element appendContainer(String name, String type) Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java 2009-08-18 18:10:39 UTC (rev 114) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java 2009-08-18 18:19:50 UTC (rev 115) @@ -66,6 +66,18 @@ } + private void assertConversionException(String message, Bean2XmlDriver driver, Object data) + { + try + { + driver.convert(data, "test"); + fail(message); + } + catch (ConversionException ee) + { /* success */ } + } + + //---------------------------------------------------------------------------- // Test Cases //---------------------------------------------------------------------------- @@ -317,6 +329,19 @@ } + public void testConvertMapIntrospectWithInvalidKey() throws Exception + { + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.INTROSPECT_MAPS); + + Map<String,Integer> data = new TreeMap<String,Integer>(); + data.put("%key1%", new Integer(123)); + data.put("%key2%", new Integer(456)); + + assertConversionException("converted map with invalid key under INTROSPECT_MAPS", + driver, data); + } + + public void testConvertSimpleBeanDefault() throws Exception { Bean2XmlDriver driver = new Bean2XmlDriver(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 18:10:51
|
Revision: 114 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=114&view=rev Author: kdgregory Date: 2009-08-18 18:10:39 +0000 (Tue, 18 Aug 2009) Log Message: ----------- rename conversion options; remove unused options Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 17:57:48 UTC (rev 113) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-18 18:10:39 UTC (rev 114) @@ -93,7 +93,7 @@ protected void setType(Element elem, String type) { - if (isOptionSet(Bean2XmlOptions.XSI_TYPE)) + if (isOptionSet(Bean2XmlOptions.ADD_XSI_TYPE)) elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", type); } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 17:57:48 UTC (rev 113) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 18:10:39 UTC (rev 114) @@ -114,7 +114,7 @@ private boolean shouldUseXsdFormatting() { return _options.contains(Bean2XmlOptions.XSD_FORMAT) - || _options.contains(Bean2XmlOptions.XSI_TYPE); + || _options.contains(Bean2XmlOptions.ADD_XSI_TYPE); } @@ -143,7 +143,7 @@ private void doXsiNamespaceHack(Element root) { if (_options.contains(Bean2XmlOptions.XSI_NIL) - && !_options.contains(Bean2XmlOptions.XSI_TYPE)) + && !_options.contains(Bean2XmlOptions.ADD_XSI_TYPE)) { root.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "false"); } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java 2009-08-18 17:57:48 UTC (rev 113) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java 2009-08-18 18:10:39 UTC (rev 114) @@ -17,39 +17,40 @@ /** * Options used by {@link Bean2XmlHandler} to control the structure of the - * DOM tree. + * generated DOM tree. */ public enum Bean2XmlOptions { /** - * Outputs values using formats defined by XML Schema, rather than Java's - * <code>String.valueOf()</code> method. Note that these formats are not - * flagged in the element, so sender and receiver will have to agree on - * the format. - */ - XSD_FORMAT, - - /** * Will add an <code>xsi:type</code> attribute to each element. For values * covered by the XML Schema simple types, this attribute's value will be - * "<code>xsd:XXX</code>", where XXX is the XSD type name. For complex - * types, this attribute's value will be "<code>java:XXX</code>", where - * XXX is the fully-qualified classname. + * "<code>xsd:TYPE</code>", where TYPE is the XSD type name. For complex + * types, this attribute's value will be "<code>java:TYPE</code>", where + * TYPE is the fully-qualified classname. * <p> * <em>This option implies {@link #XSD_FORMAT} for simple types</em>. */ - XSI_TYPE, + ADD_XSI_TYPE, /** - * Report null values using the <code>xsi:nil="true"</code> attribute. If - * not present, null values are ignored, and not added to DOM tree. + * Output maps in an "introspected" format, where the name of each item + * is the map key (rather than "data"), and the "key" attribute is omitted. + * If any key is not a valid XML identifier, the converter will throw. */ + INTROSPECT_MAPS, + + /** + * Add null values into the tree, as an element without content, with the + * attribute <code>xsi:nil</code> set to "true". If not present, null + * values are ignored, and not added to DOM tree. + */ XSI_NIL, /** - * Output maps in an "introspected" format, where the name of each item - * is the map key (rather than "data"), and the "key" attribute is omitted. - * If any key is not a valid XML identifier, the converter will throw. + * Outputs values using formats defined by XML Schema, rather than Java's + * <code>String.valueOf()</code> method. Note that these formats are not + * flagged in the element, so sender and receiver will have to agree on + * the format. */ - INTROSPECT_MAPS + XSD_FORMAT } Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java 2009-08-18 17:57:48 UTC (rev 113) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java 2009-08-18 18:10:39 UTC (rev 114) @@ -29,13 +29,11 @@ */ CONVERT_BLANK_AS_NULL, - /** * Expect data (in particular, dates) to be formatted per XML Schema spec. */ EXPECT_XSD_FORMAT, - /** * If present, the converter ignores elements that don't correspond to * settable properties of the bean. @@ -44,21 +42,12 @@ /** - * If present, the converter will look for a setter method taking a - * <code>String</code>, in preference to a non-string method returned - * from the bean introspector. - */ - PREFER_STRING_SETTER, - - - /** * If present, the converter requires an <code>xsi:nil</code> attribute * on any empty nodes, and will throw if it's not present. Default is to * treat empty nodes as <code>null</code>. */ REQUIRE_XSI_NIL, - /** * If present, the converter requires an <code>xsi:type</code> attribute * on each element, and will throw if it's not present. Default behavior Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java 2009-08-18 17:57:48 UTC (rev 113) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java 2009-08-18 18:10:39 UTC (rev 114) @@ -72,7 +72,7 @@ { Element root = DomUtil.newDocument("root"); - Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.XSI_TYPE)); + Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.ADD_XSI_TYPE)); Element child = appender.appendValue("foo", "bar", "baz"); assertNull(child.getNamespaceURI()); @@ -128,7 +128,7 @@ { Element root = DomUtil.newDocument("root"); - Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.XSI_TYPE)); + Appender appender = new BasicAppender(root, useOptions(Bean2XmlOptions.ADD_XSI_TYPE)); Element child0 = appender.appendContainer("foo", "bar"); Element child1 = appender.appendContainer("argle", "bargle"); @@ -297,7 +297,7 @@ { Element root = DomUtil.newDocument("root"); - Appender appender = new DirectAppender(root, useOptions(Bean2XmlOptions.XSI_TYPE)); + Appender appender = new DirectAppender(root, useOptions(Bean2XmlOptions.ADD_XSI_TYPE)); Element child = appender.appendValue("foo", "bar", "baz"); assertSame(root, child); @@ -361,7 +361,7 @@ { Element root = DomUtil.newDocument("root"); - Appender appender = new DirectAppender(root, useOptions(Bean2XmlOptions.XSI_TYPE)); + Appender appender = new DirectAppender(root, useOptions(Bean2XmlOptions.ADD_XSI_TYPE)); Element child0 = appender.appendContainer("foo", "bar"); assertSame(root, child0); Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java 2009-08-18 17:57:48 UTC (rev 113) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java 2009-08-18 18:10:39 UTC (rev 114) @@ -128,7 +128,7 @@ public void testConvertPrimitivesWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.ADD_XSI_TYPE); for (int idx = 0 ; idx < PRIMITIVE_VALUES.length ; idx++) { PrimitiveValue value = PRIMITIVE_VALUES[idx]; @@ -164,7 +164,7 @@ public void testConvertPrimitiveArrayWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.ADD_XSI_TYPE); int[] data = new int[] { 1, 2, 3 }; Element root = driver.convert(data, "test"); @@ -188,7 +188,7 @@ public void testConvertStringArrayWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.ADD_XSI_TYPE); String[] data = new String[] { "foo", "bar", "baz" }; Element root = driver.convert(data, "test"); @@ -212,7 +212,7 @@ public void testConvertStringListWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.ADD_XSI_TYPE); List<String> data = new ArrayList<String>(); data.add("foo"); @@ -240,7 +240,7 @@ public void testConvertStringSetWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.ADD_XSI_TYPE); // TreeSet means that the data will be re-ordered Set<String> data = new TreeSet<String>(); @@ -269,7 +269,7 @@ public void testConvertMapDefaultWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.ADD_XSI_TYPE); // TreeMap means that the data will be re-ordered Map<String,Integer> data = new TreeMap<String,Integer>(); @@ -294,7 +294,7 @@ public void testConvertMapIntrospectWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.INTROSPECT_MAPS, Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.INTROSPECT_MAPS, Bean2XmlOptions.ADD_XSI_TYPE); // TreeMap means that the data will be re-ordered Map<String,Integer> data = new TreeMap<String,Integer>(); @@ -335,7 +335,7 @@ public void testConvertSimpleBeanWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.ADD_XSI_TYPE); SimpleBean bean = new SimpleBean("zippy", 123, new BigDecimal("456.78"), true); Element root = driver.convert(bean, "test"); @@ -383,7 +383,7 @@ public void testConvertSimpleBeanXsiNilAndXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_NIL, Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_NIL, Bean2XmlOptions.ADD_XSI_TYPE); SimpleBean bean = new SimpleBean(null, 123, null, true); Element root = driver.convert(bean, "test"); @@ -399,7 +399,7 @@ public void testConvertBeanArrayWithXsiType() throws Exception { - Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.XSI_TYPE); + Bean2XmlDriver driver = new Bean2XmlDriver(Bean2XmlOptions.ADD_XSI_TYPE); SimpleBean bean1 = new SimpleBean("foo", 123, new BigDecimal("456.789"), true); SimpleBean bean2 = new SimpleBean("bar", 456, new BigDecimal("0.0"), false); Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-08-18 17:57:48 UTC (rev 113) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-08-18 18:10:39 UTC (rev 114) @@ -216,7 +216,7 @@ List<Integer> data = Arrays.asList(1, 2, 3); assert(data.get(0) instanceof Integer); - BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSI_TYPE); + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); BeanConverter inConverter = new BeanConverter(); Element root = outConverter.convertToXml(data, "test"); @@ -311,7 +311,7 @@ { SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); - BeanConverter outconverter1 = new BeanConverter(Bean2XmlOptions.XSI_TYPE); + BeanConverter outconverter1 = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); BeanConverter outconverter2 = new BeanConverter(); BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_TYPE); @@ -335,7 +335,7 @@ SimpleBean bean2 = new SimpleBean("zyx", 987, null, false); List<SimpleBean> data = Arrays.asList(bean1, bean2); - BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSI_TYPE); + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.ADD_XSI_TYPE); BeanConverter inConverter = new BeanConverter(); Element root = outConverter.convertToXml(data, "test"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 17:57:56
|
Revision: 113 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=113&view=rev Author: kdgregory Date: 2009-08-18 17:57:48 +0000 (Tue, 18 Aug 2009) Log Message: ----------- create internals package, put ConversionHelper in it Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java Removed Paths: ------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java Deleted: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java 2009-08-18 17:41:38 UTC (rev 112) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java 2009-08-18 17:57:48 UTC (rev 113) @@ -1,479 +0,0 @@ -// Copyright 2008-2009 severally by the contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package net.sf.practicalxml.converter; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import net.sf.practicalxml.XmlUtil; - - -/** - * Responsible for converting "primitive" types -- those with unambiguous - * string representations -- to/from such a representation. - */ -public class ConversionHelper -{ - private static Map<String,Class<?>> XSD_TYPE_TO_JAVA_CLASS - = new HashMap<String,Class<?>>(); - static - { - XSD_TYPE_TO_JAVA_CLASS.put("xsd:string", String.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:boolean", Boolean.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:byte", Byte.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:short", Short.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:int", Integer.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:long", Long.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:decimal", BigDecimal.class); - XSD_TYPE_TO_JAVA_CLASS.put("xsd:dateTime", Date.class); - } - - - // this is not static because the helpers are inner classes - private Map<Class<?>,ConversionHandler<?>> _helpers - = new HashMap<Class<?>,ConversionHandler<?>>(); - { - _helpers.put(String.class, new StringConversionHandler()); - _helpers.put(Character.class, new CharacterConversionHandler()); - _helpers.put(Boolean.class, new BooleanConversionHandler()); - _helpers.put(Byte.class, new ByteConversionHandler()); - _helpers.put(Short.class, new ShortConversionHandler()); - _helpers.put(Integer.class, new IntegerConversionHandler()); - _helpers.put(Long.class, new LongConversionHandler()); - _helpers.put(Float.class, new FloatConversionHandler()); - _helpers.put(Double.class, new DoubleConversionHandler()); - _helpers.put(BigInteger.class, new BigIntegerConversionHandler()); - _helpers.put(BigDecimal.class, new BigDecimalConversionHandler()); - _helpers.put(Date.class, new DateConversionHandler()); - - _helpers.put(Boolean.TYPE, new BooleanConversionHandler()); - _helpers.put(Byte.TYPE, new ByteConversionHandler()); - _helpers.put(Short.TYPE, new ShortConversionHandler()); - _helpers.put(Integer.TYPE, new IntegerConversionHandler()); - _helpers.put(Long.TYPE, new LongConversionHandler()); - _helpers.put(Float.TYPE, new FloatConversionHandler()); - _helpers.put(Double.TYPE, new DoubleConversionHandler()); - } - - private boolean _useXsdFormatting; - - - /** - * Default constructor, which uses Java formatting. - */ - public ConversionHelper() - { - // nothing to see here - } - - - /** - * Constructor that allows selection of Java or XSD formatting. - */ - public ConversionHelper(boolean useXsdFormatting) - { - _useXsdFormatting = useXsdFormatting; - } - - -//---------------------------------------------------------------------------- -// Public Methods -//---------------------------------------------------------------------------- - - /** - * Returns the XSD type name to use for stringified objects of the - * specified class, <code>null</code> if this converter can't convert - * instances of the class. - */ - public String getXsdType(Class<?> klass) - { - ConversionHandler<?> helper = _helpers.get(klass); - return (helper == null) ? null : helper.getXsiType(); - } - - - /** - * Returns the Java type that best matches the given Schema type name, - * <code>null</code> if we do not have an appropriate mapping. - */ - public Class<?> getJavaType(String xsdTypename) - { - return XSD_TYPE_TO_JAVA_CLASS.get(xsdTypename); - } - - - /** - * Converts the passed object into its string representation, according - * to the options currently in effect. Passing <code>null</code> will - * return <code>null</code>. Throws {@link ConversionException} if - * unable to convert the passed object. - */ - public String stringify(Object obj) - { - if (obj == null) - return null; - - try - { - return getHelper(obj.getClass()).stringify(obj); - } - catch (Exception ee) - { - if (ee instanceof ConversionException) - throw (ConversionException)ee; - throw new ConversionException("unable to convert: " + obj, ee); - } - } - - - /** - * Parses the passed string into an object of the desired class. Passing - * <code>null</code> will return <code>null</code>, passing an empty - * string will typically throw a {@link ConversionException}. - */ - public Object parse(String str, Class<?> klass) - { - if (str == null) - return null; - - try - { - return getHelper(klass).parse(str); - } - catch (Exception ee) - { - if (ee instanceof ConversionException) - throw (ConversionException)ee; - throw new ConversionException("unable to parse: " + str, ee); - } - } - - -//---------------------------------------------------------------------------- -// Internals -//---------------------------------------------------------------------------- - - /** - * Returns the appropriate conversion helper or throws. - */ - @SuppressWarnings(value="unchecked") - private ConversionHandler getHelper(Class<?> klass) - { - ConversionHandler<?> helper = _helpers.get(klass); - if (helper == null) - throw new ConversionException("unable to get helper: " + klass.getName()); - return helper; - } - - - /** - * Each primitive class has its own conversion handler that is responsible - * for converting to/from a string representation. Handlers are guaranteed - * to receive non-null objects/strings. - * <p> - * This interface is parameterized so that the compiler will generate - * bridge methods for implementation classes. Elsewhere, we don't care - * about parameterization, so wildcard or drop it (see {@link #getHelper}). - * <p> - * Implementation classes are expected to be inner classes, so that they - * have access to configuration information (such as formatting rules). - * <p> - * Implementation classes are permitted to throw any exception; caller is - * expected to catch them and translate to a {@link ConversionException}. - */ - private static interface ConversionHandler<T> - { - public String getXsiType(); - public String stringify(T obj) throws Exception; - public T parse(String str) throws Exception; - } - - - private class StringConversionHandler - implements ConversionHandler<String> - { - public String getXsiType() - { - return "xsd:string"; - } - - public String stringify(String obj) - { - return String.valueOf(obj); - } - - public String parse(String str) - { - return str; - } - } - - - private class CharacterConversionHandler - implements ConversionHandler<Character> - { - private final Character NUL = Character.valueOf('\0'); - - public String getXsiType() - { - return "xsd:string"; - } - - public String stringify(Character obj) - { - if (obj.equals(NUL)) - return ""; - return obj.toString(); - } - - public Character parse(String str) - { - if (str.length() == 0) - return NUL; - if (str.length() > 1) - throw new ConversionException( - "attempted to convert multi-character string: \"" + str + "\""); - return Character.valueOf(str.charAt(0)); - } - } - - - private class BooleanConversionHandler - implements ConversionHandler<Boolean> - { - public String getXsiType() - { - return "xsd:boolean"; - } - - public String stringify(Boolean obj) - { - return _useXsdFormatting - ? XmlUtil.formatXsdBoolean(obj.booleanValue()) - : obj.toString(); - } - - public Boolean parse(String str) - { - return _useXsdFormatting - ? XmlUtil.parseXsdBoolean(str) - : Boolean.parseBoolean(str); - } - } - - - private class ByteConversionHandler - implements ConversionHandler<Byte> - { - public String getXsiType() - { - return "xsd:byte"; - } - - public String stringify(Byte obj) - { - return obj.toString(); - } - - public Byte parse(String str) - { - return Byte.valueOf(str.trim()); - } - } - - - private class ShortConversionHandler - implements ConversionHandler<Short> - { - public String getXsiType() - { - return "xsd:short"; - } - - public String stringify(Short obj) - { - return obj.toString(); - } - - public Short parse(String str) - { - return Short.valueOf(str.trim()); - } - } - - - private class IntegerConversionHandler - implements ConversionHandler<Integer> - { - public String getXsiType() - { - return "xsd:int"; - } - - public String stringify(Integer obj) - { - return obj.toString(); - } - - public Integer parse(String str) - { - return Integer.valueOf(str.trim()); - } - } - - - private class LongConversionHandler - implements ConversionHandler<Long> - { - public String getXsiType() - { - return "xsd:long"; - } - - public String stringify(Long obj) - { - return obj.toString(); - } - - public Long parse(String str) - { - return Long.valueOf(str.trim()); - } - } - - - private class FloatConversionHandler - implements ConversionHandler<Float> - { - public String getXsiType() - { - return "xsd:decimal"; - } - - public String stringify(Float obj) - { - return _useXsdFormatting - ? XmlUtil.formatXsdDecimal(obj) - : obj.toString(); - } - - public Float parse(String str) - { - return Float.valueOf(str.trim()); - } - } - - - private class DoubleConversionHandler - implements ConversionHandler<Double> - { - public String getXsiType() - { - return "xsd:decimal"; - } - - public String stringify(Double obj) - { - return _useXsdFormatting - ? XmlUtil.formatXsdDecimal(obj) - : obj.toString(); - } - - public Double parse(String str) - { - return Double.valueOf(str.trim()); - } - } - - - private class BigIntegerConversionHandler - implements ConversionHandler<BigInteger> - { - public String getXsiType() - { - return "xsd:decimal"; - } - - public String stringify(BigInteger obj) - { - return obj.toString(); - } - - public BigInteger parse(String str) - { - return new BigInteger(str.trim()); - } - } - - - private class BigDecimalConversionHandler - implements ConversionHandler<BigDecimal> - { - public String getXsiType() - { - return "xsd:decimal"; - } - - public String stringify(BigDecimal obj) - { - return obj.toString(); - } - - public BigDecimal parse(String str) - { - return new BigDecimal(str.trim()); - } - } - - - private class DateConversionHandler - implements ConversionHandler<Date> - { - // format as specified by Date.toString() JavaDoc - private DateFormat _defaultFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); - - public String getXsiType() - { - return "xsd:dateTime"; - } - - public String stringify(Date obj) - { - return _useXsdFormatting - ? XmlUtil.formatXsdDatetime(obj) - : obj.toString(); - } - - public Date parse(String str) - throws ParseException - { - if (_useXsdFormatting) - return XmlUtil.parseXsdDatetime(str); - else - { - synchronized (_defaultFormat) - { - return _defaultFormat.parse(str); - } - } - } - } -} Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 17:41:38 UTC (rev 112) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-18 17:57:48 UTC (rev 113) @@ -30,8 +30,8 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.converter.ConversionHelper; import net.sf.practicalxml.converter.bean.Bean2XmlAppenders.*; +import net.sf.practicalxml.converter.internal.ConversionHelper; /** Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 17:41:38 UTC (rev 112) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-18 17:57:48 UTC (rev 113) @@ -37,7 +37,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.converter.ConversionHelper; +import net.sf.practicalxml.converter.internal.ConversionHelper; import net.sf.practicalxml.internal.StringUtils; import org.w3c.dom.Element; Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-18 17:41:38 UTC (rev 112) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-18 17:57:48 UTC (rev 113) @@ -18,7 +18,7 @@ import net.sf.practicalxml.XmlException; import net.sf.practicalxml.XmlUtil; import net.sf.practicalxml.converter.ConversionException; -import net.sf.practicalxml.converter.ConversionHelper; +import net.sf.practicalxml.converter.internal.ConversionHelper; import net.sf.practicalxml.internal.StringUtils; import java.util.Arrays; Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java (from rev 110, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/ConversionHelper.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/internal/ConversionHelper.java 2009-08-18 17:57:48 UTC (rev 113) @@ -0,0 +1,480 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.internal; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import net.sf.practicalxml.XmlUtil; +import net.sf.practicalxml.converter.ConversionException; + + +/** + * Responsible for converting "primitive" types -- those with unambiguous + * string representations -- to/from such a representation. + */ +public class ConversionHelper +{ + private static Map<String,Class<?>> XSD_TYPE_TO_JAVA_CLASS + = new HashMap<String,Class<?>>(); + static + { + XSD_TYPE_TO_JAVA_CLASS.put("xsd:string", String.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:boolean", Boolean.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:byte", Byte.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:short", Short.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:int", Integer.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:long", Long.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:decimal", BigDecimal.class); + XSD_TYPE_TO_JAVA_CLASS.put("xsd:dateTime", Date.class); + } + + + // this is not static because the helpers are inner classes + private Map<Class<?>,ConversionHandler<?>> _helpers + = new HashMap<Class<?>,ConversionHandler<?>>(); + { + _helpers.put(String.class, new StringConversionHandler()); + _helpers.put(Character.class, new CharacterConversionHandler()); + _helpers.put(Boolean.class, new BooleanConversionHandler()); + _helpers.put(Byte.class, new ByteConversionHandler()); + _helpers.put(Short.class, new ShortConversionHandler()); + _helpers.put(Integer.class, new IntegerConversionHandler()); + _helpers.put(Long.class, new LongConversionHandler()); + _helpers.put(Float.class, new FloatConversionHandler()); + _helpers.put(Double.class, new DoubleConversionHandler()); + _helpers.put(BigInteger.class, new BigIntegerConversionHandler()); + _helpers.put(BigDecimal.class, new BigDecimalConversionHandler()); + _helpers.put(Date.class, new DateConversionHandler()); + + _helpers.put(Boolean.TYPE, new BooleanConversionHandler()); + _helpers.put(Byte.TYPE, new ByteConversionHandler()); + _helpers.put(Short.TYPE, new ShortConversionHandler()); + _helpers.put(Integer.TYPE, new IntegerConversionHandler()); + _helpers.put(Long.TYPE, new LongConversionHandler()); + _helpers.put(Float.TYPE, new FloatConversionHandler()); + _helpers.put(Double.TYPE, new DoubleConversionHandler()); + } + + private boolean _useXsdFormatting; + + + /** + * Default constructor, which uses Java formatting. + */ + public ConversionHelper() + { + // nothing to see here + } + + + /** + * Constructor that allows selection of Java or XSD formatting. + */ + public ConversionHelper(boolean useXsdFormatting) + { + _useXsdFormatting = useXsdFormatting; + } + + +//---------------------------------------------------------------------------- +// Public Methods +//---------------------------------------------------------------------------- + + /** + * Returns the XSD type name to use for stringified objects of the + * specified class, <code>null</code> if this converter can't convert + * instances of the class. + */ + public String getXsdType(Class<?> klass) + { + ConversionHandler<?> helper = _helpers.get(klass); + return (helper == null) ? null : helper.getXsiType(); + } + + + /** + * Returns the Java type that best matches the given Schema type name, + * <code>null</code> if we do not have an appropriate mapping. + */ + public Class<?> getJavaType(String xsdTypename) + { + return XSD_TYPE_TO_JAVA_CLASS.get(xsdTypename); + } + + + /** + * Converts the passed object into its string representation, according + * to the options currently in effect. Passing <code>null</code> will + * return <code>null</code>. Throws {@link ConversionException} if + * unable to convert the passed object. + */ + public String stringify(Object obj) + { + if (obj == null) + return null; + + try + { + return getHelper(obj.getClass()).stringify(obj); + } + catch (Exception ee) + { + if (ee instanceof ConversionException) + throw (ConversionException)ee; + throw new ConversionException("unable to convert: " + obj, ee); + } + } + + + /** + * Parses the passed string into an object of the desired class. Passing + * <code>null</code> will return <code>null</code>, passing an empty + * string will typically throw a {@link ConversionException}. + */ + public Object parse(String str, Class<?> klass) + { + if (str == null) + return null; + + try + { + return getHelper(klass).parse(str); + } + catch (Exception ee) + { + if (ee instanceof ConversionException) + throw (ConversionException)ee; + throw new ConversionException("unable to parse: " + str, ee); + } + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + /** + * Returns the appropriate conversion helper or throws. + */ + @SuppressWarnings(value="unchecked") + private ConversionHandler getHelper(Class<?> klass) + { + ConversionHandler<?> helper = _helpers.get(klass); + if (helper == null) + throw new ConversionException("unable to get helper: " + klass.getName()); + return helper; + } + + + /** + * Each primitive class has its own conversion handler that is responsible + * for converting to/from a string representation. Handlers are guaranteed + * to receive non-null objects/strings. + * <p> + * This interface is parameterized so that the compiler will generate + * bridge methods for implementation classes. Elsewhere, we don't care + * about parameterization, so wildcard or drop it (see {@link #getHelper}). + * <p> + * Implementation classes are expected to be inner classes, so that they + * have access to configuration information (such as formatting rules). + * <p> + * Implementation classes are permitted to throw any exception; caller is + * expected to catch them and translate to a {@link ConversionException}. + */ + private static interface ConversionHandler<T> + { + public String getXsiType(); + public String stringify(T obj) throws Exception; + public T parse(String str) throws Exception; + } + + + private class StringConversionHandler + implements ConversionHandler<String> + { + public String getXsiType() + { + return "xsd:string"; + } + + public String stringify(String obj) + { + return String.valueOf(obj); + } + + public String parse(String str) + { + return str; + } + } + + + private class CharacterConversionHandler + implements ConversionHandler<Character> + { + private final Character NUL = Character.valueOf('\0'); + + public String getXsiType() + { + return "xsd:string"; + } + + public String stringify(Character obj) + { + if (obj.equals(NUL)) + return ""; + return obj.toString(); + } + + public Character parse(String str) + { + if (str.length() == 0) + return NUL; + if (str.length() > 1) + throw new ConversionException( + "attempted to convert multi-character string: \"" + str + "\""); + return Character.valueOf(str.charAt(0)); + } + } + + + private class BooleanConversionHandler + implements ConversionHandler<Boolean> + { + public String getXsiType() + { + return "xsd:boolean"; + } + + public String stringify(Boolean obj) + { + return _useXsdFormatting + ? XmlUtil.formatXsdBoolean(obj.booleanValue()) + : obj.toString(); + } + + public Boolean parse(String str) + { + return _useXsdFormatting + ? XmlUtil.parseXsdBoolean(str) + : Boolean.parseBoolean(str); + } + } + + + private class ByteConversionHandler + implements ConversionHandler<Byte> + { + public String getXsiType() + { + return "xsd:byte"; + } + + public String stringify(Byte obj) + { + return obj.toString(); + } + + public Byte parse(String str) + { + return Byte.valueOf(str.trim()); + } + } + + + private class ShortConversionHandler + implements ConversionHandler<Short> + { + public String getXsiType() + { + return "xsd:short"; + } + + public String stringify(Short obj) + { + return obj.toString(); + } + + public Short parse(String str) + { + return Short.valueOf(str.trim()); + } + } + + + private class IntegerConversionHandler + implements ConversionHandler<Integer> + { + public String getXsiType() + { + return "xsd:int"; + } + + public String stringify(Integer obj) + { + return obj.toString(); + } + + public Integer parse(String str) + { + return Integer.valueOf(str.trim()); + } + } + + + private class LongConversionHandler + implements ConversionHandler<Long> + { + public String getXsiType() + { + return "xsd:long"; + } + + public String stringify(Long obj) + { + return obj.toString(); + } + + public Long parse(String str) + { + return Long.valueOf(str.trim()); + } + } + + + private class FloatConversionHandler + implements ConversionHandler<Float> + { + public String getXsiType() + { + return "xsd:decimal"; + } + + public String stringify(Float obj) + { + return _useXsdFormatting + ? XmlUtil.formatXsdDecimal(obj) + : obj.toString(); + } + + public Float parse(String str) + { + return Float.valueOf(str.trim()); + } + } + + + private class DoubleConversionHandler + implements ConversionHandler<Double> + { + public String getXsiType() + { + return "xsd:decimal"; + } + + public String stringify(Double obj) + { + return _useXsdFormatting + ? XmlUtil.formatXsdDecimal(obj) + : obj.toString(); + } + + public Double parse(String str) + { + return Double.valueOf(str.trim()); + } + } + + + private class BigIntegerConversionHandler + implements ConversionHandler<BigInteger> + { + public String getXsiType() + { + return "xsd:decimal"; + } + + public String stringify(BigInteger obj) + { + return obj.toString(); + } + + public BigInteger parse(String str) + { + return new BigInteger(str.trim()); + } + } + + + private class BigDecimalConversionHandler + implements ConversionHandler<BigDecimal> + { + public String getXsiType() + { + return "xsd:decimal"; + } + + public String stringify(BigDecimal obj) + { + return obj.toString(); + } + + public BigDecimal parse(String str) + { + return new BigDecimal(str.trim()); + } + } + + + private class DateConversionHandler + implements ConversionHandler<Date> + { + // format as specified by Date.toString() JavaDoc + private DateFormat _defaultFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); + + public String getXsiType() + { + return "xsd:dateTime"; + } + + public String stringify(Date obj) + { + return _useXsdFormatting + ? XmlUtil.formatXsdDatetime(obj) + : obj.toString(); + } + + public Date parse(String str) + throws ParseException + { + if (_useXsdFormatting) + return XmlUtil.parseXsdDatetime(str); + else + { + synchronized (_defaultFormat) + { + return _defaultFormat.parse(str); + } + } + } + } +} Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java 2009-08-18 17:41:38 UTC (rev 112) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestConversionHelper.java 2009-08-18 17:57:48 UTC (rev 113) @@ -18,7 +18,9 @@ import java.math.BigInteger; import java.util.Date; +import net.sf.practicalxml.converter.internal.ConversionHelper; + public class TestConversionHelper extends AbstractBeanConverterTestCase { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-18 17:41:55
|
Revision: 112 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=112&view=rev Author: kdgregory Date: 2009-08-18 17:41:38 +0000 (Tue, 18 Aug 2009) Log Message: ----------- change BeanConverter API, write tests for it Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-17 20:24:04 UTC (rev 111) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-18 17:41:38 UTC (rev 112) @@ -19,6 +19,8 @@ import net.sf.practicalxml.converter.bean.Bean2XmlDriver; import net.sf.practicalxml.converter.bean.Bean2XmlOptions; +import net.sf.practicalxml.converter.bean.Xml2BeanDriver; +import net.sf.practicalxml.converter.bean.Xml2BeanOptions; /** @@ -26,11 +28,13 @@ * Originally developed to support simple web services, without the overhead * (schema definitions and/or annotations) required by JAXB. * <p> - * A single instance handles conversions in one direction only. This is a - * consequence of specifying options as varargs, but fits well with "normal" - * application design, in which input and output are distinct operations. - * Note that, depending on options settings, output generated by one converter - * may not be valid input for another. + * A single instance is intended for conversions in one direction only. This + * is a consequence of specifying options as varargs, but fits well with + * "normal" application design, in which input and output are handled by + * different parts of the code. You won't get an error if you try to convert + * the "wrong" way, you'll simply get default behavior. Note that, depending + * on options settings, output generated by one converter may not be valid + * input for another. * <p> * The basic structure of XML produced/consumed by this class is that the * root element represents the object being converted, and its child nodes @@ -140,15 +144,50 @@ * </table> * * <strong>Warning</strong>: - * this class makes use of <code>java.beans.Introspector</code>, which holds - * a cache of introspected objects. If you use this converter in an app-server - * you should call <code>Introspector.flushCaches()</code> during deploy. + * <code>java.beans.Introspector</code> holds a cache of introspected objects. + * If you use this converter in an app-server you should call + * <code>Introspector.flushCaches()</code> during deploy. */ public class BeanConverter { + private Bean2XmlDriver _outputDriver; + private Xml2BeanDriver _inputDriver; + + /** + * Creates an instance with all options disabled. This can be used for + * conversions in either direction, and is meant primarily for testing. + */ + public BeanConverter() + { + _outputDriver = new Bean2XmlDriver(); + _inputDriver = new Xml2BeanDriver(); + } + + + /** + * Creates an instance to be used for Bean -> XML conversion, + */ + public BeanConverter(Bean2XmlOptions... options) + { + _outputDriver = new Bean2XmlDriver(options); + _inputDriver = new Xml2BeanDriver(); + } + + /** + * Creates an instance to be used for XML -> Bean conversion. + */ + public BeanConverter(Xml2BeanOptions options) + { + _outputDriver = new Bean2XmlDriver(); + _inputDriver = new Xml2BeanDriver(options); + } + + + /** * Creates a new DOM document from the passed bean, in which all elements - * are members of the specified namespace. + * are members of the specified namespace and will inherit the root's + * prefix (if any). * * @param bean The source object. This can be any Java object: * bean, collection, or simple type. @@ -157,14 +196,10 @@ * @param rootName The qualified name given to the root element of the * generated document. If a qualified name, all child * elements will inherit its prefix. - * @param options Options controlling output. -. */ - public static Document generateXml(Object bean, String nsUri, String rootName, - Bean2XmlOptions... options) + public Element convertToXml(Object bean, String nsUri, String rootName) { - Bean2XmlDriver driver = new Bean2XmlDriver(options); - return driver.convert(bean, nsUri, rootName).getOwnerDocument(); + return _outputDriver.convert(bean, nsUri, rootName); } @@ -175,13 +210,37 @@ * bean, collection, or simple type. * @param rootName The name given to the root element of the produced * document. - * @param options Options controlling output. -. */ - public static Document generateXml(Object bean, String rootName, - Bean2XmlOptions... options) + public Element convertToXml(Object bean, String rootName) { - Bean2XmlDriver driver = new Bean2XmlDriver(options); - return driver.convert(bean, rootName).getOwnerDocument(); + return _outputDriver.convert(bean, rootName); } + + + /** + * Creates a new Java object from the root of the passed <code>Document + * </code>. + * + * @param dom The source document. + * @param klass The desired class to instantiate and fill from this + * document. + */ + public <T> T convertToJava(Document dom, Class<T> klass) + { + return convertToJava(dom.getDocumentElement(), klass); + } + + + /** + * Creates a new Java object from the the passed DOM <code>Element</code>. + * + * @param dom The source element -- this may or may not be the + * root element of its document. + * @param klass The desired class to instantiate and fill from this + * document. + */ + public <T> T convertToJava(Element root, Class<T> klass) + { + return _inputDriver.convert(root, klass); + } } Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java 2009-08-17 20:24:04 UTC (rev 111) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/AbstractBeanConverterTestCase.java 2009-08-18 17:41:38 UTC (rev 112) @@ -16,6 +16,7 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Arrays; import java.util.Date; import java.util.List; @@ -23,6 +24,8 @@ import org.w3c.dom.Element; +import junit.framework.Assert; + import net.sf.practicalxml.AbstractTestCase; import net.sf.practicalxml.DomUtil; @@ -120,6 +123,15 @@ public boolean isBval() { return _bval; } public void setBval(boolean bval) { _bval = bval; } + + public void assertEquals(SimpleBean that) + { + assertNotNull(that); + Assert.assertEquals("sval", _sval, that._sval); + Assert.assertEquals("ival", _ival, that._ival); + Assert.assertEquals("dval", _dval, that._dval); + Assert.assertEquals("bval", _bval, that._bval); + } } @@ -150,6 +162,13 @@ public List<String> getStringList() { return _stringList; } public void setStringList(List<String> list) { _stringList = list; } + + public void assertEquals(CompoundBean that) + { + _simple.assertEquals(that._simple); + Assert.assertTrue("primArray", Arrays.equals(_primArray, that._primArray)); + Assert.assertEquals("stringlist", _stringList, that._stringList); + } } Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-08-17 20:24:04 UTC (rev 111) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-08-18 17:41:38 UTC (rev 112) @@ -14,19 +14,34 @@ package net.sf.practicalxml.converter; +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.OutputUtil; import net.sf.practicalxml.converter.bean.Bean2XmlOptions; +import net.sf.practicalxml.converter.bean.Xml2BeanOptions; +import net.sf.practicalxml.junit.DomAsserts; -import javax.xml.XMLConstants; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - /** - * Tests for the top-level <code>BeanConverter</code> methods. These are - * minimal; the detailed testing happens in {@link TestBean2XmlDriver} - * and {@link TestXml2BeanDriver}. + * Tests for the top-level <code>BeanConverter</code> methods. These are all + * "out and back" tests to verify that we can read the XML that we produce + * (and to show cases where we can't). Detailed tests (verifying specific + * output) are in {@link TestBean2XmlDriver} and {@link TestXml2BeanDriver}. + * <p> + * Note that each conversion has a commented-out line that will print the + * generated XML. Uncommenting these lines may help you understand how + * conversion works in particular cases. */ public class TestBeanConverter extends AbstractBeanConverterTestCase @@ -41,41 +56,368 @@ // Support Code //---------------------------------------------------------------------------- + private static void assertConversionError( + String message, BeanConverter converter, Element elem, Class<?> klass) + { + try + { + converter.convertToJava(elem, klass); + fail(message); + } + catch (ConversionException ee) + { /* success */ } + } //---------------------------------------------------------------------------- // Test Cases //---------------------------------------------------------------------------- - public void testGenerateSimpleContentSansNamespace() throws Exception + // an initial test to verify everything works + public void testConvertStringDefault() throws Exception { - String rootName = "argle"; - String value = "foo"; + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); - Document dom = BeanConverter.generateXml(value, rootName, Bean2XmlOptions.XSI_TYPE); -// System.out.println(OutputUtil.compactString(dom)); + String obj = "this is a test"; + Element root = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + assertEquals("test", DomUtil.getLocalName(root)); - Element root = dom.getDocumentElement(); - assertEquals(rootName, root.getNodeName()); - assertEquals(value, root.getTextContent()); - assertEquals("xsd:string", root.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type")); - assertEquals(0, DomUtil.getChildren(root).size()); + Object result = inConverter.convertToJava(root, String.class); + assertEquals(obj, result); } - public void testGenerateSimpleContentWithNamespace() throws Exception + public void testConvertPrimitiveDefault() throws Exception { - String nsUri = "urn:fibble"; - String rootName = "argle:bargle"; - String value = "foo"; + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); - Document dom = BeanConverter.generateXml(value, nsUri, rootName, Bean2XmlOptions.XSI_TYPE); + for (PrimitiveValue value : PRIMITIVE_VALUES) + { + Object obj = value.getValue(); + Element root = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Object result = inConverter.convertToJava(root, value.getKlass()); + assertEquals(obj, result); + } + } + + + public void testConvertPrimitiveFormatXsd() throws Exception + { + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSD_FORMAT); + BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.EXPECT_XSD_FORMAT); + + for (PrimitiveValue value : PRIMITIVE_VALUES) + { + Object obj = value.getValue(); + Element root = outConverter.convertToXml(obj, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Object result = inConverter.convertToJava(root, value.getKlass()); + assertEquals(obj, result); + } + } + + + public void testConvertNullDefault() throws Exception + { + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Object result = inConverter.convertToJava(root, String.class); + assertNull(result); + } + + + public void testConvertNullUseAndRequireXsiNil() throws Exception + { + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSI_NIL); + BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_NIL); + + Element root = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Object result = inConverter.convertToJava(root, String.class); + assertNull(result); + } + + + public void testConvertNullFailureRequireXsiNil() throws Exception + { + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_NIL); + + Element root = outConverter.convertToXml(null, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + assertConversionError("accepted DOM with null entry but no xsi:nil", + inConverter, root, String.class); + } + + + public void testPrimitiveArrayDefault() throws Exception + { + int[] data = new int[] { 1, 2, 4, 5 }; + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + int[] result = inConverter.convertToJava(root, int[].class); + assertTrue(Arrays.equals(data, result)); + } + + + public void testStringListDefault() throws Exception + { + List<String> data = Arrays.asList("foo", "bar", "baz"); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + List<String> result = inConverter.convertToJava(root, List.class); + assertEquals(data, result); + } + + + // demonstrates that the list will be read as List<String> even though + // it was written as List<Integer> + public void testIntegerListDefault() throws Exception + { + List<Integer> data = Arrays.asList(1, 2, 3); + assert(data.get(0) instanceof Integer); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + List<?> result = inConverter.convertToJava(root, List.class); + assertTrue(result instanceof List); + assertTrue(result.get(0) instanceof String); + } + + + // demonstrates that you don't need to require xsi:type to use it + public void testIntegerListWithXsiType() throws Exception + { + List<Integer> data = Arrays.asList(1, 2, 3); + assert(data.get(0) instanceof Integer); + + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSI_TYPE); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + List<?> result = inConverter.convertToJava(root, List.class); + assertEquals(data, result); + } + + + // demonstrates that the caller drives the inbound conversion + public void testConvertListToSortedSet() throws Exception + { + List<String> data = Arrays.asList("foo", "bar", "baz", "bar"); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Set<?> result = inConverter.convertToJava(root, SortedSet.class); + Iterator<?> itx = result.iterator(); + assertEquals("bar", itx.next()); + assertEquals("baz", itx.next()); + assertEquals("foo", itx.next()); + assertFalse(itx.hasNext()); + } + + + public void testMapDefault() throws Exception + { + Map<String,String> data = new HashMap<String,String>(); + data.put("foo", "argle"); + data.put("bar", "bargle"); + data.put("baz", "bazgle"); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + DomAsserts.assertCount(3, root, "/test/data"); + DomAsserts.assertCount(1, root, "/test/data[@key='foo']"); + DomAsserts.assertEquals("argle", root, "/test/data[@key='foo']"); + + Map<?,?> result = inConverter.convertToJava(root, Map.class); + assertEquals(data, result); + } + + + // demonstrates that the input converter handles either format by default + public void testMapIntrospected() throws Exception + { + Map<String,String> data = new HashMap<String,String>(); + data.put("foo", "argle"); + data.put("bar", "bargle"); + data.put("baz", "bazgle"); + + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.INTROSPECT_MAPS); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + DomAsserts.assertCount(0, root, "/test/data"); + DomAsserts.assertCount(1, root, "/test/foo"); + DomAsserts.assertEquals("argle", root, "/test/foo"); + + Map<?,?> result = inConverter.convertToJava(root, Map.class); + assertEquals(data, result); + } + + + public void testSimpleBeanDefault() throws Exception + { + SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + SimpleBean result = inConverter.convertToJava(root, SimpleBean.class); + data.assertEquals(result); + } + + + public void testSimpleBeanRequireXsiType() throws Exception + { + SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + + BeanConverter outconverter1 = new BeanConverter(Bean2XmlOptions.XSI_TYPE); + BeanConverter outconverter2 = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(Xml2BeanOptions.REQUIRE_XSI_TYPE); + + Element valid = outconverter1.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(valid.getOwnerDocument())); + + SimpleBean result = inConverter.convertToJava(valid, SimpleBean.class); + data.assertEquals(result); + + Element invalid = outconverter2.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(invalid.getOwnerDocument())); + + assertConversionError("converter requiring xsi:type accepted XML without", + inConverter, invalid, SimpleBean.class); + } + + + public void testListOfSimpleBeanWithXsiTypeAndNulls() throws Exception + { + SimpleBean bean1 = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + SimpleBean bean2 = new SimpleBean("zyx", 987, null, false); + List<SimpleBean> data = Arrays.asList(bean1, bean2); + + BeanConverter outConverter = new BeanConverter(Bean2XmlOptions.XSI_TYPE); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + List<SimpleBean> result = inConverter.convertToJava(root, List.class); + assertEquals(2, result.size()); + bean1.assertEquals(result.get(0)); + bean2.assertEquals(result.get(1)); + } + + + // another demonstration that caller drives input conversion + // ... and note that we don't care about xsi:type in this case + public void testListOfSimpleBeanToArrayOfSame() throws Exception + { + SimpleBean bean1 = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + SimpleBean bean2 = new SimpleBean("zyx", 987, null, false); + List<SimpleBean> data = Arrays.asList(bean1, bean2); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + SimpleBean[] result = inConverter.convertToJava(root, SimpleBean[].class); + assertEquals(2, result.length); + bean1.assertEquals(result[0]); + bean2.assertEquals(result[1]); + } + + + public void testCompoundBeanDefault() throws Exception + { + CompoundBean data = new CompoundBean( + new SimpleBean("abc", 123, new BigDecimal("456.789"), true), + new int[] { 1, 5, 7, 9 }, + Arrays.asList("foo", "bar", "baz")); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + CompoundBean result = inConverter.convertToJava(root, CompoundBean.class); + data.assertEquals(result); + } + + + public void testSimpleBeanWithNamespace() throws Exception + { + SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Element root = outConverter.convertToXml(data, "urn:foo", "bar:test"); +// System.out.println(OutputUtil.compactString(root.getOwnerDocument())); + + Element child = DomUtil.getChild(root, "sval"); + assertEquals("urn:foo", child.getNamespaceURI()); + assertEquals("bar", child.getPrefix()); + + SimpleBean result = inConverter.convertToJava(root, SimpleBean.class); + data.assertEquals(result); + } + + + // this one is here just for coverage + public void testSimpleBeanFromDocument() throws Exception + { + SimpleBean data = new SimpleBean("abc", 123, new BigDecimal("456.789"), true); + + BeanConverter outConverter = new BeanConverter(); + BeanConverter inConverter = new BeanConverter(); + + Document dom = outConverter.convertToXml(data, "test").getOwnerDocument(); // System.out.println(OutputUtil.compactString(dom)); - Element root = dom.getDocumentElement(); - assertEquals(nsUri, root.getNamespaceURI()); - assertEquals(rootName, root.getNodeName()); - assertEquals(value, root.getTextContent()); - assertEquals("xsd:string", root.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type")); - assertEquals(0, DomUtil.getChildren(root).size()); + SimpleBean result = inConverter.convertToJava(dom, SimpleBean.class); + data.assertEquals(result); } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-17 20:24:31
|
Revision: 111 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=111&view=rev Author: kdgregory Date: 2009-08-17 20:24:04 +0000 (Mon, 17 Aug 2009) Log Message: ----------- update comments Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/package.html Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-17 17:26:40 UTC (rev 110) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-17 20:24:04 UTC (rev 111) @@ -15,60 +15,162 @@ package net.sf.practicalxml.converter; import org.w3c.dom.Document; +import org.w3c.dom.Element; import net.sf.practicalxml.converter.bean.Bean2XmlDriver; import net.sf.practicalxml.converter.bean.Bean2XmlOptions; /** - * Converts Java objects (not just beans) to and from an XML representation. - * This was originally developed to support RESTful web services, without the - * class-generation hassle of JAXB. + * Converts Java objects (not just beans) to or from an XML representation. + * Originally developed to support simple web services, without the overhead + * (schema definitions and/or annotations) required by JAXB. * <p> - * The XML generated/consumed by this class obeys the following rules, with - * options controlled by {@link Bean2XmlOptions}: - * <ul> - * <li> All elements inherit their parent's namespace and namespace prefix. - * <li> Elements of sets are output using the element name "data". - * <li> Elements of lists and arrays are output using the element name "data", - * with an attribute "index" that contains the numeric index. - * <li> Elements of maps are by default output using the name "data", with an - * attribute "name" containing the actual map key. The output option - * <code>INTROSPECT_MAPS</code> will change this behavior, but will throw - * if the map keys are not valid XML element names. - * <li> Values are output using <code>toString()</code>, except as overridden - * by options. - * <li> Null values do not generate output, unless the <code>XSI_NIL</code> - * option is in effect. - * </ul> + * A single instance handles conversions in one direction only. This is a + * consequence of specifying options as varargs, but fits well with "normal" + * application design, in which input and output are distinct operations. + * Note that, depending on options settings, output generated by one converter + * may not be valid input for another. + * <p> + * The basic structure of XML produced/consumed by this class is that the + * root element represents the object being converted, and its child nodes + * represent the elements/properties of the object. Nodes representing complex + * objects have child elements, those representing simple (primitive) objects + * have a single text child. Objects are processed recursively, and cycles are + * <em>not</em> detected (although this may change). + * <p> + * A namespace and qualified name may be provided to {@link #convertToXml}, + * and all elements will inherit the namespace and prefix. Namespaces are + * ignored on input; all property matches uses the element's local name. + * <p> + * Each element may have an <code>xsi:type</code> attribute (where <code>xsi + * </code> references to the XML Schema instance namespace). This attribute + * is optional for both output and input; if used for output, it is merely + * informational, but for input will be examined to validate that the XML is + * appropriate for the desired object type. For primitive types, wrappers, + * and strings, it takes the form "<code>xsd:TYPE</code>", where <code>TYPE + * </code> is one of the simple types defined by XML schema. For other Java + * types, it takes the form "<code>java:TYPE</code>", where <code>TYPE</code> + * is the fully qualified Java classname. + * <p> + * On input, the desired type is specified by the caller or by introspection + * (except in the case of collection elements; see below). The <code>xsi:type + * </code> value, if any, is ignored except for validation. + * <p> + * Additional conversion rules are as follows: + * + * <table border="1"> + * <tr><th>Java Object Type + * <th>{@link #convertToXml} + * <th>{@link #convertToJava} + * <tr><td>Primitives, Wrapper objects, and String + * <td> + * <td> + * <tr><td>Arrays + * <td>Elements of the array are written in sequence to the DOM, using the + * element name "<code>data</code>". Elements are given an attribute + * named "<code>index</code>", which contains the element's position + * within the array. + * <td>Elements of the array are processed in sequence, ignoring both + * element name and "index" attribute. + * <tr><td>Lists and Sets + * <td>The collection is iterated, and elements are written in sequence to + * the DOM, using the element name "<code>data</code>". Elements are + * given an attribute named "<code>index</code>", which contains the + * element's position within the iteration (meaningful only for lists). + * <td>Elements of the are processed in sequence, ignoring both element + * name and "index" attribute. + * <p> + * If an <code>xsi:type</code> attribute is present, it will be used + * to drive conversion of the element. Otherwise, the element will be + * converted as a <code>String</code> (which will fail for complex + * types, because string conversion assumes a single text node). + * <p> + * Where the caller specifies an interface as the conversion class, the + * converter will choose an appropriate implementation class: + * <ul> + * <li> <code>ArrayList</code> for <code>List</code> or <code>Collection</code> + * <li> <code>TreeSet</code> for <code>SortedSet</code> + * <li> <code>HashSet</code> for <code>Set</code> + * </ul> + * <tr><td>Maps + * <td>The collection is iterated, and elements are written in sequence to + * the DOM. Depending on the output options, either the entry key will + * be used as the element name, or the name will be "<code>data</code>" + * and the key stored in an attribute named "<code>key</code>". The + * former option is only permitted if all keys in the map are valid + * XML element names; otherwise the converter will throw. + * <td>Elements are processed in sequence. The converter first looks for + * a "<code>key</code>" attribute, and will use it as the entry key + * if found. Otherwise, it will use the element name. If your maps + * are being reduced to a single entry, look for a missing attribute. + * <p> + * If an <code>xsi:type</code> attribute is present, it will be used + * to drive conversion of the element. Otherwise, the element will be + * converted as a <code>String</code> (which will fail for complex + * types, because string conversion assumes a single text node). + * <p> + * Where the caller specifies an interface as the conversion class, + * the converter will choose an appropriate implementation class: + * <code>TreeMap</code> for <code>SortedMap</code>, and <code>HashMap + * </code> for <code>Map</code>. + * <tr><td>Bean-structured Objects + * <td>The object is introspected, and properties are written in the order + * provided by the <code>Introspector</code>. + * <td>The bean class must provide a no-argument constructor (otherwise it + * doesn't follow the bean spec, and we can't use it). + * <p> + * The converter relies on <code>java.beans.Introspector</code> to find + * property setter methods for an object. If the object provides + * multiple methods for the property, the converter will use whichever + * one the introspector provides. + * <p> + * Elements are processed in order, and the element's localname is used + * to find the associated object property. If the XML does not contain + * an element corresponding to a bean property, that property is left + * with its default value (ie, we don't try to find an element based + * on property name). + * <p> + * If the XML contains an element that does not correspond to any bean + * property, the converter will either throw or ignore the element, + * depending on options settings. + * <tr><td>Other Objects + * <td>not supported + * <td>not supported + * </table> + * + * <strong>Warning</strong>: + * this class makes use of <code>java.beans.Introspector</code>, which holds + * a cache of introspected objects. If you use this converter in an app-server + * you should call <code>Introspector.flushCaches()</code> during deploy. */ public class BeanConverter { /** * Creates a new DOM document from the passed bean, in which all elements * are members of the specified namespace. - * + * * @param bean The source object. This can be any Java object: * bean, collection, or simple type. * @param nsUri The namespace of the root element. This will be * inherited by all child elements. - * @param rootName The qualified name given to the root element of the + * @param rootName The qualified name given to the root element of the * generated document. If a qualified name, all child * elements will inherit its prefix. * @param options Options controlling output. . */ - public static Document generateXml(Object bean, String nsUri, String rootName, + public static Document generateXml(Object bean, String nsUri, String rootName, Bean2XmlOptions... options) { Bean2XmlDriver driver = new Bean2XmlDriver(options); return driver.convert(bean, nsUri, rootName).getOwnerDocument(); } - - + + /** * Creates a new DOM document from the passed bean, without namespace. - * + * * @param bean The source object. This can be any Java object: * bean, collection, or simple type. * @param rootName The name given to the root element of the produced @@ -76,7 +178,7 @@ * @param options Options controlling output. . */ - public static Document generateXml(Object bean, String rootName, + public static Document generateXml(Object bean, String rootName, Bean2XmlOptions... options) { Bean2XmlDriver driver = new Bean2XmlDriver(options); Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-17 17:26:40 UTC (rev 110) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-17 20:24:04 UTC (rev 111) @@ -48,31 +48,6 @@ * Driver class for converting an XML DOM into a Java bean. Normal usage is * to create a single instance of this class with desired options, then use * it for multiple conversions. This class is thread-safe. - * <p> - * This class assumes that the source XML will be in the form produced by - * {@link Bean2XmlDriver}: each element either contains child elements, or - * a text node containing the element's value. However, conversion is - * driven by the parameters passed to {@link #convert}, not by the content - * of the XML document; this can lead to some unexpected behavior: - * <ul> - * <li> Bean classes are introspected, and recursively processed base on - * the property descriptors. If the bean has multiple setter methods - * for a property, the method selected is arbitrarily chosen by the - * JavaBeans introspector. You can pass an option that looks for a - * setters using <code>String</code>, but this is not recommended - * from a performance perspective. - * <li> JDK collection types do not carry type information, so the only - * way to properly convert them is using an <code>xsi:type</code> - * attribute on the child elements. If this attribute is missing - * or cannot be interpreted, the element will be processed as if - * it is a <code>String</code>. - * <li> The converter will to pick an appropriate implementation class - * if given one of the JDK collections interfaces: <code> - * ArrayList</code> for <code>List</code> or <code>Collection</code>, - * <code>TreeSet</code> for <code>SortedSet</code>, <code>HashSet</code> - * for any other <code>Set</code>, and likewise <code>TreeMap</code> and - * <code>HashMap</code> for <code>SortedMap</code> and <code>Map</code>. - * </ul> */ public class Xml2BeanDriver { Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/package.html =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/package.html 2009-08-17 17:26:40 UTC (rev 110) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/package.html 2009-08-17 20:24:04 UTC (rev 111) @@ -1,6 +1,15 @@ <html> <body> This package contains classes to convert between XML and a variety of - other formats. + other formats. Each conversion has a top-level convenience class in + this package, which handles common conversion scenarios and provides + overall documentation on the conversion. Sub-packages contain the + actual conversion classes; you may need to use those classes directly + for "unusual" conversions. + <p> + Any problems during conversion (in either direction) are reported via + {@link ConversionException}, which is a runtime exception and will + wrap any actual exception. If appropriate, this exception will also + contain the XPath to the node failing conversion. </body> </html> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: Auto-Generated S. C. M. <pra...@li...> - 2009-08-17 17:26:48
|
Revision: 110 http://practicalxml.svn.sourceforge.net/practicalxml/?rev=110&view=rev Author: kdgregory Date: 2009-08-17 17:26:40 +0000 (Mon, 17 Aug 2009) Log Message: ----------- repackage Modified Paths: -------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java Added Paths: ----------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java Removed Paths: ------------- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/ Modified: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-17 17:13:36 UTC (rev 109) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/BeanConverter.java 2009-08-17 17:26:40 UTC (rev 110) @@ -16,8 +16,8 @@ import org.w3c.dom.Document; -import net.sf.practicalxml.converter.bean2xml.Bean2XmlDriver; -import net.sf.practicalxml.converter.bean2xml.Bean2XmlOptions; +import net.sf.practicalxml.converter.bean.Bean2XmlDriver; +import net.sf.practicalxml.converter.bean.Bean2XmlOptions; /** Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java (from rev 100, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlAppenders.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlAppenders.java 2009-08-17 17:26:40 UTC (rev 110) @@ -0,0 +1,235 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.bean; + +import java.util.EnumSet; + +import javax.xml.XMLConstants; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.DomUtil; + + +/** + * Packaging class used for XML output appenders. This class is a temporary + * hack, as I move intelligence into {@link Bean2XmlDriver}; the contained + * classes will end up in a new package, once I figure out what the package + * structure should be. + */ +public abstract class Bean2XmlAppenders +{ + /** + * An <code>Appender</code> appends children to a single node of the + * output tree. The driver is responsible for creating new appenders + * for each compound element, including the root, and providing those + * appenders with options to control output generation. + */ + public interface Appender + { + /** + * Appends a value element to the current element. Value elements have + * associated text, but no other children. + * + * @param name Name to be associated with the node. + * @param type Type to be associated with the node; may or may + * not be written to the output, depending on the + * appender's options. + * @param value The node's value. May be <code>null</code>, in + * which case the appender decides whether or not + * to actually append the node. + * + * @return The appended element. This is a convenience for subclasses, + * which may want to set additional attributes after their + * super has done the work of appending the element. + * @throws ConversionException if unable to append the node. + */ + public Element appendValue(String name, String type, String value); + + + /** + * Appends a container element to the current element. Container + * elements have other elements as children, and may have a type, + * but do not have an associated value. + */ + public Element appendContainer(String name, String type); + } + + + /** + * Base class for XML appenders, providing helper methods for subclasses. + */ + private static abstract class AbstractAppender + implements Appender + { + private EnumSet<Bean2XmlOptions> _options; + + public AbstractAppender(EnumSet<Bean2XmlOptions> options) + { + _options = options; + } + + protected boolean isOptionSet(Bean2XmlOptions option) + { + return _options.contains(option); + } + + protected boolean shouldSkip(Object value) + { + return (value == null) && !_options.contains(Bean2XmlOptions.XSI_NIL); + } + + protected void setType(Element elem, String type) + { + if (isOptionSet(Bean2XmlOptions.XSI_TYPE)) + elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type", type); + } + + protected void setValue(Element elem, String value) + { + if (value != null) + DomUtil.setText(elem, value); + else if (isOptionSet(Bean2XmlOptions.XSI_NIL)) + elem.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "true"); + } + } + + + /** + * Basic appender, which appends new elements to a parent. + */ + public static class BasicAppender + extends AbstractAppender + { + private Element _parent; + + public BasicAppender(Element parent, EnumSet<Bean2XmlOptions> options) + { + super(options); + _parent = parent; + } + + public Element appendValue(String name, String type, String value) + { + if (shouldSkip(value)) + return null; + + Element child = DomUtil.appendChildInheritNamespace(_parent, name); + setType(child, type); + setValue(child, value); + return child; + } + + public Element appendContainer(String name, String type) + { + Element child = DomUtil.appendChildInheritNamespace(_parent, name); + setType(child, type); + return child; + } + } + + + /** + * Appender for children of an indexed/iterated item (array, list, or set). + * Each element will have an incremented <code>index</code> attribute that + * indicates the position of the element within the iteration. + */ + public static class IndexedAppender + extends BasicAppender + { + int _index = 0; + + public IndexedAppender(Element parent, EnumSet<Bean2XmlOptions> options) + { + super(parent, options); + } + + + @Override + public Element appendValue(String name, String type, String value) + { + Element child = super.appendValue(name, type, value); + if (child != null) + child.setAttribute("index", String.valueOf(_index++)); + return child; + } + } + + + /** + * Appender for children of a <code>Map</code>. Depending on options, + * will either create children named after the key, or a generic "data" + * child with the key as an attribute. + */ + public static class MapAppender + extends BasicAppender + { + public MapAppender(Element parent, EnumSet<Bean2XmlOptions> options) + { + super(parent, options); + } + + + @Override + public Element appendValue(String name, String type, String value) + { + Element child = null; + if (isOptionSet(Bean2XmlOptions.INTROSPECT_MAPS)) + { + child = super.appendValue(name, type, value); + } + else + { + child = super.appendValue("data", type, value); + if (child != null) + child.setAttribute("key", name); + } + return child; + } + } + + + /** + * An appender that sets values directly on the "parent" element. Used for + * the conversion root element. + */ + public static class DirectAppender + extends AbstractAppender + { + private Element _elem; + + public DirectAppender(Element elem, EnumSet<Bean2XmlOptions> options) + { + super(options); + _elem = elem; + } + + public Element appendValue(String name, String type, String value) + { + if (!shouldSkip(value)) + { + setType(_elem, type); + setValue(_elem, value); + } + return _elem; + } + + public Element appendContainer(String name, String type) + { + setType(_elem, type); + return _elem; + } + } +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java (from rev 108, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlDriver.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlDriver.java 2009-08-17 17:26:40 UTC (rev 110) @@ -0,0 +1,259 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.bean; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Map; + +import javax.xml.XMLConstants; + +import org.w3c.dom.Element; + +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.ConversionHelper; +import net.sf.practicalxml.converter.bean.Bean2XmlAppenders.*; + + +/** + * Driver class for converting a Java bean into an XML DOM. Normal usage is + * to create a single instance of this class with desired options, then use + * it for multiple conversions. This class is thread-safe. + */ +public class Bean2XmlDriver +{ + private ConversionHelper _helper; + private EnumSet<Bean2XmlOptions> _options = EnumSet.noneOf(Bean2XmlOptions.class); + + public Bean2XmlDriver(Bean2XmlOptions... options) + { + for (Bean2XmlOptions option : options) + _options.add(option); + _helper = new ConversionHelper(shouldUseXsdFormatting()); + } + + +//---------------------------------------------------------------------------- +// Public methods +//---------------------------------------------------------------------------- + + /** + * Creates an XML DOM with the specified root element name, and fills it + * by introspecting the passed object (see {@link #introspect} for + * treatment of simple objects). + */ + public Element convert(Object obj, String rootName) + { + return convert(obj, null, rootName); + } + + + /** + * Creates an XML DOM with the specified root element name and namespace + * URI, and fills it by introspecting the passed object (see {@link + * #introspect} for treatment of simple objects). The namespace URI (and + * prefix, if provided) will be used for all child elements. + */ + public Element convert(Object obj, String nsUri, String rootName) + { + Element root = DomUtil.newDocument(nsUri, rootName); + doXsiNamespaceHack(root); + convert(obj, "", new DirectAppender(root, _options)); + return root; + } + + + /** + * Introspects the passed object, and appends its contents to the output. + * This method is public to allow non-standard conversions, such as + * appending into an existing tree, or (in the future, if we introduce an + * appender factory) producing non-XML output. + */ + public void convert(Object obj, String name, Appender appender) + { + // these methods have side effects! + // empty blocks and comments are there to keep Eclipse happy + if (tryToConvertAsPrimitiveOrNull(obj, null, name, appender)) + { /* it was converted */ } + else if (tryToConvertAsArray(obj, name, appender)) + { /* it was converted */ } + else if (tryToConvertAsMap(obj, name, appender)) + { /* it was converted */ } + else if (tryToConvertAsCollection(obj, name, appender)) + { /* it was converted */ } + else if (tryToConvertAsBean(obj, name, appender)) + { /* it was converted */ } + else + throw new ConversionException("unable to convert: " + obj.getClass().getName()); + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + private boolean shouldUseXsdFormatting() + { + return _options.contains(Bean2XmlOptions.XSD_FORMAT) + || _options.contains(Bean2XmlOptions.XSI_TYPE); + } + + + private String getJavaXsiType(Object obj) + { + return "java:" + obj.getClass().getName(); + } + + + /** + * Introduces the XML Schema Instance namespace into the DOM tree using a + * meaningless attribute. The Xerces serializer does not attempt to promote + * namespace definitions above the subtree in which they first appear, which + * means that the XSI definition could be repeated many times throughout the + * serialized tree, adding bulk to the serialized representation. + * <p> + * By putting "nil=false" at the root element, we will keep the serializer + * from inserting all these definitions. This has to happen <em>before</em> + * any actual conversion, in case some bozo passes <code>null</code> to + * the top-level conversion routine. + * <p> + * Note that we only do this if <code>xsi:nil</code> is enabled by itself. + * If <code>xsi:type</code> is enabled, the converter will attach that + * attribute to the root instead, thereby establishing the namespace context. + */ + private void doXsiNamespaceHack(Element root) + { + if (_options.contains(Bean2XmlOptions.XSI_NIL) + && !_options.contains(Bean2XmlOptions.XSI_TYPE)) + { + root.setAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil", "false"); + } + } + + + private boolean tryToConvertAsPrimitiveOrNull( + Object obj, Class<?> klass, String name, Appender appender) + { + if (obj != null) + klass = obj.getClass(); + + String objType = _helper.getXsdType(klass); + if ((obj == null) || (objType != null)) + { + appender.appendValue(name, objType, _helper.stringify(obj)); + return true; + } + + return false; + } + + + private boolean tryToConvertAsArray(Object array, String name, Appender appender) + { + if (!array.getClass().isArray()) + return false; + + Element parent = appender.appendContainer(name, getJavaXsiType(array)); + Appender childAppender = new IndexedAppender(parent, _options); + int length = Array.getLength(array); + for (int idx = 0 ; idx < length ; idx++) + { + Object value = Array.get(array, idx); + convert(value, "data", childAppender); + } + return true; + } + + + private boolean tryToConvertAsMap(Object obj, String name, Appender appender) + { + if (!(obj instanceof Map)) + return false; + + Element parent = appender.appendContainer(name, getJavaXsiType(obj)); + Appender childAppender = new MapAppender(parent, _options); + for (Map.Entry<?,?> entry : ((Map<?,?>)obj).entrySet()) + { + convert(entry.getValue(), String.valueOf(entry.getKey()), childAppender); + } + return true; + } + + + private boolean tryToConvertAsCollection(Object obj, String name, Appender appender) + { + if (!(obj instanceof Collection)) + return false; + + Element parent = appender.appendContainer(name, getJavaXsiType(obj)); + Appender childAppender = new IndexedAppender(parent, _options); + for (Object value : (Collection<?>)obj) + { + convert(value, "data", childAppender); + } + return true; + } + + + private boolean tryToConvertAsBean(Object bean, String name, Appender appender) + { + Element parent = appender.appendContainer(name, getJavaXsiType(bean)); + Appender childAppender = new BasicAppender(parent, _options); + try + { + BeanInfo info = Introspector.getBeanInfo(bean.getClass(), Object.class); + PropertyDescriptor[] props = info.getPropertyDescriptors(); + for (int ii = 0 ; ii < props.length ; ii++) + convertBeanProperty(bean, props[ii], childAppender); + } + catch (IntrospectionException ee) + { + throw new ConversionException("introspection failure", ee); + } + return true; + } + + + private void convertBeanProperty( + Object bean, PropertyDescriptor propDesc, Appender appender) + { + String name = propDesc.getName(); + Class<?> type = propDesc.getPropertyType(); + Object value; + try + { + Method getter = propDesc.getReadMethod(); + if (getter == null) + return; + value = getter.invoke(bean); + } + catch (Exception ee) + { + throw new ConversionException("unable to retrieve bean value", ee); + } + + if (value == null) + tryToConvertAsPrimitiveOrNull(value, type, name, appender); + else + convert(value, name, appender); + } +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java (from rev 100, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean2xml/Bean2XmlOptions.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Bean2XmlOptions.java 2009-08-17 17:26:40 UTC (rev 110) @@ -0,0 +1,55 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.bean; + + +/** + * Options used by {@link Bean2XmlHandler} to control the structure of the + * DOM tree. + */ +public enum Bean2XmlOptions +{ + /** + * Outputs values using formats defined by XML Schema, rather than Java's + * <code>String.valueOf()</code> method. Note that these formats are not + * flagged in the element, so sender and receiver will have to agree on + * the format. + */ + XSD_FORMAT, + + /** + * Will add an <code>xsi:type</code> attribute to each element. For values + * covered by the XML Schema simple types, this attribute's value will be + * "<code>xsd:XXX</code>", where XXX is the XSD type name. For complex + * types, this attribute's value will be "<code>java:XXX</code>", where + * XXX is the fully-qualified classname. + * <p> + * <em>This option implies {@link #XSD_FORMAT} for simple types</em>. + */ + XSI_TYPE, + + /** + * Report null values using the <code>xsi:nil="true"</code> attribute. If + * not present, null values are ignored, and not added to DOM tree. + */ + XSI_NIL, + + /** + * Output maps in an "introspected" format, where the name of each item + * is the map key (rather than "data"), and the "key" attribute is omitted. + * If any key is not a valid XML identifier, the converter will throw. + */ + INTROSPECT_MAPS +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java (from rev 109, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanDriver.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanDriver.java 2009-08-17 17:26:40 UTC (rev 110) @@ -0,0 +1,447 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.bean; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +import javax.xml.XMLConstants; + +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.ConversionHelper; +import net.sf.practicalxml.internal.StringUtils; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + + +/** + * Driver class for converting an XML DOM into a Java bean. Normal usage is + * to create a single instance of this class with desired options, then use + * it for multiple conversions. This class is thread-safe. + * <p> + * This class assumes that the source XML will be in the form produced by + * {@link Bean2XmlDriver}: each element either contains child elements, or + * a text node containing the element's value. However, conversion is + * driven by the parameters passed to {@link #convert}, not by the content + * of the XML document; this can lead to some unexpected behavior: + * <ul> + * <li> Bean classes are introspected, and recursively processed base on + * the property descriptors. If the bean has multiple setter methods + * for a property, the method selected is arbitrarily chosen by the + * JavaBeans introspector. You can pass an option that looks for a + * setters using <code>String</code>, but this is not recommended + * from a performance perspective. + * <li> JDK collection types do not carry type information, so the only + * way to properly convert them is using an <code>xsi:type</code> + * attribute on the child elements. If this attribute is missing + * or cannot be interpreted, the element will be processed as if + * it is a <code>String</code>. + * <li> The converter will to pick an appropriate implementation class + * if given one of the JDK collections interfaces: <code> + * ArrayList</code> for <code>List</code> or <code>Collection</code>, + * <code>TreeSet</code> for <code>SortedSet</code>, <code>HashSet</code> + * for any other <code>Set</code>, and likewise <code>TreeMap</code> and + * <code>HashMap</code> for <code>SortedMap</code> and <code>Map</code>. + * </ul> + */ +public class Xml2BeanDriver +{ + private EnumSet<Xml2BeanOptions> _options; + private ConversionHelper _helper; + private Map<Class<?>,Map<String,Method>> _introspectedClasses; + + + public Xml2BeanDriver(Xml2BeanOptions... options) + { + _options = EnumSet.noneOf(Xml2BeanOptions.class); + for (Xml2BeanOptions option : options) + _options.add(option); + + _helper = new ConversionHelper(_options.contains(Xml2BeanOptions.EXPECT_XSD_FORMAT)); + _introspectedClasses = new HashMap<Class<?>,Map<String,Method>>(); + } + + +//---------------------------------------------------------------------------- +// Public Methods +//---------------------------------------------------------------------------- + + /** + * Attempts to convert the passed DOM subtree into an object of the + * specified class. + */ + public <T> T convert(Element elem, Class<T> klass) + { + return klass.cast(convertWithoutCast(elem, klass)); + } + + +//---------------------------------------------------------------------------- +// Internal Conversion Methods +//---------------------------------------------------------------------------- + + + + /** + * Attempts to convert the passed DOM subtree into an object of the + * specified class. Note that this version does not use generics, + * and does not try to cast the result, whereas the public version + * does. Internally, we want to treat <code>Integer.TYPE</code> the + * same as <code>Integer.class</code>, and the cast prevents that. + */ + public Object convertWithoutCast(Element elem, Class<?> klass) + { + validateXsiType(elem, klass); + if (isAllowableNull(elem)) + return null; + + Object obj = tryConvertAsPrimitive(elem, klass); + if (obj == null) + obj = tryConvertAsArray(elem, klass); + if (obj == null) + obj = tryConvertAsSimpleCollection(elem, klass); + if (obj == null) + obj = tryConvertAsMap(elem, klass); + if (obj == null) + obj = tryConvertAsBean(elem, klass); + return obj; + } + + + private boolean isAllowableNull(Element elem) + { + String text = getText(elem); + if ((text != null) || hasElementChildren(elem)) + return false; + + if (_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL)) + { + String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); + if (!attr.equals("true")) + throw new ConversionException( + "missing xsi:nil: " + DomUtil.getAbsolutePath(elem)); + } + + return true; + } + + + private Object tryConvertAsPrimitive(Element elem, Class<?> klass) + { + if (_helper.getXsdType(klass) == null) + return null; + + if (hasElementChildren(elem)) + throw new ConversionException( + "expecting primitive; has children: " + DomUtil.getAbsolutePath(elem)); + + return _helper.parse(getText(elem), klass); + } + + + private Object tryConvertAsArray(Element elem, Class<?> klass) + { + Class<?> childKlass = klass.getComponentType(); + if (childKlass == null) + return null; + + List<Element> children = DomUtil.getChildren(elem); + Object result = Array.newInstance(childKlass, children.size()); + int idx = 0; + for (Element child : children) + { + Array.set(result, idx++, convertWithoutCast(child, childKlass)); + } + return result; + } + + + private Object tryConvertAsSimpleCollection(Element elem, Class<?> klass) + { + Collection<Object> result = instantiateCollection(klass); + if (result == null) + return null; + + List<Element> children = DomUtil.getChildren(elem); + for (Element child : children) + { + Class<?> childClass = getClassFromXsiType(child); + if (childClass == null) + childClass = String.class; + result.add(convertWithoutCast(child, childClass)); + } + return result; + } + + + private Object tryConvertAsMap(Element elem, Class<?> klass) + { + Map<Object,Object> result = instantiateMap(klass); + if (result == null) + return null; + + List<Element> children = DomUtil.getChildren(elem); + for (Element child : children) + { + String key = child.getAttribute("key"); + if (StringUtils.isEmpty(key)) + key = DomUtil.getLocalName(child); + Class<?> childClass = getClassFromXsiType(child); + if (childClass == null) + childClass = String.class; + result.put(key, convertWithoutCast(child, childClass)); + } + return result; + } + + + private Object tryConvertAsBean(Element elem, Class<?> klass) + { + Object bean = instantiateBean(elem, klass); + + List<Element> children = DomUtil.getChildren(elem); + for (Element child : children) + { + Method setter = getSetterMethod(klass, child); + if (setter == null) + continue; + + Class<?> childClass = setter.getParameterTypes()[0]; + Object childValue = convertWithoutCast(child, childClass); + invokeSetter(elem, bean, setter, childValue); + } + return bean; + } + + +//---------------------------------------------------------------------------- +// Other Internals +//---------------------------------------------------------------------------- + + /** + * Returns the text content of an element, applying appropriate options. + */ + private String getText(Element elem) + { + String text = DomUtil.getText(elem); + if (StringUtils.isBlank(text) + && _options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL)) + text = null; + return text; + } + + + /** + * Returns the <code>xsi:type</code> attribute value, <code>null</code> if + * it's not set. + */ + private String getXsiType(Element elem) + { + String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); + return StringUtils.isEmpty(xsiType) + ? null + : xsiType; + } + + + /** + * Examines an element's <code>xsi:type</code> attribute, if any, and + * returns the Java class corresponding to it. Used when converting + * collection types, which don't have type information that can be + * introspected, and also to validate non-XSD types. + */ + private Class<?> getClassFromXsiType(Element elem) + { + String xsiType = getXsiType(elem); + if (xsiType == null) + return null; + + if (xsiType.startsWith("java:")) + { + String javaType = xsiType.substring(5); + try + { + return Class.forName(javaType); + } + catch (ClassNotFoundException ee) + { + throw new ConversionException( + "invalid Java type specification (" + javaType + "): " + + DomUtil.getAbsolutePath(elem), + ee); + } + } + return _helper.getJavaType(xsiType); + } + + + private void validateXsiType(Element elem, Class<?> klass) + { + if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_TYPE)) + return; + + String xsiType = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); + if (StringUtils.isEmpty(xsiType)) + throw new ConversionException( + "missing xsi:type: " + DomUtil.getAbsolutePath(elem)); + + if (xsiType.equals(_helper.getXsdType(klass))) + return; + + Class<?> xsiKlass = getClassFromXsiType(elem); + if (klass.isAssignableFrom(xsiKlass)) + return; + + throw new ConversionException( + "invalid xsi:type (\"" + xsiType + "\" for " + klass.getName() + "): " + + DomUtil.getAbsolutePath(elem)); + } + + + private boolean hasElementChildren(Element elem) + { + Node child = elem.getFirstChild(); + while (child != null) + { + if (child instanceof Element) + return true; + child = child.getNextSibling(); + } + return false; + } + + + private Method getSetterMethod(Class<?> beanKlass, Element child) + { + Map<String,Method> methodMap = _introspectedClasses.get(beanKlass); + if (methodMap == null) + methodMap = introspect(beanKlass); + + Method setter = methodMap.get(DomUtil.getLocalName(child)); + if ((setter == null) && !_options.contains(Xml2BeanOptions.IGNORE_MISSING_PROPERTIES)) + { + throw new ConversionException( + "can't find property setter in " + beanKlass.getName() + ": " + + DomUtil.getAbsolutePath(child)); + } + + return setter; + } + + + private Map<String,Method> introspect(Class<?> klass) + { + Map<String,Method> methodMap = new HashMap<String,Method>(); + try + { + BeanInfo info = Introspector.getBeanInfo(klass, Object.class); + for (PropertyDescriptor propDesc : info.getPropertyDescriptors()) + { + Method setter = propDesc.getWriteMethod(); + if (setter != null) + methodMap.put(propDesc.getName(), setter); + } + } + catch (IntrospectionException e) + { + throw new ConversionException("unable to introspect", e); + } + + _introspectedClasses.put(klass, methodMap); + return methodMap; + } + + + /** + * Attempts to create a <code>Collection</code> instance appropriate for + * the passed class, returns <code>null</code> if unable. + */ + private Collection<Object> instantiateCollection(Class<?> klass) + { + if (SortedSet.class.isAssignableFrom(klass)) + return new TreeSet<Object>(); + else if (Set.class.isAssignableFrom(klass)) + return new HashSet<Object>(); + else if (List.class.isAssignableFrom(klass)) + return new ArrayList<Object>(); + else if (Collection.class.isAssignableFrom(klass)) + return new ArrayList<Object>(); + else + return null; + } + + + /** + * Attempts to create a <code>Map</code> instance appropriate for the + * passed class, returns <code>null</code> if unable. + */ + private Map<Object,Object> instantiateMap(Class<?> klass) + { + if (SortedMap.class.isAssignableFrom(klass)) + return new TreeMap<Object,Object>(); + else if (Map.class.isAssignableFrom(klass)) + return new HashMap<Object,Object>(); + else + return null; + } + + + private Object instantiateBean(Element elem, Class<?> klass) + { + try + { + return klass.newInstance(); + } + catch (Exception ee) + { + throw new ConversionException( + "unable to instantiate bean: " + DomUtil.getAbsolutePath(elem), + ee); + } + } + + + private void invokeSetter(Element elem, Object bean, Method setter, Object value) + { + try + { + setter.invoke(bean, value); + } + catch (Exception ee) + { + throw new ConversionException( + "unable to set property: " + DomUtil.getAbsolutePath(elem), + ee); + } + } +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java (from rev 105, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanHandler.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanHandler.java 2009-08-17 17:26:40 UTC (rev 110) @@ -0,0 +1,194 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.bean; + +import net.sf.practicalxml.DomUtil; +import net.sf.practicalxml.XmlException; +import net.sf.practicalxml.XmlUtil; +import net.sf.practicalxml.converter.ConversionException; +import net.sf.practicalxml.converter.ConversionHelper; +import net.sf.practicalxml.internal.StringUtils; + +import java.util.Arrays; +import java.util.Date; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.xml.XMLConstants; + +import org.w3c.dom.Element; + + +/** + * Invoked by {@link Xml2BeanDriver} to convert a DOM <code>Element</code> + * into the appropriate Java object. Unlike {@link Bean2XmlHandler}, there + * will only be one instance of this object created during conversion; all + * intermediate data can be held on the stack. + */ +public class Xml2BeanHandler +{ + private EnumSet<Xml2BeanOptions> _options; + private ConversionHelper _primitiveHelper; + + + /** + * Public constructor, allowing various options specifications. + */ + public Xml2BeanHandler(Xml2BeanOptions... options) + { + _options = EnumSet.noneOf(Xml2BeanOptions.class); + for (Xml2BeanOptions option : options) + _options.add(option); + + _primitiveHelper = new ConversionHelper(true); + } + + +//---------------------------------------------------------------------------- +// Public Methods +//---------------------------------------------------------------------------- + + public Boolean convertBoolean(Element elem) + { + return (Boolean)_primitiveHelper.parse(getText(elem), Boolean.class); + } + + + public Byte convertByte(Element elem) + { + return (Byte)_primitiveHelper.parse(getText(elem), Byte.class); + } + + + public Character convertCharacter(Element elem) + { + return (Character)_primitiveHelper.parse(getText(elem), Character.class); + } + + + public Date convertDate(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Double convertDouble(Element elem) + { + return (Double)_primitiveHelper.parse(getText(elem), Double.class); + } + + + public Float convertFloat(Element elem) + { + return (Float)_primitiveHelper.parse(getText(elem), Float.class); + } + + + public Integer convertInteger(Element elem) + { + return (Integer)_primitiveHelper.parse(getText(elem), Integer.class); + } + + + public Long convertLong(Element elem) + { + return (Long)_primitiveHelper.parse(getText(elem), Long.class); + } + + + public Number convertNumber(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Short convertShort(Element elem) + { + return (Short)_primitiveHelper.parse(getText(elem), Short.class); + } + + + public String convertString(Element elem) + { + return (String)_primitiveHelper.parse(getText(elem), String.class); + } + + + public List<?> convertList(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Set<?> convertSet(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Map<?,?> convertMap(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Object convertObject(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + + public Object[] convertObjectArray(Element elem) + { + throw new UnsupportedOperationException("not implemented yet"); + } + + +//---------------------------------------------------------------------------- +// Internals +//---------------------------------------------------------------------------- + + /** + * Returns the text from a passed element, applying any low-level options + * along the way. + */ + private String getText(Element elem) + { + String text = DomUtil.getText(elem); + if (_options.contains(Xml2BeanOptions.CONVERT_BLANK_AS_NULL) && StringUtils.isBlank(text)) + text = null; + validateXsiNil(elem, text); + return text; + } + + + /** + * Checks for elements that require <code>xsi:nil</code>, and throws if missing. + */ + private void validateXsiNil(Element elem, String text) + { + if (text != null) + return; + if (!_options.contains(Xml2BeanOptions.REQUIRE_XSI_NIL)) + return; + + String attr = elem.getAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "nil"); + if ((attr == null) || !attr.equals("true")) + throw new ConversionException("empty element without required xsi:nil"); + } + +} Copied: branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java (from rev 109, branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/xml2bean/Xml2BeanOptions.java) =================================================================== --- branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java (rev 0) +++ branches/dev-1.1/src/main/java/net/sf/practicalxml/converter/bean/Xml2BeanOptions.java 2009-08-17 17:26:40 UTC (rev 110) @@ -0,0 +1,69 @@ +// Copyright 2008-2009 severally by the contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package net.sf.practicalxml.converter.bean; + + + +/** + * Options used by {@link Xml2BeanHandler} to control the way that DOM trees + * are translated to Java beans. + */ +public enum Xml2BeanOptions +{ + /** + * If present, the converter will treat all elements with empty text nodes + * as if they were empty elements -- in other words, <code>null</code>. + * Note that this flag will interact with <code>REQUIRE_XSI_NIL</code>. + */ + CONVERT_BLANK_AS_NULL, + + + /** + * Expect data (in particular, dates) to be formatted per XML Schema spec. + */ + EXPECT_XSD_FORMAT, + + + /** + * If present, the converter ignores elements that don't correspond to + * settable properties of the bean. + */ + IGNORE_MISSING_PROPERTIES, + + + /** + * If present, the converter will look for a setter method taking a + * <code>String</code>, in preference to a non-string method returned + * from the bean introspector. + */ + PREFER_STRING_SETTER, + + + /** + * If present, the converter requires an <code>xsi:nil</code> attribute + * on any empty nodes, and will throw if it's not present. Default is to + * treat empty nodes as <code>null</code>. + */ + REQUIRE_XSI_NIL, + + + /** + * If present, the converter requires an <code>xsi:type</code> attribute + * on each element, and will throw if it's not present. Default behavior + * uses the <code>xsi:type</code> value to choose between different setter + * methods, but otherwise ignores it. + */ + REQUIRE_XSI_TYPE +} Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java 2009-08-17 17:13:36 UTC (rev 109) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlAppenders.java 2009-08-17 17:26:40 UTC (rev 110) @@ -20,9 +20,9 @@ import org.w3c.dom.Element; import net.sf.practicalxml.DomUtil; -import net.sf.practicalxml.converter.bean2xml.Bean2XmlOptions; +import net.sf.practicalxml.converter.bean.Bean2XmlOptions; -import static net.sf.practicalxml.converter.bean2xml.Bean2XmlAppenders.*; +import static net.sf.practicalxml.converter.bean.Bean2XmlAppenders.*; public class TestBean2XmlAppenders Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java 2009-08-17 17:13:36 UTC (rev 109) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBean2XmlDriver.java 2009-08-17 17:26:40 UTC (rev 110) @@ -27,8 +27,8 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.OutputUtil; -import net.sf.practicalxml.converter.bean2xml.Bean2XmlDriver; -import net.sf.practicalxml.converter.bean2xml.Bean2XmlOptions; +import net.sf.practicalxml.converter.bean.Bean2XmlDriver; +import net.sf.practicalxml.converter.bean.Bean2XmlOptions; import net.sf.practicalxml.junit.DomAsserts; Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-08-17 17:13:36 UTC (rev 109) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestBeanConverter.java 2009-08-17 17:26:40 UTC (rev 110) @@ -16,7 +16,7 @@ import net.sf.practicalxml.DomUtil; import net.sf.practicalxml.OutputUtil; -import net.sf.practicalxml.converter.bean2xml.Bean2XmlOptions; +import net.sf.practicalxml.converter.bean.Bean2XmlOptions; import javax.xml.XMLConstants; import org.w3c.dom.Document; Modified: branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java =================================================================== --- branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java 2009-08-17 17:13:36 UTC (rev 109) +++ branches/dev-1.1/src/test/java/net/sf/practicalxml/converter/TestXml2BeanDriver.java 2009-08-17 17:26:40 UTC (rev 110) @@ -27,8 +27,8 @@ import javax.xml.XMLConstants; import org.w3c.dom.Element; -import net.sf.practicalxml.converter.xml2bean.Xml2BeanDriver; -import net.sf.practicalxml.converter.xml2bean.Xml2BeanOptions; +import net.sf.practicalxml.converter.bean.Xml2BeanDriver; +import net.sf.practicalxml.converter.bean.Xml2BeanOptions; import static net.sf.practicalxml.builder.XmlBuilder.*; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |