/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_forms.hxx"

#include "binding.hxx"

#include "model.hxx"
#include "unohelper.hxx"
#include "NameContainer.hxx"
#include "evaluationcontext.hxx"
#include "convert.hxx"
#include "resourcehelper.hxx"
#include "xmlhelper.hxx"
#include "xformsevent.hxx"

#include <rtl/ustrbuf.hxx>
#include <osl/diagnose.h>

#include <tools/diagnose_ex.h>

#include <algorithm>
#include <functional>

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/xml/dom/XNodeList.hpp>
#include <com/sun/star/xml/dom/XNode.hpp>
#include <com/sun/star/xml/dom/XDocument.hpp>
#include <com/sun/star/xml/dom/XElement.hpp>
#include <com/sun/star/xml/dom/NodeType.hpp>
#include <com/sun/star/xml/dom/events/XEventTarget.hpp>
#include <com/sun/star/xml/dom/events/XEventListener.hpp>
#include <com/sun/star/xml/dom/events/XDocumentEvent.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <com/sun/star/container/XSet.hpp>
#include <com/sun/star/container/XNameContainer.hpp>

#include <comphelper/propertysetinfo.hxx>
#include <unotools/textsearch.hxx>
#include <cppuhelper/typeprovider.hxx>

using namespace com::sun::star::xml::xpath;
using namespace com::sun::star::xml::dom::events;

using rtl::OUString;
using rtl::OUStringBuffer;
using std::vector;
using xforms::Binding;
using xforms::MIP;
using xforms::Model;
using xforms::getResource;
using xforms::EvaluationContext;
using com::sun::star::beans::PropertyVetoException;
using com::sun::star::beans::UnknownPropertyException;
using com::sun::star::beans::XPropertySet;
using com::sun::star::container::XSet;
using com::sun::star::container::XNameAccess;
using com::sun::star::form::binding::IncompatibleTypesException;
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::IllegalArgumentException;
using com::sun::star::lang::IndexOutOfBoundsException;
using com::sun::star::lang::NoSupportException;
using com::sun::star::lang::NullPointerException;
using com::sun::star::lang::WrappedTargetException;
using com::sun::star::lang::XUnoTunnel;
using com::sun::star::uno::Any;
using com::sun::star::uno::Reference;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::Sequence;
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;
using com::sun::star::xml::dom::NodeType_TEXT_NODE;
using com::sun::star::xml::dom::XNode;
using com::sun::star::xml::dom::XNodeList;
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) OUSTRING(msg),static_cast<XValueBinding*>(this)

#define HANDLE_BindingID 0
#define HANDLE_BindingExpression 1
#define HANDLE_Model 2
#define HANDLE_ModelID 3
#define HANDLE_BindingNamespaces 4
#define HANDLE_ReadonlyExpression 5
#define HANDLE_RelevantExpression 6
#define HANDLE_RequiredExpression 7
#define HANDLE_ConstraintExpression 8
#define HANDLE_CalculateExpression 9
#define HANDLE_Type 10
#define HANDLE_ReadOnly 11  // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control
#define HANDLE_Relevant 12  // from com.sun.star.form.binding.ValueBinding, for interaction with a bound form control
#define HANDLE_ModelNamespaces 13
#define HANDLE_ExternalData 14


Binding::Binding() :
    mxModel(),
    msBindingID(),
    maBindingExpression(),
    maReadonly(),
    mxNamespaces( new NameContainer<OUString>() ),
    mbInCalculate( false ),
    mnDeferModifyNotifications( 0 ),
    mbValueModified( false ),
    mbBindingModified( false )

{
    initializePropertySet();
}

Binding::~Binding() throw()
{
	_setModel(NULL);
}


Binding::Model_t Binding::getModel() const
{
    return mxModel;
}

void Binding::_setModel( const Model_t& xModel )
{
    PropertyChangeNotifier aNotifyModelChange( *this, HANDLE_Model );
    PropertyChangeNotifier aNotifyModelIDChange( *this, HANDLE_ModelID );

    // prepare binding for removal of old model
    clear(); // remove all cached data (e.g. XPath evaluation results)
    XNameContainer_t xNamespaces = getModelNamespaces(); // save namespaces

    mxModel = xModel;

    // set namespaces (and move to model, if appropriate)
    setBindingNamespaces( xNamespaces );
    _checkBindingID();

    notifyAndCachePropertyValue( HANDLE_ExternalData );
}


OUString Binding::getModelID() const
{
    Model* pModel = getModelImpl();
    return ( pModel == NULL ) ? OUString() : pModel->getID();
}


Binding::XNodeList_t Binding::getXNodeList()
{
    // first make sure we are bound
    if( ! maBindingExpression.hasValue() )
        bind( sal_False );

    return maBindingExpression.getXNodeList();
}

bool Binding::isSimpleBinding() const
{
    return maBindingExpression.isSimpleExpression()
        && maReadonly.isSimpleExpression()
        && maRelevant.isSimpleExpression()
        && maRequired.isSimpleExpression()
        && maConstraint.isSimpleExpression()
        && maCalculate.isSimpleExpression();
}

bool Binding::isSimpleBindingExpression() const
{
    return maBindingExpression.isSimpleExpression();
}

