[committed]TerrainPage loading issue (with fix)

I've noticed a problem with the Savable implementation in TerrainPage: it's casting to the wrong Vector types.



There are 3 (related) patches here.



  • fix-savable-bug-in-terrain-page.patch
    This is the actual bug that I wanted to fix: terrain pages weren't being saved correctly. This bug fixes that and adds a unit test for it.

  • improve-null-handling-in-dom-io-capsules.patch
    This fixes an issue with the XML export/import code that (sometimes) caused NullPointerException on export and IOException on import, both related to null value handling.
       
    I think that there are other examples of the same issue in these 2 files (DOMInputCapsule and DOMOutputCapsule), if people are happy with this patch I will go through the capsules and check for more occurrences.

  • prettify-dom-serializer-output.patch
    This cleans up the output from the DOMSerializer - since I was using this to test the TerrainPage patch it was pretty painful to try to read the output of the existing code (basically, the line breaking and indentation were all messed up).
       
    This patch also deprecates the serialize method that takes a Writer argument as it did not set the charset correctly. No core JME code uses this and it should be a trivial change for any applications so I don't see a problem with removing it in short order.
       
    I've also taken the liberty of deprecating the DOM_PrettyPrinter class as part of this - it isn't required had a wierd name.  :)



If there are no complaints I'll commit these early next week.

Cheers,
Ian.

[Edit: Added 'committed' to topic - nymon]

As nobody has complained I'm going to commit this.

Done.

Better post the paches in code tags if they are not too big, that way it will get more attention :slight_smile:



I think the global moderators like nymon and basixs cant see the attached files.

hmm, yeah I see no patches (or attachments, which I thought was fixed for nymon and I).  Are there attachments here?



(Sorry, I have been hard pressed at work lately…)

yep 3 patches, downloaded once each :slight_smile:

That is super odd, I don't see anything…

links to the attachements for nymon and basixs :slight_smile:



http://www.jmonkeyengine.com/jmeforum/index.php?action=dlattach;topic=10708.0;attach=249



http://www.jmonkeyengine.com/jmeforum/index.php?action=dlattach;topic=10708.0;attach=248



http://www.jmonkeyengine.com/jmeforum/index.php?action=dlattach;topic=10708.0;attach=247

heh, clicking on the links…

It seems that you are not allowed to download or view attachments on this board.

Errm, sorry about that. I had been told before that some people had issues with seeing attachments but I forgot.



Here's the patches:



fix-savable-bug-in-terrain-page.patch.txt


### Eclipse Workspace Patch 1.0
#P jme
Index: junit/com/jmex/terrain/TestTerrainPage.java
===================================================================
--- junit/com/jmex/terrain/TestTerrainPage.java   (revision 0)
+++ junit/com/jmex/terrain/TestTerrainPage.java   (revision 0)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2003-2009 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jmex.terrain;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.junit.Test;
+
+import com.jme.math.Vector3f;
+import com.jme.system.DisplaySystem;
+import com.jme.system.dummy.DummySystemProvider;
+import com.jme.util.export.JMEExporter;
+import com.jme.util.export.JMEImporter;
+import com.jme.util.export.binary.BinaryExporter;
+import com.jme.util.export.binary.BinaryImporter;
+import com.jme.util.export.xml.XMLExporter;
+import com.jme.util.export.xml.XMLImporter;
+
+/**
+ * Unit tests for {@link TerrainPage}.
+ *
+ * @version $Revision$, $Date$
+ */
+public class TestTerrainPage {
+
+    @Test
+    public void checkThatSavingAsBinaryWorks() throws Exception {
+        DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
+        checkThatSavingWorks(BinaryExporter.getInstance(), BinaryImporter.getInstance());
+    }
+
+    @Test
+    public void checkThatSavingAsXMLWorks() throws Exception {
+        checkThatSavingWorks(XMLExporter.getInstance(), XMLImporter.getInstance());
+    }
+   
+    public void checkThatSavingWorks(JMEExporter exporter, JMEImporter importer) throws Exception {
+        int blockSize = 16;
+        int size = 65;
+        Vector3f stepScale = new Vector3f();
+        float[] heightMap = new float[size];
+
+        TerrainPage page = new TerrainPage("testTerrainPage", blockSize, size, stepScale, heightMap);
+
+        File file = File.createTempFile("testTerrainPage", ".tmp");
+
+        // check the the page writes without throwing an exception
+        OutputStream output = new FileOutputStream(file);
+        exporter.save(page, output);
+        output.flush();
+        output.close();
+
+        // now see if we can load it back in correctly
+        InputStream input = new FileInputStream(file);
+        TerrainPage loadedPage = (TerrainPage) importer.load(input);
+       
+        file.deleteOnExit();
+
+        // and some trivial sanity checks
+        assertTrue(loadedPage.getSize() == size);
+        assertTrue(loadedPage.getStepScale().equals(stepScale));
+        assertTrue(loadedPage.getTotalSize() == size);
+       
+        // should probably also probe the height map here as well
+    }
+   
+}
Index: src/com/jmex/terrain/TerrainPage.java
===================================================================
--- src/com/jmex/terrain/TerrainPage.java   (revision 4136)
+++ src/com/jmex/terrain/TerrainPage.java   (working copy)
@@ -1127,11 +1127,10 @@
     public void read(JMEImporter e) throws IOException {
         super.read(e);
         InputCapsule capsule = e.getCapsule(this);
-        offset = (Vector2f) capsule
-                .readSavable("offset", Vector3f.ZERO.clone());
+        offset = (Vector2f) capsule.readSavable("offset", new Vector2f());
         totalSize = capsule.readInt("totalSize", 0);
         size = capsule.readInt("size", 0);
-        stepScale = (Vector3f) capsule.readSavable("stepScale", new Vector2f());
+        stepScale = (Vector3f) capsule.readSavable("stepScale", new Vector3f());
         offsetAmount = capsule.readFloat("offsetAmount", 0);
         quadrant = capsule.readShort("quadrant", (short) 1);
     }



