You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by jo...@apache.org on 2008/08/19 04:27:54 UTC

svn commit: r686935 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java

Author: johnh
Date: Mon Aug 18 19:27:54 2008
New Revision: 686935

URL: http://svn.apache.org/viewvc?rev=686935&view=rev
Log:
Adding ability for GadgetHtmlNode to render itself as HTML via GadgetHtmlNode.render(Writer w).


Modified:
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java?rev=686935&r1=686934&r2=686935&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java Mon Aug 18 19:27:54 2008
@@ -17,6 +17,8 @@
  */
 package org.apache.shindig.gadgets.parse;
 
+import java.io.IOException;
+import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -25,6 +27,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.commons.lang.StringEscapeUtils;
+
 /**
  * Mutable wrapper around a {@code ParsedHtmlNode}.
  * Used by rewriting to manipulate a parsed gadget DOM, and
@@ -280,6 +284,44 @@
     this.text = text;
   }
   
+  /**
+   * Render self as HTML. Rendering is relatively simple as no
+   * additional validation is performed on content beyond what
+   * the rest of the class provides, such as attribute key
+   * validation. All whitespace and comments are maintained. Nodes
+   * with zero children are rendered short-form (<foo/>)
+   * unless tagName is "style" since many browsers dislike short-form for that.
+   * One space is provided between attributes. Attribute values are surrounded
+   * in double-quotes. Null-valued attributes are rendered without ="value".
+   * Attributes are rendered in no particular order.
+   * @param w Writer to which to send content
+   * @throws IOException If the writer throws an error on append(...)
+   */
+  public void render(Writer w) throws IOException {
+    if (isText()) {
+      w.append(StringEscapeUtils.escapeHtml(getText()));
+    } else {
+      w.append('<').append(tagName);
+      for (String attrKey : getAttributeKeys()) {
+        String attrValue = getAttributeValue(attrKey);
+        w.append(' ').append(attrKey);
+        if (attrValue != null) {
+          w.append("=\"").append(StringEscapeUtils.escapeHtml(attrValue)).append('"');
+        }
+      }
+      if (children.size() == 0 &&
+          !tagName.equalsIgnoreCase("style")) {
+        w.append("/>");
+      } else {
+        w.append('>');
+        for (GadgetHtmlNode child : children) {
+          child.render(w);
+        }
+        w.append("</").append(tagName).append('>');
+      }
+    }
+  }
+  
   // Helper that cleans up and validates an attribute key
   private String validateAttributeKey(String key) {
     if (key == null) {

Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java?rev=686935&r1=686934&r2=686935&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java Mon Aug 18 19:27:54 2008
@@ -24,6 +24,8 @@
 
 import junit.framework.TestCase;
 
+import java.io.IOException;
+import java.io.StringWriter;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
@@ -431,4 +433,78 @@
       // Expected condition
     }
   }
+  
+  public void testRenderOnlyTextNode() {
+    String content = "  hello, world!\n  ";
+    assertEquals(content, renderNode(new GadgetHtmlNode(content)));
+  }
+  
+  public void testRenderOnlyTagNodeShortForm() {
+    String[][] attribs = { { "id", "foo" }, { "bar", "baz" } };
+    GadgetHtmlNode tag = new GadgetHtmlNode("div", attribs);
+    assertEquals("<div bar=\"baz\" id=\"foo\"/>", renderNode(tag));
+  }
+  
+  public void testRenderStyleSrcTag() {
+    String[][] attribs = { { "src", "http://www.foo.com/bar.css" } };
+    GadgetHtmlNode styleTag = new GadgetHtmlNode("style", attribs);
+    assertEquals("<style src=\"http://www.foo.com/bar.css\"></style>",
+                 renderNode(styleTag));
+  }
+  
+  public void testRenderEscapedAttribute() {
+    String[][] attribs = { { "foo", "<script&\"data\">" } };
+    GadgetHtmlNode escapedTag = new GadgetHtmlNode("div", attribs);
+    assertEquals("<div foo=\"&lt;script&amp;&quot;data&quot;&gt;\"/>",
+                 renderNode(escapedTag));
+  }
+  
+  public void testRenderNullValuedAttribute() {
+    String[][] attribs = { { "marker", null } };
+    GadgetHtmlNode tag = new GadgetHtmlNode("span", attribs);
+    assertEquals("<span marker/>", renderNode(tag));
+  }
+  
+  public void testRenderEscapedTextContent() {
+    GadgetHtmlNode escapedTextNode = new GadgetHtmlNode("<script&\"data'>");
+    assertEquals("&lt;script&amp;&quot;data'&gt;",
+                 renderNode(escapedTextNode));
+  }
+  
+  public void testRenderAdjacentStringsInTag() {
+    GadgetHtmlNode container = new GadgetHtmlNode("div", null);
+    container.appendChild(new GadgetHtmlNode("one"));
+    container.appendChild(new GadgetHtmlNode("\n"));
+    container.appendChild(new GadgetHtmlNode(" two "));
+    assertEquals("<div>one\n two </div>", renderNode(container));
+  }
+  
+  public void testRenderMixedContent() {
+    // Something of a catch-all for smaller above tests.
+    String[][] attribs = { { "readonly", null } };
+    GadgetHtmlNode parent = new GadgetHtmlNode("div", attribs);
+    parent.appendChild(new GadgetHtmlNode(" content\n"));
+    parent.appendChild(new GadgetHtmlNode("<br>"));
+    GadgetHtmlNode child1 = new GadgetHtmlNode("span", null);
+    child1.appendChild(new GadgetHtmlNode("hr", null));
+    parent.appendChild(child1);
+    parent.appendChild(new GadgetHtmlNode("\"after text\""));
+    GadgetHtmlNode child2 = new GadgetHtmlNode("p", null);
+    child2.appendChild(new GadgetHtmlNode("paragraph!"));
+    parent.appendChild(child2);
+    assertEquals("<div readonly> content\n&lt;br&gt;<span><hr/>" +
+                 "</span>&quot;after text&quot;<p>paragraph!</p></div>",
+                 renderNode(parent));
+  }
+  
+  private String renderNode(GadgetHtmlNode node) {
+    StringWriter sw = new StringWriter();
+    try {
+      node.render(sw);
+    } catch (IOException e) {
+      // Should never happen, but fail just in case.
+      fail("Unexpected IOException on StringWriter operation");
+    }
+    return sw.toString();
+  }
 }



Re: svn commit: r686935 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java

Posted by John Hjelmstad <fa...@google.com>.
Yeah, evidently the vagaries of my setup were such that they were ordered
the same in every test run. In any case, there never was an ordering
guarantee so the test shouldn't have depended on one. :(
--John