void Binding::update()
{
    // clear all expressions (to remove cached node references)
    maBindingExpression.clear();
    maReadonly.clear();
    maRelevant.clear();
    maRequired.clear();
    maConstraint.clear();
    maCalculate.clear();

    // let's just pretend the binding has been modified -> full rebind()
    bindingModified();
}

void Binding::deferNotifications( bool bDefer )
{
    mnDeferModifyNotifications += ( bDefer ? 1 : -1 );
    OSL_ENSURE( mnDeferModifyNotifications >= 0, "you're deferring too much" );

    if( mnDeferModifyNotifications == 0 )
    {
        if( mbBindingModified )
            bindingModified();
        if( mbValueModified )
            valueModified();
    }

    OSL_ENSURE( ( mnDeferModifyNotifications > 0 )
                || ( ! mbBindingModified  &&  ! mbValueModified ),
                "deferred modifications not delivered?" );
}

bool Binding::isValid()
{
    // TODO: determine whether node is suitable, not just whether it exists
    return maBindingExpression.getNode().is() &&
        isValid_DataType() &&
        maMIP.isConstraint() &&
        ( ! maMIP.isRequired() ||
             ( maBindingExpression.hasValue() && 
               maBindingExpression.getString().getLength() > 0 ) );
}

bool Binding::isUseful()
{
    // we are useful, if
    // 0) we don't have a model
    //    (at least, in this case we shouldn't be removed from the model)
    // 1) we have a proper name
    // 2) we have some MIPs,
    // 3) we are bound to some control
    //    (this can be assumed if some listeners are set)
    bool bUseful =
        getModelImpl() == NULL
//        || msBindingID.getLength() > 0
        || msTypeName.getLength() > 0
        || ! maReadonly.isEmptyExpression()
        || ! maRelevant.isEmptyExpression()
        || ! maRequired.isEmptyExpression()
        || ! maConstraint.isEmptyExpression()
        || ! maCalculate.isEmptyExpression()
        || ! maModifyListeners.empty()
        || ! maListEntryListeners.empty()
        || ! maValidityListeners.empty();

    return bUseful;
}

OUString Binding::explainInvalid()
{
    OUString sReason;
    if( ! maBindingExpression.getNode().is() )
    {
        sReason = ( maBindingExpression.getExpression().getLength() == 0 )
            ? getResource( RID_STR_XFORMS_NO_BINDING_EXPRESSION )
            : getResource( RID_STR_XFORMS_INVALID_BINDING_EXPRESSION );
    }
    else if( ! isValid_DataType() )
    {
        sReason = explainInvalid_DataType();
        if( sReason.getLength() == 0 )
        {
            // no explanation given by data type? Then give generic message
            sReason = getResource( RID_STR_XFORMS_INVALID_VALUE, 
                                   maMIP.getTypeName() );
        }
    }
    else if( ! maMIP.isConstraint() )
    {
        sReason = maMIP.getConstraintExplanation();
    }
    else if( maMIP.isRequired() && maBindingExpression.hasValue() && 
        ( maBindingExpression.getString().getLength() == 0 )  )
    {
        sReason = getResource( RID_STR_XFORMS_REQUIRED );
    }
    // else: no explanation given; should only happen if data is valid

    OSL_ENSURE( ( sReason.getLength() == 0 ) == isValid(),
                "invalid data should have an explanation!" );

    return sReason;
}



EvaluationContext Binding::getEvaluationContext() const
{
    OSL_ENSURE( getModelImpl() != NULL, "need model impl" );
    EvaluationContext aContext = getModelImpl()->getEvaluationContext();
    aContext.mxNamespaces = getBindingNamespaces();
    return aContext;
}

::std::vector<EvaluationContext> Binding::getMIPEvaluationContexts()
{
    OSL_ENSURE( getModelImpl() != NULL, "need model impl" );

    // bind (in case we were not bound before)
    bind( sal_False );
    return _getMIPEvaluationContexts();
}


Binding::IntSequence_t Binding::getUnoTunnelID()
{
    static cppu::OImplementationId aImplementationId;
    return aImplementationId.getImplementationId();
}

Binding* SAL_CALL Binding::getBinding( const Reference<XPropertySet>& xPropertySet )
{
    Reference<XUnoTunnel> xTunnel( xPropertySet, UNO_QUERY );
    return xTunnel.is() 
        ? reinterpret_cast<Binding*>( xTunnel->getSomething(getUnoTunnelID()))
        : NULL;
}




OUString Binding::getBindingID() const
{
    return msBindingID;
}

void Binding::setBindingID( const OUString& sBindingID )
{
    msBindingID = sBindingID;
}

OUString Binding::getBindingExpression() const
{
    return maBindingExpression.getExpression();
}

void Binding::setBindingExpression( const OUString& sBindingExpression)
{
    maBindingExpression.setExpression( sBindingExpression );
    bindingModified();
}

OUString Binding::getReadonlyExpression() const
{
    return maReadonly.getExpression();
}

void Binding::setReadonlyExpression( const OUString& sReadonly)
{
    maReadonly.setExpression( sReadonly );
    bindingModified();
}

OUString Binding::getRelevantExpression() const
{
    return maRelevant.getExpression();
}

