summaryrefslogtreecommitdiff
path: root/forms/source/xforms/binding.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'forms/source/xforms/binding.cxx')
-rw-r--r--forms/source/xforms/binding.cxx183
1 files changed, 96 insertions, 87 deletions
diff --git a/forms/source/xforms/binding.cxx b/forms/source/xforms/binding.cxx
index 6d8735f6366c..c739126642c4 100644
--- a/forms/source/xforms/binding.cxx
+++ b/forms/source/xforms/binding.cxx
@@ -31,9 +31,10 @@
#include <strings.hrc>
#include <rtl/ustrbuf.hxx>
+#include <o3tl/safeint.hxx>
#include <osl/diagnose.h>
-#include <tools/diagnose_ex.h>
+#include <comphelper/diagnose_ex.hxx>
#include <algorithm>
#include <functional>
@@ -70,7 +71,6 @@ using com::sun::star::form::binding::InvalidBindingStateException;
using com::sun::star::form::binding::XValueBinding;
using com::sun::star::lang::EventObject;
using com::sun::star::lang::IndexOutOfBoundsException;
-using com::sun::star::lang::XUnoTunnel;
using com::sun::star::uno::Any;
using com::sun::star::uno::Reference;
using com::sun::star::uno::RuntimeException;
@@ -79,7 +79,6 @@ using com::sun::star::uno::UNO_QUERY;
using com::sun::star::uno::UNO_QUERY_THROW;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Exception;
-using com::sun::star::uno::makeAny;
using com::sun::star::util::XModifyListener;
using com::sun::star::xforms::XDataTypeRepository;
using com::sun::star::xml::dom::NodeType_ATTRIBUTE_NODE;
@@ -90,9 +89,6 @@ using com::sun::star::xml::dom::events::XEventListener;
using com::sun::star::xml::dom::events::XEventTarget;
using com::sun::star::xsd::XDataType;
-
-#define EXCEPT(msg) msg,static_cast<XValueBinding*>(this)
-
#define HANDLE_BindingID 0
#define HANDLE_BindingExpression 1
#define HANDLE_Model 2
@@ -125,7 +121,7 @@ Binding::~Binding()
_setModel(nullptr);
}
-void Binding::_setModel( const css::uno::Reference<css::xforms::XModel>& xModel )
+void Binding::_setModel( const rtl::Reference<Model>& xModel )
{
PropertyChangeNotifier aNotifyModelChange( *this, HANDLE_Model );
PropertyChangeNotifier aNotifyModelIDChange( *this, HANDLE_ModelID );
@@ -146,8 +142,7 @@ void Binding::_setModel( const css::uno::Reference<css::xforms::XModel>& xModel
OUString Binding::getModelID() const
{
- Model* pModel = getModelImpl();
- return ( pModel == nullptr ) ? OUString() : pModel->getID();
+ return ( mxModel == nullptr ) ? OUString() : mxModel->getID();
}
@@ -211,7 +206,14 @@ bool Binding::isValid() const
{
// TODO: determine whether node is suitable, not just whether it exists
return maBindingExpression.getNode().is() &&
- isValid_DataType() &&
+ (
+ // tdf#155121, validity rules should be apply when field is required or
+ // when the field is not required but not empty
+ // so if the field is not required and empty, do not check validity
+ (! maMIP.isRequired() && maBindingExpression.hasValue()
+ && maBindingExpression.getString().isEmpty() ) ||
+ isValid_DataType()
+ ) &&
maMIP.isConstraint() &&
( ! maMIP.isRequired() ||
( maBindingExpression.hasValue() &&
@@ -228,7 +230,7 @@ bool Binding::isUseful() const
// 3) we are bound to some control
// (this can be assumed if some listeners are set)
bool bUseful =
- getModelImpl() == nullptr
+ mxModel == nullptr
// || msBindingID.getLength() > 0
|| ! msTypeName.isEmpty()
|| ! maReadonly.isEmptyExpression()
@@ -282,15 +284,15 @@ OUString Binding::explainInvalid()
EvaluationContext Binding::getEvaluationContext() const
{
- OSL_ENSURE( getModelImpl() != nullptr, "need model impl" );
- EvaluationContext aContext = getModelImpl()->getEvaluationContext();
+ OSL_ENSURE( mxModel != nullptr, "need model impl" );
+ EvaluationContext aContext = mxModel->getEvaluationContext();
aContext.mxNamespaces = getBindingNamespaces();
return aContext;
}
::std::vector<EvaluationContext> Binding::getMIPEvaluationContexts()
{
- OSL_ENSURE( getModelImpl() != nullptr, "need model impl" );
+ OSL_ENSURE( mxModel != nullptr, "need model impl" );
// bind (in case we were not bound before)
bind();
@@ -422,9 +424,8 @@ bool Binding::getExternalData() const
try
{
- Reference< XPropertySet > xModelProps( mxModel, UNO_QUERY_THROW );
OSL_VERIFY(
- xModelProps->getPropertyValue( "ExternalData" ) >>= bExternalData );
+ mxModel->getPropertyValue( "ExternalData" ) >>= bExternalData );
}
catch( const Exception& )
{
@@ -437,19 +438,14 @@ bool Binding::getExternalData() const
void Binding::checkLive()
{
if( ! isLive() )
- throw RuntimeException( EXCEPT("Binding not initialized") );
+ throw RuntimeException("Binding not initialized", static_cast<XValueBinding*>(this));
}
bool Binding::isLive() const
{
- const Model* pModel = getModelImpl();
- return pModel && pModel->isInitialized();
+ return mxModel && mxModel->isInitialized();
}
-Model* Binding::getModelImpl() const
-{
- return comphelper::getFromUnoTunnel<Model>( mxModel );
-}
static void lcl_addListenerToNode( const Reference<XNode>& xNode,
const Reference<XEventListener>& xListener )
@@ -466,8 +462,6 @@ static void lcl_addListenerToNode( const Reference<XNode>& xNode,
xListener, false );
xTarget->addEventListener( "DOMAttrModified",
xListener, true );
- xTarget->addEventListener( "DOMAttrModified",
- xListener, true );
xTarget->addEventListener( "xforms-generic",
xListener, true );
}
@@ -493,7 +487,7 @@ static void lcl_removeListenerFromNode( const Reference<XNode>& xNode,
::std::vector<EvaluationContext> Binding::_getMIPEvaluationContexts() const
{
- OSL_ENSURE( getModelImpl() != nullptr, "need model impl" );
+ OSL_ENSURE( mxModel != nullptr, "need model impl" );
// iterate over nodes of bind expression and create
// EvaluationContext for each
@@ -504,7 +498,7 @@ static void lcl_removeListenerFromNode( const Reference<XNode>& xNode,
OSL_ENSURE( node.is(), "no node?" );
// create proper evaluation context for this MIP
- aVector.emplace_back( node, getModel(), getBindingNamespaces() );
+ aVector.emplace_back( node, mxModel, getBindingNamespaces() );
}
return aVector;
}
@@ -512,7 +506,7 @@ static void lcl_removeListenerFromNode( const Reference<XNode>& xNode,
void Binding::bind( bool bForceRebind )
{
if( ! mxModel.is() )
- throw RuntimeException( EXCEPT("Binding has no Model") );
+ throw RuntimeException("Binding has no Model", static_cast<XValueBinding*>(this));
// bind() will evaluate this binding as follows:
// 1) evaluate the binding expression
@@ -561,9 +555,8 @@ void Binding::bind( bool bForceRebind )
}
// 3) remove old MIPs defined by this binding
- Model* pModel = getModelImpl();
- OSL_ENSURE( pModel != nullptr, "need model" );
- pModel->removeMIPs( this );
+ OSL_ENSURE( mxModel != nullptr, "need model" );
+ mxModel->removeMIPs( this );
// 4) calculate all MIPs
::std::vector<EvaluationContext> aMIPContexts = _getMIPEvaluationContexts();
@@ -579,7 +572,7 @@ void Binding::bind( bool bForceRebind )
{
mbInCalculate = true;
maCalculate.evaluate( rContext );
- pModel->setSimpleContent( rContext.mxContextNode,
+ mxModel->setSimpleContent( rContext.mxContextNode,
maCalculate.getString() );
mbInCalculate = false;
}
@@ -593,7 +586,7 @@ void Binding::bind( bool bForceRebind )
// type is static; does not need updating
// evaluate the locally defined MIPs, and push them to the model
- pModel->addMIP( this, rContext.mxContextNode, getLocalMIP() );
+ mxModel->addMIP( this, rContext.mxContextNode, getLocalMIP() );
}
}
@@ -636,7 +629,7 @@ void Binding::valueModified()
// query MIP used by our first node (also note validity)
Reference<XNode> xNode = maBindingExpression.getNode();
- maMIP = getModelImpl()->queryMIP( xNode );
+ maMIP = mxModel->queryMIP( xNode );
// distribute MIPs _used_ by this binding
if( xNode.is() )
@@ -737,11 +730,11 @@ MIP Binding::getLocalMIP() const
css::uno::Reference<css::xsd::XDataType> Binding::getDataType() const
{
- OSL_ENSURE( getModel().is(), "need model" );
- OSL_ENSURE( getModel()->getDataTypeRepository().is(), "need types" );
+ OSL_ENSURE( mxModel.is(), "need model" );
+ OSL_ENSURE( mxModel->getDataTypeRepository().is(), "need types" );
Reference<XDataTypeRepository> xRepository =
- getModel()->getDataTypeRepository();
+ mxModel->getDataTypeRepository();
OUString sTypeName = maMIP.getTypeName();
return ( xRepository.is() && xRepository->hasByName( sTypeName ) )
@@ -767,9 +760,8 @@ OUString Binding::explainInvalid_DataType()
void Binding::clear()
{
// remove MIPs contributed by this binding
- Model* pModel = getModelImpl();
- if( pModel != nullptr )
- pModel->removeMIPs( this );
+ if( mxModel != nullptr )
+ mxModel->removeMIPs( this );
// remove all references
for (auto const& eventNode : maEventNodes)
@@ -858,9 +850,8 @@ css::uno::Reference<css::container::XNameContainer> Binding::_getNamespaces() co
lcl_copyNamespaces( mxNamespaces, xNamespaces, true );
// merge model's with binding's own namespaces
- Model* pModel = getModelImpl();
- if( pModel != nullptr )
- lcl_copyNamespaces( pModel->getNamespaces(), xNamespaces, false );
+ if( mxModel != nullptr )
+ lcl_copyNamespaces( mxModel->getNamespaces(), xNamespaces, false );
return xNamespaces;
}
@@ -870,11 +861,10 @@ css::uno::Reference<css::container::XNameContainer> Binding::_getNamespaces() co
void Binding::_setNamespaces( const css::uno::Reference<css::container::XNameContainer>& rNamespaces,
bool bBinding )
{
- Model* pModel = getModelImpl();
- css::uno::Reference<css::container::XNameContainer> xModelNamespaces = ( pModel != nullptr )
- ? pModel->getNamespaces()
+ css::uno::Reference<css::container::XNameContainer> xModelNamespaces = ( mxModel != nullptr )
+ ? mxModel->getNamespaces()
: nullptr;
- OSL_ENSURE( ( pModel != nullptr ) == xModelNamespaces.is(), "no model nmsp?");
+ OSL_ENSURE( ( mxModel != nullptr ) == xModelNamespaces.is(), "no model nmsp?");
// remove deleted namespaces
lcl_removeOtherNamespaces( rNamespaces, mxNamespaces );
@@ -923,10 +913,10 @@ void Binding::_setNamespaces( const css::uno::Reference<css::container::XNameCon
void Binding::_checkBindingID()
{
- if( !getModel().is() )
+ if( !mxModel.is() )
return;
- Reference<XNameAccess> xBindings( getModel()->getBindings(), UNO_QUERY_THROW );
+ Reference<XNameAccess> xBindings( mxModel->getBindings(), UNO_QUERY_THROW );
if( !msBindingID.isEmpty() )
return;
@@ -964,7 +954,7 @@ css::uno::Any Binding::getValue( const css::uno::Type& rType )
// second, check for type
if( ! supportsType( rType ) )
- throw IncompatibleTypesException( EXCEPT( "type unsupported" ) );
+ throw IncompatibleTypesException("type unsupported", static_cast<XValueBinding*>(this));
// return string value (if present; else return empty Any)
css::uno::Any result;
@@ -984,19 +974,19 @@ void Binding::setValue( const css::uno::Any& aValue )
// check for supported type
if( ! supportsType( aValue.getValueType() ) )
- throw IncompatibleTypesException( EXCEPT( "type unsupported" ) );
+ throw IncompatibleTypesException("type unsupported", static_cast<XValueBinding*>(this));
if( !maBindingExpression.hasValue() )
- throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) );
+ throw InvalidBindingStateException("no suitable node found", static_cast<XValueBinding*>(this));
css::uno::Reference<css::xml::dom::XNode> xNode = maBindingExpression.getNode();
if( !xNode.is() )
- throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) );
+ throw InvalidBindingStateException("no suitable node found", static_cast<XValueBinding*>(this));
OUString sValue = Convert::get().toXSD( aValue );
- bool bSuccess = getModelImpl()->setSimpleContent( xNode, sValue );
+ bool bSuccess = mxModel->setSimpleContent( xNode, sValue );
if( ! bSuccess )
- throw InvalidBindingStateException( EXCEPT( "can't set value" ) );
+ throw InvalidBindingStateException("can't set value", static_cast<XValueBinding*>(this));
}
@@ -1046,8 +1036,8 @@ OUString Binding::getListEntry( sal_Int32 nPosition )
// check bounds and return proper item
PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList();
- if( nPosition < 0 || nPosition >= static_cast<sal_Int32>( aNodes.size() ) )
- throw IndexOutOfBoundsException( EXCEPT("") );
+ if( nPosition < 0 || o3tl::make_unsigned(nPosition) >= aNodes.size() )
+ throw IndexOutOfBoundsException("", static_cast<XValueBinding*>(this));
return lcl_getString( aNodes[ nPosition ] );
}
@@ -1177,9 +1167,8 @@ css::uno::Reference<css::util::XCloneable> SAL_CALL Binding::createClone()
{
Reference< XPropertySet > xClone;
- Model* pModel = getModelImpl();
- if ( pModel )
- xClone = pModel->cloneBinding( this );
+ if ( mxModel )
+ xClone = mxModel->cloneBinding( this );
else
{
xClone = new Binding;
@@ -1188,39 +1177,59 @@ css::uno::Reference<css::util::XCloneable> SAL_CALL Binding::createClone()
return css::uno::Reference<css::util::XCloneable>( xClone, UNO_QUERY );
}
+css::uno::Reference<css::xforms::XModel> Binding::getModel() const
+{
+ return mxModel;
+}
// property set implementations
+void Binding::initializePropertySet()
+{
+ registerProperty( css::beans::Property("BindingID", HANDLE_BindingID, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, OUString >(this, &Binding::setBindingID, &Binding::getBindingID));
-#define REGISTER_PROPERTY( property, type ) \
- registerProperty( PROPERTY( property, type ), \
- new DirectPropertyAccessor< Binding, type >( this, &Binding::set##property, &Binding::get##property ) );
+ registerProperty( css::beans::Property("BindingExpression", HANDLE_BindingExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, OUString >(this, &Binding::setBindingExpression, &Binding::getBindingExpression));
-#define REGISTER_PROPERTY_RO( property, type ) \
- registerProperty( PROPERTY_RO( property, type ), \
- new DirectPropertyAccessor< Binding, type >( this, nullptr, &Binding::get##property ) );
+ registerProperty( css::beans::Property("Model", HANDLE_Model, cppu::UnoType<css::uno::Reference<css::xforms::XModel>>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
+ new DirectPropertyAccessor< Binding, css::uno::Reference<css::xforms::XModel> >(this, nullptr, &Binding::getModel));
-#define REGISTER_BOOL_PROPERTY_RO( property ) \
- registerProperty( PROPERTY_RO( property, sal_Bool ), \
- new BooleanPropertyAccessor< Binding >( this, nullptr, &Binding::get##property ) );
+ registerProperty( css::beans::Property("BindingNamespaces", HANDLE_BindingNamespaces, cppu::UnoType<css::uno::Reference<css::container::XNameContainer>>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, css::uno::Reference<css::container::XNameContainer> >(this, &Binding::setBindingNamespaces, &Binding::getBindingNamespaces));
-void Binding::initializePropertySet()
-{
- REGISTER_PROPERTY ( BindingID, OUString );
- REGISTER_PROPERTY ( BindingExpression, OUString );
- REGISTER_PROPERTY_RO ( Model, css::uno::Reference<css::xforms::XModel> );
- REGISTER_PROPERTY ( BindingNamespaces, css::uno::Reference<css::container::XNameContainer> );
- REGISTER_PROPERTY ( ModelNamespaces, css::uno::Reference<css::container::XNameContainer> );
- REGISTER_PROPERTY_RO ( ModelID, OUString );
- REGISTER_PROPERTY ( ReadonlyExpression, OUString );
- REGISTER_PROPERTY ( RelevantExpression, OUString );
- REGISTER_PROPERTY ( RequiredExpression, OUString );
- REGISTER_PROPERTY ( ConstraintExpression, OUString );
- REGISTER_PROPERTY ( CalculateExpression, OUString );
- REGISTER_PROPERTY ( Type, OUString );
- REGISTER_PROPERTY_RO ( ReadOnly, bool );
- REGISTER_PROPERTY_RO ( Relevant, bool );
- REGISTER_BOOL_PROPERTY_RO( ExternalData );
+ registerProperty( css::beans::Property("ModelNamespaces", HANDLE_ModelNamespaces, cppu::UnoType<css::uno::Reference<css::container::XNameContainer>>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, css::uno::Reference<css::container::XNameContainer> >(this, &Binding::setModelNamespaces, &Binding::getModelNamespaces));
+
+ registerProperty( css::beans::Property("ModelID", HANDLE_ModelID, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
+ new DirectPropertyAccessor< Binding, OUString >(this, nullptr, &Binding::getModelID));
+
+ registerProperty( css::beans::Property("ReadonlyExpression", HANDLE_ReadonlyExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, OUString >(this, &Binding::setReadonlyExpression, &Binding::getReadonlyExpression));
+
+ registerProperty( css::beans::Property("RelevantExpression", HANDLE_RelevantExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, OUString >(this, &Binding::setRelevantExpression, &Binding::getRelevantExpression));
+
+ registerProperty( css::beans::Property("RequiredExpression", HANDLE_RequiredExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, OUString >(this, &Binding::setRequiredExpression, &Binding::getRequiredExpression));
+
+ registerProperty( css::beans::Property("ConstraintExpression", HANDLE_ConstraintExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, OUString >(this, &Binding::setConstraintExpression, &Binding::getConstraintExpression));
+
+ registerProperty( css::beans::Property("CalculateExpression", HANDLE_CalculateExpression, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, OUString >(this, &Binding::setCalculateExpression, &Binding::getCalculateExpression));
+
+ registerProperty( css::beans::Property("Type", HANDLE_Type, cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::BOUND ),
+ new DirectPropertyAccessor< Binding, OUString >(this, &Binding::setType, &Binding::getType));
+
+ registerProperty( css::beans::Property("ReadOnly", HANDLE_ReadOnly, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
+ new DirectPropertyAccessor< Binding, bool >(this, nullptr, &Binding::getReadOnly));
+
+ registerProperty( css::beans::Property("Relevant", HANDLE_Relevant, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
+ new DirectPropertyAccessor< Binding, bool >(this, nullptr, &Binding::getRelevant));
+
+ registerProperty( css::beans::Property("ExternalData", HANDLE_ExternalData, cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::BOUND | css::beans::PropertyAttribute::READONLY ),
+ new BooleanPropertyAccessor< Binding >(this, nullptr, &Binding::getExternalData));
initializePropertyValueCache( HANDLE_ReadOnly );
initializePropertyValueCache( HANDLE_Relevant );
@@ -1260,7 +1269,7 @@ void SAL_CALL Binding::setName( const OUString& rName )
{
// use the XPropertySet methods, so the change in the name is notified to the
// property listeners
- setFastPropertyValue( HANDLE_BindingID, makeAny( rName ) );
+ setFastPropertyValue( HANDLE_BindingID, Any( rName ) );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */