124acc546SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
324acc546SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
424acc546SAndrew Rist * or more contributor license agreements. See the NOTICE file
524acc546SAndrew Rist * distributed with this work for additional information
624acc546SAndrew Rist * regarding copyright ownership. The ASF licenses this file
724acc546SAndrew Rist * to you under the Apache License, Version 2.0 (the
824acc546SAndrew Rist * "License"); you may not use this file except in compliance
924acc546SAndrew Rist * with the License. You may obtain a copy of the License at
1024acc546SAndrew Rist *
1124acc546SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
1224acc546SAndrew Rist *
1324acc546SAndrew Rist * Unless required by applicable law or agreed to in writing,
1424acc546SAndrew Rist * software distributed under the License is distributed on an
1524acc546SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1624acc546SAndrew Rist * KIND, either express or implied. See the License for the
1724acc546SAndrew Rist * specific language governing permissions and limitations
1824acc546SAndrew Rist * under the License.
1924acc546SAndrew Rist *
2024acc546SAndrew Rist *************************************************************/
2124acc546SAndrew Rist
2224acc546SAndrew 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
677*07a3d7f1SPedro Giffuni // now evaluate remaining MIPs in the appropriate 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.
1277*07a3d7f1SPedro Giffuni // This can happened 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