void Binding::setRelevantExpression( const OUString& sRelevant )
{
    maRelevant.setExpression( sRelevant );
    bindingModified();
}

OUString Binding::getRequiredExpression() const
{
    return maRequired.getExpression();
}

void Binding::setRequiredExpression( const OUString& sRequired )
{
    maRequired.setExpression( sRequired );
    bindingModified();
}

OUString Binding::getConstraintExpression() const
{
    return maConstraint.getExpression();
}

void Binding::setConstraintExpression( const OUString& sConstraint )
{
    maConstraint.setExpression( sConstraint );
    msExplainConstraint = getResource( RID_STR_XFORMS_INVALID_CONSTRAINT,
                                       sConstraint );

    // TODO: This should only re-evaluate the constraint, and notify
    // the validity constraint listeners; instead we currently pretend
    // the entire binding was notified, which does a little too much.
    bindingModified();
}

OUString Binding::getCalculateExpression() const
{
    return maCalculate.getExpression();
}

void Binding::setCalculateExpression( const OUString& sCalculate )
{
    maCalculate.setExpression( sCalculate );
    bindingModified();
}

OUString Binding::getType() const
{
    return msTypeName;
}

void Binding::setType( const OUString& sTypeName )
{
    msTypeName = sTypeName;
    bindingModified();
}

Binding::XNameContainer_t Binding::getBindingNamespaces() const
{
    //    return _getNamespaces();
    return mxNamespaces;
}

void Binding::setBindingNamespaces( const XNameContainer_t& rNamespaces )
{
    _setNamespaces( rNamespaces, true );
}

Binding::XNameContainer_t Binding::getModelNamespaces() const
{
    return _getNamespaces();
}

void Binding::setModelNamespaces( const XNameContainer_t& rNamespaces )
{
    _setNamespaces( rNamespaces, false );
}

bool Binding::getReadOnly() const
{
    return maMIP.isReadonly();
}

bool Binding::getRelevant() const
{
    return maMIP.isRelevant();
}

bool Binding::getExternalData() const
{
    bool bExternalData = true;
    if ( !mxModel.is() )
        return bExternalData;

    try
    {
        Reference< XPropertySet > xModelProps( mxModel, UNO_QUERY_THROW );
        OSL_VERIFY(
            xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) ) ) >>= bExternalData );
    }
    catch( const Exception& )
    {
    	DBG_UNHANDLED_EXCEPTION();
    }
    return bExternalData;
}


void Binding::checkLive()
    throw( RuntimeException )
{
    if( ! isLive() )
        throw RuntimeException( EXCEPT("Binding not initialized") );
}

void Binding::checkModel()
    throw( RuntimeException )
{
    if( ! mxModel.is() )
        throw RuntimeException( EXCEPT("Binding has no Model") );
}

bool Binding::isLive() const
{
    const Model* pModel = getModelImpl();
    return ( pModel != NULL ) ? pModel->isInitialized() : false;
}

Model* Binding::getModelImpl() const
{
    return getModelImpl( mxModel );
}

Model* Binding::getModelImpl( const Model_t& xModel ) const
{
    Reference<XUnoTunnel> xTunnel( xModel, UNO_QUERY );
    Model* pModel = xTunnel.is() 
        ? reinterpret_cast<Model*>(
            xTunnel->getSomething( Model::getUnoTunnelID() ) )
        : NULL;
    return pModel;
}

void lcl_addListenerToNode( Reference<XNode> xNode,
                            Reference<XEventListener> xListener )
{
    Reference<XEventTarget> xTarget( xNode, UNO_QUERY );
    if( xTarget.is() )
    {
        xTarget->addEventListener( OUSTRING("DOMCharacterDataModified"),
                                   xListener, false );
        xTarget->addEventListener( OUSTRING("DOMCharacterDataModified"),
                                   xListener, true );
        xTarget->addEventListener( OUSTRING("DOMAttrModified"), 
                                   xListener, false );
        xTarget->addEventListener( OUSTRING("DOMAttrModified"), 
                                   xListener, true );
        xTarget->addEventListener( OUSTRING("DOMAttrModified"), 
                                   xListener, true );
        xTarget->addEventListener( OUSTRING("xforms-generic"), 
                                   xListener, true );
    }
}

void lcl_removeListenerFromNode( Reference<XNode> xNode,
                                 Reference<XEventListener> xListener )
{
    Reference<XEventTarget> xTarget( xNode, UNO_QUERY );
    if( xTarget.is() )
    {
        xTarget->removeEventListener( OUSTRING("DOMCharacterDataModified"),
                                      xListener, false );
        xTarget->removeEventListener( OUSTRING("DOMCharacterDataModified"),
                                      xListener, true );
        xTarget->removeEventListener( OUSTRING("DOMAttrModified"), 
                                      xListener, false );
        xTarget->removeEventListener( OUSTRING("DOMAttrModified"), 
                                      xListener, true );
        xTarget->removeEventListener( OUSTRING("xforms-generic"), 
                                      xListener, true );
    }
}

