1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_forms.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include "binding.hxx" 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #include "model.hxx" 34*cdf0e10cSrcweir #include "unohelper.hxx" 35*cdf0e10cSrcweir #include "NameContainer.hxx" 36*cdf0e10cSrcweir #include "evaluationcontext.hxx" 37*cdf0e10cSrcweir #include "convert.hxx" 38*cdf0e10cSrcweir #include "resourcehelper.hxx" 39*cdf0e10cSrcweir #include "xmlhelper.hxx" 40*cdf0e10cSrcweir #include "xformsevent.hxx" 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 43*cdf0e10cSrcweir #include <osl/diagnose.h> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir #include <algorithm> 48*cdf0e10cSrcweir #include <functional> 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir #include <com/sun/star/uno/Any.hxx> 51*cdf0e10cSrcweir #include <com/sun/star/xml/dom/XNodeList.hpp> 52*cdf0e10cSrcweir #include <com/sun/star/xml/dom/XNode.hpp> 53*cdf0e10cSrcweir #include <com/sun/star/xml/dom/XDocument.hpp> 54*cdf0e10cSrcweir #include <com/sun/star/xml/dom/XElement.hpp> 55*cdf0e10cSrcweir #include <com/sun/star/xml/dom/NodeType.hpp> 56*cdf0e10cSrcweir #include <com/sun/star/xml/dom/events/XEventTarget.hpp> 57*cdf0e10cSrcweir #include <com/sun/star/xml/dom/events/XEventListener.hpp> 58*cdf0e10cSrcweir #include <com/sun/star/xml/dom/events/XDocumentEvent.hpp> 59*cdf0e10cSrcweir #include <com/sun/star/lang/XUnoTunnel.hpp> 60*cdf0e10cSrcweir #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> 61*cdf0e10cSrcweir #include <com/sun/star/container/XSet.hpp> 62*cdf0e10cSrcweir #include <com/sun/star/container/XNameContainer.hpp> 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir #include <comphelper/propertysetinfo.hxx> 65*cdf0e10cSrcweir #include <unotools/textsearch.hxx> 66*cdf0e10cSrcweir #include <cppuhelper/typeprovider.hxx> 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir using namespace com::sun::star::xml::xpath; 69*cdf0e10cSrcweir using namespace com::sun::star::xml::dom::events; 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir using rtl::OUString; 72*cdf0e10cSrcweir using rtl::OUStringBuffer; 73*cdf0e10cSrcweir using std::vector; 74*cdf0e10cSrcweir using xforms::Binding; 75*cdf0e10cSrcweir using xforms::MIP; 76*cdf0e10cSrcweir using xforms::Model; 77*cdf0e10cSrcweir using xforms::getResource; 78*cdf0e10cSrcweir using xforms::EvaluationContext; 79*cdf0e10cSrcweir using com::sun::star::beans::PropertyVetoException; 80*cdf0e10cSrcweir using com::sun::star::beans::UnknownPropertyException; 81*cdf0e10cSrcweir using com::sun::star::beans::XPropertySet; 82*cdf0e10cSrcweir using com::sun::star::container::XSet; 83*cdf0e10cSrcweir using com::sun::star::container::XNameAccess; 84*cdf0e10cSrcweir using com::sun::star::form::binding::IncompatibleTypesException; 85*cdf0e10cSrcweir using com::sun::star::form::binding::InvalidBindingStateException; 86*cdf0e10cSrcweir using com::sun::star::form::binding::XValueBinding; 87*cdf0e10cSrcweir using com::sun::star::lang::EventObject; 88*cdf0e10cSrcweir using com::sun::star::lang::IllegalArgumentException; 89*cdf0e10cSrcweir using com::sun::star::lang::IndexOutOfBoundsException; 90*cdf0e10cSrcweir using com::sun::star::lang::NoSupportException; 91*cdf0e10cSrcweir using com::sun::star::lang::NullPointerException; 92*cdf0e10cSrcweir using com::sun::star::lang::WrappedTargetException; 93*cdf0e10cSrcweir using com::sun::star::lang::XUnoTunnel; 94*cdf0e10cSrcweir using com::sun::star::uno::Any; 95*cdf0e10cSrcweir using com::sun::star::uno::Reference; 96*cdf0e10cSrcweir using com::sun::star::uno::RuntimeException; 97*cdf0e10cSrcweir using com::sun::star::uno::Sequence; 98*cdf0e10cSrcweir using com::sun::star::uno::UNO_QUERY; 99*cdf0e10cSrcweir using com::sun::star::uno::UNO_QUERY_THROW; 100*cdf0e10cSrcweir using com::sun::star::uno::XInterface; 101*cdf0e10cSrcweir using com::sun::star::uno::Exception; 102*cdf0e10cSrcweir using com::sun::star::uno::makeAny; 103*cdf0e10cSrcweir using com::sun::star::util::XModifyListener; 104*cdf0e10cSrcweir using com::sun::star::xforms::XDataTypeRepository; 105*cdf0e10cSrcweir using com::sun::star::xml::dom::NodeType_ATTRIBUTE_NODE; 106*cdf0e10cSrcweir using com::sun::star::xml::dom::NodeType_TEXT_NODE; 107*cdf0e10cSrcweir using com::sun::star::xml::dom::XNode; 108*cdf0e10cSrcweir using com::sun::star::xml::dom::XNodeList; 109*cdf0e10cSrcweir using com::sun::star::xml::dom::events::XEventListener; 110*cdf0e10cSrcweir using com::sun::star::xml::dom::events::XEventTarget; 111*cdf0e10cSrcweir using com::sun::star::xsd::XDataType; 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir 114*cdf0e10cSrcweir 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir #define EXCEPT(msg) OUSTRING(msg),static_cast<XValueBinding*>(this) 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir #define HANDLE_BindingID 0 119*cdf0e10cSrcweir #define HANDLE_BindingExpression 1 120*cdf0e10cSrcweir #define HANDLE_Model 2 121*cdf0e10cSrcweir #define HANDLE_ModelID 3 122*cdf0e10cSrcweir #define HANDLE_BindingNamespaces 4 123*cdf0e10cSrcweir #define HANDLE_ReadonlyExpression 5 124*cdf0e10cSrcweir #define HANDLE_RelevantExpression 6 125*cdf0e10cSrcweir #define HANDLE_RequiredExpression 7 126*cdf0e10cSrcweir #define HANDLE_ConstraintExpression 8 127*cdf0e10cSrcweir #define HANDLE_CalculateExpression 9 128*cdf0e10cSrcweir #define HANDLE_Type 10 129*cdf0e10cSrcweir #define HANDLE_ReadOnly 11 // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control 130*cdf0e10cSrcweir #define HANDLE_Relevant 12 // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control 131*cdf0e10cSrcweir #define HANDLE_ModelNamespaces 13 132*cdf0e10cSrcweir #define HANDLE_ExternalData 14 133*cdf0e10cSrcweir 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir Binding::Binding() : 136*cdf0e10cSrcweir mxModel(), 137*cdf0e10cSrcweir msBindingID(), 138*cdf0e10cSrcweir maBindingExpression(), 139*cdf0e10cSrcweir maReadonly(), 140*cdf0e10cSrcweir mxNamespaces( new NameContainer<OUString>() ), 141*cdf0e10cSrcweir mbInCalculate( false ), 142*cdf0e10cSrcweir mnDeferModifyNotifications( 0 ), 143*cdf0e10cSrcweir mbValueModified( false ), 144*cdf0e10cSrcweir mbBindingModified( false ) 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir { 147*cdf0e10cSrcweir initializePropertySet(); 148*cdf0e10cSrcweir } 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir Binding::~Binding() throw() 151*cdf0e10cSrcweir { 152*cdf0e10cSrcweir _setModel(NULL); 153*cdf0e10cSrcweir } 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir 156*cdf0e10cSrcweir Binding::Model_t Binding::getModel() const 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir return mxModel; 159*cdf0e10cSrcweir } 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir void Binding::_setModel( const Model_t& xModel ) 162*cdf0e10cSrcweir { 163*cdf0e10cSrcweir PropertyChangeNotifier aNotifyModelChange( *this, HANDLE_Model ); 164*cdf0e10cSrcweir PropertyChangeNotifier aNotifyModelIDChange( *this, HANDLE_ModelID ); 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir // prepare binding for removal of old model 167*cdf0e10cSrcweir clear(); // remove all cached data (e.g. XPath evaluation results) 168*cdf0e10cSrcweir XNameContainer_t xNamespaces = getModelNamespaces(); // save namespaces 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir mxModel = xModel; 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir // set namespaces (and move to model, if appropriate) 173*cdf0e10cSrcweir setBindingNamespaces( xNamespaces ); 174*cdf0e10cSrcweir _checkBindingID(); 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir notifyAndCachePropertyValue( HANDLE_ExternalData ); 177*cdf0e10cSrcweir } 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir OUString Binding::getModelID() const 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir Model* pModel = getModelImpl(); 183*cdf0e10cSrcweir return ( pModel == NULL ) ? OUString() : pModel->getID(); 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir Binding::XNodeList_t Binding::getXNodeList() 188*cdf0e10cSrcweir { 189*cdf0e10cSrcweir // first make sure we are bound 190*cdf0e10cSrcweir if( ! maBindingExpression.hasValue() ) 191*cdf0e10cSrcweir bind( sal_False ); 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir return maBindingExpression.getXNodeList(); 194*cdf0e10cSrcweir } 195*cdf0e10cSrcweir 196*cdf0e10cSrcweir bool Binding::isSimpleBinding() const 197*cdf0e10cSrcweir { 198*cdf0e10cSrcweir return maBindingExpression.isSimpleExpression() 199*cdf0e10cSrcweir && maReadonly.isSimpleExpression() 200*cdf0e10cSrcweir && maRelevant.isSimpleExpression() 201*cdf0e10cSrcweir && maRequired.isSimpleExpression() 202*cdf0e10cSrcweir && maConstraint.isSimpleExpression() 203*cdf0e10cSrcweir && maCalculate.isSimpleExpression(); 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir bool Binding::isSimpleBindingExpression() const 207*cdf0e10cSrcweir { 208*cdf0e10cSrcweir return maBindingExpression.isSimpleExpression(); 209*cdf0e10cSrcweir } 210*cdf0e10cSrcweir 211*cdf0e10cSrcweir void Binding::update() 212*cdf0e10cSrcweir { 213*cdf0e10cSrcweir // clear all expressions (to remove cached node references) 214*cdf0e10cSrcweir maBindingExpression.clear(); 215*cdf0e10cSrcweir maReadonly.clear(); 216*cdf0e10cSrcweir maRelevant.clear(); 217*cdf0e10cSrcweir maRequired.clear(); 218*cdf0e10cSrcweir maConstraint.clear(); 219*cdf0e10cSrcweir maCalculate.clear(); 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir // let's just pretend the binding has been modified -> full rebind() 222*cdf0e10cSrcweir bindingModified(); 223*cdf0e10cSrcweir } 224*cdf0e10cSrcweir 225*cdf0e10cSrcweir void Binding::deferNotifications( bool bDefer ) 226*cdf0e10cSrcweir { 227*cdf0e10cSrcweir mnDeferModifyNotifications += ( bDefer ? 1 : -1 ); 228*cdf0e10cSrcweir OSL_ENSURE( mnDeferModifyNotifications >= 0, "you're deferring too much" ); 229*cdf0e10cSrcweir 230*cdf0e10cSrcweir if( mnDeferModifyNotifications == 0 ) 231*cdf0e10cSrcweir { 232*cdf0e10cSrcweir if( mbBindingModified ) 233*cdf0e10cSrcweir bindingModified(); 234*cdf0e10cSrcweir if( mbValueModified ) 235*cdf0e10cSrcweir valueModified(); 236*cdf0e10cSrcweir } 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir OSL_ENSURE( ( mnDeferModifyNotifications > 0 ) 239*cdf0e10cSrcweir || ( ! mbBindingModified && ! mbValueModified ), 240*cdf0e10cSrcweir "deferred modifications not delivered?" ); 241*cdf0e10cSrcweir } 242*cdf0e10cSrcweir 243*cdf0e10cSrcweir bool Binding::isValid() 244*cdf0e10cSrcweir { 245*cdf0e10cSrcweir // TODO: determine whether node is suitable, not just whether it exists 246*cdf0e10cSrcweir return maBindingExpression.getNode().is() && 247*cdf0e10cSrcweir isValid_DataType() && 248*cdf0e10cSrcweir maMIP.isConstraint() && 249*cdf0e10cSrcweir ( ! maMIP.isRequired() || 250*cdf0e10cSrcweir ( maBindingExpression.hasValue() && 251*cdf0e10cSrcweir maBindingExpression.getString().getLength() > 0 ) ); 252*cdf0e10cSrcweir } 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir bool Binding::isUseful() 255*cdf0e10cSrcweir { 256*cdf0e10cSrcweir // we are useful, if 257*cdf0e10cSrcweir // 0) we don't have a model 258*cdf0e10cSrcweir // (at least, in this case we shouldn't be removed from the model) 259*cdf0e10cSrcweir // 1) we have a proper name 260*cdf0e10cSrcweir // 2) we have some MIPs, 261*cdf0e10cSrcweir // 3) we are bound to some control 262*cdf0e10cSrcweir // (this can be assumed if some listeners are set) 263*cdf0e10cSrcweir bool bUseful = 264*cdf0e10cSrcweir getModelImpl() == NULL 265*cdf0e10cSrcweir // || msBindingID.getLength() > 0 266*cdf0e10cSrcweir || msTypeName.getLength() > 0 267*cdf0e10cSrcweir || ! maReadonly.isEmptyExpression() 268*cdf0e10cSrcweir || ! maRelevant.isEmptyExpression() 269*cdf0e10cSrcweir || ! maRequired.isEmptyExpression() 270*cdf0e10cSrcweir || ! maConstraint.isEmptyExpression() 271*cdf0e10cSrcweir || ! maCalculate.isEmptyExpression() 272*cdf0e10cSrcweir || ! maModifyListeners.empty() 273*cdf0e10cSrcweir || ! maListEntryListeners.empty() 274*cdf0e10cSrcweir || ! maValidityListeners.empty(); 275*cdf0e10cSrcweir 276*cdf0e10cSrcweir return bUseful; 277*cdf0e10cSrcweir } 278*cdf0e10cSrcweir 279*cdf0e10cSrcweir OUString Binding::explainInvalid() 280*cdf0e10cSrcweir { 281*cdf0e10cSrcweir OUString sReason; 282*cdf0e10cSrcweir if( ! maBindingExpression.getNode().is() ) 283*cdf0e10cSrcweir { 284*cdf0e10cSrcweir sReason = ( maBindingExpression.getExpression().getLength() == 0 ) 285*cdf0e10cSrcweir ? getResource( RID_STR_XFORMS_NO_BINDING_EXPRESSION ) 286*cdf0e10cSrcweir : getResource( RID_STR_XFORMS_INVALID_BINDING_EXPRESSION ); 287*cdf0e10cSrcweir } 288*cdf0e10cSrcweir else if( ! isValid_DataType() ) 289*cdf0e10cSrcweir { 290*cdf0e10cSrcweir sReason = explainInvalid_DataType(); 291*cdf0e10cSrcweir if( sReason.getLength() == 0 ) 292*cdf0e10cSrcweir { 293*cdf0e10cSrcweir // no explanation given by data type? Then give generic message 294*cdf0e10cSrcweir sReason = getResource( RID_STR_XFORMS_INVALID_VALUE, 295*cdf0e10cSrcweir maMIP.getTypeName() ); 296*cdf0e10cSrcweir } 297*cdf0e10cSrcweir } 298*cdf0e10cSrcweir else if( ! maMIP.isConstraint() ) 299*cdf0e10cSrcweir { 300*cdf0e10cSrcweir sReason = maMIP.getConstraintExplanation(); 301*cdf0e10cSrcweir } 302*cdf0e10cSrcweir else if( maMIP.isRequired() && maBindingExpression.hasValue() && 303*cdf0e10cSrcweir ( maBindingExpression.getString().getLength() == 0 ) ) 304*cdf0e10cSrcweir { 305*cdf0e10cSrcweir sReason = getResource( RID_STR_XFORMS_REQUIRED ); 306*cdf0e10cSrcweir } 307*cdf0e10cSrcweir // else: no explanation given; should only happen if data is valid 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir OSL_ENSURE( ( sReason.getLength() == 0 ) == isValid(), 310*cdf0e10cSrcweir "invalid data should have an explanation!" ); 311*cdf0e10cSrcweir 312*cdf0e10cSrcweir return sReason; 313*cdf0e10cSrcweir } 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir 317*cdf0e10cSrcweir EvaluationContext Binding::getEvaluationContext() const 318*cdf0e10cSrcweir { 319*cdf0e10cSrcweir OSL_ENSURE( getModelImpl() != NULL, "need model impl" ); 320*cdf0e10cSrcweir EvaluationContext aContext = getModelImpl()->getEvaluationContext(); 321*cdf0e10cSrcweir aContext.mxNamespaces = getBindingNamespaces(); 322*cdf0e10cSrcweir return aContext; 323*cdf0e10cSrcweir } 324*cdf0e10cSrcweir 325*cdf0e10cSrcweir ::std::vector<EvaluationContext> Binding::getMIPEvaluationContexts() 326*cdf0e10cSrcweir { 327*cdf0e10cSrcweir OSL_ENSURE( getModelImpl() != NULL, "need model impl" ); 328*cdf0e10cSrcweir 329*cdf0e10cSrcweir // bind (in case we were not bound before) 330*cdf0e10cSrcweir bind( sal_False ); 331*cdf0e10cSrcweir return _getMIPEvaluationContexts(); 332*cdf0e10cSrcweir } 333*cdf0e10cSrcweir 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir Binding::IntSequence_t Binding::getUnoTunnelID() 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir static cppu::OImplementationId aImplementationId; 338*cdf0e10cSrcweir return aImplementationId.getImplementationId(); 339*cdf0e10cSrcweir } 340*cdf0e10cSrcweir 341*cdf0e10cSrcweir Binding* SAL_CALL Binding::getBinding( const Reference<XPropertySet>& xPropertySet ) 342*cdf0e10cSrcweir { 343*cdf0e10cSrcweir Reference<XUnoTunnel> xTunnel( xPropertySet, UNO_QUERY ); 344*cdf0e10cSrcweir return xTunnel.is() 345*cdf0e10cSrcweir ? reinterpret_cast<Binding*>( xTunnel->getSomething(getUnoTunnelID())) 346*cdf0e10cSrcweir : NULL; 347*cdf0e10cSrcweir } 348*cdf0e10cSrcweir 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir 352*cdf0e10cSrcweir OUString Binding::getBindingID() const 353*cdf0e10cSrcweir { 354*cdf0e10cSrcweir return msBindingID; 355*cdf0e10cSrcweir } 356*cdf0e10cSrcweir 357*cdf0e10cSrcweir void Binding::setBindingID( const OUString& sBindingID ) 358*cdf0e10cSrcweir { 359*cdf0e10cSrcweir msBindingID = sBindingID; 360*cdf0e10cSrcweir } 361*cdf0e10cSrcweir 362*cdf0e10cSrcweir OUString Binding::getBindingExpression() const 363*cdf0e10cSrcweir { 364*cdf0e10cSrcweir return maBindingExpression.getExpression(); 365*cdf0e10cSrcweir } 366*cdf0e10cSrcweir 367*cdf0e10cSrcweir void Binding::setBindingExpression( const OUString& sBindingExpression) 368*cdf0e10cSrcweir { 369*cdf0e10cSrcweir maBindingExpression.setExpression( sBindingExpression ); 370*cdf0e10cSrcweir bindingModified(); 371*cdf0e10cSrcweir } 372*cdf0e10cSrcweir 373*cdf0e10cSrcweir OUString Binding::getReadonlyExpression() const 374*cdf0e10cSrcweir { 375*cdf0e10cSrcweir return maReadonly.getExpression(); 376*cdf0e10cSrcweir } 377*cdf0e10cSrcweir 378*cdf0e10cSrcweir void Binding::setReadonlyExpression( const OUString& sReadonly) 379*cdf0e10cSrcweir { 380*cdf0e10cSrcweir maReadonly.setExpression( sReadonly ); 381*cdf0e10cSrcweir bindingModified(); 382*cdf0e10cSrcweir } 383*cdf0e10cSrcweir 384*cdf0e10cSrcweir OUString Binding::getRelevantExpression() const 385*cdf0e10cSrcweir { 386*cdf0e10cSrcweir return maRelevant.getExpression(); 387*cdf0e10cSrcweir } 388*cdf0e10cSrcweir 389*cdf0e10cSrcweir void Binding::setRelevantExpression( const OUString& sRelevant ) 390*cdf0e10cSrcweir { 391*cdf0e10cSrcweir maRelevant.setExpression( sRelevant ); 392*cdf0e10cSrcweir bindingModified(); 393*cdf0e10cSrcweir } 394*cdf0e10cSrcweir 395*cdf0e10cSrcweir OUString Binding::getRequiredExpression() const 396*cdf0e10cSrcweir { 397*cdf0e10cSrcweir return maRequired.getExpression(); 398*cdf0e10cSrcweir } 399*cdf0e10cSrcweir 400*cdf0e10cSrcweir void Binding::setRequiredExpression( const OUString& sRequired ) 401*cdf0e10cSrcweir { 402*cdf0e10cSrcweir maRequired.setExpression( sRequired ); 403*cdf0e10cSrcweir bindingModified(); 404*cdf0e10cSrcweir } 405*cdf0e10cSrcweir 406*cdf0e10cSrcweir OUString Binding::getConstraintExpression() const 407*cdf0e10cSrcweir { 408*cdf0e10cSrcweir return maConstraint.getExpression(); 409*cdf0e10cSrcweir } 410*cdf0e10cSrcweir 411*cdf0e10cSrcweir void Binding::setConstraintExpression( const OUString& sConstraint ) 412*cdf0e10cSrcweir { 413*cdf0e10cSrcweir maConstraint.setExpression( sConstraint ); 414*cdf0e10cSrcweir msExplainConstraint = getResource( RID_STR_XFORMS_INVALID_CONSTRAINT, 415*cdf0e10cSrcweir sConstraint ); 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir // TODO: This should only re-evaluate the constraint, and notify 418*cdf0e10cSrcweir // the validity constraint listeners; instead we currently pretend 419*cdf0e10cSrcweir // the entire binding was notified, which does a little too much. 420*cdf0e10cSrcweir bindingModified(); 421*cdf0e10cSrcweir } 422*cdf0e10cSrcweir 423*cdf0e10cSrcweir OUString Binding::getCalculateExpression() const 424*cdf0e10cSrcweir { 425*cdf0e10cSrcweir return maCalculate.getExpression(); 426*cdf0e10cSrcweir } 427*cdf0e10cSrcweir 428*cdf0e10cSrcweir void Binding::setCalculateExpression( const OUString& sCalculate ) 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir maCalculate.setExpression( sCalculate ); 431*cdf0e10cSrcweir bindingModified(); 432*cdf0e10cSrcweir } 433*cdf0e10cSrcweir 434*cdf0e10cSrcweir OUString Binding::getType() const 435*cdf0e10cSrcweir { 436*cdf0e10cSrcweir return msTypeName; 437*cdf0e10cSrcweir } 438*cdf0e10cSrcweir 439*cdf0e10cSrcweir void Binding::setType( const OUString& sTypeName ) 440*cdf0e10cSrcweir { 441*cdf0e10cSrcweir msTypeName = sTypeName; 442*cdf0e10cSrcweir bindingModified(); 443*cdf0e10cSrcweir } 444*cdf0e10cSrcweir 445*cdf0e10cSrcweir Binding::XNameContainer_t Binding::getBindingNamespaces() const 446*cdf0e10cSrcweir { 447*cdf0e10cSrcweir // return _getNamespaces(); 448*cdf0e10cSrcweir return mxNamespaces; 449*cdf0e10cSrcweir } 450*cdf0e10cSrcweir 451*cdf0e10cSrcweir void Binding::setBindingNamespaces( const XNameContainer_t& rNamespaces ) 452*cdf0e10cSrcweir { 453*cdf0e10cSrcweir _setNamespaces( rNamespaces, true ); 454*cdf0e10cSrcweir } 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir Binding::XNameContainer_t Binding::getModelNamespaces() const 457*cdf0e10cSrcweir { 458*cdf0e10cSrcweir return _getNamespaces(); 459*cdf0e10cSrcweir } 460*cdf0e10cSrcweir 461*cdf0e10cSrcweir void Binding::setModelNamespaces( const XNameContainer_t& rNamespaces ) 462*cdf0e10cSrcweir { 463*cdf0e10cSrcweir _setNamespaces( rNamespaces, false ); 464*cdf0e10cSrcweir } 465*cdf0e10cSrcweir 466*cdf0e10cSrcweir bool Binding::getReadOnly() const 467*cdf0e10cSrcweir { 468*cdf0e10cSrcweir return maMIP.isReadonly(); 469*cdf0e10cSrcweir } 470*cdf0e10cSrcweir 471*cdf0e10cSrcweir bool Binding::getRelevant() const 472*cdf0e10cSrcweir { 473*cdf0e10cSrcweir return maMIP.isRelevant(); 474*cdf0e10cSrcweir } 475*cdf0e10cSrcweir 476*cdf0e10cSrcweir bool Binding::getExternalData() const 477*cdf0e10cSrcweir { 478*cdf0e10cSrcweir bool bExternalData = true; 479*cdf0e10cSrcweir if ( !mxModel.is() ) 480*cdf0e10cSrcweir return bExternalData; 481*cdf0e10cSrcweir 482*cdf0e10cSrcweir try 483*cdf0e10cSrcweir { 484*cdf0e10cSrcweir Reference< XPropertySet > xModelProps( mxModel, UNO_QUERY_THROW ); 485*cdf0e10cSrcweir OSL_VERIFY( 486*cdf0e10cSrcweir xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) ) ) >>= bExternalData ); 487*cdf0e10cSrcweir } 488*cdf0e10cSrcweir catch( const Exception& ) 489*cdf0e10cSrcweir { 490*cdf0e10cSrcweir DBG_UNHANDLED_EXCEPTION(); 491*cdf0e10cSrcweir } 492*cdf0e10cSrcweir return bExternalData; 493*cdf0e10cSrcweir } 494*cdf0e10cSrcweir 495*cdf0e10cSrcweir 496*cdf0e10cSrcweir void Binding::checkLive() 497*cdf0e10cSrcweir throw( RuntimeException ) 498*cdf0e10cSrcweir { 499*cdf0e10cSrcweir if( ! isLive() ) 500*cdf0e10cSrcweir throw RuntimeException( EXCEPT("Binding not initialized") ); 501*cdf0e10cSrcweir } 502*cdf0e10cSrcweir 503*cdf0e10cSrcweir void Binding::checkModel() 504*cdf0e10cSrcweir throw( RuntimeException ) 505*cdf0e10cSrcweir { 506*cdf0e10cSrcweir if( ! mxModel.is() ) 507*cdf0e10cSrcweir throw RuntimeException( EXCEPT("Binding has no Model") ); 508*cdf0e10cSrcweir } 509*cdf0e10cSrcweir 510*cdf0e10cSrcweir bool Binding::isLive() const 511*cdf0e10cSrcweir { 512*cdf0e10cSrcweir const Model* pModel = getModelImpl(); 513*cdf0e10cSrcweir return ( pModel != NULL ) ? pModel->isInitialized() : false; 514*cdf0e10cSrcweir } 515*cdf0e10cSrcweir 516*cdf0e10cSrcweir Model* Binding::getModelImpl() const 517*cdf0e10cSrcweir { 518*cdf0e10cSrcweir return getModelImpl( mxModel ); 519*cdf0e10cSrcweir } 520*cdf0e10cSrcweir 521*cdf0e10cSrcweir Model* Binding::getModelImpl( const Model_t& xModel ) const 522*cdf0e10cSrcweir { 523*cdf0e10cSrcweir Reference<XUnoTunnel> xTunnel( xModel, UNO_QUERY ); 524*cdf0e10cSrcweir Model* pModel = xTunnel.is() 525*cdf0e10cSrcweir ? reinterpret_cast<Model*>( 526*cdf0e10cSrcweir xTunnel->getSomething( Model::getUnoTunnelID() ) ) 527*cdf0e10cSrcweir : NULL; 528*cdf0e10cSrcweir return pModel; 529*cdf0e10cSrcweir } 530*cdf0e10cSrcweir 531*cdf0e10cSrcweir void lcl_addListenerToNode( Reference<XNode> xNode, 532*cdf0e10cSrcweir Reference<XEventListener> xListener ) 533*cdf0e10cSrcweir { 534*cdf0e10cSrcweir Reference<XEventTarget> xTarget( xNode, UNO_QUERY ); 535*cdf0e10cSrcweir if( xTarget.is() ) 536*cdf0e10cSrcweir { 537*cdf0e10cSrcweir xTarget->addEventListener( OUSTRING("DOMCharacterDataModified"), 538*cdf0e10cSrcweir xListener, false ); 539*cdf0e10cSrcweir xTarget->addEventListener( OUSTRING("DOMCharacterDataModified"), 540*cdf0e10cSrcweir xListener, true ); 541*cdf0e10cSrcweir xTarget->addEventListener( OUSTRING("DOMAttrModified"), 542*cdf0e10cSrcweir xListener, false ); 543*cdf0e10cSrcweir xTarget->addEventListener( OUSTRING("DOMAttrModified"), 544*cdf0e10cSrcweir xListener, true ); 545*cdf0e10cSrcweir xTarget->addEventListener( OUSTRING("DOMAttrModified"), 546*cdf0e10cSrcweir xListener, true ); 547*cdf0e10cSrcweir xTarget->addEventListener( OUSTRING("xforms-generic"), 548*cdf0e10cSrcweir xListener, true ); 549*cdf0e10cSrcweir } 550*cdf0e10cSrcweir } 551*cdf0e10cSrcweir 552*cdf0e10cSrcweir void lcl_removeListenerFromNode( Reference<XNode> xNode, 553*cdf0e10cSrcweir Reference<XEventListener> xListener ) 554*cdf0e10cSrcweir { 555*cdf0e10cSrcweir Reference<XEventTarget> xTarget( xNode, UNO_QUERY ); 556*cdf0e10cSrcweir if( xTarget.is() ) 557*cdf0e10cSrcweir { 558*cdf0e10cSrcweir xTarget->removeEventListener( OUSTRING("DOMCharacterDataModified"), 559*cdf0e10cSrcweir xListener, false ); 560*cdf0e10cSrcweir xTarget->removeEventListener( OUSTRING("DOMCharacterDataModified"), 561*cdf0e10cSrcweir xListener, true ); 562*cdf0e10cSrcweir xTarget->removeEventListener( OUSTRING("DOMAttrModified"), 563*cdf0e10cSrcweir xListener, false ); 564*cdf0e10cSrcweir xTarget->removeEventListener( OUSTRING("DOMAttrModified"), 565*cdf0e10cSrcweir xListener, true ); 566*cdf0e10cSrcweir xTarget->removeEventListener( OUSTRING("xforms-generic"), 567*cdf0e10cSrcweir xListener, true ); 568*cdf0e10cSrcweir } 569*cdf0e10cSrcweir } 570*cdf0e10cSrcweir 571*cdf0e10cSrcweir ::std::vector<EvaluationContext> Binding::_getMIPEvaluationContexts() const 572*cdf0e10cSrcweir { 573*cdf0e10cSrcweir OSL_ENSURE( getModelImpl() != NULL, "need model impl" ); 574*cdf0e10cSrcweir 575*cdf0e10cSrcweir // iterate over nodes of bind expression and create 576*cdf0e10cSrcweir // EvaluationContext for each 577*cdf0e10cSrcweir PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList(); 578*cdf0e10cSrcweir ::std::vector<EvaluationContext> aVector; 579*cdf0e10cSrcweir sal_Int32 nCount = 0; // count nodes for context position 580*cdf0e10cSrcweir for( PathExpression::NodeVector_t::iterator aIter = aNodes.begin(); 581*cdf0e10cSrcweir aIter != aNodes.end(); 582*cdf0e10cSrcweir aIter++, nCount++ ) 583*cdf0e10cSrcweir { 584*cdf0e10cSrcweir OSL_ENSURE( aIter->is(), "no node?" ); 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir // create proper evaluation context for this MIP 587*cdf0e10cSrcweir aVector.push_back( EvaluationContext( *aIter, getModel(), 588*cdf0e10cSrcweir getBindingNamespaces(), 589*cdf0e10cSrcweir nCount, aNodes.size() ) ); 590*cdf0e10cSrcweir } 591*cdf0e10cSrcweir return aVector; 592*cdf0e10cSrcweir } 593*cdf0e10cSrcweir 594*cdf0e10cSrcweir void Binding::bind( bool bForceRebind ) 595*cdf0e10cSrcweir { 596*cdf0e10cSrcweir checkModel(); 597*cdf0e10cSrcweir 598*cdf0e10cSrcweir // bind() will evaluate this binding as follows: 599*cdf0e10cSrcweir // 1) evaluate the binding expression 600*cdf0e10cSrcweir // 1b) if necessary, create node according to 'lazy author' rules 601*cdf0e10cSrcweir // 2) register suitable listeners on the instance (and remove old ones) 602*cdf0e10cSrcweir // 3) remove old MIPs defined by this binding 603*cdf0e10cSrcweir // 4) for every node in the binding nodeset do: 604*cdf0e10cSrcweir // 1) create proper evaluation context for this MIP 605*cdf0e10cSrcweir // 2) evaluate calculate expression (and push value into instance) 606*cdf0e10cSrcweir // 3) evaluate remaining MIPs 607*cdf0e10cSrcweir // 4) evaluate the locally defined MIPs, and push them to the model 608*cdf0e10cSrcweir 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir // 1) evaluate the binding expression 611*cdf0e10cSrcweir EvaluationContext aContext = getEvaluationContext(); 612*cdf0e10cSrcweir maBindingExpression.evaluate( aContext ); 613*cdf0e10cSrcweir if( ! maBindingExpression.getNode().is() ) 614*cdf0e10cSrcweir { 615*cdf0e10cSrcweir // 1b) create node (if valid element name) 616*cdf0e10cSrcweir if( isValidQName( maBindingExpression.getExpression(), 617*cdf0e10cSrcweir aContext.mxNamespaces ) ) 618*cdf0e10cSrcweir { 619*cdf0e10cSrcweir aContext.mxContextNode->appendChild( 620*cdf0e10cSrcweir Reference<XNode>( 621*cdf0e10cSrcweir aContext.mxContextNode->getOwnerDocument()->createElement( 622*cdf0e10cSrcweir maBindingExpression.getExpression() ), 623*cdf0e10cSrcweir UNO_QUERY ) ); 624*cdf0e10cSrcweir maBindingExpression.evaluate( aContext ); 625*cdf0e10cSrcweir OSL_ENSURE( maBindingExpression.getNode().is(), 626*cdf0e10cSrcweir "we should bind to the newly inserted node!" ); 627*cdf0e10cSrcweir } 628*cdf0e10cSrcweir } 629*cdf0e10cSrcweir PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList(); 630*cdf0e10cSrcweir 631*cdf0e10cSrcweir // 2) register suitable listeners on the instance (and remove old ones) 632*cdf0e10cSrcweir if( maEventNodes.empty() || bForceRebind ) 633*cdf0e10cSrcweir { 634*cdf0e10cSrcweir for( XNodes_t::iterator aIter = maEventNodes.begin(); 635*cdf0e10cSrcweir aIter != maEventNodes.end(); 636*cdf0e10cSrcweir aIter ++ ) 637*cdf0e10cSrcweir lcl_removeListenerFromNode( *aIter, this ); 638*cdf0e10cSrcweir maEventNodes.clear(); 639*cdf0e10cSrcweir if( isSimpleBinding() ) 640*cdf0e10cSrcweir for( PathExpression::NodeVector_t::iterator aIter = aNodes.begin(); 641*cdf0e10cSrcweir aIter != aNodes.end(); 642*cdf0e10cSrcweir aIter++ ) 643*cdf0e10cSrcweir maEventNodes.push_back( *aIter ); 644*cdf0e10cSrcweir else 645*cdf0e10cSrcweir maEventNodes.push_back( 646*cdf0e10cSrcweir Reference<XNode>( aContext.mxContextNode->getOwnerDocument(), 647*cdf0e10cSrcweir UNO_QUERY_THROW ) ); 648*cdf0e10cSrcweir for( PathExpression::NodeVector_t::iterator aIter2 = maEventNodes.begin(); 649*cdf0e10cSrcweir aIter2 != maEventNodes.end(); 650*cdf0e10cSrcweir aIter2 ++ ) 651*cdf0e10cSrcweir lcl_addListenerToNode( *aIter2, this ); 652*cdf0e10cSrcweir } 653*cdf0e10cSrcweir 654*cdf0e10cSrcweir // 3) remove old MIPs defined by this binding 655*cdf0e10cSrcweir Model* pModel = getModelImpl(); 656*cdf0e10cSrcweir OSL_ENSURE( pModel != NULL, "need model" ); 657*cdf0e10cSrcweir pModel->removeMIPs( this ); 658*cdf0e10cSrcweir 659*cdf0e10cSrcweir // 4) calculate all MIPs 660*cdf0e10cSrcweir ::std::vector<EvaluationContext> aMIPContexts = _getMIPEvaluationContexts(); 661*cdf0e10cSrcweir for( ::std::vector<EvaluationContext>::iterator aIter = aMIPContexts.begin(); 662*cdf0e10cSrcweir aIter != aMIPContexts.end(); 663*cdf0e10cSrcweir aIter++ ) 664*cdf0e10cSrcweir { 665*cdf0e10cSrcweir EvaluationContext& rContext = *aIter; 666*cdf0e10cSrcweir 667*cdf0e10cSrcweir // evaluate calculate expression (and push value into instance) 668*cdf0e10cSrcweir // (prevent recursion using mbInCalculate 669*cdf0e10cSrcweir if( ! maCalculate.isEmptyExpression() ) 670*cdf0e10cSrcweir { 671*cdf0e10cSrcweir if( ! mbInCalculate ) 672*cdf0e10cSrcweir { 673*cdf0e10cSrcweir mbInCalculate = true; 674*cdf0e10cSrcweir maCalculate.evaluate( rContext ); 675*cdf0e10cSrcweir pModel->setSimpleContent( rContext.mxContextNode, 676*cdf0e10cSrcweir maCalculate.getString() ); 677*cdf0e10cSrcweir mbInCalculate = false; 678*cdf0e10cSrcweir } 679*cdf0e10cSrcweir } 680*cdf0e10cSrcweir 681*cdf0e10cSrcweir // now evaluate remaining MIPs in the apropriate context 682*cdf0e10cSrcweir maReadonly.evaluate( rContext ); 683*cdf0e10cSrcweir maRelevant.evaluate( rContext ); 684*cdf0e10cSrcweir maRequired.evaluate( rContext ); 685*cdf0e10cSrcweir maConstraint.evaluate( rContext ); 686*cdf0e10cSrcweir // type is static; does not need updating 687*cdf0e10cSrcweir 688*cdf0e10cSrcweir // evaluate the locally defined MIPs, and push them to the model 689*cdf0e10cSrcweir pModel->addMIP( this, rContext.mxContextNode, getLocalMIP() ); 690*cdf0e10cSrcweir } 691*cdf0e10cSrcweir } 692*cdf0e10cSrcweir 693*cdf0e10cSrcweir 694*cdf0e10cSrcweir // helper for Binding::valueModified 695*cdf0e10cSrcweir void lcl_modified( const Binding::XModifyListener_t xListener, 696*cdf0e10cSrcweir const Reference<XInterface> xSource ) 697*cdf0e10cSrcweir { 698*cdf0e10cSrcweir OSL_ENSURE( xListener.is(), "no listener?" ); 699*cdf0e10cSrcweir xListener->modified( EventObject( xSource ) ); 700*cdf0e10cSrcweir } 701*cdf0e10cSrcweir 702*cdf0e10cSrcweir // helper for Binding::valueModified 703*cdf0e10cSrcweir void lcl_listentry( const Binding::XListEntryListener_t xListener, 704*cdf0e10cSrcweir const Reference<XInterface> xSource ) 705*cdf0e10cSrcweir { 706*cdf0e10cSrcweir OSL_ENSURE( xListener.is(), "no listener?" ); 707*cdf0e10cSrcweir // TODO: send fine granular events 708*cdf0e10cSrcweir xListener->allEntriesChanged( EventObject( xSource ) ); 709*cdf0e10cSrcweir } 710*cdf0e10cSrcweir 711*cdf0e10cSrcweir // helper for Binding::valueModified 712*cdf0e10cSrcweir void lcl_validate( const Binding::XValidityConstraintListener_t xListener, 713*cdf0e10cSrcweir const Reference<XInterface> xSource ) 714*cdf0e10cSrcweir { 715*cdf0e10cSrcweir OSL_ENSURE( xListener.is(), "no listener?" ); 716*cdf0e10cSrcweir xListener->validityConstraintChanged( EventObject( xSource ) ); 717*cdf0e10cSrcweir } 718*cdf0e10cSrcweir 719*cdf0e10cSrcweir 720*cdf0e10cSrcweir void Binding::valueModified() 721*cdf0e10cSrcweir { 722*cdf0e10cSrcweir // defer notifications, if so desired 723*cdf0e10cSrcweir if( mnDeferModifyNotifications > 0 ) 724*cdf0e10cSrcweir { 725*cdf0e10cSrcweir mbValueModified = true; 726*cdf0e10cSrcweir return; 727*cdf0e10cSrcweir } 728*cdf0e10cSrcweir mbValueModified = false; 729*cdf0e10cSrcweir 730*cdf0e10cSrcweir // query MIP used by our first node (also note validity) 731*cdf0e10cSrcweir Reference<XNode> xNode = maBindingExpression.getNode(); 732*cdf0e10cSrcweir maMIP = getModelImpl()->queryMIP( xNode ); 733*cdf0e10cSrcweir 734*cdf0e10cSrcweir // distribute MIPs _used_ by this binding 735*cdf0e10cSrcweir if( xNode.is() ) 736*cdf0e10cSrcweir { 737*cdf0e10cSrcweir notifyAndCachePropertyValue( HANDLE_ReadOnly ); 738*cdf0e10cSrcweir notifyAndCachePropertyValue( HANDLE_Relevant ); 739*cdf0e10cSrcweir } 740*cdf0e10cSrcweir 741*cdf0e10cSrcweir // iterate over _value_ listeners and send each a modified signal, 742*cdf0e10cSrcweir // using this object as source (will also update validity, because 743*cdf0e10cSrcweir // control will query once the value has changed) 744*cdf0e10cSrcweir Reference<XInterface> xSource = static_cast<XPropertySet*>( this ); 745*cdf0e10cSrcweir ::std::for_each( maModifyListeners.begin(), 746*cdf0e10cSrcweir maModifyListeners.end(), 747*cdf0e10cSrcweir ::std::bind2nd( ::std::ptr_fun( lcl_modified ), xSource ) ); 748*cdf0e10cSrcweir ::std::for_each( maListEntryListeners.begin(), 749*cdf0e10cSrcweir maListEntryListeners.end(), 750*cdf0e10cSrcweir ::std::bind2nd( ::std::ptr_fun( lcl_listentry ), xSource ) ); 751*cdf0e10cSrcweir ::std::for_each( maValidityListeners.begin(), 752*cdf0e10cSrcweir maValidityListeners.end(), 753*cdf0e10cSrcweir ::std::bind2nd( ::std::ptr_fun( lcl_validate ), xSource ) ); 754*cdf0e10cSrcweir 755*cdf0e10cSrcweir // now distribute MIPs to childs 756*cdf0e10cSrcweir if( xNode.is() ) 757*cdf0e10cSrcweir distributeMIP( xNode->getFirstChild() ); 758*cdf0e10cSrcweir } 759*cdf0e10cSrcweir 760*cdf0e10cSrcweir void Binding::distributeMIP( const XNode_t & rxNode ) { 761*cdf0e10cSrcweir 762*cdf0e10cSrcweir typedef com::sun::star::xforms::XFormsEventConcrete XFormsEvent_t; 763*cdf0e10cSrcweir OUString sEventName( RTL_CONSTASCII_USTRINGPARAM("xforms-generic") ); 764*cdf0e10cSrcweir XFormsEvent_t *pEvent = new XFormsEvent_t; 765*cdf0e10cSrcweir pEvent->initXFormsEvent(sEventName, sal_True, sal_False); 766*cdf0e10cSrcweir Reference<XEvent> xEvent(pEvent); 767*cdf0e10cSrcweir 768*cdf0e10cSrcweir // naive depth-first traversal 769*cdf0e10cSrcweir XNode_t xNode( rxNode ); 770*cdf0e10cSrcweir while(xNode.is()) { 771*cdf0e10cSrcweir 772*cdf0e10cSrcweir // notifications should be triggered at the 773*cdf0e10cSrcweir // leaf nodes first, bubbling upwards the hierarchy. 774*cdf0e10cSrcweir XNode_t child(xNode->getFirstChild()); 775*cdf0e10cSrcweir if(child.is()) 776*cdf0e10cSrcweir distributeMIP(child); 777*cdf0e10cSrcweir 778*cdf0e10cSrcweir // we're standing at a particular node somewhere 779*cdf0e10cSrcweir // below the one which changed a property (MIP). 780*cdf0e10cSrcweir // bindings which are listening at this node will receive 781*cdf0e10cSrcweir // a notification message about what exactly happened. 782*cdf0e10cSrcweir Reference< XEventTarget > target(xNode,UNO_QUERY); 783*cdf0e10cSrcweir target->dispatchEvent(xEvent); 784*cdf0e10cSrcweir 785*cdf0e10cSrcweir xNode = xNode->getNextSibling(); 786*cdf0e10cSrcweir }; 787*cdf0e10cSrcweir } 788*cdf0e10cSrcweir 789*cdf0e10cSrcweir void Binding::bindingModified() 790*cdf0e10cSrcweir { 791*cdf0e10cSrcweir // defer notifications, if so desired 792*cdf0e10cSrcweir if( mnDeferModifyNotifications > 0 ) 793*cdf0e10cSrcweir { 794*cdf0e10cSrcweir mbBindingModified = true; 795*cdf0e10cSrcweir return; 796*cdf0e10cSrcweir } 797*cdf0e10cSrcweir mbBindingModified = false; 798*cdf0e10cSrcweir 799*cdf0e10cSrcweir // rebind (if live); then call valueModified 800*cdf0e10cSrcweir // A binding should be inert until its model is fully constructed. 801*cdf0e10cSrcweir if( isLive() ) 802*cdf0e10cSrcweir { 803*cdf0e10cSrcweir bind( true ); 804*cdf0e10cSrcweir valueModified(); 805*cdf0e10cSrcweir } 806*cdf0e10cSrcweir } 807*cdf0e10cSrcweir 808*cdf0e10cSrcweir 809*cdf0e10cSrcweir MIP Binding::getLocalMIP() const 810*cdf0e10cSrcweir { 811*cdf0e10cSrcweir MIP aMIP; 812*cdf0e10cSrcweir 813*cdf0e10cSrcweir if( maReadonly.hasValue() ) 814*cdf0e10cSrcweir aMIP.setReadonly( maReadonly.getBool( false ) ); 815*cdf0e10cSrcweir if( maRelevant.hasValue() ) 816*cdf0e10cSrcweir aMIP.setRelevant( maRelevant.getBool( true ) ); 817*cdf0e10cSrcweir if( maRequired.hasValue() ) 818*cdf0e10cSrcweir aMIP.setRequired( maRequired.getBool( false ) ); 819*cdf0e10cSrcweir if( maConstraint.hasValue() ) 820*cdf0e10cSrcweir { 821*cdf0e10cSrcweir aMIP.setConstraint( maConstraint.getBool( true ) ); 822*cdf0e10cSrcweir if( ! aMIP.isConstraint() ) 823*cdf0e10cSrcweir aMIP.setConstraintExplanation( msExplainConstraint ); 824*cdf0e10cSrcweir } 825*cdf0e10cSrcweir if( msTypeName.getLength() > 0 ) 826*cdf0e10cSrcweir aMIP.setTypeName( msTypeName ); 827*cdf0e10cSrcweir 828*cdf0e10cSrcweir // calculate: only handle presence of calculate; value set elsewhere 829*cdf0e10cSrcweir aMIP.setHasCalculate( !maCalculate.isEmptyExpression() ); 830*cdf0e10cSrcweir 831*cdf0e10cSrcweir return aMIP; 832*cdf0e10cSrcweir } 833*cdf0e10cSrcweir 834*cdf0e10cSrcweir Binding::XDataType_t Binding::getDataType() 835*cdf0e10cSrcweir { 836*cdf0e10cSrcweir OSL_ENSURE( getModel().is(), "need model" ); 837*cdf0e10cSrcweir OSL_ENSURE( getModel()->getDataTypeRepository().is(), "need types" ); 838*cdf0e10cSrcweir 839*cdf0e10cSrcweir Reference<XDataTypeRepository> xRepository( 840*cdf0e10cSrcweir getModel()->getDataTypeRepository(), UNO_QUERY ); 841*cdf0e10cSrcweir OUString sTypeName = maMIP.getTypeName(); 842*cdf0e10cSrcweir 843*cdf0e10cSrcweir return ( xRepository.is() && xRepository->hasByName( sTypeName ) ) 844*cdf0e10cSrcweir ? Reference<XDataType>( xRepository->getByName( sTypeName ), UNO_QUERY) 845*cdf0e10cSrcweir : Reference<XDataType>( NULL ); 846*cdf0e10cSrcweir } 847*cdf0e10cSrcweir 848*cdf0e10cSrcweir bool Binding::isValid_DataType() 849*cdf0e10cSrcweir { 850*cdf0e10cSrcweir Reference<XDataType> xDataType = getDataType(); 851*cdf0e10cSrcweir return xDataType.is() 852*cdf0e10cSrcweir ? xDataType->validate( maBindingExpression.getString() ) 853*cdf0e10cSrcweir : true; 854*cdf0e10cSrcweir } 855*cdf0e10cSrcweir 856*cdf0e10cSrcweir rtl::OUString Binding::explainInvalid_DataType() 857*cdf0e10cSrcweir { 858*cdf0e10cSrcweir Reference<XDataType> xDataType = getDataType(); 859*cdf0e10cSrcweir return xDataType.is() 860*cdf0e10cSrcweir ? xDataType->explainInvalid( maBindingExpression.getString() ) 861*cdf0e10cSrcweir : OUString(); 862*cdf0e10cSrcweir } 863*cdf0e10cSrcweir 864*cdf0e10cSrcweir void Binding::clear() 865*cdf0e10cSrcweir { 866*cdf0e10cSrcweir // remove MIPs contributed by this binding 867*cdf0e10cSrcweir Model* pModel = getModelImpl(); 868*cdf0e10cSrcweir if( pModel != NULL ) 869*cdf0e10cSrcweir pModel->removeMIPs( this ); 870*cdf0e10cSrcweir 871*cdf0e10cSrcweir // remove all references 872*cdf0e10cSrcweir for( XNodes_t::iterator aIter = maEventNodes.begin(); 873*cdf0e10cSrcweir aIter != maEventNodes.end(); 874*cdf0e10cSrcweir aIter ++ ) 875*cdf0e10cSrcweir lcl_removeListenerFromNode( *aIter, this ); 876*cdf0e10cSrcweir maEventNodes.clear(); 877*cdf0e10cSrcweir 878*cdf0e10cSrcweir // clear expressions 879*cdf0e10cSrcweir maBindingExpression.clear(); 880*cdf0e10cSrcweir maReadonly.clear(); 881*cdf0e10cSrcweir maRelevant.clear(); 882*cdf0e10cSrcweir maRequired.clear(); 883*cdf0e10cSrcweir maConstraint.clear(); 884*cdf0e10cSrcweir maCalculate.clear(); 885*cdf0e10cSrcweir 886*cdf0e10cSrcweir // TODO: what about our listeners? 887*cdf0e10cSrcweir } 888*cdf0e10cSrcweir 889*cdf0e10cSrcweir 890*cdf0e10cSrcweir void lcl_removeOtherNamespaces( const Binding::XNameContainer_t& xFrom, 891*cdf0e10cSrcweir Binding::XNameContainer_t& xTo ) 892*cdf0e10cSrcweir { 893*cdf0e10cSrcweir OSL_ENSURE( xFrom.is(), "no source" ); 894*cdf0e10cSrcweir OSL_ENSURE( xTo.is(), "no target" ); 895*cdf0e10cSrcweir 896*cdf0e10cSrcweir // iterate over name in source 897*cdf0e10cSrcweir Sequence<OUString> aNames = xTo->getElementNames(); 898*cdf0e10cSrcweir sal_Int32 nNames = aNames.getLength(); 899*cdf0e10cSrcweir const OUString* pNames = aNames.getConstArray(); 900*cdf0e10cSrcweir for( sal_Int32 i = 0; i < nNames; i++ ) 901*cdf0e10cSrcweir { 902*cdf0e10cSrcweir const OUString& rName = pNames[i]; 903*cdf0e10cSrcweir 904*cdf0e10cSrcweir if( ! xFrom->hasByName( rName ) ) 905*cdf0e10cSrcweir xTo->removeByName( rName ); 906*cdf0e10cSrcweir } 907*cdf0e10cSrcweir } 908*cdf0e10cSrcweir 909*cdf0e10cSrcweir /** copy namespaces from one namespace container into another 910*cdf0e10cSrcweir * @param bOverwrite true: overwrite namespaces in target 911*cdf0e10cSrcweir * false: do not overwrite namespaces in target 912*cdf0e10cSrcweir * @param bMove true: move namespaces (i.e., delete in source) 913*cdf0e10cSrcweir * false: copy namespaces (do not modify source) 914*cdf0e10cSrcweir * @param bFromSource true: use elements from source 915*cdf0e10cSrcweir * false: use only elements from target 916*cdf0e10cSrcweir */ 917*cdf0e10cSrcweir void lcl_copyNamespaces( const Binding::XNameContainer_t& xFrom, 918*cdf0e10cSrcweir Binding::XNameContainer_t& xTo, 919*cdf0e10cSrcweir bool bOverwrite ) 920*cdf0e10cSrcweir { 921*cdf0e10cSrcweir OSL_ENSURE( xFrom.is(), "no source" ); 922*cdf0e10cSrcweir OSL_ENSURE( xTo.is(), "no target" ); 923*cdf0e10cSrcweir 924*cdf0e10cSrcweir // iterate over name in source 925*cdf0e10cSrcweir Sequence<OUString> aNames = xFrom->getElementNames(); 926*cdf0e10cSrcweir sal_Int32 nNames = aNames.getLength(); 927*cdf0e10cSrcweir const OUString* pNames = aNames.getConstArray(); 928*cdf0e10cSrcweir for( sal_Int32 i = 0; i < nNames; i++ ) 929*cdf0e10cSrcweir { 930*cdf0e10cSrcweir const OUString& rName = pNames[i]; 931*cdf0e10cSrcweir 932*cdf0e10cSrcweir // determine whether to copy the value, and whether to delete 933*cdf0e10cSrcweir // it in the source: 934*cdf0e10cSrcweir 935*cdf0e10cSrcweir bool bInTarget = xTo->hasByName( rName ); 936*cdf0e10cSrcweir 937*cdf0e10cSrcweir // we copy: if property is in target, and 938*cdf0e10cSrcweir // if bOverwrite is set, or when the namespace prefix is free 939*cdf0e10cSrcweir bool bCopy = bOverwrite || ! bInTarget; 940*cdf0e10cSrcweir 941*cdf0e10cSrcweir // and now... ACTION! 942*cdf0e10cSrcweir if( bCopy ) 943*cdf0e10cSrcweir { 944*cdf0e10cSrcweir if( bInTarget ) 945*cdf0e10cSrcweir xTo->replaceByName( rName, xFrom->getByName( rName ) ); 946*cdf0e10cSrcweir else 947*cdf0e10cSrcweir xTo->insertByName( rName, xFrom->getByName( rName ) ); 948*cdf0e10cSrcweir } 949*cdf0e10cSrcweir } 950*cdf0e10cSrcweir } 951*cdf0e10cSrcweir 952*cdf0e10cSrcweir // implement get*Namespaces() 953*cdf0e10cSrcweir // (identical for both variants) 954*cdf0e10cSrcweir Binding::XNameContainer_t Binding::_getNamespaces() const 955*cdf0e10cSrcweir { 956*cdf0e10cSrcweir XNameContainer_t xNamespaces = new NameContainer<OUString>(); 957*cdf0e10cSrcweir lcl_copyNamespaces( mxNamespaces, xNamespaces, true ); 958*cdf0e10cSrcweir 959*cdf0e10cSrcweir // merge model's with binding's own namespaces 960*cdf0e10cSrcweir Model* pModel = getModelImpl(); 961*cdf0e10cSrcweir if( pModel != NULL ) 962*cdf0e10cSrcweir lcl_copyNamespaces( pModel->getNamespaces(), xNamespaces, false ); 963*cdf0e10cSrcweir 964*cdf0e10cSrcweir return xNamespaces; 965*cdf0e10cSrcweir } 966*cdf0e10cSrcweir 967*cdf0e10cSrcweir // implement set*Namespaces() 968*cdf0e10cSrcweir // bBinding = true: setBindingNamespaces, otherwise: setModelNamespaces 969*cdf0e10cSrcweir void Binding::_setNamespaces( const XNameContainer_t& rNamespaces, 970*cdf0e10cSrcweir bool bBinding ) 971*cdf0e10cSrcweir { 972*cdf0e10cSrcweir Model* pModel = getModelImpl(); 973*cdf0e10cSrcweir XNameContainer_t xModelNamespaces = ( pModel != NULL ) 974*cdf0e10cSrcweir ? pModel->getNamespaces() 975*cdf0e10cSrcweir : NULL; 976*cdf0e10cSrcweir OSL_ENSURE( ( pModel != NULL ) == xModelNamespaces.is(), "no model nmsp?"); 977*cdf0e10cSrcweir 978*cdf0e10cSrcweir // remove deleted namespaces 979*cdf0e10cSrcweir lcl_removeOtherNamespaces( rNamespaces, mxNamespaces ); 980*cdf0e10cSrcweir if( !bBinding && xModelNamespaces.is() ) 981*cdf0e10cSrcweir lcl_removeOtherNamespaces( rNamespaces, xModelNamespaces ); 982*cdf0e10cSrcweir 983*cdf0e10cSrcweir // copy namespaces as appropriate 984*cdf0e10cSrcweir Sequence<OUString> aNames = rNamespaces->getElementNames(); 985*cdf0e10cSrcweir sal_Int32 nNames = aNames.getLength(); 986*cdf0e10cSrcweir const OUString* pNames = aNames.getConstArray(); 987*cdf0e10cSrcweir for( sal_Int32 i = 0; i < nNames; i++ ) 988*cdf0e10cSrcweir { 989*cdf0e10cSrcweir const OUString& rName = pNames[i]; 990*cdf0e10cSrcweir Any aValue = rNamespaces->getByName( rName ); 991*cdf0e10cSrcweir 992*cdf0e10cSrcweir // determine whether the namespace should go into model's or 993*cdf0e10cSrcweir // into binding's namespaces 994*cdf0e10cSrcweir bool bLocal = 995*cdf0e10cSrcweir ! xModelNamespaces.is() 996*cdf0e10cSrcweir || mxNamespaces->hasByName( rName ) 997*cdf0e10cSrcweir || ( bBinding 998*cdf0e10cSrcweir && xModelNamespaces.is() 999*cdf0e10cSrcweir && xModelNamespaces->hasByName( rName ) ); 1000*cdf0e10cSrcweir 1001*cdf0e10cSrcweir // write namespace into the appropriate namespace container 1002*cdf0e10cSrcweir XNameContainer_t& rWhich = bLocal ? mxNamespaces : xModelNamespaces; 1003*cdf0e10cSrcweir OSL_ENSURE( rWhich.is(), "whoops" ); 1004*cdf0e10cSrcweir if( rWhich->hasByName( rName ) ) 1005*cdf0e10cSrcweir rWhich->replaceByName( rName, aValue ); 1006*cdf0e10cSrcweir else 1007*cdf0e10cSrcweir rWhich->insertByName( rName, aValue ); 1008*cdf0e10cSrcweir 1009*cdf0e10cSrcweir // always 'promote' namespaces from binding to model, if equal 1010*cdf0e10cSrcweir if( xModelNamespaces.is() 1011*cdf0e10cSrcweir && xModelNamespaces->hasByName( rName ) 1012*cdf0e10cSrcweir && mxNamespaces->hasByName( rName ) 1013*cdf0e10cSrcweir && xModelNamespaces->getByName( rName ) == mxNamespaces->getByName( rName ) ) 1014*cdf0e10cSrcweir { 1015*cdf0e10cSrcweir mxNamespaces->removeByName( rName ); 1016*cdf0e10cSrcweir } 1017*cdf0e10cSrcweir } 1018*cdf0e10cSrcweir 1019*cdf0e10cSrcweir // ... done. But we modified the binding! 1020*cdf0e10cSrcweir bindingModified(); 1021*cdf0e10cSrcweir } 1022*cdf0e10cSrcweir 1023*cdf0e10cSrcweir void Binding::_checkBindingID() 1024*cdf0e10cSrcweir { 1025*cdf0e10cSrcweir if( getModel().is() ) 1026*cdf0e10cSrcweir { 1027*cdf0e10cSrcweir Reference<XNameAccess> xBindings( getModel()->getBindings(), UNO_QUERY_THROW ); 1028*cdf0e10cSrcweir if( msBindingID.getLength() == 0 ) 1029*cdf0e10cSrcweir { 1030*cdf0e10cSrcweir // no binding ID? then make one up! 1031*cdf0e10cSrcweir OUString sIDPrefix = getResource( RID_STR_XFORMS_BINDING_UI_NAME ); 1032*cdf0e10cSrcweir sIDPrefix += String::CreateFromAscii( " " ); 1033*cdf0e10cSrcweir sal_Int32 nNumber = 0; 1034*cdf0e10cSrcweir OUString sName; 1035*cdf0e10cSrcweir do 1036*cdf0e10cSrcweir { 1037*cdf0e10cSrcweir nNumber++; 1038*cdf0e10cSrcweir sName = sIDPrefix + OUString::valueOf( nNumber ); 1039*cdf0e10cSrcweir } 1040*cdf0e10cSrcweir while( xBindings->hasByName( sName ) ); 1041*cdf0e10cSrcweir setBindingID( sName ); 1042*cdf0e10cSrcweir } 1043*cdf0e10cSrcweir } 1044*cdf0e10cSrcweir } 1045*cdf0e10cSrcweir 1046*cdf0e10cSrcweir 1047*cdf0e10cSrcweir 1048*cdf0e10cSrcweir 1049*cdf0e10cSrcweir // 1050*cdf0e10cSrcweir // XValueBinding 1051*cdf0e10cSrcweir // 1052*cdf0e10cSrcweir 1053*cdf0e10cSrcweir Binding::Sequence_Type_t Binding::getSupportedValueTypes() 1054*cdf0e10cSrcweir throw( RuntimeException ) 1055*cdf0e10cSrcweir { 1056*cdf0e10cSrcweir return Convert::get().getTypes(); 1057*cdf0e10cSrcweir } 1058*cdf0e10cSrcweir 1059*cdf0e10cSrcweir sal_Bool Binding::supportsType( const Type_t& rType ) 1060*cdf0e10cSrcweir throw( RuntimeException ) 1061*cdf0e10cSrcweir { 1062*cdf0e10cSrcweir return Convert::get().hasType( rType ); 1063*cdf0e10cSrcweir } 1064*cdf0e10cSrcweir 1065*cdf0e10cSrcweir Binding::Any_t Binding::getValue( const Type_t& rType ) 1066*cdf0e10cSrcweir throw( IncompatibleTypesException, 1067*cdf0e10cSrcweir RuntimeException ) 1068*cdf0e10cSrcweir { 1069*cdf0e10cSrcweir // first, check for model 1070*cdf0e10cSrcweir checkLive(); 1071*cdf0e10cSrcweir 1072*cdf0e10cSrcweir // second, check for type 1073*cdf0e10cSrcweir if( ! supportsType( rType ) ) 1074*cdf0e10cSrcweir throw IncompatibleTypesException( EXCEPT( "type unsupported" ) ); 1075*cdf0e10cSrcweir 1076*cdf0e10cSrcweir // return string value (if present; else return empty Any) 1077*cdf0e10cSrcweir Binding::Any_t result = Any(); 1078*cdf0e10cSrcweir if(maBindingExpression.hasValue()) { 1079*cdf0e10cSrcweir rtl::OUString pathExpr(maBindingExpression.getString()); 1080*cdf0e10cSrcweir Convert &rConvert = Convert::get(); 1081*cdf0e10cSrcweir result = rConvert.toAny(pathExpr,rType); 1082*cdf0e10cSrcweir } 1083*cdf0e10cSrcweir 1084*cdf0e10cSrcweir // return maBindingExpression.hasValue() 1085*cdf0e10cSrcweir // ? Convert::get().toAny( maBindingExpression.getString(), rType ) 1086*cdf0e10cSrcweir // : Any(); 1087*cdf0e10cSrcweir 1088*cdf0e10cSrcweir return result; 1089*cdf0e10cSrcweir } 1090*cdf0e10cSrcweir 1091*cdf0e10cSrcweir void Binding::setValue( const Any_t& aValue ) 1092*cdf0e10cSrcweir throw( IncompatibleTypesException, 1093*cdf0e10cSrcweir InvalidBindingStateException, 1094*cdf0e10cSrcweir NoSupportException, 1095*cdf0e10cSrcweir RuntimeException ) 1096*cdf0e10cSrcweir { 1097*cdf0e10cSrcweir // first, check for model 1098*cdf0e10cSrcweir checkLive(); 1099*cdf0e10cSrcweir 1100*cdf0e10cSrcweir // check for supported type 1101*cdf0e10cSrcweir if( ! supportsType( aValue.getValueType() ) ) 1102*cdf0e10cSrcweir throw IncompatibleTypesException( EXCEPT( "type unsupported" ) ); 1103*cdf0e10cSrcweir 1104*cdf0e10cSrcweir if( maBindingExpression.hasValue() ) 1105*cdf0e10cSrcweir { 1106*cdf0e10cSrcweir Binding::XNode_t xNode = maBindingExpression.getNode(); 1107*cdf0e10cSrcweir if( xNode.is() ) 1108*cdf0e10cSrcweir { 1109*cdf0e10cSrcweir OUString sValue = Convert::get().toXSD( aValue ); 1110*cdf0e10cSrcweir bool bSuccess = getModelImpl()->setSimpleContent( xNode, sValue ); 1111*cdf0e10cSrcweir if( ! bSuccess ) 1112*cdf0e10cSrcweir throw InvalidBindingStateException( EXCEPT( "can't set value" ) ); 1113*cdf0e10cSrcweir } 1114*cdf0e10cSrcweir else 1115*cdf0e10cSrcweir throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) ); 1116*cdf0e10cSrcweir } 1117*cdf0e10cSrcweir else 1118*cdf0e10cSrcweir throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) ); 1119*cdf0e10cSrcweir } 1120*cdf0e10cSrcweir 1121*cdf0e10cSrcweir 1122*cdf0e10cSrcweir // 1123*cdf0e10cSrcweir // XListEntry Source 1124*cdf0e10cSrcweir // 1125*cdf0e10cSrcweir 1126*cdf0e10cSrcweir sal_Int32 Binding::getListEntryCount() 1127*cdf0e10cSrcweir throw( RuntimeException ) 1128*cdf0e10cSrcweir { 1129*cdf0e10cSrcweir // first, check for model 1130*cdf0e10cSrcweir checkLive(); 1131*cdf0e10cSrcweir 1132*cdf0e10cSrcweir // return size of node list 1133*cdf0e10cSrcweir return maBindingExpression.getNodeList().size(); 1134*cdf0e10cSrcweir } 1135*cdf0e10cSrcweir 1136*cdf0e10cSrcweir void lcl_getString( const Reference<XNode>& xNode, OUStringBuffer& rBuffer ) 1137*cdf0e10cSrcweir { 1138*cdf0e10cSrcweir if( xNode->getNodeType() == NodeType_TEXT_NODE 1139*cdf0e10cSrcweir || xNode->getNodeType() == NodeType_ATTRIBUTE_NODE ) 1140*cdf0e10cSrcweir { 1141*cdf0e10cSrcweir rBuffer.append( xNode->getNodeValue() ); 1142*cdf0e10cSrcweir } 1143*cdf0e10cSrcweir else 1144*cdf0e10cSrcweir { 1145*cdf0e10cSrcweir for( Reference<XNode> xChild = xNode->getFirstChild(); 1146*cdf0e10cSrcweir xChild.is(); 1147*cdf0e10cSrcweir xChild = xChild->getNextSibling() ) 1148*cdf0e10cSrcweir { 1149*cdf0e10cSrcweir lcl_getString( xChild, rBuffer ); 1150*cdf0e10cSrcweir } 1151*cdf0e10cSrcweir } 1152*cdf0e10cSrcweir } 1153*cdf0e10cSrcweir 1154*cdf0e10cSrcweir OUString lcl_getString( const Reference<XNode>& xNode ) 1155*cdf0e10cSrcweir { 1156*cdf0e10cSrcweir OUStringBuffer aBuffer; 1157*cdf0e10cSrcweir lcl_getString( xNode, aBuffer ); 1158*cdf0e10cSrcweir return aBuffer.makeStringAndClear(); 1159*cdf0e10cSrcweir } 1160*cdf0e10cSrcweir 1161*cdf0e10cSrcweir OUString Binding::getListEntry( sal_Int32 nPosition ) 1162*cdf0e10cSrcweir throw( IndexOutOfBoundsException, 1163*cdf0e10cSrcweir RuntimeException ) 1164*cdf0e10cSrcweir { 1165*cdf0e10cSrcweir // first, check for model 1166*cdf0e10cSrcweir checkLive(); 1167*cdf0e10cSrcweir 1168*cdf0e10cSrcweir // check bounds and return proper item 1169*cdf0e10cSrcweir PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList(); 1170*cdf0e10cSrcweir if( nPosition < 0 || nPosition >= static_cast<sal_Int32>( aNodes.size() ) ) 1171*cdf0e10cSrcweir throw IndexOutOfBoundsException( EXCEPT("") ); 1172*cdf0e10cSrcweir return lcl_getString( aNodes[ nPosition ] ); 1173*cdf0e10cSrcweir } 1174*cdf0e10cSrcweir 1175*cdf0e10cSrcweir Sequence<OUString> Binding::getAllListEntries() 1176*cdf0e10cSrcweir throw( RuntimeException ) 1177*cdf0e10cSrcweir { 1178*cdf0e10cSrcweir // first, check for model 1179*cdf0e10cSrcweir checkLive(); 1180*cdf0e10cSrcweir 1181*cdf0e10cSrcweir // create sequence of string values 1182*cdf0e10cSrcweir PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList(); 1183*cdf0e10cSrcweir Sequence<OUString> aSequence( aNodes.size() ); 1184*cdf0e10cSrcweir OUString* pSequence = aSequence.getArray(); 1185*cdf0e10cSrcweir for( sal_Int32 n = 0; n < aSequence.getLength(); n++ ) 1186*cdf0e10cSrcweir { 1187*cdf0e10cSrcweir pSequence[n] = lcl_getString( aNodes[n] ); 1188*cdf0e10cSrcweir } 1189*cdf0e10cSrcweir 1190*cdf0e10cSrcweir return aSequence; 1191*cdf0e10cSrcweir } 1192*cdf0e10cSrcweir 1193*cdf0e10cSrcweir void Binding::addListEntryListener( const XListEntryListener_t& xListener ) 1194*cdf0e10cSrcweir throw( NullPointerException, 1195*cdf0e10cSrcweir RuntimeException ) 1196*cdf0e10cSrcweir { 1197*cdf0e10cSrcweir OSL_ENSURE( xListener.is(), "need listener!" ); 1198*cdf0e10cSrcweir if( ::std::find( maListEntryListeners.begin(), 1199*cdf0e10cSrcweir maListEntryListeners.end(), 1200*cdf0e10cSrcweir xListener) 1201*cdf0e10cSrcweir == maListEntryListeners.end() ) 1202*cdf0e10cSrcweir maListEntryListeners.push_back( xListener ); 1203*cdf0e10cSrcweir } 1204*cdf0e10cSrcweir 1205*cdf0e10cSrcweir void Binding::removeListEntryListener( const XListEntryListener_t& xListener ) 1206*cdf0e10cSrcweir throw( NullPointerException, 1207*cdf0e10cSrcweir RuntimeException ) 1208*cdf0e10cSrcweir { 1209*cdf0e10cSrcweir XListEntryListeners_t::iterator aIter = 1210*cdf0e10cSrcweir ::std::find( maListEntryListeners.begin(), maListEntryListeners.end(), 1211*cdf0e10cSrcweir xListener ); 1212*cdf0e10cSrcweir if( aIter != maListEntryListeners.end() ) 1213*cdf0e10cSrcweir maListEntryListeners.erase( aIter ); 1214*cdf0e10cSrcweir } 1215*cdf0e10cSrcweir 1216*cdf0e10cSrcweir 1217*cdf0e10cSrcweir // 1218*cdf0e10cSrcweir // XValidator 1219*cdf0e10cSrcweir // 1220*cdf0e10cSrcweir 1221*cdf0e10cSrcweir sal_Bool Binding::isValid( const Any_t& ) 1222*cdf0e10cSrcweir throw( RuntimeException ) 1223*cdf0e10cSrcweir { 1224*cdf0e10cSrcweir // first, check for model 1225*cdf0e10cSrcweir checkLive(); 1226*cdf0e10cSrcweir 1227*cdf0e10cSrcweir // ignore value; determine validate only on current data 1228*cdf0e10cSrcweir return isValid(); 1229*cdf0e10cSrcweir } 1230*cdf0e10cSrcweir 1231*cdf0e10cSrcweir rtl::OUString Binding::explainInvalid( 1232*cdf0e10cSrcweir const Any_t& /*Value*/ ) 1233*cdf0e10cSrcweir throw( RuntimeException ) 1234*cdf0e10cSrcweir { 1235*cdf0e10cSrcweir // first, check for model 1236*cdf0e10cSrcweir checkLive(); 1237*cdf0e10cSrcweir 1238*cdf0e10cSrcweir // ignore value; determine explanation only on current data 1239*cdf0e10cSrcweir return explainInvalid(); 1240*cdf0e10cSrcweir } 1241*cdf0e10cSrcweir 1242*cdf0e10cSrcweir void Binding::addValidityConstraintListener( 1243*cdf0e10cSrcweir const XValidityConstraintListener_t& xListener ) 1244*cdf0e10cSrcweir throw( NullPointerException, 1245*cdf0e10cSrcweir RuntimeException ) 1246*cdf0e10cSrcweir { 1247*cdf0e10cSrcweir OSL_ENSURE( xListener.is(), "need listener!" ); 1248*cdf0e10cSrcweir if( ::std::find(maValidityListeners.begin(), maValidityListeners.end(), xListener) 1249*cdf0e10cSrcweir == maValidityListeners.end() ) 1250*cdf0e10cSrcweir maValidityListeners.push_back( xListener ); 1251*cdf0e10cSrcweir } 1252*cdf0e10cSrcweir 1253*cdf0e10cSrcweir void Binding::removeValidityConstraintListener( 1254*cdf0e10cSrcweir const XValidityConstraintListener_t& xListener ) 1255*cdf0e10cSrcweir throw( NullPointerException, 1256*cdf0e10cSrcweir RuntimeException ) 1257*cdf0e10cSrcweir { 1258*cdf0e10cSrcweir XValidityConstraintListeners_t::iterator aIter = 1259*cdf0e10cSrcweir ::std::find( maValidityListeners.begin(), maValidityListeners.end(), 1260*cdf0e10cSrcweir xListener ); 1261*cdf0e10cSrcweir if( aIter != maValidityListeners.end() ) 1262*cdf0e10cSrcweir maValidityListeners.erase( aIter ); 1263*cdf0e10cSrcweir } 1264*cdf0e10cSrcweir 1265*cdf0e10cSrcweir 1266*cdf0e10cSrcweir 1267*cdf0e10cSrcweir // 1268*cdf0e10cSrcweir // xml::dom::event::XEventListener 1269*cdf0e10cSrcweir // 1270*cdf0e10cSrcweir 1271*cdf0e10cSrcweir void Binding::handleEvent( const XEvent_t& xEvent ) 1272*cdf0e10cSrcweir throw( RuntimeException ) 1273*cdf0e10cSrcweir { 1274*cdf0e10cSrcweir OUString sType(xEvent->getType()); 1275*cdf0e10cSrcweir //OUString sEventMIPChanged(RTL_CONSTASCII_USTRINGPARAM("xforms-generic")); 1276*cdf0e10cSrcweir //if(sType.equals(sEventMIPChanged)) { 1277*cdf0e10cSrcweir if(!sType.compareToAscii("xforms-generic")) { 1278*cdf0e10cSrcweir 1279*cdf0e10cSrcweir // the modification of the 'mnDeferModifyNotifications'-member 1280*cdf0e10cSrcweir // is necessary to prevent infinite notication looping. 1281*cdf0e10cSrcweir // This can happend in case the binding which caused 1282*cdf0e10cSrcweir // the notification chain is listening to those events 1283*cdf0e10cSrcweir // as well... 1284*cdf0e10cSrcweir bool bPreserveValueModified = mbValueModified; 1285*cdf0e10cSrcweir mnDeferModifyNotifications++; 1286*cdf0e10cSrcweir valueModified(); 1287*cdf0e10cSrcweir --mnDeferModifyNotifications; 1288*cdf0e10cSrcweir mbValueModified = bPreserveValueModified; 1289*cdf0e10cSrcweir return; 1290*cdf0e10cSrcweir } 1291*cdf0e10cSrcweir 1292*cdf0e10cSrcweir // if we're a dynamic binding, we better re-bind, too! 1293*cdf0e10cSrcweir bind( false ); 1294*cdf0e10cSrcweir 1295*cdf0e10cSrcweir // our value was maybe modified 1296*cdf0e10cSrcweir valueModified(); 1297*cdf0e10cSrcweir } 1298*cdf0e10cSrcweir 1299*cdf0e10cSrcweir 1300*cdf0e10cSrcweir // 1301*cdf0e10cSrcweir // lang::XUnoTunnel 1302*cdf0e10cSrcweir // 1303*cdf0e10cSrcweir 1304*cdf0e10cSrcweir sal_Int64 Binding::getSomething( const IntSequence_t& xId ) 1305*cdf0e10cSrcweir throw( RuntimeException ) 1306*cdf0e10cSrcweir { 1307*cdf0e10cSrcweir return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL ); 1308*cdf0e10cSrcweir } 1309*cdf0e10cSrcweir 1310*cdf0e10cSrcweir // 1311*cdf0e10cSrcweir // XCloneable 1312*cdf0e10cSrcweir // 1313*cdf0e10cSrcweir 1314*cdf0e10cSrcweir Binding::XCloneable_t SAL_CALL Binding::createClone() 1315*cdf0e10cSrcweir throw( RuntimeException ) 1316*cdf0e10cSrcweir { 1317*cdf0e10cSrcweir Reference< XPropertySet > xClone; 1318*cdf0e10cSrcweir 1319*cdf0e10cSrcweir Model* pModel = getModelImpl(); 1320*cdf0e10cSrcweir if ( pModel ) 1321*cdf0e10cSrcweir xClone = pModel->cloneBinding( this ); 1322*cdf0e10cSrcweir else 1323*cdf0e10cSrcweir { 1324*cdf0e10cSrcweir xClone = new Binding; 1325*cdf0e10cSrcweir copy( this, xClone ); 1326*cdf0e10cSrcweir } 1327*cdf0e10cSrcweir return XCloneable_t( xClone, UNO_QUERY ); 1328*cdf0e10cSrcweir } 1329*cdf0e10cSrcweir 1330*cdf0e10cSrcweir // 1331*cdf0e10cSrcweir // property set implementations 1332*cdf0e10cSrcweir // 1333*cdf0e10cSrcweir 1334*cdf0e10cSrcweir #define REGISTER_PROPERTY( property, type ) \ 1335*cdf0e10cSrcweir registerProperty( PROPERTY( property, type ), \ 1336*cdf0e10cSrcweir new DirectPropertyAccessor< Binding, type >( this, &Binding::set##property, &Binding::get##property ) ); 1337*cdf0e10cSrcweir 1338*cdf0e10cSrcweir #define REGISTER_PROPERTY_RO( property, type ) \ 1339*cdf0e10cSrcweir registerProperty( PROPERTY_RO( property, type ), \ 1340*cdf0e10cSrcweir new DirectPropertyAccessor< Binding, type >( this, NULL, &Binding::get##property ) ); 1341*cdf0e10cSrcweir 1342*cdf0e10cSrcweir #define REGISTER_BOOL_PROPERTY_RO( property ) \ 1343*cdf0e10cSrcweir registerProperty( PROPERTY_RO( property, sal_Bool ), \ 1344*cdf0e10cSrcweir new BooleanPropertyAccessor< Binding, bool >( this, NULL, &Binding::get##property ) ); 1345*cdf0e10cSrcweir 1346*cdf0e10cSrcweir void Binding::initializePropertySet() 1347*cdf0e10cSrcweir { 1348*cdf0e10cSrcweir REGISTER_PROPERTY ( BindingID, OUString ); 1349*cdf0e10cSrcweir REGISTER_PROPERTY ( BindingExpression, OUString ); 1350*cdf0e10cSrcweir REGISTER_PROPERTY_RO ( Model, Model_t ); 1351*cdf0e10cSrcweir REGISTER_PROPERTY ( BindingNamespaces, XNameContainer_t ); 1352*cdf0e10cSrcweir REGISTER_PROPERTY ( ModelNamespaces, XNameContainer_t ); 1353*cdf0e10cSrcweir REGISTER_PROPERTY_RO ( ModelID, OUString ); 1354*cdf0e10cSrcweir REGISTER_PROPERTY ( ReadonlyExpression, OUString ); 1355*cdf0e10cSrcweir REGISTER_PROPERTY ( RelevantExpression, OUString ); 1356*cdf0e10cSrcweir REGISTER_PROPERTY ( RequiredExpression, OUString ); 1357*cdf0e10cSrcweir REGISTER_PROPERTY ( ConstraintExpression, OUString ); 1358*cdf0e10cSrcweir REGISTER_PROPERTY ( CalculateExpression, OUString ); 1359*cdf0e10cSrcweir REGISTER_PROPERTY ( Type, OUString ); 1360*cdf0e10cSrcweir REGISTER_PROPERTY_RO ( ReadOnly, bool ); 1361*cdf0e10cSrcweir REGISTER_PROPERTY_RO ( Relevant, bool ); 1362*cdf0e10cSrcweir REGISTER_BOOL_PROPERTY_RO( ExternalData ); 1363*cdf0e10cSrcweir 1364*cdf0e10cSrcweir initializePropertyValueCache( HANDLE_ReadOnly ); 1365*cdf0e10cSrcweir initializePropertyValueCache( HANDLE_Relevant ); 1366*cdf0e10cSrcweir initializePropertyValueCache( HANDLE_ExternalData ); 1367*cdf0e10cSrcweir } 1368*cdf0e10cSrcweir 1369*cdf0e10cSrcweir void Binding::addModifyListener( 1370*cdf0e10cSrcweir const XModifyListener_t& xListener ) 1371*cdf0e10cSrcweir throw( RuntimeException ) 1372*cdf0e10cSrcweir { 1373*cdf0e10cSrcweir OSL_ENSURE( xListener.is(), "need listener!" ); 1374*cdf0e10cSrcweir if( ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener ) 1375*cdf0e10cSrcweir == maModifyListeners.end() ) 1376*cdf0e10cSrcweir maModifyListeners.push_back( xListener ); 1377*cdf0e10cSrcweir 1378*cdf0e10cSrcweir // HACK: currently, we have to 'push' some MIPs to the control 1379*cdf0e10cSrcweir // (read-only, relevant, etc.) To enable this, we need to update 1380*cdf0e10cSrcweir // the control at least once when it registers here. 1381*cdf0e10cSrcweir valueModified(); 1382*cdf0e10cSrcweir } 1383*cdf0e10cSrcweir 1384*cdf0e10cSrcweir void Binding::removeModifyListener( 1385*cdf0e10cSrcweir const XModifyListener_t& xListener ) 1386*cdf0e10cSrcweir throw( RuntimeException ) 1387*cdf0e10cSrcweir { 1388*cdf0e10cSrcweir ModifyListeners_t::iterator aIter = 1389*cdf0e10cSrcweir ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener ); 1390*cdf0e10cSrcweir if( aIter != maModifyListeners.end() ) 1391*cdf0e10cSrcweir maModifyListeners.erase( aIter ); 1392*cdf0e10cSrcweir } 1393*cdf0e10cSrcweir 1394*cdf0e10cSrcweir 1395*cdf0e10cSrcweir 1396*cdf0e10cSrcweir 1397*cdf0e10cSrcweir rtl::OUString Binding::getName() 1398*cdf0e10cSrcweir throw( RuntimeException ) 1399*cdf0e10cSrcweir { 1400*cdf0e10cSrcweir return getBindingID(); 1401*cdf0e10cSrcweir } 1402*cdf0e10cSrcweir 1403*cdf0e10cSrcweir void SAL_CALL Binding::setName( const rtl::OUString& rName ) 1404*cdf0e10cSrcweir throw( RuntimeException ) 1405*cdf0e10cSrcweir { 1406*cdf0e10cSrcweir // use the XPropertySet methods, so the change in the name is notified to the 1407*cdf0e10cSrcweir // property listeners 1408*cdf0e10cSrcweir setFastPropertyValue( HANDLE_BindingID, makeAny( rName ) ); 1409*cdf0e10cSrcweir } 1410