and

improve-null-handling-in-dom-io-capsules.patch.txt


### Eclipse Workspace Patch 1.0
#P jme
Index: src/com/jme/util/export/xml/DOMInputCapsule.java
===================================================================
--- src/com/jme/util/export/xml/DOMInputCapsule.java   (revision 4136)
+++ src/com/jme/util/export/xml/DOMInputCapsule.java   (working copy)
@@ -498,15 +498,15 @@
     }
 
     public short readShort(String name, short defVal) throws IOException {
-        short ret = defVal;
+        String attribute = currentElem.getAttribute(name);
+        if (attribute == null || attribute.length() == 0) { return defVal; }
         try {
-            ret = Short.parseShort(currentElem.getAttribute(name));
-        } catch (Exception e) {
-            IOException ex = new IOException();
+            return Short.parseShort(attribute);
+        } catch (NumberFormatException e) {
+            IOException ex = new IOException("error reading " + name);
             ex.initCause(e);
             throw ex;
         }
-        return ret;
     }
 
     public short[] readShortArray(String name, short[] defVal) throws IOException {
@@ -1127,7 +1127,7 @@
             tmp.flip();
             ret = tmp;
         } catch (Exception e) {
-            IOException ex = new IOException();
+            IOException ex = new IOException("error reading " + name);
             ex.initCause(e);
             throw ex;
         }
Index: src/com/jme/util/export/xml/DOMOutputCapsule.java
===================================================================
--- src/com/jme/util/export/xml/DOMOutputCapsule.java   (revision 4136)
+++ src/com/jme/util/export/xml/DOMOutputCapsule.java   (working copy)
@@ -200,15 +200,17 @@
         if (value == null) {
             value = defVal;
         }
-        for (float b : value) {
-            buf.append(b);
-            buf.append(" ");
+        if (value != null) {
+            for (float b : value) {
+                buf.append(b);
+                buf.append(" ");
+            }
+            //remove last space
+            buf.setLength(buf.length() - 1);
         }
-        //remove last space
-        buf.setLength(buf.length() - 1);
 
         Element el = appendElement(name);
-        el.setAttribute("size", String.valueOf(value.length));
+        el.setAttribute("size", value == null ? "0" : String.valueOf(value.length));
         el.setAttribute(dataAttributeName, buf.toString());
         currentElement = (Element) currentElement.getParentNode();
     }



Cheers,
Ian.

Looks okay here :slight_smile:

Agreed

It's in - actually a few days ago, but I forgot to post a note here (you all follow commits via RSS anyway, right ;).

I did see the commit, just nice to see the patches too :slight_smile:

Could someone add a [commiteed] to the topic?

Its easier to keep track of uncommited patches.