::std::vector<EvaluationContext> Binding::_getMIPEvaluationContexts() const
{
    OSL_ENSURE( getModelImpl() != NULL, "need model impl" );

    // iterate over nodes of bind expression and create
    // EvaluationContext for each
    PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList();
    ::std::vector<EvaluationContext> aVector;
    sal_Int32 nCount = 0; // count nodes for context position
    for( PathExpression::NodeVector_t::iterator aIter = aNodes.begin();
         aIter != aNodes.end();
         aIter++, nCount++ )
    {
        OSL_ENSURE( aIter->is(), "no node?" );

        // create proper evaluation context for this MIP
        aVector.push_back( EvaluationContext( *aIter, getModel(), 
                                              getBindingNamespaces(),
                                              nCount, aNodes.size() ) );
    }
    return aVector;
}

void Binding::bind( bool bForceRebind )
{
    checkModel();

    // bind() will evaluate this binding as follows:
    // 1) evaluate the binding expression
    // 1b) if necessary, create node according to 'lazy author' rules
    // 2) register suitable listeners on the instance (and remove old ones)
    // 3) remove old MIPs defined by this binding
    // 4) for every node in the binding nodeset do:
    //    1) create proper evaluation context for this MIP
    //    2) evaluate calculate expression (and push value into instance)
    //    3) evaluate remaining MIPs
    //    4) evaluate the locally defined MIPs, and push them to the model


    // 1) evaluate the binding expression
    EvaluationContext aContext = getEvaluationContext();
    maBindingExpression.evaluate( aContext );
    if( ! maBindingExpression.getNode().is() )
    {
        // 1b) create node (if valid element name)
        if( isValidQName( maBindingExpression.getExpression(), 
                          aContext.mxNamespaces ) )
        {
            aContext.mxContextNode->appendChild( 
                Reference<XNode>( 
                    aContext.mxContextNode->getOwnerDocument()->createElement( 
                        maBindingExpression.getExpression() ),
                    UNO_QUERY ) );
            maBindingExpression.evaluate( aContext );
            OSL_ENSURE( maBindingExpression.getNode().is(), 
                        "we should bind to the newly inserted node!" );
        }
    }
    PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList();

    // 2) register suitable listeners on the instance (and remove old ones)
    if( maEventNodes.empty() || bForceRebind )
    {
        for( XNodes_t::iterator aIter = maEventNodes.begin();
             aIter != maEventNodes.end();
             aIter ++ )
            lcl_removeListenerFromNode( *aIter, this );
        maEventNodes.clear();
        if( isSimpleBinding() )
            for( PathExpression::NodeVector_t::iterator aIter = aNodes.begin();
                 aIter != aNodes.end();
                 aIter++ )
                maEventNodes.push_back( *aIter );
        else
            maEventNodes.push_back( 
                Reference<XNode>( aContext.mxContextNode->getOwnerDocument(), 
                                  UNO_QUERY_THROW ) );
        for( PathExpression::NodeVector_t::iterator aIter2 = maEventNodes.begin();
             aIter2 != maEventNodes.end();
             aIter2 ++ )
            lcl_addListenerToNode( *aIter2, this );
    }

    // 3) remove old MIPs defined by this binding
    Model* pModel = getModelImpl();
    OSL_ENSURE( pModel != NULL, "need model" );
    pModel->removeMIPs( this );

    // 4) calculate all MIPs
    ::std::vector<EvaluationContext> aMIPContexts = _getMIPEvaluationContexts();
    for( ::std::vector<EvaluationContext>::iterator aIter = aMIPContexts.begin();
         aIter != aMIPContexts.end();
         aIter++ )
    {
        EvaluationContext& rContext = *aIter;

        // evaluate calculate expression (and push value into instance)
        // (prevent recursion using mbInCalculate
        if( ! maCalculate.isEmptyExpression() )
        {
            if( ! mbInCalculate )
            {
                mbInCalculate = true;
                maCalculate.evaluate( rContext );
                pModel->setSimpleContent( rContext.mxContextNode,
                                          maCalculate.getString() );
                mbInCalculate = false;
            }
        }

        // now evaluate remaining MIPs in the apropriate context
        maReadonly.evaluate( rContext );
        maRelevant.evaluate( rContext );
        maRequired.evaluate( rContext );
        maConstraint.evaluate( rContext );
        // type is static; does not need updating

        // evaluate the locally defined MIPs, and push them to the model
        pModel->addMIP( this, rContext.mxContextNode, getLocalMIP() );
    }
}


// helper for Binding::valueModified
void lcl_modified( const Binding::XModifyListener_t xListener,
                   const Reference<XInterface> xSource )
{
    OSL_ENSURE( xListener.is(), "no listener?" );
    xListener->modified( EventObject( xSource ) );
}

// helper for Binding::valueModified
void lcl_listentry( const Binding::XListEntryListener_t xListener,
                    const Reference<XInterface> xSource )
{
    OSL_ENSURE( xListener.is(), "no listener?" );
    // TODO: send fine granular events
    xListener->allEntriesChanged( EventObject( xSource ) );
}

// helper for Binding::valueModified
void lcl_validate( const Binding::XValidityConstraintListener_t xListener,
                   const Reference<XInterface> xSource )
{
    OSL_ENSURE( xListener.is(), "no listener?" );
    xListener->validityConstraintChanged( EventObject( xSource ) );
}


