LibreOffice Module forms (master) 1
binding.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20
21#include "binding.hxx"
22
23#include "model.hxx"
24#include "unohelper.hxx"
25#include "NameContainer.hxx"
26#include "evaluationcontext.hxx"
27#include "convert.hxx"
28#include "resourcehelper.hxx"
29#include "xmlhelper.hxx"
30#include "xformsevent.hxx"
31#include <strings.hrc>
32
33#include <rtl/ustrbuf.hxx>
34#include <o3tl/safeint.hxx>
35#include <osl/diagnose.h>
36
38
39#include <algorithm>
40#include <functional>
41
42#include <com/sun/star/form/binding/IncompatibleTypesException.hpp>
43#include <com/sun/star/form/binding/InvalidBindingStateException.hpp>
44#include <com/sun/star/uno/Any.hxx>
45#include <com/sun/star/xml/dom/XNodeList.hpp>
46#include <com/sun/star/xml/dom/XNode.hpp>
47#include <com/sun/star/xml/dom/XDocument.hpp>
48#include <com/sun/star/xml/dom/XElement.hpp>
49#include <com/sun/star/xml/dom/NodeType.hpp>
50#include <com/sun/star/xml/dom/events/XEventTarget.hpp>
51#include <com/sun/star/xml/dom/events/XEventListener.hpp>
52#include <com/sun/star/lang/XUnoTunnel.hpp>
53#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
54#include <com/sun/star/container/XNameContainer.hpp>
55
57
58using namespace com::sun::star::xml::xpath;
60
61using std::vector;
62using xforms::Binding;
63using xforms::MIP;
64using xforms::Model;
68using com::sun::star::container::XNameAccess;
69using com::sun::star::form::binding::IncompatibleTypesException;
70using com::sun::star::form::binding::InvalidBindingStateException;
71using com::sun::star::form::binding::XValueBinding;
72using com::sun::star::lang::EventObject;
73using com::sun::star::lang::IndexOutOfBoundsException;
74using com::sun::star::uno::Any;
76using com::sun::star::uno::RuntimeException;
78using com::sun::star::uno::UNO_QUERY;
79using com::sun::star::uno::UNO_QUERY_THROW;
80using com::sun::star::uno::XInterface;
81using com::sun::star::uno::Exception;
82using com::sun::star::util::XModifyListener;
83using com::sun::star::xforms::XDataTypeRepository;
84using com::sun::star::xml::dom::NodeType_ATTRIBUTE_NODE;
85using com::sun::star::xml::dom::NodeType_TEXT_NODE;
86using com::sun::star::xml::dom::XNode;
87using com::sun::star::xml::dom::XNodeList;
88using com::sun::star::xml::dom::events::XEventListener;
89using com::sun::star::xml::dom::events::XEventTarget;
90using com::sun::star::xsd::XDataType;
91
92#define HANDLE_BindingID 0
93#define HANDLE_BindingExpression 1
94#define HANDLE_Model 2
95#define HANDLE_ModelID 3
96#define HANDLE_BindingNamespaces 4
97#define HANDLE_ReadonlyExpression 5
98#define HANDLE_RelevantExpression 6
99#define HANDLE_RequiredExpression 7
100#define HANDLE_ConstraintExpression 8
101#define HANDLE_CalculateExpression 9
102#define HANDLE_Type 10
103#define HANDLE_ReadOnly 11 // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control
104#define HANDLE_Relevant 12 // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control
105#define HANDLE_ModelNamespaces 13
106#define HANDLE_ExternalData 14
107
108
109Binding::Binding() :
110 mxNamespaces( new NameContainer<OUString>() ),
111 mbInCalculate( false ),
112 mnDeferModifyNotifications( 0 ),
113 mbValueModified( false ),
114 mbBindingModified( false )
115{
117}
118
120{
121 _setModel(nullptr);
122}
123
124void Binding::_setModel( const css::uno::Reference<css::xforms::XModel>& xModel )
125{
126 PropertyChangeNotifier aNotifyModelChange( *this, HANDLE_Model );
127 PropertyChangeNotifier aNotifyModelIDChange( *this, HANDLE_ModelID );
128
129 // prepare binding for removal of old model
130 clear(); // remove all cached data (e.g. XPath evaluation results)
131 css::uno::Reference<css::container::XNameContainer> xNamespaces = getModelNamespaces(); // save namespaces
132
133 mxModel = xModel;
134
135 // set namespaces (and move to model, if appropriate)
136 setBindingNamespaces( xNamespaces );
138
139 notifyAndCachePropertyValue( HANDLE_ExternalData );
140}
141
142
143OUString Binding::getModelID() const
144{
145 Model* pModel = getModelImpl();
146 return ( pModel == nullptr ) ? OUString() : pModel->getID();
147}
148
149
150css::uno::Reference<css::xml::dom::XNodeList> Binding::getXNodeList()
151{
152 // first make sure we are bound
154 bind();
155
157}
158
160{
167}
168
170{
172}
173
175{
176 // clear all expressions (to remove cached node references)
183
184 // let's just pretend the binding has been modified -> full rebind()
186}
187
189{
190 mnDeferModifyNotifications += ( bDefer ? 1 : -1 );
191 OSL_ENSURE( mnDeferModifyNotifications >= 0, "you're deferring too much" );
192
194 {
197 if( mbValueModified )
199 }
200
201 OSL_ENSURE( ( mnDeferModifyNotifications > 0 )
203 "deferred modifications not delivered?" );
204}
205
207{
208 // TODO: determine whether node is suitable, not just whether it exists
209 return maBindingExpression.getNode().is() &&
210 (
211 // tdf#155121, validity rules should be apply when field is required or
212 // when the field is not required but not empty
213 // so if the field is not required and empty, do not check validity
215 && maBindingExpression.getString().isEmpty() ) ||
217 ) &&
219 ( ! maMIP.isRequired() ||
221 !maBindingExpression.getString().isEmpty() ) );
222}
223
225{
226 // we are useful, if
227 // 0) we don't have a model
228 // (at least, in this case we shouldn't be removed from the model)
229 // 1) we have a proper name
230 // 2) we have some MIPs,
231 // 3) we are bound to some control
232 // (this can be assumed if some listeners are set)
233 bool bUseful =
234 getModelImpl() == nullptr
235// || msBindingID.getLength() > 0
236 || ! msTypeName.isEmpty()
242 || ! maModifyListeners.empty()
243 || ! maListEntryListeners.empty()
244 || ! maValidityListeners.empty();
245
246 return bUseful;
247}
248
250{
251 OUString sReason;
252 if( ! maBindingExpression.getNode().is() )
253 {
254 sReason = ( maBindingExpression.getExpression().isEmpty() )
255 ? getResource( RID_STR_XFORMS_NO_BINDING_EXPRESSION )
256 : getResource( RID_STR_XFORMS_INVALID_BINDING_EXPRESSION );
257 }
258 else if( ! isValid_DataType() )
259 {
260 sReason = explainInvalid_DataType();
261 if( sReason.isEmpty() )
262 {
263 // no explanation given by data type? Then give generic message
264 sReason = getResource( RID_STR_XFORMS_INVALID_VALUE,
265 maMIP.getTypeName() );
266 }
267 }
268 else if( ! maMIP.isConstraint() )
269 {
271 }
273 maBindingExpression.getString().isEmpty() )
274 {
275 sReason = getResource( RID_STR_XFORMS_REQUIRED );
276 }
277 // else: no explanation given; should only happen if data is valid
278
279 OSL_ENSURE( sReason.isEmpty() == isValid(),
280 "invalid data should have an explanation!" );
281
282 return sReason;
283}
284
285
287{
288 OSL_ENSURE( getModelImpl() != nullptr, "need model impl" );
291 return aContext;
292}
293
294::std::vector<EvaluationContext> Binding::getMIPEvaluationContexts()
295{
296 OSL_ENSURE( getModelImpl() != nullptr, "need model impl" );
297
298 // bind (in case we were not bound before)
299 bind();
301}
302
303
304css::uno::Sequence<sal_Int8> Binding::getUnoTunnelId()
305{
306 static const comphelper::UnoIdInit aImplementationId;
307 return aImplementationId.getSeq();
308}
309
310
311void Binding::setBindingID( const OUString& sBindingID )
312{
313 msBindingID = sBindingID;
314}
315
317{
319}
320
321void Binding::setBindingExpression( const OUString& sBindingExpression)
322{
323 maBindingExpression.setExpression( sBindingExpression );
325}
326
328{
329 return maReadonly.getExpression();
330}
331
332void Binding::setReadonlyExpression( const OUString& sReadonly)
333{
334 maReadonly.setExpression( sReadonly );
336}
337
339{
340 return maRelevant.getExpression();
341}
342
343void Binding::setRelevantExpression( const OUString& sRelevant )
344{
345 maRelevant.setExpression( sRelevant );
347}
348
350{
351 return maRequired.getExpression();
352}
353
354void Binding::setRequiredExpression( const OUString& sRequired )
355{
356 maRequired.setExpression( sRequired );
358}
359
361{
363}
364
365void Binding::setConstraintExpression( const OUString& sConstraint )
366{
367 maConstraint.setExpression( sConstraint );
368 msExplainConstraint = getResource( RID_STR_XFORMS_INVALID_CONSTRAINT,
369 sConstraint );
370
371 // TODO: This should only re-evaluate the constraint, and notify
372 // the validity constraint listeners; instead we currently pretend
373 // the entire binding was notified, which does a little too much.
375}
376
378{
379 return maCalculate.getExpression();
380}
381
382void Binding::setCalculateExpression( const OUString& sCalculate )
383{
384 maCalculate.setExpression( sCalculate );
386}
387
388
389void Binding::setType( const OUString& sTypeName )
390{
391 msTypeName = sTypeName;
393}
394
395void Binding::setBindingNamespaces( const css::uno::Reference<css::container::XNameContainer>& rNamespaces )
396{
397 _setNamespaces( rNamespaces, true );
398}
399
400css::uno::Reference<css::container::XNameContainer> Binding::getModelNamespaces() const
401{
402 return _getNamespaces();
403}
404
405void Binding::setModelNamespaces( const css::uno::Reference<css::container::XNameContainer>& rNamespaces )
406{
407 _setNamespaces( rNamespaces, false );
408}
409
411{
412 return maMIP.isReadonly();
413}
414
416{
417 return maMIP.isRelevant();
418}
419
421{
422 bool bExternalData = true;
423 if ( !mxModel.is() )
424 return bExternalData;
425
426 try
427 {
428 Reference< XPropertySet > xModelProps( mxModel, UNO_QUERY_THROW );
429 OSL_VERIFY(
430 xModelProps->getPropertyValue( "ExternalData" ) >>= bExternalData );
431 }
432 catch( const Exception& )
433 {
434 DBG_UNHANDLED_EXCEPTION("forms.xforms");
435 }
436 return bExternalData;
437}
438
439
441{
442 if( ! isLive() )
443 throw RuntimeException("Binding not initialized", static_cast<XValueBinding*>(this));
444}
445
446bool Binding::isLive() const
447{
448 const Model* pModel = getModelImpl();
449 return pModel && pModel->isInitialized();
450}
451
453{
454 return dynamic_cast<Model*>( mxModel.get() );
455}
456
457static void lcl_addListenerToNode( const Reference<XNode>& xNode,
458 const Reference<XEventListener>& xListener )
459{
460 Reference<XEventTarget> xTarget( xNode, UNO_QUERY );
461 if( !xTarget.is() )
462 return;
463
464 xTarget->addEventListener( "DOMCharacterDataModified",
465 xListener, false );
466 xTarget->addEventListener( "DOMCharacterDataModified",
467 xListener, true );
468 xTarget->addEventListener( "DOMAttrModified",
469 xListener, false );
470 xTarget->addEventListener( "DOMAttrModified",
471 xListener, true );
472 xTarget->addEventListener( "xforms-generic",
473 xListener, true );
474}
475
477 const Reference<XEventListener>& xListener )
478{
479 Reference<XEventTarget> xTarget( xNode, UNO_QUERY );
480 if( !xTarget.is() )
481 return;
482
483 xTarget->removeEventListener( "DOMCharacterDataModified",
484 xListener, false );
485 xTarget->removeEventListener( "DOMCharacterDataModified",
486 xListener, true );
487 xTarget->removeEventListener( "DOMAttrModified",
488 xListener, false );
489 xTarget->removeEventListener( "DOMAttrModified",
490 xListener, true );
491 xTarget->removeEventListener( "xforms-generic",
492 xListener, true );
493}
494
495::std::vector<EvaluationContext> Binding::_getMIPEvaluationContexts() const
496{
497 OSL_ENSURE( getModelImpl() != nullptr, "need model impl" );
498
499 // iterate over nodes of bind expression and create
500 // EvaluationContext for each
502 ::std::vector<EvaluationContext> aVector;
503 for (auto const& node : aNodes)
504 {
505 OSL_ENSURE( node.is(), "no node?" );
506
507 // create proper evaluation context for this MIP
508 aVector.emplace_back( node, getModel(), getBindingNamespaces() );
509 }
510 return aVector;
511}
512
513void Binding::bind( bool bForceRebind )
514{
515 if( ! mxModel.is() )
516 throw RuntimeException("Binding has no Model", static_cast<XValueBinding*>(this));
517
518 // bind() will evaluate this binding as follows:
519 // 1) evaluate the binding expression
520 // 1b) if necessary, create node according to 'lazy author' rules
521 // 2) register suitable listeners on the instance (and remove old ones)
522 // 3) remove old MIPs defined by this binding
523 // 4) for every node in the binding nodeset do:
524 // 1) create proper evaluation context for this MIP
525 // 2) evaluate calculate expression (and push value into instance)
526 // 3) evaluate remaining MIPs
527 // 4) evaluate the locally defined MIPs, and push them to the model
528
529
530 // 1) evaluate the binding expression
532 maBindingExpression.evaluate( aContext );
533 if( ! maBindingExpression.getNode().is() )
534 {
535 // 1b) create node (if valid element name)
537 aContext.mxNamespaces ) )
538 {
539 aContext.mxContextNode->appendChild(
540 aContext.mxContextNode->getOwnerDocument()->createElement(
542 maBindingExpression.evaluate( aContext );
543 OSL_ENSURE( maBindingExpression.getNode().is(),
544 "we should bind to the newly inserted node!" );
545 }
546 }
548
549 // 2) register suitable listeners on the instance (and remove old ones)
550 if( maEventNodes.empty() || bForceRebind )
551 {
552 for (auto const& eventNode : maEventNodes)
553 lcl_removeListenerFromNode( eventNode, this );
554 maEventNodes.clear();
555 if( isSimpleBinding() )
556 maEventNodes.insert(maEventNodes.end(), aNodes.begin(), aNodes.end());
557 else
558 maEventNodes.emplace_back( aContext.mxContextNode->getOwnerDocument(),
559 UNO_QUERY_THROW );
560 for (auto const& eventNode : maEventNodes)
561 lcl_addListenerToNode( eventNode, this );
562 }
563
564 // 3) remove old MIPs defined by this binding
565 Model* pModel = getModelImpl();
566 OSL_ENSURE( pModel != nullptr, "need model" );
567 pModel->removeMIPs( this );
568
569 // 4) calculate all MIPs
570 ::std::vector<EvaluationContext> aMIPContexts = _getMIPEvaluationContexts();
571 for (auto & context : aMIPContexts)
572 {
573 EvaluationContext& rContext = context;
574
575 // evaluate calculate expression (and push value into instance)
576 // (prevent recursion using mbInCalculate
578 {
579 if( ! mbInCalculate )
580 {
581 mbInCalculate = true;
582 maCalculate.evaluate( rContext );
583 pModel->setSimpleContent( rContext.mxContextNode,
585 mbInCalculate = false;
586 }
587 }
588
589 // now evaluate remaining MIPs in the appropriate context
590 maReadonly.evaluate( rContext );
591 maRelevant.evaluate( rContext );
592 maRequired.evaluate( rContext );
593 maConstraint.evaluate( rContext );
594 // type is static; does not need updating
595
596 // evaluate the locally defined MIPs, and push them to the model
597 pModel->addMIP( this, rContext.mxContextNode, getLocalMIP() );
598 }
599}
600
601
602// helper for Binding::valueModified
603static void lcl_modified( const css::uno::Reference<css::util::XModifyListener>& xListener,
604 const Reference<XInterface>& xSource )
605{
606 OSL_ENSURE( xListener.is(), "no listener?" );
607 xListener->modified( EventObject( xSource ) );
608}
609
610// helper for Binding::valueModified
611static void lcl_listentry( const css::uno::Reference<css::form::binding::XListEntryListener>& xListener,
612 const Reference<XInterface>& xSource )
613{
614 OSL_ENSURE( xListener.is(), "no listener?" );
615 // TODO: send fine granular events
616 xListener->allEntriesChanged( EventObject( xSource ) );
617}
618
619// helper for Binding::valueModified
620static void lcl_validate( const css::uno::Reference<css::form::validation::XValidityConstraintListener>& xListener,
621 const Reference<XInterface>& xSource )
622{
623 OSL_ENSURE( xListener.is(), "no listener?" );
624 xListener->validityConstraintChanged( EventObject( xSource ) );
625}
626
627
629{
630 // defer notifications, if so desired
632 {
633 mbValueModified = true;
634 return;
635 }
636 mbValueModified = false;
637
638 // query MIP used by our first node (also note validity)
640 maMIP = getModelImpl()->queryMIP( xNode );
641
642 // distribute MIPs _used_ by this binding
643 if( xNode.is() )
644 {
645 notifyAndCachePropertyValue( HANDLE_ReadOnly );
646 notifyAndCachePropertyValue( HANDLE_Relevant );
647 }
648
649 // iterate over _value_ listeners and send each a modified signal,
650 // using this object as source (will also update validity, because
651 // control will query once the value has changed)
652 Reference<XInterface> xSource = static_cast<XPropertySet*>( this );
653 ::std::for_each( maModifyListeners.begin(),
654 maModifyListeners.end(),
655 ::std::bind( lcl_modified, std::placeholders::_1, xSource ) );
656 ::std::for_each( maListEntryListeners.begin(),
658 ::std::bind( lcl_listentry, std::placeholders::_1, xSource ) );
659 ::std::for_each( maValidityListeners.begin(),
661 ::std::bind( lcl_validate, std::placeholders::_1, xSource ) );
662
663 // now distribute MIPs to children
664 if( xNode.is() )
665 distributeMIP( xNode->getFirstChild() );
666}
667
668void Binding::distributeMIP( const css::uno::Reference<css::xml::dom::XNode> & rxNode ) {
669
670 rtl::Reference<css::xforms::XFormsEventConcrete> pEvent = new css::xforms::XFormsEventConcrete;
671 pEvent->initXFormsEvent("xforms-generic", true, false);
672
673 // naive depth-first traversal
674 css::uno::Reference<css::xml::dom::XNode> xNode( rxNode );
675 while(xNode.is()) {
676
677 // notifications should be triggered at the
678 // leaf nodes first, bubbling upwards the hierarchy.
679 css::uno::Reference<css::xml::dom::XNode> child(xNode->getFirstChild());
680 if(child.is())
681 distributeMIP(child);
682
683 // we're standing at a particular node somewhere
684 // below the one which changed a property (MIP).
685 // bindings which are listening at this node will receive
686 // a notification message about what exactly happened.
687 Reference< XEventTarget > target(xNode,UNO_QUERY);
688 target->dispatchEvent(pEvent);
689
690 xNode = xNode->getNextSibling();
691 }
692}
693
695{
696 // defer notifications, if so desired
698 {
699 mbBindingModified = true;
700 return;
701 }
702 mbBindingModified = false;
703
704 // rebind (if live); then call valueModified
705 // A binding should be inert until its model is fully constructed.
706 if( isLive() )
707 {
708 bind( true );
710 }
711}
712
713
715{
716 MIP aMIP;
717
718 if( maReadonly.hasValue() )
720 if( maRelevant.hasValue() )
721 aMIP.setRelevant( maRelevant.getBool( true ) );
722 if( maRequired.hasValue() )
724 if( maConstraint.hasValue() )
725 {
726 aMIP.setConstraint( maConstraint.getBool( true ) );
727 if( ! aMIP.isConstraint() )
729 }
730 if( !msTypeName.isEmpty() )
731 aMIP.setTypeName( msTypeName );
732
733 // calculate: only handle presence of calculate; value set elsewhere
735
736 return aMIP;
737}
738
739css::uno::Reference<css::xsd::XDataType> Binding::getDataType() const
740{
741 OSL_ENSURE( getModel().is(), "need model" );
742 OSL_ENSURE( getModel()->getDataTypeRepository().is(), "need types" );
743
745 getModel()->getDataTypeRepository();
746 OUString sTypeName = maMIP.getTypeName();
747
748 return ( xRepository.is() && xRepository->hasByName( sTypeName ) )
749 ? Reference<XDataType>( xRepository->getByName( sTypeName ), UNO_QUERY)
750 : Reference<XDataType>( nullptr );
751}
752
754{
755 Reference<XDataType> xDataType = getDataType();
756 return !xDataType.is()
757 || xDataType->validate( maBindingExpression.getString() );
758}
759
761{
762 Reference<XDataType> xDataType = getDataType();
763 return xDataType.is()
764 ? xDataType->explainInvalid( maBindingExpression.getString() )
765 : OUString();
766}
767
769{
770 // remove MIPs contributed by this binding
771 Model* pModel = getModelImpl();
772 if( pModel != nullptr )
773 pModel->removeMIPs( this );
774
775 // remove all references
776 for (auto const& eventNode : maEventNodes)
777 lcl_removeListenerFromNode( eventNode, this );
778 maEventNodes.clear();
779
780 // clear expressions
787
788 // TODO: what about our listeners?
789}
790
791
792static void lcl_removeOtherNamespaces( const css::uno::Reference<css::container::XNameContainer>& xFrom,
793 css::uno::Reference<css::container::XNameContainer> const & xTo )
794{
795 OSL_ENSURE( xFrom.is(), "no source" );
796 OSL_ENSURE( xTo.is(), "no target" );
797
798 // iterate over name in source
799 Sequence<OUString> aNames = xTo->getElementNames();
800 sal_Int32 nNames = aNames.getLength();
801 const OUString* pNames = aNames.getConstArray();
802 for( sal_Int32 i = 0; i < nNames; i++ )
803 {
804 const OUString& rName = pNames[i];
805
806 if( ! xFrom->hasByName( rName ) )
807 xTo->removeByName( rName );
808 }
809}
810
819static void lcl_copyNamespaces( const css::uno::Reference<css::container::XNameContainer>& xFrom,
820 css::uno::Reference<css::container::XNameContainer> const & xTo,
821 bool bOverwrite )
822{
823 OSL_ENSURE( xFrom.is(), "no source" );
824 OSL_ENSURE( xTo.is(), "no target" );
825
826 // iterate over name in source
827 Sequence<OUString> aNames = xFrom->getElementNames();
828 sal_Int32 nNames = aNames.getLength();
829 const OUString* pNames = aNames.getConstArray();
830 for( sal_Int32 i = 0; i < nNames; i++ )
831 {
832 const OUString& rName = pNames[i];
833
834 // determine whether to copy the value, and whether to delete
835 // it in the source:
836
837 bool bInTarget = xTo->hasByName( rName );
838
839 // we copy: if property is in target, and
840 // if bOverwrite is set, or when the namespace prefix is free
841 bool bCopy = bOverwrite || ! bInTarget;
842
843 // and now... ACTION!
844 if( bCopy )
845 {
846 if( bInTarget )
847 xTo->replaceByName( rName, xFrom->getByName( rName ) );
848 else
849 xTo->insertByName( rName, xFrom->getByName( rName ) );
850 }
851 }
852}
853
854// implement get*Namespaces()
855// (identical for both variants)
856css::uno::Reference<css::container::XNameContainer> Binding::_getNamespaces() const
857{
858 css::uno::Reference<css::container::XNameContainer> xNamespaces = new NameContainer<OUString>();
859 lcl_copyNamespaces( mxNamespaces, xNamespaces, true );
860
861 // merge model's with binding's own namespaces
862 Model* pModel = getModelImpl();
863 if( pModel != nullptr )
864 lcl_copyNamespaces( pModel->getNamespaces(), xNamespaces, false );
865
866 return xNamespaces;
867}
868
869// implement set*Namespaces()
870// bBinding = true: setBindingNamespaces, otherwise: setModelNamespaces
871void Binding::_setNamespaces( const css::uno::Reference<css::container::XNameContainer>& rNamespaces,
872 bool bBinding )
873{
874 Model* pModel = getModelImpl();
875 css::uno::Reference<css::container::XNameContainer> xModelNamespaces = ( pModel != nullptr )
876 ? pModel->getNamespaces()
877 : nullptr;
878 OSL_ENSURE( ( pModel != nullptr ) == xModelNamespaces.is(), "no model nmsp?");
879
880 // remove deleted namespaces
882 if( !bBinding && xModelNamespaces.is() )
883 lcl_removeOtherNamespaces( rNamespaces, xModelNamespaces );
884
885 // copy namespaces as appropriate
886 Sequence<OUString> aNames = rNamespaces->getElementNames();
887 sal_Int32 nNames = aNames.getLength();
888 const OUString* pNames = aNames.getConstArray();
889 for( sal_Int32 i = 0; i < nNames; i++ )
890 {
891 const OUString& rName = pNames[i];
892 Any aValue = rNamespaces->getByName( rName );
893
894 // determine whether the namespace should go into model's or
895 // into binding's namespaces
896 bool bLocal =
897 ! xModelNamespaces.is()
898 || mxNamespaces->hasByName( rName )
899 || ( bBinding
900 && xModelNamespaces.is()
901 && xModelNamespaces->hasByName( rName ) );
902
903 // write namespace into the appropriate namespace container
904 css::uno::Reference<css::container::XNameContainer>& rWhich = bLocal ? mxNamespaces : xModelNamespaces;
905 OSL_ENSURE( rWhich.is(), "whoops" );
906 if( rWhich->hasByName( rName ) )
907 rWhich->replaceByName( rName, aValue );
908 else
909 rWhich->insertByName( rName, aValue );
910
911 // always 'promote' namespaces from binding to model, if equal
912 if( xModelNamespaces.is()
913 && xModelNamespaces->hasByName( rName )
914 && mxNamespaces->hasByName( rName )
915 && xModelNamespaces->getByName( rName ) == mxNamespaces->getByName( rName ) )
916 {
917 mxNamespaces->removeByName( rName );
918 }
919 }
920
921 // ... done. But we modified the binding!
923}
924
926{
927 if( !getModel().is() )
928 return;
929
930 Reference<XNameAccess> xBindings( getModel()->getBindings(), UNO_QUERY_THROW );
931 if( !msBindingID.isEmpty() )
932 return;
933
934 // no binding ID? then make one up!
935 OUString sIDPrefix = getResource( RID_STR_XFORMS_BINDING_UI_NAME ) + " ";
936 sal_Int32 nNumber = 0;
937 OUString sName;
938 do
939 {
940 nNumber++;
941 sName = sIDPrefix + OUString::number( nNumber );
942 }
943 while( xBindings->hasByName( sName ) );
945}
946
947
948// XValueBinding
949
950
951css::uno::Sequence<css::uno::Type> Binding::getSupportedValueTypes()
952{
953 return Convert::get().getTypes();
954}
955
956sal_Bool Binding::supportsType( const css::uno::Type& rType )
957{
958 return Convert::get().hasType( rType );
959}
960
961css::uno::Any Binding::getValue( const css::uno::Type& rType )
962{
963 // first, check for model
964 checkLive();
965
966 // second, check for type
967 if( ! supportsType( rType ) )
968 throw IncompatibleTypesException("type unsupported", static_cast<XValueBinding*>(this));
969
970 // return string value (if present; else return empty Any)
971 css::uno::Any result;
973 OUString pathExpr(maBindingExpression.getString());
974 Convert &rConvert = Convert::get();
975 result = rConvert.toAny(pathExpr,rType);
976 }
977
978 return result;
979}
980
981void Binding::setValue( const css::uno::Any& aValue )
982{
983 // first, check for model
984 checkLive();
985
986 // check for supported type
987 if( ! supportsType( aValue.getValueType() ) )
988 throw IncompatibleTypesException("type unsupported", static_cast<XValueBinding*>(this));
989
991 throw InvalidBindingStateException("no suitable node found", static_cast<XValueBinding*>(this));
992
993 css::uno::Reference<css::xml::dom::XNode> xNode = maBindingExpression.getNode();
994 if( !xNode.is() )
995 throw InvalidBindingStateException("no suitable node found", static_cast<XValueBinding*>(this));
996
997 OUString sValue = Convert::get().toXSD( aValue );
998 bool bSuccess = getModelImpl()->setSimpleContent( xNode, sValue );
999 if( ! bSuccess )
1000 throw InvalidBindingStateException("can't set value", static_cast<XValueBinding*>(this));
1001
1002
1003}
1004
1005
1006// XListEntry Source
1007
1008
1010{
1011 // first, check for model
1012 checkLive();
1013
1014 // return size of node list
1015 return maBindingExpression.getNodeList().size();
1016}
1017
1018static void lcl_getString( const Reference<XNode>& xNode, OUStringBuffer& rBuffer )
1019{
1020 if( xNode->getNodeType() == NodeType_TEXT_NODE
1021 || xNode->getNodeType() == NodeType_ATTRIBUTE_NODE )
1022 {
1023 rBuffer.append( xNode->getNodeValue() );
1024 }
1025 else
1026 {
1027 for( Reference<XNode> xChild = xNode->getFirstChild();
1028 xChild.is();
1029 xChild = xChild->getNextSibling() )
1030 {
1031 lcl_getString( xChild, rBuffer );
1032 }
1033 }
1034}
1035
1036static OUString lcl_getString( const Reference<XNode>& xNode )
1037{
1038 OUStringBuffer aBuffer;
1039 lcl_getString( xNode, aBuffer );
1040 return aBuffer.makeStringAndClear();
1041}
1042
1043OUString Binding::getListEntry( sal_Int32 nPosition )
1044{
1045 // first, check for model
1046 checkLive();
1047
1048 // check bounds and return proper item
1050 if( nPosition < 0 || o3tl::make_unsigned(nPosition) >= aNodes.size() )
1051 throw IndexOutOfBoundsException("", static_cast<XValueBinding*>(this));
1052 return lcl_getString( aNodes[ nPosition ] );
1053}
1054
1056{
1057 // first, check for model
1058 checkLive();
1059
1060 // create sequence of string values
1062 Sequence<OUString> aSequence( aNodes.size() );
1063 OUString* pSequence = aSequence.getArray();
1064 for( sal_Int32 n = 0; n < aSequence.getLength(); n++ )
1065 {
1066 pSequence[n] = lcl_getString( aNodes[n] );
1067 }
1068
1069 return aSequence;
1070}
1071
1072void Binding::addListEntryListener( const css::uno::Reference<css::form::binding::XListEntryListener>& xListener )
1073{
1074 OSL_ENSURE( xListener.is(), "need listener!" );
1075 if( ::std::find( maListEntryListeners.begin(),
1077 xListener)
1078 == maListEntryListeners.end() )
1079 maListEntryListeners.push_back( xListener );
1080}
1081
1082void Binding::removeListEntryListener( const css::uno::Reference<css::form::binding::XListEntryListener>& xListener )
1083{
1084 XListEntryListeners_t::iterator aIter =
1085 ::std::find( maListEntryListeners.begin(), maListEntryListeners.end(),
1086 xListener );
1087 if( aIter != maListEntryListeners.end() )
1088 maListEntryListeners.erase( aIter );
1089}
1090
1091
1092// XValidator
1093
1094
1095sal_Bool Binding::isValid( const css::uno::Any& )
1096{
1097 // first, check for model
1098 checkLive();
1099
1100 // ignore value; determine validate only on current data
1101 return isValid();
1102}
1103
1105 const css::uno::Any& /*Value*/ )
1106{
1107 // first, check for model
1108 checkLive();
1109
1110 // ignore value; determine explanation only on current data
1111 return explainInvalid();
1112}
1113
1115 const css::uno::Reference<css::form::validation::XValidityConstraintListener>& xListener )
1116{
1117 OSL_ENSURE( xListener.is(), "need listener!" );
1118 if( ::std::find(maValidityListeners.begin(), maValidityListeners.end(), xListener)
1119 == maValidityListeners.end() )
1120 maValidityListeners.push_back( xListener );
1121}
1122
1124 const css::uno::Reference<css::form::validation::XValidityConstraintListener>& xListener )
1125{
1126 XValidityConstraintListeners_t::iterator aIter =
1127 ::std::find( maValidityListeners.begin(), maValidityListeners.end(),
1128 xListener );
1129 if( aIter != maValidityListeners.end() )
1130 maValidityListeners.erase( aIter );
1131}
1132
1133
1134// xml::dom::event::XEventListener
1135
1136
1137void Binding::handleEvent( const css::uno::Reference<css::xml::dom::events::XEvent>& xEvent )
1138{
1139 OUString sType(xEvent->getType());
1140 //OUString sEventMIPChanged("xforms-generic");
1141 //if(sType.equals(sEventMIPChanged)) {
1142 if(sType == "xforms-generic") {
1143
1144 // the modification of the 'mnDeferModifyNotifications'-member
1145 // is necessary to prevent infinite notification looping.
1146 // This can happened in case the binding which caused
1147 // the notification chain is listening to those events
1148 // as well...
1149 bool bPreserveValueModified = mbValueModified;
1151 valueModified();
1153 mbValueModified = bPreserveValueModified;
1154 return;
1155 }
1156
1157 // if we're a dynamic binding, we better re-bind, too!
1158 bind();
1159
1160 // our value was maybe modified
1161 valueModified();
1162}
1163
1164
1165// lang::XUnoTunnel
1166
1167
1168sal_Int64 Binding::getSomething( const css::uno::Sequence<sal_Int8>& xId )
1169{
1170 return comphelper::getSomethingImpl(xId, this);
1171}
1172
1173
1174// XCloneable
1175
1176
1177css::uno::Reference<css::util::XCloneable> SAL_CALL Binding::createClone()
1178{
1180
1181 Model* pModel = getModelImpl();
1182 if ( pModel )
1183 xClone = pModel->cloneBinding( this );
1184 else
1185 {
1186 xClone = new Binding;
1187 copy( this, xClone );
1188 }
1189 return css::uno::Reference<css::util::XCloneable>( xClone, UNO_QUERY );
1190}
1191
1192
1193// property set implementations
1194
1196{
1197 registerProperty( css::beans::Property("BindingID", HANDLE_BindingID, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
1199
1200 registerProperty( css::beans::Property("BindingExpression", HANDLE_BindingExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
1202
1203 registerProperty( css::beans::Property("Model", HANDLE_Model, cppu::UnoType<css::uno::Reference<css::xforms::XModel>>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
1204 new DirectPropertyAccessor< Binding, css::uno::Reference<css::xforms::XModel> >(this, nullptr, &Binding::getModel));
1205
1206 registerProperty( css::beans::Property("BindingNamespaces", HANDLE_BindingNamespaces, cppu::UnoType<css::uno::Reference<css::container::XNameContainer>>::get(), css::beans::PropertyAttribute::BOUND ),
1207 new DirectPropertyAccessor< Binding, css::uno::Reference<css::container::XNameContainer> >(this, &Binding::setBindingNamespaces, &Binding::getBindingNamespaces));
1208
1209 registerProperty( css::beans::Property("ModelNamespaces", HANDLE_ModelNamespaces, cppu::UnoType<css::uno::Reference<css::container::XNameContainer>>::get(), css::beans::PropertyAttribute::BOUND ),
1210 new DirectPropertyAccessor< Binding, css::uno::Reference<css::container::XNameContainer> >(this, &Binding::setModelNamespaces, &Binding::getModelNamespaces));
1211
1212 registerProperty( css::beans::Property("ModelID", HANDLE_ModelID, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
1214
1215 registerProperty( css::beans::Property("ReadonlyExpression", HANDLE_ReadonlyExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
1217
1218 registerProperty( css::beans::Property("RelevantExpression", HANDLE_RelevantExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
1220
1221 registerProperty( css::beans::Property("RequiredExpression", HANDLE_RequiredExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
1223
1224 registerProperty( css::beans::Property("ConstraintExpression", HANDLE_ConstraintExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
1226
1227 registerProperty( css::beans::Property("CalculateExpression", HANDLE_CalculateExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
1229
1230 registerProperty( css::beans::Property("Type", HANDLE_Type, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
1232
1233 registerProperty( css::beans::Property("ReadOnly", HANDLE_ReadOnly, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
1235
1236 registerProperty( css::beans::Property("Relevant", HANDLE_Relevant, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
1238
1239 registerProperty( css::beans::Property("ExternalData", HANDLE_ExternalData, cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
1241
1242 initializePropertyValueCache( HANDLE_ReadOnly );
1243 initializePropertyValueCache( HANDLE_Relevant );
1244 initializePropertyValueCache( HANDLE_ExternalData );
1245}
1246
1248 const css::uno::Reference<css::util::XModifyListener>& xListener )
1249{
1250 OSL_ENSURE( xListener.is(), "need listener!" );
1251 if( ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener )
1252 == maModifyListeners.end() )
1253 maModifyListeners.push_back( xListener );
1254
1255 // HACK: currently, we have to 'push' some MIPs to the control
1256 // (read-only, relevant, etc.) To enable this, we need to update
1257 // the control at least once when it registers here.
1258 valueModified();
1259}
1260
1262 const css::uno::Reference<css::util::XModifyListener>& xListener )
1263{
1264 ModifyListeners_t::iterator aIter =
1265 ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener );
1266 if( aIter != maModifyListeners.end() )
1267 maModifyListeners.erase( aIter );
1268}
1269
1270
1272{
1273 return getBindingID();
1274}
1275
1276void SAL_CALL Binding::setName( const OUString& rName )
1277{
1278 // use the XPropertySet methods, so the change in the name is notified to the
1279 // property listeners
1280 setFastPropertyValue( HANDLE_BindingID, Any( rName ) );
1281}
1282
1283/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptionalString sType
static void lcl_addListenerToNode(const Reference< XNode > &xNode, const Reference< XEventListener > &xListener)
Definition: binding.cxx:457
static void lcl_getString(const Reference< XNode > &xNode, OUStringBuffer &rBuffer)
Definition: binding.cxx:1018
#define HANDLE_ExternalData
Definition: binding.cxx:106
#define HANDLE_BindingExpression
Definition: binding.cxx:93
static void lcl_copyNamespaces(const css::uno::Reference< css::container::XNameContainer > &xFrom, css::uno::Reference< css::container::XNameContainer > const &xTo, bool bOverwrite)
copy namespaces from one namespace container into another
Definition: binding.cxx:819
static void lcl_validate(const css::uno::Reference< css::form::validation::XValidityConstraintListener > &xListener, const Reference< XInterface > &xSource)
Definition: binding.cxx:620
#define HANDLE_Relevant
Definition: binding.cxx:104
static void lcl_modified(const css::uno::Reference< css::util::XModifyListener > &xListener, const Reference< XInterface > &xSource)
Definition: binding.cxx:603
#define HANDLE_ModelID
Definition: binding.cxx:95
#define HANDLE_Type
Definition: binding.cxx:102
#define HANDLE_CalculateExpression
Definition: binding.cxx:101
#define HANDLE_ConstraintExpression
Definition: binding.cxx:100
static void lcl_removeOtherNamespaces(const css::uno::Reference< css::container::XNameContainer > &xFrom, css::uno::Reference< css::container::XNameContainer > const &xTo)
Definition: binding.cxx:792
#define HANDLE_ModelNamespaces
Definition: binding.cxx:105
#define HANDLE_ReadOnly
Definition: binding.cxx:103
static void lcl_removeListenerFromNode(const Reference< XNode > &xNode, const Reference< XEventListener > &xListener)
Definition: binding.cxx:476
#define HANDLE_BindingID
Definition: binding.cxx:92
#define HANDLE_BindingNamespaces
Definition: binding.cxx:96
#define HANDLE_RequiredExpression
Definition: binding.cxx:99
#define HANDLE_Model
Definition: binding.cxx:94
static void lcl_listentry(const css::uno::Reference< css::form::binding::XListEntryListener > &xListener, const Reference< XInterface > &xSource)
Definition: binding.cxx:611
#define HANDLE_ReadonlyExpression
Definition: binding.cxx:97
#define HANDLE_RelevantExpression
Definition: binding.cxx:98
helper class for implementing non-UNO accessors to a boolean property
helper class for implementing property accessors via non-UNO methods
const css::uno::Sequence< sal_Int8 > & getSeq() const
bool isSimpleBindingExpression() const
heuristically determine whether this binding's binding expression is simple
Definition: binding.cxx:169
void setRelevantExpression(const OUString &)
get relevant MIP
Definition: binding.cxx:343
void setReadonlyExpression(const OUString &)
get read-only MIP
Definition: binding.cxx:332
OUString getRelevantExpression() const
set read-only MIP
Definition: binding.cxx:338
void update()
update this binding (e.g. called by model for refresh )
Definition: binding.cxx:174
OUString explainInvalid_DataType()
explain validity of binding with respect to the given data type
Definition: binding.cxx:760
virtual void SAL_CALL handleEvent(const css::uno::Reference< css::xml::dom::events::XEvent > &xEvent) override
Definition: binding.cxx:1137
void checkLive()
check whether object is live, and throw suitable exception if not (to be used be API methods before a...
Definition: binding.cxx:440
virtual void SAL_CALL removeValidityConstraintListener(const css::uno::Reference< css::form::validation::XValidityConstraintListener > &xListener) override
Definition: binding.cxx:1123
xforms::EvaluationContext getEvaluationContext() const
get this binding's context node
Definition: binding.cxx:286
PathExpression maBindingExpression
an XPath-expression to be instantiated on the data instance
Definition: binding.hxx:103
void setBindingExpression(const OUString &)
get binding expression
Definition: binding.cxx:321
css::uno::Reference< css::xsd::XDataType > getDataType() const
get the data type that applies to this binding
Definition: binding.cxx:739
bool mbValueModified
Definition: binding.hxx:150
bool isLive() const
determine whether object is live live: has model, and model has been initialized
Definition: binding.cxx:446
void setConstraintExpression(const OUString &)
get constraint MIP
Definition: binding.cxx:365
BoolExpression maRelevant
an XPath-expression to determine relevance
Definition: binding.hxx:109
bool getExternalData() const
Definition: binding.cxx:420
void _setModel(const css::uno::Reference< css::xforms::XModel > &)
get XForms model
Definition: binding.cxx:124
css::uno::Reference< css::container::XNameContainer > getBindingNamespaces() const
set type name MIP (static)
Definition: binding.hxx:202
void valueModified()
the binding value has been changed: trigger a modified event on all modified listeners
Definition: binding.cxx:628
static css::uno::Sequence< sal_Int8 > getUnoTunnelId()
Definition: binding.cxx:304
sal_Int32 mnDeferModifyNotifications
if >0, valueModified() and bindingModified() will only set flags
Definition: binding.hxx:149
bool mbBindingModified
if true, valueModified needs to be called
Definition: binding.hxx:151
XValidityConstraintListeners_t maValidityListeners
validity listeners;
Definition: binding.hxx:136
virtual css::uno::Any SAL_CALL getValue(const css::uno::Type &aType) override
Definition: binding.cxx:961
bool getReadOnly() const
get model nmsp.
Definition: binding.cxx:410
css::uno::Reference< css::xforms::XModel > getModel() const
Definition: binding.hxx:165
OUString getType() const
set calculate MIP
Definition: binding.hxx:194
void _checkBindingID()
set a useful default binding ID (if none is set)
Definition: binding.cxx:925
OUString getBindingExpression() const
set ID for this binding
Definition: binding.cxx:316
void bindingModified()
the binding itself has changed: force rebind, then call valueModified()
Definition: binding.cxx:694
std::vector< xforms::EvaluationContext > _getMIPEvaluationContexts() const
get MIP evaluation contexts (only valid if control has already been bound)
Definition: binding.cxx:495
ModifyListeners_t maModifyListeners
modify listeners
Definition: binding.hxx:130
void setCalculateExpression(const OUString &)
get calculate MIP
Definition: binding.cxx:382
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &xListener) override
Definition: binding.cxx:1247
MIP maMIP
the current MIP object for the first node we are bound to
Definition: binding.hxx:142
bool mbInCalculate
flag to detect recursions in calculate
Definition: binding.hxx:145
bool isUseful() const
determine whether this binding currently performs a useful function, r whether is may be discarded
Definition: binding.cxx:224
virtual void SAL_CALL removeListEntryListener(const css::uno::Reference< css::form::binding::XListEntryListener > &) override
Definition: binding.cxx:1082
virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override
Definition: binding.cxx:1177
void clear()
'clear' this binding - remove all listeners, etc.
Definition: binding.cxx:768
virtual void SAL_CALL setName(const OUString &) override
Definition: binding.cxx:1276
void deferNotifications(bool)
prevent change notifications being sent to controls
Definition: binding.cxx:188
void initializePropertySet()
if true, bindingModified needs to be called
Definition: binding.cxx:1195
BoolExpression maReadonly
an XPath-expression to determine read-only status
Definition: binding.hxx:106
void bind(bool bForceRebind=false)
bind this binding, and pre-compute the affected nodes
Definition: binding.cxx:513
virtual void SAL_CALL addValidityConstraintListener(const css::uno::Reference< css::form::validation::XValidityConstraintListener > &xListener) override
Definition: binding.cxx:1114
OUString msBindingID
binding-ID. A document-wide unique ID for this binding element.
Definition: binding.hxx:100
css::uno::Reference< css::xml::dom::XNodeList > getXNodeList()
get nodeset the bind is bound to
Definition: binding.cxx:150
void setBindingID(const OUString &)
get ID for this binding
Definition: binding.cxx:311
OUString getConstraintExpression() const
set required MIP
Definition: binding.cxx:360
OUString msTypeName
a type name
Definition: binding.hxx:127
virtual void SAL_CALL setValue(const css::uno::Any &aValue) override
Definition: binding.cxx:981
void distributeMIP(const css::uno::Reference< css::xml::dom::XNode > &rxNode)
distribute MIPs from current node recursively to children
Definition: binding.cxx:668
bool getRelevant() const
Definition: binding.cxx:415
xforms::Model * getModelImpl() const
get the model implementation
Definition: binding.cxx:452
bool isSimpleBinding() const
heuristically determine whether this binding is simple binding (here: simple binding == does not depe...
Definition: binding.cxx:159
void setType(const OUString &)
get type name MIP (static)
Definition: binding.cxx:389
virtual ~Binding() override
Definition: binding.cxx:119
ComputedExpression maCalculate
an XPath-expression to calculate values
Definition: binding.hxx:121
css::uno::Reference< css::container::XNameContainer > mxNamespaces
the XML namespaces used for XML names/XPath-expressions in this binding
Definition: binding.hxx:124
void setRequiredExpression(const OUString &)
get required MIP
Definition: binding.cxx:354
void setBindingNamespaces(const css::uno::Reference< css::container::XNameContainer > &)
Definition: binding.cxx:395
OUString getBindingID() const
get ID of XForms model
Definition: binding.hxx:171
BoolExpression maRequired
an XPath-expression to determine if item is required
Definition: binding.hxx:112
OUString getCalculateExpression() const
set constraint MIP
Definition: binding.cxx:377
virtual sal_Int32 SAL_CALL getListEntryCount() override
Definition: binding.cxx:1009
css::uno::Reference< css::xforms::XModel > mxModel
the Model to which this Binding belongs; may be NULL
Definition: binding.hxx:97
virtual sal_Bool SAL_CALL supportsType(const css::uno::Type &aType) override
Definition: binding.cxx:956
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getSupportedValueTypes() override
Definition: binding.cxx:951
std::vector< xforms::EvaluationContext > getMIPEvaluationContexts()
get evaluation contexts for this binding's MIPs
Definition: binding.cxx:294
BoolExpression maConstraint
an XPath-expression to determine if item is valid
Definition: binding.hxx:115
std::vector< css::uno::Reference< css::xml::dom::XNode > > maEventNodes
nodes on which we are listening for events
Definition: binding.hxx:139
void setModelNamespaces(const css::uno::Reference< css::container::XNameContainer > &)
set model namespaces
Definition: binding.cxx:405
virtual OUString SAL_CALL getListEntry(sal_Int32 nPosition) override
Definition: binding.cxx:1043
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &xListener) override
Definition: binding.cxx:1261
css::uno::Reference< css::container::XNameContainer > _getNamespaces() const
implement get*Namespaces()
Definition: binding.cxx:856
virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence< sal_Int8 > &) override
Definition: binding.cxx:1168
virtual void SAL_CALL addListEntryListener(const css::uno::Reference< css::form::binding::XListEntryListener > &) override
Definition: binding.cxx:1072
OUString getRequiredExpression() const
set relevant MIP
Definition: binding.cxx:349
void _setNamespaces(const css::uno::Reference< css::container::XNameContainer > &, bool bBinding)
implement set*Namespaces()
Definition: binding.cxx:871
XListEntryListeners_t maListEntryListeners
list entry listener
Definition: binding.hxx:133
virtual OUString SAL_CALL getName() override
Definition: binding.cxx:1271
bool isValid_DataType() const
determine whether binding is valid according to the given data type
Definition: binding.cxx:753
MIP getLocalMIP() const
set MIPs defined by this binding on MIP item
Definition: binding.cxx:714
OUString getModelID() const
set XForms model (only called by Model)
Definition: binding.cxx:143
OUString msExplainConstraint
user-readable explanation of the constraint
Definition: binding.hxx:118
bool isValid() const
is this binding valid? (are constraint, type and required MIPs ok?)
Definition: binding.cxx:206
OUString getReadonlyExpression() const
set binding exp.
Definition: binding.cxx:327
virtual css::uno::Sequence< OUString > SAL_CALL getAllListEntries() override
Definition: binding.cxx:1055
OUString explainInvalid()
explain why binding is invalid
Definition: binding.cxx:249
css::uno::Reference< css::container::XNameContainer > getModelNamespaces() const
get binding nmsp.
Definition: binding.cxx:400
void setExpression(const OUString &rExpression)
set the expression string (overridden for new definition of a simple expression)
bool isSimpleExpression() const
heuristically determine whether this expression is 'simple', i.e.
const OUString & getExpression() const
get the expression string
bool isEmptyExpression() const
do we have an actual expression?
bool getBool(bool bDefault=false) const
bool hasValue() const
does this expression have a value?
void clear()
remove value/evaluate results
bool evaluate(const xforms::EvaluationContext &rContext)
evaluate the expression relative to the content node.
void setExpression(const OUString &rExpression)
set a new expression string
css::uno::Sequence< css::uno::Type > getTypes() const
get list of convertible types
Definition: convert.cxx:286
bool hasType(const css::uno::Type &)
can we convert this type?
Definition: convert.cxx:281
static Convert & get()
get/create Singleton class
Definition: convert.cxx:274
css::uno::Any toAny(const OUString &, const css::uno::Type &)
convert XML representation to Any of given type
Definition: convert.cxx:297
OUString toXSD(const css::uno::Any &rAny)
convert any to XML representation
Definition: convert.cxx:291
define the context for the evaluation of an XPath expression
css::uno::Reference< css::xml::dom::XNode > mxContextNode
css::uno::Reference< css::container::XNameContainer > mxNamespaces
represents the XForms *m*odel *i*tem *p*roperties (MIPs) for a given XNode in the instance data at a ...
Definition: mip.hxx:31
void setConstraintExplanation(const OUString &)
Definition: mip.cxx:89
const OUString & getConstraintExplanation() const
Definition: mip.hxx:88
bool isRelevant() const
Definition: mip.hxx:77
const OUString & getTypeName() const
Definition: mip.hxx:62
bool isRequired() const
Definition: mip.hxx:72
void setTypeName(const OUString &)
Definition: mip.cxx:93
void setRelevant(bool)
Definition: mip.cxx:83
void setConstraint(bool)
Definition: mip.cxx:86
void setHasCalculate(bool)
Definition: mip.cxx:91
void setRequired(bool)
Definition: mip.cxx:80
bool isConstraint() const
Definition: mip.hxx:82
bool isReadonly() const
Definition: mip.cxx:76
void setReadonly(bool)
Definition: mip.cxx:77
xforms::EvaluationContext getEvaluationContext()
Definition: model.cxx:109
bool setSimpleContent(const XNode_t &, const OUString &)
set a data value in the instance (also defers notifications)
Definition: model.cxx:245
css::uno::Reference< css::container::XNameContainer > getNamespaces() const
Definition: model.hxx:124
bool isInitialized() const
has model been initialized?
Definition: model.hxx:165
void removeMIPs(void const *pTag)
Definition: model.cxx:175
virtual OUString SAL_CALL getID() override
Definition: model.cxx:372
void addMIP(void *pTag, const XNode_t &, const MIP &)
Definition: model.cxx:166
virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL cloneBinding(const css::uno::Reference< css::beans::XPropertySet > &) override
Definition: model.cxx:491
MIP queryMIP(const XNode_t &xNode) const
query which MIPs apply to the given node
Definition: model.cxx:191
std::vector< css::uno::Reference< css::xml::dom::XNode > > NodeVector_t
css::uno::Reference< css::xml::dom::XNodeList > getXNodeList() const
void setExpression(const OUString &rExpression)
set the expression string (overridden to do remove old listeners) (also defines simple expressions)
const NodeVector_t & getNodeList() const
void evaluate(const xforms::EvaluationContext &rContext)
evaluate the expression relative to the content node.
css::uno::Reference< css::xml::dom::XNode > getNode() const
#define DBG_UNHANDLED_EXCEPTION(...)
Reference< XInterface > xTarget
OUString sName
sal_Int64 n
@ Exception
class SAL_NO_VTABLE XPropertySet
sal_Int64 getSomethingImpl(const css::uno::Sequence< sal_Int8 > &rId, T *pThis, FallbackToGetSomethingOf< Base >={})
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
void copy(const css::uno::Reference< css::beans::XPropertySet > &, css::uno::Reference< css::beans::XPropertySet > const &)
copy the properties from one PropertySet into the next
OUString getResource(TranslateId pResourceId)
get a resource string for the current language
a helper class for notifying property changes in a <type>PropertySetBase</type> instance.
Reference< XModel > xModel
unsigned char sal_Bool
Any result
std::unique_ptr< char[]> aBuffer
bool isValidQName(const OUString &sName, const Reference< XNameContainer > &)
Definition: xmlhelper.cxx:85