]> source.dussan.org Git - vaadin-framework.git/commitdiff
Allow reading and writing empty designs (#7749).
authorMika Murtojarvi <mika@vaadin.com>
Wed, 17 Dec 2014 16:10:09 +0000 (18:10 +0200)
committerVaadin Code Review <review@vaadin.com>
Thu, 18 Dec 2014 16:35:13 +0000 (16:35 +0000)
Change-Id: Id66201d040d07f0e0d731418624c9b702b2d0d3b

server/src/com/vaadin/ui/declarative/Design.java
server/src/com/vaadin/ui/declarative/DesignContext.java
server/tests/src/com/vaadin/tests/server/component/TestReadEmptyDesign.java [new file with mode: 0644]
server/tests/src/com/vaadin/tests/server/component/TestWriteEmptyDesign.java [new file with mode: 0644]

index 59393a781598a567c468a4e4d825f379d5b91905..dc96e789bf78a0ed918c09b3d3dbb5ea2fffaea1 100644 (file)
@@ -184,13 +184,18 @@ public class Design implements Serializable {
         // taken care of by jsoup.
         Element root = doc.body();
         Elements children = root.children();
-        if (children.size() != 1) {
+        if (children.size() > 1) {
             throw new DesignException(
-                    "The first level of a component hierarchy should contain exactly one root component, but found "
-                            + children.size());
+                    "The first level of a component hierarchy should contain at most one root component, but found "
+                            + children.size() + ".");
         }
-        Element element = children.first();
+        Element element = children.size() == 0 ? null : children.first();
         if (componentRoot != null) {
+            if (element == null) {
+                throw new DesignException(
+                        "The root element cannot be null when the specified root Component is"
+                                + " not null.");
+            }
             // user has specified root instance that may have member fields that
             // should be bound
             final FieldBinder binder;
@@ -222,7 +227,8 @@ public class Design implements Serializable {
             designContext.removeComponentCreationListener(creationListener);
         } else {
             // createChild creates the entire component hierarchy
-            componentRoot = designContext.readDesign(element);
+            componentRoot = element == null ? null : designContext
+                    .readDesign(element);
         }
         designContext.setRootComponent(componentRoot);
         return designContext;
@@ -255,8 +261,10 @@ public class Design implements Serializable {
         // creates the entire component hierarchy rooted at the
         // given root node.
         Component root = designContext.getRootComponent();
-        Node rootNode = designContext.createElement(root);
-        body.appendChild(rootNode);
+        if (root != null) {
+            Node rootNode = designContext.createElement(root);
+            body.appendChild(rootNode);
+        }
         designContext.writePackageMappings(doc);
         return doc;
     }
@@ -424,10 +432,11 @@ public class Design implements Serializable {
 
     /**
      * Writes the given component tree in design format to the given output
-     * stream
+     * stream.
      * 
      * @param component
-     *            the root component of the component tree
+     *            the root component of the component tree, null can be used for
+     *            generating an empty design
      * @param outputStream
      *            the output stream to write the design to. The design is always
      *            written as UTF-8
@@ -446,8 +455,10 @@ public class Design implements Serializable {
      * and other information not available in the component tree.
      * 
      * @param designContext
-     *            the DesignContext object specifying the component hierarchy
-     *            and the local id values of the objects
+     *            The DesignContext object specifying the component hierarchy
+     *            and the local id values of the objects. If
+     *            designContext.getRootComponent() is null, an empty design will
+     *            be generated.
      * @param outputStream
      *            the output stream to write the design to. The design is always
      *            written as UTF-8
index ade249463816fb14dfe233bd97e5b0456d13a5a4..fd83339b763a6552b72d3dbaa18fe839ec0cf253 100644 (file)
@@ -415,7 +415,7 @@ public class DesignContext implements Serializable {
      * 
      * @param componentDesign
      *            The design element containing the description of the component
-     *            to be created
+     *            to be created.
      * @return the root component of component tree
      */
     public Component readDesign(Element componentDesign) {
diff --git a/server/tests/src/com/vaadin/tests/server/component/TestReadEmptyDesign.java b/server/tests/src/com/vaadin/tests/server/component/TestReadEmptyDesign.java
new file mode 100644 (file)
index 0000000..ecd303b
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.server.component;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.DocumentType;
+import org.jsoup.nodes.Element;
+
+import com.vaadin.ui.Component;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.declarative.Design;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
+
+/**
+ * Test cases for checking that reading a design with no elements in the html
+ * body produces null as the root component.
+ */
+public class TestReadEmptyDesign extends TestCase {
+    InputStream is;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        String html = createDesign().toString();
+        is = new ByteArrayInputStream(html.getBytes());
+    }
+
+    public void testReadComponent() {
+        Component root = Design.read(is);
+        assertNull("The root component should be null.", root);
+    }
+
+    public void testReadContext() {
+        DesignContext ctx = Design.read(is, null);
+        assertNotNull("The design context should not be null.", ctx);
+        assertNull("The root component should be null.", ctx.getRootComponent());
+    }
+
+    public void testReadContextWithRootParameter() {
+        try {
+            Component rootComponent = new VerticalLayout();
+            DesignContext ctx = Design.read(is, rootComponent);
+            fail("Reading a design with no elements should fail when a non-null root Component is specified.");
+        } catch (DesignException e) {
+            // This is the expected outcome, nothing to do.
+        }
+    }
+
+    private Document createDesign() {
+        Document doc = new Document("");
+        DocumentType docType = new DocumentType("html", "", "", "");
+        doc.appendChild(docType);
+        Element html = doc.createElement("html");
+        doc.appendChild(html);
+        html.appendChild(doc.createElement("head"));
+        html.appendChild(doc.createElement("body"));
+        return doc;
+    }
+}
\ No newline at end of file
diff --git a/server/tests/src/com/vaadin/tests/server/component/TestWriteEmptyDesign.java b/server/tests/src/com/vaadin/tests/server/component/TestWriteEmptyDesign.java
new file mode 100644 (file)
index 0000000..b50915f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.server.component;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import junit.framework.TestCase;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+
+import com.vaadin.ui.Component;
+import com.vaadin.ui.declarative.Design;
+import com.vaadin.ui.declarative.DesignContext;
+
+/**
+ * Test cases for checking that writing a component hierarchy with null root
+ * produces an html document that has no elements in the html body.
+ */
+public class TestWriteEmptyDesign extends TestCase {
+
+    public void testWriteComponent() throws IOException {
+        OutputStream os = new ByteArrayOutputStream();
+        Design.write((Component) null, os);
+        checkHtml(os.toString());
+    }
+
+    public void testWriteContext() throws IOException {
+        OutputStream os = new ByteArrayOutputStream();
+        DesignContext ctx = new DesignContext();
+        ctx.setRootComponent(null);
+        Design.write(ctx, os);
+        checkHtml(os.toString());
+    }
+
+    private void checkHtml(String html) {
+        Document doc = Jsoup.parse(html);
+        Element body = doc.body();
+        assertEquals("There should be no elements in the html body.", "",
+                body.html());
+    }
+}
\ No newline at end of file