void Binding::valueModified()
{
    // defer notifications, if so desired
    if( mnDeferModifyNotifications > 0 )
    {
        mbValueModified = true;
        return;
    }
    mbValueModified = false;

    // query MIP used by our first node (also note validity)
    Reference<XNode> xNode = maBindingExpression.getNode();
    maMIP = getModelImpl()->queryMIP( xNode );

    // distribute MIPs _used_ by this binding
    if( xNode.is() )
    {
        notifyAndCachePropertyValue( HANDLE_ReadOnly );
        notifyAndCachePropertyValue( HANDLE_Relevant );
    }

    // iterate over _value_ listeners and send each a modified signal,
    // using this object as source (will also update validity, because
    // control will query once the value has changed)
    Reference<XInterface> xSource = static_cast<XPropertySet*>( this );
    ::std::for_each( maModifyListeners.begin(),
              maModifyListeners.end(), 
              ::std::bind2nd( ::std::ptr_fun( lcl_modified ), xSource ) );
    ::std::for_each( maListEntryListeners.begin(),
              maListEntryListeners.end(), 
              ::std::bind2nd( ::std::ptr_fun( lcl_listentry ), xSource ) );
    ::std::for_each( maValidityListeners.begin(),
              maValidityListeners.end(), 
              ::std::bind2nd( ::std::ptr_fun( lcl_validate ), xSource ) );

	// now distribute MIPs to childs
    if( xNode.is() )
        distributeMIP( xNode->getFirstChild() );
}

void Binding::distributeMIP( const XNode_t & rxNode ) {

	typedef com::sun::star::xforms::XFormsEventConcrete XFormsEvent_t;
    OUString sEventName( RTL_CONSTASCII_USTRINGPARAM("xforms-generic") );
	XFormsEvent_t *pEvent = new XFormsEvent_t;
    pEvent->initXFormsEvent(sEventName, sal_True, sal_False);
	Reference<XEvent> xEvent(pEvent);

	// naive depth-first traversal
	XNode_t xNode( rxNode );
	while(xNode.is()) {

		// notifications should be triggered at the
		// leaf nodes first, bubbling upwards the hierarchy.
		XNode_t child(xNode->getFirstChild());
		if(child.is())
			distributeMIP(child);

		// we're standing at a particular node somewhere
		// below the one which changed a property (MIP).
		// bindings which are listening at this node will receive
		// a notification message about what exactly happened.
		Reference< XEventTarget > target(xNode,UNO_QUERY);
        target->dispatchEvent(xEvent);

		xNode = xNode->getNextSibling();
	};
}

void Binding::bindingModified()
{
    // defer notifications, if so desired
    if( mnDeferModifyNotifications > 0 )
    {
        mbBindingModified = true;
        return;
    }
    mbBindingModified = false;

    // rebind (if live); then call valueModified
    // A binding should be inert until its model is fully constructed.
    if( isLive() )
    {
        bind( true );
        valueModified();
    }
}


MIP Binding::getLocalMIP() const
{
    MIP aMIP;

    if( maReadonly.hasValue() )
        aMIP.setReadonly( maReadonly.getBool( false ) );
    if( maRelevant.hasValue() )
        aMIP.setRelevant( maRelevant.getBool( true ) );
    if( maRequired.hasValue() )
        aMIP.setRequired( maRequired.getBool( false ) );
    if( maConstraint.hasValue() )
    {
        aMIP.setConstraint( maConstraint.getBool( true ) );
        if( ! aMIP.isConstraint() )
            aMIP.setConstraintExplanation( msExplainConstraint );
    }
    if( msTypeName.getLength() > 0 )
        aMIP.setTypeName( msTypeName );

    // calculate: only handle presence of calculate; value set elsewhere
    aMIP.setHasCalculate( !maCalculate.isEmptyExpression() );

    return aMIP;
}

Binding::XDataType_t Binding::getDataType()
{
    OSL_ENSURE( getModel().is(), "need model" );
    OSL_ENSURE( getModel()->getDataTypeRepository().is(), "need types" );

    Reference<XDataTypeRepository> xRepository( 
        getModel()->getDataTypeRepository(), UNO_QUERY );
    OUString sTypeName = maMIP.getTypeName();

    return ( xRepository.is() && xRepository->hasByName( sTypeName ) )
        ? Reference<XDataType>( xRepository->getByName( sTypeName ), UNO_QUERY)
        : Reference<XDataType>( NULL );
}

bool Binding::isValid_DataType()
{
    Reference<XDataType> xDataType = getDataType();
    return xDataType.is()
        ? xDataType->validate( maBindingExpression.getString() )
        : true;
}

rtl::OUString Binding::explainInvalid_DataType()
{
    Reference<XDataType> xDataType = getDataType();
    return xDataType.is()
        ? xDataType->explainInvalid( maBindingExpression.getString() )
        : OUString();
}

void Binding::clear()
{
    // remove MIPs contributed by this binding
    Model* pModel = getModelImpl();
    if( pModel != NULL )
        pModel->removeMIPs( this );

    // remove all references
    for( XNodes_t::iterator aIter = maEventNodes.begin();
         aIter != maEventNodes.end();
         aIter ++ )
        lcl_removeListenerFromNode( *aIter, this );
    maEventNodes.clear();

    // clear expressions
    maBindingExpression.clear();
    maReadonly.clear();
    maRelevant.clear();
    maRequired.clear();
    maConstraint.clear();
    maCalculate.clear();

    // TODO: what about our listeners?
}


