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