On Tue, Aug 19, 2008 at 4:44 PM, Kevin Brown <et...@google.com> wrote:

> On Tue, Aug 19, 2008 at 4:37 PM, John Hjelmstad <fa...@google.com> wrote:
>
> > Fixed in r687195. I'd ran this suite several times, but in retrospect
> > shouldn't have assumed that the particular Set in question (2-item Set of
> > attributes) would happen to be ordered the same across all JVMs.
> > Let me know if you find any other issues.
>
>
> It's not just across VMs -- having a different number of elements could
> change the ordering as well, since it's just using a hash table under the
> covers.
>
>
> >
> >
> > Apologies,
> > --John
> >
> > On Tue, Aug 19, 2008 at 4:32 PM, John Hjelmstad <fa...@google.com>
> wrote:
> >
> > > Well that's decidedly not good. Fixing now.
> > >
> > > On Tue, Aug 19, 2008 at 4:17 PM, Kevin Brown <et...@google.com> wrote:
> > >
> > >> Some of these tests are failing because the internal code is returning
> > >> sets
> > >> that don't guarantee ordering, and the tests are assuming that they
> do.
> > >>
> > >> On Mon, Aug 18, 2008 at 7:27 PM, <jo...@apache.org> wrote:
> > >>
> > >> > Author: johnh
> > >> > Date: Mon Aug 18 19:27:54 2008
> > >> > New Revision: 686935
> > >> >
> > >> > URL: http://svn.apache.org/viewvc?rev=686935&view=rev
> > >> > Log:
> > >> > Adding ability for GadgetHtmlNode to render itself as HTML via
> > >> > GadgetHtmlNode.render(Writer w).
> > >> >
> > >> >
> > >> > Modified:
> > >> >
> > >> >
> > >>
> >
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> > >> >
> > >> >
> > >>
> >
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> > >> >
> > >> > Modified:
> > >> >
> > >>
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> > >> > URL:
> > >> >
> > >>
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java?rev=686935&r1=686934&r2=686935&view=diff
> > >> >
> > >> >
> > >>
> >
> ==============================================================================
> > >> > ---
> > >> >
> > >>
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> > >> > (original)
> > >> > +++
> > >> >
> > >>
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> > >> > Mon Aug 18 19:27:54 2008
> > >> > @@ -17,6 +17,8 @@
> > >> >  */
> > >> >  package org.apache.shindig.gadgets.parse;
> > >> >
> > >> > +import java.io.IOException;
> > >> > +import java.io.Writer;
> > >> >  import java.util.ArrayList;
> > >> >  import java.util.Collections;
> > >> >  import java.util.HashMap;
> > >> > @@ -25,6 +27,8 @@
> > >> >  import java.util.Map;
> > >> >  import java.util.Set;
> > >> >
> > >> > +import org.apache.commons.lang.StringEscapeUtils;
> > >> > +
> > >> >  /**
> > >> >  * Mutable wrapper around a {@code ParsedHtmlNode}.
> > >> >  * Used by rewriting to manipulate a parsed gadget DOM, and
> > >> > @@ -280,6 +284,44 @@
> > >> >     this.text = text;
> > >> >   }
> > >> >
> > >> > +  /**
> > >> > +   * Render self as HTML. Rendering is relatively simple as no
> > >> > +   * additional validation is performed on content beyond what
> > >> > +   * the rest of the class provides, such as attribute key
> > >> > +   * validation. All whitespace and comments are maintained. Nodes
> > >> > +   * with zero children are rendered short-form (&lt;foo/&gt;)
> > >> > +   * unless tagName is "style" since many browsers dislike
> short-form
> > >> for
> > >> > that.
> > >> > +   * One space is provided between attributes. Attribute values are
> > >> > surrounded
> > >> > +   * in double-quotes. Null-valued attributes are rendered without
> > >> > ="value".
> > >> > +   * Attributes are rendered in no particular order.
> > >> > +   * @param w Writer to which to send content
> > >> > +   * @throws IOException If the writer throws an error on
> append(...)
> > >> > +   */
> > >> > +  public void render(Writer w) throws IOException {
> > >> > +    if (isText()) {
> > >> > +      w.append(StringEscapeUtils.escapeHtml(getText()));
> > >> > +    } else {
> > >> > +      w.append('<').append(tagName);
> > >> > +      for (String attrKey : getAttributeKeys()) {
> > >> > +        String attrValue = getAttributeValue(attrKey);
> > >> > +        w.append(' ').append(attrKey);
> > >> > +        if (attrValue != null) {
> > >> > +
> > >> >
> > >>
> >
>  w.append("=\"").append(StringEscapeUtils.escapeHtml(attrValue)).append('"');
> > >> > +        }
> > >> > +      }
> > >> > +      if (children.size() == 0 &&
> > >> > +          !tagName.equalsIgnoreCase("style")) {
> > >> > +        w.append("/>");
> > >> > +      } else {
> > >> > +        w.append('>');
> > >> > +        for (GadgetHtmlNode child : children) {
> > >> > +          child.render(w);
> > >> > +        }
> > >> > +        w.append("</").append(tagName).append('>');
> > >> > +      }
> > >> > +    }
> > >> > +  }
> > >> > +
> > >> >   // Helper that cleans up and validates an attribute key
> > >> >   private String validateAttributeKey(String key) {
> > >> >     if (key == null) {
> > >> >
> > >> > Modified:
> > >> >
> > >>
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> > >> > URL:
> > >> >
> > >>
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java?rev=686935&r1=686934&r2=686935&view=diff
> > >> >
> > >> >
> > >>
> >
> ==============================================================================
> > >> > ---
> > >> >
> > >>
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> > >> > (original)
> > >> > +++
> > >> >
> > >>
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> > >> > Mon Aug 18 19:27:54 2008
> > >> > @@ -24,6 +24,8 @@
> > >> >
> > >> >  import junit.framework.TestCase;
> > >> >
> > >> > +import java.io.IOException;
> > >> > +import java.io.StringWriter;
> > >> >  import java.util.LinkedList;
> > >> >  import java.util.List;
> > >> >  import java.util.Set;
> > >> > @@ -431,4 +433,78 @@
> > >> >       // Expected condition
> > >> >     }
> > >> >   }
> > >> > +
> > >> > +  public void testRenderOnlyTextNode() {
> > >> > +    String content = "  hello, world!\n  ";
> > >> > +    assertEquals(content, renderNode(new GadgetHtmlNode(content)));
> > >> > +  }
> > >> > +
> > >> > +  public void testRenderOnlyTagNodeShortForm() {
> > >> > +    String[][] attribs = { { "id", "foo" }, { "bar", "baz" } };
> > >> > +    GadgetHtmlNode tag = new GadgetHtmlNode("div", attribs);
> > >> > +    assertEquals("<div bar=\"baz\" id=\"foo\"/>", renderNode(tag));
> > >> > +  }
> > >> > +
> > >> > +  public void testRenderStyleSrcTag() {
> > >> > +    String[][] attribs = { { "src", "http://www.foo.com/bar.css" }
> > };
> > >> > +    GadgetHtmlNode styleTag = new GadgetHtmlNode("style", attribs);
> > >> > +    assertEquals("<style src=\"http://www.foo.com/bar.css\<
> http://www.foo.com/bar.css%5C>
> > <http://www.foo.com/bar.css%5C>
> > >> <http://www.foo.com/bar.css%5C>
> > >> > "></style>",
> > >> > +                 renderNode(styleTag));
> > >> > +  }
> > >> > +
> > >> > +  public void testRenderEscapedAttribute() {
> > >> > +    String[][] attribs = { { "foo", "<script&\"data\">" } };
> > >> > +    GadgetHtmlNode escapedTag = new GadgetHtmlNode("div", attribs);
> > >> > +    assertEquals("<div
> > foo=\"&lt;script&amp;&quot;data&quot;&gt;\"/>",
> > >> > +                 renderNode(escapedTag));
> > >> > +  }
> > >> > +
> > >> > +  public void testRenderNullValuedAttribute() {
> > >> > +    String[][] attribs = { { "marker", null } };
> > >> > +    GadgetHtmlNode tag = new GadgetHtmlNode("span", attribs);
> > >> > +    assertEquals("<span marker/>", renderNode(tag));
> > >> > +  }
> > >> > +
> > >> > +  public void testRenderEscapedTextContent() {
> > >> > +    GadgetHtmlNode escapedTextNode = new
> > >> > GadgetHtmlNode("<script&\"data'>");
> > >> > +    assertEquals("&lt;script&amp;&quot;data'&gt;",
> > >> > +                 renderNode(escapedTextNode));
> > >> > +  }
> > >> > +
> > >> > +  public void testRenderAdjacentStringsInTag() {
> > >> > +    GadgetHtmlNode container = new GadgetHtmlNode("div", null);
> > >> > +    container.appendChild(new GadgetHtmlNode("one"));
> > >> > +    container.appendChild(new GadgetHtmlNode("\n"));
> > >> > +    container.appendChild(new GadgetHtmlNode(" two "));
> > >> > +    assertEquals("<div>one\n two </div>", renderNode(container));
> > >> > +  }
> > >> > +
> > >> > +  public void testRenderMixedContent() {
> > >> > +    // Something of a catch-all for smaller above tests.
> > >> > +    String[][] attribs = { { "readonly", null } };
> > >> > +    GadgetHtmlNode parent = new GadgetHtmlNode("div", attribs);
> > >> > +    parent.appendChild(new GadgetHtmlNode(" content\n"));
> > >> > +    parent.appendChild(new GadgetHtmlNode("<br>"));
> > >> > +    GadgetHtmlNode child1 = new GadgetHtmlNode("span", null);
> > >> > +    child1.appendChild(new GadgetHtmlNode("hr", null));
> > >> > +    parent.appendChild(child1);
> > >> > +    parent.appendChild(new GadgetHtmlNode("\"after text\""));
> > >> > +    GadgetHtmlNode child2 = new GadgetHtmlNode("p", null);
> > >> > +    child2.appendChild(new GadgetHtmlNode("paragraph!"));
> > >> > +    parent.appendChild(child2);
> > >> > +    assertEquals("<div readonly> content\n&lt;br&gt;<span><hr/>" +
> > >> > +                 "</span>&quot;after
> > >> text&quot;<p>paragraph!</p></div>",
> > >> > +                 renderNode(parent));
> > >> > +  }
> > >> > +
> > >> > +  private String renderNode(GadgetHtmlNode node) {
> > >> > +    StringWriter sw = new StringWriter();
> > >> > +    try {
> > >> > +      node.render(sw);
> > >> > +    } catch (IOException e) {
> > >> > +      // Should never happen, but fail just in case.
> > >> > +      fail("Unexpected IOException on StringWriter operation");
> > >> > +    }
> > >> > +    return sw.toString();
> > >> > +  }
> > >> >  }
> > >> >
> > >> >
> > >> >
> > >>
> > >
> > >
> >
>