void lcl_removeOtherNamespaces( const Binding::XNameContainer_t& xFrom,
                                Binding::XNameContainer_t& xTo )
{
    OSL_ENSURE( xFrom.is(), "no source" );
    OSL_ENSURE( xTo.is(), "no target" );

    // iterate over name in source
    Sequence<OUString> aNames = xTo->getElementNames();
    sal_Int32 nNames = aNames.getLength();
    const OUString* pNames = aNames.getConstArray();
    for( sal_Int32 i = 0; i < nNames; i++ )
    {
        const OUString& rName = pNames[i];

        if( ! xFrom->hasByName( rName ) )
            xTo->removeByName( rName );
    }
}

/** copy namespaces from one namespace container into another
 * @param bOverwrite true: overwrite namespaces in target
 *                   false: do not overwrite namespaces in target
 * @param bMove true: move namespaces (i.e., delete in source)
 *              false: copy namespaces (do not modify source)
 * @param bFromSource true: use elements from source
 *                    false: use only elements from target
 */
void lcl_copyNamespaces( const Binding::XNameContainer_t& xFrom,
                         Binding::XNameContainer_t& xTo,
                         bool bOverwrite )
{
    OSL_ENSURE( xFrom.is(), "no source" );
    OSL_ENSURE( xTo.is(), "no target" );

    // iterate over name in source
    Sequence<OUString> aNames = xFrom->getElementNames();
    sal_Int32 nNames = aNames.getLength();
    const OUString* pNames = aNames.getConstArray();
    for( sal_Int32 i = 0; i < nNames; i++ )
    {
        const OUString& rName = pNames[i];

        // determine whether to copy the value, and whether to delete
        // it in the source:

        bool bInTarget = xTo->hasByName( rName );

        // we copy: if property is in target, and
        //          if bOverwrite is set, or when the namespace prefix is free
        bool bCopy = bOverwrite || ! bInTarget;

        // and now... ACTION!
        if( bCopy )
        {
            if( bInTarget )
                xTo->replaceByName( rName, xFrom->getByName( rName ) );
            else
                xTo->insertByName( rName, xFrom->getByName( rName ) );
        }
    }
}

// implement get*Namespaces()
// (identical for both variants)
Binding::XNameContainer_t Binding::_getNamespaces() const
{
    XNameContainer_t xNamespaces = new NameContainer<OUString>();
    lcl_copyNamespaces( mxNamespaces, xNamespaces, true );

    // merge model's with binding's own namespaces
    Model* pModel = getModelImpl();
    if( pModel != NULL )
        lcl_copyNamespaces( pModel->getNamespaces(), xNamespaces, false );

    return xNamespaces;
}

// implement set*Namespaces()
// bBinding = true: setBindingNamespaces, otherwise: setModelNamespaces
void Binding::_setNamespaces( const XNameContainer_t& rNamespaces,
                              bool bBinding )
{
    Model* pModel = getModelImpl();
    XNameContainer_t xModelNamespaces = ( pModel != NULL ) 
                                            ? pModel->getNamespaces()
                                            : NULL;
    OSL_ENSURE( ( pModel != NULL ) == xModelNamespaces.is(), "no model nmsp?");

    // remove deleted namespaces
    lcl_removeOtherNamespaces( rNamespaces, mxNamespaces );
    if( !bBinding && xModelNamespaces.is() )
        lcl_removeOtherNamespaces( rNamespaces, xModelNamespaces );

    // copy namespaces as appropriate
    Sequence<OUString> aNames = rNamespaces->getElementNames();
    sal_Int32 nNames = aNames.getLength();
    const OUString* pNames = aNames.getConstArray();
    for( sal_Int32 i = 0; i < nNames; i++ )
    {
        const OUString& rName = pNames[i];
        Any aValue = rNamespaces->getByName( rName );

        // determine whether the namespace should go into model's or
        // into binding's namespaces
        bool bLocal = 
            ! xModelNamespaces.is()
            || mxNamespaces->hasByName( rName )
            || ( bBinding 
                 && xModelNamespaces.is()
                 && xModelNamespaces->hasByName( rName ) );

        // write namespace into the appropriate namespace container
        XNameContainer_t& rWhich = bLocal ? mxNamespaces : xModelNamespaces;
        OSL_ENSURE( rWhich.is(), "whoops" );
        if( rWhich->hasByName( rName ) )
            rWhich->replaceByName( rName, aValue );
        else
            rWhich->insertByName( rName, aValue );

        // always 'promote' namespaces from binding to model, if equal
        if( xModelNamespaces.is()
            && xModelNamespaces->hasByName( rName )
            && mxNamespaces->hasByName( rName )
            && xModelNamespaces->getByName( rName ) == mxNamespaces->getByName( rName ) )
        {
            mxNamespaces->removeByName( rName );
        }
    }

    // ... done. But we modified the binding!
    bindingModified();
}

