From e47ab4522b49fb0ed93cdca3c3ea2211a3ba05d3 Mon Sep 17 00:00:00 2001
From: Ralf Jung <ralfjung-e@gmx.de>
Date: Thu, 11 Aug 2011 12:06:51 +0200
Subject: [PATCH] fix xxforms:element on read-only instances

---
 src/java/org/orbeon/oxf/xforms/XFormsUtils.java    |   11 +++++-
 .../xforms/action/actions/XFormsInsertAction.java  |    4 +-
 .../xforms/function/xxforms/XXFormsElement.java    |   33 ++++++++-----------
 3 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/src/java/org/orbeon/oxf/xforms/XFormsUtils.java b/src/java/org/orbeon/oxf/xforms/XFormsUtils.java
index 07e8ee9..da66f61 100644
--- a/src/java/org/orbeon/oxf/xforms/XFormsUtils.java
+++ b/src/java/org/orbeon/oxf/xforms/XFormsUtils.java
@@ -947,9 +947,16 @@ public class XFormsUtils {
         return null;
     }
 
-    public static Node getNodeFromNodeInfoConvert(NodeInfo nodeInfo, String errorMessage) {
+    /**
+     * Return the underlying Node from the given NodeInfo, possibly converting it to a Dom4j Node. Changes to the returned Node may or may not 
+     * reflect on the original, depending on its type.
+     *
+     * @param nodeInfo      NodeInfo to process
+     * @return              Node
+     */
+    public static Node getNodeFromNodeInfoConvert(NodeInfo nodeInfo) {
         if (nodeInfo instanceof NodeWrapper)
-            return getNodeFromNodeInfo(nodeInfo, errorMessage);
+            return (Node) ((NodeWrapper) nodeInfo).getUnderlyingNode();
         else
             return TransformerUtils.tinyTreeToDom4j2((nodeInfo.getParent() instanceof DocumentInfo) ? nodeInfo.getParent() : nodeInfo);
     }
diff --git a/src/java/org/orbeon/oxf/xforms/action/actions/XFormsInsertAction.java b/src/java/org/orbeon/oxf/xforms/action/actions/XFormsInsertAction.java
index 431ec64..fdf00dc 100644
--- a/src/java/org/orbeon/oxf/xforms/action/actions/XFormsInsertAction.java
+++ b/src/java/org/orbeon/oxf/xforms/action/actions/XFormsInsertAction.java
@@ -199,7 +199,7 @@ public class XFormsInsertAction extends XFormsAction {
 
                 // "Otherwise, if the origin attribute is not given, then the origin node-set consists of the last
                 // node of the Node Set Binding node-set."
-                final Node singleSourceNode = XFormsUtils.getNodeFromNodeInfoConvert((NodeInfo) collectionToBeUpdated.get(collectionToBeUpdated.size() - 1), CANNOT_INSERT_READONLY_MESSAGE);
+                final Node singleSourceNode = XFormsUtils.getNodeFromNodeInfoConvert((NodeInfo) collectionToBeUpdated.get(collectionToBeUpdated.size() - 1));
                 // TODO: check namespace handling might be incorrect. Should use copyElementCopyParentNamespaces() instead?
                 final Node singleClonedNode = Dom4jUtils.createCopy(singleSourceNode);
 
@@ -227,7 +227,7 @@ public class XFormsInsertAction extends XFormsAction {
                         // This is the regular case covered by XForms 1.1 / XPath 1.0
 
                         // NOTE: Don't clone nodes if doClone == false
-                        final Node sourceNode = XFormsUtils.getNodeFromNodeInfoConvert((NodeInfo) currentObject, CANNOT_INSERT_READONLY_MESSAGE);
+                        final Node sourceNode = XFormsUtils.getNodeFromNodeInfoConvert((NodeInfo) currentObject);
                         final Node clonedNode = doClone ? (sourceNode instanceof Element) ? ((Element) sourceNode).createCopy() : (Node) sourceNode.clone() : sourceNode;
 
                         sourceNodes.add(sourceNode);
diff --git a/src/java/org/orbeon/oxf/xforms/function/xxforms/XXFormsElement.java b/src/java/org/orbeon/oxf/xforms/function/xxforms/XXFormsElement.java
index d30944c..c7dec70 100644
--- a/src/java/org/orbeon/oxf/xforms/function/xxforms/XXFormsElement.java
+++ b/src/java/org/orbeon/oxf/xforms/function/xxforms/XXFormsElement.java
@@ -14,10 +14,12 @@
 package org.orbeon.oxf.xforms.function.xxforms;
 
 import org.dom4j.Attribute;
+import org.dom4j.Document;
 import org.dom4j.Element;
 import org.dom4j.Node;
 import org.dom4j.QName;
 import org.orbeon.oxf.xforms.function.XFormsFunction;
+import org.orbeon.oxf.xforms.XFormsUtils;
 import org.orbeon.oxf.xml.dom4j.Dom4jUtils;
 import org.orbeon.saxon.dom4j.NodeWrapper;
 import org.orbeon.saxon.expr.Expression;
@@ -85,27 +87,20 @@ public class XXFormsElement extends XFormsFunction {
         } else if (item instanceof NodeInfo) {
             // Insert nodes
 
-            if (item instanceof NodeWrapper) {
-                // dom4j node
-
-                // Copy node before using it
-                final Node newNode; {
-                final Node currentNode = (Node) ((NodeWrapper) item).getUnderlyingNode();
-                    // TODO: check namespace handling might be incorrect. Should use copyElementCopyParentNamespaces() instead?
-                    newNode = Dom4jUtils.createCopy(currentNode);
-                }
-
-                if (newNode instanceof Attribute) {
-                    // Add attribute
-                    element.add((Attribute) newNode);
-                } else {
-                    // Append node
-                    element.content().add(newNode);
-                }
+            // Copy node before using it
+            final Node currentNode = XFormsUtils.getNodeFromNodeInfoConvert((NodeInfo) item);
+            // TODO: check namespace handling might be incorrect. Should use copyElementCopyParentNamespaces() instead?
+            final Node newNode = Dom4jUtils.createCopy(currentNode);
 
+            if (newNode instanceof Attribute) {
+                // Add attribute
+                element.add((Attribute) newNode);
+            } else if (newNode instanceof Document) {
+                // use the document root instead
+                element.content().add(newNode.getDocument().getRootElement());
             } else {
-                // Other type of node
-                // TODO: read and convert
+                // Append node
+                element.content().add(newNode);
             }
         }
         return hasNewText;
-- 
1.7.5.4