Re: svn commit: r686935 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java

Posted by Kevin Brown <et...@google.com>.
On Tue, Aug 19, 2008 at 4:37 PM, John Hjelmstad <fa...@google.com> wrote:

> Fixed in r687195. I'd ran this suite several times, but in retrospect
> shouldn't have assumed that the particular Set in question (2-item Set of
> attributes) would happen to be ordered the same across all JVMs.
> Let me know if you find any other issues.


It's not just across VMs -- having a different number of elements could
change the ordering as well, since it's just using a hash table under the
covers.


>
>
> Apologies,
> --John
>
> On Tue, Aug 19, 2008 at 4:32 PM, John Hjelmstad <fa...@google.com> wrote:
>
> > Well that's decidedly not good. Fixing now.
> >
> > On Tue, Aug 19, 2008 at 4:17 PM, Kevin Brown <et...@google.com> wrote:
> >
> >> Some of these tests are failing because the internal code is returning
> >> sets
> >> that don't guarantee ordering, and the tests are assuming that they do.
> >>
> >> On Mon, Aug 18, 2008 at 7:27 PM, <jo...@apache.org> wrote:
> >>
> >> > Author: johnh
> >> > Date: Mon Aug 18 19:27:54 2008
> >> > New Revision: 686935
> >> >
> >> > URL: http://svn.apache.org/viewvc?rev=686935&view=rev
> >> > Log:
> >> > Adding ability for GadgetHtmlNode to render itself as HTML via
> >> > GadgetHtmlNode.render(Writer w).
> >> >
> >> >
> >> > Modified:
> >> >
> >> >
> >>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> >> >
> >> >
> >>
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> >> >
> >> > Modified:
> >> >
> >>
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> >> > URL:
> >> >
> >>
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java?rev=686935&r1=686934&r2=686935&view=diff
> >> >
> >> >
> >>
> ==============================================================================
> >> > ---
> >> >
> >>
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> >> > (original)
> >> > +++
> >> >
> >>
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> >> > Mon Aug 18 19:27:54 2008
> >> > @@ -17,6 +17,8 @@
> >> >  */
> >> >  package org.apache.shindig.gadgets.parse;
> >> >
> >> > +import java.io.IOException;
> >> > +import java.io.Writer;
> >> >  import java.util.ArrayList;
> >> >  import java.util.Collections;
> >> >  import java.util.HashMap;
> >> > @@ -25,6 +27,8 @@
> >> >  import java.util.Map;
> >> >  import java.util.Set;
> >> >
> >> > +import org.apache.commons.lang.StringEscapeUtils;
> >> > +
> >> >  /**
> >> >  * Mutable wrapper around a {@code ParsedHtmlNode}.
> >> >  * Used by rewriting to manipulate a parsed gadget DOM, and
> >> > @@ -280,6 +284,44 @@
> >> >     this.text = text;
> >> >   }
> >> >
> >> > +  /**
> >> > +   * Render self as HTML. Rendering is relatively simple as no
> >> > +   * additional validation is performed on content beyond what
> >> > +   * the rest of the class provides, such as attribute key
> >> > +   * validation. All whitespace and comments are maintained. Nodes
> >> > +   * with zero children are rendered short-form (&lt;foo/&gt;)
> >> > +   * unless tagName is "style" since many browsers dislike short-form
> >> for
> >> > that.
> >> > +   * One space is provided between attributes. Attribute values are
> >> > surrounded
> >> > +   * in double-quotes. Null-valued attributes are rendered without
> >> > ="value".
> >> > +   * Attributes are rendered in no particular order.
> >> > +   * @param w Writer to which to send content
> >> > +   * @throws IOException If the writer throws an error on append(...)
> >> > +   */
> >> > +  public void render(Writer w) throws IOException {
> >> > +    if (isText()) {
> >> > +      w.append(StringEscapeUtils.escapeHtml(getText()));
> >> > +    } else {
> >> > +      w.append('<').append(tagName);
> >> > +      for (String attrKey : getAttributeKeys()) {
> >> > +        String attrValue = getAttributeValue(attrKey);
> >> > +        w.append(' ').append(attrKey);
> >> > +        if (attrValue != null) {
> >> > +
> >> >
> >>
>  w.append("=\"").append(StringEscapeUtils.escapeHtml(attrValue)).append('"');
> >> > +        }
> >> > +      }
> >> > +      if (children.size() == 0 &&
> >> > +          !tagName.equalsIgnoreCase("style")) {
> >> > +        w.append("/>");
> >> > +      } else {
> >> > +        w.append('>');
> >> > +        for (GadgetHtmlNode child : children) {
> >> > +          child.render(w);
> >> > +        }
> >> > +        w.append("</").append(tagName).append('>');
> >> > +      }
> >> > +    }
> >> > +  }
> >> > +
> >> >   // Helper that cleans up and validates an attribute key
> >> >   private String validateAttributeKey(String key) {
> >> >     if (key == null) {
> >> >
> >> > Modified:
> >> >
> >>
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> >> > URL:
> >> >
> >>
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java?rev=686935&r1=686934&r2=686935&view=diff
> >> >
> >> >
> >>
> ==============================================================================
> >> > ---
> >> >
> >>
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> >> > (original)
> >> > +++
> >> >
> >>
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> >> > Mon Aug 18 19:27:54 2008
> >> > @@ -24,6 +24,8 @@
> >> >
> >> >  import junit.framework.TestCase;
> >> >
> >> > +import java.io.IOException;
> >> > +import java.io.StringWriter;
> >> >  import java.util.LinkedList;
> >> >  import java.util.List;
> >> >  import java.util.Set;
> >> > @@ -431,4 +433,78 @@
> >> >       // Expected condition
> >> >     }
> >> >   }
> >> > +
> >> > +  public void testRenderOnlyTextNode() {
> >> > +    String content = "  hello, world!\n  ";
> >> > +    assertEquals(content, renderNode(new GadgetHtmlNode(content)));
> >> > +  }
> >> > +
> >> > +  public void testRenderOnlyTagNodeShortForm() {
> >> > +    String[][] attribs = { { "id", "foo" }, { "bar", "baz" } };
> >> > +    GadgetHtmlNode tag = new GadgetHtmlNode("div", attribs);
> >> > +    assertEquals("<div bar=\"baz\" id=\"foo\"/>", renderNode(tag));
> >> > +  }
> >> > +
> >> > +  public void testRenderStyleSrcTag() {
> >> > +    String[][] attribs = { { "src", "http://www.foo.com/bar.css" }
> };
> >> > +    GadgetHtmlNode styleTag = new GadgetHtmlNode("style", attribs);
> >> > +    assertEquals("<style src=\"http://www.foo.com/bar.css\<http://www.foo.com/bar.css%5C>
> <http://www.foo.com/bar.css%5C>
> >> <http://www.foo.com/bar.css%5C>
> >> > "></style>",
> >> > +                 renderNode(styleTag));
> >> > +  }
> >> > +
> >> > +  public void testRenderEscapedAttribute() {
> >> > +    String[][] attribs = { { "foo", "<script&\"data\">" } };
> >> > +    GadgetHtmlNode escapedTag = new GadgetHtmlNode("div", attribs);
> >> > +    assertEquals("<div
> foo=\"&lt;script&amp;&quot;data&quot;&gt;\"/>",
> >> > +                 renderNode(escapedTag));
> >> > +  }
> >> > +
> >> > +  public void testRenderNullValuedAttribute() {
> >> > +    String[][] attribs = { { "marker", null } };
> >> > +    GadgetHtmlNode tag = new GadgetHtmlNode("span", attribs);
> >> > +    assertEquals("<span marker/>", renderNode(tag));
> >> > +  }
> >> > +
> >> > +  public void testRenderEscapedTextContent() {
> >> > +    GadgetHtmlNode escapedTextNode = new
> >> > GadgetHtmlNode("<script&\"data'>");
> >> > +    assertEquals("&lt;script&amp;&quot;data'&gt;",
> >> > +                 renderNode(escapedTextNode));
> >> > +  }
> >> > +
> >> > +  public void testRenderAdjacentStringsInTag() {
> >> > +    GadgetHtmlNode container = new GadgetHtmlNode("div", null);
> >> > +    container.appendChild(new GadgetHtmlNode("one"));
> >> > +    container.appendChild(new GadgetHtmlNode("\n"));
> >> > +    container.appendChild(new GadgetHtmlNode(" two "));
> >> > +    assertEquals("<div>one\n two </div>", renderNode(container));
> >> > +  }
> >> > +
> >> > +  public void testRenderMixedContent() {
> >> > +    // Something of a catch-all for smaller above tests.
> >> > +    String[][] attribs = { { "readonly", null } };
> >> > +    GadgetHtmlNode parent = new GadgetHtmlNode("div", attribs);
> >> > +    parent.appendChild(new GadgetHtmlNode(" content\n"));
> >> > +    parent.appendChild(new GadgetHtmlNode("<br>"));
> >> > +    GadgetHtmlNode child1 = new GadgetHtmlNode("span", null);
> >> > +    child1.appendChild(new GadgetHtmlNode("hr", null));
> >> > +    parent.appendChild(child1);
> >> > +    parent.appendChild(new GadgetHtmlNode("\"after text\""));
> >> > +    GadgetHtmlNode child2 = new GadgetHtmlNode("p", null);
> >> > +    child2.appendChild(new GadgetHtmlNode("paragraph!"));
> >> > +    parent.appendChild(child2);
> >> > +    assertEquals("<div readonly> content\n&lt;br&gt;<span><hr/>" +
> >> > +                 "</span>&quot;after
> >> text&quot;<p>paragraph!</p></div>",
> >> > +                 renderNode(parent));
> >> > +  }
> >> > +
> >> > +  private String renderNode(GadgetHtmlNode node) {
> >> > +    StringWriter sw = new StringWriter();
> >> > +    try {
> >> > +      node.render(sw);
> >> > +    } catch (IOException e) {
> >> > +      // Should never happen, but fail just in case.
> >> > +      fail("Unexpected IOException on StringWriter operation");
> >> > +    }
> >> > +    return sw.toString();
> >> > +  }
> >> >  }
> >> >
> >> >
> >> >
> >>
> >
> >
>