void Binding::_checkBindingID()
{
    if( getModel().is() )
    {
        Reference<XNameAccess> xBindings( getModel()->getBindings(), UNO_QUERY_THROW );
        if( msBindingID.getLength() == 0 )
        {
            // no binding ID? then make one up!
            OUString sIDPrefix = getResource( RID_STR_XFORMS_BINDING_UI_NAME );
            sIDPrefix += String::CreateFromAscii( " " );
            sal_Int32 nNumber = 0;
            OUString sName;
            do
            {
                nNumber++;
                sName = sIDPrefix + OUString::valueOf( nNumber );
            }
            while( xBindings->hasByName( sName ) );
            setBindingID( sName );
        }
    }
}




//
// XValueBinding
//

Binding::Sequence_Type_t Binding::getSupportedValueTypes() 
    throw( RuntimeException )
{
    return Convert::get().getTypes();
}

sal_Bool Binding::supportsType( const Type_t& rType ) 
    throw( RuntimeException )
{
    return Convert::get().hasType( rType );
}

Binding::Any_t Binding::getValue( const Type_t& rType )
    throw( IncompatibleTypesException, 
           RuntimeException )
{
    // first, check for model
    checkLive();

    // second, check for type
    if( ! supportsType( rType ) )
        throw IncompatibleTypesException( EXCEPT( "type unsupported" ) );

    // return string value (if present; else return empty Any)
		Binding::Any_t result = Any();
		if(maBindingExpression.hasValue()) {
			rtl::OUString pathExpr(maBindingExpression.getString());
			Convert &rConvert = Convert::get();
			result = rConvert.toAny(pathExpr,rType);
		}
    
//		return maBindingExpression.hasValue() 
  //      ? Convert::get().toAny( maBindingExpression.getString(), rType )
    //    : Any();

		return result;
}

void Binding::setValue( const Any_t& aValue ) 
    throw( IncompatibleTypesException, 
           InvalidBindingStateException, 
           NoSupportException, 
           RuntimeException )
{
    // first, check for model
    checkLive();

    // check for supported type
    if( ! supportsType( aValue.getValueType() ) )
        throw IncompatibleTypesException( EXCEPT( "type unsupported" ) );

    if( maBindingExpression.hasValue() )
    {
        Binding::XNode_t xNode = maBindingExpression.getNode();
        if( xNode.is() )
        {
            OUString sValue = Convert::get().toXSD( aValue );
            bool bSuccess = getModelImpl()->setSimpleContent( xNode, sValue );
            if( ! bSuccess )
                throw InvalidBindingStateException( EXCEPT( "can't set value" ) );
        }
        else
            throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) );
    }
    else
        throw InvalidBindingStateException( EXCEPT( "no suitable node found" ) );
}


//
// XListEntry Source
//

sal_Int32 Binding::getListEntryCount()
    throw( RuntimeException )
{
    // first, check for model
    checkLive();

    // return size of node list
    return maBindingExpression.getNodeList().size();
}

void lcl_getString( const Reference<XNode>& xNode, OUStringBuffer& rBuffer )
{
    if( xNode->getNodeType() == NodeType_TEXT_NODE
        || xNode->getNodeType() == NodeType_ATTRIBUTE_NODE )
    {
        rBuffer.append( xNode->getNodeValue() );
    }
    else
    {
        for( Reference<XNode> xChild = xNode->getFirstChild();
             xChild.is();
             xChild = xChild->getNextSibling() )
        {
            lcl_getString( xChild, rBuffer );
        }
    }
}

OUString lcl_getString( const Reference<XNode>& xNode )
{
    OUStringBuffer aBuffer;
    lcl_getString( xNode, aBuffer );
    return aBuffer.makeStringAndClear();
}

OUString Binding::getListEntry( sal_Int32 nPosition )
    throw( IndexOutOfBoundsException,
           RuntimeException )
{
    // first, check for model
    checkLive();

    // 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("") );
    return lcl_getString( aNodes[ nPosition ] );
}

Sequence<OUString> Binding::getAllListEntries()
    throw( RuntimeException )
{
    // first, check for model
    checkLive();

    // create sequence of string values
    PathExpression::NodeVector_t aNodes = maBindingExpression.getNodeList();
    Sequence<OUString> aSequence( aNodes.size() );
    OUString* pSequence = aSequence.getArray();
    for( sal_Int32 n = 0; n < aSequence.getLength(); n++ )
    {
        pSequence[n] = lcl_getString( aNodes[n] );
    }

    return aSequence;
}

void Binding::addListEntryListener( const XListEntryListener_t& xListener )
    throw( NullPointerException,
           RuntimeException )
{
    OSL_ENSURE( xListener.is(), "need listener!" );
    if( ::std::find( maListEntryListeners.begin(), 
              maListEntryListeners.end(), 
              xListener)
        == maListEntryListeners.end() )
        maListEntryListeners.push_back( xListener );
}

void Binding::removeListEntryListener( const XListEntryListener_t& xListener )
    throw( NullPointerException,
           RuntimeException )
{
    XListEntryListeners_t::iterator aIter = 
        ::std::find( maListEntryListeners.begin(), maListEntryListeners.end(), 
              xListener );
    if( aIter != maListEntryListeners.end() )
        maListEntryListeners.erase( aIter );
}


// 
// XValidator
//

sal_Bool Binding::isValid( const Any_t& )
    throw( RuntimeException )
{
    // first, check for model
    checkLive();

    // ignore value; determine validate only on current data
    return isValid();
}

