summaryrefslogtreecommitdiff
path: root/forms
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2004-11-16 09:54:37 +0000
committerOliver Bolte <obo@openoffice.org>2004-11-16 09:54:37 +0000
commited8c4fd992a4e2e43e65d05e6f06336bfe2fdba2 (patch)
treeeff58ff104cf29dfd2c409e6bf65b35d7d189b4c /forms
parent784ab960f3806301c357a3c739647f9bc2d8b217 (diff)
INTEGRATION: CWS eforms2 (1.1.2); FILE ADDED
2004/11/05 16:35:54 fs 1.1.2.24: #i35395# also serializeForDisplay attribute nodes 2004/11/03 20:07:39 dvo 1.1.2.23: don't allow multiple attributes with the same name Issue number: Submitted by: Reviewed by: 2004/11/03 19:21:20 dvo 1.1.2.22: #i36196# fix renameNode for attribute nodes Issue number: Submitted by: Reviewed by: 2004/10/29 15:59:19 dvo 1.1.2.21: #i36195# fix XFormsUIHelper1::renameInstance Issue number: Submitted by: Reviewed by: 2004/10/29 15:22:57 fs 1.1.2.20: #i35400# moved the whitespace conversion methods to the Convert class 2004/10/21 15:15:14 dvo 1.1.2.19: #i34791# XForms: set node value according to XForms simple-content rules Issue number: Submitted by: Reviewed by: 2004/09/22 16:00:07 dvo 1.1.2.18: fix: recognize tab as whitespace character Issue number: Submitted by: Reviewed by: 2004/08/12 18:01:56 dvo 1.1.2.17: #i31958# fix Linux build Issue number: Submitted by: Reviewed by: 2004/08/12 16:21:20 dvo 1.1.2.16: #i31958# adjust bindings when renaming nodes Issue number: Submitted by: Reviewed by: 2004/08/12 13:58:34 dvo 1.1.2.15: #i31958# fix :getBindingForNode Issue number: Submitted by: Reviewed by: 2004/08/11 18:07:26 dvo 1.1.2.14: #i31958# implement XFormsUIHelper1::renameNode() 2004/08/11 12:36:32 dvo 1.1.2.13: #i31958# fix XModelUIHelper1:::getResultForExpression("/",...) Issue number: Submitted by: Reviewed by: 2004/08/09 14:06:28 dvo 1.1.2.12: #i31958# continue XForms implementation Issue number: Submitted by: Reviewed by: 2004/08/06 16:18:15 dvo 1.1.2.11: #i31958# continue XForms implementation Issue number: Submitted by: Reviewed by: 2004/08/05 16:53:02 dvo 1.1.2.10: #i31958# continue XFormsUIHelper1 Issue number: Submitted by: Reviewed by: 2004/08/05 12:07:05 dvo 1.1.2.9: #i31958# continue XFormsUIHelper1 Issue number: Submitted by: Reviewed by: 2004/08/05 09:24:16 dvo 1.1.2.8: #i31958# continue XForms implementation 2004/08/02 13:49:44 dvo 1.1.2.7: #i31958# continue XForms implementation Issue number: Submitted by: Reviewed by: 2004/07/26 17:04:14 dvo 1.1.2.6: #i31958# prevent empty 'name' for instance root node Issue number: Submitted by: Reviewed by: 2004/07/21 17:45:11 dvo 1.1.2.5: #114856# continue XFormsUIHelper1 Issue number: Submitted by: Reviewed by: 2004/07/20 16:26:13 dvo 1.1.2.4: #114856# implement XFormsUIHelper1::newInstance Issue number: Submitted by: Reviewed by: 2004/07/20 15:54:22 dvo 1.1.2.3: #114856# continue XFormsUIHelper1 Issue number: Submitted by: Reviewed by: 2004/07/20 15:33:10 dvo 1.1.2.2: #114856# fix Linux build Issue number: Submitted by: Reviewed by: 2004/07/16 17:02:20 dvo 1.1.2.1: #114856# move XFormsUIHelper1 implementation to new file Issue number: Submitted by: Reviewed by:
Diffstat (limited to 'forms')
-rw-r--r--forms/source/xforms/model_ui.cxx1019
1 files changed, 1019 insertions, 0 deletions
diff --git a/forms/source/xforms/model_ui.cxx b/forms/source/xforms/model_ui.cxx
new file mode 100644
index 000000000000..1f7f7a60eb27
--- /dev/null
+++ b/forms/source/xforms/model_ui.cxx
@@ -0,0 +1,1019 @@
+/*************************************************************************
+ *
+ * $RCSfile: model_ui.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: obo $ $Date: 2004-11-16 10:54:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (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.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include "model.hxx"
+#include "model_helper.hxx"
+#include "mip.hxx"
+#include "evaluationcontext.hxx"
+#include "unohelper.hxx"
+#include "submission/serialization_app_xml.hxx"
+#include "resourcehelper.hxx"
+#include "xmlhelper.hxx"
+#ifndef _CONVERT_HXX
+#include "convert.hxx"
+#endif
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/debug.hxx>
+
+// UNO classes
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
+#include <com/sun/star/xml/dom/XDocumentFragment.hpp>
+#include <com/sun/star/xml/dom/XNamedNodeMap.hpp>
+#include <com/sun/star/xml/xpath/XXPathObject.hpp>
+#include <com/sun/star/xml/xpath/XPathObjectType.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XTextInputStream.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/xforms/XFormsSupplier.hpp>
+
+
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using com::sun::star::beans::PropertyValue;
+using com::sun::star::io::XInputStream;
+using com::sun::star::io::XActiveDataSink;
+using com::sun::star::io::XTextInputStream;
+using com::sun::star::container::XEnumeration;
+using com::sun::star::container::XNameContainer;
+using com::sun::star::xforms::XFormsSupplier;
+
+using namespace xforms;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::xml::dom;
+using namespace com::sun::star::xml::xpath;
+
+
+
+//
+// implement XFormsUIHelper1
+//
+
+OUString Model::getDefaultServiceNameForNode( const XNode_t& xNode )
+ throw( RuntimeException )
+{
+ // determine default data type; string is default
+ OUString sService = OUSTRING("com.sun.star.form.component.TextField");
+
+ // TODO: more data types; use repository to find base type
+ OUString sXMLType = queryMIP( xNode ).getTypeName();
+ if( sXMLType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("xsd:double") ) )
+ sService = OUSTRING("com.sun.star.form.component.NumericField");
+ else if( sXMLType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("xsd:boolean")))
+ sService = OUSTRING("com.sun.star.form.component.CheckBox");
+
+ return sService;
+}
+
+
+void lcl_OutPosition( OUStringBuffer& rBuffer,
+ const Reference<XNode>& xNode )
+{
+ OSL_ENSURE( xNode->getParentNode().is(), "need parent" );
+
+ // count # of occurences of this node
+ sal_Int32 nFound = 0;
+ sal_Int32 nPosition = -1;
+ if( xNode->getParentNode().is() )
+ {
+ for( Reference<XNode> xIter = xNode->getParentNode()->getFirstChild();
+ xIter != NULL;
+ xIter = xIter->getNextSibling() )
+ {
+ if( xIter->getNodeType() == xNode->getNodeType() &&
+ xIter->getNodeName() == xNode->getNodeName() &&
+ xIter->getNamespaceURI() == xNode->getNamespaceURI() )
+ {
+ nFound++;
+ if( xIter == xNode )
+ nPosition = nFound;
+ }
+ }
+ }
+ OSL_ENSURE( nFound > 0 && nPosition > 0, "node not found???" );
+
+ // output position (if necessary)
+ if( nFound > 1 )
+ {
+ rBuffer.insert( 0, sal_Unicode(']') );
+ rBuffer.insert( 0, nPosition );
+ rBuffer.insert( 0, sal_Unicode('[') );
+ }
+}
+
+void lcl_OutName( OUStringBuffer& rBuffer,
+ const Reference<XNode>& xNode )
+{
+ rBuffer.insert( 0, xNode->getNodeName() );
+ OUString sPrefix = xNode->getPrefix();
+ if( sPrefix.getLength() > 0 )
+ {
+ rBuffer.insert( 0, sal_Unicode(':') );
+ rBuffer.insert( 0, sPrefix );
+ }
+}
+
+void lcl_OutInstance( OUStringBuffer& rBuffer,
+ const Reference<XNode>& xNode,
+ Model* pModel )
+{
+ Reference<XDocument> xDoc = xNode->getOwnerDocument();
+
+ if( xDoc != pModel->getDefaultInstance() )
+ {
+ rBuffer.insert( 0, OUSTRING("')") );
+
+ // iterate over instances, and find the right one
+ OUString sInstanceName;
+ Reference<XEnumeration> xEnum =
+ pModel->getInstances()->createEnumeration();
+ while( ( sInstanceName.getLength() == 0 ) && xEnum->hasMoreElements() )
+ {
+ Sequence<PropertyValue> aValues;
+ xEnum->nextElement() >>= aValues;
+
+ // get ID and instance
+ OUString sId;
+ Reference<XDocument> xInstance;
+ getInstanceData( aValues, &sId, &xInstance, NULL, NULL );
+
+ // now check whether this was our instance:
+ if( xInstance == xDoc )
+ sInstanceName = sId;
+ }
+
+ rBuffer.insert( 0, sInstanceName );
+ rBuffer.insert( 0, OUSTRING("instance('") );
+ }
+}
+
+OUString Model::getDefaultBindingExpressionForNode(
+ const XNode_t& xNode,
+ const EvaluationContext& rContext)
+{
+ OSL_ENSURE( xNode.is(), "need node" );
+
+ // iterate upwards and put sections into the expression buffer.
+ // Stop iteration either at context node (relative expression) or
+ // at document root, whichever occurs first.
+ OUStringBuffer aBuffer;
+ for( Reference<XNode> xCurrent = xNode;
+ xCurrent.is() && xCurrent != rContext.mxContextNode;
+ xCurrent = xCurrent->getParentNode() )
+ {
+ // insert a '/' for every step except the first
+ if( aBuffer.getLength() > 0 )
+ aBuffer.insert( 0, sal_Unicode('/') );
+
+ switch( xCurrent->getNodeType() )
+ {
+ case NodeType_ELEMENT_NODE:
+ lcl_OutPosition( aBuffer, xCurrent );
+ lcl_OutName( aBuffer, xCurrent );
+ break;
+
+ case NodeType_TEXT_NODE:
+ lcl_OutPosition( aBuffer, xCurrent );
+ aBuffer.insert( 0, OUSTRING("text()") );
+ break;
+
+ case NodeType_ATTRIBUTE_NODE:
+ lcl_OutName( aBuffer, xCurrent );
+ aBuffer.insert( 0, sal_Unicode('@') );
+ break;
+
+ case NodeType_DOCUMENT_NODE:
+ // check for which instance we have
+ lcl_OutInstance( aBuffer, xCurrent, this );
+ break;
+
+ default:
+ // unknown type? fail!
+ OSL_ENSURE( false, "unknown node type!" );
+ xCurrent.set( NULL );
+ aBuffer.makeStringAndClear();
+ // we'll remove the slash below
+ aBuffer.insert( 0, sal_Unicode('/') );
+ break;
+ }
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+
+
+OUString Model::getDefaultBindingExpressionForNode( const XNode_t& xNode )
+ throw( RuntimeException )
+{
+ return getDefaultBindingExpressionForNode( xNode, getEvaluationContext() );
+}
+
+bool lcl_isWhitespace( const OUString& rString )
+{
+ sal_Int32 nLength = rString.getLength();
+ const sal_Unicode* pStr = rString.getStr();
+
+ bool bWhitespace = true;
+ for( sal_Int32 i = 0; bWhitespace && ( i < nLength ); i++ )
+ {
+ sal_Unicode c = pStr[i];
+ bWhitespace = ( c == sal_Unicode(0x09) ||
+ c == sal_Unicode(0x0A) ||
+ c == sal_Unicode(0x0D) ||
+ c == sal_Unicode(0x20) );
+ }
+ return bWhitespace;
+}
+
+OUString Model::getNodeDisplayName( const XNode_t& xNode,
+ sal_Bool bDetail )
+ throw( RuntimeException )
+{
+ OUStringBuffer aBuffer;
+
+ switch( xNode->getNodeType() )
+ {
+ case NodeType_ELEMENT_NODE:
+ lcl_OutName( aBuffer, xNode );
+ break;
+
+ case NodeType_TEXT_NODE:
+ {
+ OUString sContent = xNode->getNodeValue();
+ if( bDetail || ! lcl_isWhitespace( sContent ) )
+ {
+ aBuffer.append( sal_Unicode('"') );
+ aBuffer.append( Convert::collapseWhitespace( sContent ) );
+ aBuffer.append( sal_Unicode('"') );
+ }
+ }
+ break;
+
+ case NodeType_ATTRIBUTE_NODE:
+ lcl_OutName( aBuffer, xNode );
+ aBuffer.insert( 0, sal_Unicode('@') );
+ break;
+
+ case NodeType_DOCUMENT_NODE:
+ if( xNode == getDefaultInstance() )
+ aBuffer.append( sal_Unicode('/') );
+ else
+ lcl_OutInstance( aBuffer, xNode, this );
+ break;
+
+ default:
+ // unknown type? fail!
+ OSL_ENSURE( false, "unknown node type!" );
+ break;
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+OUString Model::getNodeName( const XNode_t& xNode )
+ throw( RuntimeException )
+{
+ OUStringBuffer aBuffer;
+
+ switch( xNode->getNodeType() )
+ {
+ case NodeType_ELEMENT_NODE:
+ case NodeType_ATTRIBUTE_NODE:
+ lcl_OutName( aBuffer, xNode );
+ break;
+
+ case NodeType_TEXT_NODE:
+ case NodeType_DOCUMENT_NODE:
+ default:
+ // unknown type? fail!
+ OSL_ENSURE( false, "no name for this node type!" );
+ break;
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+OUString Model::getBindingName( const XPropertySet_t& xBinding,
+ sal_Bool bDetail )
+ throw( RuntimeException )
+{
+ OUString sID;
+ xBinding->getPropertyValue( OUSTRING("BindingID" ) ) >>= sID;
+ OUString sExpression;
+ xBinding->getPropertyValue( OUSTRING("BindingExpression" ) ) >>= sExpression;
+
+ OUStringBuffer aBuffer;
+ if( sID.getLength() > 0 )
+ {
+ aBuffer.append( sID );
+ aBuffer.append( OUSTRING(" (" ));
+ aBuffer.append( sExpression );
+ aBuffer.append( OUSTRING(")" ));
+ }
+ else
+ aBuffer.append( sExpression );
+
+ return aBuffer.makeStringAndClear();
+}
+
+OUString Model::getSubmissionName( const XPropertySet_t& xSubmission,
+ sal_Bool bDetail )
+ throw( RuntimeException )
+{
+ OUString sID;
+ xSubmission->getPropertyValue( OUSTRING("ID") ) >>= sID;
+ return sID;
+}
+
+Model::XDocument_t Model::newInstance( const rtl::OUString& sName,
+ const rtl::OUString& sURL,
+ sal_Bool bURLOnce )
+ throw( RuntimeException )
+{
+ // create a default instance with <instanceData> element
+ XDocument_t xInstance = getDocumentBuilder()->newDocument();
+ DBG_ASSERT( xInstance.is(), "failed to create DOM instance" );
+
+ Reference<XNode>( xInstance, UNO_QUERY_THROW )->appendChild(
+ Reference<XNode>( xInstance->createElement( OUSTRING("instanceData") ),
+ UNO_QUERY_THROW ) );
+
+ Sequence<PropertyValue> aSequence;
+ bool bOnce = bURLOnce; // bool, so we can take address in setInstanceData
+ setInstanceData( aSequence, &sName, &xInstance, &sURL, &bOnce );
+ sal_Int32 nInstance = mpInstances->addItem( aSequence );
+ loadInstance( nInstance );
+
+ return xInstance;
+}
+
+sal_Int32 lcl_findProp( const PropertyValue* pValues,
+ sal_Int32 nLength,
+ const rtl::OUString& rName )
+{
+ bool bFound = false;
+ sal_Int32 n = 0;
+ for( ; !bFound && n < nLength; n++ )
+ {
+ bFound = ( pValues[n].Name == rName );
+ }
+ return bFound ? ( n - 1) : -1;
+}
+
+sal_Int32 xforms::lcl_findInstance( const InstanceCollection* pInstances,
+ const rtl::OUString& rName )
+{
+ sal_Int32 nLength = pInstances->countItems();
+ sal_Int32 n = 0;
+ bool bFound = false;
+ for( ; !bFound && n < nLength; n++ )
+ {
+ OUString sName;
+ getInstanceData( pInstances->getItem( n ), &sName, NULL, NULL, NULL );
+ bFound = ( sName == rName );
+ }
+ return bFound ? ( n - 1 ) : -1;
+}
+
+void Model::renameInstance( const rtl::OUString& sFrom,
+ const rtl::OUString& sTo )
+ throw( RuntimeException )
+{
+ sal_Int32 nPos = lcl_findInstance( mpInstances, sFrom );
+ if( nPos != -1 )
+ {
+ Sequence<PropertyValue> aSeq = mpInstances->getItem( nPos );
+ PropertyValue* pSeq = aSeq.getArray();
+ sal_Int32 nLength = aSeq.getLength();
+
+ sal_Int32 nProp = lcl_findProp( pSeq, nLength, OUSTRING("ID") );
+ if( nProp == -1 )
+ {
+ // add name property
+ aSeq.realloc( nLength + 1 );
+ pSeq = aSeq.getArray();
+ pSeq[ nLength ].Name = OUSTRING("ID");
+ nProp = nLength;
+ }
+
+ // change name
+ pSeq[ nProp ].Value <<= sTo;
+
+ // set instance
+ mpInstances->setItem( nPos, aSeq );
+ }
+}
+
+void Model::removeInstance( const rtl::OUString& sName )
+ throw( RuntimeException )
+{
+ sal_Int32 nPos = lcl_findInstance( mpInstances, sName );
+ if( nPos != -1 )
+ mpInstances->removeItem( mpInstances->getItem( nPos ) );
+}
+
+Reference<XNameContainer> lcl_getModels(
+ const Reference<com::sun::star::frame::XModel>& xComponent )
+{
+ Reference<XNameContainer> xRet;
+ Reference<XFormsSupplier> xSupplier( xComponent, UNO_QUERY );
+ if( xSupplier.is() )
+ {
+ xRet = xSupplier->getXForms();
+ }
+ return xRet;
+}
+
+Model::XModel_t Model::newModel( const Reference<com::sun::star::frame::XModel>& xCmp,
+ const OUString& sName )
+ throw( RuntimeException )
+{
+ Model* pModel = NULL;
+ Reference<XNameContainer> xModels = lcl_getModels( xCmp );
+ if( xModels.is()
+ && ! xModels->hasByName( sName ) )
+ {
+ pModel = new Model();
+ pModel->setID( sName );
+ pModel->newInstance( OUString(), OUString(), sal_False );
+ xModels->insertByName( sName, makeAny( Reference<XModel>( pModel ) ) );
+ }
+
+ return pModel;
+}
+
+void Model::renameModel( const Reference<com::sun::star::frame::XModel>& xCmp,
+ const OUString& sFrom,
+ const OUString& sTo )
+ throw( RuntimeException )
+{
+ Reference<XNameContainer> xModels = lcl_getModels( xCmp );
+ if( xModels.is()
+ && xModels->hasByName( sFrom )
+ && ! xModels->hasByName( sTo ) )
+ {
+ Reference<XModel> xModel( xModels->getByName( sFrom ), UNO_QUERY );
+ xModel->setID( sTo );
+ xModels->insertByName( sTo, makeAny( xModel ) );
+ xModels->removeByName( sFrom );
+ }
+}
+
+void Model::removeModel( const Reference<com::sun::star::frame::XModel>& xCmp,
+ const OUString& sName )
+ throw( RuntimeException )
+{
+ Reference<XNameContainer> xModels = lcl_getModels( xCmp );
+ if( xModels.is()
+ && xModels->hasByName( sName ) )
+ {
+ xModels->removeByName( sName );
+ }
+}
+
+Model::XNode_t Model::createElement( const XNode_t& xParent,
+ const OUString& sName )
+ throw( RuntimeException )
+{
+ Reference<XNode> xNode;
+ if( xParent.is()
+ && isValidXMLName( sName ) )
+ {
+ // TODO: implement proper namespace handling
+ xNode.set( xParent->getOwnerDocument()->createElement( sName ),
+ UNO_QUERY );
+ }
+ return xNode;
+}
+
+Model::XNode_t Model::createAttribute( const XNode_t& xParent,
+ const OUString& sName )
+ throw( RuntimeException )
+{
+ Reference<XNode> xNode;
+ Reference<XElement> xElement( xParent, UNO_QUERY );
+ if( xParent.is()
+ && xElement.is()
+ && isValidXMLName( sName ) )
+ {
+ // handle case where attribute already exists
+ sal_Int32 nCount = 0;
+ OUString sUniqueName = sName;
+ while( xElement->hasAttribute( sUniqueName ) )
+ {
+ nCount++;
+ sUniqueName = sName + OUString::valueOf( nCount );
+ }
+
+ // TODO: implement proper namespace handling
+ xNode.set( xParent->getOwnerDocument()->createAttribute( sUniqueName ),
+ UNO_QUERY );
+ }
+ return xNode;
+}
+
+Model::XNode_t Model::renameNode( const XNode_t& xNode,
+ const rtl::OUString& sName )
+ throw( RuntimeException )
+{
+ // early out if we don't have to change the name
+ if( xNode->getNodeName() == sName )
+ return xNode;
+
+ // refuse to change name if its an attribute, and the name is already used
+ if( xNode->getNodeType() == NodeType_ATTRIBUTE_NODE
+ && xNode->getParentNode().is()
+ && Reference<XElement>(xNode->getParentNode(), UNO_QUERY_THROW)->hasAttribute( sName ) )
+ return xNode;
+
+ // note old binding expression so we can adjust bindings below
+ OUString sOldDefaultBindingExpression =
+ getDefaultBindingExpressionForNode( xNode );
+
+ Reference<XDocument> xDoc = xNode->getOwnerDocument();
+ Reference<XNode> xNew;
+ if( xNode->getNodeType() == NodeType_ELEMENT_NODE )
+ {
+ Reference<XElement> xElem = xDoc->createElement( sName );
+ xNew.set( xElem, UNO_QUERY );
+
+ // iterate over all attributes and append them to the new element
+ Reference<XElement> xOldElem( xNode, UNO_QUERY );
+ OSL_ENSURE( xNode.is(), "no element?" );
+
+ Reference<XNamedNodeMap> xMap = xNode->getAttributes();
+ sal_Int32 nLength = xMap.is() ? xMap->getLength() : 0;
+ for( sal_Int32 n = 0; n < nLength; n++ )
+ {
+ Reference<XAttr> xAttr( xMap->item(n), UNO_QUERY );
+ xElem->setAttributeNode( xOldElem->removeAttributeNode( xAttr ) );
+ }
+
+ // iterate over all children and append them to the new element
+ for( Reference<XNode> xCurrent = xNode->getFirstChild();
+ xCurrent.is();
+ xCurrent = xNode->getFirstChild() )
+ {
+ xNew->appendChild( xNode->removeChild( xCurrent ) );
+ }
+
+ xNode->getParentNode()->replaceChild( xNew, xNode );
+ }
+ else if( xNode->getNodeType() == NodeType_ATTRIBUTE_NODE )
+ {
+ // create new attribute
+ Reference<XAttr> xAttr = xDoc->createAttribute( sName );
+ xAttr->setValue( xNode->getNodeValue() );
+
+ // replace node
+ Reference<XNode> xParent = xNode->getParentNode();
+ xParent->removeChild( xNode );
+ xNew = xParent->appendChild( Reference<XNode>( xAttr, UNO_QUERY ) );
+ }
+ else
+ {
+ OSL_ENSURE( false, "can't rename this node type" );
+ }
+
+ // adjust bindings (if necessary):
+ if( xNew.is() )
+ {
+ // iterate over bindings and replace default expressions
+ OUString sNewDefaultBindingExpression =
+ getDefaultBindingExpressionForNode( xNew );
+ for( sal_Int32 n = 0; n < mpBindings->countItems(); n++ )
+ {
+ Binding* pBinding = Binding::getBinding(
+ mpBindings->Collection<XPropertySet_t>::getItem( n ) );
+
+ if( pBinding->getBindingExpression()
+ == sOldDefaultBindingExpression )
+ pBinding->setBindingExpression( sNewDefaultBindingExpression );
+ }
+ }
+
+ // return node; return old node if renaming failed
+ return xNew.is() ? xNew : xNode;
+}
+
+Model::XPropertySet_t Model::getBindingForNode( const XNode_t& xNode,
+ sal_Bool bCreate )
+ throw( RuntimeException )
+{
+ OSL_ENSURE( xNode.is(), "no node?" );
+
+ // We will iterate over all bindings and determine the
+ // appropriateness of the respective binding for this node. The
+ // best one will be used. If we don't find any and bCreate is set,
+ // then we will create a suitable binding.
+ Binding* pBestBinding = NULL;
+ sal_Int32 nBestScore = 0;
+
+ for( sal_Int32 n = 0; n < mpBindings->countItems(); n++ )
+ {
+ Binding* pBinding = Binding::getBinding(
+ mpBindings->Collection<XPropertySet_t>::getItem( n ) );
+
+ OSL_ENSURE( pBinding != NULL, "no binding?" );
+ Reference<XNodeList> xNodeList = pBinding->getXNodeList();
+
+ sal_Int32 nNodes = xNodeList.is() ? xNodeList->getLength() : 0;
+ if( nNodes > 0 && xNodeList->item( 0 ) == xNode )
+ {
+ // allright, we found a suitable node. Let's determine how
+ // well it fits. Score:
+ // - bind to exactly this node is better than whole nodeset
+ // - simple binding expressions is better than complex ones
+ sal_Int32 nScore = 0;
+ if( nNodes == 1 )
+ nScore ++;
+ if( pBinding->isSimpleBindingExpression() )
+ nScore ++;
+
+ // if we found a better binding, remember it
+ if( nScore > nBestScore )
+ {
+ pBestBinding = pBinding;
+ nBestScore = nScore;
+ }
+ }
+ }
+
+ // create binding, if none was found and bCreate is set
+ OSL_ENSURE( ( nBestScore == 0 ) == ( pBestBinding == NULL ),
+ "score != binding?" );
+ if( bCreate && pBestBinding == NULL )
+ {
+ pBestBinding = new Binding();
+ pBestBinding->setBindingExpression(
+ getDefaultBindingExpressionForNode( xNode ) );
+ mpBindings->addItem( pBestBinding );
+ }
+
+ return pBestBinding;
+}
+
+void Model::removeBindingForNode( const XNode_t& )
+ throw( RuntimeException )
+{
+ // determine whether suitable binding is still used
+}
+
+OUString lcl_serializeForDisplay( const Reference< XAttr >& _rxAttrNode )
+{
+ ::rtl::OUString sResult;
+ OSL_ENSURE( _rxAttrNode.is(), "lcl_serializeForDisplay( attr ): invalid argument!" );
+ if ( _rxAttrNode.is() )
+ {
+ ::rtl::OUStringBuffer aBuffer;
+ aBuffer.append( _rxAttrNode->getName() );
+ aBuffer.appendAscii( "=" );
+ ::rtl::OUString sValue = _rxAttrNode->getValue();
+ sal_Unicode nQuote = '"';
+ if ( sValue.indexOf( nQuote ) >= 0 )
+ nQuote = '\'';
+ aBuffer.append( nQuote );
+ aBuffer.append( sValue );
+ aBuffer.append( nQuote );
+ aBuffer.append( (sal_Unicode)' ' );
+ sResult = aBuffer.makeStringAndClear();
+ }
+ return sResult;
+}
+
+OUString lcl_serializeForDisplay( const Reference<XNodeList>& xNodes )
+{
+ ::rtl::OUString sResult;
+
+ // create document fragment
+ Reference<XDocument> xDocument( getDocumentBuilder()->newDocument() );
+ Reference<XDocumentFragment> xFragment(
+ xDocument->createDocumentFragment() );
+ Reference<XNode> xNode( xFragment, UNO_QUERY );
+ OSL_ENSURE( xFragment.is(), "xFragment" );
+ OSL_ENSURE( xNode.is(), "xNode" );
+
+ sal_Int32 nAttributeNodes = 0;
+
+ // attach nodelist to fragment
+ sal_Int32 nLength = xNodes->getLength();
+ for( sal_Int32 i = 0; i < nLength; i++ )
+ {
+ Reference<XNode> xCurrent = xNodes->item( i );
+
+ switch ( xCurrent->getNodeType() )
+ {
+ case NodeType_DOCUMENT_NODE:
+ // special-case documents: use top-level element instead
+ xCurrent = xCurrent->getFirstChild();
+ break;
+ case NodeType_ATTRIBUTE_NODE:
+ {
+ Reference< XAttr > xAttr( xCurrent, UNO_QUERY );
+ if ( xAttr.is() )
+ {
+ sResult += lcl_serializeForDisplay( xAttr );
+ ++nAttributeNodes;
+ }
+ continue;
+ }
+ break;
+ }
+
+ // append node
+ xNode->appendChild( xDocument->importNode( xCurrent, sal_True ) );
+ }
+ OSL_ENSURE( ( nAttributeNodes == 0 ) || ( nAttributeNodes == nLength ),
+ "lcl_serializeForDisplay: mixed attribute and non-attribute nodes?" );
+ if ( nAttributeNodes )
+ // had only attribute nodes
+ return sResult;
+
+ // serialize fragment
+ CSerializationAppXML aSerialization;
+ aSerialization.setSource( xFragment );
+ aSerialization.serialize();
+
+ // copy stream into buffer
+ Reference<XTextInputStream> xTextInputStream(
+ createInstance( OUSTRING("com.sun.star.io.TextInputStream") ),
+ UNO_QUERY );
+ Reference<XActiveDataSink>( xTextInputStream, UNO_QUERY_THROW )
+ ->setInputStream( aSerialization.getInputStream() );
+
+ /* WORK AROUND for problem in serialization: currently, multiple
+ XML delarations (<?xml...?>) are being written out and we don't
+ want them. When this is fixed, the code below is nice and
+ simple. The current code filters out the declarations.
+ OUString sResult = xTextInputStream->readString( Sequence<sal_Unicode>(),
+ sal_True );
+ */
+
+ // well, the serialization prepends XML header(s) that we need to
+ // remove first.
+ OUStringBuffer aBuffer;
+ while( ! xTextInputStream->isEOF() )
+ {
+ OUString sLine = xTextInputStream->readLine();
+ if( sLine.getLength() > 0
+ && sLine.compareToAscii( "<?xml", 5 ) != 0 )
+ {
+ aBuffer.append( sLine );
+ aBuffer.append( sal_Unicode('\n') );
+ }
+ }
+ sResult = aBuffer.makeStringAndClear();
+
+ return sResult;
+}
+
+OUString lcl_serializeForDisplay( const Reference<XXPathObject>& xResult )
+{
+ // error handling first
+ if( ! xResult.is() )
+ return getResource( RID_STR_XFORMS_CANT_EVALUATE );
+
+
+ // TODO: localize
+ OUStringBuffer aBuffer;
+
+ switch( xResult->getObjectType() )
+ {
+ case XPathObjectType_XPATH_BOOLEAN:
+ aBuffer.append( xResult->getBoolean()
+ ? OUSTRING("true")
+ : OUSTRING("false") );
+ break;
+
+ case XPathObjectType_XPATH_STRING:
+ aBuffer.append( sal_Unicode('"') );
+ aBuffer.append( xResult->getString() );
+ aBuffer.append( sal_Unicode('"') );
+ break;
+
+ case XPathObjectType_XPATH_NODESET:
+ aBuffer.append( lcl_serializeForDisplay( xResult->getNodeList() ) );
+ break;
+
+ case XPathObjectType_XPATH_NUMBER:
+ aBuffer.append( xResult->getDouble() );
+ break;
+
+ case XPathObjectType_XPATH_UNDEFINED:
+ case XPathObjectType_XPATH_POINT:
+ case XPathObjectType_XPATH_RANGE:
+ case XPathObjectType_XPATH_LOCATIONSET:
+ case XPathObjectType_XPATH_USERS:
+ case XPathObjectType_XPATH_XSLT_TREE:
+ default:
+ // TODO: localized error message?
+ break;
+ }
+
+ return aBuffer.makeStringAndClear();
+}
+
+OUString Model::getResultForExpression(
+ const XPropertySet_t& xBinding,
+ sal_Bool bIsBindingExpression,
+ const OUString& sExpression )
+ throw( RuntimeException )
+{
+ Binding* pBinding = Binding::getBinding( xBinding );
+ if( pBinding == NULL )
+ throw RuntimeException();
+
+ // prepare & evaluate expression
+ OUStringBuffer aBuffer;
+ ComputedExpression aExpression;
+ aExpression.setExpression( sExpression );
+ aExpression.setNamespaces( pBinding->getBindingNamespaces() );
+ if( bIsBindingExpression )
+ {
+ // binding: use binding context and evaluation
+ aExpression.evaluate( pBinding->getEvaluationContext() );
+ aBuffer.append( lcl_serializeForDisplay( aExpression.getXPath() ) );
+ }
+ else
+ {
+ // MIP (not binding): iterate over bindings contexts
+ std::vector<EvaluationContext> aContext =
+ pBinding->getMIPEvaluationContexts();
+ for( std::vector<EvaluationContext>::iterator aIter = aContext.begin();
+ aIter != aContext.end();
+ aIter ++ )
+ {
+ aExpression.evaluate( *aIter );
+ aBuffer.append( lcl_serializeForDisplay(aExpression.getXPath()) );
+ aBuffer.append( sal_Unicode('\n') );
+ }
+ }
+ return aBuffer.makeStringAndClear();
+}
+
+sal_Bool Model::isValidXMLName( const OUString& sName )
+ throw( RuntimeException )
+{
+ return isValidQName( sName, NULL );
+}
+
+sal_Bool Model::isValidPrefixName( const OUString& sName )
+ throw( RuntimeException )
+{
+ return ::isValidPrefixName( sName, NULL );
+}
+
+void Model::setNodeValue(
+ const XNode_t& xNode,
+ const rtl::OUString& sValue )
+ throw( RuntimeException )
+{
+ setSimpleContent( xNode, sValue );
+}
+
+
+//
+// helper functions from model_helper.hxx
+//
+
+void xforms::getInstanceData(
+ const Sequence<PropertyValue>& aValues,
+ OUString* pID,
+ Reference<XDocument>* pInstance,
+ OUString* pURL,
+ bool* pURLOnce )
+{
+ sal_Int32 nValues = aValues.getLength();
+ const PropertyValue* pValues = aValues.getConstArray();
+ for( sal_Int32 n = 0; n < nValues; n++ )
+ {
+ const PropertyValue& rValue = pValues[n];
+#define PROP(NAME) \
+ if( p##NAME != NULL && \
+ rValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(#NAME)) ) \
+ rValue.Value >>= (*p##NAME)
+ PROP(ID);
+ PROP(Instance);
+ PROP(URL);
+ PROP(URLOnce);
+#undef PROP
+ }
+}
+
+void xforms::setInstanceData(
+ Sequence<PropertyValue>& aSequence,
+ const OUString* _pID,
+ const Reference<XDocument>* _pInstance,
+ const OUString* _pURL,
+ const bool* _pURLOnce )
+{
+ // get old instance data
+ OUString sID;
+ Reference<XDocument> xInstance;
+ OUString sURL;
+ bool bURLOnce = false;
+ getInstanceData( aSequence, &sID, &xInstance, &sURL, &bURLOnce );
+ const OUString* pID = ( sID.getLength() > 0 ) ? &sID : NULL;
+ const Reference<XDocument>* pInstance = xInstance.is() ? &xInstance : NULL;
+ const OUString* pURL = ( sURL.getLength() > 0 ) ? &sURL : NULL;
+ const bool* pURLOnce = ( bURLOnce && pURL != NULL ) ? &bURLOnce : NULL;
+
+ // determine new instance data
+#define PROP(NAME) if( _p##NAME != NULL ) p##NAME = _p##NAME
+ PROP(ID);
+ PROP(Instance);
+ PROP(URL);
+ PROP(URLOnce);
+#undef PROP
+
+ // count # of values we want to set
+ sal_Int32 nCount = 0;
+#define PROP(NAME) if( p##NAME != NULL ) nCount++
+ PROP(ID);
+ PROP(Instance);
+ PROP(URL);
+ PROP(URLOnce);
+#undef PROP
+
+ // realloc sequence and enter values;
+ aSequence.realloc( nCount );
+ PropertyValue* pSequence = aSequence.getArray();
+ sal_Int32 nIndex = 0;
+#define PROP(NAME) \
+ if( p##NAME != NULL ) \
+ { \
+ pSequence[ nIndex ].Name = OUSTRING(#NAME); \
+ pSequence[ nIndex ].Value <<= *p##NAME; \
+ nIndex++; \
+ }
+ PROP(ID);
+ PROP(Instance);
+ PROP(URL);
+ PROP(URLOnce);
+#undef PROP
+}