Re: svn commit: r686935 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java

Posted by John Hjelmstad <fa...@google.com>.
Fixed in r687195. I'd ran this suite several times, but in retrospect
shouldn't have assumed that the particular Set in question (2-item Set of
attributes) would happen to be ordered the same across all JVMs.
Let me know if you find any other issues.

Apologies,
--John

On Tue, Aug 19, 2008 at 4:32 PM, John Hjelmstad <fa...@google.com> wrote:

> Well that's decidedly not good. Fixing now.
>
> On Tue, Aug 19, 2008 at 4:17 PM, Kevin Brown <et...@google.com> wrote:
>
>> Some of these tests are failing because the internal code is returning
>> sets
>> that don't guarantee ordering, and the tests are assuming that they do.
>>
>> On Mon, Aug 18, 2008 at 7:27 PM, <jo...@apache.org> wrote:
>>
>> > Author: johnh
>> > Date: Mon Aug 18 19:27:54 2008
>> > New Revision: 686935
>> >
>> > URL: http://svn.apache.org/viewvc?rev=686935&view=rev
>> > Log:
>> > Adding ability for GadgetHtmlNode to render itself as HTML via
>> > GadgetHtmlNode.render(Writer w).
>> >
>> >
>> > Modified:
>> >
>> >
>>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
>> >
>> >
>>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
>> >
>> > Modified:
>> >
>> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
>> > URL:
>> >
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java?rev=686935&r1=686934&r2=686935&view=diff
>> >
>> >
>> ==============================================================================
>> > ---
>> >
>> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
>> > (original)
>> > +++
>> >
>> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
>> > Mon Aug 18 19:27:54 2008
>> > @@ -17,6 +17,8 @@
>> >  */
>> >  package org.apache.shindig.gadgets.parse;
>> >
>> > +import java.io.IOException;
>> > +import java.io.Writer;
>> >  import java.util.ArrayList;
>> >  import java.util.Collections;
>> >  import java.util.HashMap;
>> > @@ -25,6 +27,8 @@
>> >  import java.util.Map;
>> >  import java.util.Set;
>> >
>> > +import org.apache.commons.lang.StringEscapeUtils;
>> > +
>> >  /**
>> >  * Mutable wrapper around a {@code ParsedHtmlNode}.
>> >  * Used by rewriting to manipulate a parsed gadget DOM, and
>> > @@ -280,6 +284,44 @@
>> >     this.text = text;
>> >   }
>> >
>> > +  /**
>> > +   * Render self as HTML. Rendering is relatively simple as no
>> > +   * additional validation is performed on content beyond what
>> > +   * the rest of the class provides, such as attribute key
>> > +   * validation. All whitespace and comments are maintained. Nodes
>> > +   * with zero children are rendered short-form (&lt;foo/&gt;)
>> > +   * unless tagName is "style" since many browsers dislike short-form
>> for
>> > that.
>> > +   * One space is provided between attributes. Attribute values are
>> > surrounded
>> > +   * in double-quotes. Null-valued attributes are rendered without
>> > ="value".
>> > +   * Attributes are rendered in no particular order.
>> > +   * @param w Writer to which to send content
>> > +   * @throws IOException If the writer throws an error on append(...)
>> > +   */
>> > +  public void render(Writer w) throws IOException {
>> > +    if (isText()) {
>> > +      w.append(StringEscapeUtils.escapeHtml(getText()));
>> > +    } else {
>> > +      w.append('<').append(tagName);
>> > +      for (String attrKey : getAttributeKeys()) {
>> > +        String attrValue = getAttributeValue(attrKey);
>> > +        w.append(' ').append(attrKey);
>> > +        if (attrValue != null) {
>> > +
>> >
>>  w.append("=\"").append(StringEscapeUtils.escapeHtml(attrValue)).append('"');
>> > +        }
>> > +      }
>> > +      if (children.size() == 0 &&
>> > +          !tagName.equalsIgnoreCase("style")) {
>> > +        w.append("/>");
>> > +      } else {
>> > +        w.append('>');
>> > +        for (GadgetHtmlNode child : children) {
>> > +          child.render(w);
>> > +        }
>> > +        w.append("</").append(tagName).append('>');
>> > +      }
>> > +    }
>> > +  }
>> > +
>> >   // Helper that cleans up and validates an attribute key
>> >   private String validateAttributeKey(String key) {
>> >     if (key == null) {
>> >
>> > Modified:
>> >
>> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
>> > URL:
>> >
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java?rev=686935&r1=686934&r2=686935&view=diff
>> >
>> >
>> ==============================================================================
>> > ---
>> >
>> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
>> > (original)
>> > +++
>> >
>> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
>> > Mon Aug 18 19:27:54 2008
>> > @@ -24,6 +24,8 @@
>> >
>> >  import junit.framework.TestCase;
>> >
>> > +import java.io.IOException;
>> > +import java.io.StringWriter;
>> >  import java.util.LinkedList;
>> >  import java.util.List;
>> >  import java.util.Set;
>> > @@ -431,4 +433,78 @@
>> >       // Expected condition
>> >     }
>> >   }
>> > +
>> > +  public void testRenderOnlyTextNode() {
>> > +    String content = "  hello, world!\n  ";
>> > +    assertEquals(content, renderNode(new GadgetHtmlNode(content)));
>> > +  }
>> > +
>> > +  public void testRenderOnlyTagNodeShortForm() {
>> > +    String[][] attribs = { { "id", "foo" }, { "bar", "baz" } };
>> > +    GadgetHtmlNode tag = new GadgetHtmlNode("div", attribs);
>> > +    assertEquals("<div bar=\"baz\" id=\"foo\"/>", renderNode(tag));
>> > +  }
>> > +
>> > +  public void testRenderStyleSrcTag() {
>> > +    String[][] attribs = { { "src", "http://www.foo.com/bar.css" } };
>> > +    GadgetHtmlNode styleTag = new GadgetHtmlNode("style", attribs);
>> > +    assertEquals("<style src=\"http://www.foo.com/bar.css\<http://www.foo.com/bar.css%5C>
>> <http://www.foo.com/bar.css%5C>
>> > "></style>",
>> > +                 renderNode(styleTag));
>> > +  }
>> > +
>> > +  public void testRenderEscapedAttribute() {
>> > +    String[][] attribs = { { "foo", "<script&\"data\">" } };
>> > +    GadgetHtmlNode escapedTag = new GadgetHtmlNode("div", attribs);
>> > +    assertEquals("<div foo=\"&lt;script&amp;&quot;data&quot;&gt;\"/>",
>> > +                 renderNode(escapedTag));
>> > +  }
>> > +
>> > +  public void testRenderNullValuedAttribute() {
>> > +    String[][] attribs = { { "marker", null } };
>> > +    GadgetHtmlNode tag = new GadgetHtmlNode("span", attribs);
>> > +    assertEquals("<span marker/>", renderNode(tag));
>> > +  }
>> > +
>> > +  public void testRenderEscapedTextContent() {
>> > +    GadgetHtmlNode escapedTextNode = new
>> > GadgetHtmlNode("<script&\"data'>");
>> > +    assertEquals("&lt;script&amp;&quot;data'&gt;",
>> > +                 renderNode(escapedTextNode));
>> > +  }
>> > +
>> > +  public void testRenderAdjacentStringsInTag() {
>> > +    GadgetHtmlNode container = new GadgetHtmlNode("div", null);
>> > +    container.appendChild(new GadgetHtmlNode("one"));
>> > +    container.appendChild(new GadgetHtmlNode("\n"));
>> > +    container.appendChild(new GadgetHtmlNode(" two "));
>> > +    assertEquals("<div>one\n two </div>", renderNode(container));
>> > +  }
>> > +
>> > +  public void testRenderMixedContent() {
>> > +    // Something of a catch-all for smaller above tests.
>> > +    String[][] attribs = { { "readonly", null } };
>> > +    GadgetHtmlNode parent = new GadgetHtmlNode("div", attribs);
>> > +    parent.appendChild(new GadgetHtmlNode(" content\n"));
>> > +    parent.appendChild(new GadgetHtmlNode("<br>"));
>> > +    GadgetHtmlNode child1 = new GadgetHtmlNode("span", null);
>> > +    child1.appendChild(new GadgetHtmlNode("hr", null));
>> > +    parent.appendChild(child1);
>> > +    parent.appendChild(new GadgetHtmlNode("\"after text\""));
>> > +    GadgetHtmlNode child2 = new GadgetHtmlNode("p", null);
>> > +    child2.appendChild(new GadgetHtmlNode("paragraph!"));
>> > +    parent.appendChild(child2);
>> > +    assertEquals("<div readonly> content\n&lt;br&gt;<span><hr/>" +
>> > +                 "</span>&quot;after
>> text&quot;<p>paragraph!</p></div>",
>> > +                 renderNode(parent));
>> > +  }
>> > +
>> > +  private String renderNode(GadgetHtmlNode node) {
>> > +    StringWriter sw = new StringWriter();
>> > +    try {
>> > +      node.render(sw);
>> > +    } catch (IOException e) {
>> > +      // Should never happen, but fail just in case.
>> > +      fail("Unexpected IOException on StringWriter operation");
>> > +    }
>> > +    return sw.toString();
>> > +  }
>> >  }
>> >
>> >
>> >
>>
>
>

