summaryrefslogtreecommitdiff
path: root/forms/source/xforms
diff options
context:
space:
mode:
Diffstat (limited to 'forms/source/xforms')
-rw-r--r--forms/source/xforms/NameContainer.hxx224
-rw-r--r--forms/source/xforms/binding.cxx1412
-rw-r--r--forms/source/xforms/binding.hxx530
-rw-r--r--forms/source/xforms/boolexpression.cxx61
-rw-r--r--forms/source/xforms/boolexpression.hxx58
-rw-r--r--forms/source/xforms/collection.hxx340
-rw-r--r--forms/source/xforms/computedexpression.cxx249
-rw-r--r--forms/source/xforms/computedexpression.hxx141
-rw-r--r--forms/source/xforms/convert.cxx630
-rw-r--r--forms/source/xforms/convert.hxx116
-rw-r--r--forms/source/xforms/datatyperepository.cxx294
-rw-r--r--forms/source/xforms/datatyperepository.hxx100
-rw-r--r--forms/source/xforms/datatypes.cxx993
-rw-r--r--forms/source/xforms/datatypes.hxx426
-rw-r--r--forms/source/xforms/datatypes_impl.hxx78
-rw-r--r--forms/source/xforms/enumeration.cxx77
-rw-r--r--forms/source/xforms/enumeration.hxx66
-rw-r--r--forms/source/xforms/evaluationcontext.hxx78
-rw-r--r--forms/source/xforms/makefile.mk66
-rw-r--r--forms/source/xforms/mip.cxx129
-rw-r--r--forms/source/xforms/mip.hxx125
-rw-r--r--forms/source/xforms/model.cxx810
-rw-r--r--forms/source/xforms/model.hxx438
-rw-r--r--forms/source/xforms/model_helper.hxx170
-rw-r--r--forms/source/xforms/model_ui.cxx1069
-rw-r--r--forms/source/xforms/namedcollection.hxx145
-rw-r--r--forms/source/xforms/pathexpression.cxx157
-rw-r--r--forms/source/xforms/pathexpression.hxx94
-rw-r--r--forms/source/xforms/propertysetbase.cxx195
-rw-r--r--forms/source/xforms/propertysetbase.hxx374
-rw-r--r--forms/source/xforms/resourcehelper.cxx82
-rw-r--r--forms/source/xforms/resourcehelper.hxx55
-rw-r--r--forms/source/xforms/submission.cxx721
-rw-r--r--forms/source/xforms/submission.hxx279
-rw-r--r--forms/source/xforms/submission/makefile.mk57
-rw-r--r--forms/source/xforms/submission/replace.cxx145
-rw-r--r--forms/source/xforms/submission/serialization.hxx101
-rw-r--r--forms/source/xforms/submission/serialization_app_xml.cxx124
-rw-r--r--forms/source/xforms/submission/serialization_app_xml.hxx58
-rw-r--r--forms/source/xforms/submission/serialization_urlencoded.cxx212
-rw-r--r--forms/source/xforms/submission/serialization_urlencoded.hxx59
-rw-r--r--forms/source/xforms/submission/submission.hxx163
-rw-r--r--forms/source/xforms/submission/submission_get.cxx119
-rw-r--r--forms/source/xforms/submission/submission_get.hxx47
-rw-r--r--forms/source/xforms/submission/submission_post.cxx104
-rw-r--r--forms/source/xforms/submission/submission_post.hxx43
-rw-r--r--forms/source/xforms/submission/submission_put.cxx83
-rw-r--r--forms/source/xforms/submission/submission_put.hxx46
-rw-r--r--forms/source/xforms/unohelper.cxx106
-rw-r--r--forms/source/xforms/unohelper.hxx60
-rw-r--r--forms/source/xforms/warnings_guard_unicode_regex.h51
-rw-r--r--forms/source/xforms/xforms_services.cxx75
-rw-r--r--forms/source/xforms/xforms_services.hxx30
-rw-r--r--forms/source/xforms/xformsevent.cxx103
-rw-r--r--forms/source/xforms/xformsevent.hxx69
-rw-r--r--forms/source/xforms/xmlhelper.cxx150
-rw-r--r--forms/source/xforms/xmlhelper.hxx54
-rw-r--r--forms/source/xforms/xpathlib/extension.cxx104
-rw-r--r--forms/source/xforms/xpathlib/extension.hxx42
-rw-r--r--forms/source/xforms/xpathlib/makefile.mk56
-rw-r--r--forms/source/xforms/xpathlib/xpathlib.cxx570
-rw-r--r--forms/source/xforms/xpathlib/xpathlib.hxx59
62 files changed, 13672 insertions, 0 deletions
diff --git a/forms/source/xforms/NameContainer.hxx b/forms/source/xforms/NameContainer.hxx
new file mode 100644
index 000000000000..b4481a5434d8
--- /dev/null
+++ b/forms/source/xforms/NameContainer.hxx
@@ -0,0 +1,224 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _NAMECONTAINER_HXX
+#define _NAMECONTAINER_HXX
+
+#include <cppuhelper/implbase1.hxx>
+#include <map>
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/WrappedTargetException.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Type.hxx>
+
+typedef cppu::WeakImplHelper1<
+ com::sun::star::container::XNameContainer
+> NameContainer_t;
+
+template<class T>
+class NameContainer : public NameContainer_t
+{
+protected:
+ typedef std::map<rtl::OUString,T> map_t;
+ map_t maItems;
+
+
+ bool hasItems()
+ {
+ return ! maItems.empty();
+ }
+
+ typename map_t::const_iterator findItem( const rtl::OUString& rName )
+ {
+ return maItems.find( rName );
+ }
+
+ bool hasItem( const rtl::OUString& rName )
+ {
+ return findItem( rName ) != maItems.end();
+ }
+
+ T getItem( const rtl::OUString& rName )
+ {
+ OSL_ENSURE( hasItem( rName ), "can't get non-existant item" );
+ return maItems[ rName ];
+ }
+
+
+ void replace( const rtl::OUString& rName,
+ const T& aElement )
+ {
+ OSL_ENSURE( hasItem( rName ), "unknown item" );
+ maItems[ rName ] = aElement;
+ }
+
+ void insert( const rtl::OUString& rName,
+ const T& aElement )
+ {
+ OSL_ENSURE( ! hasItem( rName ), "item already in set" );
+ maItems[ rName ] = aElement;
+ }
+
+ void remove( const rtl::OUString& rName )
+ {
+ OSL_ENSURE( hasItem( rName ), "item not in set" );
+ maItems.erase( rName );
+ }
+
+
+public:
+
+ NameContainer() {}
+ virtual ~NameContainer() {}
+
+ //
+ // methods for XElementAccess
+ //
+
+ virtual com::sun::star::uno::Type SAL_CALL getElementType()
+ throw( com::sun::star::uno::RuntimeException )
+ {
+ return getCppuType( static_cast<T*>( NULL ) );
+ }
+
+ virtual sal_Bool SAL_CALL hasElements()
+ throw( com::sun::star::uno::RuntimeException )
+ {
+ return hasItems();
+ }
+
+
+ //
+ // methods for XNameAccess (inherits XElementAccess)
+ //
+
+ virtual com::sun::star::uno::Any SAL_CALL getByName(
+ const rtl::OUString& rName )
+ throw( com::sun::star::container::NoSuchElementException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException )
+ {
+ typename map_t::const_iterator aIter = findItem( rName );
+ if( aIter == maItems.end() )
+ throw com::sun::star::container::NoSuchElementException();
+ else
+ return com::sun::star::uno::makeAny( aIter->second );
+ }
+
+ virtual com::sun::star::uno::Sequence<rtl::OUString> SAL_CALL getElementNames()
+ throw( com::sun::star::uno::RuntimeException )
+ {
+ com::sun::star::uno::Sequence<rtl::OUString> aSequence( maItems.size() );
+ typename map_t::const_iterator aIter = maItems.begin();
+ rtl::OUString* pStrings = aSequence.getArray();
+ while( aIter != maItems.end() )
+ {
+ *pStrings = aIter->first;
+ ++aIter;
+ ++pStrings;
+ }
+ OSL_ENSURE( pStrings == aSequence.getArray() + aSequence.getLength(),
+ "sequence not of right size; possible buffer overflow" );
+ return aSequence;
+ }
+
+ virtual sal_Bool SAL_CALL hasByName(
+ const rtl::OUString& rName )
+ throw( com::sun::star::uno::RuntimeException )
+ {
+ return hasItem( rName );
+ }
+
+
+ //
+ // methods for XNameReplace (inherits XNameAccess)
+ //
+
+ virtual void SAL_CALL replaceByName(
+ const rtl::OUString& rName,
+ const com::sun::star::uno::Any& aElement )
+ throw( com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::container::NoSuchElementException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException)
+ {
+ T aItem;
+ if( aElement >>= aItem )
+ if( hasByName( rName ) )
+ replace( rName, aItem );
+ else
+ throw com::sun::star::container::NoSuchElementException();
+ else
+ throw com::sun::star::lang::IllegalArgumentException();
+ }
+
+
+ //
+ // methods for XNameContainer (inherits XNameReplace)
+ //
+
+ virtual void SAL_CALL insertByName(
+ const rtl::OUString& rName,
+ const com::sun::star::uno::Any& aElement )
+ throw( com::sun::star::lang::IllegalArgumentException,
+ com::sun::star::container::ElementExistException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException )
+ {
+ T aItem;
+ if( aElement >>= aItem )
+ if( ! hasByName( rName ) )
+ insert( rName, aItem );
+ else
+ throw com::sun::star::container::ElementExistException();
+ else
+ throw com::sun::star::lang::IllegalArgumentException();
+ }
+
+ virtual void SAL_CALL removeByName(
+ const rtl::OUString& rName )
+ throw( com::sun::star::container::NoSuchElementException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException)
+ {
+ if( hasByName( rName ) )
+ remove( rName );
+ else
+ throw com::sun::star::container::NoSuchElementException();
+ }
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/binding.cxx b/forms/source/xforms/binding.cxx
new file mode 100644
index 000000000000..7389eabb4409
--- /dev/null
+++ b/forms/source/xforms/binding.cxx
@@ -0,0 +1,1412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "binding.hxx"
+
+#include "model.hxx"
+#include "unohelper.hxx"
+#include "NameContainer.hxx"
+#include "evaluationcontext.hxx"
+#include "convert.hxx"
+#include "resourcehelper.hxx"
+#include "xmlhelper.hxx"
+#include "xformsevent.hxx"
+
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+
+#include <tools/diagnose_ex.h>
+
+#include <algorithm>
+#include <functional>
+
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/xml/dom/XNodeList.hpp>
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/dom/XElement.hpp>
+#include <com/sun/star/xml/dom/NodeType.hpp>
+#include <com/sun/star/xml/dom/events/XEventTarget.hpp>
+#include <com/sun/star/xml/dom/events/XEventListener.hpp>
+#include <com/sun/star/xml/dom/events/XDocumentEvent.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/container/XSet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+
+#include <comphelper/propertysetinfo.hxx>
+#include <unotools/textsearch.hxx>
+#include <cppuhelper/typeprovider.hxx>
+
+using namespace com::sun::star::xml::xpath;
+using namespace com::sun::star::xml::dom::events;
+
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using std::vector;
+using xforms::Binding;
+using xforms::MIP;
+using xforms::Model;
+using xforms::getResource;
+using xforms::EvaluationContext;
+using com::sun::star::beans::PropertyVetoException;
+using com::sun::star::beans::UnknownPropertyException;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::container::XSet;
+using com::sun::star::container::XNameAccess;
+using com::sun::star::form::binding::IncompatibleTypesException;
+using com::sun::star::form::binding::InvalidBindingStateException;
+using com::sun::star::form::binding::XValueBinding;
+using com::sun::star::lang::EventObject;
+using com::sun::star::lang::IllegalArgumentException;
+using com::sun::star::lang::IndexOutOfBoundsException;
+using com::sun::star::lang::NoSupportException;
+using com::sun::star::lang::NullPointerException;
+using com::sun::star::lang::WrappedTargetException;
+using com::sun::star::lang::XUnoTunnel;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::UNO_QUERY_THROW;
+using com::sun::star::uno::XInterface;
+using com::sun::star::uno::Exception;
+using com::sun::star::uno::makeAny;
+using com::sun::star::util::XModifyListener;
+using com::sun::star::xforms::XDataTypeRepository;
+using com::sun::star::xml::dom::NodeType_ATTRIBUTE_NODE;
+using com::sun::star::xml::dom::NodeType_TEXT_NODE;
+using com::sun::star::xml::dom::XNode;
+using com::sun::star::xml::dom::XNodeList;
+using com::sun::star::xml::dom::events::XEventListener;
+using com::sun::star::xml::dom::events::XEventTarget;
+using com::sun::star::xsd::XDataType;
+
+
+
+
+#define EXCEPT(msg) OUSTRING(msg),static_cast<XValueBinding*>(this)
+
+#define HANDLE_BindingID 0
+#define HANDLE_BindingExpression 1
+#define HANDLE_Model 2
+#define HANDLE_ModelID 3
+#define HANDLE_BindingNamespaces 4
+#define HANDLE_ReadonlyExpression 5
+#define HANDLE_RelevantExpression 6
+#define HANDLE_RequiredExpression 7
+#define HANDLE_ConstraintExpression 8
+#define HANDLE_CalculateExpression 9
+#define HANDLE_Type 10
+#define HANDLE_ReadOnly 11 // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control
+#define HANDLE_Relevant 12 // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control
+#define HANDLE_ModelNamespaces 13
+#define HANDLE_ExternalData 14
+
+
+Binding::Binding() :
+ mxModel(),
+ msBindingID(),
+ maBindingExpression(),
+ maReadonly(),
+ mxNamespaces( new NameContainer<OUString>() ),
+ mbInCalculate( false ),
+ mnDeferModifyNotifications( 0 ),
+ mbValueModified( false ),
+ mbBindingModified( false )
+
+{
+ initializePropertySet();
+}
+
+Binding::~Binding() throw()
+{
+ _setModel(NULL);
+}
+
+
+Binding::Model_t Binding::getModel() const
+{
+ return mxModel;
+}
+
+void Binding::_setModel( const Model_t& xModel )
+{
+ PropertyChangeNotifier aNotifyModelChange( *this, HANDLE_Model );
+ PropertyChangeNotifier aNotifyModelIDChange( *this, HANDLE_ModelID );
+
+ // prepare binding for removal of old model
+ clear(); // remove all cached data (e.g. XPath evaluation results)
+ XNameContainer_t xNamespaces = getModelNamespaces(); // save namespaces
+
+ mxModel = xModel;
+
+ // set namespaces (and move to model, if appropriate)
+ setBindingNamespaces( xNamespaces );
+ _checkBindingID();
+
+ notifyAndCachePropertyValue( HANDLE_ExternalData );
+}
+
+
+OUString Binding::getModelID() const
+{
+ Model* pModel = getModelImpl();
+ return ( pModel == NULL ) ? OUString() : pModel->getID();
+}
+
+
+Binding::XNodeList_t Binding::getXNodeList()
+{
+ // first make sure we are bound
+ if( ! maBindingExpression.hasValue() )
+ bind( sal_False );
+
+ return maBindingExpression.getXNodeList();
+}
+
+bool Binding::isSimpleBinding() const
+{
+ return maBindingExpression.isSimpleExpression()
+ && maReadonly.isSimpleExpression()
+ && maRelevant.isSimpleExpression()
+ && maRequired.isSimpleExpression()
+ && maConstraint.isSimpleExpression()
+ && maCalculate.isSimpleExpression();
+}
+
+bool Binding::isSimpleBindingExpression() const
+{
+ return maBindingExpression.isSimpleExpression();
+}
+
+void Binding::update()
+{
+ // clear all expressions (to remove cached node references)
+ maBindingExpression.clear();
+ maReadonly.clear();
+ maRelevant.clear();
+ maRequired.clear();
+ maConstraint.clear();
+ maCalculate.clear();
+
+ // let's just pretend the binding has been modified -> full rebind()
+ bindingModified();
+}
+
+void Binding::deferNotifications( bool bDefer )
+{
+ mnDeferModifyNotifications += ( bDefer ? 1 : -1 );
+ OSL_ENSURE( mnDeferModifyNotifications >= 0, "you're deferring too much" );
+
+ if( mnDeferModifyNotifications == 0 )
+ {
+ if( mbBindingModified )
+ bindingModified();
+ if( mbValueModified )
+ valueModified();
+ }
+
+ OSL_ENSURE( ( mnDeferModifyNotifications > 0 )
+ || ( ! mbBindingModified && ! mbValueModified ),
+ "deferred modifications not delivered?" );
+}
+
+bool Binding::isValid()
+{
+ // TODO: determine whether node is suitable, not just whether it exists
+ return maBindingExpression.getNode().is() &&
+ isValid_DataType() &&
+ maMIP.isConstraint() &&
+ ( ! maMIP.isRequired() ||
+ ( maBindingExpression.hasValue() &&
+ maBindingExpression.getString().getLength() > 0 ) );
+}
+
+bool Binding::isUseful()
+{
+ // we are useful, if
+ // 0) we don't have a model
+ // (at least, in this case we shouldn't be removed from the model)
+ // 1) we have a proper name
+ // 2) we have some MIPs,
+ // 3) we are bound to some control
+ // (this can be assumed if some listeners are set)
+ bool bUseful =
+ getModelImpl() == NULL
+// || msBindingID.getLength() > 0
+ || msTypeName.getLength() > 0
+ || ! maReadonly.isEmptyExpression()
+ || ! maRelevant.isEmptyExpression()
+ || ! maRequired.isEmptyExpression()
+ || ! maConstraint.isEmptyExpression()
+ || ! maCalculate.isEmptyExpression()
+ || ! maModifyListeners.empty()
+ || ! maListEntryListeners.empty()
+ || ! maValidityListeners.empty();
+
+ return bUseful;
+}
+
+OUString Binding::explainInvalid()
+{
+ OUString sReason;
+ if( ! maBindingExpression.getNode().is() )
+ {
+ sReason = ( maBindingExpression.getExpression().getLength() == 0 )
+ ? getResource( RID_STR_XFORMS_NO_BINDING_EXPRESSION )
+ : getResource( RID_STR_XFORMS_INVALID_BINDING_EXPRESSION );
+ }
+ else if( ! isValid_DataType() )
+ {
+ sReason = explainInvalid_DataType();
+ if( sReason.getLength() == 0 )
+ {
+ // no explanation given by data type? Then give generic message
+ sReason = getResource( RID_STR_XFORMS_INVALID_VALUE,
+ maMIP.getTypeName() );
+ }
+ }
+ else if( ! maMIP.isConstraint() )
+ {
+ sReason = maMIP.getConstraintExplanation();
+ }
+ else if( maMIP.isRequired() && maBindingExpression.hasValue() &&
+ ( maBindingExpression.getString().getLength() == 0 ) )
+ {
+ sReason = getResource( RID_STR_XFORMS_REQUIRED );
+ }
+ // else: no explanation given; should only happen if data is valid
+
+ OSL_ENSURE( ( sReason.getLength() == 0 ) == isValid(),
+ "invalid data should have an explanation!" );
+
+ return sReason;
+}
+
+
+
+EvaluationContext Binding::getEvaluationContext() const
+{
+ OSL_ENSURE( getModelImpl() != NULL, "need model impl" );
+ EvaluationContext aContext = getModelImpl()->getEvaluationContext();
+ aContext.mxNamespaces = getBindingNamespaces();
+ return aContext;
+}
+
+::std::vector<EvaluationContext> Binding::getMIPEvaluationContexts()
+{
+ OSL_ENSURE( getModelImpl() != NULL, "need model impl" );
+
+ // bind (in case we were not bound before)
+ bind( sal_False );
+ return _getMIPEvaluationContexts();
+}
+
+
+Binding::IntSequence_t Binding::getUnoTunnelID()
+{
+ static cppu::OImplementationId aImplementationId;
+ return aImplementationId.getImplementationId();
+}
+
+Binding* SAL_CALL Binding::getBinding( const Reference<XPropertySet>& xPropertySet )
+{
+ Reference<XUnoTunnel> xTunnel( xPropertySet, UNO_QUERY );
+ return xTunnel.is()
+ ? reinterpret_cast<Binding*>( xTunnel->getSomething(getUnoTunnelID()))
+ : NULL;
+}
+
+
+
+
+OUString Binding::getBindingID() const
+{
+ return msBindingID;
+}
+
+void Binding::setBindingID( const OUString& sBindingID )
+{
+ msBindingID = sBindingID;
+}
+
+OUString Binding::getBindingExpression() const
+{
+ return maBindingExpression.getExpression();
+}
+
+void Binding::setBindingExpression( const OUString& sBindingExpression)
+{
+ maBindingExpression.setExpression( sBindingExpression );
+ bindingModified();
+}
+
+OUString Binding::getReadonlyExpression() const
+{
+ return maReadonly.getExpression();
+}
+
+void Binding::setReadonlyExpression( const OUString& sReadonly)
+{
+ maReadonly.setExpression( sReadonly );
+ bindingModified();
+}
+
+OUString Binding::getRelevantExpression() const
+{
+ return maRelevant.getExpression();
+}
+
+void Binding::setRelevantExpression( const OUString& sRelevant )
+{
+ maRelevant.setExpression( sRelevant );
+ bindingModified();
+}
+
+OUString Binding::getRequiredExpression() const
+{
+ return maRequired.getExpression();
+}
+
+void Binding::setRequiredExpression( const OUString& sRequired )
+{
+ maRequired.setExpression( sRequired );
+ bindingModified();
+}
+
+OUString Binding::getConstraintExpression() const
+{
+ return maConstraint.getExpression();
+}
+
+void Binding::setConstraintExpression( const OUString& sConstraint )
+{
+ maConstraint.setExpression( sConstraint );
+ msExplainConstraint = getResource( RID_STR_XFORMS_INVALID_CONSTRAINT,
+ sConstraint );
+
+ // TODO: This should only re-evaluate the constraint, and notify
+ // the validity constraint listeners; instead we currently pretend
+ // the entire binding was notified, which does a little too much.
+ bindingModified();
+}
+
+OUString Binding::getCalculateExpression() const
+{
+ return maCalculate.getExpression();
+}
+
+void Binding::setCalculateExpression( const OUString& sCalculate )
+{
+ maCalculate.setExpression( sCalculate );
+ bindingModified();
+}
+
+OUString Binding::getType() const
+{
+ return msTypeName;
+}
+
+void Binding::setType( const OUString& sTypeName )
+{
+ msTypeName = sTypeName;
+ bindingModified();
+}
+
+Binding::XNameContainer_t Binding::getBindingNamespaces() const
+{
+ // return _getNamespaces();
+ return mxNamespaces;
+}
+
+void Binding::setBindingNamespaces( const XNameContainer_t& rNamespaces )
+{
+ _setNamespaces( rNamespaces, true );
+}
+
+Binding::XNameContainer_t Binding::getModelNamespaces() const
+{
+ return _getNamespaces();
+}
+
+void Binding::setModelNamespaces( const XNameContainer_t& rNamespaces )
+{
+ _setNamespaces( rNamespaces, false );
+}
+
+bool Binding::getReadOnly() const
+{
+ return maMIP.isReadonly();
+}
+
+bool Binding::getRelevant() const
+{
+ return maMIP.isRelevant();
+}
+
+bool Binding::getExternalData() const
+{
+ bool bExternalData = true;
+ if ( !mxModel.is() )
+ return bExternalData;
+
+ try
+ {
+ Reference< XPropertySet > xModelProps( mxModel, UNO_QUERY_THROW );
+ OSL_VERIFY(
+ xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) ) ) >>= bExternalData );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return bExternalData;
+}
+
+
+void Binding::checkLive()
+ throw( RuntimeException )
+{
+ if( ! isLive() )
+ throw RuntimeException( EXCEPT("Binding not initialized") );
+}
+
+void Binding::checkModel()
+ throw( RuntimeException )
+{
+ if( ! mxModel.is() )
+ throw RuntimeException( EXCEPT("Binding has no Model") );
+}
+
+bool Binding::isLive() const
+{
+ const Model* pModel = getModelImpl();
+ return ( pModel != NULL ) ? pModel->isInitialized() : false;
+}
+
+Model* Binding::getModelImpl() const
+{
+ return getModelImpl( mxModel );
+}
+
+Model* Binding::getModelImpl( const Model_t& xModel ) const
+{
+ Reference<XUnoTunnel> xTunnel( xModel, UNO_QUERY );
+ Model* pModel = xTunnel.is()
+ ? reinterpret_cast<Model*>(
+ xTunnel->getSomething( Model::getUnoTunnelID() ) )
+ : NULL;
+ return pModel;
+}
+
+void lcl_addListenerToNode( Reference<XNode> xNode,
+ Reference<XEventListener> xListener )
+{
+ Reference<XEventTarget> xTarget( xNode, UNO_QUERY );
+ if( xTarget.is() )
+ {
+ xTarget->addEventListener( OUSTRING("DOMCharacterDataModified"),
+ xListener, false );
+ xTarget->addEventListener( OUSTRING("DOMCharacterDataModified"),
+ xListener, true );
+ xTarget->addEventListener( OUSTRING("DOMAttrModified"),
+ xListener, false );
+ xTarget->addEventListener( OUSTRING("DOMAttrModified"),
+ xListener, true );
+ xTarget->addEventListener( OUSTRING("DOMAttrModified"),
+ xListener, true );
+ xTarget->addEventListener( OUSTRING("xforms-generic"),
+ xListener, true );
+ }
+}
+
+void lcl_removeListenerFromNode( Reference<XNode> xNode,
+ Reference<XEventListener> xListener )
+{
+ Reference<XEventTarget> xTarget( xNode, UNO_QUERY );
+ if( xTarget.is() )
+ {
+ xTarget->removeEventListener( OUSTRING("DOMCharacterDataModified"),
+ xListener, false );
+ xTarget->removeEventListener( OUSTRING("DOMCharacterDataModified"),
+ xListener, true );
+ xTarget->removeEventListener( OUSTRING("DOMAttrModified"),
+ xListener, false );
+ xTarget->removeEventListener( OUSTRING("DOMAttrModified"),
+ xListener, true );
+ xTarget->removeEventListener( OUSTRING("xforms-generic"),
+ xListener, true );
+ }
+}
+
+::std::vector<EvaluationContext> Binding::_getMIPEvaluationContexts() const
+{
+ OSL_ENSURE( getModelImpl() != NULL, "need model impl" );
+
+ // iterate over nodes of bind expression and create
+ // EvaluationContext for each
+ PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList();
+ ::std::vector<EvaluationContext> aVector;
+ sal_Int32 nCount = 0; // count nodes for context position
+ for( PathExpression::NodeVector_t::iterator aIter = aNodes.begin();
+ aIter != aNodes.end();
+ ++aIter, ++nCount )
+ {
+ OSL_ENSURE( aIter->is(), "no node?" );
+
+ // create proper evaluation context for this MIP
+ aVector.push_back( EvaluationContext( *aIter, getModel(),
+ getBindingNamespaces(),
+ nCount, aNodes.size() ) );
+ }
+ return aVector;
+}
+
+void Binding::bind( bool bForceRebind )
+{
+ checkModel();
+
+ // bind() will evaluate this binding as follows:
+ // 1) evaluate the binding expression
+ // 1b) if necessary, create node according to 'lazy author' rules
+ // 2) register suitable listeners on the instance (and remove old ones)
+ // 3) remove old MIPs defined by this binding
+ // 4) for every node in the binding nodeset do:
+ // 1) create proper evaluation context for this MIP
+ // 2) evaluate calculate expression (and push value into instance)
+ // 3) evaluate remaining MIPs
+ // 4) evaluate the locally defined MIPs, and push them to the model
+
+
+ // 1) evaluate the binding expression
+ EvaluationContext aContext = getEvaluationContext();
+ maBindingExpression.evaluate( aContext );
+ if( ! maBindingExpression.getNode().is() )
+ {
+ // 1b) create node (if valid element name)
+ if( isValidQName( maBindingExpression.getExpression(),
+ aContext.mxNamespaces ) )
+ {
+ aContext.mxContextNode->appendChild(
+ Reference<XNode>(
+ aContext.mxContextNode->getOwnerDocument()->createElement(
+ maBindingExpression.getExpression() ),
+ UNO_QUERY ) );
+ maBindingExpression.evaluate( aContext );
+ OSL_ENSURE( maBindingExpression.getNode().is(),
+ "we should bind to the newly inserted node!" );
+ }
+ }
+ PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList();
+
+ // 2) register suitable listeners on the instance (and remove old ones)
+ if( maEventNodes.empty() || bForceRebind )
+ {
+ for( XNodes_t::iterator aIter = maEventNodes.begin();
+ aIter != maEventNodes.end();
+ ++aIter )
+ lcl_removeListenerFromNode( *aIter, this );
+ maEventNodes.clear();
+ if( isSimpleBinding() )
+ for( PathExpression::NodeVector_t::iterator aIter = aNodes.begin();
+ aIter != aNodes.end();
+ ++aIter )
+ maEventNodes.push_back( *aIter );
+ else
+ maEventNodes.push_back(
+ Reference<XNode>( aContext.mxContextNode->getOwnerDocument(),
+ UNO_QUERY_THROW ) );
+ for( PathExpression::NodeVector_t::iterator aIter2 = maEventNodes.begin();
+ aIter2 != maEventNodes.end();
+ ++aIter2 )
+ lcl_addListenerToNode( *aIter2, this );
+ }
+
+ // 3) remove old MIPs defined by this binding
+ Model* pModel = getModelImpl();
+ OSL_ENSURE( pModel != NULL, "need model" );
+ pModel->removeMIPs( this );
+
+ // 4) calculate all MIPs
+ ::std::vector<EvaluationContext> aMIPContexts = _getMIPEvaluationContexts();
+ for( ::std::vector<EvaluationContext>::iterator aIter = aMIPContexts.begin();
+ aIter != aMIPContexts.end();
+ aIter++ )
+ {
+ EvaluationContext& rContext = *aIter;
+
+ // evaluate calculate expression (and push value into instance)
+ // (prevent recursion using mbInCalculate
+ if( ! maCalculate.isEmptyExpression() )
+ {
+ if( ! mbInCalculate )
+ {
+ mbInCalculate = true;
+ maCalculate.evaluate( rContext );
+ pModel->setSimpleContent( rContext.mxContextNode,
+ maCalculate.getString() );
+ mbInCalculate = false;
+ }
+ }
+
+ // now evaluate remaining MIPs in the apropriate context
+ maReadonly.evaluate( rContext );
+ maRelevant.evaluate( rContext );
+ maRequired.evaluate( rContext );
+ maConstraint.evaluate( rContext );
+ // type is static; does not need updating
+
+ // evaluate the locally defined MIPs, and push them to the model
+ pModel->addMIP( this, rContext.mxContextNode, getLocalMIP() );
+ }
+}
+
+
+// helper for Binding::valueModified
+void lcl_modified( const Binding::XModifyListener_t xListener,
+ const Reference<XInterface> xSource )
+{
+ OSL_ENSURE( xListener.is(), "no listener?" );
+ xListener->modified( EventObject( xSource ) );
+}
+
+// helper for Binding::valueModified
+void lcl_listentry( const Binding::XListEntryListener_t xListener,
+ const Reference<XInterface> xSource )
+{
+ OSL_ENSURE( xListener.is(), "no listener?" );
+ // TODO: send fine granular events
+ xListener->allEntriesChanged( EventObject( xSource ) );
+}
+
+// helper for Binding::valueModified
+void lcl_validate( const Binding::XValidityConstraintListener_t xListener,
+ const Reference<XInterface> xSource )
+{
+ OSL_ENSURE( xListener.is(), "no listener?" );
+ xListener->validityConstraintChanged( EventObject( xSource ) );
+}
+
+
+void Binding::valueModified()
+{
+ // defer notifications, if so desired
+ if( mnDeferModifyNotifications > 0 )
+ {
+ mbValueModified = true;
+ return;
+ }
+ mbValueModified = false;
+
+ // query MIP used by our first node (also note validity)
+ Reference<XNode> xNode = maBindingExpression.getNode();
+ maMIP = getModelImpl()->queryMIP( xNode );
+
+ // distribute MIPs _used_ by this binding
+ if( xNode.is() )
+ {
+ notifyAndCachePropertyValue( HANDLE_ReadOnly );
+ notifyAndCachePropertyValue( HANDLE_Relevant );
+ }
+
+ // iterate over _value_ listeners and send each a modified signal,
+ // using this object as source (will also update validity, because
+ // control will query once the value has changed)
+ Reference<XInterface> xSource = static_cast<XPropertySet*>( this );
+ ::std::for_each( maModifyListeners.begin(),
+ maModifyListeners.end(),
+ ::std::bind2nd( ::std::ptr_fun( lcl_modified ), xSource ) );
+ ::std::for_each( maListEntryListeners.begin(),
+ maListEntryListeners.end(),
+ ::std::bind2nd( ::std::ptr_fun( lcl_listentry ), xSource ) );
+ ::std::for_each( maValidityListeners.begin(),
+ maValidityListeners.end(),
+ ::std::bind2nd( ::std::ptr_fun( lcl_validate ), xSource ) );
+
+ // now distribute MIPs to childs
+ if( xNode.is() )
+ distributeMIP( xNode->getFirstChild() );
+}
+
+void Binding::distributeMIP( const XNode_t & rxNode ) {
+
+ typedef com::sun::star::xforms::XFormsEventConcrete XFormsEvent_t;
+ OUString sEventName( RTL_CONSTASCII_USTRINGPARAM("xforms-generic") );
+ XFormsEvent_t *pEvent = new XFormsEvent_t;
+ pEvent->initXFormsEvent(sEventName, sal_True, sal_False);
+ Reference<XEvent> xEvent(pEvent);
+
+ // naive depth-first traversal
+ XNode_t xNode( rxNode );
+ while(xNode.is()) {
+
+ // notifications should be triggered at the
+ // leaf nodes first, bubbling upwards the hierarchy.
+ XNode_t child(xNode->getFirstChild());
+ if(child.is())
+ distributeMIP(child);
+
+ // we're standing at a particular node somewhere
+ // below the one which changed a property (MIP).
+ // bindings which are listening at this node will receive
+ // a notification message about what exactly happened.
+ Reference< XEventTarget > target(xNode,UNO_QUERY);
+ target->dispatchEvent(xEvent);
+
+ xNode = xNode->getNextSibling();
+ };
+}
+
+void Binding::bindingModified()
+{
+ // defer notifications, if so desired
+ if( mnDeferModifyNotifications > 0 )
+ {
+ mbBindingModified = true;
+ return;
+ }
+ mbBindingModified = false;
+
+ // rebind (if live); then call valueModified
+ // A binding should be inert until its model is fully constructed.
+ if( isLive() )
+ {
+ bind( true );
+ valueModified();
+ }
+}
+
+
+MIP Binding::getLocalMIP() const
+{
+ MIP aMIP;
+
+ if( maReadonly.hasValue() )
+ aMIP.setReadonly( maReadonly.getBool( false ) );
+ if( maRelevant.hasValue() )
+ aMIP.setRelevant( maRelevant.getBool( true ) );
+ if( maRequired.hasValue() )
+ aMIP.setRequired( maRequired.getBool( false ) );
+ if( maConstraint.hasValue() )
+ {
+ aMIP.setConstraint( maConstraint.getBool( true ) );
+ if( ! aMIP.isConstraint() )
+ aMIP.setConstraintExplanation( msExplainConstraint );
+ }
+ if( msTypeName.getLength() > 0 )
+ aMIP.setTypeName( msTypeName );
+
+ // calculate: only handle presence of calculate; value set elsewhere
+ aMIP.setHasCalculate( !maCalculate.isEmptyExpression() );
+
+ return aMIP;
+}
+
+Binding::XDataType_t Binding::getDataType()
+{
+ OSL_ENSURE( getModel().is(), "need model" );
+ OSL_ENSURE( getModel()->getDataTypeRepository().is(), "need types" );
+
+ Reference<XDataTypeRepository> xRepository(
+ getModel()->getDataTypeRepository(), UNO_QUERY );
+ OUString sTypeName = maMIP.getTypeName();
+
+ return ( xRepository.is() && xRepository->hasByName( sTypeName ) )
+ ? Reference<XDataType>( xRepository->getByName( sTypeName ), UNO_QUERY)
+ : Reference<XDataType>( NULL );
+}
+
+bool Binding::isValid_DataType()
+{
+ Reference<XDataType> xDataType = getDataType();
+ return xDataType.is()
+ ? xDataType->validate( maBindingExpression.getString() )
+ : true;
+}
+
+rtl::OUString Binding::explainInvalid_DataType()
+{
+ Reference<XDataType> xDataType = getDataType();
+ return xDataType.is()
+ ? xDataType->explainInvalid( maBindingExpression.getString() )
+ : OUString();
+}
+
+void Binding::clear()
+{
+ // remove MIPs contributed by this binding
+ Model* pModel = getModelImpl();
+ if( pModel != NULL )
+ pModel->removeMIPs( this );
+
+ // remove all references
+ for( XNodes_t::iterator aIter = maEventNodes.begin();
+ aIter != maEventNodes.end();
+ ++aIter )
+ lcl_removeListenerFromNode( *aIter, this );
+ maEventNodes.clear();
+
+ // clear expressions
+ maBindingExpression.clear();
+ maReadonly.clear();
+ maRelevant.clear();
+ maRequired.clear();
+ maConstraint.clear();
+ maCalculate.clear();
+
+ // TODO: what about our listeners?
+}
+
+
+void lcl_removeOtherNamespaces( const Binding::XNameContainer_t& xFrom,
+ Binding::XNameContainer_t& xTo )
+{
+ OSL_ENSURE( xFrom.is(), "no source" );
+ OSL_ENSURE( xTo.is(), "no target" );
+
+ // iterate over name in source
+ Sequence<OUString> aNames = xTo->getElementNames();
+ sal_Int32 nNames = aNames.getLength();
+ const OUString* pNames = aNames.getConstArray();
+ for( sal_Int32 i = 0; i < nNames; i++ )
+ {
+ const OUString& rName = pNames[i];
+
+ if( ! xFrom->hasByName( rName ) )
+ xTo->removeByName( rName );
+ }
+}
+
+/** copy namespaces from one namespace container into another
+ * @param bOverwrite true: overwrite namespaces in target
+ * false: do not overwrite namespaces in target
+ * @param bMove true: move namespaces (i.e., delete in source)
+ * false: copy namespaces (do not modify source)
+ * @param bFromSource true: use elements from source
+ * false: use only elements from target
+ */
+void lcl_copyNamespaces( const Binding::XNameContainer_t& xFrom,
+ Binding::XNameContainer_t& xTo,
+ bool bOverwrite )
+{
+ OSL_ENSURE( xFrom.is(), "no source" );
+ OSL_ENSURE( xTo.is(), "no target" );
+
+ // iterate over name in source
+ Sequence<OUString> aNames = xFrom->getElementNames();
+ sal_Int32 nNames = aNames.getLength();
+ const OUString* pNames = aNames.getConstArray();
+ for( sal_Int32 i = 0; i < nNames; i++ )
+ {
+ const OUString& rName = pNames[i];
+
+ // determine whether to copy the value, and whether to delete
+ // it in the source:
+
+ bool bInTarget = xTo->hasByName( rName );
+
+ // we copy: if property is in target, and
+ // if bOverwrite is set, or when the namespace prefix is free
+ bool bCopy = bOverwrite || ! bInTarget;
+
+ // and now... ACTION!
+ if( bCopy )
+ {
+ if( bInTarget )
+ xTo->replaceByName( rName, xFrom->getByName( rName ) );
+ else
+ xTo->insertByName( rName, xFrom->getByName( rName ) );
+ }
+ }
+}
+
+// implement get*Namespaces()
+// (identical for both variants)
+Binding::XNameContainer_t Binding::_getNamespaces() const
+{
+ XNameContainer_t xNamespaces = new NameContainer<OUString>();
+ lcl_copyNamespaces( mxNamespaces, xNamespaces, true );
+
+ // merge model's with binding's own namespaces
+ Model* pModel = getModelImpl();
+ if( pModel != NULL )
+ lcl_copyNamespaces( pModel->getNamespaces(), xNamespaces, false );
+
+ return xNamespaces;
+}
+
+// implement set*Namespaces()
+// bBinding = true: setBindingNamespaces, otherwise: setModelNamespaces
+void Binding::_setNamespaces( const XNameContainer_t& rNamespaces,
+ bool bBinding )
+{
+ Model* pModel = getModelImpl();
+ XNameContainer_t xModelNamespaces = ( pModel != NULL )
+ ? pModel->getNamespaces()
+ : NULL;
+ OSL_ENSURE( ( pModel != NULL ) == xModelNamespaces.is(), "no model nmsp?");
+
+ // remove deleted namespaces
+ lcl_removeOtherNamespaces( rNamespaces, mxNamespaces );
+ if( !bBinding && xModelNamespaces.is() )
+ lcl_removeOtherNamespaces( rNamespaces, xModelNamespaces );
+
+ // copy namespaces as appropriate
+ Sequence<OUString> aNames = rNamespaces->getElementNames();
+ sal_Int32 nNames = aNames.getLength();
+ const OUString* pNames = aNames.getConstArray();
+ for( sal_Int32 i = 0; i < nNames; i++ )
+ {
+ const OUString& rName = pNames[i];
+ Any aValue = rNamespaces->getByName( rName );
+
+ // determine whether the namespace should go into model's or
+ // into binding's namespaces
+ bool bLocal =
+ ! xModelNamespaces.is()
+ || mxNamespaces->hasByName( rName )
+ || ( bBinding
+ && xModelNamespaces.is()
+ && xModelNamespaces->hasByName( rName ) );
+
+ // write namespace into the appropriate namespace container
+ XNameContainer_t& rWhich = bLocal ? mxNamespaces : xModelNamespaces;
+ OSL_ENSURE( rWhich.is(), "whoops" );
+ if( rWhich->hasByName( rName ) )
+ rWhich->replaceByName( rName, aValue );
+ else
+ rWhich->insertByName( rName, aValue );
+
+ // always 'promote' namespaces from binding to model, if equal
+ if( xModelNamespaces.is()
+ && xModelNamespaces->hasByName( rName )
+ && mxNamespaces->hasByName( rName )
+ && xModelNamespaces->getByName( rName ) == mxNamespaces->getByName( rName ) )
+ {
+ mxNamespaces->removeByName( rName );
+ }
+ }
+
+ // ... done. But we modified the binding!
+ bindingModified();
+}
+
+void Binding::_checkBindingID()
+{
+ if( getModel().is() )
+ {
+ Reference<XNameAccess> xBindings( getModel()->getBindings(), UNO_QUERY_THROW );
+ if( msBindingID.getLength() == 0 )
+ {
+ // no binding ID? then make one up!
+ OUString sIDPrefix = getResource( RID_STR_XFORMS_BINDING_UI_NAME );
+ sIDPrefix += String::CreateFromAscii( " " );
+ sal_Int32 nNumber = 0;
+ OUString sName;
+ do
+ {
+ nNumber++;
+ sName = sIDPrefix + OUString::valueOf( nNumber );
+ }
+ while( xBindings->hasByName( sName ) );
+ setBindingID( sName );
+ }
+ }
+}
+
+
+
+
+//
+// XValueBinding
+//
+
+Binding::Sequence_Type_t Binding::getSupportedValueTypes()
+ throw( RuntimeException )
+{
+ return Convert::get().getTypes();
+}
+
+sal_Bool Binding::supportsType( const Type_t& rType )
+ throw( RuntimeException )
+{
+ return Convert::get().hasType( rType );
+}
+
+Binding::Any_t Binding::getValue( const Type_t& rType )
+ throw( IncompatibleTypesException,
+ RuntimeException )
+{
+ // first, check for model
+ checkLive();
+
+ // second, check for type
+ if( ! supportsType( rType ) )
+ throw IncompatibleTypesException( EXCEPT( "type unsupported" ) );
+
+ // return string value (if present; else return empty Any)
+ Binding::Any_t result = Any();
+ if(maBindingExpression.hasValue()) {
+ rtl::OUString pathExpr(maBindingExpression.getString());
+ Convert &rConvert = Convert::get();
+ result = rConvert.toAny(pathExpr,rType);
+ }
+
+// return maBindingExpression.hasValue()
+ // ? Convert::get().toAny( maBindingExpression.getString(), rType )
+ // : Any();
+
+ return result;
+}
+
+void Binding::setValue( const Any_t& aValue )
+ throw( IncompatibleTypesException,
+ InvalidBindingStateException,
+ NoSupportException,
+ RuntimeException )
+{
+ // first, check for model
+ checkLive();
+
+ // check for supported type
+ if( ! supportsType( aValue.getValueType() ) )
+ throw IncompatibleTypesException( EXCEPT( "type unsupported" ) );
+
+ if( maBindingExpression.hasValue() )
+ {
+ Binding::XNode_t xNode = maBindingExpression.getNode();
+ if( xNode.is() )
+ {
+ OUString sValue = Convert::get().toXSD( aValue );
+ bool bSuccess = getModelImpl()->setSimpleContent( xNode, sValue );
+ if( ! bSuccess )
+ throw InvalidBindingStateException( EXCEPT( "can't set value" ) );
+ }
+ else
+ throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) );
+ }
+ else
+ throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) );
+}
+
+
+//
+// XListEntry Source
+//
+
+sal_Int32 Binding::getListEntryCount()
+ throw( RuntimeException )
+{
+ // first, check for model
+ checkLive();
+
+ // return size of node list
+ return maBindingExpression.getNodeList().size();
+}
+
+void lcl_getString( const Reference<XNode>& xNode, OUStringBuffer& rBuffer )
+{
+ if( xNode->getNodeType() == NodeType_TEXT_NODE
+ || xNode->getNodeType() == NodeType_ATTRIBUTE_NODE )
+ {
+ rBuffer.append( xNode->getNodeValue() );
+ }
+ else
+ {
+ for( Reference<XNode> xChild = xNode->getFirstChild();
+ xChild.is();
+ xChild = xChild->getNextSibling() )
+ {
+ lcl_getString( xChild, rBuffer );
+ }
+ }
+}
+
+OUString lcl_getString( const Reference<XNode>& xNode )
+{
+ OUStringBuffer aBuffer;
+ lcl_getString( xNode, aBuffer );
+ return aBuffer.makeStringAndClear();
+}
+
+OUString Binding::getListEntry( sal_Int32 nPosition )
+ throw( IndexOutOfBoundsException,
+ RuntimeException )
+{
+ // first, check for model
+ checkLive();
+
+ // check bounds and return proper item
+ PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList();
+ if( nPosition < 0 || nPosition >= static_cast<sal_Int32>( aNodes.size() ) )
+ throw IndexOutOfBoundsException( EXCEPT("") );
+ return lcl_getString( aNodes[ nPosition ] );
+}
+
+Sequence<OUString> Binding::getAllListEntries()
+ throw( RuntimeException )
+{
+ // first, check for model
+ checkLive();
+
+ // create sequence of string values
+ PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList();
+ Sequence<OUString> aSequence( aNodes.size() );
+ OUString* pSequence = aSequence.getArray();
+ for( sal_Int32 n = 0; n < aSequence.getLength(); n++ )
+ {
+ pSequence[n] = lcl_getString( aNodes[n] );
+ }
+
+ return aSequence;
+}
+
+void Binding::addListEntryListener( const XListEntryListener_t& xListener )
+ throw( NullPointerException,
+ RuntimeException )
+{
+ OSL_ENSURE( xListener.is(), "need listener!" );
+ if( ::std::find( maListEntryListeners.begin(),
+ maListEntryListeners.end(),
+ xListener)
+ == maListEntryListeners.end() )
+ maListEntryListeners.push_back( xListener );
+}
+
+void Binding::removeListEntryListener( const XListEntryListener_t& xListener )
+ throw( NullPointerException,
+ RuntimeException )
+{
+ XListEntryListeners_t::iterator aIter =
+ ::std::find( maListEntryListeners.begin(), maListEntryListeners.end(),
+ xListener );
+ if( aIter != maListEntryListeners.end() )
+ maListEntryListeners.erase( aIter );
+}
+
+
+//
+// XValidator
+//
+
+sal_Bool Binding::isValid( const Any_t& )
+ throw( RuntimeException )
+{
+ // first, check for model
+ checkLive();
+
+ // ignore value; determine validate only on current data
+ return isValid();
+}
+
+rtl::OUString Binding::explainInvalid(
+ const Any_t& /*Value*/ )
+ throw( RuntimeException )
+{
+ // first, check for model
+ checkLive();
+
+ // ignore value; determine explanation only on current data
+ return explainInvalid();
+}
+
+void Binding::addValidityConstraintListener(
+ const XValidityConstraintListener_t& xListener )
+ throw( NullPointerException,
+ RuntimeException )
+{
+ OSL_ENSURE( xListener.is(), "need listener!" );
+ if( ::std::find(maValidityListeners.begin(), maValidityListeners.end(), xListener)
+ == maValidityListeners.end() )
+ maValidityListeners.push_back( xListener );
+}
+
+void Binding::removeValidityConstraintListener(
+ const XValidityConstraintListener_t& xListener )
+ throw( NullPointerException,
+ RuntimeException )
+{
+ XValidityConstraintListeners_t::iterator aIter =
+ ::std::find( maValidityListeners.begin(), maValidityListeners.end(),
+ xListener );
+ if( aIter != maValidityListeners.end() )
+ maValidityListeners.erase( aIter );
+}
+
+
+
+//
+// xml::dom::event::XEventListener
+//
+
+void Binding::handleEvent( const XEvent_t& xEvent )
+ throw( RuntimeException )
+{
+ OUString sType(xEvent->getType());
+ //OUString sEventMIPChanged(RTL_CONSTASCII_USTRINGPARAM("xforms-generic"));
+ //if(sType.equals(sEventMIPChanged)) {
+ if(!sType.compareToAscii("xforms-generic")) {
+
+ // the modification of the 'mnDeferModifyNotifications'-member
+ // is necessary to prevent infinite notication looping.
+ // This can happend in case the binding which caused
+ // the notification chain is listening to those events
+ // as well...
+ bool bPreserveValueModified = mbValueModified;
+ mnDeferModifyNotifications++;
+ valueModified();
+ --mnDeferModifyNotifications;
+ mbValueModified = bPreserveValueModified;
+ return;
+ }
+
+ // if we're a dynamic binding, we better re-bind, too!
+ bind( false );
+
+ // our value was maybe modified
+ valueModified();
+}
+
+
+//
+// lang::XUnoTunnel
+//
+
+sal_Int64 Binding::getSomething( const IntSequence_t& xId )
+ throw( RuntimeException )
+{
+ return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL );
+}
+
+//
+// XCloneable
+//
+
+Binding::XCloneable_t SAL_CALL Binding::createClone()
+ throw( RuntimeException )
+{
+ Reference< XPropertySet > xClone;
+
+ Model* pModel = getModelImpl();
+ if ( pModel )
+ xClone = pModel->cloneBinding( this );
+ else
+ {
+ xClone = new Binding;
+ copy( this, xClone );
+ }
+ return XCloneable_t( xClone, UNO_QUERY );
+}
+
+//
+// property set implementations
+//
+
+#define REGISTER_PROPERTY( property, type ) \
+ registerProperty( PROPERTY( property, type ), \
+ new DirectPropertyAccessor< Binding, type >( this, &Binding::set##property, &Binding::get##property ) );
+
+#define REGISTER_PROPERTY_RO( property, type ) \
+ registerProperty( PROPERTY_RO( property, type ), \
+ new DirectPropertyAccessor< Binding, type >( this, NULL, &Binding::get##property ) );
+
+#define REGISTER_BOOL_PROPERTY_RO( property ) \
+ registerProperty( PROPERTY_RO( property, sal_Bool ), \
+ new BooleanPropertyAccessor< Binding, bool >( this, NULL, &Binding::get##property ) );
+
+void Binding::initializePropertySet()
+{
+ REGISTER_PROPERTY ( BindingID, OUString );
+ REGISTER_PROPERTY ( BindingExpression, OUString );
+ REGISTER_PROPERTY_RO ( Model, Model_t );
+ REGISTER_PROPERTY ( BindingNamespaces, XNameContainer_t );
+ REGISTER_PROPERTY ( ModelNamespaces, XNameContainer_t );
+ REGISTER_PROPERTY_RO ( ModelID, OUString );
+ REGISTER_PROPERTY ( ReadonlyExpression, OUString );
+ REGISTER_PROPERTY ( RelevantExpression, OUString );
+ REGISTER_PROPERTY ( RequiredExpression, OUString );
+ REGISTER_PROPERTY ( ConstraintExpression, OUString );
+ REGISTER_PROPERTY ( CalculateExpression, OUString );
+ REGISTER_PROPERTY ( Type, OUString );
+ REGISTER_PROPERTY_RO ( ReadOnly, bool );
+ REGISTER_PROPERTY_RO ( Relevant, bool );
+ REGISTER_BOOL_PROPERTY_RO( ExternalData );
+
+ initializePropertyValueCache( HANDLE_ReadOnly );
+ initializePropertyValueCache( HANDLE_Relevant );
+ initializePropertyValueCache( HANDLE_ExternalData );
+}
+
+void Binding::addModifyListener(
+ const XModifyListener_t& xListener )
+ throw( RuntimeException )
+{
+ OSL_ENSURE( xListener.is(), "need listener!" );
+ if( ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener )
+ == maModifyListeners.end() )
+ maModifyListeners.push_back( xListener );
+
+ // HACK: currently, we have to 'push' some MIPs to the control
+ // (read-only, relevant, etc.) To enable this, we need to update
+ // the control at least once when it registers here.
+ valueModified();
+}
+
+void Binding::removeModifyListener(
+ const XModifyListener_t& xListener )
+ throw( RuntimeException )
+{
+ ModifyListeners_t::iterator aIter =
+ ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener );
+ if( aIter != maModifyListeners.end() )
+ maModifyListeners.erase( aIter );
+}
+
+
+
+
+rtl::OUString Binding::getName()
+ throw( RuntimeException )
+{
+ return getBindingID();
+}
+
+void SAL_CALL Binding::setName( const rtl::OUString& rName )
+ throw( RuntimeException )
+{
+ // use the XPropertySet methods, so the change in the name is notified to the
+ // property listeners
+ setFastPropertyValue( HANDLE_BindingID, makeAny( rName ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/binding.hxx b/forms/source/xforms/binding.hxx
new file mode 100644
index 000000000000..ba538441df91
--- /dev/null
+++ b/forms/source/xforms/binding.hxx
@@ -0,0 +1,530 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _BINDING_HXX
+#define _BINDING_HXX
+
+#include <com/sun/star/uno/Reference.hxx>
+
+// forward declaractions
+namespace xforms
+{
+ class Model;
+ class EvaluationContext;
+}
+namespace com { namespace sun { namespace star {
+ namespace xml {
+ namespace xpath { class XXPathAPI; }
+ namespace dom
+ {
+ class XNode;
+ class XNodeList;
+ }
+ }
+ namespace container { class XNameContainer; }
+ namespace xforms { class XModel; }
+ namespace xsd { class XDataType; }
+} } }
+
+// includes for parent classes
+#include <cppuhelper/implbase8.hxx>
+#include <propertysetbase.hxx>
+#include <com/sun/star/form/binding/XValueBinding.hpp>
+#include <com/sun/star/form/binding/XListEntrySource.hpp>
+#include <com/sun/star/form/validation/XValidator.hpp>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/xml/dom/events/XEventListener.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/util/XCloneable.hpp>
+
+// includes for member variables
+#include "pathexpression.hxx"
+#include "boolexpression.hxx"
+#include "mip.hxx"
+#include <rtl/ustring.hxx>
+#include <vector>
+#include <memory> // auto_ptr
+
+
+
+namespace xforms
+{
+
+/** An XForms Binding. Contains:
+ * # a connection to its model
+ * # an ID
+ * # an binding expression
+ * # model item properties
+ * # (NOT YET IMPLEMENTED) child bindings (sequence of)
+ *
+ * See http://www.w3.org/TR/xforms/ for more information.
+ */
+
+typedef cppu::ImplInheritanceHelper8<
+ PropertySetBase,
+ com::sun::star::form::binding::XValueBinding,
+ com::sun::star::form::binding::XListEntrySource,
+ com::sun::star::form::validation::XValidator,
+ com::sun::star::util::XModifyBroadcaster,
+ com::sun::star::container::XNamed,
+ com::sun::star::xml::dom::events::XEventListener,
+ com::sun::star::lang::XUnoTunnel,
+ com::sun::star::util::XCloneable
+> Binding_t;
+
+class Binding : public Binding_t
+{
+public:
+ typedef com::sun::star::uno::Reference<com::sun::star::xforms::XModel> Model_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::util::XModifyListener> XModifyListener_t;
+ typedef std::vector<XModifyListener_t> ModifyListeners_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::form::validation::XValidityConstraintListener> XValidityConstraintListener_t;
+ typedef std::vector<XValidityConstraintListener_t> XValidityConstraintListeners_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::form::binding::XListEntryListener> XListEntryListener_t;
+ typedef std::vector<XListEntryListener_t> XListEntryListeners_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::container::XNameContainer> XNameContainer_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> XNode_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XNodeList> XNodeList_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::util::XCloneable> XCloneable_t;
+ typedef com::sun::star::uno::Sequence<sal_Int8> IntSequence_t;
+ typedef com::sun::star::uno::Sequence<rtl::OUString> StringSequence_t;
+ typedef std::vector<MIP> MIPs_t;
+ typedef std::vector<XNode_t> XNodes_t;
+
+
+
+private:
+
+ /// the Model to which this Binding belongs; may be NULL
+ Model_t mxModel;
+
+ /// binding-ID. A document-wide unique ID for this binding element.
+ rtl::OUString msBindingID;
+
+ /// an XPath-expression to be instantiated on the data instance
+ PathExpression maBindingExpression;
+
+ /// an XPath-expression to determine read-only status
+ BoolExpression maReadonly;
+
+ /// an XPath-expression to determine relevance
+ BoolExpression maRelevant;
+
+ /// an XPath-expression to determine if item is required
+ BoolExpression maRequired;
+
+ /// an XPath-expression to determine if item is valid
+ BoolExpression maConstraint;
+
+ /// user-readable explanation of the constraint
+ rtl::OUString msExplainConstraint;
+
+ /// an XPath-expression to calculate values
+ ComputedExpression maCalculate;
+
+ /// the XML namespaces used for XML names/XPath-expressions in this binding
+ XNameContainer_t mxNamespaces;
+
+ /// a type name
+ rtl::OUString msTypeName;
+
+ /// modify listeners
+ ModifyListeners_t maModifyListeners;
+
+ /// list entry listener
+ XListEntryListeners_t maListEntryListeners;
+
+ /// validity listeners;
+ XValidityConstraintListeners_t maValidityListeners;
+
+ /// nodes on which we are listening for events
+ XNodes_t maEventNodes;
+
+ /// the current MIP object for the first node we are bound to
+ MIP maMIP;
+
+ /// flag to detect recursions in calculate
+ bool mbInCalculate;
+
+ // flags to manage deferred notifications:
+ /// if >0, valueModified() and bindingModified() will only set flags
+ sal_Int32 mnDeferModifyNotifications;
+ bool mbValueModified; /// if true, valueModified needs to be called
+ bool mbBindingModified; /// if true, bindingModified needs to be called
+
+
+ void initializePropertySet();
+
+
+public:
+ Binding();
+ virtual ~Binding() throw();
+
+ //
+ // property methods: get/set value
+ //
+
+ Model_t getModel() const; /// get XForms model
+ void _setModel( const Model_t& ); /// set XForms model (only called by Model)
+
+
+ rtl::OUString getModelID() const; /// get ID of XForms model
+
+ rtl::OUString getBindingID() const; /// get ID for this binding
+ void setBindingID( const rtl::OUString& ); /// set ID for this binding
+
+ rtl::OUString getBindingExpression() const; /// get binding expression
+ void setBindingExpression( const rtl::OUString& ); /// set binding exp.
+
+ // MIPs (model item properties)
+
+ rtl::OUString getReadonlyExpression() const; /// get read-only MIP
+ void setReadonlyExpression( const rtl::OUString& ); /// set read-only MIP
+
+ rtl::OUString getRelevantExpression() const; /// get relevant MIP
+ void setRelevantExpression( const rtl::OUString& ); /// set relevant MIP
+
+ rtl::OUString getRequiredExpression() const; /// get required MIP
+ void setRequiredExpression( const rtl::OUString& ); /// set required MIP
+
+ rtl::OUString getConstraintExpression() const; /// get constraint MIP
+ void setConstraintExpression( const rtl::OUString& );/// set constraint MIP
+
+ rtl::OUString getCalculateExpression() const; /// get calculate MIP
+ void setCalculateExpression( const rtl::OUString& ); /// set calculate MIP
+
+ rtl::OUString getType() const; /// get type name MIP (static)
+ void setType( const rtl::OUString& ); /// set type name MIP (static)
+
+ // a binding expression can only be interpreted with respect to
+ // suitable namespace declarations. We collect those in the model and in a binding.
+
+ // access to a binding's namespace
+ // (set-method only changes local namespaces (but may add to model))
+ XNameContainer_t getBindingNamespaces() const; /// set binding namespaces
+ void setBindingNamespaces( const XNameContainer_t& ); /// get binding nmsp.
+
+ // access to the model's namespaces
+ // (set-method changes model's namespaces (unless a local one is present))
+ XNameContainer_t getModelNamespaces() const; /// set model namespaces
+ void setModelNamespaces( const XNameContainer_t& ); /// get model nmsp.
+
+
+ // read-only properties that map MIPs to control data source properties
+ bool getReadOnly() const; // MIP readonly
+ bool getRelevant() const; // MIP relevant
+ bool getExternalData() const; // mapped from model's ExternalData property
+
+
+ // missing binding properties:
+ // - type (static; default: xsd:string)
+ // - minOccurs/maxOccurs (computed XPath; default: 0/inf)
+ // - p3ptype (static; no default)
+
+
+
+
+ /// get this binding's context node
+ xforms::EvaluationContext getEvaluationContext() const;
+
+ /// get evalation contexts for this binding's MIPs
+ std::vector<xforms::EvaluationContext> getMIPEvaluationContexts();
+
+ /// get nodeset the bind is bound to
+ XNodeList_t getXNodeList();
+
+ /// heuristically determine whether this binding is simple binding
+ /// (here: simple binding == does not depend on other parts of the
+ /// instance, it's not a 'dynamic' binding)
+ bool isSimpleBinding() const;
+
+ /// heuristically determine whether this binding's binding
+ /// expression is simple
+ bool isSimpleBindingExpression() const;
+
+ /// update this binding (e.g. called by model for refresh )
+ void update();
+
+ /// prevent change notifications being sent to controls
+ void deferNotifications( bool );
+
+ /// is this binding valid? (are constraint, type and required MIPs ok?)
+ bool isValid();
+
+ /// determine whether this binding currently performs a useful
+ /// function, r whether is may be discarded
+ bool isUseful();
+
+ /// explain why binding is invalid
+ rtl::OUString explainInvalid();
+
+
+ // the ID for XUnoTunnel calls
+ static IntSequence_t getUnoTunnelID();
+ static Binding* getBinding( const com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>& );
+
+ //
+ // class-scoped typedef for easy-to-read UNO interfaces
+ //
+
+ // basic types
+ typedef com::sun::star::uno::Any Any_t;
+ typedef com::sun::star::uno::Sequence<com::sun::star::uno::Type> Sequence_Type_t;
+ typedef com::sun::star::uno::Type Type_t;
+
+ // reference types
+ typedef com::sun::star::uno::Reference<com::sun::star::beans::XPropertyChangeListener> XPropertyChangeListener_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::beans::XPropertySetInfo> XPropertySetInfo_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::beans::XVetoableChangeListener> XVetoableChangeListener_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xml::xpath::XXPathAPI> XXPathAPI_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::events::XEvent> XEvent_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xsd::XDataType> XDataType_t;
+
+ // exceptions
+ typedef com::sun::star::beans::PropertyVetoException PropertyVetoException_t;
+ typedef com::sun::star::beans::UnknownPropertyException UnknownPropertyException_t;
+ typedef com::sun::star::lang::IllegalArgumentException IllegalArgumentException_t;
+ typedef com::sun::star::lang::NoSupportException NoSupportException_t;
+ typedef com::sun::star::lang::WrappedTargetException WrappedTargetException_t;
+ typedef com::sun::star::uno::RuntimeException RuntimeException_t;
+ typedef com::sun::star::form::binding::IncompatibleTypesException IncompatibleTypesException_t;
+ typedef com::sun::star::form::binding::InvalidBindingStateException InvalidBindingStateException_t;
+ typedef com::sun::star::lang::NullPointerException NullPointerException_t;
+ typedef com::sun::star::lang::IndexOutOfBoundsException IndexOutOfBoundsException_t;
+
+
+
+private:
+ /// check whether object is live, and throw suitable exception if not
+ /// (to be used be API methods before acting on the object)
+ void checkLive() throw( RuntimeException_t );
+
+ /// check whether binding has a model, and throw exception if not
+ /// (to be used be API methods before acting on the object)
+ void checkModel() throw( RuntimeException_t );
+
+ /// determine whether object is live
+ /// live: has model, and model has been initialized
+ bool isLive() const;
+
+ /// get the model implementation
+ xforms::Model* getModelImpl() const;
+ xforms::Model* getModelImpl( const Model_t& xModel ) const;
+
+ /// get MIP evaluation contexts
+ /// (only valid if control has already been bound)
+ std::vector<xforms::EvaluationContext> _getMIPEvaluationContexts() const;
+
+ /// bind this binding, and pre-compute the affected nodes
+ void bind( bool bForceRebind = false );
+
+ /// the binding value has been changed:
+ /// trigger a modified event on all modified listeners
+ void valueModified();
+
+ /// the binding itself has changed:
+ /// force rebind, then call valueModified()
+ void bindingModified();
+
+
+ /// register the event listeners for
+ void registerListeners();
+
+ /// set MIPs defined by this binding on MIP item
+ MIP getLocalMIP() const;
+
+ /// get the data type that applies to this binding
+ XDataType_t getDataType();
+
+ /// determine whether binding is valid according to the given data type
+ bool isValid_DataType();
+
+ /// explain validity of binding with respect to the given data type
+ rtl::OUString explainInvalid_DataType();
+
+ /// 'clear' this binding - remove all listeners, etc.
+ void clear();
+
+ /// distribute MIPs from current node recursively to childs
+ void distributeMIP( const XNode_t &rxNode );
+
+ /// implement get*Namespaces()
+ XNameContainer_t _getNamespaces() const;
+
+ /// implement set*Namespaces()
+ void _setNamespaces( const XNameContainer_t&, bool bBinding );
+
+ /// set a useful default binding ID (if none is set)
+ void _checkBindingID();
+
+public:
+ /// for debugging purposes only: get the MIPs defined by this binding
+ const MIP* _getMIP();
+
+
+
+
+
+ //
+ // XValueBinding:
+ //
+
+public:
+
+ virtual Sequence_Type_t SAL_CALL getSupportedValueTypes()
+ throw( RuntimeException_t );
+
+ virtual sal_Bool SAL_CALL supportsType( const Type_t& aType )
+ throw( RuntimeException_t );
+
+ virtual Any_t SAL_CALL getValue( const Type_t& aType )
+ throw( IncompatibleTypesException_t,
+ RuntimeException_t );
+
+ virtual void SAL_CALL setValue( const Any_t& aValue )
+ throw( IncompatibleTypesException_t,
+ InvalidBindingStateException_t,
+ NoSupportException_t,
+ RuntimeException_t );
+
+
+
+ //
+ // XListEntry Source
+ //
+
+ virtual sal_Int32 SAL_CALL getListEntryCount()
+ throw( RuntimeException_t );
+
+ virtual rtl::OUString SAL_CALL getListEntry( sal_Int32 nPosition )
+ throw( IndexOutOfBoundsException_t,
+ RuntimeException_t );
+
+ virtual StringSequence_t SAL_CALL getAllListEntries()
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL addListEntryListener( const XListEntryListener_t& )
+ throw( NullPointerException_t,
+ RuntimeException_t );
+
+ virtual void SAL_CALL removeListEntryListener( const XListEntryListener_t&)
+ throw( NullPointerException_t,
+ RuntimeException_t );
+
+
+
+ //
+ // XValidator:
+ //
+
+ virtual sal_Bool SAL_CALL isValid(
+ const Any_t& )
+ throw( RuntimeException_t );
+
+ virtual rtl::OUString SAL_CALL explainInvalid(
+ const Any_t& )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL addValidityConstraintListener(
+ const XValidityConstraintListener_t& xListener )
+ throw( NullPointerException_t,
+ RuntimeException_t );
+
+ virtual void SAL_CALL removeValidityConstraintListener(
+ const XValidityConstraintListener_t& xListener )
+ throw( NullPointerException_t,
+ RuntimeException_t );
+
+
+ //
+ // XModifyBroadcaster & friends:
+ // inform listeners about changes in our values
+ //
+
+public:
+
+ virtual void SAL_CALL addModifyListener(
+ const XModifyListener_t& xListener )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL removeModifyListener(
+ const XModifyListener_t& xListener )
+ throw( RuntimeException_t );
+
+
+
+
+ //
+ // XNamed:
+ // get/set name
+ //
+
+public:
+
+ virtual rtl::OUString SAL_CALL getName()
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL setName( const rtl::OUString& )
+ throw( RuntimeException_t );
+
+
+
+ //
+ // xml::dom::event::XEventListener
+ // receive an event if our node changed
+ //
+
+ virtual void SAL_CALL handleEvent(
+ const XEvent_t& xEvent )
+ throw( RuntimeException_t );
+
+
+
+ //
+ // XUnoTunnel
+ //
+
+ virtual sal_Int64 SAL_CALL getSomething( const IntSequence_t& )
+ throw( RuntimeException_t );
+
+
+ //
+ // XCloneable
+ //
+
+ virtual XCloneable_t SAL_CALL createClone()
+ throw( RuntimeException_t );
+};
+
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/boolexpression.cxx b/forms/source/xforms/boolexpression.cxx
new file mode 100644
index 000000000000..9abf5590f70d
--- /dev/null
+++ b/forms/source/xforms/boolexpression.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "boolexpression.hxx"
+
+
+namespace xforms
+{
+
+/** BoolExpression represents a computed XPath expression that returns
+ * a bool value and caches the results.
+ *
+ * As this class has no virtual methods, it should never be used
+ * polymorphically. */
+
+BoolExpression::BoolExpression() : ComputedExpression()
+{
+}
+
+BoolExpression::~BoolExpression()
+{
+}
+
+void BoolExpression::setExpression( const rtl::OUString& rExpression )
+{
+ ComputedExpression::setExpression( rExpression );
+ mbIsSimple = _checkExpression( " *(true)|(false) *\\( *\\) *" );
+}
+
+
+} // namespace xforms
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/boolexpression.hxx b/forms/source/xforms/boolexpression.hxx
new file mode 100644
index 000000000000..8da5d58ad3c0
--- /dev/null
+++ b/forms/source/xforms/boolexpression.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _BOOLEXPRESSION_HXX
+#define _BOOLEXPRESSION_HXX
+
+// include for parent class
+#include "computedexpression.hxx"
+
+namespace xforms
+{
+
+/** BoolExpression represents a computed XPath expression that returns
+ * a bool value and caches the results.
+ *
+ * As this class has no virtual methods, it should never be used
+ * polymorphically. */
+class BoolExpression : public ComputedExpression
+{
+public:
+ BoolExpression();
+ ~BoolExpression();
+
+ /// set the expression string
+ /// (overridden for new definition of a simple expression)
+ void setExpression( const rtl::OUString& rExpression );
+};
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/collection.hxx b/forms/source/xforms/collection.hxx
new file mode 100644
index 000000000000..0ba804c8e608
--- /dev/null
+++ b/forms/source/xforms/collection.hxx
@@ -0,0 +1,340 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _COLLECTION_HXX
+#define _COLLECTION_HXX
+
+#include "enumeration.hxx"
+
+#include <cppuhelper/implbase3.hxx>
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/container/XSet.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetException.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/uno/Type.hxx>
+#include <vector>
+#include <algorithm>
+
+
+typedef cppu::WeakImplHelper3<
+ com::sun::star::container::XIndexReplace,
+ com::sun::star::container::XSet,
+ com::sun::star::container::XContainer>
+Collection_t;
+
+template<class ELEMENT_TYPE>
+class Collection : public Collection_t
+{
+public:
+ typedef ELEMENT_TYPE T;
+ typedef com::sun::star::uno::Reference<com::sun::star::container::XContainerListener> XContainerListener_t;
+ typedef std::vector<XContainerListener_t> Listeners_t;
+
+protected:
+ std::vector<T> maItems;
+ Listeners_t maListeners;
+
+public:
+
+ Collection() {}
+ virtual ~Collection() {}
+
+ const T& getItem( sal_Int32 n ) const
+ {
+ OSL_ENSURE( isValidIndex(n), "invalid index" );
+ OSL_ENSURE( isValid( maItems[n] ), "invalid item found" );
+ return maItems[n];
+ }
+
+ void setItem( sal_Int32 n, const T& t)
+ {
+ OSL_ENSURE( isValidIndex(n), "invalid index" );
+ OSL_ENSURE( isValid ( t ), "invalid item" );
+
+ T& aRef = maItems[ n ];
+ _elementReplaced( n, t );
+ _remove( aRef );
+ aRef = t;
+ _insert( t );
+ }
+
+ bool hasItem( const T& t ) const
+ {
+ return maItems.end() != std::find( maItems.begin(), maItems.end(), t );
+ }
+
+ sal_Int32 addItem( const T& t )
+ {
+ OSL_ENSURE( !hasItem( t ), "item to be added already present" );
+ OSL_ENSURE( isValid( t ), "invalid item" );
+
+ maItems.push_back( t );
+ _insert( t );
+ _elementInserted( maItems.size() - 1 );
+ return ( maItems.size() - 1 );
+ }
+
+ void removeItem( const T& t )
+ {
+ OSL_ENSURE( hasItem( t ), "item to be removed not present" );
+ OSL_ENSURE( isValid( t ), "an invalid item, funny that!" );
+
+ _elementRemoved( t );
+ _remove( t );
+ maItems.erase( std::find( maItems.begin(), maItems.end(), t ) );
+ }
+
+ bool hasItems() const
+ {
+ return maItems.size() != 0;
+ }
+
+ sal_Int32 countItems() const
+ {
+ return static_cast<sal_Int32>( maItems.size() );
+ }
+
+ bool isValidIndex( sal_Int32 n ) const
+ {
+ return n >= 0 && n < static_cast<sal_Int32>( maItems.size() );
+ }
+
+
+ // the following method may be overriden by sub-classes for
+ // customized behaviour
+
+ /// called before insertion to determine whether item is valid
+ virtual bool isValid( const T& ) const { return true; }
+
+
+protected:
+
+ // the following methods may be overriden by sub-classes for
+ // customized behaviour
+
+ /// called after item has been inserted into the collection
+ virtual void _insert( const T& ) { }
+
+ /// called before item is removed from the collection
+ virtual void _remove( const T& ) { }
+
+public:
+
+ typedef com::sun::star::uno::Type Type_t;
+ typedef com::sun::star::uno::Any Any_t;
+ typedef com::sun::star::uno::RuntimeException RuntimeException_t;
+ typedef com::sun::star::lang::IllegalArgumentException IllegalArgumentException_t;
+ typedef com::sun::star::container::NoSuchElementException NoSuchElementException_t;
+ typedef com::sun::star::lang::IndexOutOfBoundsException IndexOutOfBoundsException_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::container::XEnumeration> XEnumeration_t;
+ typedef com::sun::star::lang::WrappedTargetException WrappedTargetException_t;
+ typedef com::sun::star::container::ElementExistException ElementExistException_t;
+
+
+ // XElementAccess
+ virtual Type_t SAL_CALL getElementType()
+ throw( RuntimeException_t )
+ {
+ return getCppuType( static_cast<T*>( NULL ) );
+ }
+
+ virtual sal_Bool SAL_CALL hasElements()
+ throw( RuntimeException_t )
+ {
+ return hasItems();
+ }
+
+ // XIndexAccess : XElementAccess
+ virtual sal_Int32 SAL_CALL getCount()
+ throw( RuntimeException_t )
+ {
+ return countItems();
+ }
+
+ virtual Any_t SAL_CALL getByIndex( sal_Int32 nIndex )
+ throw( IndexOutOfBoundsException_t,
+ WrappedTargetException_t,
+ RuntimeException_t)
+ {
+ if( isValidIndex( nIndex ) )
+ return com::sun::star::uno::makeAny( getItem( nIndex ) );
+ else
+ throw IndexOutOfBoundsException_t();
+ }
+
+ // XIndexReplace : XIndexAccess
+ virtual void SAL_CALL replaceByIndex( sal_Int32 nIndex,
+ const Any_t& aElement )
+ throw( IllegalArgumentException_t,
+ IndexOutOfBoundsException_t,
+ WrappedTargetException_t,
+ RuntimeException_t)
+ {
+ T t;
+ if( isValidIndex( nIndex) )
+ if( ( aElement >>= t ) && isValid( t ) )
+ setItem( nIndex, t );
+ else
+ throw IllegalArgumentException_t();
+ else
+ throw IndexOutOfBoundsException_t();
+ }
+
+ // XEnumerationAccess : XElementAccess
+ virtual XEnumeration_t SAL_CALL createEnumeration()
+ throw( RuntimeException_t )
+ {
+ return new Enumeration( this );
+ }
+
+
+ // XSet : XEnumerationAccess
+ virtual sal_Bool SAL_CALL has( const Any_t& aElement )
+ throw( RuntimeException_t )
+ {
+ T t;
+ return ( aElement >>= t ) ? hasItem( t ) : sal_False;
+ }
+
+ virtual void SAL_CALL insert( const Any_t& aElement )
+ throw( IllegalArgumentException_t,
+ ElementExistException_t,
+ RuntimeException_t )
+ {
+ T t;
+ if( ( aElement >>= t ) && isValid( t ) )
+ if( ! hasItem( t ) )
+ addItem( t );
+ else
+ throw ElementExistException_t();
+ else
+ throw IllegalArgumentException_t();
+ }
+
+ virtual void SAL_CALL remove( const Any_t& aElement )
+ throw( IllegalArgumentException_t,
+ NoSuchElementException_t,
+ RuntimeException_t )
+ {
+ T t;
+ if( aElement >>= t )
+ if( hasItem( t ) )
+ removeItem( t );
+ else
+ throw NoSuchElementException_t();
+ else
+ throw IllegalArgumentException_t();
+ }
+
+
+ // XContainer
+ virtual void SAL_CALL addContainerListener(
+ const XContainerListener_t& xListener )
+ throw( RuntimeException_t )
+ {
+ OSL_ENSURE( xListener.is(), "need listener!" );
+ if( std::find( maListeners.begin(), maListeners.end(), xListener)
+ == maListeners.end() )
+ maListeners.push_back( xListener );
+ }
+
+ virtual void SAL_CALL removeContainerListener(
+ const XContainerListener_t& xListener )
+ throw( RuntimeException_t )
+ {
+ OSL_ENSURE( xListener.is(), "need listener!" );
+ Listeners_t::iterator aIter =
+ std::find( maListeners.begin(), maListeners.end(), xListener );
+ if( aIter != maListeners.end() )
+ maListeners.erase( aIter );
+ }
+
+protected:
+
+ // call listeners:
+ void _elementInserted( sal_Int32 nPos )
+ {
+ OSL_ENSURE( isValidIndex(nPos), "invalid index" );
+ com::sun::star::container::ContainerEvent aEvent(
+ static_cast<com::sun::star::container::XIndexReplace*>( this ),
+ com::sun::star::uno::makeAny( nPos ),
+ com::sun::star::uno::makeAny( getItem( nPos ) ),
+ com::sun::star::uno::Any() );
+ for( Listeners_t::iterator aIter = maListeners.begin();
+ aIter != maListeners.end();
+ aIter++ )
+ {
+ (*aIter)->elementInserted( aEvent );
+ }
+ }
+
+ void _elementRemoved( const T& aOld )
+ {
+ com::sun::star::container::ContainerEvent aEvent(
+ static_cast<com::sun::star::container::XIndexReplace*>( this ),
+ com::sun::star::uno::Any(),
+ com::sun::star::uno::makeAny( aOld ),
+ com::sun::star::uno::Any() );
+ for( Listeners_t::iterator aIter = maListeners.begin();
+ aIter != maListeners.end();
+ aIter++ )
+ {
+ (*aIter)->elementRemoved( aEvent );
+ }
+ }
+
+ void _elementReplaced( const sal_Int32 nPos, const T& aNew )
+ {
+ OSL_ENSURE( isValidIndex(nPos), "invalid index" );
+ com::sun::star::container::ContainerEvent aEvent(
+ static_cast<com::sun::star::container::XIndexReplace*>( this ),
+ com::sun::star::uno::makeAny( nPos ),
+ com::sun::star::uno::makeAny( getItem( nPos ) ),
+ com::sun::star::uno::makeAny( aNew ) );
+ for( Listeners_t::iterator aIter = maListeners.begin();
+ aIter != maListeners.end();
+ aIter++ )
+ {
+ (*aIter)->elementReplaced( aEvent );
+ }
+ }
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/computedexpression.cxx b/forms/source/xforms/computedexpression.cxx
new file mode 100644
index 000000000000..4739924b8d53
--- /dev/null
+++ b/forms/source/xforms/computedexpression.cxx
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "computedexpression.hxx"
+#include "unohelper.hxx"
+#include "evaluationcontext.hxx"
+#include "NameContainer.hxx"
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/xml/dom/NodeType.hpp>
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/xml/xpath/XXPathAPI.hpp>
+#include <com/sun/star/xml/xpath/XXPathObject.hpp>
+#include <com/sun/star/xml/xpath/XXPathExtension.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/util/SearchAlgorithms.hpp>
+
+#include <unotools/textsearch.hxx>
+#include <comphelper/processfactory.hxx>
+
+using rtl::OUString;
+using com::sun::star::beans::NamedValue;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::lang::XInitialization;
+using com::sun::star::lang::XMultiServiceFactory;
+using com::sun::star::xml::dom::XNode;
+using com::sun::star::container::XNameContainer;
+using com::sun::star::xml::xpath::XXPathAPI;
+using com::sun::star::xml::xpath::XXPathExtension;
+using com::sun::star::xml::xpath::XXPathObject;
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::uno::Exception;
+using com::sun::star::uno::UNO_QUERY_THROW;
+using com::sun::star::xml::xpath::XPathObjectType_XPATH_UNDEFINED;
+using com::sun::star::util::SearchOptions;
+using com::sun::star::util::SearchAlgorithms_REGEXP;
+
+
+namespace xforms
+{
+
+ComputedExpression::ComputedExpression()
+ : msExpression(),
+ mbIsEmpty( true ),
+ mbIsSimple( true ),
+ mxResult()
+{
+}
+
+ComputedExpression::~ComputedExpression()
+{
+}
+
+
+OUString ComputedExpression::getExpression() const
+{
+ return msExpression;
+}
+
+void ComputedExpression::setExpression( const OUString& rExpression )
+{
+ // set new expression, and clear pre-computed results
+ msExpression = rExpression;
+ mbIsEmpty = _checkExpression( " *" );
+ mbIsSimple = false;
+ mxResult.clear();
+}
+
+
+bool ComputedExpression::_checkExpression( const sal_Char* pExpression ) const
+{
+ OSL_ENSURE( pExpression != NULL, "no expression?" );
+
+ // call RegExp engine
+ SearchOptions aSearchOptions;
+ aSearchOptions.algorithmType = SearchAlgorithms_REGEXP;
+ aSearchOptions.searchString = String( pExpression, RTL_TEXTENCODING_ASCII_US );
+ utl::TextSearch aTextSearch( aSearchOptions );
+
+ xub_StrLen nLength =
+ static_cast<xub_StrLen>( msExpression.getLength() );
+ xub_StrLen nStart = 0;
+ xub_StrLen nEnd = nLength;
+ int nSearch = aTextSearch.SearchFrwrd( msExpression, &nStart, &nEnd );
+
+ // our expression is static only if 1) we found our regexp, and 2)
+ // the regexp goes from beginning to end.
+ return ( nLength == 0 || nSearch != 0 )
+ && ( nStart == 0 && nEnd == nLength );
+}
+
+/// do we have an actual expression?
+bool ComputedExpression::isEmptyExpression() const
+{
+ return mbIsEmpty;
+}
+
+bool ComputedExpression::isSimpleExpression() const
+{
+ // actual work is done by setExpression
+ return mbIsEmpty || mbIsSimple;
+}
+
+
+const OUString ComputedExpression::_getExpressionForEvaluation() const
+{
+ // the default implementation is to do nothing...
+ return msExpression;
+}
+
+bool ComputedExpression::_evaluate(
+ const xforms::EvaluationContext& rContext,
+ const OUString& sExpression )
+{
+ OSL_ENSURE( rContext.mxContextNode.is(), "no context node in context" );
+
+ // obtain value by evaluating XPath expression
+ mxResult.clear();
+ try
+ {
+ mxResult = _getXPathAPI(rContext)->eval( rContext.mxContextNode,
+ sExpression );
+ }
+ catch( const Exception& )
+ {
+ ; // ignore exception -> mxResult will be empty
+ }
+
+ return hasValue();
+}
+
+bool ComputedExpression::evaluate( const EvaluationContext& rContext )
+{
+ // for simple expression we don't need to re-evaluate (if we have
+ // an older result); neither for empty expressions
+ if( mbIsEmpty || (mxResult.is() && mbIsSimple) )
+ return true;
+
+ return _evaluate( rContext, _getExpressionForEvaluation() );
+}
+
+
+bool ComputedExpression::hasValue() const
+{
+ return mxResult.is() &&
+ mxResult->getObjectType() != XPathObjectType_XPATH_UNDEFINED;
+}
+
+void ComputedExpression::clear()
+{
+ mxResult.clear();
+}
+
+Reference<XXPathObject> ComputedExpression::getXPath() const
+{
+ return mxResult;
+}
+
+OUString ComputedExpression::getString( const rtl::OUString& rDefault ) const
+{
+ return mxResult.is() ? mxResult->getString() : rDefault;
+}
+
+bool ComputedExpression::getBool( bool bDefault ) const
+{
+ return mxResult.is() ? mxResult->getBoolean() : bDefault;
+}
+
+
+
+
+Reference<XXPathAPI> ComputedExpression::_getXPathAPI(const xforms::EvaluationContext& aContext)
+{
+ // create XPath API, then register namespaces
+ Reference<XXPathAPI> xXPath( createInstance(
+ OUSTRING( "com.sun.star.xml.xpath.XPathAPI" ) ),
+ UNO_QUERY_THROW );
+ OSL_ENSURE( xXPath.is(), "cannot get XPath API" );
+
+ // register xforms extension#
+ Sequence< Any > aSequence(2);
+ NamedValue aValue;
+ aValue.Name = OUSTRING("Model");
+ aValue.Value <<= aContext.mxModel;
+ aSequence[0] <<= aValue;
+ aValue.Name = OUSTRING("ContextNode");
+ aValue.Value <<= aContext.mxContextNode;
+ aSequence[1] <<= aValue;
+ Reference<XMultiServiceFactory> aFactory = comphelper::getProcessServiceFactory();
+ Reference< XXPathExtension > aExtension( aFactory->createInstanceWithArguments(
+ OUSTRING( "com.sun.star.comp.xml.xpath.XFormsExtension"), aSequence), UNO_QUERY_THROW);
+ xXPath->registerExtensionInstance(aExtension);
+
+ // register namespaces
+ if( aContext.mxNamespaces.is() )
+ {
+ Sequence<OUString> aPrefixes =aContext.mxNamespaces->getElementNames();
+ sal_Int32 nCount = aPrefixes.getLength();
+ const OUString* pPrefixes = aPrefixes.getConstArray();
+ for( sal_Int32 i = 0; i < nCount; i++ )
+ {
+ const OUString* pNamePrefix = &pPrefixes[i];
+ OUString sNameURL;
+ aContext.mxNamespaces->getByName( *pNamePrefix ) >>= sNameURL;
+ xXPath->registerNS( *pNamePrefix, sNameURL );
+ }
+ }
+
+ // done, so return xXPath-object
+ return xXPath;
+}
+
+
+} // namespace xforms
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/computedexpression.hxx b/forms/source/xforms/computedexpression.hxx
new file mode 100644
index 000000000000..528bda5e457f
--- /dev/null
+++ b/forms/source/xforms/computedexpression.hxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _COMPUTEDEXPRESSION_HXX
+#define _COMPUTEDEXPRESSION_HXX
+
+
+// includes for member variables
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+
+// forward declaractions
+namespace com { namespace sun { namespace star
+{
+ namespace xml
+ {
+ namespace dom { class XNode; }
+ namespace dom { class XNodeset; }
+ namespace xpath { class XXPathAPI; }
+ namespace xpath { class XXPathObject; }
+ }
+ namespace container { class XNameContainer; }
+} } }
+namespace xforms { class EvaluationContext; }
+
+
+
+namespace xforms
+{
+
+/** ComputedExpression represents an XPath Expression and caches results.
+ *
+ * As this class has no virtual methods, it should never be used
+ * polymorphically. */
+class ComputedExpression
+{
+ /// the expression string
+ rtl::OUString msExpression;
+
+ /// is msExpression empty?
+ bool mbIsEmpty;
+
+protected:
+ /// is msExpression a simple expression?
+ bool mbIsSimple;
+
+ /// the result from the last bind
+ com::sun::star::uno::Reference<com::sun::star::xml::xpath::XXPathObject> mxResult;
+
+
+ /// implementation of isSimpleExpression
+ bool _checkExpression( const sal_Char* pExpression ) const;
+
+ /// allow manipulation of the expression before it is evaluated
+ const rtl::OUString _getExpressionForEvaluation() const;
+
+ /// obtain a (suitable) XPathAPI implementation
+ com::sun::star::uno::Reference<com::sun::star::xml::xpath::XXPathAPI> _getXPathAPI(const xforms::EvaluationContext& aContext);
+
+ /// evaluate the expression relative to the content node.
+ bool _evaluate( const xforms::EvaluationContext& rContext,
+ const rtl::OUString& sExpression );
+
+
+public:
+ ComputedExpression();
+ ~ComputedExpression();
+
+
+ /// get the expression string
+ rtl::OUString getExpression() const;
+
+ /// set a new expression string
+ void setExpression( const rtl::OUString& rExpression );
+
+ /// get the namespaces that are used to interpret the expression string
+ com::sun::star::uno::Reference<com::sun::star::container::XNameContainer> getNamespaces() const;
+
+ /// set the namespaces that are used to interpret the expression string
+ void setNamespaces( const com::sun::star::uno::Reference<com::sun::star::container::XNameContainer>& );
+
+ /// do we have an actual expression?
+ bool isEmptyExpression() const;
+
+ /// heuristically determine whether this expression is 'simple',
+ /// i.e. whether its value will change depending on the values
+ /// of other nodes
+ bool isSimpleExpression() const;
+
+
+ /// evaluate the expression relative to the content node.
+ bool evaluate( const xforms::EvaluationContext& rContext );
+
+
+ /// does this expression have a value?
+ bool hasValue() const;
+
+
+ /// remove value/evaluate results
+ void clear();
+
+
+ // get the result of this expression as string/bool/...
+ // (Results will be based on the last call of evaluate(..). The caller
+ // must call evaluate to ensure current results.)
+ com::sun::star::uno::Reference<com::sun::star::xml::xpath::XXPathObject> getXPath() const;
+ bool getBool( bool bDefault = false ) const;
+ rtl::OUString getString( const rtl::OUString& rDefault = rtl::OUString() ) const;
+
+};
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/convert.cxx b/forms/source/xforms/convert.cxx
new file mode 100644
index 000000000000..4e7ecbab2561
--- /dev/null
+++ b/forms/source/xforms/convert.cxx
@@ -0,0 +1,630 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "convert.hxx"
+
+#include "unohelper.hxx"
+#include <memory>
+#include <algorithm>
+#include <functional>
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/date.hxx>
+#include <com/sun/star/uno/Type.hxx>
+#include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Time.hpp>
+
+using xforms::Convert;
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::makeAny;
+using com::sun::star::util::Time;
+using namespace std;
+
+typedef com::sun::star::util::Date UNODate;
+typedef com::sun::star::util::Time UNOTime;
+typedef com::sun::star::util::DateTime UNODateTime;
+
+Convert::Convert()
+ : maMap()
+{
+ init();
+}
+
+#define ADD_ENTRY(XCONVERT,TYPE) XCONVERT->maMap[ getCppuType( static_cast<TYPE*>( NULL ) ) ] = Convert_t( &lcl_toXSD_##TYPE, &lcl_toAny_##TYPE )
+
+namespace
+{
+ // ========================================================================
+ struct StringToken
+ {
+ private:
+ ::rtl::OUString m_sString;
+ sal_Int32 m_nTokenStart;
+ sal_Int32 m_nTokenEnd;
+
+ public:
+ StringToken() : m_sString(), m_nTokenStart( 0 ), m_nTokenEnd( 0 ) { }
+ StringToken( const ::rtl::OUString& _rString, sal_Int32 _nTokenStart, sal_Int32 _nTokenEnd );
+ StringToken( const StringToken& );
+ StringToken& operator=( const StringToken& );
+
+ inline bool isEmpty() const { return m_nTokenEnd <= m_nTokenStart; }
+ inline sal_Int32 getLength() const { return isEmpty() ? 0 : m_nTokenEnd - m_nTokenStart - 1; }
+ inline const sal_Unicode* begin() const { return m_sString.getStr() + m_nTokenStart; }
+ inline const sal_Unicode* end() const { return m_sString.getStr() + m_nTokenEnd; }
+
+ bool toInt32( sal_Int32& _rValue ) const;
+ };
+
+ // ------------------------------------------------------------------------
+ StringToken::StringToken( const ::rtl::OUString& _rString, sal_Int32 _nTokenStart, sal_Int32 _nTokenEnd )
+ :m_sString( _rString )
+ ,m_nTokenStart( _nTokenStart )
+ ,m_nTokenEnd( _nTokenEnd )
+ {
+ OSL_ENSURE( ( m_nTokenStart >= 0 ) && ( m_nTokenStart <= m_sString.getLength() ), "StringToken::StringToken: invalid token start!" );
+ OSL_ENSURE( ( m_nTokenEnd >= 0 ) && ( m_nTokenEnd <= m_sString.getLength() ), "StringToken::StringToken: invalid token end!" );
+ }
+
+ // ------------------------------------------------------------------------
+ StringToken::StringToken( const StringToken& _rRHS )
+ {
+ *this = _rRHS;
+ }
+
+ // ------------------------------------------------------------------------
+ StringToken& StringToken::operator=( const StringToken& _rRHS )
+ {
+ if ( this == &_rRHS )
+ return *this;
+
+ m_sString = _rRHS.m_sString;
+ m_nTokenStart = _rRHS.m_nTokenStart;
+ m_nTokenEnd = _rRHS.m_nTokenEnd;
+
+ return *this;
+ }
+
+ // ------------------------------------------------------------------------
+ bool StringToken::toInt32( sal_Int32& _rValue ) const
+ {
+ if ( isEmpty() )
+ return false;
+
+ _rValue = 0;
+ const sal_Unicode* pStr = begin();
+ while ( pStr < end() )
+ {
+ if ( ( *pStr < '0' ) || ( *pStr > '9' ) )
+ return false;
+
+ _rValue *= 10;
+ _rValue += ( *pStr - '0' );
+
+ ++pStr;
+ }
+
+ return true;
+ }
+
+ // ========================================================================
+ class StringTokenizer
+ {
+ private:
+ ::rtl::OUString m_sString;
+ const sal_Unicode m_nTokenSeparator;
+ sal_Int32 m_nTokenStart;
+
+ public:
+ /** constructs a tokenizer
+ @param _rString the string to tokenize
+ @param _nTokenSeparator the token value. May be 0, in this case the tokenizer
+ will recognize exactly one token, being the whole string.
+ This may make sense if you want to apply <type>StringToken</type>
+ methods to a whole string.
+ */
+ StringTokenizer( const ::rtl::OUString& _rString, sal_Unicode _nTokenSeparator = ';' );
+
+ /// resets the tokenizer to the beginning of the string
+ void reset();
+
+ /// determines whether there is a next token
+ bool hasNextToken() const;
+
+ /// retrieves the next token
+ StringToken
+ getNextToken();
+ };
+
+ // ------------------------------------------------------------------------
+ StringTokenizer::StringTokenizer( const ::rtl::OUString& _rString, sal_Unicode _nTokenSeparator )
+ :m_sString( _rString )
+ ,m_nTokenSeparator( _nTokenSeparator )
+ {
+ reset();
+ }
+
+ // ------------------------------------------------------------------------
+ void StringTokenizer::reset()
+ {
+ m_nTokenStart = 0;
+ }
+
+ // ------------------------------------------------------------------------
+ bool StringTokenizer::hasNextToken() const
+ {
+ return ( m_nTokenStart < m_sString.getLength() );
+ }
+
+ // ------------------------------------------------------------------------
+ StringToken StringTokenizer::getNextToken()
+ {
+ OSL_PRECOND( hasNextToken(), "StringTokenizer::getNextToken: there is no next token!" );
+ if ( !hasNextToken() )
+ return StringToken();
+
+ // determine the end of the current token
+ sal_Int32 nTokenEnd = m_nTokenSeparator ? m_sString.indexOf( m_nTokenSeparator, m_nTokenStart ) : m_sString.getLength();
+ bool bLastToken = !m_nTokenSeparator || ( nTokenEnd == -1 );
+
+ // construct a new token
+ StringToken aToken( m_sString, m_nTokenStart, bLastToken ? m_sString.getLength() : nTokenEnd );
+ // advance
+ m_nTokenStart = bLastToken ? m_sString.getLength() : nTokenEnd + 1;
+ // outta here
+ return aToken;
+ }
+
+ // ========================================================================
+ // ------------------------------------------------------------------------
+ OUString lcl_toXSD_OUString( const Any& rAny )
+ { OUString sStr; rAny >>= sStr; return sStr; }
+
+ // ------------------------------------------------------------------------
+ Any lcl_toAny_OUString( const OUString& rStr )
+ { Any aAny; aAny <<= rStr; return aAny; }
+
+ // ------------------------------------------------------------------------
+ OUString lcl_toXSD_bool( const Any& rAny )
+ { bool b = false; rAny >>= b; return b ? OUSTRING("true") : OUSTRING("false"); }
+
+ // ------------------------------------------------------------------------
+ Any lcl_toAny_bool( const OUString& rStr )
+ {
+ bool b = ( rStr == OUSTRING("true") || rStr == OUSTRING("1") );
+ return makeAny( b );
+ }
+
+ // ------------------------------------------------------------------------
+ OUString lcl_toXSD_double( const Any& rAny )
+ {
+ double f = 0.0;
+ rAny >>= f;
+
+ return rtl::math::isFinite( f )
+ ? rtl::math::doubleToUString( f, rtl_math_StringFormat_Automatic,
+ rtl_math_DecimalPlaces_Max, '.',
+ sal_True )
+ : OUString();
+ }
+
+ // ------------------------------------------------------------------------
+ Any lcl_toAny_double( const OUString& rString )
+ {
+ rtl_math_ConversionStatus eStatus;
+ double f = rtl::math::stringToDouble(
+ rString, sal_Unicode('.'), sal_Unicode(','), &eStatus, NULL );
+ return ( eStatus == rtl_math_ConversionStatus_Ok ) ? makeAny( f ) : Any();
+ }
+
+ // ------------------------------------------------------------------------
+ void lcl_appendInt32ToBuffer( const sal_Int32 _nValue, ::rtl::OUStringBuffer& _rBuffer, sal_Int16 _nMinDigits )
+ {
+ if ( ( _nMinDigits >= 4 ) && ( _nValue < 1000 ) )
+ _rBuffer.append( (sal_Unicode)'0' );
+ if ( ( _nMinDigits >= 3 ) && ( _nValue < 100 ) )
+ _rBuffer.append( (sal_Unicode)'0' );
+ if ( ( _nMinDigits >= 2 ) && ( _nValue < 10 ) )
+ _rBuffer.append( (sal_Unicode)'0' );
+ _rBuffer.append( _nValue );
+ }
+
+ // ------------------------------------------------------------------------
+ OUString lcl_toXSD_UNODate_typed( const UNODate& rDate )
+ {
+
+ ::rtl::OUStringBuffer sInfo;
+ lcl_appendInt32ToBuffer( rDate.Year, sInfo, 4 );
+ sInfo.appendAscii( "-" );
+ lcl_appendInt32ToBuffer( rDate.Month, sInfo, 2 );
+ sInfo.appendAscii( "-" );
+ lcl_appendInt32ToBuffer( rDate.Day, sInfo, 2 );
+
+ return sInfo.makeStringAndClear();
+ }
+
+ // ------------------------------------------------------------------------
+ OUString lcl_toXSD_UNODate( const Any& rAny )
+ {
+ UNODate aDate;
+ OSL_VERIFY( rAny >>= aDate );
+ return lcl_toXSD_UNODate_typed( aDate );
+ }
+
+ // ------------------------------------------------------------------------
+ UNODate lcl_toUNODate( const OUString& rString )
+ {
+ bool bWellformed = true;
+
+ UNODate aDate( 1, 1, 1900 );
+
+ sal_Int32 nToken = 0;
+ StringTokenizer aTokenizer( rString, '-' );
+ while ( aTokenizer.hasNextToken() )
+ {
+ sal_Int32 nTokenValue = 0;
+ if ( !aTokenizer.getNextToken().toInt32( nTokenValue ) )
+ {
+ bWellformed = false;
+ break;
+ }
+
+ if ( nToken == 0 )
+ aDate.Year = (sal_uInt16)nTokenValue;
+ else if ( nToken == 1 )
+ aDate.Month = (sal_uInt16)nTokenValue;
+ else if ( nToken == 2 )
+ aDate.Day = (sal_uInt16)nTokenValue;
+ else
+ {
+ bWellformed = false;
+ break;
+ }
+ ++nToken;
+ }
+
+ // sanity checks
+ if ( ( aDate.Year > 9999 ) || ( aDate.Month < 1 ) || ( aDate.Month > 12 ) || ( aDate.Day < 1 ) || ( aDate.Day > 31 ) )
+ bWellformed = false;
+ else
+ {
+ ::Date aDateCheck( 1, aDate.Month, aDate.Year );
+ if ( aDate.Day > aDateCheck.GetDaysInMonth() )
+ bWellformed = false;
+ }
+
+ // all okay?
+ if ( !bWellformed )
+ return UNODate( 1, 1, 1900 );
+
+ return aDate;
+ }
+
+ // ------------------------------------------------------------------------
+ Any lcl_toAny_UNODate( const OUString& rString )
+ {
+ return makeAny( lcl_toUNODate( rString ) );
+ }
+
+ // ------------------------------------------------------------------------
+ OUString lcl_toXSD_UNOTime_typed( const UNOTime& rTime )
+ {
+
+ ::rtl::OUStringBuffer sInfo;
+ lcl_appendInt32ToBuffer( rTime.Hours, sInfo, 2 );
+ sInfo.appendAscii( ":" );
+ lcl_appendInt32ToBuffer( rTime.Minutes, sInfo, 2 );
+ sInfo.appendAscii( ":" );
+ lcl_appendInt32ToBuffer( rTime.Seconds, sInfo, 2 );
+ if ( rTime.HundredthSeconds )
+ {
+ sInfo.appendAscii( "." );
+ lcl_appendInt32ToBuffer( rTime.HundredthSeconds, sInfo, 2 );
+ }
+
+ return sInfo.makeStringAndClear();
+ }
+
+ // ------------------------------------------------------------------------
+ OUString lcl_toXSD_UNOTime( const Any& rAny )
+ {
+ UNOTime aTime;
+ OSL_VERIFY( rAny >>= aTime );
+ return lcl_toXSD_UNOTime_typed( aTime );
+ }
+
+ // ------------------------------------------------------------------------
+ UNOTime lcl_toUNOTime( const OUString& rString )
+ {
+ bool bWellformed = true;
+
+ UNOTime aTime( 0, 0, 0, 0 );
+
+ ::rtl::OUString sString( rString );
+ // see if there's a decimal separator for the seconds,
+ // and if so, handle it separately
+ sal_Int32 nDecimalSepPos = rString.indexOf( '.' );
+ if ( nDecimalSepPos == -1 )
+ // ISO 8601 allows for both a comma and a dot
+ nDecimalSepPos = rString.indexOf( ',' );
+ if ( nDecimalSepPos != -1 )
+ {
+ // handle fractional seconds
+ ::rtl::OUString sFractional = sString.copy( nDecimalSepPos + 1 );
+ if ( sFractional.getLength() > 2 )
+ // our precision is HundrethSeconds - it's all a css.util.Time can hold
+ sFractional = sFractional.copy( 0, 2 );
+ sal_Int32 nFractional = 0;
+ if ( sFractional.getLength() )
+ {
+ if ( StringTokenizer( sFractional, 0 ).getNextToken().toInt32( nFractional ) )
+ {
+ aTime.HundredthSeconds = (sal_uInt16)nFractional;
+ if ( nFractional < 10 )
+ aTime.HundredthSeconds *= 10;
+ }
+ else
+ bWellformed = false;
+ }
+
+ // strip the fraction before further processing
+ sString = sString.copy( 0, nDecimalSepPos );
+ }
+
+ // split into the tokens which are separated by colon
+ sal_Int32 nToken = 0;
+ StringTokenizer aTokenizer( sString, ':' );
+ while ( aTokenizer.hasNextToken() )
+ {
+ sal_Int32 nTokenValue = 0;
+ if ( !aTokenizer.getNextToken().toInt32( nTokenValue ) )
+ {
+ bWellformed = false;
+ break;
+ }
+
+ if ( nToken == 0 )
+ aTime.Hours = (sal_uInt16)nTokenValue;
+ else if ( nToken == 1 )
+ aTime.Minutes = (sal_uInt16)nTokenValue;
+ else if ( nToken == 2 )
+ aTime.Seconds = (sal_uInt16)nTokenValue;
+ else
+ {
+ bWellformed = false;
+ break;
+ }
+ ++nToken;
+ }
+
+ // sanity checks
+ // note that Seconds == 60 denotes leap seconds. Normally, they're not allowed everywhere,
+ // but we accept them all the time for simplicity reasons
+ if ( ( aTime.Hours > 24 )
+ || ( aTime.Minutes > 59 )
+ || ( aTime.Seconds > 60 )
+ )
+ bWellformed = false;
+
+ if ( bWellformed
+ && ( aTime.Hours == 24 )
+ && ( ( aTime.Minutes != 0 )
+ || ( aTime.Seconds != 0 )
+ || ( aTime.HundredthSeconds != 0 )
+ )
+ )
+ bWellformed = false;
+
+ // all okay?
+ if ( !bWellformed )
+ return UNOTime( 0, 0, 0, 0 );
+
+ return aTime;
+ }
+
+ // ------------------------------------------------------------------------
+ Any lcl_toAny_UNOTime( const OUString& rString )
+ {
+ return makeAny( lcl_toUNOTime( rString ) );
+ }
+
+ // ------------------------------------------------------------------------
+ OUString lcl_toXSD_UNODateTime( const Any& rAny )
+ {
+ UNODateTime aDateTime;
+ OSL_VERIFY( rAny >>= aDateTime );
+
+ UNODate aDate( aDateTime.Day, aDateTime.Month, aDateTime.Year );
+ ::rtl::OUString sDate = lcl_toXSD_UNODate_typed( aDate );
+
+ UNOTime aTime( aDateTime.HundredthSeconds, aDateTime.Seconds, aDateTime.Minutes, aDateTime.Hours );
+ ::rtl::OUString sTime = lcl_toXSD_UNOTime_typed( aTime );
+
+ ::rtl::OUStringBuffer sInfo;
+ sInfo.append( sDate );
+ sInfo.append( (sal_Unicode) 'T' );
+ sInfo.append( sTime );
+ return sInfo.makeStringAndClear();
+ }
+
+ // ------------------------------------------------------------------------
+ Any lcl_toAny_UNODateTime( const OUString& rString )
+ {
+ // separate the date from the time part
+ sal_Int32 nDateTimeSep = rString.indexOf( 'T' );
+ if ( nDateTimeSep == -1 )
+ nDateTimeSep = rString.indexOf( 't' );
+
+ UNODate aDate;
+ UNOTime aTime;
+ if ( nDateTimeSep == -1 )
+ { // no time part
+ aDate = lcl_toUNODate( rString );
+ aTime = UNOTime( 0, 0, 0, 0 );
+ }
+ else
+ {
+ aDate = lcl_toUNODate( rString.copy( 0, nDateTimeSep ) );
+ aTime = lcl_toUNOTime( rString.copy( nDateTimeSep + 1 ) );
+ }
+ UNODateTime aDateTime(
+ aTime.HundredthSeconds, aTime.Seconds, aTime.Minutes, aTime.Hours,
+ aDate.Day, aDate.Month, aDate.Year
+ );
+ return makeAny( aDateTime );
+ }
+}
+
+// ============================================================================
+void Convert::init()
+{
+ ADD_ENTRY( this, OUString );
+ ADD_ENTRY( this, bool );
+ ADD_ENTRY( this, double );
+ ADD_ENTRY( this, UNODate );
+ ADD_ENTRY( this, UNOTime );
+ ADD_ENTRY( this, UNODateTime );
+}
+
+
+Convert& Convert::get()
+{
+ // create our Singleton instance on demand
+ static Convert* pConvert = NULL;
+ if( pConvert == NULL )
+ pConvert = new Convert();
+
+ OSL_ENSURE( pConvert != NULL, "no converter?" );
+ return *pConvert;
+}
+
+bool Convert::hasType( const Type_t& rType )
+{
+ return maMap.find( rType ) != maMap.end();
+}
+
+Convert::Types_t Convert::getTypes()
+{
+ Types_t aTypes( maMap.size() );
+ transform( maMap.begin(), maMap.end(), aTypes.getArray(),
+ select1st<Map_t::value_type>() );
+ return aTypes;
+}
+
+rtl::OUString Convert::toXSD( const Any_t& rAny )
+{
+ Map_t::iterator aIter = maMap.find( rAny.getValueType() );
+ return aIter != maMap.end() ? aIter->second.first( rAny ) : OUString();
+}
+
+Convert::Any_t Convert::toAny( const rtl::OUString& rValue,
+ const Type_t& rType )
+{
+ Map_t::iterator aIter = maMap.find( rType );
+ return aIter != maMap.end() ? aIter->second.second( rValue ) : Any_t();
+}
+
+//------------------------------------------------------------------------
+::rtl::OUString Convert::convertWhitespace( const ::rtl::OUString& _rString, sal_Int16 _nWhitespaceTreatment )
+{
+ ::rtl::OUString sConverted;
+ switch( _nWhitespaceTreatment )
+ {
+ default:
+ OSL_ENSURE( sal_False, "Convert::convertWhitespace: invalid whitespace treatment constant!" );
+ // NO break
+ case com::sun::star::xsd::WhiteSpaceTreatment::Preserve:
+ sConverted = _rString;
+ break;
+ case com::sun::star::xsd::WhiteSpaceTreatment::Replace:
+ sConverted = replaceWhitespace( _rString );
+ break;
+ case com::sun::star::xsd::WhiteSpaceTreatment::Collapse:
+ sConverted = collapseWhitespace( _rString );
+ break;
+ }
+ return sConverted;
+}
+
+//------------------------------------------------------------------------
+::rtl::OUString Convert::replaceWhitespace( const ::rtl::OUString& _rString )
+{
+ OUStringBuffer aBuffer( _rString );
+ sal_Int32 nLength = aBuffer.getLength();
+ const sal_Unicode* pBuffer = aBuffer.getStr();
+ for( sal_Int32 i = 0; i < nLength; i++ )
+ {
+ sal_Unicode c = pBuffer[i];
+ if( c == sal_Unicode(0x08) ||
+ c == sal_Unicode(0x0A) ||
+ c == sal_Unicode(0x0D) )
+ aBuffer.setCharAt( i, sal_Unicode(0x20) );
+ }
+ return aBuffer.makeStringAndClear();
+}
+
+//------------------------------------------------------------------------
+::rtl::OUString Convert::collapseWhitespace( const ::rtl::OUString& _rString )
+{
+ sal_Int32 nLength = _rString.getLength();
+ OUStringBuffer aBuffer( nLength );
+ const sal_Unicode* pStr = _rString.getStr();
+ bool bStrip = true;
+ for( sal_Int32 i = 0; i < nLength; i++ )
+ {
+ sal_Unicode c = pStr[i];
+ if( c == sal_Unicode(0x08) ||
+ c == sal_Unicode(0x0A) ||
+ c == sal_Unicode(0x0D) ||
+ c == sal_Unicode(0x20) )
+ {
+ if( ! bStrip )
+ {
+ aBuffer.append( sal_Unicode(0x20) );
+ bStrip = true;
+ }
+ }
+ else
+ {
+ bStrip = false;
+ aBuffer.append( c );
+ }
+ }
+ if( aBuffer[ aBuffer.getLength() - 1 ] == sal_Unicode( 0x20 ) )
+ aBuffer.setLength( aBuffer.getLength() - 1 );
+ return aBuffer.makeStringAndClear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/convert.hxx b/forms/source/xforms/convert.hxx
new file mode 100644
index 000000000000..c2cdaef6c558
--- /dev/null
+++ b/forms/source/xforms/convert.hxx
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _CONVERT_HXX
+#define _CONVERT_HXX
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <map>
+
+namespace com { namespace sun { namespace star { namespace uno
+{
+ class Any;
+ class Type;
+} } } }
+namespace rtl { class OUString; }
+class ConvertImpl;
+
+namespace xforms
+{
+
+struct TypeLess
+{
+ bool operator()( const com::sun::star::uno::Type& rType1,
+ const com::sun::star::uno::Type& rType2 ) const
+ { return rType1.getTypeName() < rType2.getTypeName(); }
+};
+
+class Convert
+{
+ typedef com::sun::star::uno::Type Type_t;
+ typedef com::sun::star::uno::Sequence<com::sun::star::uno::Type> Types_t;
+ typedef com::sun::star::uno::Any Any_t;
+
+ // hold conversion objects
+ typedef rtl::OUString (*fn_toXSD)( const Any_t& );
+ typedef Any_t (*fn_toAny)( const rtl::OUString& );
+ typedef std::pair<fn_toXSD,fn_toAny> Convert_t;
+ typedef std::map<Type_t,Convert_t,TypeLess> Map_t;
+ Map_t maMap;
+
+ Convert();
+
+ void init();
+
+public:
+ /** get/create Singleton class */
+ static Convert& get();
+
+ /// can we convert this type?
+ bool hasType( const Type_t& );
+
+ /// get list of convertable types
+ Types_t getTypes();
+
+ /// convert any to XML representation
+ rtl::OUString toXSD( const Any_t& rAny );
+
+ /// convert XML representation to Any of given type
+ Any_t toAny( const rtl::OUString&, const Type_t& );
+
+ /** translates the whitespaces in a given string, according
+ to a given <type scope="com::sun::star::xsd">WhiteSpaceTreatment</type>.
+
+ @param _rString
+ the string to convert
+ @param _nWhitespaceTreatment
+ a constant from the <type scope="com::sun::star::xsd">WhiteSpaceTreatment</type> group, specifying
+ how to handle whitespaces
+ @return
+ the converted string
+ */
+ static ::rtl::OUString convertWhitespace(
+ const ::rtl::OUString& _rString,
+ sal_Int16 _nWhitespaceTreatment
+ );
+
+ /** replace all occurrences 0x08, 0x0A, 0x0D with 0x20
+ */
+ static ::rtl::OUString replaceWhitespace( const ::rtl::OUString& _rString );
+
+ /** replace all sequences of 0x08, 0x0A, 0x0D, 0x20 with a single 0x20.
+ also strip leading/trailing whitespace.
+ */
+ static ::rtl::OUString collapseWhitespace( const ::rtl::OUString& _rString );
+};
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/datatyperepository.cxx b/forms/source/xforms/datatyperepository.cxx
new file mode 100644
index 000000000000..a4bce7e66db3
--- /dev/null
+++ b/forms/source/xforms/datatyperepository.cxx
@@ -0,0 +1,294 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "datatyperepository.hxx"
+#include "datatypes.hxx"
+#include "frm_resource.hrc"
+#include "frm_resource.hxx"
+#include "frm_strings.hxx"
+#include "property.hrc"
+
+/** === begin UNO includes === **/
+/** === end UNO includes === **/
+#include <tools/debug.hxx>
+#include <comphelper/enumhelper.hxx>
+
+#include <functional>
+#include <algorithm>
+
+//........................................................................
+namespace xforms
+{
+//........................................................................
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::util::VetoException;
+ using ::com::sun::star::container::NoSuchElementException;
+ using ::com::sun::star::container::ElementExistException;
+ using ::com::sun::star::container::XEnumeration;
+ using ::com::sun::star::lang::WrappedTargetException;
+ using ::com::sun::star::xsd::XDataType;
+ using namespace frm;
+
+ //====================================================================
+ //= ODataTypeRepository
+ //====================================================================
+ DBG_NAME( ODataTypeRepository )
+ //--------------------------------------------------------------------
+ ODataTypeRepository::ODataTypeRepository( )
+ {
+ DBG_CTOR( ODataTypeRepository, NULL );
+
+ // insert some basic types
+ ::rtl::OUString sName( FRM_RES_STRING( RID_STR_DATATYPE_STRING ) );
+ m_aRepository[ sName ] = new OStringType( sName, ::com::sun::star::xsd::DataTypeClass::STRING );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_URL );
+ m_aRepository[ sName ] = new OStringType( sName, ::com::sun::star::xsd::DataTypeClass::anyURI );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_BOOLEAN );
+ m_aRepository[ sName ] = new OBooleanType( sName );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_DECIMAL );
+ m_aRepository[ sName ] = new ODecimalType( sName, ::com::sun::star::xsd::DataTypeClass::DECIMAL );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_FLOAT );
+ m_aRepository[ sName ] = new ODecimalType( sName, ::com::sun::star::xsd::DataTypeClass::FLOAT );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_DOUBLE );
+ m_aRepository[ sName ] = new ODecimalType( sName, ::com::sun::star::xsd::DataTypeClass::DOUBLE );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_DATE );
+ m_aRepository[ sName ] = new ODateType( sName );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_TIME );
+ m_aRepository[ sName ] = new OTimeType( sName );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_DATETIME );
+ m_aRepository[ sName ] = new ODateTimeType( sName );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_YEAR );
+ m_aRepository[ sName ] = new OShortIntegerType( sName, ::com::sun::star::xsd::DataTypeClass::gYear );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_MONTH );
+ m_aRepository[ sName ] = new OShortIntegerType( sName, ::com::sun::star::xsd::DataTypeClass::gMonth );
+
+ sName = FRM_RES_STRING( RID_STR_DATATYPE_DAY );
+ m_aRepository[ sName ] = new OShortIntegerType( sName, ::com::sun::star::xsd::DataTypeClass::gDay );
+ }
+
+ //--------------------------------------------------------------------
+ ODataTypeRepository::~ODataTypeRepository( )
+ {
+ DBG_DTOR( ODataTypeRepository, NULL );
+ }
+
+ //--------------------------------------------------------------------
+ ODataTypeRepository::Repository::iterator ODataTypeRepository::implLocate( const ::rtl::OUString& _rName, bool _bAllowMiss ) SAL_THROW( ( NoSuchElementException ) )
+ {
+ Repository::iterator aTypePos = m_aRepository.find( _rName );
+ if ( aTypePos == m_aRepository.end() && !_bAllowMiss )
+ throw NoSuchElementException( ::rtl::OUString(), *this );
+
+ return aTypePos;
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XDataType > SAL_CALL ODataTypeRepository::getBasicDataType( sal_Int16 dataTypeClass ) throw (NoSuchElementException, RuntimeException)
+ {
+ Reference< XDataType > xReturn;
+
+ for ( Repository::const_iterator lookup = m_aRepository.begin();
+ ( lookup != m_aRepository.end() ) && ! xReturn.is();
+ ++lookup
+ )
+ {
+ if ( lookup->second->getIsBasic() && ( lookup->second->getTypeClass() == dataTypeClass ) )
+ xReturn = lookup->second.get();
+ }
+
+ if ( !xReturn.is() )
+ throw NoSuchElementException( ::rtl::OUString(), *this );
+
+ return xReturn;
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XDataType > SAL_CALL ODataTypeRepository::cloneDataType( const ::rtl::OUString& sourceName, const ::rtl::OUString& newName ) throw (NoSuchElementException, ElementExistException, RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Repository::iterator aTypePos = implLocate( newName, true );
+ if ( aTypePos != m_aRepository.end() )
+ throw ElementExistException( ::rtl::OUString(), *this );
+
+ aTypePos = implLocate( sourceName );
+ OXSDDataType* pClone = aTypePos->second->clone( newName );
+ m_aRepository[ newName ] = pClone;
+
+ return pClone;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL ODataTypeRepository::revokeDataType( const ::rtl::OUString& typeName ) throw (NoSuchElementException, VetoException, RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Repository::iterator aTypePos = implLocate( typeName );
+ if ( aTypePos->second->getIsBasic() )
+ throw VetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "This is a built-in type and cannot be removed." ) ), *this );
+ // TODO: localize this error message
+
+ m_aRepository.erase( aTypePos );
+ }
+
+ //--------------------------------------------------------------------
+ Reference< XDataType > SAL_CALL ODataTypeRepository::getDataType( const ::rtl::OUString& typeName ) throw (NoSuchElementException, RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return implLocate( typeName, false )->second.get();
+ }
+
+
+ //--------------------------------------------------------------------
+ Reference< XEnumeration > SAL_CALL ODataTypeRepository::createEnumeration( ) throw (RuntimeException)
+ {
+ return new ::comphelper::OEnumerationByName( this );
+ }
+
+ //--------------------------------------------------------------------
+ Any SAL_CALL ODataTypeRepository::getByName( const ::rtl::OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
+ {
+ return makeAny( getDataType( aName ) );
+ }
+
+ //--------------------------------------------------------------------
+ Sequence< ::rtl::OUString > SAL_CALL ODataTypeRepository::getElementNames( ) throw (RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Sequence< ::rtl::OUString > aNames( m_aRepository.size() );
+ ::std::transform(
+ m_aRepository.begin(),
+ m_aRepository.end(),
+ aNames.getArray(),
+ ::std::select1st< Repository::value_type >()
+ );
+ return aNames;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool SAL_CALL ODataTypeRepository::hasByName( const ::rtl::OUString& aName ) throw (RuntimeException)
+ {
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return m_aRepository.find( aName ) != m_aRepository.end();
+ }
+
+ //--------------------------------------------------------------------
+ Type SAL_CALL ODataTypeRepository::getElementType( ) throw (RuntimeException)
+ {
+ return ::getCppuType( static_cast< Reference< XDataType >* >( NULL ) );
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool SAL_CALL ODataTypeRepository::hasElements( ) throw (RuntimeException)
+ {
+ return !m_aRepository.empty();
+ }
+
+ //--------------------------------------------------------------------
+ // type specific implementation of registerProperties, using explicit
+ // template instantiations
+
+ template<>
+ void OValueLimitedType<com::sun::star::util::Date>::registerProperties()
+ {
+ OValueLimitedType_Base::registerProperties();
+
+ REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_DATE, m_aMaxInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_DATE, m_aMaxExclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_DATE, m_aMinInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_DATE, m_aMinExclusive, ValueType );
+ }
+
+ template<>
+ void OValueLimitedType<com::sun::star::util::Time>::registerProperties()
+ {
+ OValueLimitedType_Base::registerProperties();
+
+ REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_TIME, m_aMaxInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_TIME, m_aMaxExclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_TIME, m_aMinInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_TIME, m_aMinExclusive, ValueType );
+ }
+
+ template<>
+ void OValueLimitedType<com::sun::star::util::DateTime>::registerProperties()
+ {
+ OValueLimitedType_Base::registerProperties();
+
+ REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_DATE_TIME, m_aMaxInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_DATE_TIME, m_aMaxExclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_DATE_TIME, m_aMinInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_DATE_TIME, m_aMinExclusive, ValueType );
+ }
+
+ template<>
+ void OValueLimitedType<double>::registerProperties()
+ {
+ OValueLimitedType_Base::registerProperties();
+
+ REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_DOUBLE, m_aMaxInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_DOUBLE, m_aMaxExclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_DOUBLE, m_aMinInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_DOUBLE, m_aMinExclusive, ValueType );
+ }
+
+ template<>
+ void OValueLimitedType<sal_Int16>::registerProperties()
+ {
+ OValueLimitedType_Base::registerProperties();
+
+ REGISTER_VOID_PROP( XSD_MAX_INCLUSIVE_INT, m_aMaxInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MAX_EXCLUSIVE_INT, m_aMaxExclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_INCLUSIVE_INT, m_aMinInclusive, ValueType );
+ REGISTER_VOID_PROP( XSD_MIN_EXCLUSIVE_INT, m_aMinExclusive, ValueType );
+ }
+//........................................................................
+} // namespace xforms
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/datatyperepository.hxx b/forms/source/xforms/datatyperepository.hxx
new file mode 100644
index 000000000000..e2f61cdaaf35
--- /dev/null
+++ b/forms/source/xforms/datatyperepository.hxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef OFFAPI_COM_SUN_STAR_XFORMS_DATATYPEREPOSITORY_HXX
+#define OFFAPI_COM_SUN_STAR_XFORMS_DATATYPEREPOSITORY_HXX
+
+/** === begin UNO includes === **/
+#include <com/sun/star/xforms/XDataTypeRepository.hpp>
+/** === end UNO includes === **/
+#include <cppuhelper/implbase1.hxx>
+#include <rtl/ref.hxx>
+
+#include <map>
+
+//........................................................................
+namespace xforms
+{
+//........................................................................
+
+ class OXSDDataType;
+ //====================================================================
+ //= ODataTypeRepository
+ //====================================================================
+ typedef ::cppu::WeakImplHelper1 < ::com::sun::star::xforms::XDataTypeRepository
+ > ODataTypeRepository_Base;
+ class ODataTypeRepository : public ODataTypeRepository_Base
+ {
+ private:
+ typedef ::rtl::Reference< OXSDDataType > DataType;
+ typedef ::std::map< ::rtl::OUString, DataType > Repository;
+
+ ::osl::Mutex m_aMutex;
+ Repository m_aRepository;
+
+ public:
+ ODataTypeRepository( );
+
+ protected:
+ ~ODataTypeRepository( );
+
+ // XDataTypeRepository
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::xsd::XDataType > SAL_CALL getBasicDataType( sal_Int16 dataTypeClass ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::xsd::XDataType > SAL_CALL cloneDataType( const ::rtl::OUString& sourceName, const ::rtl::OUString& newName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL revokeDataType( const ::rtl::OUString& typeName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::util::VetoException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::xsd::XDataType > SAL_CALL getDataType( const ::rtl::OUString& typeName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
+
+ // XEnumerationAccess (base of XDataTypeRepository)
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration( ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XNameAccess (base of XDataTypeRepository)
+ virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XElementAccess (base of XEnumerationAccess and XNameAccess)
+ virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException);
+
+ private:
+ ODataTypeRepository( const ODataTypeRepository& ); // never implemented
+ ODataTypeRepository& operator=( const ODataTypeRepository& ); // never implemented
+
+ private:
+ /** locates the type with the given name in our repository, or throws an exception if there is no such type
+ */
+ Repository::iterator implLocate( const ::rtl::OUString& _rName, bool _bAllowMiss = false ) SAL_THROW( ( ::com::sun::star::container::NoSuchElementException ) );
+ };
+
+//........................................................................
+} // namespace xforms
+//........................................................................
+
+#endif // OFFAPI_COM_SUN_STAR_XFORMS_DATATYPEREPOSITORY_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/datatypes.cxx b/forms/source/xforms/datatypes.cxx
new file mode 100644
index 000000000000..329e65b76cc8
--- /dev/null
+++ b/forms/source/xforms/datatypes.cxx
@@ -0,0 +1,993 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+#include "datatypes.hxx"
+#include "resourcehelper.hxx"
+#include "property.hrc"
+#include "convert.hxx"
+
+#include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
+#include <tools/debug.hxx>
+#include <tools/datetime.hxx>
+#include <rtl/math.hxx>
+
+//........................................................................
+namespace xforms
+{
+//........................................................................
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::util::VetoException;
+ using ::com::sun::star::util::Date;
+ using ::com::sun::star::util::Time;
+ using ::com::sun::star::util::DateTime;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ using ::com::sun::star::lang::WrappedTargetException;
+ using ::com::sun::star::beans::UnknownPropertyException;
+ using ::com::sun::star::beans::PropertyVetoException;
+ using ::com::sun::star::beans::XPropertyChangeListener;
+ using ::com::sun::star::beans::XVetoableChangeListener;
+
+ using ::com::sun::star::beans::PropertyAttribute::BOUND;
+ using ::com::sun::star::beans::PropertyAttribute::READONLY;
+
+ using namespace ::com::sun::star::xsd;
+ using namespace ::frm;
+ U_NAMESPACE_USE
+
+ //====================================================================
+ //= OXSDDataType
+ //====================================================================
+ //--------------------------------------------------------------------
+ OXSDDataType::OXSDDataType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass )
+ :OXSDDataType_PBase( m_aBHelper )
+ ,m_bIsBasic( sal_True )
+ ,m_nTypeClass( _nTypeClass )
+ ,m_sName( _rName )
+ ,m_nWST( WhiteSpaceTreatment::Preserve )
+ ,m_bPatternMatcherDirty( true )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ OXSDDataType::~OXSDDataType()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void OXSDDataType::registerProperties()
+ {
+ registerProperty( PROPERTY_NAME, PROPERTY_ID_NAME, BOUND, &m_sName, ::getCppuType( &m_sName ) );
+ registerProperty( PROPERTY_XSD_WHITESPACE, PROPERTY_ID_XSD_WHITESPACE, BOUND, &m_nWST, ::getCppuType( &m_nWST ) );
+ registerProperty( PROPERTY_XSD_PATTERN, PROPERTY_ID_XSD_PATTERN, BOUND, &m_sPattern, ::getCppuType( &m_sPattern ) );
+
+ registerProperty( PROPERTY_XSD_IS_BASIC, PROPERTY_ID_XSD_IS_BASIC, READONLY, &m_bIsBasic, ::getCppuType( &m_bIsBasic ) );
+ registerProperty( PROPERTY_XSD_TYPE_CLASS, PROPERTY_ID_XSD_TYPE_CLASS, READONLY, &m_nTypeClass, ::getCppuType( &m_nTypeClass ) );
+ }
+
+ //--------------------------------------------------------------------
+ void OXSDDataType::initializeClone( const OXSDDataType& _rCloneSource )
+ {
+ m_bIsBasic = sal_False;
+ m_nTypeClass = _rCloneSource.m_nTypeClass;
+ m_sPattern = _rCloneSource.m_sPattern;
+ m_nWST = _rCloneSource.m_nWST;
+ }
+
+ //--------------------------------------------------------------------
+ OXSDDataType* OXSDDataType::clone( const ::rtl::OUString& _rNewName ) const
+ {
+ OXSDDataType* pClone = createClone( _rNewName );
+ pClone->initializeClone( *this );
+ return pClone;
+ }
+
+ //--------------------------------------------------------------------
+ IMPLEMENT_FORWARD_XINTERFACE2( OXSDDataType, OXSDDataType_Base, ::comphelper::OPropertyContainer )
+
+ //--------------------------------------------------------------------
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( OXSDDataType, OXSDDataType_Base, ::comphelper::OPropertyContainer )
+
+#define SET_PROPERTY( propertyid, value, member ) \
+ setFastPropertyValue( PROPERTY_ID_##propertyid, makeAny( value ) ); \
+ OSL_POSTCOND( member == value, "OXSDDataType::setFoo: inconsistency!" );
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString SAL_CALL OXSDDataType::getName( ) throw (RuntimeException)
+ {
+ return m_sName;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::setName( const ::rtl::OUString& aName ) throw (RuntimeException, VetoException)
+ {
+ // TODO: check the name for conflicts in the repository
+ SET_PROPERTY( NAME, aName, m_sName );
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString SAL_CALL OXSDDataType::getPattern() throw (RuntimeException)
+ {
+ return m_sPattern;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::setPattern( const ::rtl::OUString& _pattern ) throw (RuntimeException)
+ {
+ SET_PROPERTY( XSD_PATTERN, _pattern, m_sPattern );
+ }
+
+ //--------------------------------------------------------------------
+ sal_Int16 SAL_CALL OXSDDataType::getWhiteSpaceTreatment() throw (RuntimeException)
+ {
+ return m_nWST;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::setWhiteSpaceTreatment( sal_Int16 _whitespacetreatment ) throw (RuntimeException, IllegalArgumentException)
+ {
+ SET_PROPERTY( XSD_WHITESPACE, _whitespacetreatment, m_nWST );
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool SAL_CALL OXSDDataType::getIsBasic() throw (RuntimeException)
+ {
+ return m_bIsBasic;
+ }
+
+
+ //--------------------------------------------------------------------
+ sal_Int16 SAL_CALL OXSDDataType::getTypeClass() throw (RuntimeException)
+ {
+ return m_nTypeClass;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool OXSDDataType::validate( const ::rtl::OUString& sValue ) throw( RuntimeException )
+ {
+ return ( _validate( sValue ) == 0 );
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString OXSDDataType::explainInvalid( const ::rtl::OUString& sValue ) throw( RuntimeException )
+ {
+ // get reason
+ sal_uInt16 nReason = _validate( sValue );
+
+ // get resource and return localized string
+ return ( nReason == 0 )
+ ? ::rtl::OUString()
+ : getResource( nReason, sValue,
+ _explainInvalid( nReason ) );
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString OXSDDataType::_explainInvalid( sal_uInt16 nReason )
+ {
+ if ( RID_STR_XFORMS_PATTERN_DOESNT_MATCH == nReason )
+ {
+ OSL_ENSURE( m_sPattern.getLength(), "OXSDDataType::_explainInvalid: how can this error occur without a regular expression?" );
+ return m_sPattern;
+ }
+ return ::rtl::OUString();
+ }
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ static void lcl_initializePatternMatcher( ::std::auto_ptr< RegexMatcher >& _rpMatcher, const ::rtl::OUString& _rPattern )
+ {
+ UErrorCode nMatchStatus = U_ZERO_ERROR;
+ UnicodeString aIcuPattern( reinterpret_cast<const UChar *>(_rPattern.getStr()), _rPattern.getLength() ); // UChar != sal_Unicode in MinGW
+ _rpMatcher.reset( new RegexMatcher( aIcuPattern, 0, nMatchStatus ) );
+ OSL_ENSURE( U_SUCCESS( nMatchStatus ), "lcl_initializePatternMatcher: invalid pattern property!" );
+ // if asserts, then something changed our pattern without going to convertFastPropertyValue/checkPropertySanity
+ }
+
+ static bool lcl_matchString( RegexMatcher& _rMatcher, const ::rtl::OUString& _rText )
+ {
+ UErrorCode nMatchStatus = U_ZERO_ERROR;
+ UnicodeString aInput( reinterpret_cast<const UChar *>(_rText.getStr()), _rText.getLength() ); // UChar != sal_Unicode in MinGW
+ _rMatcher.reset( aInput );
+ if ( _rMatcher.matches( nMatchStatus ) )
+ {
+ int32_t nStart = _rMatcher.start( nMatchStatus );
+ int32_t nEnd = _rMatcher.end ( nMatchStatus );
+ if ( ( nStart == 0 ) && ( nEnd == _rText.getLength() ) )
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ sal_uInt16 OXSDDataType::_validate( const ::rtl::OUString& _rValue )
+ {
+ // care for the whitespaces
+ ::rtl::OUString sConverted = Convert::convertWhitespace( _rValue, m_nWST );
+
+ // care for the regular expression
+ if ( m_sPattern.getLength() )
+ {
+ // ensure our pattern matcher is up to date
+ if ( m_bPatternMatcherDirty )
+ {
+ lcl_initializePatternMatcher( m_pPatternMatcher, m_sPattern );
+ m_bPatternMatcherDirty = false;
+ }
+
+ // let it match the string
+ if ( !lcl_matchString( *m_pPatternMatcher.get(), _rValue ) )
+ return RID_STR_XFORMS_PATTERN_DOESNT_MATCH;
+ }
+
+ return 0;
+ }
+
+ //--------------------------------------------------------------------
+ sal_Bool OXSDDataType::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw(IllegalArgumentException)
+ {
+ // let the base class do the conversion
+ if ( !OXSDDataType_PBase::convertFastPropertyValue( _rConvertedValue, _rOldValue, _nHandle, _rValue ) )
+ return sal_False;
+
+ // sanity checks
+ ::rtl::OUString sErrorMessage;
+ if ( !checkPropertySanity( _nHandle, _rConvertedValue, sErrorMessage ) )
+ {
+ IllegalArgumentException aException;
+ aException.Message = sErrorMessage;
+ aException.Context = *this;
+ throw IllegalArgumentException( aException );
+ }
+
+ return sal_True;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception)
+ {
+ OXSDDataType_PBase::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
+ if ( _nHandle == PROPERTY_ID_XSD_PATTERN )
+ m_bPatternMatcherDirty = true;
+ }
+
+ //--------------------------------------------------------------------
+ bool OXSDDataType::checkPropertySanity( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, ::rtl::OUString& _rErrorMessage )
+ {
+ if ( _nHandle == PROPERTY_ID_XSD_PATTERN )
+ {
+ ::rtl::OUString sPattern;
+ OSL_VERIFY( _rNewValue >>= sPattern );
+
+ UnicodeString aIcuPattern( reinterpret_cast<const UChar *>(sPattern.getStr()), sPattern.getLength() ); // UChar != sal_Unicode in MinGW
+ UErrorCode nMatchStatus = U_ZERO_ERROR;
+ RegexMatcher aMatcher( aIcuPattern, 0, nMatchStatus );
+ if ( U_FAILURE( nMatchStatus ) )
+ {
+ _rErrorMessage = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "This is no valid pattern." ) );
+ return false;
+ }
+ }
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::setPropertyValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+ {
+ OXSDDataType_PBase::setPropertyValue( aPropertyName, aValue );
+ }
+
+ //--------------------------------------------------------------------
+ Any SAL_CALL OXSDDataType::getPropertyValue( const ::rtl::OUString& PropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ return OXSDDataType_PBase::getPropertyValue( PropertyName );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ OXSDDataType_PBase::addPropertyChangeListener( aPropertyName, xListener );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ OXSDDataType_PBase::removePropertyChangeListener( aPropertyName, aListener );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::addVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ OXSDDataType_PBase::addVetoableChangeListener( PropertyName, aListener );
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OXSDDataType::removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
+ {
+ OXSDDataType_PBase::removeVetoableChangeListener( PropertyName, aListener );
+ }
+
+ //====================================================================
+ //= OValueLimitedType_Base
+ //====================================================================
+ OValueLimitedType_Base::OValueLimitedType_Base( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass )
+ :OXSDDataType( _rName, _nTypeClass )
+ ,m_fCachedMaxInclusive( 0 )
+ ,m_fCachedMaxExclusive( 0 )
+ ,m_fCachedMinInclusive( 0 )
+ ,m_fCachedMinExclusive( 0 )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void OValueLimitedType_Base::initializeClone( const OXSDDataType& _rCloneSource )
+ {
+ OXSDDataType::initializeClone( _rCloneSource );
+ initializeTypedClone( static_cast< const OValueLimitedType_Base& >( _rCloneSource ) );
+ }
+
+ //--------------------------------------------------------------------
+ void OValueLimitedType_Base::initializeTypedClone( const OValueLimitedType_Base& _rCloneSource )
+ {
+ m_aMaxInclusive = _rCloneSource.m_aMaxInclusive;
+ m_aMaxExclusive = _rCloneSource.m_aMaxExclusive;
+ m_aMinInclusive = _rCloneSource.m_aMinInclusive;
+ m_aMinExclusive = _rCloneSource.m_aMinExclusive;
+ m_fCachedMaxInclusive = _rCloneSource.m_fCachedMaxInclusive;
+ m_fCachedMaxExclusive = _rCloneSource.m_fCachedMaxExclusive;
+ m_fCachedMinInclusive = _rCloneSource.m_fCachedMinInclusive;
+ m_fCachedMinExclusive = _rCloneSource.m_fCachedMinExclusive;
+ }
+
+ //--------------------------------------------------------------------
+ void SAL_CALL OValueLimitedType_Base::setFastPropertyValue_NoBroadcast(
+ sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::uno::Exception)
+ {
+ OXSDDataType::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
+
+ // if one of our limit properties has been set, translate it into a double
+ // value, for later efficient validation
+ switch ( _nHandle )
+ {
+ case PROPERTY_ID_XSD_MAX_INCLUSIVE_INT:
+ case PROPERTY_ID_XSD_MAX_INCLUSIVE_DOUBLE:
+ case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE:
+ case PROPERTY_ID_XSD_MAX_INCLUSIVE_TIME:
+ case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE_TIME:
+ if ( m_aMaxInclusive.hasValue() )
+ normalizeValue( m_aMaxInclusive, m_fCachedMaxInclusive );
+ else
+ m_fCachedMaxInclusive = 0;
+ break;
+ case PROPERTY_ID_XSD_MAX_EXCLUSIVE_INT:
+ case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DOUBLE:
+ case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE:
+ case PROPERTY_ID_XSD_MAX_EXCLUSIVE_TIME:
+ case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE_TIME:
+ if ( m_aMaxExclusive.hasValue() )
+ normalizeValue( m_aMaxExclusive, m_fCachedMaxExclusive );
+ else
+ m_fCachedMaxExclusive = 0;
+ break;
+ case PROPERTY_ID_XSD_MIN_INCLUSIVE_INT:
+ case PROPERTY_ID_XSD_MIN_INCLUSIVE_DOUBLE:
+ case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE:
+ case PROPERTY_ID_XSD_MIN_INCLUSIVE_TIME:
+ case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE_TIME:
+ if ( m_aMinInclusive.hasValue() )
+ normalizeValue( m_aMinInclusive, m_fCachedMinInclusive );
+ else
+ m_fCachedMinInclusive = 0;
+ break;
+ case PROPERTY_ID_XSD_MIN_EXCLUSIVE_INT:
+ case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DOUBLE:
+ case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE:
+ case PROPERTY_ID_XSD_MIN_EXCLUSIVE_TIME:
+ case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE_TIME:
+ if ( m_aMinExclusive.hasValue() )
+ normalizeValue( m_aMinExclusive, m_fCachedMinExclusive );
+ else
+ m_fCachedMinExclusive = 0;
+ break;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ bool OValueLimitedType_Base::_getValue( const ::rtl::OUString& rValue, double& fValue )
+ {
+ // convert to double
+ rtl_math_ConversionStatus eStatus;
+ sal_Int32 nEnd;
+ double f = ::rtl::math::stringToDouble(
+ rValue, sal_Unicode('.'), sal_Unicode(0), &eStatus, &nEnd );
+
+ // error checking...
+ bool bReturn = false;
+ if( eStatus == rtl_math_ConversionStatus_Ok
+ && nEnd == rValue.getLength() )
+ {
+ bReturn = true;
+ fValue = f;
+ }
+ return bReturn;
+ }
+
+ //--------------------------------------------------------------------
+ sal_uInt16 OValueLimitedType_Base::_validate( const ::rtl::OUString& rValue )
+ {
+ sal_uInt16 nReason = OXSDDataType::_validate( rValue );
+ if( nReason == 0 )
+ {
+
+ // convert value and check format
+ double f;
+ if( ! _getValue( rValue, f ) )
+ nReason = RID_STR_XFORMS_VALUE_IS_NOT_A;
+
+ // check range
+ else if( ( m_aMaxInclusive.hasValue() ) && f > m_fCachedMaxInclusive )
+ nReason = RID_STR_XFORMS_VALUE_MAX_INCL;
+ else if( ( m_aMaxExclusive.hasValue() ) && f >= m_fCachedMaxExclusive )
+ nReason = RID_STR_XFORMS_VALUE_MAX_EXCL;
+ else if( ( m_aMinInclusive.hasValue() ) && f < m_fCachedMinInclusive )
+ nReason = RID_STR_XFORMS_VALUE_MIN_INCL;
+ else if( ( m_aMinExclusive.hasValue() ) && f <= m_fCachedMinExclusive )
+ nReason = RID_STR_XFORMS_VALUE_MIN_EXCL;
+ }
+ return nReason;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString OValueLimitedType_Base::_explainInvalid( sal_uInt16 nReason )
+ {
+ ::rtl::OUStringBuffer sInfo;
+ switch( nReason )
+ {
+ case 0:
+ // nothing to do!
+ break;
+
+ case RID_STR_XFORMS_VALUE_IS_NOT_A:
+ sInfo.append( getName() );
+ break;
+
+ case RID_STR_XFORMS_VALUE_MAX_INCL:
+ sInfo.append( typedValueAsHumanReadableString( m_aMaxInclusive ) );
+ break;
+
+ case RID_STR_XFORMS_VALUE_MAX_EXCL:
+ sInfo.append( typedValueAsHumanReadableString( m_aMaxExclusive ) );
+ break;
+
+ case RID_STR_XFORMS_VALUE_MIN_INCL:
+ sInfo.append( typedValueAsHumanReadableString( m_aMinInclusive ) );
+ break;
+
+ case RID_STR_XFORMS_VALUE_MIN_EXCL:
+ sInfo.append( typedValueAsHumanReadableString( m_aMinExclusive ) );
+ break;
+
+ default:
+ OSL_ENSURE( false, "OValueLimitedType::_explainInvalid: unknown reason!" );
+ break;
+ }
+
+ return sInfo.makeStringAndClear();
+ }
+
+ //====================================================================
+ //= OStringType
+ //====================================================================
+ //--------------------------------------------------------------------
+ OStringType::OStringType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass )
+ :OStringType_Base( _rName, _nTypeClass )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ void OStringType::registerProperties()
+ {
+ OStringType_Base::registerProperties();
+
+ REGISTER_VOID_PROP( XSD_LENGTH, m_aLength, sal_Int32 );
+ REGISTER_VOID_PROP( XSD_MIN_LENGTH, m_aMinLength, sal_Int32 );
+ REGISTER_VOID_PROP( XSD_MAX_LENGTH, m_aMaxLength, sal_Int32 );
+ }
+
+ //--------------------------------------------------------------------
+ IMPLEMENT_DEFAULT_TYPED_CLONING( OStringType, OStringType_Base )
+
+ //--------------------------------------------------------------------
+ void OStringType::initializeTypedClone( const OStringType& _rCloneSource )
+ {
+ m_aLength = _rCloneSource.m_aLength;
+ m_aMinLength = _rCloneSource.m_aMinLength;
+ m_aMaxLength = _rCloneSource.m_aMaxLength;
+ }
+
+ //--------------------------------------------------------------------
+ bool OStringType::checkPropertySanity( sal_Int32 _nHandle, const Any& _rNewValue, ::rtl::OUString& _rErrorMessage )
+ {
+ // let the base class do the conversion
+ if ( !OStringType_Base::checkPropertySanity( _nHandle, _rNewValue, _rErrorMessage ) )
+ return false;
+
+ _rErrorMessage = ::rtl::OUString();
+ switch ( _nHandle )
+ {
+ case PROPERTY_ID_XSD_LENGTH:
+ case PROPERTY_ID_XSD_MIN_LENGTH:
+ case PROPERTY_ID_XSD_MAX_LENGTH:
+ {
+ sal_Int32 nValue( 0 );
+ OSL_VERIFY( _rNewValue >>= nValue );
+ if ( nValue <= 0 )
+ _rErrorMessage = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Length limits must denote positive integer values." ) );
+ // TODO/eforms: localize the error message
+ }
+ break;
+ }
+
+ return _rErrorMessage.getLength() == 0;
+ }
+
+ //--------------------------------------------------------------------
+ sal_uInt16 OStringType::_validate( const ::rtl::OUString& rValue )
+ {
+ // check regexp, whitespace etc. in parent class
+ sal_uInt16 nReason = OStringType_Base::_validate( rValue );
+
+ if( nReason == 0 )
+ {
+ // check string constraints
+ sal_Int32 nLength = rValue.getLength();
+ sal_Int32 nLimit = 0;
+ if ( m_aLength >>= nLimit )
+ {
+ if ( nLimit != nLength )
+ nReason = RID_STR_XFORMS_VALUE_LENGTH;
+ }
+ else
+ {
+ if ( ( m_aMaxLength >>= nLimit ) && ( nLength > nLimit ) )
+ nReason = RID_STR_XFORMS_VALUE_MAX_LENGTH;
+ else if ( ( m_aMinLength >>= nLimit ) && ( nLength < nLimit ) )
+ nReason = RID_STR_XFORMS_VALUE_MIN_LENGTH;
+ }
+ }
+ return nReason;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString OStringType::_explainInvalid( sal_uInt16 nReason )
+ {
+ sal_Int32 nValue = 0;
+ ::rtl::OUStringBuffer sInfo;
+ switch( nReason )
+ {
+ case 0:
+ // nothing to do!
+ break;
+
+ case RID_STR_XFORMS_VALUE_LENGTH:
+ if( m_aLength >>= nValue )
+ sInfo.append( nValue );
+ break;
+
+ case RID_STR_XFORMS_VALUE_MAX_LENGTH:
+ if( m_aMaxLength >>= nValue )
+ sInfo.append( nValue );
+ break;
+
+ case RID_STR_XFORMS_VALUE_MIN_LENGTH:
+ if( m_aMinLength >>= nValue )
+ sInfo.append( nValue );
+ break;
+
+ default:
+ sInfo.append( OStringType_Base::_explainInvalid( nReason ) );
+ break;
+ }
+ return sInfo.makeStringAndClear();
+ }
+
+ //====================================================================
+ //= OBooleanType
+ //====================================================================
+ //--------------------------------------------------------------------
+ OBooleanType::OBooleanType( const ::rtl::OUString& _rName )
+ :OBooleanType_Base( _rName, DataTypeClass::BOOLEAN )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ IMPLEMENT_DEFAULT_CLONING( OBooleanType, OBooleanType_Base )
+
+ //--------------------------------------------------------------------
+ void OBooleanType::initializeTypedClone( const OBooleanType& /*_rCloneSource*/ )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ sal_uInt16 OBooleanType::_validate( const ::rtl::OUString& sValue )
+ {
+ sal_uInt16 nInvalidityReason = OBooleanType_Base::_validate( sValue );
+ if ( nInvalidityReason )
+ return nInvalidityReason;
+
+ bool bValid =
+ sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("0")) ||
+ sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("1")) ||
+ sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("true")) ||
+ sValue.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("false"));
+ return bValid ? 0 : RID_STR_XFORMS_INVALID_VALUE;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString OBooleanType::_explainInvalid( sal_uInt16 nReason )
+ {
+ return ( nReason == 0 ) ? ::rtl::OUString() : getName();
+ }
+
+ //====================================================================
+ //= ODecimalType
+ //====================================================================
+ //--------------------------------------------------------------------
+ ODecimalType::ODecimalType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass )
+ :ODecimalType_Base( _rName, _nTypeClass )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ IMPLEMENT_DEFAULT_TYPED_CLONING( ODecimalType, ODecimalType_Base )
+
+ //--------------------------------------------------------------------
+ void ODecimalType::initializeTypedClone( const ODecimalType& _rCloneSource )
+ {
+ m_aTotalDigits = _rCloneSource.m_aTotalDigits;
+ m_aFractionDigits = _rCloneSource.m_aFractionDigits;
+ }
+
+ //--------------------------------------------------------------------
+ void ODecimalType::registerProperties()
+ {
+ ODecimalType_Base::registerProperties();
+
+ REGISTER_VOID_PROP( XSD_TOTAL_DIGITS, m_aTotalDigits, sal_Int32 );
+ REGISTER_VOID_PROP( XSD_FRACTION_DIGITS, m_aFractionDigits, sal_Int32 );
+ }
+
+ //--------------------------------------------------------------------
+
+ // validate decimals and return code for which facets failed
+ // to be used by: ODecimalType::validate and ODecimalType::explainInvalid
+ sal_uInt16 ODecimalType::_validate( const ::rtl::OUString& rValue )
+ {
+ sal_Int16 nReason = ODecimalType_Base::_validate( rValue );
+
+ // check digits (if no other cause is available so far)
+ if( nReason == 0 )
+ {
+ sal_Int32 nLength = rValue.getLength();
+ sal_Int32 n = 0;
+ sal_Int32 nTotalDigits = 0;
+ sal_Int32 nFractionDigits = 0;
+ const sal_Unicode* pValue = rValue.getStr();
+ for( ; pValue[n] != sal_Unicode('.') && n < nLength; n++ )
+ if( pValue[n] >= sal_Unicode('0')
+ && pValue[n] <= sal_Unicode('9'))
+ nTotalDigits++;
+ for( ; n < nLength; n++ )
+ if( pValue[n] >= sal_Unicode('0')
+ && pValue[n] <= sal_Unicode('9'))
+ nFractionDigits++;
+ nTotalDigits += nFractionDigits;
+
+ sal_Int32 nValue = 0;
+ if( ( m_aTotalDigits >>= nValue ) && nTotalDigits > nValue )
+ nReason = RID_STR_XFORMS_VALUE_TOTAL_DIGITS;
+ else if( ( m_aFractionDigits >>= nValue ) &&
+ ( nFractionDigits > nValue ) )
+ nReason = RID_STR_XFORMS_VALUE_FRACTION_DIGITS;
+ }
+
+ return nReason;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString ODecimalType::_explainInvalid( sal_uInt16 nReason )
+ {
+ sal_Int32 nValue = 0;
+ ::rtl::OUStringBuffer sInfo;
+ switch( nReason )
+ {
+ case RID_STR_XFORMS_VALUE_TOTAL_DIGITS:
+ if( m_aTotalDigits >>= nValue )
+ sInfo.append( nValue );
+ break;
+
+ case RID_STR_XFORMS_VALUE_FRACTION_DIGITS:
+ if( m_aFractionDigits >>= nValue )
+ sInfo.append( nValue );
+ break;
+
+ default:
+ sInfo.append( ODecimalType_Base::_explainInvalid( nReason ) );
+ break;
+ }
+ return sInfo.makeStringAndClear();
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString ODecimalType::typedValueAsHumanReadableString( const Any& _rValue ) const
+ {
+ double fValue( 0 );
+ normalizeValue( _rValue, fValue );
+ return ::rtl::OUString::valueOf( fValue );
+ }
+
+ //--------------------------------------------------------------------
+ void ODecimalType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
+ {
+ OSL_VERIFY( _rValue >>= _rDoubleValue );
+ }
+
+ //====================================================================
+ //=
+ //====================================================================
+#define DEFAULT_IMPLEMNENT_SUBTYPE( classname, typeclass ) \
+ classname::classname( const ::rtl::OUString& _rName ) \
+ :classname##_Base( _rName, DataTypeClass::typeclass ) \
+ { \
+ } \
+ \
+ IMPLEMENT_DEFAULT_CLONING( classname, classname##_Base ) \
+ \
+ void classname::initializeTypedClone( const classname& /*_rCloneSource*/ ) \
+ { \
+ } \
+
+
+ //====================================================================
+ //= ODateType
+ //====================================================================
+ //--------------------------------------------------------------------
+ DEFAULT_IMPLEMNENT_SUBTYPE( ODateType, DATE )
+
+ //--------------------------------------------------------------------
+ sal_uInt16 ODateType::_validate( const ::rtl::OUString& _rValue )
+ {
+ return ODateType_Base::_validate( _rValue );
+ }
+
+ //--------------------------------------------------------------------
+ bool ODateType::_getValue( const ::rtl::OUString& value, double& fValue )
+ {
+ Any aTypeValue = Convert::get().toAny( value, getCppuType() );
+
+ Date aValue;
+ if ( !( aTypeValue >>= aValue ) )
+ return false;
+
+ ::Date aToolsDate( aValue.Day, aValue.Month, aValue.Year );
+ fValue = aToolsDate.GetDate();
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString ODateType::typedValueAsHumanReadableString( const Any& _rValue ) const
+ {
+ OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "ODateType::typedValueAsHumanReadableString: unexpected type" );
+ return Convert::get().toXSD( _rValue );
+ }
+
+ //--------------------------------------------------------------------
+ void ODateType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
+ {
+ Date aValue;
+ OSL_VERIFY( _rValue >>= aValue );
+ ::Date aToolsDate( aValue.Day, aValue.Month, aValue.Year );
+ _rDoubleValue = aToolsDate.GetDate();
+ }
+
+ //====================================================================
+ //= OTimeType
+ //====================================================================
+ //--------------------------------------------------------------------
+ DEFAULT_IMPLEMNENT_SUBTYPE( OTimeType, TIME )
+
+ //--------------------------------------------------------------------
+ sal_uInt16 OTimeType::_validate( const ::rtl::OUString& _rValue )
+ {
+ return OTimeType_Base::_validate( _rValue );
+ }
+
+ //--------------------------------------------------------------------
+ bool OTimeType::_getValue( const ::rtl::OUString& value, double& fValue )
+ {
+ Any aTypedValue = Convert::get().toAny( value, getCppuType() );
+
+ Time aValue;
+ if ( !( aTypedValue >>= aValue ) )
+ return false;
+
+ ::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.HundredthSeconds );
+ fValue = aToolsTime.GetTime();
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString OTimeType::typedValueAsHumanReadableString( const Any& _rValue ) const
+ {
+ OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "OTimeType::typedValueAsHumanReadableString: unexpected type" );
+ return Convert::get().toXSD( _rValue );
+ }
+
+ //--------------------------------------------------------------------
+ void OTimeType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
+ {
+ Time aValue;
+ OSL_VERIFY( _rValue >>= aValue );
+ ::Time aToolsTime( aValue.Hours, aValue.Minutes, aValue.Seconds, aValue.HundredthSeconds );
+ _rDoubleValue = aToolsTime.GetTime();
+ }
+
+ //====================================================================
+ //= ODateTimeType
+ //====================================================================
+ //--------------------------------------------------------------------
+ DEFAULT_IMPLEMNENT_SUBTYPE( ODateTimeType, DATETIME )
+
+ //--------------------------------------------------------------------
+ sal_uInt16 ODateTimeType::_validate( const ::rtl::OUString& _rValue )
+ {
+ return ODateTimeType_Base::_validate( _rValue );
+ }
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ double lcl_normalizeDateTime( const DateTime& _rValue )
+ {
+ ::DateTime aToolsValue(
+ ::Date( _rValue.Day, _rValue.Month, _rValue.Year ),
+ ::Time( _rValue.Hours, _rValue.Minutes, _rValue.Seconds, _rValue.HundredthSeconds )
+ );
+
+ double fValue = 0;
+ // days since 1.1.1900 (which is relatively arbitrary but fixed date)
+ fValue += ::Date( aToolsValue ) - ::Date( 1, 1, 1900 );
+ // time
+ fValue += aToolsValue.GetTimeInDays();
+ return fValue;
+ }
+ }
+
+ //--------------------------------------------------------------------
+ bool ODateTimeType::_getValue( const ::rtl::OUString& value, double& fValue )
+ {
+ Any aTypedValue = Convert::get().toAny( value, getCppuType() );
+
+ DateTime aValue;
+ if ( !( aTypedValue >>= aValue ) )
+ return false;
+
+ fValue = lcl_normalizeDateTime( aValue );
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString ODateTimeType::typedValueAsHumanReadableString( const Any& _rValue ) const
+ {
+ OSL_PRECOND( _rValue.getValueType().equals( getCppuType() ), "OTimeType::typedValueAsHumanReadableString: unexpected type" );
+ ::rtl::OUString sString = Convert::get().toXSD( _rValue );
+
+ // ISO 8601 notation has a "T" to separate between date and time. Our only concession
+ // to the "human readable" in the method name is to replace this T with a whitespace.
+ OSL_ENSURE( sString.indexOf( 'T' ) != -1, "ODateTimeType::typedValueAsHumanReadableString: hmm - no ISO notation?" );
+ return sString.replace( 'T', ' ' );
+ }
+
+ //--------------------------------------------------------------------
+ void ODateTimeType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
+ {
+ DateTime aValue;
+ OSL_VERIFY( _rValue >>= aValue );
+ _rDoubleValue = lcl_normalizeDateTime( aValue );
+ }
+
+ //====================================================================
+ //= OShortIntegerType
+ //====================================================================
+ //--------------------------------------------------------------------
+ OShortIntegerType::OShortIntegerType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass )
+ :OShortIntegerType_Base( _rName, _nTypeClass )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ IMPLEMENT_DEFAULT_TYPED_CLONING( OShortIntegerType, OShortIntegerType_Base )
+
+ //--------------------------------------------------------------------
+ void OShortIntegerType::initializeTypedClone( const OShortIntegerType& /*_rCloneSource*/ )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ bool OShortIntegerType::_getValue( const ::rtl::OUString& value, double& fValue )
+ {
+ fValue = (double)(sal_Int16)value.toInt32();
+ // TODO/eforms
+ // this does not care for values which do not fit into a sal_Int16, but simply
+ // cuts them down. A better implementation here should probably return <FALSE/>
+ // for those values.
+ // Else, we may have a situation where the UI claims an input to be valid
+ // (say "12345678"), while internally, and at submission time, this is cut to
+ // some smaller value.
+ //
+ // Additionally, this of course does not care for strings which are no numers ...
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ ::rtl::OUString OShortIntegerType::typedValueAsHumanReadableString( const Any& _rValue ) const
+ {
+ sal_Int16 nValue( 0 );
+ OSL_VERIFY( _rValue >>= nValue );
+ return ::rtl::OUString::valueOf( (sal_Int32)nValue );
+ }
+
+ //--------------------------------------------------------------------
+ void OShortIntegerType::normalizeValue( const Any& _rValue, double& _rDoubleValue ) const
+ {
+ sal_Int16 nValue( 0 );
+ OSL_VERIFY( _rValue >>= nValue );
+ _rDoubleValue = nValue;
+ }
+ //====================================================================
+ //====================================================================
+
+#define DATATYPES_INCLUDED_BY_MASTER_HEADER
+#include "datatypes_impl.hxx"
+#undef DATATYPES_INCLUDED_BY_MASTER_HEADER
+
+//........................................................................
+} // namespace xforms
+//........................................................................
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/datatypes.hxx b/forms/source/xforms/datatypes.hxx
new file mode 100644
index 000000000000..83ac51b551f4
--- /dev/null
+++ b/forms/source/xforms/datatypes.hxx
@@ -0,0 +1,426 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef FORMS_SOURCE_XFORMS_DATATYPES_HXX
+#define FORMS_SOURCE_XFORMS_DATATYPES_HXX
+
+/** === begin UNO includes === **/
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/xsd/XDataType.hpp>
+#include <com/sun/star/xsd/DataTypeClass.hpp>
+/** === end UNO includes === **/
+#include <cppuhelper/implbase1.hxx>
+#include <comphelper/uno3.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include "warnings_guard_unicode_regex.h"
+
+#include <memory>
+
+//........................................................................
+namespace xforms
+{
+//........................................................................
+
+ //====================================================================
+ //= OXSDDataType
+ //====================================================================
+ typedef ::cppu::WeakImplHelper1 < ::com::sun::star::xsd::XDataType
+ > OXSDDataType_Base;
+ typedef ::comphelper::OMutexAndBroadcastHelper OXSDDataType_BBase;
+ typedef ::comphelper::OPropertyContainer OXSDDataType_PBase;
+
+ class OXSDDataType :public OXSDDataType_Base
+ ,public OXSDDataType_BBase // order matters: OMutexAndBroadcastHelper before
+ ,public OXSDDataType_PBase // OPropertyContainer
+ {
+ private:
+ // <properties>
+ sal_Bool m_bIsBasic;
+ sal_Int16 m_nTypeClass;
+ ::rtl::OUString m_sName;
+ ::rtl::OUString m_sPattern;
+ sal_uInt16 m_nWST;
+ // </properties>
+
+ ::std::auto_ptr< U_NAMESPACE_QUALIFIER RegexMatcher >
+ m_pPatternMatcher;
+ bool m_bPatternMatcherDirty;
+
+ protected:
+
+ sal_Bool isBasic() const { return m_bIsBasic; }
+ sal_Int16 getTypeClass() const { return m_nTypeClass; }
+ const ::rtl::OUString&
+ getName() const { return m_sName; }
+
+ private:
+ OXSDDataType( ); // never implemented
+ OXSDDataType( const OXSDDataType& ); // never implemented
+ OXSDDataType& operator=( const OXSDDataType& ); // never implemented
+
+ protected:
+ // create basic data type
+ OXSDDataType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass );
+ ~OXSDDataType();
+
+ public:
+ DECLARE_XINTERFACE()
+ DECLARE_XTYPEPROVIDER()
+
+ virtual ::rtl::OUString SAL_CALL getName( ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::util::VetoException);
+ virtual ::rtl::OUString SAL_CALL getPattern() throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setPattern( const ::rtl::OUString& _pattern ) throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int16 SAL_CALL getWhiteSpaceTreatment() throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setWhiteSpaceTreatment( sal_Int16 _whitespacetreatment ) throw (::com::sun::star::uno::RuntimeException, ::com::sun::star::lang::IllegalArgumentException);
+ virtual sal_Bool SAL_CALL getIsBasic() throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Int16 SAL_CALL getTypeClass() throw (::com::sun::star::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL validate( const ::rtl::OUString& value ) throw (::com::sun::star::uno::RuntimeException);
+ virtual ::rtl::OUString SAL_CALL explainInvalid( const ::rtl::OUString& value ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XPropertySet - is a base of XDataType and needs to be disambiguated
+ virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+
+ public:
+ OXSDDataType* clone( const ::rtl::OUString& _rNewName ) const;
+
+ protected:
+ // XPropertySet and friends
+ virtual sal_Bool SAL_CALL convertFastPropertyValue( ::com::sun::star::uno::Any& _rConvertedValue, ::com::sun::star::uno::Any& _rOldValue, sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw(::com::sun::star::lang::IllegalArgumentException);
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const ::com::sun::star::uno::Any& rValue
+ )
+ throw (::com::sun::star::uno::Exception);
+
+ // --- own overridables ---
+ // helper for implementing cloning of data types
+ virtual OXSDDataType* createClone( const ::rtl::OUString& _rName ) const = 0;
+ virtual void initializeClone( const OXSDDataType& _rCloneSource );
+
+ // helper method for validate and explainInvalid
+ virtual sal_uInt16 _validate( const ::rtl::OUString& value );
+ virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason );
+
+ // helper method for checking properties values which are to be set
+ virtual bool checkPropertySanity( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, ::rtl::OUString& _rErrorMessage );
+
+ // register properties implemented by this instance - call the base class when overriding
+ virtual void registerProperties();
+ };
+
+ //====================================================================
+ //= helper for deriving from OXSDDataType
+ //====================================================================
+#define DECLARE_DEFAULT_CLONING( classname ) \
+ virtual OXSDDataType* createClone( const ::rtl::OUString& _rName ) const; \
+ virtual void initializeClone( const OXSDDataType& _rCloneSource ); \
+ void initializeTypedClone( const classname& _rCloneSource );
+
+#define IMPLEMENT_DEFAULT_CLONING( classname, baseclass ) \
+ OXSDDataType* classname::createClone( const ::rtl::OUString& _rName ) const \
+ { \
+ return new classname( _rName ); \
+ } \
+ void classname::initializeClone( const OXSDDataType& _rCloneSource ) \
+ { \
+ baseclass::initializeClone( _rCloneSource ); \
+ initializeTypedClone( static_cast< const classname& >( _rCloneSource ) ); \
+ } \
+
+#define IMPLEMENT_DEFAULT_TYPED_CLONING( classname, baseclass ) \
+ OXSDDataType* classname::createClone( const ::rtl::OUString& _rName ) const \
+ { \
+ return new classname( _rName, getTypeClass() ); \
+ } \
+ void classname::initializeClone( const OXSDDataType& _rCloneSource ) \
+ { \
+ baseclass::initializeClone( _rCloneSource ); \
+ initializeTypedClone( static_cast< const classname& >( _rCloneSource ) ); \
+ } \
+
+#define REGISTER_VOID_PROP( prop, memberAny, type ) \
+ registerMayBeVoidProperty( PROPERTY_##prop, PROPERTY_ID_##prop, ::com::sun::star::beans::PropertyAttribute::BOUND | ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, \
+ &memberAny, ::getCppuType( static_cast< type* >( NULL ) ) );
+
+ //====================================================================
+ //= OValueLimitedType_Base
+ //====================================================================
+ class OValueLimitedType_Base : public OXSDDataType
+ {
+ protected:
+ ::com::sun::star::uno::Any m_aMaxInclusive;
+ ::com::sun::star::uno::Any m_aMaxExclusive;
+ ::com::sun::star::uno::Any m_aMinInclusive;
+ ::com::sun::star::uno::Any m_aMinExclusive;
+
+ double m_fCachedMaxInclusive;
+ double m_fCachedMaxExclusive;
+ double m_fCachedMinInclusive;
+ double m_fCachedMinExclusive;
+
+ protected:
+ OValueLimitedType_Base( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass );
+
+ virtual void initializeClone( const OXSDDataType& _rCloneSource );
+ void initializeTypedClone( const OValueLimitedType_Base& _rCloneSource );
+
+ // XPropertySet and friends
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 nHandle,
+ const ::com::sun::star::uno::Any& rValue
+ )
+ throw (::com::sun::star::uno::Exception);
+
+ // OXSDDataType overridables
+ virtual bool _getValue( const ::rtl::OUString& value, double& fValue );
+ virtual sal_uInt16 _validate( const ::rtl::OUString& value );
+ virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason );
+
+ // own overridables
+ /** translate a given value into a human-readable string
+
+ The value is guaranteed to be not <NULL/>, and is of type <member>ValueType</member>
+ */
+ virtual ::rtl::OUString typedValueAsHumanReadableString( const ::com::sun::star::uno::Any& _rValue ) const = 0;
+
+ /** translates a <member>ValueType</member> value into a double value
+
+ The normalization must respect the "<" and "==" relations on the value
+ space. That is, if two values are equal, their normalizations must be equal, too.
+ Similarily, if <code>foo</code> is less than <code>bar</code>, the same
+ must hold for their normalizations.
+
+ @param _rValue
+ the value to translate. Guranteed to be not <NULL/>, and of type <member>ValueType</member>
+ @param _rDoubleValue
+ output parameter to hold the resulting double value
+ */
+ virtual void normalizeValue( const ::com::sun::star::uno::Any& _rValue, double& _rDoubleValue ) const = 0;
+ };
+
+ //====================================================================
+ //= OValueLimitedType
+ //====================================================================
+ template < typename VALUE_TYPE >
+ class OValueLimitedType : public OValueLimitedType_Base
+ {
+ protected:
+ typedef VALUE_TYPE ValueType;
+ inline const ::com::sun::star::uno::Type&
+ getCppuType() const { return ::getCppuType( static_cast< ValueType* >( NULL ) ); }
+
+ protected:
+ OValueLimitedType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass );
+
+ // OXSDDataType overridables
+ virtual void registerProperties();
+ };
+
+ //====================================================================
+ //= ODerivedDataType
+ //====================================================================
+ /** helper class for implementing interfaces derived from XDataType
+ */
+ template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS = OXSDDataType >
+ class ODerivedDataType :public SUPERCLASS
+ ,::comphelper::OPropertyArrayUsageHelper< CONCRETE_DATA_TYPE_IMPL >
+ {
+ private:
+ bool m_bPropertiesRegistered;
+
+ protected:
+ ODerivedDataType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass );
+
+ protected:
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;
+
+ // XPropertySet
+ virtual com::sun::star::uno::Reference<com::sun::star::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() throw(com::sun::star::uno::RuntimeException);
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
+ };
+
+ //====================================================================
+ //= OBooleanType
+ //====================================================================
+ class OBooleanType;
+ typedef ODerivedDataType< OBooleanType > OBooleanType_Base;
+ class OBooleanType : public OBooleanType_Base
+ {
+ public:
+ OBooleanType( const ::rtl::OUString& _rName );
+
+ protected:
+ DECLARE_DEFAULT_CLONING( OBooleanType )
+
+ // OXSDDataType overridables
+ virtual sal_uInt16 _validate( const ::rtl::OUString& value );
+ virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason );
+ };
+
+ //====================================================================
+ //= OStringType
+ //====================================================================
+ class OStringType;
+ typedef ODerivedDataType< OStringType > OStringType_Base;
+ class OStringType :public OStringType_Base
+ {
+ protected:
+ // <properties>
+ ::com::sun::star::uno::Any m_aLength;
+ ::com::sun::star::uno::Any m_aMinLength;
+ ::com::sun::star::uno::Any m_aMaxLength;
+ // </properties>
+
+ public:
+ OStringType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass /* = ::com::sun::star::xsd::DataTypeClass::STRING */ );
+
+ protected:
+ DECLARE_DEFAULT_CLONING( OStringType )
+
+ // OXSDDataType overridables
+ virtual sal_uInt16 _validate( const ::rtl::OUString& value );
+ virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason );
+ virtual bool checkPropertySanity( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rNewValue, ::rtl::OUString& _rErrorMessage );
+ virtual void registerProperties();
+ };
+
+ //====================================================================
+ //= ODecimalType
+ //====================================================================
+ class ODecimalType;
+ typedef ODerivedDataType< ODecimalType, OValueLimitedType< double > > ODecimalType_Base;
+ class ODecimalType : public ODecimalType_Base
+ {
+ protected:
+ ::com::sun::star::uno::Any m_aTotalDigits;
+ ::com::sun::star::uno::Any m_aFractionDigits;
+
+ public:
+ ODecimalType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass /* = ::com::sun::star::xsd::DataTypeClass::DECIMAL */ );
+
+ protected:
+ DECLARE_DEFAULT_CLONING( ODecimalType )
+
+ // OXSDDataType overridables
+ virtual sal_uInt16 _validate( const ::rtl::OUString& value );
+ virtual ::rtl::OUString _explainInvalid( sal_uInt16 nReason );
+ virtual void registerProperties();
+
+ // OValueLimitedType overridables
+ virtual ::rtl::OUString typedValueAsHumanReadableString( const ::com::sun::star::uno::Any& _rValue ) const;
+ virtual void normalizeValue( const ::com::sun::star::uno::Any& _rValue, double& _rDoubleValue ) const;
+
+ private:
+ using ODecimalType_Base::initializeTypedClone;
+ };
+
+ //====================================================================
+ //=
+ //====================================================================
+#define DEFAULT_DECLARE_SUBTYPE( classname, valuetype ) \
+ class classname; \
+ typedef ODerivedDataType< classname, OValueLimitedType< valuetype > > classname##_Base; \
+ class classname : public classname##_Base \
+ { \
+ public: \
+ classname( const ::rtl::OUString& _rName ); \
+ \
+ protected: \
+ DECLARE_DEFAULT_CLONING( classname ) \
+ \
+ /* OXSDDataType overridables */ \
+ virtual sal_uInt16 _validate( const ::rtl::OUString& value ); \
+ virtual bool _getValue( const ::rtl::OUString& value, double& fValue ); \
+ \
+ /* OValueLimitedType overridables */ \
+ virtual ::rtl::OUString typedValueAsHumanReadableString( const ::com::sun::star::uno::Any& _rValue ) const; \
+ virtual void normalizeValue( const ::com::sun::star::uno::Any& _rValue, double& _rDoubleValue ) const; \
+ \
+ private: \
+ using classname##_Base::initializeTypedClone; \
+ };
+
+ //====================================================================
+ //= ODateType
+ //====================================================================
+ DEFAULT_DECLARE_SUBTYPE( ODateType, ::com::sun::star::util::Date )
+
+ //====================================================================
+ //= OTimeType
+ //====================================================================
+ DEFAULT_DECLARE_SUBTYPE( OTimeType, ::com::sun::star::util::Time )
+
+ //====================================================================
+ //= ODateTimeType
+ //====================================================================
+ DEFAULT_DECLARE_SUBTYPE( ODateTimeType, ::com::sun::star::util::DateTime )
+
+ //====================================================================
+ //= OShortIntegerType
+ //====================================================================
+ class OShortIntegerType;
+ typedef ODerivedDataType< OShortIntegerType, OValueLimitedType< sal_Int16 > > OShortIntegerType_Base;
+ class OShortIntegerType : public OShortIntegerType_Base
+ {
+ public:
+ OShortIntegerType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass );
+
+ protected:
+ DECLARE_DEFAULT_CLONING( OShortIntegerType )
+
+ // OXSDDataType overridables
+ virtual bool _getValue( const ::rtl::OUString& value, double& fValue );
+
+ // OValueLimitedType overridables
+ virtual ::rtl::OUString typedValueAsHumanReadableString( const ::com::sun::star::uno::Any& _rValue ) const;
+ virtual void normalizeValue( const ::com::sun::star::uno::Any& _rValue, double& _rDoubleValue ) const;
+
+ private:
+ using OShortIntegerType_Base::initializeTypedClone;
+ };
+
+//........................................................................
+} // namespace xforms
+//........................................................................
+
+#endif // FORMS_SOURCE_XFORMS_DATATYPES_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/datatypes_impl.hxx b/forms/source/xforms/datatypes_impl.hxx
new file mode 100644
index 000000000000..cc0b2c5b3b35
--- /dev/null
+++ b/forms/source/xforms/datatypes_impl.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef DATATYPES_INCLUDED_BY_MASTER_HEADER
+ #error "not to be included directly!"
+#endif
+
+//--------------------------------------------------------------------
+template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS >
+ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::ODerivedDataType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass )
+ :SUPERCLASS( _rName, _nTypeClass )
+ ,m_bPropertiesRegistered( false )
+{
+}
+
+//--------------------------------------------------------------------
+template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS >
+::cppu::IPropertyArrayHelper* ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::createArrayHelper( ) const
+{
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property > aProps;
+ ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::describeProperties( aProps );
+ return new ::cppu::OPropertyArrayHelper( aProps );
+}
+
+//--------------------------------------------------------------------
+template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS >
+::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::getPropertySetInfo() throw( ::com::sun::star::uno::RuntimeException )
+{
+ return ::cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() );
+}
+
+//--------------------------------------------------------------------
+template< typename CONCRETE_DATA_TYPE_IMPL, typename SUPERCLASS >
+::cppu::IPropertyArrayHelper& SAL_CALL ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::getInfoHelper()
+{
+ if ( !m_bPropertiesRegistered )
+ {
+ const_cast< ODerivedDataType* >( this )->registerProperties();
+ const_cast< ODerivedDataType* >( this )->m_bPropertiesRegistered = true;
+ }
+
+ return *ODerivedDataType< CONCRETE_DATA_TYPE_IMPL, SUPERCLASS >::getArrayHelper();
+}
+
+
+//--------------------------------------------------------------------
+template< typename VALUE_TYPE >
+OValueLimitedType< VALUE_TYPE >::OValueLimitedType( const ::rtl::OUString& _rName, sal_Int16 _nTypeClass )
+ :OValueLimitedType_Base( _rName, _nTypeClass )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/enumeration.cxx b/forms/source/xforms/enumeration.cxx
new file mode 100644
index 000000000000..82a9118f7e66
--- /dev/null
+++ b/forms/source/xforms/enumeration.cxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "enumeration.hxx"
+
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/lang/WrappedTargetException.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+using com::sun::star::container::NoSuchElementException;
+using com::sun::star::container::XIndexAccess;
+using com::sun::star::lang::WrappedTargetException;
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::RuntimeException;
+
+
+Enumeration::Enumeration( XIndexAccess* pContainer )
+ : mxContainer( pContainer ),
+ mnIndex( 0 )
+{
+ OSL_ENSURE( mxContainer.is(), "no container?" );
+}
+
+sal_Bool Enumeration::hasMoreElements()
+ throw( RuntimeException )
+{
+ if( ! mxContainer.is() )
+ throw RuntimeException();
+
+ return mnIndex < mxContainer->getCount();
+}
+
+Any Enumeration::nextElement()
+ throw( NoSuchElementException,
+ WrappedTargetException,
+ RuntimeException )
+{
+ if( ! mxContainer.is() )
+ throw RuntimeException();
+ if( mnIndex >= mxContainer->getCount() )
+ throw NoSuchElementException();
+
+ return mxContainer->getByIndex( mnIndex++ );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/enumeration.hxx b/forms/source/xforms/enumeration.hxx
new file mode 100644
index 000000000000..395f29dd4845
--- /dev/null
+++ b/forms/source/xforms/enumeration.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _ENUMERATION_HXX
+#define _ENUMERATION_HXX
+
+
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+namespace com { namespace sun { namespace star {
+ namespace container { class XIndexAccess; }
+ namespace uno { class Any; }
+ namespace container { class NoSuchElementException; }
+ namespace lang { class WrappedTargetException; }
+ namespace uno { class RuntimeException; }
+} } }
+
+/** implement XEnumeration based on container::XIndexAccess */
+class Enumeration
+ : public cppu::WeakImplHelper1<com::sun::star::container::XEnumeration>
+{
+ com::sun::star::uno::Reference<com::sun::star::container::XIndexAccess> mxContainer;
+ sal_Int32 mnIndex;
+
+public:
+ Enumeration( com::sun::star::container::XIndexAccess* );
+
+ virtual sal_Bool SAL_CALL hasMoreElements()
+ throw( com::sun::star::uno::RuntimeException );
+
+ virtual com::sun::star::uno::Any SAL_CALL nextElement()
+ throw( com::sun::star::container::NoSuchElementException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/evaluationcontext.hxx b/forms/source/xforms/evaluationcontext.hxx
new file mode 100644
index 000000000000..a5f8b32d5df3
--- /dev/null
+++ b/forms/source/xforms/evaluationcontext.hxx
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _EVALUATIONCONTEXT_HXX
+#define _EVALUATIONCONTEXT_HXX
+
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/xforms/XModel.hpp>
+
+namespace xforms
+{
+
+
+/** define the context for the evaluation of an XPath expression */
+class EvaluationContext
+{
+public:
+ EvaluationContext()
+ : mxContextNode(),
+ mxModel(),
+ mxNamespaces(),
+ mnContextPosition( 0 ),
+ mnContextSize( 0 )
+ { }
+
+ EvaluationContext(
+ const com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode>& xContextNode,
+ const com::sun::star::uno::Reference<com::sun::star::xforms::XModel>& xModel,
+ const com::sun::star::uno::Reference<com::sun::star::container::XNameContainer>& xNamespaces,
+ sal_Int32 nPosition,
+ sal_Int32 nSize )
+ : mxContextNode( xContextNode ),
+ mxModel( xModel ),
+ mxNamespaces( xNamespaces ),
+ mnContextPosition( nPosition ),
+ mnContextSize( nSize )
+ { }
+
+ com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> mxContextNode;
+ com::sun::star::uno::Reference<com::sun::star::xforms::XModel> mxModel;
+ com::sun::star::uno::Reference<com::sun::star::container::XNameContainer> mxNamespaces;
+
+ sal_Int32 mnContextPosition;
+ sal_Int32 mnContextSize;
+};
+
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/makefile.mk b/forms/source/xforms/makefile.mk
new file mode 100644
index 000000000000..10bbf6b49fcd
--- /dev/null
+++ b/forms/source/xforms/makefile.mk
@@ -0,0 +1,66 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=forms
+TARGET=xforms
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE: $(PRJ)$/makefile.pmk
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/model.obj \
+ $(SLO)$/model_ui.obj \
+ $(SLO)$/binding.obj \
+ $(SLO)$/xforms_services.obj \
+ $(SLO)$/unohelper.obj \
+ $(SLO)$/propertysetbase.obj \
+ $(SLO)$/pathexpression.obj \
+ $(SLO)$/computedexpression.obj \
+ $(SLO)$/boolexpression.obj \
+ $(SLO)$/mip.obj \
+ $(SLO)$/submission.obj \
+ $(SLO)$/datatyperepository.obj \
+ $(SLO)$/datatypes.obj \
+ $(SLO)$/convert.obj \
+ $(SLO)$/enumeration.obj \
+ $(SLO)$/resourcehelper.obj \
+ $(SLO)$/xmlhelper.obj \
+ $(SLO)$/xformsevent.obj
+
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/forms/source/xforms/mip.cxx b/forms/source/xforms/mip.cxx
new file mode 100644
index 000000000000..a8bcda632d34
--- /dev/null
+++ b/forms/source/xforms/mip.cxx
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "mip.hxx"
+
+
+namespace xforms
+{
+
+
+MIP::MIP()
+{
+ resetReadonly();
+ resetRequired();
+ resetRelevant();
+ resetConstraint();
+ resetCalculate();
+ resetTypeName();
+}
+
+MIP::~MIP() {}
+
+void MIP::inherit( const MIP& rMip )
+{
+ if( ! mbHasReadonly )
+ {
+ mbHasReadonly = rMip.hasReadonly();
+ mbReadonly = rMip.isReadonly();
+ }
+ if( ! mbHasRequired )
+ {
+ mbHasRequired = rMip.hasRequired();
+ mbRequired = rMip.isRequired();
+ }
+ if( ! mbHasRelevant )
+ {
+ mbHasRelevant = rMip.hasRelevant();
+ mbRelevant = rMip.isRelevant();
+ }
+ if( ! mbHasConstraint )
+ {
+ mbHasConstraint = rMip.hasConstraint();
+ mbConstraint = rMip.isConstraint();
+ msConstraintExplanation = rMip.getConstraintExplanation();
+ }
+ if( ! mbHasCalculate )
+ {
+ mbHasCalculate = rMip.hasCalculate();
+ }
+ if( ! mbHasTypeName )
+ {
+ mbHasTypeName = rMip.hasTypeName();
+ msTypeName = rMip.getTypeName();
+ }
+}
+
+void MIP::join( const MIP& rMip )
+{
+ // TODO: inherit only inheritable MIPs...
+ inherit( rMip );
+}
+
+bool MIP::hasReadonly() const { return mbHasReadonly; }
+bool MIP::isReadonly() const { return mbHasReadonly ? mbReadonly : mbHasCalculate; }
+void MIP::setReadonly( bool b ) { mbHasReadonly = true; mbReadonly = b; }
+void MIP::resetReadonly() { mbHasReadonly = false; mbReadonly = false; }
+
+bool MIP::hasRequired() const { return mbHasRequired; }
+bool MIP::isRequired() const { return mbRequired; }
+void MIP::setRequired( bool b ) { mbHasRequired = true; mbRequired = b; }
+void MIP::resetRequired() { mbHasRequired = false; mbRequired = false; }
+
+bool MIP::hasRelevant() const { return mbHasRelevant; }
+bool MIP::isRelevant() const { return mbRelevant; }
+void MIP::setRelevant( bool b ) { mbHasRelevant = true; mbRelevant = b; }
+void MIP::resetRelevant() { mbHasRelevant = false; mbRelevant = true; }
+
+bool MIP::hasConstraint() const { return mbHasConstraint; }
+bool MIP::isConstraint() const { return mbConstraint; }
+void MIP::setConstraint( bool b ) { mbHasConstraint = true; mbConstraint = b; msConstraintExplanation = rtl::OUString(); }
+void MIP::resetConstraint() { mbHasConstraint = false; mbConstraint = true; msConstraintExplanation = rtl::OUString(); }
+
+void MIP::setConstraintExplanation( const rtl::OUString& s ) { msConstraintExplanation = s; }
+rtl::OUString MIP::getConstraintExplanation() const { return msConstraintExplanation; }
+
+
+bool MIP::hasCalculate() const { return mbHasCalculate; }
+void MIP::setHasCalculate( bool b ) { mbHasCalculate = b; }
+void MIP::resetCalculate() { mbHasCalculate = false; }
+
+bool MIP::hasTypeName() const { return mbHasTypeName; }
+ rtl::OUString MIP::getTypeName() const { return msTypeName; }
+void MIP::setTypeName( const rtl::OUString& s ) { msTypeName = s; mbHasTypeName = true; }
+void MIP::resetTypeName() { msTypeName = rtl::OUString(); mbHasTypeName = false; }
+
+
+
+
+} // namespace xforms
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/mip.hxx b/forms/source/xforms/mip.hxx
new file mode 100644
index 000000000000..ad0db3e05916
--- /dev/null
+++ b/forms/source/xforms/mip.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _MIP_HXX
+#define _MIP_HXX
+
+#include <rtl/ustring.hxx>
+
+namespace xforms
+{
+
+/** represents the XForms *m*odel *i*tem *p*roperties (MIPs) for a
+ * given XNode in the instance data at a given point in time. The
+ * values will not be updated; for updated values new MIP objects have
+ * to be created/queried. */
+class MIP
+{
+ bool mbHasReadonly;
+ bool mbReadonly;
+
+ bool mbHasRequired;
+ bool mbRequired;
+
+ bool mbHasRelevant;
+ bool mbRelevant;
+
+ bool mbHasConstraint;
+ bool mbConstraint;
+
+ bool mbHasCalculate;
+
+ bool mbHasTypeName;
+ rtl::OUString msTypeName;
+
+ rtl::OUString msConstraintExplanation;
+
+public:
+ MIP();
+ ~MIP();
+
+ /// inherit from upper-level MIPs
+ void inherit( const MIP& );
+
+ /// join with same-level MIPs
+ void join( const MIP& );
+
+
+ // - type (static; default: xsd:string)
+ // (currently default implemented as empty string)
+ bool hasTypeName() const;
+ rtl::OUString getTypeName() const;
+ void setTypeName( const rtl::OUString& );
+ void resetTypeName();
+
+ // - readonly (computed XPath; default: false; true if calculate exists)
+ bool hasReadonly() const;
+ bool isReadonly() const;
+ void setReadonly( bool );
+ void resetReadonly();
+
+ // - required (computed XPath; default: false)
+ bool hasRequired() const;
+ bool isRequired() const;
+ void setRequired( bool );
+ void resetRequired();
+
+ // - relevant (computed XPath; default: true)
+ bool hasRelevant() const;
+ bool isRelevant() const;
+ void setRelevant( bool );
+ void resetRelevant();
+
+ // - constraing (computed XPath; default: true)
+ bool hasConstraint() const;
+ bool isConstraint() const;
+ void setConstraint( bool );
+ void resetConstraint();
+
+ // explain _why_ a constraint failed
+ void setConstraintExplanation( const rtl::OUString& );
+ rtl::OUString getConstraintExplanation() const;
+
+ // - calculate (computed XPath; default: has none (false))
+ // (for calculate, we only store whether a calculate MIP is present;
+ // the actual calculate value is handled my changing the instance
+ // directly)
+ bool hasCalculate() const;
+ void setHasCalculate( bool );
+ void resetCalculate();
+
+ // - minOccurs/maxOccurs (computed XPath; default: 0/inf)
+ // - p3ptype (static; no default)
+
+};
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/model.cxx b/forms/source/xforms/model.cxx
new file mode 100644
index 000000000000..26c7981ddfdf
--- /dev/null
+++ b/forms/source/xforms/model.cxx
@@ -0,0 +1,810 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "model.hxx"
+
+#include "model_helper.hxx"
+#include "unohelper.hxx"
+#include "binding.hxx"
+#include "submission.hxx"
+#include "mip.hxx"
+#include "evaluationcontext.hxx"
+#include "xmlhelper.hxx"
+#include "datatyperepository.hxx"
+#include "NameContainer.hxx"
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/debug.hxx>
+
+#include <comphelper/propertysetinfo.hxx>
+#include <cppuhelper/typeprovider.hxx>
+
+#include <algorithm>
+
+// UNO classes
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/dom/XCharacterData.hpp>
+#include <com/sun/star/xml/dom/NodeType.hpp>
+#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+
+
+using com::sun::star::lang::XMultiServiceFactory;
+using com::sun::star::lang::XUnoTunnel;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::beans::PropertyValue;
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using com::sun::star::beans::PropertyVetoException;
+using com::sun::star::beans::UnknownPropertyException;
+using com::sun::star::util::VetoException;
+using com::sun::star::lang::WrappedTargetException;
+using com::sun::star::lang::IllegalArgumentException;
+using com::sun::star::ucb::XSimpleFileAccess;
+using com::sun::star::io::XInputStream;
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::xml::dom;
+using namespace xforms;
+
+
+#if OSL_DEBUG_LEVEL > 1
+#define DBG_INVARIANT_TYPE(TYPE) class DBG_##TYPE { const TYPE* mpT; void check() { mpT->dbg_assertInvariant(); } public: DBG_##TYPE(const TYPE* pT) : mpT(pT) { check(); } ~DBG_##TYPE() { check(); } } _DBG_##TYPE(this);
+
+#define DBG_INVARIANT() DBG_INVARIANT_TYPE(Model)
+#else
+#define DBG_INVARIANT_TYPE(TYPE)
+#define DBG_INVARIANT()
+#endif
+
+
+
+//
+// The Model
+//
+
+void Model::ensureAtLeastOneInstance()
+{
+ if( ! mpInstances->hasItems() )
+ {
+ // create a default instance
+ newInstance( OUString(), OUString(), true );
+ }
+}
+
+
+
+/** Model default constructor; create empty model */
+Model::Model() :
+ msID(),
+ mpBindings( NULL ),
+ mpSubmissions( NULL ),
+ mpInstances( new InstanceCollection ),
+ mxNamespaces( new NameContainer<OUString>() ),
+ mxBindings( mpBindings ),
+ mxSubmissions( mpSubmissions ),
+ mxInstances( mpInstances ),
+ mbInitialized( false ),
+ mbExternalData( true )
+{
+ initializePropertySet();
+
+ // initialize bindings collections
+ // (not in initializer list to avoid use of incomplete 'this')
+ mpBindings = new BindingCollection( this );
+ mxBindings = mpBindings;
+
+ mpSubmissions = new SubmissionCollection( this );
+ mxSubmissions = mpSubmissions;
+
+ // invariant only holds after construction
+ DBG_INVARIANT();
+}
+
+Model::~Model() throw()
+{
+ // give up bindings & submissions; the mxBindings/mxSubmissions
+ // references will then delete them
+ mpBindings = NULL;
+ mpSubmissions = NULL;
+}
+
+Model* lcl_getModel( const Reference<XUnoTunnel>& xTunnel )
+{
+ Model* pModel = NULL;
+ if( xTunnel.is() )
+ pModel = reinterpret_cast<Model*>(
+ xTunnel->getSomething( Model::getUnoTunnelID() ) );
+ return pModel;
+}
+
+Model* Model::getModel( const Reference<XModel>& xModel )
+{
+ return lcl_getModel( Reference<XUnoTunnel>( xModel, UNO_QUERY ) );
+}
+
+EvaluationContext Model::getEvaluationContext()
+{
+ // the default context is the top-level element node. A default
+ // node (instanceData' is inserted when there is no default node
+ Reference<XDocument> xInstance = getDefaultInstance();
+ Reference<XNode> xElement( xInstance->getDocumentElement(), UNO_QUERY );
+
+ // no element found? Then insert default element 'instanceData'
+ if( ! xElement.is() )
+ {
+ xElement = Reference<XNode>(
+ xInstance->createElement( OUSTRING("instanceData") ),
+ UNO_QUERY_THROW );
+ Reference<XNode>( xInstance, UNO_QUERY_THROW)->appendChild( xElement );
+ }
+
+ OSL_ENSURE( xElement.is() &&
+ xElement->getNodeType() == NodeType_ELEMENT_NODE,
+ "no element in evaluation context" );
+
+ return EvaluationContext( xElement, this, mxNamespaces, 0, 1 );
+}
+
+
+Model::IntSequence_t Model::getUnoTunnelID()
+{
+ static cppu::OImplementationId aImplementationId;
+ return aImplementationId.getImplementationId();
+}
+
+Model::XDocument_t Model::getForeignSchema() const
+{
+ return mxForeignSchema;
+}
+
+void Model::setForeignSchema( const XDocument_t& rDocument )
+{
+ mxForeignSchema = rDocument;
+}
+
+rtl::OUString Model::getSchemaRef() const
+{
+ return msSchemaRef;
+}
+
+void Model::setSchemaRef( const rtl::OUString& rSchemaRef )
+{
+ msSchemaRef = rSchemaRef;
+}
+
+Model::XNameContainer_t Model::getNamespaces() const
+{
+ return mxNamespaces;
+}
+
+void Model::setNamespaces( const XNameContainer_t& rNamespaces )
+{
+ if( rNamespaces.is() )
+ mxNamespaces = rNamespaces;
+}
+
+bool Model::getExternalData() const
+{
+ return mbExternalData;
+}
+
+void Model::setExternalData( bool _bData )
+{
+ mbExternalData = _bData;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+void Model::dbg_assertInvariant() const
+{
+ OSL_ENSURE( mpInstances != NULL, "no instances found" );
+ OSL_ENSURE( mxInstances.is(), "No instance container!" );
+ // OSL_ENSURE( mxInstances->hasElements(), "no instance!" );
+
+ OSL_ENSURE( mpBindings != NULL, "no bindings element" );
+ OSL_ENSURE( mxBindings.is(), "No Bindings container" );
+
+ OSL_ENSURE( mpSubmissions != NULL, "no submissions element" );
+ OSL_ENSURE( mxSubmissions.is(), "No Submission container" );
+
+
+
+ /*
+ // check bindings, and things that have to do with our binding
+ std::vector<MIP*> aAllMIPs; // check MIP map
+ sal_Int32 nCount = mpBindings->countItems();
+ for( sal_Int32 i = 0; i < nCount; i++ )
+ {
+ Binding* pBind = Binding::getBinding(
+ mpBindings->Collection<XPropertySet_t>::getItem( i ) );
+
+ // examine and check binding
+ OSL_ENSURE( pBind != NULL, "invalid binding found" );
+
+ OSL_ENSURE( Model::getModel( pBind->getModel() ) == this,
+ "our binding doesn't know us.");
+ // check this binding's MIP against MIP map
+ MIP* pMIP = const_cast<MIP*>( pBind->_getMIP() );
+ sal_Int32 nFound = 0;
+ if( pMIP != NULL )
+ {
+ aAllMIPs.push_back( pMIP );
+ for( MIPs_t::const_iterator aIter = maMIPs.begin();
+ aIter != maMIPs.end();
+ aIter++ )
+ {
+ if( pMIP == aIter->second )
+ nFound++;
+ }
+ }
+ OSL_ENSURE( ( pMIP == NULL ) == ( nFound == 0 ), "MIP-map wrong" );
+ }
+
+ // check MIP map for left-over MIPs
+ for( MIPs_t::const_iterator aIter = maMIPs.begin();
+ aIter != maMIPs.end();
+ aIter++ )
+ {
+ MIP* pMIP = aIter->second;
+ std::vector<MIP*>::iterator aFound =
+ std::find( aAllMIPs.begin(), aAllMIPs.end(), pMIP );
+ if( aFound != aAllMIPs.end() )
+ aAllMIPs.erase( aFound );
+ }
+ OSL_ENSURE( aAllMIPs.empty(), "lonely MIPs found!" );
+ */
+}
+#endif
+
+
+//
+// MIP managment
+//
+
+void Model::addMIP( void* pTag, const XNode_t& xNode, const MIP& rMIP )
+{
+ OSL_ENSURE( pTag != NULL, "empty tag?" );
+ OSL_ENSURE( xNode.is(), "no node" );
+
+ MIPs_t::value_type aValue( xNode, ::std::pair<void*,MIP>( pTag, rMIP ) );
+ maMIPs.insert( aValue );
+}
+
+void Model::removeMIPs( void* pTag )
+{
+ OSL_ENSURE( pTag != NULL, "empty tag?" );
+
+ for( MIPs_t::iterator aIter = maMIPs.begin();
+ aIter != maMIPs.end(); )
+ {
+ if( aIter->second.first == pTag )
+ {
+ MIPs_t::iterator next( aIter ); ++next;
+ maMIPs.erase( aIter );
+ aIter = next;
+ }
+ else
+ ++aIter;
+ }
+}
+
+MIP Model::queryMIP( const XNode_t& xNode ) const
+{
+ // OSL_ENSURE( xNode.is(), "no node" );
+
+ // travel up inheritance chain and inherit MIPs
+ MIP aRet;
+ for( XNode_t xCurrent = xNode;
+ xCurrent.is();
+ xCurrent = xCurrent->getParentNode() )
+ {
+ // iterate over all MIPs for this node, and join MIPs
+ MIP aMIP;
+ MIPs_t::const_iterator aEnd = maMIPs.upper_bound( xCurrent );
+ MIPs_t::const_iterator aIter = maMIPs.lower_bound( xCurrent );
+ for( ; aIter != aEnd; ++aIter )
+ aMIP.join( aIter->second.second );
+
+ // inherit from current node (or set if we are at the start node)
+ if( xCurrent == xNode )
+ aRet = aMIP;
+ else
+ aRet.inherit( aMIP );
+ }
+
+ return aRet;
+}
+
+
+
+void Model::rebind()
+{
+ OSL_ENSURE( mpBindings != NULL, "bindings?" );
+
+ // iterate over all bindings and call update
+ sal_Int32 nCount = mpBindings->countItems();
+ for( sal_Int32 i = 0; i < nCount; i++ )
+ {
+ Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) );
+ OSL_ENSURE( pBind != NULL, "binding?" );
+ pBind->update();
+ }
+}
+
+
+
+void Model::deferNotifications( bool bDefer )
+{
+ // iterate over all bindings and defer notifications
+ sal_Int32 nCount = mpBindings->countItems();
+ for( sal_Int32 i = 0; i < nCount; i++ )
+ {
+ Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) );
+ OSL_ENSURE( pBind != NULL, "binding?" );
+ pBind->deferNotifications( bDefer );
+ }
+}
+
+
+bool Model::setSimpleContent( const XNode_t& xConstNode,
+ const rtl::OUString& sValue )
+{
+ OSL_ENSURE( xConstNode.is(), "need node to set data" );
+
+ bool bRet = false;
+ if( xConstNode.is() )
+ {
+ // non-const node reference so we can assign children (if necessary)
+ XNode_t xNode( xConstNode );
+
+ switch( xNode->getNodeType() )
+ {
+ case NodeType_ELEMENT_NODE:
+ {
+ // find first text node child
+ Reference<XNode> xChild;
+ for( xChild = xNode->getFirstChild();
+ xChild.is() && xChild->getNodeType() != NodeType_TEXT_NODE;
+ xChild = xChild->getNextSibling() )
+ ; // empty loop; only find first text node child
+
+ // create text node, if none is found
+ if( ! xChild.is() )
+ {
+ xChild = Reference<XNode>(
+ xNode->getOwnerDocument()->createTextNode( OUString() ),
+ UNO_QUERY_THROW );
+ xNode->appendChild( xChild );
+ }
+ xNode = xChild;
+
+ OSL_ENSURE( xNode.is() &&
+ xNode->getNodeType() == NodeType_TEXT_NODE,
+ "text node creation failed?" );
+ }
+ // no break; continue as with text node:
+
+ case NodeType_TEXT_NODE:
+ case NodeType_ATTRIBUTE_NODE:
+ {
+ // set the node value (defer notifications)
+ if( xNode->getNodeValue() != sValue )
+ {
+ deferNotifications( true );
+ xNode->setNodeValue( sValue );
+ deferNotifications( false );
+ }
+ bRet = true;
+ }
+ break;
+
+ default:
+ {
+ OSL_ENSURE( false, "bound to unknown node type?" );
+ }
+ break;
+
+ }
+ }
+ return bRet;
+}
+
+void Model::loadInstance( sal_Int32 nInstance )
+{
+ Sequence<PropertyValue> aSequence = mpInstances->getItem( nInstance );
+
+ // find URL from instance
+ OUString sURL;
+ bool bOnce = false;
+ getInstanceData( aSequence, NULL, NULL, &sURL, &bOnce );
+
+ // if we have a URL, load the document and set it into the instance
+ if( sURL.getLength() > 0 )
+ {
+ try
+ {
+ Reference<XInputStream> xInput =
+ Reference<XSimpleFileAccess>(
+ createInstance(
+ OUSTRING("com.sun.star.ucb.SimpleFileAccess") ),
+ UNO_QUERY_THROW )->openFileRead( sURL );
+ if( xInput.is() )
+ {
+ Reference<XDocument> xInstance =
+ getDocumentBuilder()->parse( xInput );
+ if( xInstance.is() )
+ {
+ OUString sEmpty;
+ setInstanceData( aSequence, NULL, &xInstance,
+ bOnce ? &sEmpty : &sURL, NULL);
+ mpInstances->setItem( nInstance, aSequence );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ // couldn't load the instance -> ignore!
+ }
+ }
+}
+
+void Model::loadInstances()
+{
+ // iterate over instance array to get PropertyValue-Sequence
+ const sal_Int32 nInstances = mpInstances->countItems();
+ for( sal_Int32 nInstance = 0; nInstance < nInstances; nInstance++ )
+ {
+ loadInstance( nInstance );
+ }
+}
+
+bool Model::isInitialized() const
+{
+ return mbInitialized;
+}
+
+bool Model::isValid() const
+{
+ bool bValid = true;
+ sal_Int32 nCount = mpBindings->countItems();
+ for( sal_Int32 i = 0; bValid && i < nCount; i++ )
+ {
+ Binding* pBind = Binding::getBinding( mpBindings->Collection<XPropertySet_t>::getItem( i ) );
+ OSL_ENSURE( pBind != NULL, "binding?" );
+ bValid = pBind->isValid();
+ }
+ return bValid;
+}
+
+
+
+//
+// implement xforms::XModel
+//
+
+rtl::OUString Model::getID()
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ return msID;
+}
+
+void Model::setID( const rtl::OUString& sID )
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ msID = sID;
+}
+
+void Model::initialize()
+ throw( RuntimeException )
+{
+ DBG_ASSERT( ! mbInitialized, "model already initialized" );
+
+ // load instances
+ loadInstances();
+
+ // let's pretend we're initialized and rebind all bindings
+ mbInitialized = true;
+ rebind();
+}
+
+void Model::rebuild()
+ throw( RuntimeException )
+{
+ if( ! mbInitialized )
+ initialize();
+ else
+ rebind();
+}
+
+void Model::recalculate()
+ throw( RuntimeException )
+{
+ rebind();
+}
+
+void Model::revalidate()
+ throw( RuntimeException )
+{
+ // do nothing. We don't validate anyways!
+}
+
+void Model::refresh()
+ throw( RuntimeException )
+{
+ rebind();
+}
+
+
+void SAL_CALL Model::submitWithInteraction(
+ const rtl::OUString& sID,
+ const XInteractionHandler_t& _rxHandler )
+ throw( VetoException,
+ WrappedTargetException,
+ RuntimeException )
+{
+ DBG_INVARIANT();
+
+ if( mpSubmissions->hasItem( sID ) )
+ {
+ Submission* pSubmission =
+ Submission::getSubmission( mpSubmissions->getItem( sID ) );
+ OSL_ENSURE( pSubmission != NULL, "no submission?" );
+ OSL_ENSURE( pSubmission->getModel() == Reference<XModel>( this ),
+ "wrong model" );
+
+ // submit. All exceptions are allowed to leave.
+ pSubmission->submitWithInteraction( _rxHandler );
+ }
+}
+
+void Model::submit( const rtl::OUString& sID )
+ throw( VetoException, WrappedTargetException, RuntimeException )
+{
+ submitWithInteraction( sID, NULL );
+}
+
+Model::XDataTypeRepository_t SAL_CALL Model::getDataTypeRepository( )
+ throw( RuntimeException )
+{
+ if ( !mxDataTypes.is() )
+ mxDataTypes = new ODataTypeRepository;
+
+ return mxDataTypes;
+}
+
+//
+// instance management
+//
+
+Model::XSet_t Model::getInstances()
+ throw( RuntimeException )
+{
+ return mxInstances;
+}
+
+Model::XDocument_t Model::getInstanceDocument( const rtl::OUString& rName )
+ throw( RuntimeException )
+{
+ ensureAtLeastOneInstance();
+ Reference<XDocument> aInstance;
+ sal_Int32 nInstance = lcl_findInstance( mpInstances, rName );
+ if( nInstance != -1 )
+ getInstanceData( mpInstances->getItem( nInstance ),
+ NULL, &aInstance, NULL, NULL );
+ return aInstance;
+}
+
+Model::XDocument_t SAL_CALL Model::getDefaultInstance()
+ throw( RuntimeException )
+{
+ ensureAtLeastOneInstance();
+ DBG_ASSERT( mpInstances->countItems() > 0, "no instance?" );
+ Reference<XDocument> aInstance;
+ getInstanceData( mpInstances->getItem( 0 ), NULL, &aInstance, NULL, NULL );
+ return aInstance;
+}
+
+
+
+//
+// bindings management
+//
+
+Model::XPropertySet_t SAL_CALL Model::createBinding()
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ return new Binding();
+}
+
+Model::XPropertySet_t Model::cloneBinding( const XPropertySet_t& xBinding )
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ XPropertySet_t xNewBinding = createBinding();
+ copy( xBinding, xNewBinding );
+ return xNewBinding;
+}
+
+Model::XPropertySet_t Model::getBinding( const rtl::OUString& sId )
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ return mpBindings->hasItem( sId ) ? mpBindings->getItem( sId ) : NULL;
+}
+
+Model::XSet_t Model::getBindings()
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ return mxBindings;
+}
+
+
+
+//
+// submission management
+//
+
+Model::XSubmission_t Model::createSubmission()
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ return new Submission();
+}
+
+Model::XSubmission_t Model::cloneSubmission(const XPropertySet_t& xSubmission)
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ XSubmission_t xNewSubmission = createSubmission();
+ XPropertySet_t xAsPropertySet( xNewSubmission.get() );
+ copy( xSubmission.get(), xAsPropertySet );
+ return xNewSubmission;
+}
+
+Model::XSubmission_t Model::getSubmission( const rtl::OUString& sId )
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ XSubmission_t xSubmission;
+ if ( mpSubmissions->hasItem( sId ) )
+ xSubmission = xSubmission.query( mpSubmissions->getItem( sId ) );
+ return xSubmission;
+}
+
+Model::XSet_t Model::getSubmissions()
+ throw( RuntimeException )
+{
+ DBG_INVARIANT();
+ return mxSubmissions;
+}
+
+
+
+//
+// implementation of XFormsUIHelper1 interface
+// can be found in file model_ui.cxx
+//
+
+
+
+//
+// implement XPropertySet & friends
+//
+
+#define HANDLE_ID 0
+#define HANDLE_Instance 1
+#define HANDLE_InstanceURL 2
+#define HANDLE_ForeignSchema 3
+#define HANDLE_SchemaRef 4
+#define HANDLE_Namespaces 5
+#define HANDLE_ExternalData 6
+
+#define REGISTER_PROPERTY( property, type ) \
+ registerProperty( PROPERTY( property, type ), \
+ new DirectPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) );
+
+#define REGISTER_PROPERTY_API( property, type ) \
+ registerProperty( PROPERTY( property, type ), \
+ new APIPropertyAccessor< Model, type >( this, &Model::set##property, &Model::get##property ) );
+
+#define REGISTER_BOOL_PROPERTY( property ) \
+ registerProperty( PROPERTY( property, sal_Bool ), \
+ new BooleanPropertyAccessor< Model, bool >( this, &Model::set##property, &Model::get##property ) );
+
+void Model::initializePropertySet()
+{
+ REGISTER_PROPERTY_API ( ID, OUString );
+ REGISTER_PROPERTY ( ForeignSchema, XDocument_t );
+ REGISTER_PROPERTY ( SchemaRef, OUString );
+ REGISTER_PROPERTY ( Namespaces, XNameContainer_t );
+ REGISTER_BOOL_PROPERTY( ExternalData );
+}
+
+void Model::update()
+ throw( RuntimeException )
+{
+ rebuild();
+}
+
+
+sal_Int64 Model::getSomething( const IntSequence_t& xId )
+ throw( RuntimeException )
+{
+ return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL );
+}
+
+Sequence<sal_Int8> Model::getImplementationId()
+ throw( RuntimeException )
+{
+ return getUnoTunnelID();
+}
+
+
+//
+// 'shift' operators for getting data into and out of Anys
+//
+
+void operator <<= ( com::sun::star::uno::Any& rAny,
+ xforms::Model* pModel)
+{
+ Reference<XPropertySet> xPropSet( static_cast<XPropertySet*>( pModel ) );
+ rAny <<= xPropSet;
+}
+
+bool operator >>= ( xforms::Model* pModel,
+ com::sun::star::uno::Any& rAny )
+{
+ bool bRet = false;
+
+ // acquire model pointer through XUnoTunnel
+ Reference<XUnoTunnel> xTunnel( rAny, UNO_QUERY );
+ if( xTunnel.is() )
+ {
+ pModel = reinterpret_cast<xforms::Model*>(
+ xTunnel->getSomething( xforms::Model::getUnoTunnelID() ) );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/model.hxx b/forms/source/xforms/model.hxx
new file mode 100644
index 000000000000..03db8210f388
--- /dev/null
+++ b/forms/source/xforms/model.hxx
@@ -0,0 +1,438 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _MODEL_HXX
+#define _MODEL_HXX
+
+
+// include for parent class(es)
+#include <cppuhelper/implbase4.hxx>
+#include <propertysetbase.hxx>
+#include <com/sun/star/xforms/XModel.hpp>
+#include <com/sun/star/xforms/XFormsUIHelper1.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+
+
+// includes for member variables
+#include <com/sun/star/uno/Reference.hxx>
+#include <map>
+
+
+// forward declaractions
+namespace com { namespace sun { namespace star
+{
+ namespace xml { namespace dom { class XDocument; } }
+ namespace xml { namespace dom { class XNode; } }
+ namespace uno { template<typename T> class Sequence; }
+ namespace lang { class IndexOutOfBoundsException; }
+ namespace lang { class IllegalArgumentException; }
+ namespace beans { class XPropertySet; }
+ namespace container { class XSet; }
+ namespace container { class XNameContainer; }
+ namespace frame { class XModel; }
+} } }
+namespace rtl { class OUString; }
+namespace xforms
+{
+ class Binding;
+ class MIP;
+ class BindingCollection;
+ class SubmissionCollection;
+ class InstanceCollection;
+ class EvaluationContext;
+}
+
+
+namespace xforms
+{
+
+/** An XForms Model. Contains:
+ * # (set of) instance data (XML DOM tree)
+ * # (set of) bindings
+ * # (set of) submissions
+ * # (NOT YET IMPLEMENTED) actions (set of)
+ *
+ * See http://www.w3.org/TR/xforms/ for more information.
+ */
+typedef cppu::ImplInheritanceHelper4<
+ PropertySetBase,
+ com::sun::star::xforms::XModel,
+ com::sun::star::xforms::XFormsUIHelper1,
+ com::sun::star::util::XUpdatable,
+ com::sun::star::lang::XUnoTunnel
+> Model_t;
+class Model : public Model_t
+{
+ // a number of local typedefs, to make the remaining header readable
+ typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XDocument> XDocument_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> XNode_t;
+ typedef com::sun::star::lang::IndexOutOfBoundsException IndexOutOfBoundsException_t;
+ typedef com::sun::star::lang::IllegalArgumentException IllegalArgumentException_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> XPropertySet_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xforms::XDataTypeRepository> XDataTypeRepository_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::container::XNameContainer> XNameContainer_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xforms::XSubmission> XSubmission_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::frame::XModel> Frame_XModel_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::xforms::XModel> XModel_t;
+ typedef com::sun::star::uno::Reference<com::sun::star::task::XInteractionHandler> XInteractionHandler_t;
+
+ typedef com::sun::star::uno::Reference<com::sun::star::container::XSet> XSet_t;
+ typedef com::sun::star::beans::PropertyVetoException PropertyVetoException_t;
+ typedef com::sun::star::beans::UnknownPropertyException UnknownPropertyException_t;
+ typedef com::sun::star::util::VetoException VetoException_t;
+ typedef com::sun::star::lang::WrappedTargetException WrappedTargetException_t;
+ typedef com::sun::star::uno::RuntimeException RuntimeException_t;
+ typedef com::sun::star::uno::Any Any_t;
+ typedef com::sun::star::uno::Sequence<sal_Int8> IntSequence_t;
+ typedef std::multimap<XNode_t,std::pair<void*,MIP> > MIPs_t;
+
+
+private:
+
+ rtl::OUString msID; /// the model ID
+ BindingCollection* mpBindings; /// the bindings
+ SubmissionCollection* mpSubmissions; /// the submissions
+ InstanceCollection* mpInstances; /// the instance(s)
+
+ XDataTypeRepository_t mxDataTypes; /// the XSD data-types used
+ XDocument_t mxForeignSchema; /// the XSD-schema part we cannot
+ /// map onto data types
+ rtl::OUString msSchemaRef; /// xforms:model/@schema attribute
+
+ XNameContainer_t mxNamespaces; /// namespaces for entire model
+
+
+ // references to mpBindings/mpSubmissions, for UNO reference counting
+ XSet_t mxBindings;
+ XSet_t mxSubmissions;
+ XSet_t mxInstances;
+
+ MIPs_t maMIPs; /// map nodes to their MIPs
+
+ bool mbInitialized; /// has model been initialized ?
+ bool mbExternalData; /// is the data of this model to be considered an ingegral part of the document?
+
+ void initializePropertySet();
+
+ void ensureAtLeastOneInstance();
+
+
+public:
+
+ /// create a new model with an empty, default instance
+ Model();
+ virtual ~Model() throw();
+
+ // get Model implementation from API object
+ static Model* getModel( const com::sun::star::uno::Reference<com::sun::star::xforms::XModel>& );
+
+ xforms::EvaluationContext getEvaluationContext();
+
+
+ static IntSequence_t getUnoTunnelID();
+
+
+ // get/set that part of the schema, that we can't interpret as data types
+ XDocument_t getForeignSchema() const;
+ void setForeignSchema( const XDocument_t& );
+
+ // get/set the xforms:model/@schema attribute
+ rtl::OUString getSchemaRef() const;
+ void setSchemaRef( const rtl::OUString& );
+
+ // get/set namespaces for entire model
+ XNameContainer_t getNamespaces() const;
+ void setNamespaces( const XNameContainer_t& );
+
+ // get/set the ExternalData property
+ bool getExternalData() const;
+ void setExternalData( bool _bData );
+
+
+#if OSL_DEBUG_LEVEL > 1
+ void dbg_assertInvariant() const;
+#endif
+
+
+ //
+ // MIP (model item property) management
+ //
+
+ // register MIPs which apply to a given node; only to be called by bindings
+ // (The pTag parameter serves only to be able to remove the MIPs
+ // that were added using the same tag. No functions will be
+ // performed on it; hence the void* type.)
+ void addMIP( void* pTag, const XNode_t&, const MIP& );
+ void removeMIPs( void* pTag );
+
+ /// query which MIPs appy to the given node
+ MIP queryMIP( const XNode_t& xNode ) const;
+
+ /// re-bind all bindings
+ void rebind();
+
+ /// call defer notifications on all bindings
+ void deferNotifications( bool );
+
+ /// set a data value in the instance
+ /// (also defers notifications)
+ bool setSimpleContent( const XNode_t&, const rtl::OUString& );
+
+ /// load instance data
+ void loadInstance( sal_Int32 nInstance );
+ void loadInstances();
+
+ /// has model been initialized?
+ bool isInitialized() const;
+
+ /// is model currently valid (for submission)?
+ bool isValid() const;
+
+
+
+ //
+ // XModel
+ // implement the xforms::XModel implementation
+ //
+
+
+ virtual rtl::OUString SAL_CALL getID()
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL setID( const rtl::OUString& sID )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL initialize()
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL rebuild()
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL recalculate()
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL revalidate()
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL refresh()
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL submit( const rtl::OUString& sID )
+ throw( VetoException_t, WrappedTargetException_t, RuntimeException_t );
+
+ virtual void SAL_CALL submitWithInteraction( const ::rtl::OUString& id, const XInteractionHandler_t& _rxHandler )
+ throw( VetoException_t, WrappedTargetException_t, RuntimeException_t );
+
+ virtual XDataTypeRepository_t SAL_CALL getDataTypeRepository( )
+ throw( RuntimeException_t );
+
+
+ // XModel: instance management
+
+ virtual XSet_t SAL_CALL getInstances()
+ throw( RuntimeException_t );
+
+ virtual XDocument_t SAL_CALL getInstanceDocument( const rtl::OUString& )
+ throw( RuntimeException_t );
+
+ virtual XDocument_t SAL_CALL getDefaultInstance()
+ throw( RuntimeException_t );
+
+
+
+ // XModel: binding management
+
+ virtual XPropertySet_t SAL_CALL createBinding()
+ throw( RuntimeException_t );
+
+ virtual XPropertySet_t SAL_CALL cloneBinding( const XPropertySet_t& )
+ throw( RuntimeException_t );
+
+ virtual XPropertySet_t SAL_CALL getBinding( const rtl::OUString& )
+ throw( RuntimeException_t );
+
+ virtual XSet_t SAL_CALL getBindings()
+ throw( RuntimeException_t );
+
+
+ // XModel: submission management
+
+ virtual XSubmission_t SAL_CALL createSubmission()
+ throw( RuntimeException_t );
+
+ virtual XSubmission_t SAL_CALL cloneSubmission( const XPropertySet_t& )
+ throw( RuntimeException_t );
+
+ virtual XSubmission_t SAL_CALL getSubmission( const rtl::OUString& )
+ throw( RuntimeException_t );
+
+ virtual XSet_t SAL_CALL getSubmissions()
+ throw( RuntimeException_t );
+
+
+
+ //
+ // XFormsUIHelper1 & friends:
+ // (implementation in model_ui.cxx)
+ //
+
+ /// determine a reasonable control service for a given node
+ /// (based on data type MIP assigned to the node)
+ virtual rtl::OUString SAL_CALL getDefaultServiceNameForNode( const XNode_t& xNode ) throw (RuntimeException_t);
+
+ /// call getDefaultBindingExpressionForNode with default evaluation context
+ virtual rtl::OUString SAL_CALL getDefaultBindingExpressionForNode( const XNode_t& xNode ) throw (RuntimeException_t);
+
+ /// determine a reasonable default binding expression for a given node
+ /// and a given evaluation context
+ /// @returns expression, or empty string if no expression could be derived
+ rtl::OUString getDefaultBindingExpressionForNode(
+ const XNode_t&,
+ const EvaluationContext& );
+
+ virtual rtl::OUString SAL_CALL getNodeDisplayName( const XNode_t&,
+ sal_Bool bDetail )
+ throw( RuntimeException_t );
+
+ virtual rtl::OUString SAL_CALL getNodeName( const XNode_t& )
+ throw( RuntimeException_t );
+
+ virtual rtl::OUString SAL_CALL getBindingName( const XPropertySet_t&,
+ sal_Bool bDetail )
+ throw( RuntimeException_t );
+
+ virtual rtl::OUString SAL_CALL getSubmissionName( const XPropertySet_t&,
+ sal_Bool bDetail )
+ throw( RuntimeException_t );
+
+ virtual XPropertySet_t SAL_CALL cloneBindingAsGhost( const XPropertySet_t& )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL removeBindingIfUseless( const XPropertySet_t& )
+ throw( RuntimeException_t );
+
+ virtual XDocument_t SAL_CALL newInstance( const rtl::OUString& sName,
+ const rtl::OUString& sURL,
+ sal_Bool bURLOnce )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL renameInstance( const rtl::OUString& sFrom,
+ const rtl::OUString& sTo,
+ const rtl::OUString& sURL,
+ sal_Bool bURLOnce )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL removeInstance( const rtl::OUString& sName )
+ throw( RuntimeException_t );
+
+
+ virtual XModel_t SAL_CALL newModel( const Frame_XModel_t& xComponent,
+ const rtl::OUString& sName )
+ throw( RuntimeException_t );
+ virtual void SAL_CALL renameModel( const Frame_XModel_t& xComponent,
+ const rtl::OUString& sFrom,
+ const rtl::OUString& sTo )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL removeModel( const Frame_XModel_t& xComponent,
+ const rtl::OUString& sName )
+ throw( RuntimeException_t );
+
+
+ virtual XNode_t SAL_CALL createElement( const XNode_t& xParent,
+ const rtl::OUString& sName )
+ throw( RuntimeException_t );
+
+ virtual XNode_t SAL_CALL createAttribute( const XNode_t& xParent,
+ const rtl::OUString& sName )
+ throw( RuntimeException_t );
+
+ virtual XNode_t SAL_CALL renameNode( const XNode_t& xNode,
+ const rtl::OUString& sName )
+ throw( RuntimeException_t );
+
+ virtual XPropertySet_t SAL_CALL getBindingForNode( const XNode_t&,
+ sal_Bool bCreate )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL removeBindingForNode( const XNode_t& )
+ throw( RuntimeException_t );
+
+ virtual rtl::OUString SAL_CALL getResultForExpression(
+ const XPropertySet_t& xBinding,
+ sal_Bool bIsBindingExpression,
+ const rtl::OUString& sExpression )
+ throw( RuntimeException_t );
+
+ virtual sal_Bool SAL_CALL isValidXMLName( const rtl::OUString& sName )
+ throw( RuntimeException_t );
+
+ virtual sal_Bool SAL_CALL isValidPrefixName( const rtl::OUString& sName )
+ throw( RuntimeException_t );
+
+ virtual void SAL_CALL setNodeValue(
+ const XNode_t& xNode,
+ const rtl::OUString& sValue )
+ throw( RuntimeException_t );
+
+
+ //
+ // XUpdatable
+ //
+
+public:
+ virtual void SAL_CALL update()
+ throw( RuntimeException_t );
+
+ //
+ // XUnoTunnel
+ //
+
+public:
+ virtual sal_Int64 SAL_CALL getSomething( const IntSequence_t& )
+ throw( RuntimeException_t );
+
+ //
+ // XTypeProvider::getImplementationId
+ //
+
+public:
+ virtual IntSequence_t SAL_CALL getImplementationId()
+ throw( RuntimeException_t );
+
+};
+
+// finally, allow 'shifting' of Model objects into/out of Any
+void operator <<= ( com::sun::star::uno::Any&, const xforms::Model* );
+bool operator >>= ( xforms::Model*, const com::sun::star::uno::Any& );
+
+} // namespace
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/model_helper.hxx b/forms/source/xforms/model_helper.hxx
new file mode 100644
index 000000000000..064d60f3ab71
--- /dev/null
+++ b/forms/source/xforms/model_helper.hxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _MODEL_HELPER_HXX
+#define _MODEL_HELPER_HXX
+
+//
+// some helper definitions that must be available for model.cxx and
+// model_ui.cxx
+//
+
+#include "namedcollection.hxx"
+#include "binding.hxx"
+#include "submission.hxx"
+#include "unohelper.hxx"
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+namespace xforms
+{
+ class Model;
+}
+
+//
+// BindingCollection
+//
+
+namespace xforms
+{
+
+class BindingCollection : public NamedCollection<com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> >
+{
+ Model* mpModel;
+
+public:
+ BindingCollection( Model* pModel ) : mpModel( pModel ) {}
+ virtual ~BindingCollection() {}
+
+ virtual bool isValid( const T& t ) const
+ {
+ return Binding::getBinding( t ) != NULL;
+ }
+
+protected:
+ virtual void _insert( const T& t )
+ {
+ OSL_ENSURE( Binding::getBinding( t ) != NULL, "invalid item?" );
+ Binding::getBinding( t )->_setModel( Binding::Model_t( mpModel ) );
+ }
+
+ virtual void _remove( const T& t )
+ {
+ OSL_ENSURE( Binding::getBinding( t ) != NULL, "invalid item?" );
+ Binding::getBinding( t )->_setModel( Binding::Model_t() );
+ }
+};
+
+
+
+//
+// SubmissionCollection
+//
+
+class SubmissionCollection : public NamedCollection<com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> >
+{
+ Model* mpModel;
+
+public:
+ SubmissionCollection( Model* pModel ) : mpModel( pModel ) {}
+ virtual ~SubmissionCollection() {}
+
+public:
+ virtual bool isValid( const T& t ) const
+ {
+ return Submission::getSubmission( t ) != NULL;
+ }
+
+protected:
+ virtual void _insert( const T& t )
+ {
+ OSL_ENSURE( Submission::getSubmission( t ) != NULL, "invalid item?" );
+ Submission::getSubmission( t )->setModel( com::sun::star::uno::Reference<com::sun::star::xforms::XModel>( mpModel ) );
+ }
+
+ virtual void _remove( const T& t )
+ {
+ OSL_ENSURE( Submission::getSubmission( t ) != NULL, "invalid item?" );
+ Submission::getSubmission( t )->setModel( com::sun::star::uno::Reference<com::sun::star::xforms::XModel>( ) );
+ }
+};
+
+
+//
+// InstanceCollection
+//
+
+class InstanceCollection : public Collection<com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> >
+{
+public:
+ virtual bool isValid( const T& t ) const
+ {
+ const com::sun::star::beans::PropertyValue* pValues = t.getConstArray();
+ rtl::OUString sInstance( OUSTRING("Instance") );
+ sal_Bool bFound = sal_False;
+ for( sal_Int32 i = 0; ( ! bFound ) && ( i < t.getLength() ); i++ )
+ {
+ bFound |= ( pValues[i].Name == sInstance );
+ }
+ return bFound ? true : false;
+ }
+};
+
+
+//
+// helper functions
+//
+
+sal_Int32 lcl_findInstance( const InstanceCollection*,
+ const rtl::OUString& );
+
+
+// get values from Sequence<PropertyValue> describing an Instance
+void getInstanceData(
+ const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>&,
+ rtl::OUString* pID,
+ com::sun::star::uno::Reference<com::sun::star::xml::dom::XDocument>*,
+ rtl::OUString* pURL,
+ bool* pURLOnce );
+
+// set values on Sequence<PropertyValue> for an Instance
+void setInstanceData(
+ com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>&,
+ const rtl::OUString* pID,
+ const com::sun::star::uno::Reference<com::sun::star::xml::dom::XDocument>*,
+ const rtl::OUString* pURL,
+ const bool* pURLOnce );
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/model_ui.cxx b/forms/source/xforms/model_ui.cxx
new file mode 100644
index 000000000000..f78bccfea00b
--- /dev/null
+++ b/forms/source/xforms/model_ui.cxx
@@ -0,0 +1,1069 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#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"
+#include "convert.hxx"
+
+#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>
+#include <com/sun/star/xforms/XDataTypeRepository.hpp>
+#include <com/sun/star/xsd/XDataType.hpp>
+#include <com/sun/star/xsd/DataTypeClass.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 service for control. string/text field is default.
+ OUString sService = OUSTRING("com.sun.star.form.component.TextField");
+
+ // query repository for suitable type
+ OSL_ENSURE( mxDataTypes.is(), "no type repository?" );
+ OUString sTypeName = queryMIP( xNode ).getTypeName();
+ if( mxDataTypes->hasByName( sTypeName ) )
+ {
+ OSL_ENSURE( mxDataTypes->getDataType( sTypeName ).is(),
+ "has or has not?" );
+
+ switch( mxDataTypes->getDataType( sTypeName )->getTypeClass() )
+ {
+ case com::sun::star::xsd::DataTypeClass::BOOLEAN:
+ sService = OUSTRING("com.sun.star.form.component.CheckBox");
+ break;
+ case com::sun::star::xsd::DataTypeClass::DOUBLE:
+ case com::sun::star::xsd::DataTypeClass::DECIMAL:
+ case com::sun::star::xsd::DataTypeClass::FLOAT:
+ sService = OUSTRING("com.sun.star.form.component.NumericField");
+ break;
+
+ case com::sun::star::xsd::DataTypeClass::STRING:
+ case com::sun::star::xsd::DataTypeClass::DURATION:
+ case com::sun::star::xsd::DataTypeClass::DATETIME:
+ case com::sun::star::xsd::DataTypeClass::TIME:
+ case com::sun::star::xsd::DataTypeClass::DATE:
+ case com::sun::star::xsd::DataTypeClass::gYearMonth:
+ case com::sun::star::xsd::DataTypeClass::gYear:
+ case com::sun::star::xsd::DataTypeClass::gMonthDay:
+ case com::sun::star::xsd::DataTypeClass::gDay:
+ case com::sun::star::xsd::DataTypeClass::gMonth:
+ case com::sun::star::xsd::DataTypeClass::hexBinary:
+ case com::sun::star::xsd::DataTypeClass::base64Binary:
+ case com::sun::star::xsd::DataTypeClass::anyURI:
+ case com::sun::star::xsd::DataTypeClass::QName:
+ case com::sun::star::xsd::DataTypeClass::NOTATION:
+ default:
+ // keep default
+ break;
+ }
+ }
+
+ return sService;
+}
+
+
+void lcl_OutPosition( OUStringBuffer& rBuffer,
+ const Reference<XNode>& xNode )
+{
+ OSL_ENSURE( xNode->getParentNode().is(), "need parent" );
+
+ // count # of occurrences 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::XPropertySet_t Model::cloneBindingAsGhost( const XPropertySet_t &xBinding )
+ throw( RuntimeException )
+{
+ // Create a new binding instance first...
+ Binding *pBinding = new Binding();
+
+ // ...and bump up the "defered notification counter"
+ // to prevent this binding from contributing to the
+ // MIPs table...
+ pBinding->deferNotifications(true);
+
+ // Copy the propertyset and return result...
+ XPropertySet_t xNewBinding(pBinding);
+ copy( xBinding, xNewBinding );
+ return xNewBinding;
+}
+
+void Model::removeBindingIfUseless( const XPropertySet_t& xBinding )
+ throw( RuntimeException )
+{
+ Binding* pBinding = Binding::getBinding( xBinding );
+ if( pBinding != NULL )
+ {
+ if( ! pBinding->isUseful() )
+ mpBindings->removeItem( pBinding );
+ }
+}
+
+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,
+ const rtl::OUString& sURL,
+ sal_Bool bURLOnce )
+ 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;
+
+ // change url
+ nProp = lcl_findProp( pSeq, nLength, OUSTRING("URL") );
+ if(nProp != -1)
+ pSeq[ nProp ].Value <<= sURL;
+
+ // change urlonce
+ nProp = lcl_findProp( pSeq, nLength, OUSTRING("URLOnce") );
+ if(nProp != -1)
+ pSeq[ nProp ].Value <<= bURLOnce;
+
+ // 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::XModel_t xModel;
+ Reference<XNameContainer> xModels = lcl_getModels( xCmp );
+ if( xModels.is()
+ && ! xModels->hasByName( sName ) )
+ {
+ Model* pModel = new Model();
+ xModel.set( pModel );
+
+ pModel->setID( sName );
+ pModel->newInstance( OUString(), OUString(), sal_False );
+ pModel->initialize();
+ xModels->insertByName( sName, makeAny( xModel ) );
+ }
+
+ return xModel;
+}
+
+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;
+
+ default:
+ 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 );
+ 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
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/namedcollection.hxx b/forms/source/xforms/namedcollection.hxx
new file mode 100644
index 000000000000..2b06343c4a40
--- /dev/null
+++ b/forms/source/xforms/namedcollection.hxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _NAMEDCOLLECTION_HXX
+#define _NAMEDCOLLECTION_HXX
+
+#include <collection.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/container/XNameAccess.hpp>
+
+#include <algorithm>
+
+template<class T>
+class NamedCollection : public cppu::ImplInheritanceHelper1<
+ Collection<T>,
+ com::sun::star::container::XNameAccess>
+{
+ using Collection<T>::maItems;
+ using Collection<T>::getItem;
+ using Collection<T>::hasItem;
+
+public:
+ NamedCollection() {}
+ virtual ~NamedCollection() {}
+
+ const T& getItem( const rtl::OUString& rName ) const
+ {
+ OSL_ENSURE( hasItem( rName ), "invalid name" );
+ return *findItem( rName );
+ }
+
+ bool hasItem( const rtl::OUString& rName ) const
+ {
+ return findItem( rName ) != maItems.end();
+ }
+
+ typedef com::sun::star::uno::Sequence<rtl::OUString> Names_t;
+ Names_t getNames() const
+ {
+ // iterate over members, and collect all those that have names
+ std::vector<rtl::OUString> aNames;
+ for( typename std::vector<T>::const_iterator aIter = maItems.begin();
+ aIter != maItems.end();
+ aIter++ )
+ {
+ com::sun::star::uno::Reference<com::sun::star::container::XNamed>
+ xNamed( *aIter, com::sun::star::uno::UNO_QUERY );
+ if( xNamed.is() )
+ aNames.push_back( xNamed->getName() );
+ }
+
+ // copy names to Sequence and return
+ Names_t aResult( aNames.size() );
+ rtl::OUString* pStrings = aResult.getArray();
+ std::copy( aNames.begin(), aNames.end(), pStrings );
+
+ return aResult;
+ }
+
+protected:
+ typename std::vector<T>::const_iterator findItem( const rtl::OUString& rName ) const
+ {
+ for( typename std::vector<T>::const_iterator aIter = maItems.begin();
+ aIter != maItems.end();
+ aIter++ )
+ {
+ com::sun::star::uno::Reference<com::sun::star::container::XNamed>
+ xNamed( *aIter, com::sun::star::uno::UNO_QUERY );
+ if( xNamed.is() && xNamed->getName() == rName )
+ return aIter;
+ }
+ return maItems.end();
+ }
+
+public:
+
+ // XElementAccess
+ virtual typename Collection<T>::Type_t SAL_CALL getElementType()
+ throw( typename Collection<T>::RuntimeException_t )
+ {
+ return Collection<T>::getElementType();
+ }
+
+ virtual sal_Bool SAL_CALL hasElements()
+ throw( typename Collection<T>::RuntimeException_t )
+ {
+ return Collection<T>::hasElements();
+ }
+
+ // XNameAccess : XElementAccess
+ virtual typename Collection<T>::Any_t SAL_CALL getByName(
+ const rtl::OUString& aName )
+ throw( typename Collection<T>::NoSuchElementException_t,
+ typename Collection<T>::WrappedTargetException_t,
+ typename Collection<T>::RuntimeException_t )
+ {
+ if( hasItem( aName ) )
+ return com::sun::star::uno::makeAny( getItem( aName ) );
+ else
+ throw typename Collection<T>::NoSuchElementException_t();
+
+ }
+
+ virtual Names_t SAL_CALL getElementNames()
+ throw( typename Collection<T>::RuntimeException_t )
+ {
+ return getNames();
+ }
+
+ virtual sal_Bool SAL_CALL hasByName(
+ const rtl::OUString& aName )
+ throw( typename Collection<T>::RuntimeException_t )
+ {
+ return hasItem( aName ) ? sal_True : sal_False;
+ }
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/pathexpression.cxx b/forms/source/xforms/pathexpression.cxx
new file mode 100644
index 000000000000..6494059f56bb
--- /dev/null
+++ b/forms/source/xforms/pathexpression.cxx
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "pathexpression.hxx"
+#include "unohelper.hxx"
+#include "evaluationcontext.hxx"
+#include "NameContainer.hxx"
+
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/xml/dom/XNodeList.hpp>
+#include <com/sun/star/xml/dom/NodeType.hpp>
+#include <com/sun/star/xml/dom/events/XEventListener.hpp>
+#include <com/sun/star/xml/dom/events/XEventTarget.hpp>
+#include <com/sun/star/xml/xpath/XXPathObject.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <unotools/textsearch.hxx>
+
+#include <algorithm>
+#include <functional>
+
+
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::xml::dom::XNode;
+using com::sun::star::xml::dom::XNodeList;
+using com::sun::star::xml::dom::events::XEventListener;
+using com::sun::star::xml::dom::events::XEventTarget;
+using com::sun::star::container::XNameContainer;
+using com::sun::star::xml::xpath::XXPathObject;
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::uno::UNO_QUERY;
+using com::sun::star::uno::UNO_QUERY_THROW;
+using com::sun::star::xml::dom::NodeType_TEXT_NODE;
+using com::sun::star::xml::xpath::XPathObjectType_XPATH_UNDEFINED;
+using namespace std;
+
+
+
+
+namespace xforms
+{
+
+PathExpression::PathExpression()
+ : ComputedExpression(),
+ maNodes()
+{
+}
+
+PathExpression::~PathExpression()
+{
+}
+
+
+
+void PathExpression::setExpression( const OUString& rExpression )
+{
+ // set new expression, and clear pre-computed results
+ ComputedExpression::setExpression( rExpression );
+
+ // check expression against regular expression to determine
+ // whether it contains only 'simple' (i.e. static) conditions. For
+ // now, we check whether it only contains number positions.
+ // (TODO: Only works for names containing only ASCII letters+digits.)
+ mbIsSimple =
+ _checkExpression( "( */@?[a-zA-Z0-9:]+( *\\[ *[0-9 ]+ *\\] *)?)+" );
+
+ maNodes.clear();
+}
+
+const rtl::OUString PathExpression::_getExpressionForEvaluation() const
+{
+ OUString sExpr = ComputedExpression::_getExpressionForEvaluation();
+ if( sExpr.getLength() == 0 )
+ sExpr = OUSTRING(".");
+ return sExpr;
+}
+
+bool PathExpression::evaluate( const EvaluationContext& rContext )
+{
+ // for simple expression we don't need to re-bind (if we were bound before)
+ // (we will evaluate empty expressions, since they are interpreted as ".")
+ if( mxResult.is() && isSimpleExpression() )
+ return true;
+
+ bool bResult = _evaluate( rContext, _getExpressionForEvaluation() );
+
+ // clear old result, and copy new
+ maNodes.clear();
+ if( mxResult.is() )
+ {
+ // copy node list
+ Reference<XNodeList> xNodeList = mxResult->getNodeList();
+ OSL_ENSURE( xNodeList.is(), "empty object (instead of empty list)" );
+ sal_Int32 nLength = xNodeList.is() ? xNodeList->getLength() : 0;
+ for( sal_Int32 n = 0; n < nLength; n++ )
+ maNodes.push_back( xNodeList->item( n ) );
+ }
+
+ return bResult;
+}
+
+
+Reference<XNode> PathExpression::getNode() const
+{
+ Reference<XNode> xResult;
+ if( ! maNodes.empty() )
+ xResult = *maNodes.begin();
+ return xResult;
+}
+
+const PathExpression::NodeVector_t PathExpression::getNodeList() const
+{
+ return maNodes;
+}
+
+Reference<XNodeList> PathExpression::getXNodeList() const
+{
+ return mxResult.is() ? mxResult->getNodeList() : Reference<XNodeList>();
+}
+
+
+} // namespace xforms
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/pathexpression.hxx b/forms/source/xforms/pathexpression.hxx
new file mode 100644
index 000000000000..a6d89186e9ff
--- /dev/null
+++ b/forms/source/xforms/pathexpression.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _PATHEXPRESSION_HXX
+#define _PATHEXPRESSION_HXX
+
+
+// include for parent class
+#include "computedexpression.hxx"
+
+// includes for member variables
+#include <vector>
+
+// forward declaractions
+namespace com { namespace sun { namespace star
+{
+ namespace xml { namespace dom
+ {
+ class XNodeList;
+ namespace events { class XEventListener; }
+ } }
+} } }
+
+
+
+namespace xforms
+{
+
+/** PathExpression represents an XPath Expression and caches results */
+class PathExpression : public ComputedExpression
+{
+public:
+ typedef std::vector<com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> > NodeVector_t;
+
+private:
+ /// the node-list result from the last bind (cached from mxResult)
+ NodeVector_t maNodes;
+
+protected:
+ /// get expression for evaluation
+ const rtl::OUString _getExpressionForEvaluation() const;
+
+
+public:
+ PathExpression();
+ ~PathExpression();
+
+ /// set the expression string
+ /// (overridden to do remove old listeners)
+ /// (also defines simple expressions)
+ void setExpression( const rtl::OUString& rExpression );
+
+
+ /// evaluate the expression relative to the content node.
+ bool evaluate( const xforms::EvaluationContext& rContext );
+
+
+ // get the result of this expression as node/node list/...
+ com::sun::star::uno::Reference<com::sun::star::xml::dom::XNode> getNode() const;
+ const NodeVector_t getNodeList() const;
+ com::sun::star::uno::Reference<com::sun::star::xml::dom::XNodeList> getXNodeList() const;
+
+};
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/propertysetbase.cxx b/forms/source/xforms/propertysetbase.cxx
new file mode 100644
index 000000000000..dd2c3f139098
--- /dev/null
+++ b/forms/source/xforms/propertysetbase.cxx
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "propertysetbase.hxx"
+
+#include <cppuhelper/typeprovider.hxx> // for getImplementationId()
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <tools/debug.hxx>
+
+#include <vector>
+
+using com::sun::star::uno::Any;
+using com::sun::star::uno::Type;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Exception;
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::lang::IllegalArgumentException;
+using com::sun::star::beans::Property;
+using com::sun::star::beans::XPropertySetInfo;
+
+oslInterlockedCount SAL_CALL PropertyAccessorBase::acquire()
+{
+ return ++m_refCount;
+}
+
+oslInterlockedCount SAL_CALL PropertyAccessorBase::release()
+{
+ if ( --m_refCount == 0 )
+ {
+ delete this;
+ return 0;
+ }
+ return m_refCount;
+}
+
+PropertySetBase::PropertySetBase( )
+ :m_pProperties( NULL )
+{
+}
+
+PropertySetBase::~PropertySetBase( )
+{
+ DELETEZ( m_pProperties );
+}
+
+cppu::IPropertyArrayHelper& SAL_CALL PropertySetBase::getInfoHelper()
+{
+ if ( !m_pProperties )
+ {
+ DBG_ASSERT( !m_aProperties.empty(), "PropertySetBase::getInfoHelper: no registered properties!" );
+ m_pProperties = new cppu::OPropertyArrayHelper( &m_aProperties[0], m_aProperties.size(), sal_False );
+ }
+ return *m_pProperties;
+}
+
+Reference< XPropertySetInfo > SAL_CALL PropertySetBase::getPropertySetInfo( ) throw(RuntimeException)
+{
+ return cppu::OPropertySetHelper::createPropertySetInfo( getInfoHelper() );
+}
+
+void PropertySetBase::registerProperty( const Property& rProperty,
+ const ::rtl::Reference< PropertyAccessorBase >& rAccessor )
+{
+ DBG_ASSERT( rAccessor.get(), "PropertySetBase::registerProperty: invalid property accessor, this will crash!" );
+ m_aAccessors.insert( PropertyAccessors::value_type( rProperty.Handle, rAccessor ) );
+
+ DBG_ASSERT( ( rAccessor->isWriteable() == true )
+ == ( ( rProperty.Attributes & com::sun::star::beans::PropertyAttribute::READONLY ) == 0 ),
+ "PropertySetBase::registerProperty: inconsistence!" );
+
+ m_aProperties.push_back( rProperty );
+}
+
+void PropertySetBase::notifyAndCachePropertyValue( sal_Int32 nHandle )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+
+ PropertyValueCache::iterator aPos = m_aCache.find( nHandle );
+ if ( aPos == m_aCache.end() )
+ { // method has never before been invoked for this property
+ try
+ {
+ // determine the type of this property
+ ::cppu::IPropertyArrayHelper& rPropertyMetaData = getInfoHelper();
+ ::rtl::OUString sPropName;
+ OSL_VERIFY( rPropertyMetaData.fillPropertyMembersByHandle( &sPropName, NULL, nHandle ) );
+ Property aProperty = rPropertyMetaData.getPropertyByName( sPropName );
+ // default construct a value of this type
+ Any aEmptyValue( NULL, aProperty.Type );
+ // insert into the cache
+ aPos = m_aCache.insert( PropertyValueCache::value_type( nHandle, aEmptyValue ) ).first;
+ }
+ catch( Exception& )
+ {
+ DBG_ERROR( "PropertySetBase::notifyAndCachePropertyValue: this is not expected to fail!" );
+ }
+ }
+ Any aOldValue = aPos->second;
+ // determine the current value
+ Any aNewValue;
+ getFastPropertyValue( aNewValue, nHandle );
+ // remember the old value
+ aPos->second = aNewValue;
+
+ aGuard.clear();
+ if ( aNewValue != aOldValue )
+ firePropertyChange( nHandle, aNewValue, aOldValue );
+}
+
+void PropertySetBase::initializePropertyValueCache( sal_Int32 nHandle )
+{
+ Any aCurrentValue;
+ getFastPropertyValue( aCurrentValue, nHandle );
+
+#if OSL_DEBUG_LEVEL > 0
+ ::std::pair< PropertyValueCache::iterator, bool > aInsertResult =
+#endif
+ m_aCache.insert( PropertyValueCache::value_type( nHandle, aCurrentValue ) );
+ DBG_ASSERT( aInsertResult.second, "PropertySetBase::initializePropertyValueCache: already cached a value for this property!" );
+}
+
+PropertyAccessorBase& PropertySetBase::locatePropertyHandler( sal_Int32 nHandle ) const
+{
+ PropertyAccessors::const_iterator aPropertyPos = m_aAccessors.find( nHandle );
+ DBG_ASSERT( aPropertyPos != m_aAccessors.end() && aPropertyPos->second.get(),
+ "PropertySetBase::locatePropertyHandler: accessor map is corrupted!" );
+ // neither should this be called for handles where there is no accessor, nor should a
+ // NULL accssor be in the map
+ return *aPropertyPos->second;
+}
+
+sal_Bool SAL_CALL PropertySetBase::convertFastPropertyValue( Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle,
+ const Any& rValue )
+ throw (IllegalArgumentException)
+{
+ PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle );
+ if ( !rAccessor.approveValue( rValue ) )
+ throw IllegalArgumentException( ::rtl::OUString(), *this, 0 );
+
+ rAccessor.getValue( rOldValue );
+ if ( rOldValue != rValue )
+ {
+ rConvertedValue = rValue; // no conversion at all
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void SAL_CALL PropertySetBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+ throw (Exception)
+{
+ PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle );
+ rAccessor.setValue( rValue );
+}
+
+void SAL_CALL PropertySetBase::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
+{
+ PropertyAccessorBase& rAccessor = locatePropertyHandler( nHandle );
+ rAccessor.getValue( rValue );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/propertysetbase.hxx b/forms/source/xforms/propertysetbase.hxx
new file mode 100644
index 000000000000..27556b1381f8
--- /dev/null
+++ b/forms/source/xforms/propertysetbase.hxx
@@ -0,0 +1,374 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _PROPERTYSETBASE_HXX
+#define _PROPERTYSETBASE_HXX
+
+
+// include for parent class
+#include <cppuhelper/weak.hxx>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <comphelper/propstate.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <rtl/ref.hxx>
+
+// include for inlined helper function below
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <map>
+
+// forward declarations for method arguments
+namespace com { namespace sun { namespace star { namespace uno {
+ class Any;
+ class Type;
+ class RuntimeException;
+ template<class T> class Sequence;
+} } } }
+
+/** base class which encapsulates accessing (reading/writing) concrete property values
+*/
+class PropertyAccessorBase : public ::rtl::IReference
+{
+private:
+ oslInterlockedCount m_refCount;
+
+protected:
+ PropertyAccessorBase() : m_refCount( 0 ) { }
+
+public:
+ virtual oslInterlockedCount SAL_CALL acquire();
+ virtual oslInterlockedCount SAL_CALL release();
+
+ virtual bool approveValue( const com::sun::star::uno::Any& rValue ) const = 0;
+ virtual void setValue( const com::sun::star::uno::Any& rValue ) = 0;
+ virtual void getValue( com::sun::star::uno::Any& rValue ) const = 0;
+ virtual bool isWriteable() const = 0;
+};
+
+
+/** helper class for implementing property accessors through public member functions
+*/
+template< typename CLASS, typename VALUE, class WRITER, class READER >
+class GenericPropertyAccessor : public PropertyAccessorBase
+{
+public:
+ typedef WRITER Writer;
+ typedef READER Reader;
+
+private:
+ CLASS* m_pInstance;
+ Writer m_pWriter;
+ Reader m_pReader;
+
+public:
+ GenericPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
+ :m_pInstance( pInstance )
+ ,m_pWriter( pWriter )
+ ,m_pReader( pReader )
+ {
+ }
+
+ virtual bool approveValue( const com::sun::star::uno::Any& rValue ) const
+ {
+ VALUE aVal;
+ return ( rValue >>= aVal );
+ }
+
+ virtual void setValue( const com::sun::star::uno::Any& rValue )
+ {
+ VALUE aTypedVal = VALUE();
+ OSL_VERIFY( rValue >>= aTypedVal );
+ (m_pInstance->*m_pWriter)( aTypedVal );
+ }
+
+ virtual void getValue( com::sun::star::uno::Any& rValue ) const
+ {
+ rValue = com::sun::star::uno::makeAny( (m_pInstance->*m_pReader)() );
+ }
+
+ virtual bool isWriteable() const
+ {
+ return m_pWriter != NULL;
+ }
+};
+
+/** helper class for implementing property accessors via non-UNO methods
+*/
+template< typename CLASS, typename VALUE >
+class DirectPropertyAccessor
+ :public GenericPropertyAccessor < CLASS
+ , VALUE
+ , void (CLASS::*)( const VALUE& )
+ , VALUE (CLASS::*)() const
+ >
+{
+protected:
+ typedef void (CLASS::*Writer)( const VALUE& );
+ typedef VALUE (CLASS::*Reader)() const;
+public:
+ DirectPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
+ :GenericPropertyAccessor< CLASS, VALUE, Writer, Reader >( pInstance, pWriter, pReader )
+ {
+ }
+};
+
+/** helper class for implementing non-UNO accessors to a boolean property
+*/
+template< typename CLASS, typename DUMMY >
+class BooleanPropertyAccessor
+ :public GenericPropertyAccessor < CLASS
+ , bool
+ , void (CLASS::*)( bool )
+ , bool (CLASS::*)() const
+ >
+{
+protected:
+ typedef void (CLASS::*Writer)( bool );
+ typedef bool (CLASS::*Reader)() const;
+public:
+ BooleanPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
+ :GenericPropertyAccessor< CLASS, bool, Writer, Reader >( pInstance, pWriter, pReader )
+ {
+ }
+};
+
+/** helper class for implementing property accessors via UNO methods
+*/
+template< typename CLASS, typename VALUE >
+class APIPropertyAccessor
+ :public GenericPropertyAccessor < CLASS
+ , VALUE
+ , void (SAL_CALL CLASS::*)( const VALUE& )
+ , VALUE (SAL_CALL CLASS::*)()
+ >
+{
+protected:
+ typedef void (SAL_CALL CLASS::*Writer)( const VALUE& );
+ typedef VALUE (SAL_CALL CLASS::*Reader)();
+public:
+ APIPropertyAccessor( CLASS* pInstance, Writer pWriter, Reader pReader )
+ :GenericPropertyAccessor< CLASS, VALUE, Writer, Reader >( pInstance, pWriter, pReader )
+ {
+ }
+};
+
+/** bridges two XPropertySet helper implementations
+
+ The <type scope="comphelper">OStatefulPropertySet</type> (basically, the
+ <type scope="cppu">OPropertySetHelper</type>) implements a comprehensive framework
+ for property sets, including property change notifications.
+ However, it lacks some easy possibilities to declare the supported properties.
+ Other helper structs and classes allow for this, but are lacking needed features
+ such as property change notifications.
+
+ The <type>PropertySetBase</type> bridges various implementations,
+ so you have the best of both worlds.
+ */
+class PropertySetBase : public ::comphelper::OStatefulPropertySet
+{
+private:
+ typedef com::sun::star::uno::Any Any_t;
+
+ typedef ::std::map< const sal_Int32, ::rtl::Reference< PropertyAccessorBase > > PropertyAccessors;
+ typedef ::std::vector< ::com::sun::star::beans::Property > PropertyArray;
+ typedef ::std::map< const sal_Int32, Any_t > PropertyValueCache;
+
+ PropertyArray m_aProperties;
+ cppu::IPropertyArrayHelper* m_pProperties;
+ PropertyAccessors m_aAccessors;
+ PropertyValueCache m_aCache;
+
+protected:
+ PropertySetBase();
+ virtual ~PropertySetBase();
+
+ /** registers a new property to be supported by this instance
+ @param rProperty
+ the descriptor for the to-be-supported property
+ @param rAccessor
+ an instance which is able to provide read and possibly write access to
+ the property.
+ @precond
+ Must not be called after any of the property set related UNO interfaces
+ has been used. Usually, you will do a number of <member>registerProperty</member>
+ calls in the constructor of your class.
+ */
+ void registerProperty(
+ const com::sun::star::beans::Property& rProperty,
+ const ::rtl::Reference< PropertyAccessorBase >& rAccessor
+ );
+
+ /** notifies a change in a given property value, if necessary
+
+ The necessity of the notification is determined by a cached value for the given
+ property. Caching happens after notification.
+
+ That is, when you call <member>notifyAndCachePropertyValue</member> for the first time,
+ a value for the given property is default constructed, and considered to be the "old value".
+ If this value differs from the current value, then this change is notified to all interested
+ listeners. Finally, the current value is remembered.
+
+ Subsequent calls to <member>notifyAndCachePropertyValue</member> use the remembered value as
+ "old value", and from then on behave as the first call.
+
+ @param nHandle
+ the handle of the property. Must denote a property supported by this instance, i.e.
+ one previously registered via <member>registerProperty</member>.
+
+ @precond
+ our ref count must not be 0. The reason is that during this method's execution,
+ the instance might be acquired and released, which would immediately destroy
+ the instance if it has a ref count of 0.
+
+ @seealso initializePropertyValueCache
+ */
+ void notifyAndCachePropertyValue( sal_Int32 nHandle );
+
+ /** initializes the property value cache for the given property, with its current value
+
+ Usually used to initialize the cache with values which are different from default
+ constructed values. Say you have a boolean property whose initial state
+ is <TRUE/>. Say you call <member>notifyAndCachePropertyValue</member> the first time: it will
+ default construct the "old value" for this property as <FALSE/>, and thus <b>not</b> do
+ any notifications if the "current value" is also <FALSE/> - which might be wrong, since
+ the guessing of the "old value" differed from the real initial value which was <TRUE/>.
+
+ Too confusing? Okay, than just call this method for every property you have.
+
+ @param nHandle
+ the handle of the property. Must denote a property supported by this instance, i.e.
+ one previously registered via <member>registerProperty</member>.
+ @param rValue
+ the value to cache
+ @seealso notifyAndCachePropertyValue
+ */
+ void initializePropertyValueCache( sal_Int32 nHandle );
+
+ /// OPropertysetHelper methods
+ virtual sal_Bool SAL_CALL convertFastPropertyValue( Any_t& rConvertedValue, Any_t& rOldValue, sal_Int32 nHandle, const Any_t& rValue )
+ throw (::com::sun::star::lang::IllegalArgumentException);
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any_t& rValue )
+ throw (::com::sun::star::uno::Exception);
+ virtual void SAL_CALL getFastPropertyValue( Any_t& rValue, sal_Int32 nHandle ) const;
+
+ virtual cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException);
+
+public:
+ /// helper struct for granting selective access to some notification-related methods
+ struct NotifierAccess { friend struct PropertyChangeNotifier; private: NotifierAccess() { } };
+ /** retrieves the current property value for the given handle
+ @param nHandle
+ the handle of the property. Must denote a property supported by this instance, i.e.
+ one previously registered via <member>registerProperty</member>.
+ @see registerProperty
+ */
+ inline void getCurrentPropertyValueByHandle( sal_Int32 nHandle, Any_t& /* [out] */ rValue, const NotifierAccess& ) const
+ {
+ getFastPropertyValue( rValue, nHandle );
+ }
+
+ /** notifies a change in a given property to all interested listeners
+ */
+ inline void notifyPropertyChange( sal_Int32 nHandle, const Any_t& rOldValue, const Any_t& rNewValue, const NotifierAccess& ) const
+ {
+ const_cast< PropertySetBase* >( this )->firePropertyChange( nHandle, rNewValue, rOldValue );
+ }
+
+ using ::comphelper::OStatefulPropertySet::getFastPropertyValue;
+
+private:
+ /** locates a property given by handle
+ @param nHandle
+ the handle of the property. Must denote a property supported by this instance, i.e.
+ one previously registered via <member>registerProperty</member>.
+ @see registerProperty
+ */
+ PropertyAccessorBase& locatePropertyHandler( sal_Int32 nHandle ) const;
+};
+
+/** a helper class for notifying property changes in a <type>PropertySetBase</type> instance.
+
+ You can create an instance of this class on the stack of a method which is to programmatically
+ change the value of a property. In its constructor, the instance will acquire the current property
+ value, and in its destructor, it will notify the change of this property's value (if necessary).
+
+ You do not need this class if you are modifying property values by using the X(Fast|Multi)PropertSet
+ methods, since those already care for property notifications. You only need it if you're changing
+ the internal representation of your property directly.
+
+ Also note that usually, notifications in the UNO world should be done without a locked mutex. So
+ if you use this class in conjunction with a <type>MutexGuard</type>, ensure that you <b>first</b>
+ instantiate the <type>PropertyChangeNotifier</type>, and <b>then</b> the <type>MutexGuard</type>,
+ so your mutex is released before the notification happens.
+*/
+struct PropertyChangeNotifier
+{
+private:
+ const PropertySetBase& m_rPropertySet;
+ sal_Int32 m_nHandle;
+ com::sun::star::uno::Any m_aOldValue;
+
+public:
+ /** constructs a PropertyChangeNotifier
+ @param rPropertySet
+ the property set implementation whose property is going to be changed. Note
+ that this property set implementation must live at least as long as the
+ PropertyChangeNotifier instance does.
+ @param nHandle
+ the handle of the property which is going to be changed. Must be a valid property
+ handle for the given <arg>rPropertySet</arg>
+ */
+ inline PropertyChangeNotifier( const PropertySetBase& rPropertySet, sal_Int32 nHandle )
+ :m_rPropertySet( rPropertySet )
+ ,m_nHandle( nHandle )
+ {
+ m_rPropertySet.getCurrentPropertyValueByHandle( m_nHandle, m_aOldValue, PropertySetBase::NotifierAccess() );
+ }
+ inline ~PropertyChangeNotifier()
+ {
+ com::sun::star::uno::Any aNewValue;
+ m_rPropertySet.getCurrentPropertyValueByHandle( m_nHandle, aNewValue, PropertySetBase::NotifierAccess() );
+ if ( aNewValue != m_aOldValue )
+ {
+ m_rPropertySet.notifyPropertyChange( m_nHandle, m_aOldValue, aNewValue, PropertySetBase::NotifierAccess() );
+ }
+ }
+};
+
+
+#define PROPERTY_FLAGS( NAME, TYPE, FLAG ) com::sun::star::beans::Property( \
+ ::rtl::OUString( #NAME, sizeof( #NAME ) - 1, RTL_TEXTENCODING_ASCII_US ), \
+ HANDLE_##NAME, getCppuType( static_cast< TYPE* >( NULL ) ), FLAG )
+#define PROPERTY( NAME, TYPE ) PROPERTY_FLAGS( NAME, TYPE, com::sun::star::beans::PropertyAttribute::BOUND )
+#define PROPERTY_RO( NAME, TYPE ) PROPERTY_FLAGS( NAME, TYPE, com::sun::star::beans::PropertyAttribute::BOUND | com::sun::star::beans::PropertyAttribute::READONLY )
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/resourcehelper.cxx b/forms/source/xforms/resourcehelper.cxx
new file mode 100644
index 000000000000..1fec9f3502d0
--- /dev/null
+++ b/forms/source/xforms/resourcehelper.cxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "resourcehelper.hxx"
+#include "frm_resource.hxx"
+
+#include <rtl/ustring.hxx>
+#include <tools/string.hxx>
+
+using rtl::OUString;
+
+#define OUSTRING(x) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(x))
+
+namespace xforms
+{
+
+OUString getResource( sal_uInt16 nResourceId )
+{
+ return getResource( nResourceId, OUString(), OUString(), OUString() );
+}
+
+OUString getResource( sal_uInt16 nResourceId,
+ const OUString& rInfo1 )
+{
+ return getResource( nResourceId, rInfo1, OUString(), OUString() );
+}
+
+OUString getResource( sal_uInt16 nResourceId,
+ const OUString& rInfo1,
+ const OUString& rInfo2 )
+{
+ return getResource( nResourceId, rInfo1, rInfo2, OUString() );
+}
+
+OUString getResource( sal_uInt16 nResourceId,
+ const OUString& rInfo1,
+ const OUString& rInfo2,
+ const OUString& rInfo3 )
+{
+ OUString sResource = frm::ResourceManager::loadString( nResourceId );
+ OSL_ENSURE( sResource.getLength() > 0, "resource not found?" );
+
+ // use old style String class for search and replace, so we don't have to
+ // code this again.
+ String sString( sResource );
+ sString.SearchAndReplaceAll( String(OUSTRING("$1")), String(rInfo1) );
+ sString.SearchAndReplaceAll( String(OUSTRING("$2")), String(rInfo2) );
+ sString.SearchAndReplaceAll( String(OUSTRING("$3")), String(rInfo3) );
+ return OUString( sString );
+}
+
+} // namespace xforms
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/resourcehelper.hxx b/forms/source/xforms/resourcehelper.hxx
new file mode 100644
index 000000000000..0b429cd0eeb7
--- /dev/null
+++ b/forms/source/xforms/resourcehelper.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _RESOURCEHELPER_HXX
+#define _RESOURCEHELPER_HXX
+
+// include resource IDs
+#include <frm_resource.hrc>
+
+#include <sal/types.h>
+
+namespace rtl { class OUString; }
+
+namespace xforms
+{
+ /// get a resource string for the current language
+ rtl::OUString getResource( sal_uInt16 );
+
+ // overloaded: get a resource string, and substitute parameters
+ rtl::OUString getResource( sal_uInt16, const rtl::OUString& );
+ rtl::OUString getResource( sal_uInt16, const rtl::OUString&,
+ const rtl::OUString& );
+ rtl::OUString getResource( sal_uInt16, const rtl::OUString&,
+ const rtl::OUString&,
+ const rtl::OUString& );
+
+} // namespace
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission.cxx b/forms/source/xforms/submission.cxx
new file mode 100644
index 000000000000..aece48afe574
--- /dev/null
+++ b/forms/source/xforms/submission.cxx
@@ -0,0 +1,721 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+#include "submission.hxx"
+
+#include "model.hxx"
+#include "binding.hxx"
+#include "mip.hxx"
+#include "evaluationcontext.hxx"
+#include "unohelper.hxx"
+#include "submission/submission_put.hxx"
+#include "submission/submission_post.hxx"
+#include "submission/submission_get.hxx"
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xforms/XModel.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/xml/xpath/XXPathObject.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/xml/xpath/XPathObjectType.hpp>
+#include <com/sun/star/xml/dom/XNodeList.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
+#include <com/sun/star/xml/dom/XDocumentFragment.hpp>
+#include <com/sun/star/xml/dom/NodeType.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/task/XInteractionRequest.hpp>
+#include <com/sun/star/task/XInteractionContinuation.hpp>
+#include <com/sun/star/xforms/InvalidDataOnSubmitException.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <cppuhelper/typeprovider.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/interaction.hxx>
+#include <unotools/processfactory.hxx>
+#include <memory>
+
+
+
+
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using com::sun::star::beans::UnknownPropertyException;
+using com::sun::star::beans::PropertyVetoException;
+using com::sun::star::lang::IllegalArgumentException;
+using com::sun::star::util::VetoException;
+using com::sun::star::form::submission::XSubmissionVetoListener;
+using com::sun::star::lang::WrappedTargetException;
+using com::sun::star::lang::NoSupportException;
+using com::sun::star::task::XInteractionHandler;
+using com::sun::star::task::XInteractionRequest;
+using com::sun::star::task::XInteractionContinuation;
+using com::sun::star::xforms::XModel;
+using com::sun::star::xforms::InvalidDataOnSubmitException;
+using com::sun::star::container::XNameAccess;
+using com::sun::star::xml::xpath::XXPathObject;
+using com::sun::star::xml::xpath::XPathObjectType;
+using com::sun::star::frame::XFrame;
+using xforms::Submission;
+using xforms::Model;
+using xforms::MIP;
+using std::auto_ptr;
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::xml::dom;
+
+Submission::Submission() :
+ msID(),
+ msBind(),
+ maRef(),
+ msAction(),
+ msMethod(),
+ msVersion(),
+ mbIndent(),
+ msMediaType(),
+ msEncoding(),
+ mbOmitXmlDeclaration(),
+ mbStandalone(),
+ msCDataSectionElement(),
+ msReplace( OUSTRING("none") ),
+ msSeparator(),
+ msIncludeNamespacePrefixes(),
+ m_aFactory(utl::getProcessServiceFactory())
+{
+ initializePropertySet();
+}
+
+Submission::~Submission() throw()
+{
+}
+
+Reference<XModel> Submission::getModel() const
+{
+ return mxModel;
+}
+
+void Submission::setModel( const Reference<XModel>& xModel )
+{
+ mxModel = xModel;
+}
+
+OUString Submission::getID() const
+{
+ return msID;
+}
+
+void Submission::setID( const OUString& sID )
+{
+ msID = sID;
+}
+
+OUString Submission::getBind() const
+{
+ return msBind;
+}
+
+void Submission::setBind( const OUString& sBind )
+{
+ msBind = sBind;
+}
+
+OUString Submission::getRef() const
+{
+ return maRef.getExpression();
+}
+
+void Submission::setRef( const OUString& sRef )
+{
+ maRef.setExpression( sRef );
+}
+
+OUString Submission::getAction() const
+{
+ return msAction;
+}
+
+void Submission::setAction( const OUString& sAction )
+{
+ msAction = sAction;
+}
+
+OUString Submission::getMethod() const
+{
+ return msMethod;
+}
+
+void Submission::setMethod( const OUString& sMethod )
+{
+ msMethod = sMethod;
+}
+
+OUString Submission::getVersion() const
+{
+ return msVersion;
+}
+
+void Submission::setVersion( const OUString& sVersion )
+{
+ msVersion = sVersion;
+}
+
+bool Submission::getIndent() const
+{
+ return mbIndent;
+}
+
+void Submission::setIndent( bool bIndent )
+{
+ mbIndent = bIndent;
+}
+
+OUString Submission::getMediaType() const
+{
+ return msMediaType;
+}
+
+void Submission::setMediaType( const OUString& sMediaType )
+{
+ msMediaType = sMediaType;
+}
+
+OUString Submission::getEncoding() const
+{
+ return msEncoding;
+}
+
+void Submission::setEncoding( const OUString& sEncoding )
+{
+ msEncoding = sEncoding;
+}
+
+bool Submission::getOmitXmlDeclaration() const
+{
+ return mbOmitXmlDeclaration;
+}
+
+void Submission::setOmitXmlDeclaration( bool bOmitXmlDeclaration )
+{
+ mbOmitXmlDeclaration = bOmitXmlDeclaration;
+}
+
+bool Submission::getStandalone() const
+{
+ return mbStandalone;
+}
+
+void Submission::setStandalone( bool bStandalone )
+{
+ mbStandalone = bStandalone;
+}
+
+OUString Submission::getCDataSectionElement() const
+{
+ return msCDataSectionElement;
+}
+
+void Submission::setCDataSectionElement( const OUString& sCDataSectionElement )
+{
+ msCDataSectionElement = sCDataSectionElement;
+}
+
+OUString Submission::getReplace() const
+{
+ return msReplace;
+}
+
+void Submission::setReplace( const OUString& sReplace )
+{
+ msReplace = sReplace;
+}
+
+OUString Submission::getSeparator() const
+{
+ return msSeparator;
+}
+
+void Submission::setSeparator( const OUString& sSeparator )
+{
+ msSeparator = sSeparator;
+}
+
+Sequence< OUString > Submission::getIncludeNamespacePrefixes() const
+{
+ return msIncludeNamespacePrefixes;
+}
+
+void Submission::setIncludeNamespacePrefixes( const Sequence< OUString >& rIncludeNamespacePrefixes )
+{
+ msIncludeNamespacePrefixes = rIncludeNamespacePrefixes;
+}
+
+bool Submission::doSubmit( const Reference< XInteractionHandler >& xHandler )
+{
+ liveCheck();
+
+ // construct XXPathObject for submission doc; use bind in preference of ref
+ EvaluationContext aEvalContext;
+ ComputedExpression aExpression;
+ if( msBind.getLength() != 0 )
+ {
+ Binding* pBinding = Binding::getBinding( mxModel->getBinding(msBind) );
+ if( pBinding != NULL )
+ {
+ aExpression.setExpression( pBinding->getBindingExpression() );
+ aEvalContext = pBinding->getEvaluationContext();
+ }
+ // TODO: else: illegal binding name -> raise error
+ }
+ else if( maRef.getExpression().getLength() != 0 )
+ {
+ aExpression.setExpression( maRef.getExpression() );
+ aEvalContext = Model::getModel( mxModel )->getEvaluationContext();
+ }
+ else
+ {
+ aExpression.setExpression( OUSTRING( "/" ) );
+ aEvalContext = Model::getModel( mxModel )->getEvaluationContext();
+ }
+ aExpression.evaluate( aEvalContext );
+ Reference<XXPathObject> xResult = aExpression.getXPath();
+ OSL_ENSURE( xResult.is(), "no result?" );
+
+ // early out if we have not obtained any result
+ if( ! xResult.is() )
+ return false;
+
+
+ // Reference< XNodeList > aList = xResult->getNodeList();
+ OUString aMethod = getMethod();
+
+ // strip whitespace-only text node for get submission
+ Reference< XDocumentFragment > aFragment = createSubmissionDocument(
+ xResult, aMethod.equalsIgnoreAsciiCaseAscii("get"));
+
+ // submit result; set encoding, etc.
+ auto_ptr<CSubmission> xSubmission;
+ if (aMethod.equalsIgnoreAsciiCaseAscii("PUT"))
+ xSubmission = auto_ptr<CSubmission>(
+ new CSubmissionPut( getAction(), aFragment));
+ else if (aMethod.equalsIgnoreAsciiCaseAscii("post"))
+ xSubmission = auto_ptr<CSubmission>(
+ new CSubmissionPost( getAction(), aFragment));
+ else if (aMethod.equalsIgnoreAsciiCaseAscii("get"))
+ xSubmission = auto_ptr<CSubmission>(
+ new CSubmissionGet( getAction(), aFragment));
+ else
+ {
+ OSL_ENSURE(sal_False, "Unsupported xforms submission method");
+ return false;
+ }
+
+ xSubmission->setEncoding(getEncoding());
+ CSubmission::SubmissionResult aResult = xSubmission->submit( xHandler );
+
+ if (aResult == CSubmission::SUCCESS)
+ {
+ Reference< XDocument > aInstanceDoc = getInstanceDocument(xResult);
+ aResult = xSubmission->replace(getReplace(), aInstanceDoc, Reference< XFrame >());
+ }
+
+ return ( aResult == CSubmission::SUCCESS );
+}
+
+Sequence<sal_Int8> Submission::getUnoTunnelID()
+{
+ static cppu::OImplementationId aImplementationId;
+ return aImplementationId.getImplementationId();
+}
+
+Submission* Submission::getSubmission(
+ const Reference<XPropertySet>& xPropertySet )
+{
+ Reference<XUnoTunnel> xTunnel( xPropertySet, UNO_QUERY );
+ return xTunnel.is()
+ ? reinterpret_cast<Submission*>(
+ xTunnel->getSomething( getUnoTunnelID() ) )
+ : NULL;
+}
+
+
+
+
+
+
+void Submission::liveCheck()
+ throw( RuntimeException )
+{
+ bool bValid = mxModel.is();
+
+ if( ! bValid )
+ throw RuntimeException();
+}
+
+Model* Submission::getModelImpl() const
+{
+ Model* pModel = NULL;
+ if( mxModel.is() )
+ pModel = Model::getModel( mxModel );
+ return pModel;
+}
+
+
+//
+// Property-Set implementation
+//
+
+#define HANDLE_ID 0
+#define HANDLE_Bind 1
+#define HANDLE_Ref 2
+#define HANDLE_Action 3
+#define HANDLE_Method 4
+#define HANDLE_Version 5
+#define HANDLE_Indent 6
+#define HANDLE_MediaType 7
+#define HANDLE_Encoding 8
+#define HANDLE_OmitXmlDeclaration 9
+#define HANDLE_Standalone 10
+#define HANDLE_CDataSectionElement 11
+#define HANDLE_Replace 12
+#define HANDLE_Separator 13
+#define HANDLE_IncludeNamespacePrefixes 14
+#define HANDLE_Model 15
+
+#define REGISTER_PROPERTY( property, type ) \
+ registerProperty( PROPERTY( property, type ), \
+ new DirectPropertyAccessor< Submission, type >( this, &Submission::set##property, &Submission::get##property ) );
+
+#define REGISTER_PROPERTY_BOOL( property ) \
+ registerProperty( PROPERTY( property, bool ), \
+ new BooleanPropertyAccessor< Submission, bool >( this, &Submission::set##property, &Submission::get##property ) );
+
+void Submission::initializePropertySet()
+{
+ REGISTER_PROPERTY ( ID, OUString );
+ REGISTER_PROPERTY ( Bind, OUString );
+ REGISTER_PROPERTY ( Ref, OUString );
+ REGISTER_PROPERTY ( Action, OUString );
+ REGISTER_PROPERTY ( Method, OUString );
+ REGISTER_PROPERTY ( Version, OUString );
+ REGISTER_PROPERTY_BOOL( Indent );
+ REGISTER_PROPERTY ( MediaType, OUString );
+ REGISTER_PROPERTY ( Encoding, OUString );
+ REGISTER_PROPERTY_BOOL( OmitXmlDeclaration );
+ REGISTER_PROPERTY_BOOL( Standalone );
+ REGISTER_PROPERTY ( CDataSectionElement, OUString );
+ REGISTER_PROPERTY ( Replace, OUString );
+ REGISTER_PROPERTY ( Separator, OUString );
+ REGISTER_PROPERTY ( IncludeNamespacePrefixes, Sequence< OUString > );
+ REGISTER_PROPERTY ( Model, Reference<XModel> );
+
+ initializePropertyValueCache( HANDLE_Indent );
+ initializePropertyValueCache( HANDLE_OmitXmlDeclaration );
+ initializePropertyValueCache( HANDLE_Standalone );
+}
+
+sal_Bool SAL_CALL Submission::convertFastPropertyValue(
+ Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue )
+ throw ( IllegalArgumentException )
+{
+ if ( nHandle == HANDLE_IncludeNamespacePrefixes )
+ {
+ // for convinience reasons (????), we accept a string which contains
+ // a comma-separated list of namespace prefixes
+ ::rtl::OUString sTokenList;
+ if ( rValue >>= sTokenList )
+ {
+ std::vector< OUString > aPrefixes;
+ sal_Int32 p = 0;
+ while ( p >= 0 )
+ aPrefixes.push_back( sTokenList.getToken( 0, ',', p ) );
+
+ Sequence< ::rtl::OUString > aConvertedPrefixes( &aPrefixes[0], aPrefixes.size() );
+ return PropertySetBase::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, makeAny( aConvertedPrefixes ) );
+ }
+ }
+
+ return PropertySetBase::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
+}
+
+OUString SAL_CALL Submission::getName()
+ throw( RuntimeException )
+{
+ return getID();
+}
+
+void SAL_CALL Submission::setName( const OUString& sID )
+ throw( RuntimeException )
+{
+ setID( sID );
+}
+
+
+
+sal_Int64 SAL_CALL Submission::getSomething(
+ const Sequence<sal_Int8>& aId )
+ throw( RuntimeException )
+{
+ return ( aId == getUnoTunnelID() ) ? reinterpret_cast<sal_Int64>(this) : 0;
+}
+
+
+OUString lcl_message( const OUString& rID, const OUString& rText )
+{
+ OUStringBuffer aMessage;
+ aMessage.append( OUSTRING("XForms submission '") );
+ aMessage.append( rID );
+ aMessage.append( OUSTRING("' failed") );
+ aMessage.append( rText );
+ aMessage.append( OUSTRING(".") );
+ return aMessage.makeStringAndClear();
+}
+
+void SAL_CALL Submission::submitWithInteraction(
+ const Reference<XInteractionHandler>& _rxHandler )
+ throw ( VetoException,
+ WrappedTargetException,
+ RuntimeException )
+{
+ // as long as this class is not really threadsafe, we need to copy
+ // the members we're interested in
+ Reference< XModel > xModel( mxModel );
+ ::rtl::OUString sID( msID );
+
+ if ( !xModel.is() || !msID.getLength() )
+ throw RuntimeException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "This is not a valid submission object." ) ),
+ *this
+ );
+
+ Model* pModel = Model::getModel( xModel );
+ OSL_ENSURE( pModel != NULL, "illegal model?" );
+
+ // #i36765# #i47248# warning on submission of illegal data
+ // check for validity (and query user if invalid)
+ bool bValid = pModel->isValid();
+ if( ! bValid )
+ {
+ InvalidDataOnSubmitException aInvalidDataException(
+ lcl_message(sID, OUSTRING(" due to invalid data") ), *this );
+
+ if( _rxHandler.is() )
+ {
+ // labouriously create interaction request
+ comphelper::OInteractionRequest* pRequest
+ = new comphelper::OInteractionRequest(
+ makeAny( aInvalidDataException ) );
+ Reference<XInteractionRequest> xRequest = pRequest;
+
+ comphelper::OInteractionApprove* pContinue
+ = new comphelper::OInteractionApprove();
+ Reference<XInteractionContinuation> xContinue = pContinue;
+ pRequest->addContinuation( xContinue );
+
+ comphelper::OInteractionDisapprove* pCancel
+ = new comphelper::OInteractionDisapprove();
+ Reference<XInteractionContinuation> xCancel = pCancel;
+ pRequest->addContinuation( xCancel );
+
+ // ask the handler...
+ _rxHandler->handle( xRequest );
+ OSL_ENSURE( pContinue->wasSelected() || pCancel->wasSelected(),
+ "handler didn't select" );
+
+ // and continue, if user chose 'continue'
+ if( pContinue->wasSelected() )
+ bValid = true;
+ }
+
+ // abort if invalid (and user didn't tell us to continue)
+ if( ! bValid )
+ throw aInvalidDataException;
+ }
+
+ // attempt submission
+ bool bResult = false;
+ try
+ {
+ bResult = doSubmit( _rxHandler );
+ }
+ catch( const VetoException& )
+ {
+ OSL_ENSURE( sal_False, "Model::submit: Hmm. How can a single submission have a veto right?" );
+ // allowed to leave
+ throw;
+ }
+ catch( const Exception& e )
+ {
+ // exception caught: re-throw as wrapped target exception
+ throw WrappedTargetException(
+ lcl_message( sID, OUSTRING(" due to exception being thrown") ),
+ *this, makeAny( e ) );
+ }
+
+ if( bResult )
+ {
+ mxModel->rebuild();
+ }
+ else
+ {
+ // other failure: throw wrapped target exception, too.
+ throw WrappedTargetException(
+ lcl_message( sID, OUString() ), *this, Any() );
+ }
+}
+
+void SAL_CALL Submission::submit( ) throw ( VetoException, WrappedTargetException, RuntimeException )
+{
+ submitWithInteraction( NULL );
+}
+
+void SAL_CALL Submission::addSubmissionVetoListener( const Reference< XSubmissionVetoListener >& /*listener*/ ) throw (NoSupportException, RuntimeException)
+{
+ // TODO
+ throw NoSupportException();
+}
+
+void SAL_CALL Submission::removeSubmissionVetoListener( const Reference< XSubmissionVetoListener >& /*listener*/ ) throw (NoSupportException, RuntimeException)
+{
+ // TODO
+ throw NoSupportException();
+}
+
+static sal_Bool _isIgnorable(const Reference< XNode >& aNode)
+{
+ // ignore whitespace-only textnodes
+ if (aNode->getNodeType() == NodeType_TEXT_NODE)
+ {
+ OUString aTrimmedValue = aNode->getNodeValue().trim();
+ if (aTrimmedValue.getLength() == 0) return sal_True;
+ }
+
+ return sal_False;
+}
+
+// recursively copy relevant nodes from A to B
+static void _cloneNodes(Model& aModel, const Reference< XNode >& dstParent, const Reference< XNode >& source, sal_Bool bRemoveWSNodes)
+{
+ if (!source.is()) return;
+
+ Reference< XNode > cur = source;
+ Reference< XDocument > dstDoc = dstParent->getOwnerDocument();
+ Reference< XNode > imported;
+
+ if (cur.is())
+ {
+ // is this node relevant?
+ MIP mip = aModel.queryMIP(cur);
+ if(mip.isRelevant() && !(bRemoveWSNodes && _isIgnorable(cur)))
+ {
+ imported = dstDoc->importNode(cur, sal_False);
+ imported = dstParent->appendChild(imported);
+ // append source children to new imported parent
+ for( cur = cur->getFirstChild(); cur.is(); cur = cur->getNextSibling() )
+ _cloneNodes(aModel, imported, cur, bRemoveWSNodes);
+ }
+ }
+}
+Reference< XDocument > Submission::getInstanceDocument(const Reference< XXPathObject >& aObj)
+{
+ using namespace com::sun::star::xml::xpath;
+ // result
+ Reference< XDocument > aDocument;
+
+ if (aObj->getObjectType() == XPathObjectType_XPATH_NODESET)
+ {
+ Reference< XNodeList > aList = aObj->getNodeList();
+ if (aList->getLength() > 0)
+ aDocument = aList->item(0)->getOwnerDocument();
+ }
+ return aDocument;
+}
+
+Reference< XDocumentFragment > Submission::createSubmissionDocument(const Reference< XXPathObject >& aObj, sal_Bool bRemoveWSNodes)
+{
+ using namespace com::sun::star::xml::xpath;
+ Reference< XDocumentBuilder > aDocBuilder(m_aFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder"))), UNO_QUERY);
+ Reference< XDocument > aDocument = aDocBuilder->newDocument();
+ Reference< XDocumentFragment > aFragment = aDocument->createDocumentFragment();
+
+ //
+ if (aObj->getObjectType() == XPathObjectType_XPATH_NODESET)
+ {
+ Reference< XNodeList > aList = aObj->getNodeList();
+ Reference< XNode > aListItem;
+ for (sal_Int32 i=0; i < aList->getLength(); i++)
+ {
+ aListItem = aList->item(i);
+ if (aListItem->getNodeType()==NodeType_DOCUMENT_NODE)
+ aListItem = Reference< XNode >(
+ (Reference< XDocument >(aListItem, UNO_QUERY))->getDocumentElement(), UNO_QUERY);
+ // copy relevant nodes from instance into fragment
+ _cloneNodes(*getModelImpl(), Reference< XNode >(aFragment, UNO_QUERY), aListItem, bRemoveWSNodes);
+ }
+ }
+ return aFragment;
+}
+
+// some forwarding: XPropertySet is implemented in our base class,
+// but also available as base of XSubmission
+Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL Submission::getPropertySetInfo( ) throw(RuntimeException)
+{
+ return PropertySetBase::getPropertySetInfo();
+}
+void SAL_CALL Submission::setPropertyValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ PropertySetBase::setPropertyValue( aPropertyName, aValue );
+}
+Any SAL_CALL Submission::getPropertyValue( const ::rtl::OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ return PropertySetBase::getPropertyValue( PropertyName );
+}
+void SAL_CALL Submission::addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ PropertySetBase::addPropertyChangeListener( aPropertyName, xListener );
+}
+void SAL_CALL Submission::removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ PropertySetBase::removePropertyChangeListener( aPropertyName, aListener );
+}
+void SAL_CALL Submission::addVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ PropertySetBase::addVetoableChangeListener( PropertyName, aListener );
+}
+void SAL_CALL Submission::removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ PropertySetBase::removeVetoableChangeListener( PropertyName, aListener );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission.hxx b/forms/source/xforms/submission.hxx
new file mode 100644
index 000000000000..b0c377844cb1
--- /dev/null
+++ b/forms/source/xforms/submission.hxx
@@ -0,0 +1,279 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SUBMISSION_HXX
+#define _SUBMISSION_HXX
+
+
+// includes for parent classes
+#include <cppuhelper/implbase2.hxx>
+#include <propertysetbase.hxx>
+#include <com/sun/star/util/XModifyBroadcaster.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/xml/dom/events/XEventListener.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/dom/XDocumentFragment.hpp>
+#include <com/sun/star/xml/xpath/XXPathObject.hpp>
+#include <com/sun/star/xforms/XSubmission.hpp>
+
+// includes for member variables
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <computedexpression.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+// forward declaractions
+namespace com { namespace sun { namespace star {
+ namespace xforms { class XModel; }
+ namespace uno { class Any; }
+ namespace beans { class UnknownPropertyException;
+ class PropertyVetoException; }
+ namespace lang { class IllegalArgumentException;
+ class WrappedTargetException; }
+} } }
+namespace xforms { class Model; }
+
+
+namespace xforms
+{
+
+/** An XForms submission.
+ *
+ * See http://www.w3.org/TR/xforms/ for more information.
+ */
+typedef cppu::ImplInheritanceHelper2<
+ PropertySetBase,
+ com::sun::star::lang::XUnoTunnel,
+ com::sun::star::xforms::XSubmission
+> Submission_t;
+
+class Submission : public Submission_t
+{
+ // submission properties
+ rtl::OUString msID;
+ rtl::OUString msBind;
+ ComputedExpression maRef;
+ rtl::OUString msAction;
+ rtl::OUString msMethod;
+ rtl::OUString msVersion;
+ bool mbIndent;
+ rtl::OUString msMediaType;
+ rtl::OUString msEncoding;
+ bool mbOmitXmlDeclaration;
+ bool mbStandalone;
+ rtl::OUString msCDataSectionElement;
+ rtl::OUString msReplace;
+ rtl::OUString msSeparator;
+ com::sun::star::uno::Sequence< rtl::OUString > msIncludeNamespacePrefixes;
+
+private:
+
+ /// the Model to which this Submission belongs; may be NULL
+ com::sun::star::uno::Reference<com::sun::star::xforms::XModel> mxModel;
+
+ // this will extract the document from the model that will be submitted
+ com::sun::star::uno::Reference< com::sun::star::xml::dom::XDocumentFragment >
+ createSubmissionDocument(const com::sun::star::uno::Reference< com::sun::star::xml::xpath::XXPathObject >& aObject,
+ sal_Bool bRemoveWSNodes = sal_False);
+ com::sun::star::uno::Reference< com::sun::star::xml::dom::XDocument >
+ getInstanceDocument(const com::sun::star::uno::Reference< com::sun::star::xml::xpath::XXPathObject >& aObject);
+
+ com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory > m_aFactory;
+public:
+ Submission();
+ virtual ~Submission() throw();
+
+ //
+ // property methods: get/set value
+ //
+
+ /// get XForms model
+ com::sun::star::uno::Reference<com::sun::star::xforms::XModel>
+ getModel() const;
+
+ /// set XForms model
+ void setModel(
+ const com::sun::star::uno::Reference<com::sun::star::xforms::XModel>& );
+
+ rtl::OUString getID() const; /// get ID for this submission
+ void setID( const rtl::OUString& ); /// set ID for this submission
+
+ rtl::OUString getBind() const;
+ void setBind( const rtl::OUString& );
+
+ rtl::OUString getRef() const;
+ void setRef( const rtl::OUString& );
+
+ rtl::OUString getAction() const;
+ void setAction( const rtl::OUString& );
+
+ rtl::OUString getMethod() const;
+ void setMethod( const rtl::OUString& );
+
+ rtl::OUString getVersion() const;
+ void setVersion( const rtl::OUString& );
+
+ bool getIndent() const;
+ void setIndent( bool );
+
+ rtl::OUString getMediaType() const;
+ void setMediaType( const rtl::OUString& );
+
+ rtl::OUString getEncoding() const;
+ void setEncoding( const rtl::OUString& );
+
+ bool getOmitXmlDeclaration() const;
+ void setOmitXmlDeclaration( bool );
+
+ bool getStandalone() const;
+ void setStandalone( bool );
+
+ rtl::OUString getCDataSectionElement() const;
+ void setCDataSectionElement( const rtl::OUString& );
+
+ rtl::OUString getReplace() const;
+ void setReplace( const rtl::OUString& );
+
+ rtl::OUString getSeparator() const;
+ void setSeparator( const rtl::OUString& );
+
+ com::sun::star::uno::Sequence< rtl::OUString > getIncludeNamespacePrefixes() const;
+ void setIncludeNamespacePrefixes( const com::sun::star::uno::Sequence< rtl::OUString >& );
+
+
+ /** perform the submission
+ * @returns if submission was successful */
+ bool doSubmit( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler );
+
+
+ /// release the model (note: Binding is unusable without model)
+ void releaseModel();
+
+
+ // helpers for UNO tunnel
+ static com::sun::star::uno::Sequence<sal_Int8> getUnoTunnelID();
+ static Submission* getSubmission( const com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>& );
+
+
+
+private:
+
+ /// check whether object is live, and throw suitable exception if not
+ /// (to be used be API methods before acting on the object)
+ void liveCheck()
+ throw( com::sun::star::uno::RuntimeException );
+
+ /// get the model implementation
+ xforms::Model* getModelImpl() const;
+ xforms::Model* getModelImpl( const com::sun::star::uno::Reference<com::sun::star::xforms::XModel>& xModel ) const;
+
+
+
+protected:
+
+ //
+ // XPropertySet & friends:
+ // implement abstract methods from PropertySetHelper
+ //
+
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ com::sun::star::uno::Any& rConvertedValue,
+ com::sun::star::uno::Any& rOldValue,
+ sal_Int32 nHandle,
+ const com::sun::star::uno::Any& rValue )
+ throw ( com::sun::star::lang::IllegalArgumentException );
+
+private:
+ void initializePropertySet();
+
+
+public:
+
+ //
+ // XNamed:
+ // get/set name
+ //
+
+ virtual rtl::OUString SAL_CALL getName()
+ throw( com::sun::star::uno::RuntimeException );
+
+ virtual void SAL_CALL setName( const rtl::OUString& )
+ throw( com::sun::star::uno::RuntimeException );
+
+
+
+ //
+ // XUnoTunnel
+ //
+
+ virtual sal_Int64 SAL_CALL getSomething(
+ const com::sun::star::uno::Sequence<sal_Int8>& )
+ throw( com::sun::star::uno::RuntimeException );
+
+
+ //
+ // XSubmission
+ //
+
+ virtual void SAL_CALL submit( )
+ throw ( com::sun::star::util::VetoException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL submitWithInteraction(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler )
+ throw ( com::sun::star::util::VetoException,
+ com::sun::star::lang::WrappedTargetException,
+ com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL addSubmissionVetoListener(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmissionVetoListener >& listener )
+ throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeSubmissionVetoListener(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::form::submission::XSubmissionVetoListener >& listener )
+ throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
+
+ //
+ // XPropertySet
+ // (need to disambiguate this)
+
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+};
+
+
+} // namespace xforms
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/makefile.mk b/forms/source/xforms/submission/makefile.mk
new file mode 100644
index 000000000000..20590cab880b
--- /dev/null
+++ b/forms/source/xforms/submission/makefile.mk
@@ -0,0 +1,57 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=forms
+TARGET=xformssubmit
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE: $(PRJ)$/makefile.pmk
+
+.IF "$(SYSTEM_LIBXML)" == "YES"
+CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS)
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/serialization_app_xml.obj \
+ $(SLO)$/serialization_urlencoded.obj \
+ $(SLO)$/submission_post.obj \
+ $(SLO)$/submission_put.obj \
+ $(SLO)$/submission_get.obj \
+ $(SLO)$/replace.obj
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/forms/source/xforms/submission/replace.cxx b/forms/source/xforms/submission/replace.cxx
new file mode 100644
index 000000000000..cfcdb1626439
--- /dev/null
+++ b/forms/source/xforms/submission/replace.cxx
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+#include <memory>
+#include "submission.hxx"
+#include "serialization_app_xml.hxx"
+
+#include <rtl/ustring.hxx>
+#include <rtl/string.hxx>
+
+#include <unotools/processfactory.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <ucbhelper/content.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::frame;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::task;
+using namespace com::sun::star::xml::dom;
+
+CSubmission::SubmissionResult CSubmission::replace(const ::rtl::OUString& aReplace, const Reference<XDocument>& aDocument, const Reference<XFrame>& aFrame)
+{
+ if (!m_aResultStream.is())
+ return CSubmission::UNKNOWN_ERROR;
+
+ try {
+ Reference< XMultiServiceFactory > xFactory = utl::getProcessServiceFactory();
+ if (aReplace.equalsIgnoreAsciiCaseAscii("all") || aReplace.equalsIgnoreAsciiCaseAscii("document")) {
+ Reference< XComponentLoader > xLoader;
+ if (aFrame.is())
+ xLoader = Reference< XComponentLoader >(aFrame, UNO_QUERY);
+
+ if (!xLoader.is())
+ xLoader = Reference< XComponentLoader >(xFactory->createInstance(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ) ), UNO_QUERY_THROW);
+
+ // open the stream from the result...
+ // build media descriptor
+ Sequence< PropertyValue > descriptor(2);
+ descriptor[0] = PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream") ),
+ -1, makeAny(m_aResultStream), PropertyState_DIRECT_VALUE);
+ descriptor[1] = PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly") ),
+ -1, makeAny(sal_True), PropertyState_DIRECT_VALUE);
+
+ ::rtl::OUString aURL = m_aURLObj.GetMainURL(INetURLObject::NO_DECODE);
+ ::rtl::OUString aTarget = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_default") );
+ xLoader->loadComponentFromURL(aURL, aTarget, FrameSearchFlag::ALL, descriptor);
+
+ return CSubmission::SUCCESS;
+
+ } else if (aReplace.equalsIgnoreAsciiCaseAscii("instance")) {
+ if (aDocument.is()) {
+ // parse the result stream into a new document
+ Reference< XDocumentBuilder > xBuilder(xFactory->createInstance(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder") ) ), UNO_QUERY_THROW);
+ Reference< XDocument > aNewDocument = xBuilder->parse(m_aResultStream);
+
+ if (aNewDocument.is()) {
+ // and replace the content of the current instance
+ Reference< XElement > oldRoot = aDocument->getDocumentElement();
+ Reference< XElement > newRoot = aNewDocument->getDocumentElement();
+
+ Reference< XNode > aImportedNode = aDocument->importNode(Reference< XNode >(newRoot, UNO_QUERY_THROW), sal_True);
+ Reference< XNode >(aDocument, UNO_QUERY_THROW)->replaceChild(aImportedNode, Reference< XNode >(oldRoot, UNO_QUERY_THROW));
+ return CSubmission::SUCCESS;
+ } else {
+ return CSubmission::UNKNOWN_ERROR;
+ }
+ } else {
+ // nothing to replace
+ return CSubmission::UNKNOWN_ERROR;
+ }
+ } else if (aReplace.equalsIgnoreAsciiCaseAscii("none")) {
+ // do nothing \o/
+ return CSubmission::SUCCESS;
+ }
+ } catch (Exception& e) {
+ ::rtl::OString aMsg("Exception during replace:\n");
+ aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
+ OSL_ENSURE(sal_False, aMsg.getStr());
+ }
+ return CSubmission::UNKNOWN_ERROR;
+}
+::std::auto_ptr< CSerialization > CSubmission::createSerialization(const Reference< XInteractionHandler >& _xHandler,Reference<XCommandEnvironment>& _rOutEnv)
+{
+ // PUT always uses application/xml
+ ::std::auto_ptr< CSerialization > apSerialization(new CSerializationAppXML());
+ apSerialization->setSource(m_aFragment);
+ apSerialization->serialize();
+
+ // create a commandEnvironment and use the default interaction handler
+ CCommandEnvironmentHelper *pHelper = new CCommandEnvironmentHelper;
+ if( _xHandler.is() )
+ pHelper->m_aInteractionHandler = _xHandler;
+ else
+ pHelper->m_aInteractionHandler = CSS::uno::Reference< XInteractionHandler >(m_aFactory->createInstance(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler") ) ), UNO_QUERY);
+ OSL_ENSURE(pHelper->m_aInteractionHandler.is(), "failed to create IntreractionHandler");
+
+ CProgressHandlerHelper *pProgressHelper = new CProgressHandlerHelper;
+ pHelper->m_aProgressHandler = Reference< XProgressHandler >(pProgressHelper);
+
+ // UCB has ownership of environment...
+ _rOutEnv = pHelper;
+ return apSerialization;
+}
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/serialization.hxx b/forms/source/xforms/submission/serialization.hxx
new file mode 100644
index 000000000000..966a3f9e0ae8
--- /dev/null
+++ b/forms/source/xforms/submission/serialization.hxx
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __SERIALIZATION_HXX
+#define __SERIALIZATION_HXX
+
+#include <map>
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/xml/xpath/XXPathObject.hpp>
+#include <com/sun/star/xml/dom/XDocumentFragment.hpp>
+
+namespace CSS = com::sun::star;
+
+/**
+Serialize an XObject
+*/
+
+typedef std::map<rtl::OUString, rtl::OUString> PropMap;
+
+class CSerialization
+{
+protected:
+ CSS::uno::Reference< CSS::xml::dom::XDocumentFragment > m_aFragment;
+ PropMap m_properties;
+
+public:
+ virtual ~CSerialization() {}
+
+ /**
+ sets the XObject that is to serialized
+ */
+ virtual void setSource(const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment)
+ {
+ m_aFragment = aFragment;
+ }
+
+ /**
+ set the properties from the submission element
+ that control aspects of the serialization
+ eachs serialization may support individual properties
+ */
+ void setProperties(const CSS::uno::Sequence< CSS::beans::NamedValue >& props)
+ {
+ m_properties.clear();
+ rtl::OUString aValue;
+ for (sal_Int32 i=0; i<props.getLength(); i++)
+ {
+ if (props[i].Value >>= aValue)
+ m_properties.insert(PropMap::value_type(props[i].Name, aValue));
+ }
+ }
+
+ /**
+ start the serialization process
+ */
+ virtual void serialize()=0;
+
+ /**
+ get the serialized bytes.
+ reads up to buffer->getLength() bytes and returns the number of
+ bytes read.
+ returns -1 on error
+ */
+ virtual CSS::uno::Reference< CSS::io::XInputStream > getInputStream() = 0;
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/serialization_app_xml.cxx b/forms/source/xforms/submission/serialization_app_xml.cxx
new file mode 100644
index 000000000000..c3e2ab545668
--- /dev/null
+++ b/forms/source/xforms/submission/serialization_app_xml.cxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "serialization.hxx"
+#include "serialization_app_xml.hxx"
+
+#include <unotools/processfactory.hxx>
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/dom/XNodeList.hpp>
+#include <com/sun/star/xml/dom/NodeType.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/xml/xpath/XPathObjectType.hpp>
+
+#include <libxml/tree.h>
+
+CSerializationAppXML::CSerializationAppXML()
+ : m_aFactory(utl::getProcessServiceFactory())
+ , m_aPipe(CSS::uno::Reference< CSS::io::XOutputStream > (m_aFactory->createInstance(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.Pipe") ) ), CSS::uno::UNO_QUERY))
+{
+ OSL_ENSURE(m_aPipe.is(), "cannot create Pipe");
+}
+
+CSS::uno::Reference< CSS::io::XInputStream >
+CSerializationAppXML::getInputStream()
+{
+ // The pipes output is provided through it's
+ // XOutputStream interface aspect
+ return CSS::uno::Reference< CSS::io::XInputStream >(m_aPipe, CSS::uno::UNO_QUERY);
+}
+
+void
+CSerializationAppXML::serialize_node(const CSS::uno::Reference< CSS::xml::dom::XNode >& rNode)
+{
+ CSS::uno::Reference< CSS::xml::dom::XNode > aNode = rNode;
+ if (aNode->getNodeType() == CSS::xml::dom::NodeType_DOCUMENT_NODE)
+ {
+ CSS::uno::Reference< CSS::xml::dom::XDocument > aDoc(rNode, CSS::uno::UNO_QUERY_THROW);
+ aNode = CSS::uno::Reference< CSS::xml::dom::XNode >(aDoc->getDocumentElement(), CSS::uno::UNO_QUERY_THROW);
+ }
+ if (aNode->getNodeType() != CSS::xml::dom::NodeType_ELEMENT_NODE)
+ return;
+
+ // clone the node to a new document and serialize that document
+ CSS::uno::Reference< CSS::lang::XUnoTunnel > aTunnel(aNode, CSS::uno::UNO_QUERY);
+ if (aTunnel.is())
+ {
+ xmlNodePtr aNodePtr = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(CSS::uno::Sequence< sal_Int8 >()) );
+ xmlDocPtr aDocPtr = xmlNewDoc((xmlChar*)"1.0");
+ xmlNodePtr aDocNodePtr = xmlDocCopyNode(aNodePtr, aDocPtr, 1);
+ if (aDocNodePtr != NULL) {
+ xmlAddChild((xmlNodePtr)aDocPtr, aDocNodePtr);
+ xmlChar *buffer = NULL;
+ sal_Int32 size = 0;
+ xmlDocDumpMemory(aDocPtr, &buffer, (int*)&size);
+
+ // write the xml into the pipe through it's XOutputStream interface
+ m_aPipe->writeBytes(CSS::uno::Sequence< sal_Int8 >((sal_Int8*)buffer, size));
+ xmlFree(buffer);
+ }
+
+ } else {
+ // can't get tunnel to native backend
+ // logic for generic implementation could be implemented here...
+ OSL_ENSURE(sal_False, "unkown dom implementation, cannot serialize");
+ return;
+ }
+}
+
+/*
+void
+CSerializationAppXML::serialize_nodeset()
+{
+ CSS::uno::Reference< CSS::xml::dom::XNodeList > aNodeList = m_aXPathObject->getNodeList();
+ for (sal_Int32 i=0; i<aNodeList->getLength(); i++)
+ serialize_node(aNodeList->item(i));
+ m_aPipe->closeOutput();
+}
+*/
+
+void
+CSerializationAppXML::serialize()
+{
+ if (!m_aFragment.is()) return;
+
+ CSS::uno::Reference< CSS::xml::dom::XNode > cur = m_aFragment->getFirstChild();
+ while (cur.is())
+ {
+ serialize_node(cur);
+ cur = cur->getNextSibling();
+ }
+ m_aPipe->closeOutput();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/serialization_app_xml.hxx b/forms/source/xforms/submission/serialization_app_xml.hxx
new file mode 100644
index 000000000000..9564961bbbc9
--- /dev/null
+++ b/forms/source/xforms/submission/serialization_app_xml.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __SERIALIZATION_APP_XML_HXX
+#define __SERIALIZATION_APP_XML_HXX
+
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include "serialization.hxx"
+
+
+class CSerializationAppXML : public CSerialization
+{
+private:
+ CSS::uno::Reference< CSS::lang::XMultiServiceFactory > m_aFactory;
+ CSS::uno::Reference< CSS::io::XOutputStream > m_aPipe;
+
+ void serialize_node(const CSS::uno::Reference< CSS::xml::dom::XNode >& aNode);
+ void serialize_nodeset();
+
+public:
+ CSerializationAppXML();
+
+ virtual void serialize();
+ // virtual void setSource(const CSS::uno::Reference< CSS::xml::xpath::XXPathObject >& object);
+ // virtual void setProperties(const CSS::uno::Sequence< CSS::beans::NamedValue >& props);
+ virtual CSS::uno::Reference< CSS::io::XInputStream > getInputStream();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/serialization_urlencoded.cxx b/forms/source/xforms/submission/serialization_urlencoded.cxx
new file mode 100644
index 000000000000..e5ab54533e61
--- /dev/null
+++ b/forms/source/xforms/submission/serialization_urlencoded.cxx
@@ -0,0 +1,212 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include <com/sun/star/xml/xpath/XPathObjectType.hpp>
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/xml/dom/XText.hpp>
+#include <com/sun/star/xml/dom/XNodeList.hpp>
+#include <com/sun/star/xml/dom/NodeType.hpp>
+
+#include <rtl/ustrbuf.hxx>
+#include <rtl/strbuf.hxx>
+#include <unotools/processfactory.hxx>
+
+#include <stdio.h>
+
+#include "serialization_urlencoded.hxx"
+
+using namespace utl;
+using namespace CSS::uno;
+using namespace CSS::io;
+using namespace CSS::xml::xpath;
+using namespace CSS::xml::dom;
+
+CSerializationURLEncoded::CSerializationURLEncoded()
+ : m_aFactory(getProcessServiceFactory())
+ , m_aPipe(Reference< XOutputStream > (m_aFactory->createInstance(
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.Pipe") ) ), UNO_QUERY))
+{
+}
+
+
+/*
+ rfc2396
+ reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
+ "$" | ","
+ mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
+ unreserved = alphanum | mark
+*/
+sal_Bool CSerializationURLEncoded::is_unreserved(sal_Char c)
+{
+ //digit?
+ if (c >= '0' && c <= '9') return sal_True;
+ if (c >= 'A' && c <= 'Z') return sal_True;
+ if (c >= 'a' && c <= 'z') return sal_True;
+ switch (c) {
+ case '-':
+ case '_':
+ case '.':
+ case '!':
+ case '~':
+ case '*':
+ case '\'':
+ case '(':
+ case ')':
+ return sal_True;
+ }
+ return sal_False;
+}
+void CSerializationURLEncoded::encode_and_append(const ::rtl::OUString& aString, ::rtl::OStringBuffer& aBuffer)
+{
+ ::rtl::OString utf8String = OUStringToOString(aString, RTL_TEXTENCODING_UTF8);
+ const sal_uInt8 *pString = reinterpret_cast< const sal_uInt8 * >( utf8String.getStr() );
+ sal_Char tmpChar[4]; tmpChar[3] = 0;
+
+ while( *pString != 0)
+ {
+ if( *pString < 0x80 )
+ {
+ if ( is_unreserved(*pString) ) {
+ aBuffer.append(*pString);
+ } else if (*pString == 0x20) {
+ aBuffer.append('+');
+ } else if (*pString == 0x0d && *(pString+1) == 0x0a) {
+ aBuffer.append("%0D%0A");
+ pString++;
+ } else if (*pString == 0x0a) {
+ aBuffer.append("%0D%0A");
+ } else {
+ snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
+ aBuffer.append(tmpChar);
+ }
+ } else {
+ snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
+ aBuffer.append(tmpChar);
+ while (*pString >= 0x80) {
+ // continuation...
+ pString++;
+ snprintf(tmpChar, 3, "%%%X", *pString % 0x100);
+ aBuffer.append(tmpChar);
+ }
+ }
+ pString++;
+ }
+}
+
+void CSerializationURLEncoded::serialize_node(const Reference< XNode >& aNode)
+{
+ // serialize recursive
+ // every element node E that has a text child T will be serialized in document order
+ // <E1>T1<E2>T2</E2></E1><E3>T3</E3> -> E1=T2&E2=T2&E3=T3 (En := local name)
+
+ // this node
+ Reference< XNodeList > aChildList = aNode->getChildNodes();
+ Reference< XNode > aChild;
+ // is this an element node?
+ if (aNode->getNodeType() == NodeType_ELEMENT_NODE)
+ {
+ ::rtl::OUString aName = aNode->getNodeName();
+ // find any text children
+ ::rtl::OUStringBuffer aValue;
+ Reference< XText > aText;
+ for(sal_Int32 i=0; i < aChildList->getLength(); i++)
+ {
+ aChild = aChildList->item(i);
+ if (aChild->getNodeType() == NodeType_TEXT_NODE)
+ {
+ aText = Reference< XText >(aChild, UNO_QUERY);
+ aValue.append(aText->getData());
+ }
+ }
+
+ // found anything?
+ if (aValue.getLength() > 0)
+ {
+ ::rtl::OUString aUnencValue = aValue.makeStringAndClear();
+ ::rtl::OStringBuffer aEncodedBuffer;
+ encode_and_append(aName, aEncodedBuffer);
+ aEncodedBuffer.append("=");
+ encode_and_append(aUnencValue, aEncodedBuffer);
+ aEncodedBuffer.append("&");
+ sal_Int8 *pData = (sal_Int8*)aEncodedBuffer.getStr();
+ Sequence< sal_Int8 > sData(pData, aEncodedBuffer.getLength());
+ m_aPipe->writeBytes(sData);
+ }
+ }
+
+ // element children...
+ for(sal_Int32 i=0; i < aChildList->getLength(); i++)
+ {
+ aChild = aChildList->item(i);
+ // if this is an element node, it might be a candidate for serialization
+ if (aChild.is() && aChild->getNodeType() == NodeType_ELEMENT_NODE)
+ serialize_node(aChild);
+ }
+
+ // siblings...
+// Reference< XNode > aSibling = aNode->getNextSibling();
+// if (aSibling.is())
+// serialize_node(aSibling);
+
+}
+
+/*
+void CSerializationURLEncoded::serialize_nodeset()
+{
+ Reference< XNodeList > aNodeList = m_aXPathObject->getNodeList();
+ for (sal_Int32 i=0; i<aNodeList->getLength(); i++)
+ serialize_node(aNodeList->item(i));
+ m_aPipe->closeOutput();
+}
+*/
+
+void CSerializationURLEncoded::serialize()
+{
+
+ // output stream to the pipe buffer
+ Reference< XOutputStream > out(m_aPipe, UNO_QUERY);
+
+ CSS::uno::Reference< CSS::xml::dom::XNode > cur = m_aFragment->getFirstChild();
+ while (cur.is())
+ {
+ serialize_node(cur);
+ cur = cur->getNextSibling();
+ }
+ m_aPipe->closeOutput();
+}
+
+Reference< XInputStream > CSerializationURLEncoded::getInputStream()
+{
+ return Reference< XInputStream >(m_aPipe, UNO_QUERY);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/serialization_urlencoded.hxx b/forms/source/xforms/submission/serialization_urlencoded.hxx
new file mode 100644
index 000000000000..a5e9a4eb1060
--- /dev/null
+++ b/forms/source/xforms/submission/serialization_urlencoded.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __SERIALIZATION_URLENCODED_HXX
+#define __SERIALIZATION_URLENCODED_HXX
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+#include <rtl/strbuf.hxx>
+
+#include "serialization.hxx"
+
+class CSerializationURLEncoded : public CSerialization
+{
+private:
+ CSS::uno::Reference< CSS::lang::XMultiServiceFactory > m_aFactory;
+ CSS::uno::Reference< CSS::io::XOutputStream > m_aPipe;
+
+ sal_Bool is_unreserved(sal_Char);
+ void encode_and_append(const rtl::OUString& aString, rtl::OStringBuffer& aBuffer);
+ void serialize_node(const CSS::uno::Reference< CSS::xml::dom::XNode >& aNode);
+ void serialize_nodeset();
+
+public:
+ CSerializationURLEncoded();
+ virtual void serialize();
+ virtual CSS::uno::Reference< CSS::io::XInputStream > getInputStream();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/submission.hxx b/forms/source/xforms/submission/submission.hxx
new file mode 100644
index 000000000000..d01fb8fb0aba
--- /dev/null
+++ b/forms/source/xforms/submission/submission.hxx
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __SUBMISSION_HXX
+#define __SUBMISSION_HXX
+
+#include <tools/urlobj.hxx>
+#include <rtl/ustring.h>
+#include <osl/conditn.hxx>
+#include <osl/mutex.hxx>
+#include <unotools/processfactory.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/xml/xpath/XXPathObject.hpp>
+#include <com/sun/star/xml/dom/XDocumentFragment.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+
+#include <com/sun/star/task/XInteractionHandler.hpp>
+
+#include <com/sun/star/frame/XFrame.hpp>
+
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <cppuhelper/implbase3.hxx>
+
+#include "serialization.hxx"
+
+namespace CSS = com::sun::star;
+
+class CSubmissionPut;
+class CSubmissionPost;
+class CSubmissionGet;
+
+class CCommandEnvironmentHelper : public cppu::WeakImplHelper1< CSS::ucb::XCommandEnvironment >
+{
+ friend class CSubmissionPut;
+ friend class CSubmissionPost;
+ friend class CSubmissionGet;
+ friend class CSubmission;
+
+protected:
+ CSS::uno::Reference< CSS::task::XInteractionHandler > m_aInteractionHandler;
+ CSS::uno::Reference< CSS::ucb::XProgressHandler > m_aProgressHandler;
+
+public:
+ virtual CSS::uno::Reference< CSS::task::XInteractionHandler > SAL_CALL getInteractionHandler() throw (CSS::uno::RuntimeException)
+ {
+ return m_aInteractionHandler;
+ }
+ virtual CSS::uno::Reference< CSS::ucb::XProgressHandler > SAL_CALL getProgressHandler() throw (CSS::uno::RuntimeException)
+ {
+ return m_aProgressHandler;
+ }
+};
+
+class CProgressHandlerHelper : public cppu::WeakImplHelper1< CSS::ucb::XProgressHandler >
+{
+ friend class CSubmissionPut;
+ friend class CSubmissionPost;
+ friend class CSubmissionGet;
+protected:
+ osl::Condition m_cFinished;
+ osl::Mutex m_mLock;
+ sal_Int32 m_count;
+public:
+ CProgressHandlerHelper()
+ : m_count(0)
+ {}
+ virtual void SAL_CALL push( const com::sun::star::uno::Any& /*aStatus*/) throw(com::sun::star::uno::RuntimeException)
+ {
+ m_mLock.acquire();
+ m_count++;
+ m_mLock.release();
+ }
+ virtual void SAL_CALL update(const com::sun::star::uno::Any& /*aStatus*/) throw(com::sun::star::uno::RuntimeException)
+ {
+ }
+ virtual void SAL_CALL pop() throw(com::sun::star::uno::RuntimeException)
+ {
+ m_mLock.acquire();
+ m_count--;
+ if (m_count == 0)
+ m_cFinished.set();
+ m_mLock.release();
+ }
+};
+
+class CSubmission
+{
+
+protected:
+ INetURLObject m_aURLObj;
+ CSS::uno::Reference< CSS::xml::xpath::XXPathObject > m_aXPathObject;
+ CSS::uno::Reference< CSS::xml::dom::XDocumentFragment > m_aFragment;
+ CSS::uno::Reference< CSS::io::XInputStream > m_aResultStream;
+ CSS::uno::Reference< CSS::lang::XMultiServiceFactory > m_aFactory;
+ rtl::OUString m_aEncoding;
+
+ ::std::auto_ptr< CSerialization > createSerialization(const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler
+ ,com::sun::star::uno::Reference<com::sun::star::ucb::XCommandEnvironment>& _rOutEnv);
+
+public:
+ enum SubmissionResult {
+ SUCCESS,
+ INVALID_METHOD,
+ INVALID_URL,
+ INVALID_ENCODING,
+ E_TRANSMISSION,
+ UNKNOWN_ERROR
+ };
+
+ CSubmission(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment)
+ : m_aURLObj(aURL)
+ , m_aFragment(aFragment)
+ , m_aFactory(::utl::getProcessServiceFactory())
+ {}
+
+ virtual ~CSubmission() {}
+
+ // virtual CSS::uno::Sequence< rtl::OUString > getSupportedEncodings() = 0;
+ virtual void setEncoding(const rtl::OUString& aEncoding)
+ {
+ m_aEncoding = aEncoding;
+ }
+ virtual SubmissionResult submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& ) = 0;
+
+ virtual SubmissionResult replace(const rtl::OUString&, const CSS::uno::Reference< CSS::xml::dom::XDocument >&, const CSS::uno::Reference< CSS::frame::XFrame>&);
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/submission_get.cxx b/forms/source/xforms/submission/submission_get.cxx
new file mode 100644
index 000000000000..c8e87fa68a04
--- /dev/null
+++ b/forms/source/xforms/submission/submission_get.cxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include <memory>
+
+#include "submission_get.hxx"
+#include "serialization_app_xml.hxx"
+#include "serialization_urlencoded.hxx"
+
+#include <rtl/strbuf.hxx>
+#include <rtl/string.hxx>
+#include <osl/file.hxx>
+#include <unotools/processfactory.hxx>
+#include <ucbhelper/content.hxx>
+
+using namespace CSS::uno;
+using namespace CSS::ucb;
+using namespace CSS::task;
+using namespace CSS::io;
+using namespace rtl;
+using namespace osl;
+using namespace ucbhelper;
+using namespace std;
+
+
+CSubmissionGet::CSubmissionGet(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment)
+ : CSubmission(aURL, aFragment)
+{
+}
+
+CSubmission::SubmissionResult CSubmissionGet::submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler)
+{
+ // GET always uses apllicatin/x-www-formurlencoded
+ auto_ptr< CSerialization > apSerialization(new CSerializationURLEncoded());
+ apSerialization->setSource(m_aFragment);
+ apSerialization->serialize();
+
+ CSS::uno::Reference< XInputStream > aInStream = apSerialization->getInputStream();
+
+ // create a commandEnvironment and use the default interaction handler
+ CCommandEnvironmentHelper *pHelper = new CCommandEnvironmentHelper;
+ if( aInteractionHandler.is() )
+ pHelper->m_aInteractionHandler = aInteractionHandler;
+ else
+ pHelper->m_aInteractionHandler = CSS::uno::Reference< XInteractionHandler >(m_aFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler"))), UNO_QUERY);
+ OSL_ENSURE(pHelper->m_aInteractionHandler.is(), "failed to create IntreractionHandler");
+ CProgressHandlerHelper *pProgressHelper = new CProgressHandlerHelper;
+ pHelper->m_aProgressHandler = CSS::uno::Reference< XProgressHandler >(pProgressHelper);
+
+ // UCB has ownership of environment...
+ CSS::uno::Reference< XCommandEnvironment > aEnvironment(pHelper);
+
+ // append query string to the URL
+ try {
+ OStringBuffer aUTF8QueryURL(OUStringToOString(m_aURLObj.GetMainURL(INetURLObject::NO_DECODE),
+ RTL_TEXTENCODING_UTF8));
+ OStringBuffer aQueryString;
+
+ const sal_Int32 size = 1024;
+ sal_Int32 n = 0;
+ Sequence< sal_Int8 > aByteBuffer(size);
+ while ((n = aInStream->readSomeBytes(aByteBuffer, size-1)) != 0)
+ aQueryString.append((sal_Char*)aByteBuffer.getArray(), n);
+ if (aQueryString.getLength() > 0 && m_aURLObj.GetProtocol() != INET_PROT_FILE)
+ {
+ aUTF8QueryURL.append('?');
+ aUTF8QueryURL.append(aQueryString.makeStringAndClear());
+ }
+ OUString aQueryURL = OStringToOUString(aUTF8QueryURL.makeStringAndClear(), RTL_TEXTENCODING_UTF8);
+ ucbhelper::Content aContent(aQueryURL, aEnvironment);
+ CSS::uno::Reference< XOutputStream > aPipe(m_aFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.Pipe"))), UNO_QUERY_THROW);
+ aContent.openStream(aPipe);
+ // get reply
+ try {
+ m_aResultStream = aContent.openStream();
+ } catch (Exception&) {
+ OSL_ENSURE(sal_False, "Cannot open reply stream from content");
+ }
+ } catch (Exception&)
+ {
+ // XXX
+ OSL_ENSURE(sal_False, "Exception during UCB operatration.");
+ return UNKNOWN_ERROR;
+ }
+
+ return SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/submission_get.hxx b/forms/source/xforms/submission/submission_get.hxx
new file mode 100644
index 000000000000..a9dfbbf3e0b6
--- /dev/null
+++ b/forms/source/xforms/submission/submission_get.hxx
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __SUBMISSION_GET_HXX
+#define __SUBMISSION_GET_HXX
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include "submission.hxx"
+
+class CSubmissionGet : public CSubmission
+{
+private:
+ CSS::uno::Reference< CSS::lang::XMultiServiceFactory > m_aFactory;
+public:
+ CSubmissionGet(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment);
+ virtual SubmissionResult submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler);
+
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/submission_post.cxx b/forms/source/xforms/submission/submission_post.cxx
new file mode 100644
index 000000000000..c76d492873d9
--- /dev/null
+++ b/forms/source/xforms/submission/submission_post.cxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include <memory>
+
+#include "submission_post.hxx"
+#include "serialization_app_xml.hxx"
+#include "serialization_urlencoded.hxx"
+
+#include <osl/file.hxx>
+#include <unotools/processfactory.hxx>
+#include <ucbhelper/content.hxx>
+#include <ucbhelper/activedatasink.hxx>
+#include <com/sun/star/ucb/PostCommandArgument2.hpp>
+
+using namespace CSS::uno;
+using namespace CSS::ucb;
+using namespace CSS::task;
+using namespace CSS::io;
+using namespace rtl;
+using namespace osl;
+using namespace ucbhelper;
+using namespace std;
+
+
+CSubmissionPost::CSubmissionPost(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment)
+ : CSubmission(aURL, aFragment)
+{
+}
+
+CSubmission::SubmissionResult CSubmissionPost::submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler)
+{
+ // PUT always uses application/xml
+ CSS::uno::Reference< XCommandEnvironment > aEnvironment;
+ auto_ptr< CSerialization > apSerialization(createSerialization(aInteractionHandler,aEnvironment));
+
+ try {
+ ucbhelper::Content aContent(m_aURLObj.GetMainURL(INetURLObject::NO_DECODE), aEnvironment);
+
+ // use post command
+
+ OUString aCommandName(RTL_CONSTASCII_USTRINGPARAM("post"));
+ PostCommandArgument2 aPostArgument;
+ aPostArgument.Source = apSerialization->getInputStream();
+ CSS::uno::Reference< XActiveDataSink > aSink(new ucbhelper::ActiveDataSink);
+ aPostArgument.Sink = aSink;
+ aPostArgument.MediaType = OUString(RTL_CONSTASCII_USTRINGPARAM("application/xml"));
+ aPostArgument.Referer = OUString();
+ Any aCommandArgument;
+ aCommandArgument <<= aPostArgument;
+ aContent.executeCommand( aCommandName, aCommandArgument);
+
+ // wait for command to finish
+ // pProgressHelper->m_cFinished.wait();
+
+ // CSS::uno::Reference< XOutputStream > xOut(aSink, UNO_QUERY_THROW);
+ // xOut->closeOutput();
+
+ try {
+ // m_aResultStream = CSS::uno::Reference< XInputStream >(aSink, UNO_QUERY_THROW);
+ m_aResultStream = aSink->getInputStream();
+ } catch (Exception&) {
+ OSL_ENSURE(sal_False, "Cannot open reply stream from content");
+ }
+ } catch (Exception&)
+ {
+ // XXX
+ OSL_ENSURE(sal_False, "Exception during UCB operatration.");
+ return UNKNOWN_ERROR;
+ }
+
+
+ return SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/submission_post.hxx b/forms/source/xforms/submission/submission_post.hxx
new file mode 100644
index 000000000000..86f040f951de
--- /dev/null
+++ b/forms/source/xforms/submission/submission_post.hxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __SUBMISSION_POST_HXX
+#define __SUBMISSION_POST_HXX
+
+#include "submission.hxx"
+
+class CSubmissionPost : public CSubmission
+{
+public:
+ CSubmissionPost(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment);
+ virtual SubmissionResult submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler);
+
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/submission_put.cxx b/forms/source/xforms/submission/submission_put.cxx
new file mode 100644
index 000000000000..a9f9681014be
--- /dev/null
+++ b/forms/source/xforms/submission/submission_put.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include <memory>
+
+#include "submission_put.hxx"
+#include "serialization_app_xml.hxx"
+#include "serialization_urlencoded.hxx"
+
+#include <osl/file.hxx>
+#include <unotools/processfactory.hxx>
+#include <ucbhelper/content.hxx>
+
+using namespace CSS::uno;
+using namespace CSS::ucb;
+using namespace CSS::task;
+using namespace CSS::io;
+using namespace rtl;
+using namespace osl;
+using namespace ucbhelper;
+using namespace std;
+
+
+CSubmissionPut::CSubmissionPut(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment)
+ : CSubmission(aURL, aFragment)
+{
+}
+
+CSubmission::SubmissionResult CSubmissionPut::submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler)
+{
+ CSS::uno::Reference< XCommandEnvironment > aEnvironment;
+ auto_ptr< CSerialization > apSerialization(createSerialization(aInteractionHandler,aEnvironment));
+
+ try {
+ ucbhelper::Content aContent(m_aURLObj.GetMainURL(INetURLObject::NO_DECODE), aEnvironment);
+
+ // insert serialized data to content -> PUT
+ CSS::uno::Reference< XInputStream > aInStream = apSerialization->getInputStream();
+ aContent.writeStream(aInStream, sal_True);
+ //aContent.closeStream();
+
+ // no content as a result of put...
+
+ } catch (Exception&)
+ {
+ // XXX
+ OSL_ENSURE(sal_False, "Exception during UCB operatration.");
+ return UNKNOWN_ERROR;
+ }
+
+
+ return SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/submission/submission_put.hxx b/forms/source/xforms/submission/submission_put.hxx
new file mode 100644
index 000000000000..acdb15e490c8
--- /dev/null
+++ b/forms/source/xforms/submission/submission_put.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef __SUBMISSION_PUT_HXX
+#define __SUBMISSION_PUT_HXX
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+
+#include "submission.hxx"
+
+class CSubmissionPut : public CSubmission
+{
+public:
+ CSubmissionPut(const rtl::OUString& aURL, const CSS::uno::Reference< CSS::xml::dom::XDocumentFragment >& aFragment);
+ virtual SubmissionResult submit(const CSS::uno::Reference< CSS::task::XInteractionHandler >& aInteractionHandler);
+
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/unohelper.cxx b/forms/source/xforms/unohelper.cxx
new file mode 100644
index 000000000000..475f366401a6
--- /dev/null
+++ b/forms/source/xforms/unohelper.cxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "unohelper.hxx"
+
+#include <osl/diagnose.h>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <unotools/processfactory.hxx>
+
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::Sequence;
+using com::sun::star::uno::Exception;
+using com::sun::star::uno::XInterface;
+using com::sun::star::lang::XMultiServiceFactory;
+using com::sun::star::beans::Property;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::beans::XPropertySetInfo;
+using com::sun::star::beans::PropertyAttribute::READONLY;
+using rtl::OUString;
+
+
+Reference<XInterface> xforms::createInstance( const OUString& sServiceName )
+{
+ Reference<XMultiServiceFactory> xFactory = utl::getProcessServiceFactory();
+ OSL_ENSURE( xFactory.is(), "can't get service factory" );
+
+ Reference<XInterface> xInstance = xFactory->createInstance( sServiceName );
+ OSL_ENSURE( xInstance.is(), "failed to create instance" );
+
+ return xInstance;
+}
+
+void xforms::copy( const Reference<XPropertySet>& xFrom,
+ Reference<XPropertySet>& xTo )
+{
+ OSL_ENSURE( xFrom.is(), "no source" );
+ OSL_ENSURE( xTo.is(), "no target" );
+
+ // get property names & infos, and iterate over target properties
+ Sequence<Property> aProperties =
+ xTo->getPropertySetInfo()->getProperties();
+ sal_Int32 nProperties = aProperties.getLength();
+ const Property* pProperties = aProperties.getConstArray();
+ Reference<XPropertySetInfo> xFromInfo = xFrom->getPropertySetInfo();
+ for( sal_Int32 n = 0; n < nProperties; n++ )
+ {
+ const OUString& rName = pProperties[n].Name;
+
+ // if both set have the property, copy the value
+ // (catch and ignore exceptions, if any)
+ if( xFromInfo->hasPropertyByName( rName ) )
+ {
+ try
+ {
+ Property aProperty = xFromInfo->getPropertyByName( rName );
+ if ( ( aProperty.Attributes & READONLY ) == 0 )
+ xTo->setPropertyValue(rName, xFrom->getPropertyValue( rName ));
+ }
+ catch( const Exception& )
+ {
+ // ignore any errors; we'll copy as good as we can
+ }
+ }
+ // else: no property? then ignore.
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/unohelper.hxx b/forms/source/xforms/unohelper.hxx
new file mode 100644
index 000000000000..76125cf1dcee
--- /dev/null
+++ b/forms/source/xforms/unohelper.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _UNOHELPER_HXX
+#define _UNOHELPER_HXX
+
+#include <sal/types.h>
+
+// forward declarations
+namespace rtl { class OUString; }
+namespace com { namespace sun { namespace star {
+ namespace uno {
+ class XInterface;
+ template<class T> class Reference;
+ }
+ namespace beans { class XPropertySet; }
+} } }
+
+
+#define OUSTRING(msg) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( msg ) )
+
+namespace xforms
+{
+
+/** instantiate a UNO service using the process global service factory */
+com::sun::star::uno::Reference<com::sun::star::uno::XInterface>
+ createInstance( const rtl::OUString& sServiceName );
+
+/** copy the properties from one PropertySet into the next */
+void copy( const com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>& , com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>& );
+
+} // namespace
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/warnings_guard_unicode_regex.h b/forms/source/xforms/warnings_guard_unicode_regex.h
new file mode 100644
index 000000000000..68f0022d7966
--- /dev/null
+++ b/forms/source/xforms/warnings_guard_unicode_regex.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_WARNINGS_GUARD_UNICODE_REGEX_H
+#define INCLUDED_WARNINGS_GUARD_UNICODE_REGEX_H
+
+// Because the GCC system_header mechanism doesn't work in .c/.cxx compilation
+// units and more important affects the rest of the current include file, the
+// warnings guard is separated into this header file on its own.
+
+// External unicode includes (from icu) cause warning C4668 on Windows.
+// We want to minimize the patches to external headers, so the warnings are
+// disabled here instead of in the header file itself.
+#ifdef _MSC_VER
+#pragma warning(push, 1)
+#elif defined __GNUC__
+#pragma GCC system_header
+#endif
+#include <unicode/regex.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif // INCLUDED_WARNINGS_GUARD_UNICODE_REGEX_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xforms_services.cxx b/forms/source/xforms/xforms_services.cxx
new file mode 100644
index 000000000000..6ef347dd0c4c
--- /dev/null
+++ b/forms/source/xforms/xforms_services.cxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+
+#include "services.hxx"
+
+#include "binding.hxx"
+#include "model.hxx"
+#include "NameContainer.hxx"
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::XInterface;
+using com::sun::star::lang::XMultiServiceFactory;
+using com::sun::star::uno::RuntimeException;
+using com::sun::star::form::binding::XValueBinding;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::container::XNameContainer;
+using rtl::OUString;
+
+
+namespace frm
+{
+
+Reference<XInterface> Model_CreateInstance(
+ const Reference<XMultiServiceFactory>& )
+ throw( RuntimeException )
+{
+ return static_cast<XPropertySet*>( new xforms::Model );
+}
+
+Reference<XInterface> XForms_CreateInstance(
+ const Reference<XMultiServiceFactory>& )
+ throw( RuntimeException )
+{
+ return static_cast<XNameContainer*>( new NameContainer<Reference<XPropertySet> >() );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xforms_services.hxx b/forms/source/xforms/xforms_services.hxx
new file mode 100644
index 000000000000..c1e4dc459dc0
--- /dev/null
+++ b/forms/source/xforms/xforms_services.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+
+namespace com { namespace sun { namespace star {
+ namespace uno { class XInterface; }
+ namespace uno { template<class T> class Reference<T>; }
+ namespace uno { class RuntimeException; }
+ namespace lang { class XMultiServiceFactory; }
+} } }
+
+
+namespace frm
+{
+ com::sun::star::uno::Reference<com::sun::star::uno::XInterface>
+ SAL_CALL Binding_CreateInstance(
+ const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory)
+ throw( com::sun::star::uno::RuntimeException );
+
+ com::sun::star::uno::Reference<com::sun::star::uno::XInterface>
+ SAL_CALL Model_CreateInstance(
+ const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory)
+ throw( com::sun::star::uno::RuntimeException );
+
+ com::sun::star::uno::Reference<com::sun::star::uno::XInterface>
+ SAL_CALL XForms_CreateInstance(
+ const com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory>& _rxFactory)
+ throw( com::sun::star::uno::RuntimeException );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xformsevent.cxx b/forms/source/xforms/xformsevent.cxx
new file mode 100644
index 000000000000..236284165bd2
--- /dev/null
+++ b/forms/source/xforms/xformsevent.cxx
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+#include "xformsevent.hxx"
+
+namespace com {
+namespace sun {
+namespace star {
+namespace xforms {
+
+using rtl::OUString;
+using com::sun::star::uno::RuntimeException;
+
+void SAL_CALL XFormsEventConcrete::initXFormsEvent(const OUString& typeArg,
+ sal_Bool canBubbleArg, sal_Bool cancelableArg)
+ throw (RuntimeException)
+{
+ initEvent(typeArg, canBubbleArg, cancelableArg);
+}
+
+OUString SAL_CALL XFormsEventConcrete::getType() throw (RuntimeException)
+{
+ return m_eventType;
+}
+
+XFormsEventConcrete::XEventTarget_t SAL_CALL XFormsEventConcrete::getTarget() throw (RuntimeException)
+{
+ return m_target;
+}
+
+XFormsEventConcrete::XEventTarget_t SAL_CALL XFormsEventConcrete::getCurrentTarget() throw (RuntimeException)
+{
+ return m_currentTarget;
+}
+
+XFormsEventConcrete::PhaseType_t SAL_CALL XFormsEventConcrete::getEventPhase() throw (RuntimeException)
+{
+ return m_phase;
+}
+
+sal_Bool SAL_CALL XFormsEventConcrete::getBubbles() throw (RuntimeException)
+{
+ return m_bubbles;
+}
+
+sal_Bool SAL_CALL XFormsEventConcrete::getCancelable() throw (RuntimeException)
+{
+ return m_cancelable;
+}
+
+XFormsEventConcrete::Time_t SAL_CALL XFormsEventConcrete::getTimeStamp() throw (RuntimeException)
+{
+ return m_time;
+}
+
+void SAL_CALL XFormsEventConcrete::stopPropagation() throw (RuntimeException)
+{
+ if(m_cancelable)
+ m_canceled = sal_True;
+}
+void SAL_CALL XFormsEventConcrete::preventDefault() throw (RuntimeException)
+{
+}
+
+void SAL_CALL XFormsEventConcrete::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg,
+ sal_Bool cancelableArg) throw (RuntimeException)
+{
+ m_eventType = eventTypeArg;
+ m_bubbles = canBubbleArg;
+ m_cancelable = cancelableArg;
+}
+
+} } } }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xformsevent.hxx b/forms/source/xforms/xformsevent.hxx
new file mode 100644
index 000000000000..806abe6e3e62
--- /dev/null
+++ b/forms/source/xforms/xformsevent.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#ifndef __XFORMSEVENT_HXX
+#define __XFORMSEVENT_HXX
+
+#include <sal/types.h>
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/xforms/XFormsEvent.hpp>
+#include <com/sun/star/xml/dom/events/XEventTarget.hpp>
+
+namespace com {
+namespace sun {
+namespace star {
+namespace xforms {
+
+class XFormsEventConcrete : public cppu::WeakImplHelper1< XFormsEvent > {
+
+ public:
+
+ typedef com::sun::star::uno::RuntimeException RuntimeException_t;
+ typedef com::sun::star::uno::Reference< com::sun::star::xml::dom::events::XEventTarget > XEventTarget_t;
+ typedef com::sun::star::xml::dom::events::PhaseType PhaseType_t;
+ typedef com::sun::star::util::Time Time_t;
+
+ inline XFormsEventConcrete( void ) : m_canceled(sal_False) {}
+ virtual ~XFormsEventConcrete( void ) {}
+
+ virtual rtl::OUString SAL_CALL getType() throw (RuntimeException_t);
+ virtual XEventTarget_t SAL_CALL getTarget() throw (RuntimeException_t);
+ virtual XEventTarget_t SAL_CALL getCurrentTarget() throw (RuntimeException_t);
+ virtual PhaseType_t SAL_CALL getEventPhase() throw (RuntimeException_t);
+ virtual sal_Bool SAL_CALL getBubbles() throw (RuntimeException_t);
+ virtual sal_Bool SAL_CALL getCancelable() throw (RuntimeException_t);
+ virtual Time_t SAL_CALL getTimeStamp() throw (RuntimeException_t);
+ virtual void SAL_CALL stopPropagation() throw (RuntimeException_t);
+ virtual void SAL_CALL preventDefault() throw (RuntimeException_t);
+
+ virtual void SAL_CALL initXFormsEvent(
+ const rtl::OUString& typeArg,
+ sal_Bool canBubbleArg,
+ sal_Bool cancelableArg )
+ throw (RuntimeException_t);
+
+ virtual void SAL_CALL initEvent(
+ const rtl::OUString& eventTypeArg,
+ sal_Bool canBubbleArg,
+ sal_Bool cancelableArg)
+ throw (RuntimeException_t);
+
+ private:
+
+ sal_Bool m_canceled;
+
+ protected:
+
+ rtl::OUString m_eventType;
+ XEventTarget_t m_target;
+ XEventTarget_t m_currentTarget;
+ PhaseType_t m_phase;
+ sal_Bool m_bubbles;
+ sal_Bool m_cancelable;
+ Time_t m_time;
+};
+
+} } } }
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xmlhelper.cxx b/forms/source/xforms/xmlhelper.cxx
new file mode 100644
index 000000000000..14c9b73163e1
--- /dev/null
+++ b/forms/source/xforms/xmlhelper.cxx
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+
+#include "xmlhelper.hxx"
+
+#include "unohelper.hxx"
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
+
+using rtl::OUString;
+using com::sun::star::uno::Reference;
+using com::sun::star::uno::UNO_QUERY_THROW;
+using com::sun::star::container::XNameContainer;
+using com::sun::star::xml::dom::XDocumentBuilder;
+
+
+//
+// determine valid XML name
+//
+
+// character class:
+// 1: NameStartChar
+// 2: NameChar
+// 4: NCNameStartChar
+// 8: NCNameChar
+inline sal_uInt8 lcl_getCharClass( sal_Unicode c )
+{
+ sal_uInt8 nClass = 0;
+
+ // NameStartChar
+ if( (c >= 'A' && c <= 'Z')
+ || c == '_'
+ || (c >= 'a' && c <= 'z')
+ || (c >= 0x00C0 && c <= 0x00D6)
+ || (c >= 0x00D8 && c <= 0x00F6)
+ || (c >= 0x00F8 && c <= 0x02FF)
+ || (c >= 0x0370 && c <= 0x037D)
+ || (c >= 0x037F && c <= 0x1FFF)
+ || (c >= 0x200C && c <= 0x200D)
+ || (c >= 0x2070 && c <= 0x218F)
+ || (c >= 0x2C00 && c <= 0x2FEF)
+ || (c >= 0x3001 && c <= 0xD7FF)
+ || (c >= 0xF900 && c <= 0xFDCF)
+ || (c >= 0xFDF0 && c <= 0xFFFD)
+
+ // surrogates
+ || (c >= 0xD800 && c <= 0xDBFF)
+ || (c >= 0xDC00 && c <= 0xDFFF) )
+ {
+ nClass = 15;
+ }
+ else if( c == '-'
+ || c == '.'
+ || (c >= '0' && c <= '9')
+ || (c == 0x00B7)
+ || (c >= 0x0300 && c <= 0x036F)
+ || (c >= 0x203F && c <= 0x2040) )
+ {
+ nClass = 10;
+ }
+ else if( c == ':' )
+ {
+ nClass = 3;
+ }
+
+ return nClass;
+}
+
+bool isValidQName( const OUString& sName,
+ const Reference<XNameContainer>& /*xNamespaces*/ )
+{
+ sal_Int32 nLength = sName.getLength();
+ const sal_Unicode* pName = sName.getStr();
+
+ bool bRet = false;
+ sal_Int32 nColon = 0;
+ if( nLength > 0 )
+ {
+ bRet = ( ( lcl_getCharClass( pName[0] ) & 4 ) != 0 );
+ for( sal_Int32 n = 1; n < nLength; n++ )
+ {
+ sal_uInt8 nClass = lcl_getCharClass( pName[n] );
+ bRet &= ( ( nClass & 2 ) != 0 );
+ if( nClass == 3 )
+ nColon++;
+ }
+ }
+ if( nColon > 1 )
+ bRet = sal_False;
+
+ return bRet;
+}
+
+bool isValidPrefixName( const OUString& sName,
+ const Reference<XNameContainer>& /*xNamespaces*/ )
+{
+ sal_Int32 nLength = sName.getLength();
+ const sal_Unicode* pName = sName.getStr();
+ bool bRet = false;
+
+ if( nLength > 0 )
+ {
+ bRet = ( ( lcl_getCharClass( pName[0] ) & 4 ) != 0 );
+ for( sal_Int32 n = 1; n < nLength; n++ )
+ bRet &= ( ( lcl_getCharClass( pName[n] ) & 8 ) != 0 );
+ }
+
+ return bRet;
+}
+
+Reference<XDocumentBuilder> getDocumentBuilder()
+{
+ Reference<XDocumentBuilder> xBuilder(
+ xforms::createInstance(
+ OUSTRING("com.sun.star.xml.dom.DocumentBuilder") ),
+ UNO_QUERY_THROW );
+ OSL_ENSURE( xBuilder.is(), "no document builder?" );
+ return xBuilder;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xmlhelper.hxx b/forms/source/xforms/xmlhelper.hxx
new file mode 100644
index 000000000000..7c102cc8aeaa
--- /dev/null
+++ b/forms/source/xforms/xmlhelper.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _XMLHELPER_HXX
+#define _XMLHELPER_HXX
+
+#include <sal/types.h>
+
+
+namespace rtl { class OUString; }
+namespace com { namespace sun { namespace star {
+ namespace uno { template<typename T> class Reference; }
+ namespace container { class XNameContainer; }
+ namespace xml { namespace dom { class XDocumentBuilder; } }
+} } }
+
+
+bool isValidQName( const rtl::OUString& sName,
+ const com::sun::star::uno::Reference<com::sun::star::container::XNameContainer>& xNamespaces );
+
+bool isValidPrefixName( const rtl::OUString& sName,
+ const com::sun::star::uno::Reference<com::sun::star::container::XNameContainer>& xNamespaces );
+
+com::sun::star::uno::Reference<com::sun::star::xml::dom::XDocumentBuilder> getDocumentBuilder();
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xpathlib/extension.cxx b/forms/source/xforms/xpathlib/extension.cxx
new file mode 100644
index 000000000000..ca75c23e31de
--- /dev/null
+++ b/forms/source/xforms/xpathlib/extension.cxx
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+#include <stdio.h>
+#include <com/sun/star/xml/xpath/Libxml2ExtensionHandle.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include "extension.hxx"
+#include "xpathlib.hxx"
+#include "frm_module.hxx"
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::xforms;
+using namespace com::sun::star::xml::xpath;
+using namespace com::sun::star::beans;
+using com::sun::star::xml::dom::XNode;
+
+Reference< XInterface > SAL_CALL CLibxml2XFormsExtension::Create(
+ const Reference< XMultiServiceFactory >& /*aFactory*/)
+{
+ Reference< XInterface > aInstance(static_cast< XXPathExtension* >(new CLibxml2XFormsExtension(/*aFactory*/)));
+ return aInstance;
+}
+
+::rtl::OUString SAL_CALL CLibxml2XFormsExtension::getImplementationName_Static()
+{
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.xml.xpath.XFormsExtension") );
+}
+
+Sequence< ::rtl::OUString > SAL_CALL CLibxml2XFormsExtension::getSupportedServiceNames_Static()
+{
+ Sequence< ::rtl::OUString > aSequence(1);
+ aSequence[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.xpath.XPathExtension") );
+ return aSequence;
+}
+
+Libxml2ExtensionHandle SAL_CALL CLibxml2XFormsExtension::getLibxml2ExtensionHandle() throw (RuntimeException)
+{
+ Libxml2ExtensionHandle aHandle;
+ aHandle.functionLookupFunction = reinterpret_cast< sal_Int64 >( &xforms_lookupFunc );
+ aHandle.functionData = reinterpret_cast< sal_Int64 >( this );
+ aHandle.variableLookupFunction = (sal_Int64)0;
+ aHandle.variableData = (sal_Int64)0;
+ return aHandle;
+}
+
+void SAL_CALL CLibxml2XFormsExtension::initialize(const Sequence< Any >& aSequence) throw (RuntimeException)
+{
+ NamedValue aValue;
+ for (sal_Int32 i = 0; i < aSequence.getLength(); i++)
+ {
+ if (! (aSequence[i] >>= aValue))
+ throw RuntimeException();
+ if (aValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Model")))
+ aValue.Value >>= m_aModel;
+ else if (aValue.Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ContextNode")))
+ aValue.Value >>= m_aContextNode;
+ }
+}
+
+Reference< XModel > CLibxml2XFormsExtension::getModel()
+{
+ return m_aModel;
+}
+
+Reference< XNode > CLibxml2XFormsExtension::getContextNode()
+{
+ return m_aContextNode;
+}
+
+extern "C" void SAL_CALL createRegistryInfo_CLibxml2XFormsExtension()
+{
+ static frm::OMultiInstanceAutoRegistration< CLibxml2XFormsExtension > aRegistration;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xpathlib/extension.hxx b/forms/source/xforms/xpathlib/extension.hxx
new file mode 100644
index 000000000000..c44a80f9860f
--- /dev/null
+++ b/forms/source/xforms/xpathlib/extension.hxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#include <rtl/ustring.h>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase2.hxx>
+
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/xml/xpath/XXPathExtension.hpp>
+#include <com/sun/star/xforms/XModel.hpp>
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/xml/dom/XNode.hpp>
+
+
+
+
+class CLibxml2XFormsExtension : public cppu::WeakImplHelper2<
+ com::sun::star::xml::xpath::XXPathExtension, com::sun::star::lang::XInitialization>
+{
+private:
+ com::sun::star::uno::Reference <com::sun::star::xforms::XModel> m_aModel;
+ com::sun::star::uno::Reference <com::sun::star::xml::dom::XNode> m_aContextNode;
+
+public:
+ static com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL Create(
+ const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& aFactory);
+ static rtl::OUString SAL_CALL getImplementationName_Static();
+ static com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames_Static();
+
+ com::sun::star::uno::Reference< com::sun::star::xforms::XModel > getModel();
+ com::sun::star::uno::Reference< com::sun::star::xml::dom::XNode > getContextNode();
+
+ virtual com::sun::star::xml::xpath::Libxml2ExtensionHandle SAL_CALL getLibxml2ExtensionHandle() throw (com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL initialize(const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aSequence) throw (com::sun::star::uno::RuntimeException);
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xpathlib/makefile.mk b/forms/source/xforms/xpathlib/makefile.mk
new file mode 100644
index 000000000000..08e58eb2834c
--- /dev/null
+++ b/forms/source/xforms/xpathlib/makefile.mk
@@ -0,0 +1,56 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..$/..
+
+PRJNAME=forms
+TARGET=xformsxpath
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE: $(PRJ)$/makefile.pmk
+
+INCPRE+=$(PRJ)$/source$/inc
+
+.IF "$(SYSTEM_LIBXML)" == "YES"
+CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS)
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/xpathlib.obj \
+ $(SLO)$/extension.obj
+
+
+# --- Tagets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/forms/source/xforms/xpathlib/xpathlib.cxx b/forms/source/xforms/xpathlib/xpathlib.cxx
new file mode 100644
index 000000000000..9a6f59a1592f
--- /dev/null
+++ b/forms/source/xforms/xpathlib/xpathlib.cxx
@@ -0,0 +1,570 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_forms.hxx"
+#include <string.h>
+#include <sal/types.h>
+#include <rtl/alloc.h>
+#include <rtl/ustring.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/strbuf.hxx>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <tools/datetime.hxx>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/xforms/XModel.hpp>
+#include <com/sun/star/xml/dom/XNode.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+
+#include "xpathlib.hxx"
+
+#include "extension.hxx"
+
+// C interface
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::xml::dom;
+using namespace com::sun::star::xforms;
+using namespace com::sun::star::lang;
+
+xmlXPathFunction xforms_lookupFunc(void *, const xmlChar *xname, const xmlChar *)
+{
+
+ const char *name = (char *)xname;
+ if (strcmp("boolean-from-string", name)==0)
+ return xforms_booleanFromStringFunction;
+ else if ((strcmp("if", name))==0)
+ return xforms_ifFunction;
+ else if ((strcmp("avg", name))==0)
+ return xforms_avgFunction;
+ else if ((strcmp("min", name))==0)
+ return xforms_minFunction;
+ else if ((strcmp("max", name))==0)
+ return xforms_maxFunction;
+ else if ((strcmp("count-non-empty", name))==0)
+ return xforms_countNonEmptyFunction;
+ else if ((strcmp("index", name))==0)
+ return xforms_indexFunction;
+ else if ((strcmp("property", name))==0)
+ return xforms_propertyFunction;
+ else if ((strcmp("now", name))==0)
+ return xforms_nowFunction;
+ else if ((strcmp("days-from-date", name))==0)
+ return xforms_daysFromDateFunction;
+ else if ((strcmp("seconds-from-dateTime", name))==0)
+ return xforms_secondsFromDateTimeFunction;
+ else if ((strcmp("seconds", name))==0)
+ return xforms_secondsFuction;
+ else if ((strcmp("months", name))==0)
+ return xforms_monthsFuction;
+ else if ((strcmp("instance", name))==0)
+ return xforms_instanceFuction;
+ else if ((strcmp("current", name))==0)
+ return xforms_currentFunction;
+ else
+ return NULL;
+}
+
+// boolean functions
+void xforms_booleanFromStringFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlChar *pString = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
+ if (aString.equalsIgnoreAsciiCaseAscii("true") || aString.equalsIgnoreAsciiCaseAscii("1"))
+ xmlXPathReturnTrue(ctxt);
+ else if (aString.equalsIgnoreAsciiCaseAscii("false") || aString.equalsIgnoreAsciiCaseAscii("0"))
+ xmlXPathReturnFalse(ctxt);
+ else
+ XP_ERROR(XPATH_NUMBER_ERROR);
+}
+
+void xforms_ifFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ if (nargs != 3) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlChar *s2 = xmlXPathPopString(ctxt);
+
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ xmlChar *s1 = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ bool aBool = xmlXPathPopBoolean(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+
+ if (aBool)
+ xmlXPathReturnString(ctxt, s1);
+ else
+ xmlXPathReturnString(ctxt, s2);
+
+}
+
+// Number Functions
+void xforms_avgFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ // use sum(), div() and count()
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+
+ // save nodeset
+ xmlXPathObjectPtr pObject = valuePop(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ //push back a copy
+ valuePush(ctxt, xmlXPathObjectCopy(pObject));
+ // get the Sum
+ xmlXPathSumFunction(ctxt, 1);
+ double nSum = xmlXPathPopNumber(ctxt);
+ // push a copy once more
+ valuePush(ctxt, xmlXPathObjectCopy(pObject));
+ xmlXPathCountFunction(ctxt, 1);
+ double nCount = xmlXPathPopNumber(ctxt);
+ // push args for div()
+ xmlXPathReturnNumber(ctxt, nSum);
+ xmlXPathReturnNumber(ctxt, nCount);
+ xmlXPathDivValues(ctxt);
+ // the result is now on the ctxt stack
+ xmlXPathFreeObject(pObject);
+}
+
+void xforms_minFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ double nMinimum = 0;
+ double nNumber = 0;
+ for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
+ {
+ nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i));
+ if (xmlXPathIsNaN(nNumber))
+ {
+ xmlXPathReturnNumber(ctxt, xmlXPathNAN);
+ return;
+ }
+ if (i == 0)
+ nMinimum = nNumber;
+ else if (nNumber < nMinimum)
+ nMinimum = nNumber;
+ }
+ xmlXPathReturnNumber(ctxt, nMinimum);
+}
+
+void xforms_maxFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ double nMaximum = 0;
+ double nNumber = 0;
+ for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
+ {
+ nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i));
+ if (xmlXPathIsNaN(nNumber))
+ {
+ xmlXPathReturnNumber(ctxt, xmlXPathNAN);
+ return;
+ }
+ if (i == 0)
+ nMaximum = nNumber;
+ else if (nNumber > nMaximum)
+ nMaximum = nNumber;
+ }
+ xmlXPathReturnNumber(ctxt, nMaximum);
+}
+void xforms_countNonEmptyFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ xmlChar *aString;
+ sal_Int32 nNotEmpty = 0;
+ for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
+ {
+ aString = xmlXPathCastNodeToString(xmlXPathNodeSetItem(pNodeSet, i));
+ if (*aString != 0) nNotEmpty++;
+ }
+ xmlXPathReturnNumber(ctxt, nNotEmpty);
+}
+void xforms_indexFunction(xmlXPathParserContextPtr /*ctxt*/, int /*nargs*/)
+{
+ // function index takes a string argument that is the IDREF of a
+ // 'repeat' and returns the current 1-based position of the repeat
+ // index of the identified repeat -- see xforms/9.3.1
+
+ // doc.getElementByID
+ // (...)
+}
+
+// String Functions
+static const char* _version = "1.0";
+static const char* _conformance = "conformance";
+void xforms_propertyFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlChar* pString = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
+ if (aString.equalsIgnoreAsciiCaseAscii("version"))
+ xmlXPathReturnString(ctxt, (xmlChar*)_version);
+ else if (aString.equalsIgnoreAsciiCaseAscii("conformance-level"))
+ xmlXPathReturnString(ctxt, (xmlChar*)_conformance);
+ else
+ xmlXPathReturnEmptyString(ctxt);
+}
+
+// Date and Time Functions
+
+static ::rtl::OString makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_True)
+{
+ ::rtl::OStringBuffer aDateTimeString;
+ aDateTimeString.append((sal_Int32)aDateTime.GetYear());
+ aDateTimeString.append("-");
+ if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
+ aDateTimeString.append("-");
+ if (aDateTime.GetDay()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetDay());
+ aDateTimeString.append("T");
+ if (aDateTime.GetHour()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetHour());
+ aDateTimeString.append(":");
+ if (aDateTime.GetMin()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetMin());
+ aDateTimeString.append(":");
+ if (aDateTime.GetSec()<10) aDateTimeString.append("0");
+ aDateTimeString.append((sal_Int32)aDateTime.GetSec());
+ if (bUTC) aDateTimeString.append("Z");
+
+ return aDateTimeString.makeStringAndClear();
+}
+
+// returns current system date and time in canonical xsd:dateTime
+// format
+void xforms_nowFunction(xmlXPathParserContextPtr ctxt, int /*nargs*/)
+{
+ /*
+ A single lexical representation, which is a subset of the lexical representations
+ allowed by [ISO 8601], is allowed for dateTime. This lexical representation is the
+ [ISO 8601] extended format CCYY-MM-DDThh:mm:ss where "CC" represents the century,
+ "YY" the year, "MM" the month and "DD" the day, preceded by an optional leading "-"
+ sign to indicate a negative number. If the sign is omitted, "+" is assumed. The letter
+ "T" is the date/time separator and "hh", "mm", "ss" represent hour, minute and second
+ respectively.
+ */
+
+ /*
+ 3.2.7.2 Canonical representation
+ The canonical representation for dateTime is defined by prohibiting certain options
+ from the Lexical representation (par.3.2.7.1). Specifically, either the time zone must
+ be omitted or, if present, the time zone must be Coordinated Universal Time (UTC)
+ indicated by a "Z".
+ */
+ DateTime aDateTime;
+ ::rtl::OString aDateTimeString = makeDateTimeString(aDateTime);
+ xmlChar *pString = static_cast<xmlChar*>(xmlMalloc(aDateTimeString.getLength()+1));
+ strncpy((char*)pString, (char*)aDateTimeString.getStr(), aDateTimeString.getLength());
+ pString[aDateTimeString.getLength()] = 0;
+ xmlXPathReturnString(ctxt, pString);
+}
+
+static sal_Bool parseDateTime(const ::rtl::OUString& aString, DateTime& aDateTime)
+{
+ // take apart a canonical literal xsd:dateTime string
+ //CCYY-MM-DDThh:mm:ss(Z)
+
+ ::rtl::OUString aDateTimeString = aString.trim();
+
+ // check length
+ if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
+ return sal_False;
+
+ sal_Int32 nDateLength = 10;
+ sal_Int32 nTimeLength = 8;
+
+ ::rtl::OUString aDateTimeSep(RTL_CONSTASCII_USTRINGPARAM("T"));
+ ::rtl::OUString aDateSep(RTL_CONSTASCII_USTRINGPARAM("-"));
+ ::rtl::OUString aTimeSep(RTL_CONSTASCII_USTRINGPARAM(":"));
+ ::rtl::OUString aUTCString(RTL_CONSTASCII_USTRINGPARAM("Z"));
+
+ ::rtl::OUString aDateString = aDateTimeString.copy(0, nDateLength);
+ ::rtl::OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
+
+ sal_Int32 nIndex = 0;
+ sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
+ sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
+ sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
+ nIndex = 0;
+ sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
+ sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
+ sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
+
+ Date tmpDate((USHORT)nDay, (USHORT)nMonth, (USHORT)nYear);
+ Time tmpTime(nHour, nMinute, nSecond);
+ DateTime tmpDateTime(tmpDate, tmpTime);
+ if (aString.indexOf(aUTCString) < 0)
+ tmpDateTime.ConvertToUTC();
+
+ aDateTime = tmpDateTime;
+
+ return sal_True;
+}
+
+
+void xforms_daysFromDateFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ // number of days from 1970-01-01 to supplied xsd:date(Time)
+
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlChar* pString = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
+
+ DateTime aDateTime;
+ if (parseDateTime(aString, aDateTime))
+ {
+ Date aReferenceDate(1, 1, 1970);
+ sal_Int32 nDays = aDateTime - aReferenceDate;
+ xmlXPathReturnNumber(ctxt, nDays);
+ }
+ else
+ xmlXPathReturnNumber(ctxt, xmlXPathNAN);
+
+
+}
+
+
+void xforms_secondsFromDateTimeFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ // number of seconds from 1970-01-01T00:00:00Z to supplied xsd:date(Time)
+
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlChar* pString = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
+
+ DateTime aDateTime;
+
+ if (parseDateTime(aString, aDateTime))
+ {
+ Date aReferenceDate(1, 1, 1970);
+ Time aReferenceTime(0, 0, 0);
+ sal_Int32 nDays = aDateTime - aReferenceDate;
+ sal_Int32 nSeconds = nDays * 24 * 60 * 60;
+ nSeconds += aDateTime.GetHour() * 60 * 60;
+ nSeconds += aDateTime.GetMin() * 60;
+ nSeconds += aDateTime.GetSec();
+ xmlXPathReturnNumber(ctxt, nSeconds);
+ }
+ else
+ xmlXPathReturnNumber(ctxt, xmlXPathNAN);
+
+}
+
+static sal_Bool parseDuration(const xmlChar* aString, sal_Bool& bNegative, sal_Int32& nYears, sal_Int32& nMonth, sal_Int32& nDays,
+ sal_Int32& nHours, sal_Int32& nMinutes, sal_Int32& nSeconds)
+{
+ sal_Bool bTime = sal_False; // in part after T
+ sal_Int32 nLength = strlen((char*)aString)+1;
+ char *pString = (char*)rtl_allocateMemory(nLength);
+ char *pString0 = pString;
+ strncpy(pString, (char*)aString, nLength);
+
+ if (pString[0] == '-') {
+ bNegative = sal_True;
+ pString++;
+ }
+
+ if (pString[0] != 'P')
+ return sal_False;
+ pString++;
+ char* pToken = pString;
+ while(pToken[0] != 0)
+ {
+ switch(pToken[0]) {
+ case 'Y':
+ pToken[0] = 0;
+ nYears = atoi(pString);
+ pString = ++pToken;
+ break;
+ case 'M':
+ pToken[0] = 0;
+ if (!bTime)
+ nMonth = atoi(pString);
+ else
+ nMinutes = atoi(pString);
+ pString = ++pToken;
+ break;
+ case 'D':
+ pToken[0] = 0;
+ nDays = atoi(pString);
+ pString = ++pToken;
+ break;
+ case 'H':
+ pToken[0] = 0;
+ nHours = atoi(pString);
+ pString = ++pToken;
+ break;
+ case 'S':
+ pToken[0] = 0;
+ nSeconds = atoi(pString);
+ pString = ++pToken;
+ break;
+ case 'T':
+ bTime = sal_True;
+ pString = ++pToken;
+ break;
+ default:
+ pToken++;
+ }
+ }
+ rtl_freeMemory(pString0);
+ return sal_True;
+}
+
+void xforms_secondsFuction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ // convert a xsd:duration to seconds
+ // (-)PnYnMnDTnHnMnS
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlChar* pString = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+
+ sal_Bool bNegative = sal_False;
+ sal_Int32 nYears = 0;
+ sal_Int32 nMonths = 0;
+ sal_Int32 nDays = 0;
+ sal_Int32 nHours = 0;
+ sal_Int32 nMinutes = 0;
+ sal_Int32 nSeconds = 0;
+
+ if (parseDuration(pString, bNegative, nYears, nMonths, nDays, nHours, nMinutes, nSeconds))
+ {
+ nSeconds += nMinutes*60;
+ nSeconds += nHours*60*60;
+ nSeconds += nDays*24*60*60;
+ // year and month are ignored according to spec
+ if (bNegative)
+ nSeconds = 0 - nSeconds;
+ xmlXPathReturnNumber(ctxt, nSeconds);
+ }
+ else
+ xmlXPathReturnNumber(ctxt, xmlXPathNAN);
+}
+
+void xforms_monthsFuction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ // convert a xsd:duration to seconds
+ // (-)PnYnMnDTnHnMnS
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlChar* pString = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+
+ sal_Bool bNegative = sal_False;
+ sal_Int32 nYears = 0;
+ sal_Int32 nMonths = 0;
+ sal_Int32 nDays = 0;
+ sal_Int32 nHours = 0;
+ sal_Int32 nMinutes = 0;
+ sal_Int32 nSeconds = 0;
+
+ if (parseDuration(pString, bNegative, nYears, nMonths, nDays, nHours, nMinutes, nSeconds))
+ {
+ nMonths += nYears*12;
+ // Days, Houres, Minutes and seconds are ignored, see spec
+ if (bNegative)
+ nMonths = 0 - nMonths;
+ xmlXPathReturnNumber(ctxt, nMonths);
+ }
+ else
+ xmlXPathReturnNumber(ctxt, xmlXPathNAN);
+
+}
+
+// Node-set Functions
+void xforms_instanceFuction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
+ xmlChar *pString = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
+ ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
+
+ Reference< XModel > aModel = ((CLibxml2XFormsExtension*)ctxt->context->funcLookupData)->getModel();
+ if (aModel.is())
+ {
+ Reference< XDocument > aInstance = aModel->getInstanceDocument(aString);
+ if (aInstance.is())
+ {
+ try {
+ // xmlXPathObjectPtr xmlXPathNewNodeSet (xmlNodePtr val);
+ Reference< XUnoTunnel > aTunnel(aInstance, UNO_QUERY_THROW);
+ xmlNodePtr pNode = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(Sequence< sal_Int8 >()) );
+ xmlXPathObjectPtr pObject = xmlXPathNewNodeSet(pNode);
+ xmlXPathReturnNodeSet(ctxt, pObject->nodesetval);
+ } catch (RuntimeException&)
+ {
+ xmlXPathReturnEmptyNodeSet(ctxt);
+ }
+ }
+ else
+ xmlXPathReturnEmptyNodeSet(ctxt);
+ }
+ else
+ xmlXPathReturnEmptyNodeSet(ctxt);
+
+}
+
+// Node-set Functions, XForms 1.1
+void xforms_currentFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ if (nargs != 0) XP_ERROR(XPATH_INVALID_ARITY);
+
+ Reference< XNode > aNode = ((CLibxml2XFormsExtension*)ctxt->context->funcLookupData)->getContextNode();
+
+ if (aNode.is())
+ {
+ try {
+ Reference< XUnoTunnel > aTunnel(aNode, UNO_QUERY_THROW);
+ xmlNodePtr pNode = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(Sequence< sal_Int8 >()) );
+ xmlXPathObjectPtr pObject = xmlXPathNewNodeSet(pNode);
+ xmlXPathReturnNodeSet(ctxt, pObject->nodesetval);
+ }
+ catch (RuntimeException&)
+ {
+ xmlXPathReturnEmptyNodeSet(ctxt);
+ }
+ }
+ else
+ xmlXPathReturnEmptyNodeSet(ctxt);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/forms/source/xforms/xpathlib/xpathlib.hxx b/forms/source/xforms/xpathlib/xpathlib.hxx
new file mode 100644
index 000000000000..2a74c1899bc8
--- /dev/null
+++ b/forms/source/xforms/xpathlib/xpathlib.hxx
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+/*
+ entry functions for libxml xpath engine
+
+*/
+
+/**
+ * xmlXPathParserContext:
+ *
+ * An XPath parser context. It contains pure parsing informations,
+ * an xmlXPathContext, and the stack of objects.
+ */
+
+extern "C"
+{
+
+// XForms
+
+// XForms Core Functions
+// boolean functions
+void xforms_booleanFromStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_ifFunction(xmlXPathParserContextPtr ctxt, int nargs);
+
+// Number Functions
+void xforms_avgFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_minFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_maxFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_countNonEmptyFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_indexFunction(xmlXPathParserContextPtr ctxt, int nargs);
+
+// String Functions
+void xforms_propertyFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_versionFunction(xmlXPathParserContextPtr ctxt, int nargs);
+
+// Date and Time Functions
+void xforms_nowFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_daysFromDateFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_secondsFromDateTimeFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_secondsFuction(xmlXPathParserContextPtr ctxt, int nargs);
+void xforms_monthsFuction(xmlXPathParserContextPtr ctxt, int nargs);
+
+// Node-set Functions
+void xforms_instanceFuction(xmlXPathParserContextPtr ctxt, int nargs);
+
+// Node-set Functions; XForms 1.1
+void xforms_currentFunction(xmlXPathParserContextPtr ctxt, int nargs);
+
+// --- lookup ---
+xmlXPathFunction xforms_lookupFunc(void *ctxt, const xmlChar *name, const xmlChar *ns_uri);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */