xref: /aoo41x/main/forms/source/xforms/binding.cxx (revision cdf0e10c)
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