Re: svn commit: r686935 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java

Posted by John Hjelmstad <fa...@google.com>.
Well that's decidedly not good. Fixing now.
On Tue, Aug 19, 2008 at 4:17 PM, Kevin Brown <et...@google.com> wrote:

> Some of these tests are failing because the internal code is returning sets
> that don't guarantee ordering, and the tests are assuming that they do.
>
> On Mon, Aug 18, 2008 at 7:27 PM, <jo...@apache.org> wrote:
>
> > Author: johnh
> > Date: Mon Aug 18 19:27:54 2008
> > New Revision: 686935
> >
> > URL: http://svn.apache.org/viewvc?rev=686935&view=rev
> > Log:
> > Adding ability for GadgetHtmlNode to render itself as HTML via
> > GadgetHtmlNode.render(Writer w).
> >
> >
> > Modified:
> >
> >
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> >
> >
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> >
> > Modified:
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java?rev=686935&r1=686934&r2=686935&view=diff
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> > (original)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> > Mon Aug 18 19:27:54 2008
> > @@ -17,6 +17,8 @@
> >  */
> >  package org.apache.shindig.gadgets.parse;
> >
> > +import java.io.IOException;
> > +import java.io.Writer;
> >  import java.util.ArrayList;
> >  import java.util.Collections;
> >  import java.util.HashMap;
> > @@ -25,6 +27,8 @@
> >  import java.util.Map;
> >  import java.util.Set;
> >
> > +import org.apache.commons.lang.StringEscapeUtils;
> > +
> >  /**
> >  * Mutable wrapper around a {@code ParsedHtmlNode}.
> >  * Used by rewriting to manipulate a parsed gadget DOM, and
> > @@ -280,6 +284,44 @@
> >     this.text = text;
> >   }
> >
> > +  /**
> > +   * Render self as HTML. Rendering is relatively simple as no
> > +   * additional validation is performed on content beyond what
> > +   * the rest of the class provides, such as attribute key
> > +   * validation. All whitespace and comments are maintained. Nodes
> > +   * with zero children are rendered short-form (&lt;foo/&gt;)
> > +   * unless tagName is "style" since many browsers dislike short-form
> for
> > that.
> > +   * One space is provided between attributes. Attribute values are
> > surrounded
> > +   * in double-quotes. Null-valued attributes are rendered without
> > ="value".
> > +   * Attributes are rendered in no particular order.
> > +   * @param w Writer to which to send content
> > +   * @throws IOException If the writer throws an error on append(...)
> > +   */
> > +  public void render(Writer w) throws IOException {
> > +    if (isText()) {
> > +      w.append(StringEscapeUtils.escapeHtml(getText()));
> > +    } else {
> > +      w.append('<').append(tagName);
> > +      for (String attrKey : getAttributeKeys()) {
> > +        String attrValue = getAttributeValue(attrKey);
> > +        w.append(' ').append(attrKey);
> > +        if (attrValue != null) {
> > +
> >
>  w.append("=\"").append(StringEscapeUtils.escapeHtml(attrValue)).append('"');
> > +        }
> > +      }
> > +      if (children.size() == 0 &&
> > +          !tagName.equalsIgnoreCase("style")) {
> > +        w.append("/>");
> > +      } else {
> > +        w.append('>');
> > +        for (GadgetHtmlNode child : children) {
> > +          child.render(w);
> > +        }
> > +        w.append("</").append(tagName).append('>');
> > +      }
> > +    }
> > +  }
> > +
> >   // Helper that cleans up and validates an attribute key
> >   private String validateAttributeKey(String key) {
> >     if (key == null) {
> >
> > Modified:
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> > URL:
> >
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java?rev=686935&r1=686934&r2=686935&view=diff
> >
> >
> ==============================================================================
> > ---
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> > (original)
> > +++
> >
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> > Mon Aug 18 19:27:54 2008
> > @@ -24,6 +24,8 @@
> >
> >  import junit.framework.TestCase;
> >
> > +import java.io.IOException;
> > +import java.io.StringWriter;
> >  import java.util.LinkedList;
> >  import java.util.List;
> >  import java.util.Set;
> > @@ -431,4 +433,78 @@
> >       // Expected condition
> >     }
> >   }
> > +
> > +  public void testRenderOnlyTextNode() {
> > +    String content = "  hello, world!\n  ";
> > +    assertEquals(content, renderNode(new GadgetHtmlNode(content)));
> > +  }
> > +
> > +  public void testRenderOnlyTagNodeShortForm() {
> > +    String[][] attribs = { { "id", "foo" }, { "bar", "baz" } };
> > +    GadgetHtmlNode tag = new GadgetHtmlNode("div", attribs);
> > +    assertEquals("<div bar=\"baz\" id=\"foo\"/>", renderNode(tag));
> > +  }
> > +
> > +  public void testRenderStyleSrcTag() {
> > +    String[][] attribs = { { "src", "http://www.foo.com/bar.css" } };
> > +    GadgetHtmlNode styleTag = new GadgetHtmlNode("style", attribs);
> > +    assertEquals("<style src=\"http://www.foo.com/bar.css\<
> http://www.foo.com/bar.css%5C>
> > "></style>",
> > +                 renderNode(styleTag));
> > +  }
> > +
> > +  public void testRenderEscapedAttribute() {
> > +    String[][] attribs = { { "foo", "<script&\"data\">" } };
> > +    GadgetHtmlNode escapedTag = new GadgetHtmlNode("div", attribs);
> > +    assertEquals("<div foo=\"&lt;script&amp;&quot;data&quot;&gt;\"/>",
> > +                 renderNode(escapedTag));
> > +  }
> > +
> > +  public void testRenderNullValuedAttribute() {
> > +    String[][] attribs = { { "marker", null } };
> > +    GadgetHtmlNode tag = new GadgetHtmlNode("span", attribs);
> > +    assertEquals("<span marker/>", renderNode(tag));
> > +  }
> > +
> > +  public void testRenderEscapedTextContent() {
> > +    GadgetHtmlNode escapedTextNode = new
> > GadgetHtmlNode("<script&\"data'>");
> > +    assertEquals("&lt;script&amp;&quot;data'&gt;",
> > +                 renderNode(escapedTextNode));
> > +  }
> > +
> > +  public void testRenderAdjacentStringsInTag() {
> > +    GadgetHtmlNode container = new GadgetHtmlNode("div", null);
> > +    container.appendChild(new GadgetHtmlNode("one"));
> > +    container.appendChild(new GadgetHtmlNode("\n"));
> > +    container.appendChild(new GadgetHtmlNode(" two "));
> > +    assertEquals("<div>one\n two </div>", renderNode(container));
> > +  }
> > +
> > +  public void testRenderMixedContent() {
> > +    // Something of a catch-all for smaller above tests.
> > +    String[][] attribs = { { "readonly", null } };
> > +    GadgetHtmlNode parent = new GadgetHtmlNode("div", attribs);
> > +    parent.appendChild(new GadgetHtmlNode(" content\n"));
> > +    parent.appendChild(new GadgetHtmlNode("<br>"));
> > +    GadgetHtmlNode child1 = new GadgetHtmlNode("span", null);
> > +    child1.appendChild(new GadgetHtmlNode("hr", null));
> > +    parent.appendChild(child1);
> > +    parent.appendChild(new GadgetHtmlNode("\"after text\""));
> > +    GadgetHtmlNode child2 = new GadgetHtmlNode("p", null);
> > +    child2.appendChild(new GadgetHtmlNode("paragraph!"));
> > +    parent.appendChild(child2);
> > +    assertEquals("<div readonly> content\n&lt;br&gt;<span><hr/>" +
> > +                 "</span>&quot;after text&quot;<p>paragraph!</p></div>",
> > +                 renderNode(parent));
> > +  }
> > +
> > +  private String renderNode(GadgetHtmlNode node) {
> > +    StringWriter sw = new StringWriter();
> > +    try {
> > +      node.render(sw);
> > +    } catch (IOException e) {
> > +      // Should never happen, but fail just in case.
> > +      fail("Unexpected IOException on StringWriter operation");
> > +    }
> > +    return sw.toString();
> > +  }
> >  }
> >
> >
> >
>