rtl::OUString Binding::explainInvalid(
    const Any_t& /*Value*/ )
    throw( RuntimeException )
{
    // first, check for model
    checkLive();

    // ignore value; determine explanation  only on current data
    return explainInvalid();
}

void Binding::addValidityConstraintListener(
    const XValidityConstraintListener_t& xListener )
    throw( NullPointerException,
           RuntimeException )
{
    OSL_ENSURE( xListener.is(), "need listener!" );
    if( ::std::find(maValidityListeners.begin(), maValidityListeners.end(), xListener)
        == maValidityListeners.end() )
        maValidityListeners.push_back( xListener );
}

void Binding::removeValidityConstraintListener(
    const XValidityConstraintListener_t& xListener )
    throw( NullPointerException,
           RuntimeException )
{
    XValidityConstraintListeners_t::iterator aIter = 
        ::std::find( maValidityListeners.begin(), maValidityListeners.end(), 
              xListener );
    if( aIter != maValidityListeners.end() )
        maValidityListeners.erase( aIter );
}



// 
// xml::dom::event::XEventListener
//

void Binding::handleEvent( const XEvent_t& xEvent )
    throw( RuntimeException )
{
	OUString sType(xEvent->getType());
	//OUString sEventMIPChanged(RTL_CONSTASCII_USTRINGPARAM("xforms-generic"));
	//if(sType.equals(sEventMIPChanged)) {
	if(!sType.compareToAscii("xforms-generic")) {

		// the modification of the 'mnDeferModifyNotifications'-member
		// is necessary to prevent infinite notication looping.
		// This can happend in case the binding which caused
		// the notification chain is listening to those events
		// as well...
        bool bPreserveValueModified = mbValueModified;
		mnDeferModifyNotifications++;
	    valueModified();
		--mnDeferModifyNotifications;
		mbValueModified = bPreserveValueModified;
		return;
	}

    // if we're a dynamic binding, we better re-bind, too!
    bind( false );

    // our value was maybe modified
    valueModified();
}


//
// lang::XUnoTunnel
//

sal_Int64 Binding::getSomething( const IntSequence_t& xId )
    throw( RuntimeException )
{
    return reinterpret_cast<sal_Int64>( ( xId == getUnoTunnelID() ) ? this : NULL );
}

//
// XCloneable
//

Binding::XCloneable_t SAL_CALL Binding::createClone()
    throw( RuntimeException )
{
    Reference< XPropertySet > xClone;

    Model* pModel = getModelImpl();
    if ( pModel )
        xClone = pModel->cloneBinding( this );
    else
    {
        xClone = new Binding;
        copy( this, xClone );
    }
    return XCloneable_t( xClone, UNO_QUERY );
}

//
// property set implementations
//

#define REGISTER_PROPERTY( property, type )   \
    registerProperty( PROPERTY( property, type ), \
    new DirectPropertyAccessor< Binding, type >( this, &Binding::set##property, &Binding::get##property ) );

#define REGISTER_PROPERTY_RO( property, type )   \
    registerProperty( PROPERTY_RO( property, type ), \
    new DirectPropertyAccessor< Binding, type >( this, NULL, &Binding::get##property ) );

#define REGISTER_BOOL_PROPERTY_RO( property )   \
    registerProperty( PROPERTY_RO( property, sal_Bool ), \
    new BooleanPropertyAccessor< Binding, bool >( this, NULL, &Binding::get##property ) );

void Binding::initializePropertySet()
{
    REGISTER_PROPERTY        ( BindingID,            OUString );
    REGISTER_PROPERTY        ( BindingExpression,    OUString );
    REGISTER_PROPERTY_RO     ( Model,                Model_t );
    REGISTER_PROPERTY        ( BindingNamespaces,    XNameContainer_t );
    REGISTER_PROPERTY        ( ModelNamespaces,      XNameContainer_t );
    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               );

    initializePropertyValueCache( HANDLE_ReadOnly );
    initializePropertyValueCache( HANDLE_Relevant );
    initializePropertyValueCache( HANDLE_ExternalData );
}

void Binding::addModifyListener( 
    const XModifyListener_t& xListener )
    throw( RuntimeException )
{
    OSL_ENSURE( xListener.is(), "need listener!" );
    if( ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener )
          == maModifyListeners.end() )
        maModifyListeners.push_back( xListener );

    // HACK: currently, we have to 'push' some MIPs to the control
    // (read-only, relevant, etc.) To enable this, we need to update
    // the control at least once when it registers here.
    valueModified();
}

void Binding::removeModifyListener(
    const XModifyListener_t& xListener )
    throw( RuntimeException )
{
    ModifyListeners_t::iterator aIter = 
        ::std::find( maModifyListeners.begin(), maModifyListeners.end(), xListener );
    if( aIter != maModifyListeners.end() )
        maModifyListeners.erase( aIter );
}




rtl::OUString Binding::getName()
    throw( RuntimeException )
{
    return getBindingID();
}

void SAL_CALL Binding::setName( const rtl::OUString& rName )
    throw( RuntimeException )
{
    // use the XPropertySet methods, so the change in the name is notified to the
    // property listeners
    setFastPropertyValue( HANDLE_BindingID, makeAny( rName ) );
}
