http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/main/javadoc/overview.html ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/javadoc/overview.html b/juneau-core/src/main/javadoc/overview.html index 478028f..de2d4f7 100644 --- a/juneau-core/src/main/javadoc/overview.html +++ b/juneau-core/src/main/javadoc/overview.html @@ -4985,8 +4985,8 @@ <h5 class='toc'>What's new in each release</h5> <ul class='toc'> - <li><p><a class='doclink' href='#6.0.1'>6.0.2 (TBD)</a></p> - <li><p><a class='doclink' href='#6.0.1'>6.0.1 (TBD)</a></p> + <li><p><a class='doclink' href='#6.0.2'>6.0.2 (TBD)</a></p> + <li><p><a class='doclink' href='#6.0.1'>6.0.1 (Jan 3, 2017)</a></p> <li><p><a class='doclink' href='#6.0.0'>6.0.0 (Oct 3, 2016)</a></p> <li><p><a class='doclink' href='#5.2.0.1'>5.2.0.1 (Mar 23, 2016)</a></p> <li><p><a class='doclink' href='#5.2.0.0'>5.2.0.0 (Dec 30, 2015)</a></p> @@ -5063,10 +5063,42 @@ In particular, this release cleans up the {@link org.apache.juneau.BeanContext} API to match the {@link org.apache.juneau.ContextFactory}/{@link org.apache.juneau.Context}/{@link org.apache.juneau.Session} paradigm previously used in the serializer and parser APIs. + It also makes several improvements to the HTML and XML serialization support and introduces HTML5 DTO beans. </p> <h6 class='topic'>org.apache.juneau</h6> <ul class='spaced-list'> + <li>Improvements to XML serialization support. + <ul> + <li>New supported XML formats: + <ul> + <li>{@link org.apache.juneau.xml.annotation.XmlFormat#ATTRS} format can now be applied to bean classes to have all bean properties serialized + as attributes instead of elements by default. + <li>{@link org.apache.juneau.xml.annotation.XmlFormat#ELEMENT} format can now be applied to bean properties to override the {@link org.apache.juneau.xml.annotation.XmlFormat#ATTRS} + setting above on specific bean properties. + <li>New {@link org.apache.juneau.xml.annotation.XmlFormat#ELEMENTS} format can be applied to a bean property of type array/Collection to represent the child elements. + <li>New {@link org.apache.juneau.xml.annotation.XmlFormat#MIXED} format can be applied to a bean property of type array/Collection to represent mixed content (text + child elements). + <li>New {@link org.apache.juneau.xml.annotation.XmlFormat#TEXT} format can be applied to a bean property of a single object to represent a text node as a child. + <li>New {@link org.apache.juneau.xml.annotation.XmlFormat#XMLTEXT} format that's identical to {@link org.apache.juneau.xml.annotation.XmlFormat#TEXT} except + XML content is not escaped and serialized directly as the child content. The parser will reconvert this to the original XML text during parsing. + </ul> + <li>New support methodology and other improvements to {@link org.apache.juneau.xml} documentation. + <li>Eliminated unnecessary <xt><string></xt> elements. + <li>Eliminated <code><del>XmlContentHandler</del></code> class. + <li>Parser efficiency improvements through reuse of string builders. + <li>Reworked and simplified the default XML serializers. The {@link org.apache.juneau.xml.XmlSerializer#DEFAULT} serializer now has namespaces disabled, + and {@link org.apache.juneau.xml.XmlSerializer#DEFAULT_NS} has namespaces enabled. The 'XML-JSON' serializers have been eliminated. + <li>Eliminated the <code>addJsonTypeAttrs</code> and <code>addJsonStringTypeAttrs</code> settings. + <li>Namespace support is now disabled by default. + </ul> + <li>Improvements to HTML serialization support. + <ul> + <li>Parser converted from <code>XMLEventReader</code>-based to <code>XMLStreamReader</code>. + <li>Eliminated many unnecessary type tags and <xt><string></xt> elements and improved the readable layout. + The new format is much leaner. + <li>New support methodology section added to {@link org.apache.juneau.html} documentation. + </ul> + <li>New HTML5 DTO support: {@link org.apache.juneau.dto.html5}. <li>{@link org.apache.juneau.BeanContext} class split into separate {@link org.apache.juneau.BeanContext} and {@link org.apache.juneau.BeanSession} classes. <ul> <li>Session object meant to be single-use that can be discarded after use and contains session-level object cache and overridable Locale and TimeZone. @@ -5112,6 +5144,19 @@ <li>{@link org.apache.juneau.transforms.CalendarSwap.DateTimeMedium},{@link org.apache.juneau.transforms.DateSwap.DateTimeMedium} - To {@link java.text.DateFormat#MEDIUM} date-time strings. <li>{@link org.apache.juneau.transforms.CalendarSwap.DateTimeShort},{@link org.apache.juneau.transforms.DateSwap.DateTimeShort} - To {@link java.text.DateFormat#SHORT} date-time strings. </ul> + <li>General improvements to Bean Dictionary support. + <ul> + <li>New {@link org.apache.juneau.BeanDictionary} class can be used for defining reusable sets of bean dictionaries. + <li>New {@link org.apache.juneau.annotation.Bean#beanDictionary()} annotation. + </ul> + <li>Removed restriction on getters and setters to be prefixed with "getX/setX/isX" if a {@link org.apache.juneau.annotation.BeanProperty#name()} annotation is used. + <li>Improvements to ATOM DTO: + <ul> + <li>New {@link org.apache.juneau.dto.atom.AtomBuilder} class. + <li>New setter method names for a better fluent design. + <li>Updated {@link org.apache.juneau.dto.atom} documentation. + </ul> + <li>New {@link org.apache.juneau.transform.MapSwap} and {@link org.apache.juneau.transform.StringSwap} classes. </ul> <h6 class='topic'>org.apache.juneau.server</h6> @@ -5124,7 +5169,7 @@ <!-- ======================================================================================================== --> <a id="6.0.1"></a> - <h3 class='topic' onclick='toggle(this)'>6.0.1 (TBD)</h3> + <h3 class='topic' onclick='toggle(this)'>6.0.1 (Jan 3, 2017)</h3> <div class='topic'> <p> Juneau 6.0.1 is a minor update. @@ -5319,7 +5364,7 @@ Juno 5.2.0.1 is a moderate update. </p> - <h6 class='topic'>com.<h6 class='topic'>Core</h6>.team.juno</h6> + <h6 class='topic'>com.ibm.team.juno</h6> <ul class='spaced-list'> <li>Improved support for multi-line values in config files. Any line that begins with whitespace is interpreted as a continuation of the previous line. @@ -6308,7 +6353,7 @@ <h6 class='topic'>Server</h6> <ul class='spaced-list'> - <li>REST method parameters can now be generic types (e.g. <del><ja>@Param</ja></del>(<js>"foo"</js>) Map<String,Integer> foo</code>). + <li>REST method parameters can now be generic types (e.g. <del><ja>@Param</ja>(<js>"foo"</js>) Map<String,Integer> foo</del>). This applies to headers, attributes, and parameters. <li>New <del><code>@Param.multipart()</code></del> and <del><code>@Query.multipart()</code></del> annotations @@ -7164,11 +7209,11 @@ </ul> </li> <li> - New {@link org.apache.juneau.xml.annotation.XmlFormat#CONTENT} enum value.<br> + New <code><del>XmlFormat.CONTENT</del></code> enum value.<br> Allows bean properties to be persisted as XML element text. </li> <li> - New {@link org.apache.juneau.xml.XmlContentHandler} class and {@link org.apache.juneau.xml.annotation.Xml#contentHandler() @Xml.contentHandler} annotation.<br> + New <code><del>XmlContentHandler</del></code> class and <code><del>@Xml.contentHandler</del></code> annotation.<br> Allows customized serialization and parsing of beans to XML element text.<br> Added for support of ATOM text content that must support both plain text and embedded XHTML. </li>
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/main/javadoc/resources/juneau-code.css ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/javadoc/resources/juneau-code.css b/juneau-core/src/main/javadoc/resources/juneau-code.css index 57a124d..f48f7cd 100644 --- a/juneau-core/src/main/javadoc/resources/juneau-code.css +++ b/juneau-core/src/main/javadoc/resources/juneau-code.css @@ -43,6 +43,7 @@ * <xa> - XML attribute * <xc> - XML comment * <xs> - XML string + * <xv> - XML value * <mk> - Manifest file key * <mv> - Manifest file value * <cc> - Config file comment @@ -110,6 +111,7 @@ xt { color: DarkCyan; } xa { color: purple; } xc { color: mediumblue; } xs { color: blue; font-style: italic; } +xv { color: black; } /*--- Manifest-file code effects ---*/ mk { color: DarkRed; font-weight: bold; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/BeanConfigTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/BeanConfigTest.java b/juneau-core/src/test/java/org/apache/juneau/BeanConfigTest.java index e17f842..de7fe8b 100755 --- a/juneau-core/src/test/java/org/apache/juneau/BeanConfigTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/BeanConfigTest.java @@ -751,9 +751,9 @@ public class BeanConfigTest { assertDifferentCache(p1, p2); } - public static class DummyPojoSwapA extends PojoSwap<A,ObjectMap> {} - public static class DummyPojoSwapB extends PojoSwap<B,ObjectMap> {} - public static class DummyPojoSwapC extends PojoSwap<C,ObjectMap> {} + public static class DummyPojoSwapA extends MapSwap<A> {} + public static class DummyPojoSwapB extends MapSwap<B> {} + public static class DummyPojoSwapC extends MapSwap<C> {} public static class DummyBeanFilterA extends BeanFilterBuilder { public DummyBeanFilterA() { super(A.class); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/JacocoDummyTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/JacocoDummyTest.java b/juneau-core/src/test/java/org/apache/juneau/JacocoDummyTest.java index 6d1ecf5..98b1212 100755 --- a/juneau-core/src/test/java/org/apache/juneau/JacocoDummyTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/JacocoDummyTest.java @@ -41,7 +41,7 @@ public class JacocoDummyTest { ConfigFileFormat.valueOf(ConfigFileFormat.INI.toString()); RdfCollectionFormat.valueOf(RdfCollectionFormat.DEFAULT.toString()); - XmlFormat.valueOf(XmlFormat.NORMAL.toString()); + XmlFormat.valueOf(XmlFormat.DEFAULT.toString()); Visibility.valueOf(Visibility.DEFAULT.toString()); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/PojoSwapTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/PojoSwapTest.java b/juneau-core/src/test/java/org/apache/juneau/PojoSwapTest.java index 4c208a9..d9b7944 100755 --- a/juneau-core/src/test/java/org/apache/juneau/PojoSwapTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/PojoSwapTest.java @@ -43,7 +43,7 @@ public class PojoSwapTest { assertEquals("{xfoox:'xbarx'}", r); } - public static class ASwap extends PojoSwap<String,String> { + public static class ASwap extends StringSwap<String> { @Override public String swap(BeanSession session, String o) throws SerializeException { return "x" + o + "x"; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/TestUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/TestUtils.java b/juneau-core/src/test/java/org/apache/juneau/TestUtils.java index 01d0903..a42ce8c 100755 --- a/juneau-core/src/test/java/org/apache/juneau/TestUtils.java +++ b/juneau-core/src/test/java/org/apache/juneau/TestUtils.java @@ -217,7 +217,7 @@ public class TestUtils { private static Pattern pTargetNs = Pattern.compile("targetNamespace=['\"]([^'\"]+)['\"]"); public static void validateXml(Object o) throws Exception { - validateXml(o, XmlSerializer.DEFAULT_SQ); + validateXml(o, XmlSerializer.DEFAULT_NS_SQ); } /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripAddClassAttrsTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripAddClassAttrsTest.java b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripAddClassAttrsTest.java index a325b08..1a7fb26 100755 --- a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripAddClassAttrsTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripAddClassAttrsTest.java @@ -61,7 +61,7 @@ public class RoundTripAddClassAttrsTest extends RoundTripTest { }, { /* 3 */ "XmlSerializer.DEFAULT/XmlParser.DEFAULT", - new XmlSerializer.XmlJson().setProperty(SERIALIZER_addBeanTypeProperties, true).setClassLoader(RoundTripAddClassAttrsTest.class.getClassLoader()), + new XmlSerializer().setProperty(SERIALIZER_addBeanTypeProperties, true).setClassLoader(RoundTripAddClassAttrsTest.class.getClassLoader()), new XmlParser().setProperty(BEAN_useInterfaceProxies, false).setClassLoader(RoundTripAddClassAttrsTest.class.getClassLoader()), CHECK_XML_WHITESPACE | VALIDATE_XML }, http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripLargeObjectsTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripLargeObjectsTest.java b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripLargeObjectsTest.java index 2d5b243..63575fd 100755 --- a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripLargeObjectsTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripLargeObjectsTest.java @@ -69,13 +69,13 @@ public class RoundTripLargeObjectsTest extends RoundTripTest { }, { /* 3 */ "Xml DEFAULT w/namespaces,validation", - new XmlSerializer.XmlJsonSq().setProperty(SERIALIZER_trimNullProperties, false).setProperty(XML_addNamespaceUrisToRoot, true).setProperty(SERIALIZER_useIndentation, true), + new XmlSerializer.NsSq().setProperty(SERIALIZER_trimNullProperties, false).setProperty(XML_addNamespaceUrisToRoot, true).setProperty(SERIALIZER_useIndentation, true), XmlParser.DEFAULT, CHECK_XML_WHITESPACE | VALIDATE_XML }, { /* 4 */ "Xml DEFAULT wo/namespaces,validation", - new XmlSerializer.SimpleXmlJsonSq().setProperty(SERIALIZER_trimNullProperties, false), + new XmlSerializer.Sq().setProperty(SERIALIZER_trimNullProperties, false), XmlParser.DEFAULT, CHECK_XML_WHITESPACE }, http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripMapsTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripMapsTest.java b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripMapsTest.java index 602913f..abd4c72 100755 --- a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripMapsTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripMapsTest.java @@ -112,13 +112,13 @@ public class RoundTripMapsTest extends RoundTripTest { r = s.serialize(t); assertEquals(e, r); - s = new XmlSerializer.SimpleXmlJsonSq().addPojoSwaps(getPojoSwaps()).setProperty(SERIALIZER_trimNullProperties, false); - e = "<object><AQID>a</AQID><BAUG nil='true'/><_x0000_>b</_x0000_></object>"; + s = new XmlSerializer.NsSq().addPojoSwaps(getPojoSwaps()).setProperty(SERIALIZER_trimNullProperties, false); + e = "<object><AQID>a</AQID><BAUG _type='null'/><_x0000_>b</_x0000_></object>"; r = s.serialize(t); assertEquals(e, r); s = new HtmlSerializer.Sq().addPojoSwaps(getPojoSwaps()).setProperty(SERIALIZER_trimNullProperties, false).setProperty(HTML_addKeyValueTableHeaders, true); - e = "<table _type='object'><tr><th><string>key</string></th><th><string>value</string></th></tr><tr><td><string>AQID</string></td><td><string>a</string></td></tr><tr><td><string>BAUG</string></td><td><null/></td></tr><tr><td><null/></td><td><string>b</string></td></tr></table>"; + e = "<table><tr><th>key</th><th>value</th></tr><tr><td>AQID</td><td>a</td></tr><tr><td>BAUG</td><td><null/></td></tr><tr><td><null/></td><td>b</td></tr></table>"; r = s.serialize(t); assertEquals(e, r); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java index 3ea2dd9..ece4771 100755 --- a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTest.java @@ -70,13 +70,13 @@ public abstract class RoundTripTest { }, { /* 3 */ "Xml - namespaces, validation, readable", - new XmlSerializer.XmlJsonSq().setProperty(SERIALIZER_trimNullProperties, false).setProperty(XML_addNamespaceUrisToRoot, true).setProperty(SERIALIZER_useIndentation, true), + new XmlSerializer.NsSq().setProperty(SERIALIZER_trimNullProperties, false).setProperty(XML_addNamespaceUrisToRoot, true).setProperty(SERIALIZER_useIndentation, true), XmlParser.DEFAULT, CHECK_XML_WHITESPACE | VALIDATE_XML }, { /* 4 */ "Xml - no namespaces, validation", - new XmlSerializer.SimpleXmlJsonSq().setProperty(SERIALIZER_trimNullProperties, false), + new XmlSerializer.Sq().setProperty(SERIALIZER_trimNullProperties, false), XmlParser.DEFAULT, CHECK_XML_WHITESPACE }, http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java index 323a8c3..fbf0805 100755 --- a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java @@ -233,7 +233,7 @@ public class RoundTripTransformBeansTest extends RoundTripTest { public String f1; } - public static class BSwap extends PojoSwap<B,String> { + public static class BSwap extends StringSwap<B> { @Override /* PojoSwap */ public String swap(BeanSession session, B o) throws SerializeException { return o.f1; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/dto/atom/AtomTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/dto/atom/AtomTest.java b/juneau-core/src/test/java/org/apache/juneau/dto/atom/AtomTest.java index dfe130d..aadc082 100755 --- a/juneau-core/src/test/java/org/apache/juneau/dto/atom/AtomTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/dto/atom/AtomTest.java @@ -12,11 +12,11 @@ // *************************************************************************************************************************** package org.apache.juneau.dto.atom; -import static javax.xml.bind.DatatypeConverter.*; import static org.apache.juneau.BeanContext.*; import static org.apache.juneau.TestUtils.*; import static org.apache.juneau.xml.XmlSerializerContext.*; import static org.junit.Assert.*; +import static org.apache.juneau.dto.atom.AtomBuilder.*; import java.net.*; @@ -26,74 +26,173 @@ import org.junit.*; @SuppressWarnings("javadoc") public class AtomTest { + public Feed createFeed() throws Exception { + return + feed("tag:foo.org", "Title", "2016-12-31T01:02:03-04:00") + .subtitle(text("html").text("Subtitle")) + .links( + link("alternate", "text/html", "http://foo.org/").hreflang("en"), + link("self", "application/atom+xml", "http://foo.org/feed.atom") + ) + .rights("Copyright (c) 2016, Apache Foundation") + .generator( + generator("Example Toolkit").uri("http://www.foo.org/").version("1.0") + ) + .entries( + entry("tag:foo.org", "Title", "2016-12-31T01:02:03-04:00") + .links( + link("alternate", "text/html", "http://foo.org/2005/04/02/atom"), + link("enclosure", "audio/mpeg", "http://foo.org/audio/foobar.mp3").length(1337) + ) + .published("2016-12-31T01:02:03-04:00") + .authors( + person("John Smith").uri(new URI("http://foo.org/")).email("[email protected]") + ) + .contributors( + person("John Smith"), + person("Jane Smith") + ) + .content( + content("xhtml") + .lang("en") + .base("http://foo.org/") + .text("<div><p><i>[Sample content]</i></p></div>") + ) + ); + } + @Test - public void testBasic() throws Exception { + public void testNormal() throws Exception { XmlSerializer s; XmlParser p = XmlParser.DEFAULT; - String expected, r; - Feed f2; + String r; + Feed f = createFeed(), f2; - Feed f = new Feed() - .setTitle(new Text("text", "Title")) - .setSubTitle(new Text("html", "Subtitle")) - .setUpdated(parseDateTime("2016-12-31T01:02:03-04:00")) - .setId(new Id("tag:foo.org")) - .addLinks( - new Link("alternate", "text/html", "http://foo.org/").setHreflang("en"), - new Link("self", "application/atom+xml", "http://foo.org/feed.atom") - ) - .setRights(new Text("Copyright (c) 2016, Apache Foundation")) - .setGenerator(new Generator("Example Toolkit").setUri(new URI("http://www.foo.org/")).setVersion("1.0")) - .addEntries( - new Entry() - .setTitle(new Text("Title")) - .addLinks( - new Link("alternate", "text/html", "http://foo.org/2005/04/02/atom"), - new Link("enclosure", "audio/mpeg", "http://foo.org/audio/foobar.mp3").setLength(1337) - ) - .setId(new Id("tag:foo.org")) - .setUpdated(parseDateTime("2016-12-31T01:02:03-04:00")) - .setPublished(parseDateTime("2016-12-31T01:02:03-04:00")) - .addAuthors(new Person("John Smith").setUri(new URI("http://foo.org/")).setEmail("[email protected]")) - .addContributors( - new Person("John Smith"), - new Person("Jane Smith") - ) - .setContent( - new Content() - .setLang("en") - .setBase(new URI("http://foo.org/")) - .setType("xhtml") - .setText("<div xmlns=\"http://www.w3.org/1999/xhtml\"><p><i>[Sample content]</i></p></div>") - ) - ) - ; + String expected = + "<feed>\n" + +" <entry>\n" + +" <author>\n" + +" <email>[email protected]</email>\n" + +" <name>John Smith</name>\n" + +" <uri>http://foo.org/</uri>\n" + +" </author>\n" + +" <content base='http://foo.org/' lang='en' type='xhtml'><div><p><i>[Sample content]</i></p></div></content>\n" + +" <contributor>\n" + +" <name>John Smith</name>\n" + +" </contributor>\n" + +" <contributor>\n" + +" <name>Jane Smith</name>\n" + +" </contributor>\n" + +" <id>tag:foo.org</id>\n" + +" <link href='http://foo.org/2005/04/02/atom' rel='alternate' type='text/html'/>\n" + +" <link href='http://foo.org/audio/foobar.mp3' length='1337' rel='enclosure' type='audio/mpeg'/>\n" + +" <published>2016-12-31T01:02:03-04:00</published>\n" + +" <title>Title</title>\n" + +" <updated>2016-12-31T01:02:03-04:00</updated>\n" + +" </entry>\n" + +" <generator uri='http://www.foo.org/' version='1.0'>Example Toolkit</generator>\n" + +" <id>tag:foo.org</id>\n" + +" <link href='http://foo.org/' hreflang='en' rel='alternate' type='text/html'/>\n" + +" <link href='http://foo.org/feed.atom' rel='self' type='application/atom+xml'/>\n" + +" <rights>Copyright (c) 2016, Apache Foundation</rights>\n" + +" <subtitle type='html'>Subtitle</subtitle>\n" + +" <title>Title</title>\n" + +" <updated>2016-12-31T01:02:03-04:00</updated>\n" + +"</feed>\n"; - //-------------------------------------------------------------------------------- - // Test without namespaces - //-------------------------------------------------------------------------------- s = new XmlSerializer.SqReadable().setProperty(XML_enableNamespaces, false).setProperty(BEAN_sortProperties, true); - expected = readFile(getClass().getResource("/dto/atom/test1.xml").getPath()); r = s.serialize(f); assertEquals(expected, r); f2 = p.parse(r, Feed.class); assertEqualObjects(f, f2); + } + + @Test + public void testWithNamespaces() throws Exception { + XmlSerializer s; + XmlParser p = XmlParser.DEFAULT; + String r; + Feed f = createFeed(), f2; + + String expected = + "<atom:feed xmlns='http://www.apache.org/2013/Juneau' xmlns:atom='http://www.w3.org/2005/Atom/' xmlns:xml='http://www.w3.org/XML/1998/namespace'>\n" + +" <atom:entry>\n" + +" <atom:author>\n" + +" <atom:email>[email protected]</atom:email>\n" + +" <atom:name>John Smith</atom:name>\n" + +" <atom:uri>http://foo.org/</atom:uri>\n" + +" </atom:author>\n" + +" <atom:content xml:base='http://foo.org/' xml:lang='en' type='xhtml'><div><p><i>[Sample content]</i></p></div></atom:content>\n" + +" <atom:contributor>\n" + +" <atom:name>John Smith</atom:name>\n" + +" </atom:contributor>\n" + +" <atom:contributor>\n" + +" <atom:name>Jane Smith</atom:name>\n" + +" </atom:contributor>\n" + +" <atom:id>tag:foo.org</atom:id>\n" + +" <atom:link href='http://foo.org/2005/04/02/atom' rel='alternate' type='text/html'/>\n" + +" <atom:link href='http://foo.org/audio/foobar.mp3' length='1337' rel='enclosure' type='audio/mpeg'/>\n" + +" <atom:published>2016-12-31T01:02:03-04:00</atom:published>\n" + +" <atom:title>Title</atom:title>\n" + +" <atom:updated>2016-12-31T01:02:03-04:00</atom:updated>\n" + +" </atom:entry>\n" + +" <atom:generator uri='http://www.foo.org/' version='1.0'>Example Toolkit</atom:generator>\n" + +" <atom:id>tag:foo.org</atom:id>\n" + +" <atom:link href='http://foo.org/' hreflang='en' rel='alternate' type='text/html'/>\n" + +" <atom:link href='http://foo.org/feed.atom' rel='self' type='application/atom+xml'/>\n" + +" <atom:rights>Copyright (c) 2016, Apache Foundation</atom:rights>\n" + +" <atom:subtitle type='html'>Subtitle</atom:subtitle>\n" + +" <atom:title>Title</atom:title>\n" + +" <atom:updated>2016-12-31T01:02:03-04:00</atom:updated>\n" + +"</atom:feed>\n"; - //-------------------------------------------------------------------------------- - // Test with namespaces - //-------------------------------------------------------------------------------- - s = new XmlSerializer.SqReadable().setProperty(BEAN_sortProperties, true); - expected = readFile(getClass().getResource("/dto/atom/test2.xml").getPath()); + s = new XmlSerializer.SqReadable().setProperty(XML_enableNamespaces, true).setProperty(XML_addNamespaceUrisToRoot, true).setProperty(BEAN_sortProperties, true); r = s.serialize(f); assertEquals(expected, r); f2 = p.parse(r, Feed.class); assertEqualObjects(f, f2); + } + + @Test + public void testWithNamespacesWithAtomAsDefault() throws Exception { + XmlSerializer s; + XmlParser p = XmlParser.DEFAULT; + String r; + Feed f = createFeed(), f2; + + String expected = + "<feed xmlns='http://www.w3.org/2005/Atom/' xmlns:xml='http://www.w3.org/XML/1998/namespace'>\n" + +" <entry>\n" + +" <author>\n" + +" <email>[email protected]</email>\n" + +" <name>John Smith</name>\n" + +" <uri>http://foo.org/</uri>\n" + +" </author>\n" + +" <content xml:base='http://foo.org/' xml:lang='en' type='xhtml'><div><p><i>[Sample content]</i></p></div></content>\n" + +" <contributor>\n" + +" <name>John Smith</name>\n" + +" </contributor>\n" + +" <contributor>\n" + +" <name>Jane Smith</name>\n" + +" </contributor>\n" + +" <id>tag:foo.org</id>\n" + +" <link href='http://foo.org/2005/04/02/atom' rel='alternate' type='text/html'/>\n" + +" <link href='http://foo.org/audio/foobar.mp3' length='1337' rel='enclosure' type='audio/mpeg'/>\n" + +" <published>2016-12-31T01:02:03-04:00</published>\n" + +" <title>Title</title>\n" + +" <updated>2016-12-31T01:02:03-04:00</updated>\n" + +" </entry>\n" + +" <generator uri='http://www.foo.org/' version='1.0'>Example Toolkit</generator>\n" + +" <id>tag:foo.org</id>\n" + +" <link href='http://foo.org/' hreflang='en' rel='alternate' type='text/html'/>\n" + +" <link href='http://foo.org/feed.atom' rel='self' type='application/atom+xml'/>\n" + +" <rights>Copyright (c) 2016, Apache Foundation</rights>\n" + +" <subtitle type='html'>Subtitle</subtitle>\n" + +" <title>Title</title>\n" + +" <updated>2016-12-31T01:02:03-04:00</updated>\n" + +"</feed>\n"; - //-------------------------------------------------------------------------------- - // Test with namespaces but with atom as the default namespace - //-------------------------------------------------------------------------------- - s = new XmlSerializer.SqReadable().setProperty(XML_defaultNamespaceUri, "atom").setProperty(BEAN_sortProperties, true); - expected = readFile(getClass().getResource("/dto/atom/test3.xml").getPath()); + s = new XmlSerializer.SqReadable().setProperty(XML_defaultNamespace, "atom").setProperty(XML_enableNamespaces, true).setProperty(XML_addNamespaceUrisToRoot, true).setProperty(BEAN_sortProperties, true); r = s.serialize(f); assertEquals(expected, r); f2 = p.parse(r, Feed.class); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/dto/cognos/CognosXmlTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/dto/cognos/CognosXmlTest.java b/juneau-core/src/test/java/org/apache/juneau/dto/cognos/CognosXmlTest.java index 0750ce9..90db605 100755 --- a/juneau-core/src/test/java/org/apache/juneau/dto/cognos/CognosXmlTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/dto/cognos/CognosXmlTest.java @@ -32,7 +32,7 @@ public class CognosXmlTest { @Test public void test() throws Exception { String expected = "" - + "<dataset xmlns='http://developer.cognos.com/schemas/xmldata/1/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>\n" + + "<dataset xmlns='http://developer.cognos.com/schemas/xmldata/1/'>\n" + " <metadata>\n" + " <item name='asOfDate' type='xs:string' length='12'/>\n" + " <item name='rateOfReturn' type='xs:double'/>\n" @@ -74,7 +74,12 @@ public class CognosXmlTest { new Column("productLineCode", "xs:int") }; - XmlSerializer s = new XmlSerializer().setProperty(SERIALIZER_useIndentation, true).setProperty(SERIALIZER_quoteChar, '\'').setProperty(XML_defaultNamespaceUri, "cognos"); + XmlSerializer s = new XmlSerializer() + .setProperty(SERIALIZER_useIndentation, true) + .setProperty(SERIALIZER_quoteChar, '\'') + .setProperty(XML_defaultNamespace, "cognos") + .setProperty(XML_enableNamespaces, true) + .setProperty(XML_addNamespaceUrisToRoot, true); DataSet ds = new DataSet(c, rows, BeanContext.DEFAULT.createSession()); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/dto/html/BasicHtmlSchemaTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/dto/html/BasicHtmlSchemaTest.java b/juneau-core/src/test/java/org/apache/juneau/dto/html/BasicHtmlSchemaTest.java new file mode 100755 index 0000000..b3ba825 --- /dev/null +++ b/juneau-core/src/test/java/org/apache/juneau/dto/html/BasicHtmlSchemaTest.java @@ -0,0 +1,156 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you 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 org.apache.juneau.dto.html; + +import static org.junit.Assert.*; + +import java.util.*; + +import org.apache.juneau.dto.html5.*; +import org.apache.juneau.html.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.xml.*; +import org.junit.*; +import org.junit.runner.*; +import org.junit.runners.*; + +@RunWith(Parameterized.class) +@SuppressWarnings({"javadoc"}) +public class BasicHtmlSchemaTest { + + private static final WriterSerializer + sXmlSq = XmlSerializer.DEFAULT_SQ, + sXmlSqReadable = XmlSerializer.DEFAULT_SQ_READABLE, + sXmlNsSq = XmlSerializer.DEFAULT_NS_SQ, + sHtmlSq = HtmlSerializer.DEFAULT_SQ, + sHtmlSqReadable = HtmlSerializer.DEFAULT_SQ_READABLE; + + private static final ReaderParser + pXml = XmlParser.DEFAULT, + pHtml = HtmlParser.DEFAULT; + + private static final B btag = HtmlBuilder.b("bbb"); + + @Parameterized.Parameters + public static Collection<Object[]> getParameters() { + return Arrays.asList(new Object[][] { + { + "A-1", + HtmlBuilder.a("http://foo", "bar"), + "<a href='http://foo'>bar</a>", + "<a href='http://foo'>bar</a>\n", + "<a href='http://foo'>bar</a>", + "<a href='http://foo'>bar</a>", + "<a href='http://foo'>bar</a>\n", + }, + { + "A-2", + HtmlBuilder.a("http://foo", "bar", btag, "baz"), + "<a href='http://foo'>bar<b>bbb</b>baz</a>", + "<a href='http://foo'>bar<b>bbb</b>baz</a>\n", + "<a href='http://foo'>bar<b>bbb</b>baz</a>", + "<a href='http://foo'>bar<b>bbb</b>baz</a>", + "<a href='http://foo'>bar<b>bbb</b>baz</a>\n", + }, + }); + } + + + private String label, e1, e2, e3, e4, e5; + private Object in; + + public BasicHtmlSchemaTest(String label, Object in, String e1, String e2, String e3, String e4, String e5) throws Exception { + this.label = label; + this.in = in; + this.e1 = e1; + this.e2 = e2; + this.e3 = e3; + this.e4 = e4; + this.e5 = e5; + } + + private void testSerialize(WriterSerializer s, String expected) throws Exception { + try { + String r = s.serialize(in); + assertEquals(label + " serialize-normal failed", expected, r); + } catch (AssertionError e) { + throw e; + } catch (Exception e) { + throw new AssertionError(label + " test failed", e); + } + } + + private void testParse(WriterSerializer s, ReaderParser p, String expected) throws Exception { + try { + String r = s.serialize(in); + Object o = p.parse(r, in == null ? Object.class : in.getClass()); + r = s.serialize(o); + assertEquals(label + " parse-normal failed", expected, r); + } catch (AssertionError e) { + throw e; + } catch (Exception e) { + throw new AssertionError(label + " test failed", e); + } + } + + @Test + public void serializeXmlDefaultSq() throws Exception { + testSerialize(sXmlSq, e1); + } + + @Test + public void parseXmlDefaultSq() throws Exception { + testParse(sXmlSq, pXml, e1); + } + + @Test + public void serializeXmlDefaultSqReadable() throws Exception { + testSerialize(sXmlSqReadable, e2); + } + + @Test + public void parseXmlDefaultSqReadable() throws Exception { + testParse(sXmlSqReadable, pXml, e2); + } + + @Test + public void serializeXmlDefaultNsSq() throws Exception { + testSerialize(sXmlNsSq, e3); + } + + @Test + public void parseXmlDefaultNsSq() throws Exception { + testParse(sXmlNsSq, pXml, e3); + } + + @Test + public void serializeHtmlDefaultSq() throws Exception { + testSerialize(sHtmlSq, e4); + } + + @Test + public void parseHtmlDefaultSq() throws Exception { + testParse(sHtmlSq, pHtml, e4); + } + + @Test + public void serializeHtmlDefaultSqReadable() throws Exception { + testSerialize(sHtmlSqReadable, e5); + } + + @Test + public void parseHtmlDefaultSqReadable() throws Exception { + testParse(sHtmlSqReadable, pHtml, e5); + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/dto/jsonschema/JsonSchemaTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/dto/jsonschema/JsonSchemaTest.java b/juneau-core/src/test/java/org/apache/juneau/dto/jsonschema/JsonSchemaTest.java index 6680edf..e6883f5 100755 --- a/juneau-core/src/test/java/org/apache/juneau/dto/jsonschema/JsonSchemaTest.java +++ b/juneau-core/src/test/java/org/apache/juneau/dto/jsonschema/JsonSchemaTest.java @@ -30,9 +30,87 @@ public class JsonSchemaTest { String r; Schema t, t2; + String expected = + "{\n" + +" id: 'http://id', \n" + +" '$schema': 'http://schemaVersionUri', \n" + +" title: 'title', \n" + +" description: 'description', \n" + +" type: 'number', \n" + +" definitions: {\n" + +" definition: {\n" + +" '$ref': 'http://definition'\n" + +" }\n" + +" }, \n" + +" properties: {\n" + +" property: {\n" + +" type: 'number'\n" + +" }\n" + +" }, \n" + +" patternProperties: {\n" + +" '/pattern/': {\n" + +" type: 'number'\n" + +" }\n" + +" }, \n" + +" dependencies: {\n" + +" dependency: {\n" + +" '$ref': 'http://dependency'\n" + +" }\n" + +" }, \n" + +" items: [\n" + +" {\n" + +" type: 'number'\n" + +" }\n" + +" ], \n" + +" multipleOf: 1, \n" + +" maximum: 2, \n" + +" exclusiveMaximum: true, \n" + +" minimum: 3, \n" + +" exclusiveMinimum: true, \n" + +" maxLength: 4, \n" + +" minLength: 5, \n" + +" pattern: '/pattern/', \n" + +" additionalItems: [\n" + +" {\n" + +" type: 'number'\n" + +" }\n" + +" ], \n" + +" maxItems: 6, \n" + +" minItems: 7, \n" + +" uniqueItems: true, \n" + +" maxProperties: 8, \n" + +" minProperties: 9, \n" + +" required: [\n" + +" 'required'\n" + +" ], \n" + +" additionalProperties: {\n" + +" '$ref': 'http://additionalProperty'\n" + +" }, \n" + +" 'enum': [\n" + +" 'enum'\n" + +" ], \n" + +" allOf: [\n" + +" {\n" + +" '$ref': 'http://allOf'\n" + +" }\n" + +" ], \n" + +" anyOf: [\n" + +" {\n" + +" '$ref': 'http://anyOf'\n" + +" }\n" + +" ], \n" + +" oneOf: [\n" + +" {\n" + +" '$ref': 'http://oneOf'\n" + +" }\n" + +" ], \n" + +" not: {\n" + +" '$ref': 'http://not'\n" + +" }\n" + +"}"; + t = getTest1(); r = s.serialize(t); - String expected = readFile(getClass().getResource("/dto/jsonschema/test1.json").getPath()); assertEquals(expected, r); t2 = p.parse(r, Schema.class); assertEqualObjects(t, t2); @@ -45,9 +123,30 @@ public class JsonSchemaTest { String r; Schema t, t2; + String expected = + "{\n" + +" id: 'http://id', \n" + +" '$schema': 'http://schemaVersionUri', \n" + +" type: [\n" + +" 'string', \n" + +" 'number'\n" + +" ], \n" + +" definitions: {\n" + +" definition: {\n" + +" id: 'http://definition'\n" + +" }\n" + +" }, \n" + +" items: [\n" + +" {\n" + +" '$ref': 'http://items'\n" + +" }\n" + +" ], \n" + +" additionalItems: true, \n" + +" additionalProperties: true\n" + +"}"; + t = getTest2(); r = s.serialize(t); - String expected = readFile(getClass().getResource("/dto/jsonschema/test2.json").getPath()); assertEquals(expected, r); t2 = p.parse(r, Schema.class); assertEqualObjects(t, t2); @@ -86,7 +185,8 @@ public class JsonSchemaTest { .addAllOf(new SchemaRef("http://allOf")) .addAnyOf(new SchemaRef("http://anyOf")) .addOneOf(new SchemaRef("http://oneOf")) - .setNot(new SchemaRef("http://not")); + .setNot(new SchemaRef("http://not")) + ; } /** Bean with other possible property value types not covered in test1 */ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb01038/juneau-core/src/test/java/org/apache/juneau/html/BasicHtmlTest.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/test/java/org/apache/juneau/html/BasicHtmlTest.java b/juneau-core/src/test/java/org/apache/juneau/html/BasicHtmlTest.java new file mode 100644 index 0000000..2fefaf4 --- /dev/null +++ b/juneau-core/src/test/java/org/apache/juneau/html/BasicHtmlTest.java @@ -0,0 +1,1614 @@ +// *************************************************************************************************************************** +// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * +// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * +// * to you 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 org.apache.juneau.html; + +import static org.junit.Assert.*; + +import java.util.*; + +import org.apache.juneau.annotation.*; +import org.junit.*; +import org.junit.runner.*; +import org.junit.runners.*; + +@RunWith(Parameterized.class) +@SuppressWarnings({"javadoc","serial"}) +public class BasicHtmlTest { + + private static final HtmlSerializer + s1 = HtmlSerializer.DEFAULT_SQ, + s2 = HtmlSerializer.DEFAULT_SQ_READABLE; + private static final HtmlParser parser = HtmlParser.DEFAULT; + + @Parameterized.Parameters + public static Collection<Object[]> getParameters() { + return Arrays.asList(new Object[][] { + + { + "SimpleTypes-1", + "foo", + "<string>foo</string>", + "<string>foo</string>", + }, + { + "SimpleTypes-2", + true, + "<boolean>true</boolean>", + "<boolean>true</boolean>", + }, + { + "SimpleTypes-3", + 123, + "<number>123</number>", + "<number>123</number>", + }, + { + "SimpleTypes-4", + 1.23f, + "<number>1.23</number>", + "<number>1.23</number>", + }, + { + "SimpleTypes-5", + null, + "<null/>", + "<null/>", + }, + { + "Arrays-1", + new String[]{"foo"}, + "<ul><li>foo</li></ul>", + "<ul>\n\t<li>foo</li>\n</ul>\n", + }, + { + "Arrays-2", + new String[]{null}, + "<ul><li><null/></li></ul>", + "<ul>\n\t<li><null/></li>\n</ul>\n", + }, + { + "Arrays-3", + new Object[]{"foo",123,true}, + "<ul><li>foo</li><li><number>123</number></li><li><boolean>true</boolean></li></ul>", + "<ul>\n\t<li>foo</li>\n\t<li><number>123</number></li>\n\t<li><boolean>true</boolean></li>\n</ul>\n", + }, + { + "Arrays-4", + new int[]{123}, + "<ul><li>123</li></ul>", + "<ul>\n\t<li>123</li>\n</ul>\n", + }, + { + "Arrays-5", + new boolean[]{true}, + "<ul><li>true</li></ul>", + "<ul>\n\t<li>true</li>\n</ul>\n", + }, + { + "Arrays-6", + new String[][]{{"foo"}}, + "<ul><li><ul><li>foo</li></ul></li></ul>", + "<ul>\n\t<li>\n\t\t<ul>\n\t\t\t<li>foo</li>\n\t\t</ul>\n\t</li>\n</ul>\n", + }, + { + "MapWithStrings", + new MapWithStrings().append("k1", "v1").append("k2", null), + "<table>" + +"<tr>" + +"<td>k1</td>" + +"<td>v1</td>" + +"</tr>" + +"<tr>" + +"<td>k2</td>" + +"<td><null/></td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>k1</td>\n" + +"\t\t<td>v1</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>k2</td>\n" + +"\t\t<td><null/></td>\n" + +"\t</tr>\n" + +"</table>\n", + }, + { + "MapsWithNumbers", + new MapWithNumbers().append("k1", 123).append("k2", 1.23).append("k3", null), + "<table>" + +"<tr>" + +"<td>k1</td>" + +"<td>123</td>" + +"</tr>" + +"<tr>" + +"<td>k2</td>" + +"<td>1.23</td>" + +"</tr>" + +"<tr>" + +"<td>k3</td>" + +"<td><null/></td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>k1</td>\n" + +"\t\t<td>123</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>k2</td>\n" + +"\t\t<td>1.23</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>k3</td>\n" + +"\t\t<td><null/></td>\n" + +"\t</tr>\n" + +"</table>\n", + }, + { + "MapWithObjects", + new MapWithObjects().append("k1", "v1").append("k2", 123).append("k3", 1.23).append("k4", true).append("k5", null), + "<table>" + +"<tr>" + +"<td>k1</td>" + +"<td>v1</td>" + +"</tr>" + +"<tr>" + +"<td>k2</td>" + +"<td><number>123</number></td>" + +"</tr>" + +"<tr>" + +"<td>k3</td>" + +"<td><number>1.23</number></td>" + +"</tr>" + +"<tr>" + +"<td>k4</td>" + +"<td><boolean>true</boolean></td>" + +"</tr>" + +"<tr>" + +"<td>k5</td>" + +"<td><null/></td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>k1</td>\n" + +"\t\t<td>v1</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>k2</td>\n" + +"\t\t<td><number>123</number></td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>k3</td>\n" + +"\t\t<td><number>1.23</number></td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>k4</td>\n" + +"\t\t<td><boolean>true</boolean></td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>k5</td>\n" + +"\t\t<td><null/></td>\n" + +"\t</tr>\n" + +"</table>\n", + }, + { + "ListWithStrings", + new ListWithStrings().append("foo").append(null), + "<ul><li>foo</li><li><null/></li></ul>", + "<ul>\n\t<li>foo</li>\n\t<li><null/></li>\n</ul>\n", + }, + { + "ListWithNumbers", + new ListWithNumbers().append(123).append(1.23).append(null), + "<ul><li>123</li><li>1.23</li><li><null/></li></ul>", + "<ul>\n\t<li>123</li>\n\t<li>1.23</li>\n\t<li><null/></li>\n</ul>\n", + }, + { + "ListWithObjects", + new ListWithObjects().append("foo").append(123).append(1.23).append(true).append(null), + "<ul><li>foo</li><li><number>123</number></li><li><number>1.23</number></li><li><boolean>true</boolean></li><li><null/></li></ul>", + "<ul>\n\t<li>foo</li>\n\t<li><number>123</number></li>\n\t<li><number>1.23</number></li>\n\t<li><boolean>true</boolean></li>\n\t<li><null/></li>\n</ul>\n", + }, + { + "BeanWithNormalProperties", + new BeanWithNormalProperties().init(), + "<table>" + +"<tr>" + +"<td>a</td>" + +"<td>foo</td>" + +"</tr>" + +"<tr>" + +"<td>b</td>" + +"<td>123</td>" + +"</tr>" + +"<tr>" + +"<td>c</td>" + +"<td>bar</td>" + +"</tr>" + +"<tr>" + +"<td>d</td>" + +"<td><number>456</number></td>" + +"</tr>" + +"<tr>" + +"<td>e</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>h</td>" + +"<td>qux</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>f</td>" + +"<td>" + +"<ul>" + +"<li>baz</li>" + +"</ul>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>g</td>" + +"<td>" + +"<ul>" + +"<li>789</li>" + +"</ul>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>a</td>\n" + +"\t\t<td>foo</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b</td>\n" + +"\t\t<td>123</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>c</td>\n" + +"\t\t<td>bar</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>d</td>\n" + +"\t\t<td><number>456</number></td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>e</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>h</td>\n" + +"\t\t\t\t\t<td>qux</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>f</td>\n" + +"\t\t<td>\n" + +"\t\t\t<ul>\n" + +"\t\t\t\t<li>baz</li>\n" + +"\t\t\t</ul>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>g</td>\n" + +"\t\t<td>\n" + +"\t\t\t<ul>\n" + +"\t\t\t\t<li>789</li>\n" + +"\t\t\t</ul>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n", + }, + { + "BeanWithMapProperties", + new BeanWithMapProperties().init(), + "<table>" + +"<tr>" + +"<td>a</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>k1</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>b</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>k2</td>" + +"<td>123</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>c</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>k3</td>" + +"<td>bar</td>" + +"</tr>" + +"<tr>" + +"<td>k4</td>" + +"<td><number>456</number></td>" + +"</tr>" + +"<tr>" + +"<td>k5</td>" + +"<td><boolean>true</boolean></td>" + +"</tr>" + +"<tr>" + +"<td>k6</td>" + +"<td><null/></td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>a</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k1</td>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k2</td>\n" + +"\t\t\t\t\t<td>123</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>c</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k3</td>\n" + +"\t\t\t\t\t<td>bar</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k4</td>\n" + +"\t\t\t\t\t<td><number>456</number></td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k5</td>\n" + +"\t\t\t\t\t<td><boolean>true</boolean></td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k6</td>\n" + +"\t\t\t\t\t<td><null/></td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n" + }, + { + "BeanWithTypeName", + new BeanWithTypeName().init(), + "<table _type='X'>" + +"<tr>" + +"<td>a</td>" + +"<td>123</td>" + +"</tr>" + +"<tr>" + +"<td>b</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>", + "<table _type='X'>\n" + +"\t<tr>\n" + +"\t\t<td>a</td>\n" + +"\t\t<td>123</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b</td>\n" + +"\t\t<td>foo</td>\n" + +"\t</tr>\n" + +"</table>\n", + }, + { + "BeanWithPropertiesWithTypeNames", + new BeanWithPropertiesWithTypeNames().init(), + "<table>" + +"<tr>" + +"<td>b1</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>b</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>b2</td>" + +"<td>" + +"<table _type='B'>" + +"<tr>" + +"<td>b</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>b1</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>b</td>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b2</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='B'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>b</td>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n" + }, + { + "BeanWithPropertiesWithArrayTypeNames", + new BeanWithPropertiesWithArrayTypeNames().init(), + "<table>" + +"<tr>" + +"<td>b1</td>" + +"<td>" + +"<table _type='array'>" + +"<tr>" + +"<th>b</th>" + +"</tr>" + +"<tr>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>b2</td>" + +"<td>" + +"<table _type='B^'>" + +"<tr>" + +"<th>b</th>" + +"</tr>" + +"<tr>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>b3</td>" + +"<td>" + +"<table _type='array'>" + +"<tr>" + +"<th>b</th>" + +"</tr>" + +"<tr _type='B'>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>b1</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='array'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>b</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b2</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='B^'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>b</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b3</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='array'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>b</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr _type='B'>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n", + }, + { + "BeanWithPropertiesWithArrayTypeNames", + new BeanWithPropertiesWith2dArrayTypeNames().init(), + "<table>" + +"<tr>" + +"<td>b1</td>" + +"<td>" + +"<ul>" + +"<li>" + +"<table _type='array'>" + +"<tr>" + +"<th>b</th>" + +"</tr>" + +"<tr>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</li>" + +"</ul>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>b2</td>" + +"<td>" + +"<ul _type='B^^'>" + +"<li>" + +"<table _type='array'>" + +"<tr>" + +"<th>b</th>" + +"</tr>" + +"<tr>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</li>" + +"</ul>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>b3</td>" + +"<td>" + +"<ul>" + +"<li>" + +"<table _type='array'>" + +"<tr>" + +"<th>b</th>" + +"</tr>" + +"<tr _type='B'>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</li>" + +"</ul>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>b1</td>\n" + +"\t\t<td>\n" + +"\t\t\t<ul>\n" + +"\t\t\t\t<li>\n" + +"\t\t\t\t\t<table _type='array'>\n" + +"\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t<th>b</th>\n" + +"\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t</table>\n" + +"\t\t\t\t</li>\n" + +"\t\t\t</ul>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b2</td>\n" + +"\t\t<td>\n" + +"\t\t\t<ul _type='B^^'>\n" + +"\t\t\t\t<li>\n" + +"\t\t\t\t\t<table _type='array'>\n" + +"\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t<th>b</th>\n" + +"\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t</table>\n" + +"\t\t\t\t</li>\n" + +"\t\t\t</ul>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b3</td>\n" + +"\t\t<td>\n" + +"\t\t\t<ul>\n" + +"\t\t\t\t<li>\n" + +"\t\t\t\t\t<table _type='array'>\n" + +"\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t<th>b</th>\n" + +"\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t\t<tr _type='B'>\n" + +"\t\t\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t</table>\n" + +"\t\t\t\t</li>\n" + +"\t\t\t</ul>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n" + }, + { + "BeanWithPropertiesWithMapTypeNames", + new BeanWithPropertiesWithMapTypeNames().init(), + "<table>" + +"<tr>" + +"<td>b1</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>k1</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>b</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>b2</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>k2</td>" + +"<td>" + +"<table _type='B'>" + +"<tr>" + +"<td>b</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>b1</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k1</td>\n" + +"\t\t\t\t\t<td>\n" + +"\t\t\t\t\t\t<table>\n" + +"\t\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t\t<td>b</td>\n" + +"\t\t\t\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t\t</table>\n" + +"\t\t\t\t\t</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b2</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k2</td>\n" + +"\t\t\t\t\t<td>\n" + +"\t\t\t\t\t\t<table _type='B'>\n" + +"\t\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t\t<td>b</td>\n" + +"\t\t\t\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t\t</table>\n" + +"\t\t\t\t\t</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n", + }, + { + "LinkBean-1", + new LinkBean().init(), + "<a href='http://apache.org'>foo</a>", + "<a href='http://apache.org'>foo</a>" + }, + { + "LinkBean-2", + new LinkBean[]{new LinkBean().init(),new LinkBean().init()}, + "<ul><li><a href='http://apache.org'>foo</a></li><li><a href='http://apache.org'>foo</a></li></ul>", + "<ul>\n\t<li><a href='http://apache.org'>foo</a></li>\n\t<li><a href='http://apache.org'>foo</a></li>\n</ul>\n" + }, + { + "ListWithLinkBeans", + new ListWithLinkBeans().append(new LinkBean().init()).append(new LinkBean().init()), + "<ul><li><a href='http://apache.org'>foo</a></li><li><a href='http://apache.org'>foo</a></li></ul>", + "<ul>\n\t<li><a href='http://apache.org'>foo</a></li>\n\t<li><a href='http://apache.org'>foo</a></li>\n</ul>\n" + }, + { + "BeanWithLinkBeanProperties", + new BeanWithLinkBeanProperties().init(), + "<table>" + +"<tr>" + +"<td>a</td>" + +"<td><a href='http://apache.org'>foo</a></td>" + +"</tr>" + +"<tr>" + +"<td>b</td>" + +"<td>" + +"<ul>" + +"<li><a href='http://apache.org'>foo</a></li>" + +"</ul>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>c</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>c1</td>" + +"<td><a href='http://apache.org'>foo</a></td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>a</td>\n" + +"\t\t<td><a href='http://apache.org'>foo</a></td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b</td>\n" + +"\t\t<td>\n" + +"\t\t\t<ul>\n" + +"\t\t\t\t<li><a href='http://apache.org'>foo</a></li>\n" + +"\t\t\t</ul>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>c</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>c1</td>\n" + +"\t\t\t\t\t<td><a href='http://apache.org'>foo</a></td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n" + }, + { + "BeanWithSpecialCharacters", + new BeanWithSpecialCharacters().init(), + "<table><tr><td>a</td><td><br/><bs/><ff/><tb> </tb></td></tr></table>", + "<table>\n\t<tr>\n\t\t<td>a</td>\n\t\t<td><br/><bs/><ff/><tb> </tb></td>\n\t</tr>\n</table>\n" + }, + { + "BeanWithNullProperties", + new BeanWithNullProperties(), + "<table></table>", + "<table>\n</table>\n" + }, + { + "BeanWithAbstractFields", + new BeanWithAbstractFields().init(), + "<table>" + +"<tr>" + +"<td>a</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>a</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>ia</td>" + +"<td>" + +"<table _type='A'>" + +"<tr>" + +"<td>a</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>aa</td>" + +"<td>" + +"<table _type='A'>" + +"<tr>" + +"<td>a</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>o</td>" + +"<td>" + +"<table _type='A'>" + +"<tr>" + +"<td>a</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>a</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>a</td>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>ia</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='A'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>a</td>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>aa</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='A'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>a</td>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>o</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='A'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>a</td>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n" + }, + { + "BeanWithAbstractArrayFields", + new BeanWithAbstractArrayFields().init(), + "<table>" + +"<tr>" + +"<td>a</td>" + +"<td>" + +"<table _type='array'>" + +"<tr>" + +"<th>a</th>" + +"</tr>" + +"<tr>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>ia1</td>" + +"<td>" + +"<table _type='A^'>" + +"<tr>" + +"<th>a</th>" + +"</tr>" + +"<tr>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>ia2</td>" + +"<td>" + +"<table _type='array'>" + +"<tr>" + +"<th>a</th>" + +"</tr>" + +"<tr _type='A'>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>aa1</td>" + +"<td>" + +"<table _type='A^'>" + +"<tr>" + +"<th>a</th>" + +"</tr>" + +"<tr>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>aa2</td>" + +"<td>" + +"<table _type='array'>" + +"<tr>" + +"<th>a</th>" + +"</tr>" + +"<tr _type='A'>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>o1</td>" + +"<td>" + +"<table _type='A^'>" + +"<tr>" + +"<th>a</th>" + +"</tr>" + +"<tr>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>o2</td>" + +"<td>" + +"<table _type='array'>" + +"<tr>" + +"<th>a</th>" + +"</tr>" + +"<tr _type='A'>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>a</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='array'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>a</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>ia1</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='A^'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>a</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>ia2</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='array'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>a</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr _type='A'>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>aa1</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='A^'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>a</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>aa2</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='array'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>a</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr _type='A'>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>o1</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='A^'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>a</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>o2</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table _type='array'>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<th>a</th>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t\t<tr _type='A'>\n" + +"\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n", + }, + { + "BeanWithAbstractMapFields", + new BeanWithAbstractMapFields().init(), + "<table>" + +"<tr>" + +"<td>a</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>k1</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>a</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>b</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>k2</td>" + +"<td>" + +"<table _type='A'>" + +"<tr>" + +"<td>a</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"<tr>" + +"<td>c</td>" + +"<td>" + +"<table>" + +"<tr>" + +"<td>k3</td>" + +"<td>" + +"<table _type='A'>" + +"<tr>" + +"<td>a</td>" + +"<td>foo</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>" + +"</td>" + +"</tr>" + +"</table>", + "<table>\n" + +"\t<tr>\n" + +"\t\t<td>a</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k1</td>\n" + +"\t\t\t\t\t<td>\n" + +"\t\t\t\t\t\t<table>\n" + +"\t\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t\t<td>a</td>\n" + +"\t\t\t\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t\t</table>\n" + +"\t\t\t\t\t</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>b</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k2</td>\n" + +"\t\t\t\t\t<td>\n" + +"\t\t\t\t\t\t<table _type='A'>\n" + +"\t\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t\t<td>a</td>\n" + +"\t\t\t\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t\t</table>\n" + +"\t\t\t\t\t</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"\t<tr>\n" + +"\t\t<td>c</td>\n" + +"\t\t<td>\n" + +"\t\t\t<table>\n" + +"\t\t\t\t<tr>\n" + +"\t\t\t\t\t<td>k3</td>\n" + +"\t\t\t\t\t<td>\n" + +"\t\t\t\t\t\t<table _type='A'>\n" + +"\t\t\t\t\t\t\t<tr>\n" + +"\t\t\t\t\t\t\t\t<td>a</td>\n" + +"\t\t\t\t\t\t\t\t<td>foo</td>\n" + +"\t\t\t\t\t\t\t</tr>\n" + +"\t\t\t\t\t\t</table>\n" + +"\t\t\t\t\t</td>\n" + +"\t\t\t\t</tr>\n" + +"\t\t\t</table>\n" + +"\t\t</td>\n" + +"\t</tr>\n" + +"</table>\n" + } + }); + } + + private String label, e1, e2; + private Object in; + + public BasicHtmlTest(String label, Object in, String e1, String e2) throws Exception { + this.label = label; + this.in = in; + this.e1 = e1; + this.e2 = e2; + } + + @Test + public void serializeNormal() { + try { + String r = s1.serialize(in); + assertEquals(label + " serialize-normal failed", e1, r); + } catch (AssertionError e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(label + " test failed", e); + } + } + + @Test + public void parseNormal() { + try { + String r = s1.serialize(in); + Object o = parser.parse(r, in == null ? Object.class : in.getClass()); + r = s1.serialize(o); + assertEquals(label + " parse-normal failed", e1, r); + } catch (AssertionError e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(label + " test failed", e); + } + } + + @Test + public void serializeReadable() { + try { + String r = s2.serialize(in); + assertEquals(label + " serialize-readable failed", e2, r); + } catch (AssertionError e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(label + " test failed", e); + } + } + + @Test + public void parseReadable() { + try { + String r = s2.serialize(in); + Object o = parser.parse(r, in == null ? Object.class : in.getClass()); + r = s2.serialize(o); + assertEquals(label + " parse-readable failed", e2, r); + } catch (AssertionError e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(label + " test failed", e); + } + } + + + //-------------------------------------------------------------------------------- + // Test beans + //-------------------------------------------------------------------------------- + + public static class MapWithStrings extends LinkedHashMap<String,String> { + public MapWithStrings append(String key, String value) { + put(key, value); + return this; + } + } + + public static class MapWithNumbers extends LinkedHashMap<String,Number> { + public MapWithNumbers append(String key, Number value) { + put(key, value); + return this; + } + } + + public static class MapWithObjects extends LinkedHashMap<String,Object> { + public MapWithObjects append(String key, Object value) { + put(key, value); + return this; + } + } + + public static class ListWithStrings extends ArrayList<String> { + public ListWithStrings append(String value) { + this.add(value); + return this; + } + } + + public static class ListWithNumbers extends ArrayList<Number> { + public ListWithNumbers append(Number value) { + this.add(value); + return this; + } + } + + public static class ListWithObjects extends ArrayList<Object> { + public ListWithObjects append(Object value) { + this.add(value); + return this; + } + } + + public static class BeanWithNormalProperties { + public String a; + public int b; + public Object c; + public Object d; + public Bean1a e; + public String[] f; + public int[] g; + + BeanWithNormalProperties init() { + a = "foo"; + b = 123; + c = "bar"; + d = 456; + e = new Bean1a().init(); + f = new String[]{ "baz" }; + g = new int[]{ 789 }; + return this; + } + } + + public static class Bean1a { + public String h; + + Bean1a init() { + h = "qux"; + return this; + } + } + + public static class BeanWithMapProperties { + @BeanProperty(type=MapWithStrings.class) + public Map<String,String> a; + @BeanProperty(type=MapWithNumbers.class) + public Map<String,Number> b; + @BeanProperty(type=MapWithObjects.class) + public Map<String,Object> c; + + BeanWithMapProperties init() { + a = new MapWithStrings().append("k1","foo"); + b = new MapWithNumbers().append("k2",123); + c = new MapWithObjects().append("k3","bar").append("k4",456).append("k5",true).append("k6",null); + return this; + } + } + + @Bean(typeName="X") + public static class BeanWithTypeName { + public int a; + public String b; + + BeanWithTypeName init() { + a = 123; + b = "foo"; + return this; + } + } + + @Bean(beanDictionary={B.class}) + public static class BeanWithPropertiesWithTypeNames { + public B b1; + public Object b2; + + BeanWithPropertiesWithTypeNames init() { + b1 = new B().init(); + b2 = new B().init(); + return this; + } + } + + @Bean(beanDictionary={B.class}) + public static class BeanWithPropertiesWithArrayTypeNames { + public B[] b1; + public Object[] b2; + public Object[] b3; + + BeanWithPropertiesWithArrayTypeNames init() { + b1 = new B[]{new B().init()}; + b2 = new B[]{new B().init()}; + b3 = new Object[]{new B().init()}; + return this; + } + } + + @Bean(beanDictionary={B.class}) + public static class BeanWithPropertiesWith2dArrayTypeNames { + public B[][] b1; + public Object[][] b2; + public Object[][] b3; + + BeanWithPropertiesWith2dArrayTypeNames init() { + b1 = new B[][]{{new B().init()}}; + b2 = new B[][]{{new B().init()}}; + b3 = new Object[][]{{new B().init()}}; + return this; + } + } + + @Bean(beanDictionary={B.class}) + public static class BeanWithPropertiesWithMapTypeNames { + public Map<String,B> b1; + public Map<String,Object> b2; + + BeanWithPropertiesWithMapTypeNames init() { + b1 = new HashMap<String,B>(); + b1.put("k1", new B().init()); + b2 = new HashMap<String,Object>(); + b2.put("k2", new B().init()); + return this; + } + } + + @Bean(typeName="B") + public static class B { + public String b; + + B init() { + b = "foo"; + return this; + } + } + + @HtmlLink(nameProperty="a",hrefProperty="b") + public static class LinkBean { + public String a; + public String b; + + LinkBean init() { + a = "foo"; + b = "http://apache.org"; + return this; + } + } + + public static class ListWithLinkBeans extends ArrayList<LinkBean> { + public ListWithLinkBeans append(LinkBean value) { + this.add(value); + return this; + } + } + + public static class BeanWithLinkBeanProperties { + public LinkBean a; + public List<LinkBean> b; + public Map<String,LinkBean> c; + + BeanWithLinkBeanProperties init() { + a = new LinkBean().init(); + b = new ListWithLinkBeans().append(new LinkBean().init()); + c = new LinkedHashMap<String,LinkBean>(); + c.put("c1", new LinkBean().init()); + return this; + } + } + + public static class BeanWithSpecialCharacters { + public String a; + + BeanWithSpecialCharacters init() { + a = "\n\b\f\t"; + return this; + } + } + + public static class BeanWithNullProperties { + public String a; + public String[] b; + } + + @Bean(beanDictionary={A.class}) + public static class BeanWithAbstractFields { + public A a; + public IA ia; + public AA aa; + public Object o; + + BeanWithAbstractFields init() { + ia = new A().init(); + aa = new A().init(); + a = new A().init(); + o = new A().init(); + return this; + } + } + + @Bean(beanDictionary={A.class}) + public static class BeanWithAbstractArrayFields { + public A[] a; + public IA[] ia1, ia2; + public AA[] aa1, aa2; + public Object[] o1, o2; + + BeanWithAbstractArrayFields init() { + a = new A[]{new A().init()}; + ia1 = new A[]{new A().init()}; + aa1 = new A[]{new A().init()}; + o1 = new A[]{new A().init()}; + ia2 = new IA[]{new A().init()}; + aa2 = new AA[]{new A().init()}; + o2 = new Object[]{new A().init()}; + return this; + } + } + + @Bean(beanDictionary={A.class}) + public static class BeanWithAbstractMapFields { + public Map<String,A> a; + public Map<String,AA> b; + public Map<String,Object> c; + + BeanWithAbstractMapFields init() { + a = new HashMap<String,A>(); + b = new HashMap<String,AA>(); + c = new HashMap<String,Object>(); + a.put("k1", new A().init()); + b.put("k2", new A().init()); + c.put("k3", new A().init()); + return this; + } + } + + public static interface IA { + public String getA(); + public void setA(String a); + } + + public static abstract class AA implements IA {} + + @Bean(typeName="A") + public static class A extends AA { + private String a; + + @Override + public String getA() { + return a; + } + + @Override + public void setA(String a) { + this.a = a; + } + + A init() { + this.a = "foo"; + return this; + } + } +}