Re: svn commit: r686935 - in /incubator/shindig/trunk/java/gadgets/src: main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java

Posted by Kevin Brown <et...@google.com>.
Some of these tests are failing because the internal code is returning sets
that don't guarantee ordering, and the tests are assuming that they do.

On Mon, Aug 18, 2008 at 7:27 PM, <jo...@apache.org> wrote:

> Author: johnh
> Date: Mon Aug 18 19:27:54 2008
> New Revision: 686935
>
> URL: http://svn.apache.org/viewvc?rev=686935&view=rev
> Log:
> Adding ability for GadgetHtmlNode to render itself as HTML via
> GadgetHtmlNode.render(Writer w).
>
>
> Modified:
>
>  incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
>
>  incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java?rev=686935&r1=686934&r2=686935&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
> Mon Aug 18 19:27:54 2008
> @@ -17,6 +17,8 @@
>  */
>  package org.apache.shindig.gadgets.parse;
>
> +import java.io.IOException;
> +import java.io.Writer;
>  import java.util.ArrayList;
>  import java.util.Collections;
>  import java.util.HashMap;
> @@ -25,6 +27,8 @@
>  import java.util.Map;
>  import java.util.Set;
>
> +import org.apache.commons.lang.StringEscapeUtils;
> +
>  /**
>  * Mutable wrapper around a {@code ParsedHtmlNode}.
>  * Used by rewriting to manipulate a parsed gadget DOM, and
> @@ -280,6 +284,44 @@
>     this.text = text;
>   }
>
> +  /**
> +   * Render self as HTML. Rendering is relatively simple as no
> +   * additional validation is performed on content beyond what
> +   * the rest of the class provides, such as attribute key
> +   * validation. All whitespace and comments are maintained. Nodes
> +   * with zero children are rendered short-form (&lt;foo/&gt;)
> +   * unless tagName is "style" since many browsers dislike short-form for
> that.
> +   * One space is provided between attributes. Attribute values are
> surrounded
> +   * in double-quotes. Null-valued attributes are rendered without
> ="value".
> +   * Attributes are rendered in no particular order.
> +   * @param w Writer to which to send content
> +   * @throws IOException If the writer throws an error on append(...)
> +   */
> +  public void render(Writer w) throws IOException {
> +    if (isText()) {
> +      w.append(StringEscapeUtils.escapeHtml(getText()));
> +    } else {
> +      w.append('<').append(tagName);
> +      for (String attrKey : getAttributeKeys()) {
> +        String attrValue = getAttributeValue(attrKey);
> +        w.append(' ').append(attrKey);
> +        if (attrValue != null) {
> +
>  w.append("=\"").append(StringEscapeUtils.escapeHtml(attrValue)).append('"');
> +        }
> +      }
> +      if (children.size() == 0 &&
> +          !tagName.equalsIgnoreCase("style")) {
> +        w.append("/>");
> +      } else {
> +        w.append('>');
> +        for (GadgetHtmlNode child : children) {
> +          child.render(w);
> +        }
> +        w.append("</").append(tagName).append('>');
> +      }
> +    }
> +  }
> +
>   // Helper that cleans up and validates an attribute key
>   private String validateAttributeKey(String key) {
>     if (key == null) {
>
> Modified:
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java?rev=686935&r1=686934&r2=686935&view=diff
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> (original)
> +++
> incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
> Mon Aug 18 19:27:54 2008
> @@ -24,6 +24,8 @@
>
>  import junit.framework.TestCase;
>
> +import java.io.IOException;
> +import java.io.StringWriter;
>  import java.util.LinkedList;
>  import java.util.List;
>  import java.util.Set;
> @@ -431,4 +433,78 @@
>       // Expected condition
>     }
>   }
> +
> +  public void testRenderOnlyTextNode() {
> +    String content = "  hello, world!\n  ";
> +    assertEquals(content, renderNode(new GadgetHtmlNode(content)));
> +  }
> +
> +  public void testRenderOnlyTagNodeShortForm() {
> +    String[][] attribs = { { "id", "foo" }, { "bar", "baz" } };
> +    GadgetHtmlNode tag = new GadgetHtmlNode("div", attribs);
> +    assertEquals("<div bar=\"baz\" id=\"foo\"/>", renderNode(tag));
> +  }
> +
> +  public void testRenderStyleSrcTag() {
> +    String[][] attribs = { { "src", "http://www.foo.com/bar.css" } };
> +    GadgetHtmlNode styleTag = new GadgetHtmlNode("style", attribs);
> +    assertEquals("<style src=\"http://www.foo.com/bar.css\<http://www.foo.com/bar.css%5C>
> "></style>",
> +                 renderNode(styleTag));
> +  }
> +
> +  public void testRenderEscapedAttribute() {
> +    String[][] attribs = { { "foo", "<script&\"data\">" } };
> +    GadgetHtmlNode escapedTag = new GadgetHtmlNode("div", attribs);
> +    assertEquals("<div foo=\"&lt;script&amp;&quot;data&quot;&gt;\"/>",
> +                 renderNode(escapedTag));
> +  }
> +
> +  public void testRenderNullValuedAttribute() {
> +    String[][] attribs = { { "marker", null } };
> +    GadgetHtmlNode tag = new GadgetHtmlNode("span", attribs);
> +    assertEquals("<span marker/>", renderNode(tag));
> +  }
> +
> +  public void testRenderEscapedTextContent() {
> +    GadgetHtmlNode escapedTextNode = new
> GadgetHtmlNode("<script&\"data'>");
> +    assertEquals("&lt;script&amp;&quot;data'&gt;",
> +                 renderNode(escapedTextNode));
> +  }
> +
> +  public void testRenderAdjacentStringsInTag() {
> +    GadgetHtmlNode container = new GadgetHtmlNode("div", null);
> +    container.appendChild(new GadgetHtmlNode("one"));
> +    container.appendChild(new GadgetHtmlNode("\n"));
> +    container.appendChild(new GadgetHtmlNode(" two "));
> +    assertEquals("<div>one\n two </div>", renderNode(container));
> +  }
> +
> +  public void testRenderMixedContent() {
> +    // Something of a catch-all for smaller above tests.
> +    String[][] attribs = { { "readonly", null } };
> +    GadgetHtmlNode parent = new GadgetHtmlNode("div", attribs);
> +    parent.appendChild(new GadgetHtmlNode(" content\n"));
> +    parent.appendChild(new GadgetHtmlNode("<br>"));
> +    GadgetHtmlNode child1 = new GadgetHtmlNode("span", null);
> +    child1.appendChild(new GadgetHtmlNode("hr", null));
> +    parent.appendChild(child1);
> +    parent.appendChild(new GadgetHtmlNode("\"after text\""));
> +    GadgetHtmlNode child2 = new GadgetHtmlNode("p", null);
> +    child2.appendChild(new GadgetHtmlNode("paragraph!"));
> +    parent.appendChild(child2);
> +    assertEquals("<div readonly> content\n&lt;br&gt;<span><hr/>" +
> +                 "</span>&quot;after text&quot;<p>paragraph!</p></div>",
> +                 renderNode(parent));
> +  }
> +
> +  private String renderNode(GadgetHtmlNode node) {
> +    StringWriter sw = new StringWriter();
> +    try {
> +      node.render(sw);
> +    } catch (IOException e) {
> +      // Should never happen, but fail just in case.
> +      fail("Unexpected IOException on StringWriter operation");
> +    }
> +    return sw.toString();
> +  }
>  }
>
>
>