/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: property.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2006/01/10 15:52:00 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _COMPHELPER_PROPERTY_HXX_
#define _COMPHELPER_PROPERTY_HXX_

#ifndef _CPPUHELPER_PROPTYPEHLP_HXX
#include <cppuhelper/proptypehlp.hxx>
#endif
#ifndef _COMPHELPER_EXTRACT_HXX_
#include <comphelper/extract.hxx>
#endif
#ifndef _COM_SUN_STAR_BEANS_PROPERTY_HPP_
#include <com/sun/star/beans/Property.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#include <functional>
#ifndef INCLUDED_COMPHELPERDLLAPI_H
#include "comphelper/comphelperdllapi.h"
#endif
#ifndef INCLUDED_CPPU_UNOTYPE_HXX
#include "cppu/unotype.hxx"
#endif

//=========================================================================
//= property helper classes
//=========================================================================

//... namespace comphelper .......................................................
namespace comphelper
{
//.........................................................................

	namespace starbeans	= ::com::sun::star::beans;
	namespace staruno	= ::com::sun::star::uno;

/** compare two properties by name
*/
	struct PropertyStringLessFunctor : ::std::binary_function< ::com::sun::star::beans::Property, ::rtl::OUString, bool > 
	{
		// ................................................................
		inline bool operator()( const ::com::sun::star::beans::Property& lhs, const ::rtl::OUString& rhs ) const
		{
			return lhs.Name.compareTo(rhs) < 0;
		}
		// ................................................................
		inline bool operator()( const ::rtl::OUString& lhs, const ::com::sun::star::beans::Property& rhs ) const
		{
			return lhs.compareTo(rhs.Name) < 0;
		}
	};
	//--------------------------------------------------------------------------
	// comparing two property instances
	struct PropertyCompareByName : public ::std::binary_function< ::com::sun::star::beans::Property, ::com::sun::star::beans::Property, bool >
	{
		bool operator() (const ::com::sun::star::beans::Property& x, const ::com::sun::star::beans::Property& y) const
		{
			return x.Name.compareTo(y.Name) < 0;// ? true : false;
		}
	};


//------------------------------------------------------------------
/// remove the property with the given name from the given sequence
COMPHELPER_DLLPUBLIC void RemoveProperty(staruno::Sequence<starbeans::Property>& seqProps, const ::rtl::OUString& _rPropName);

//------------------------------------------------------------------
/** within the given property sequence, modify attributes of a special property
	@param	_rProps			the sequence of properties to search in
	@param	_sPropName		the name of the property which's attributes should be modified
	@param	_nAddAttrib		the attributes which should be added
	@param	_nRemoveAttrib	the attributes which should be removed
*/
COMPHELPER_DLLPUBLIC void ModifyPropertyAttributes(staruno::Sequence<starbeans::Property>& _rProps, const ::rtl::OUString& _sPropName, sal_Int16 _nAddAttrib, sal_Int16 _nRemoveAttrib);

//------------------------------------------------------------------
/**	check if the given set has the given property.
*/
COMPHELPER_DLLPUBLIC sal_Bool hasProperty(const rtl::OUString& _rName, const staruno::Reference<starbeans::XPropertySet>& _rxSet);

//------------------------------------------------------------------
/**	copy properties between property sets, in compliance with the property
	attributes of the target object
*/
COMPHELPER_DLLPUBLIC void copyProperties(const staruno::Reference<starbeans::XPropertySet>& _rxSource,
					const staruno::Reference<starbeans::XPropertySet>& _rxDest);

//==================================================================
//= property conversion helpers
//==================================================================

/** helper for implementing ::cppu::OPropertySetHelper::convertFastPropertyValue
	@param			_rConvertedValue	the conversion result (if successfull)
	@param			_rOldValue			the old value of the property, calculated from _rCurrentValue
	@param			_rValueToSet		the new value which is about to be set
	@param			_rCurrentValue		the current value of the property
	@return			sal_True, if the value could be converted and has changed
					sal_False, if the value could be converted and has not changed
	@exception		InvalidArgumentException thrown if the value could not be converted to the requested type (which is the template argument)
*/
template <class TYPE>
sal_Bool tryPropertyValue(staruno::Any& /*out*/_rConvertedValue, staruno::Any& /*out*/_rOldValue, const staruno::Any& _rValueToSet, const TYPE& _rCurrentValue)
{
	sal_Bool bModified(sal_False);
	TYPE aNewValue;
	::cppu::convertPropertyValue(aNewValue, _rValueToSet);
	if (aNewValue != _rCurrentValue)
	{
		_rConvertedValue <<= aNewValue;
		_rOldValue <<= _rCurrentValue;
		bModified = sal_True;
	}
	return bModified;
}

/** helper for implementing ::cppu::OPropertySetHelper::convertFastPropertyValue for enum values
	@param			_rConvertedValue	the conversion result (if successfull)
	@param			_rOldValue			the old value of the property, calculated from _rCurrentValue
	@param			_rValueToSet		the new value which is about to be set
	@param			_rCurrentValue		the current value of the property
	@return			sal_True, if the value could be converted and has changed
					sal_False, if the value could be converted and has not changed
	@exception		InvalidArgumentException thrown if the value could not be converted to the requested type (which is the template argument)
*/
template <class ENUMTYPE>
sal_Bool tryPropertyValueEnum(staruno::Any& /*out*/_rConvertedValue, staruno::Any& /*out*/_rOldValue, const staruno::Any& _rValueToSet, const ENUMTYPE& _rCurrentValue)
{
    if (cppu::getTypeFavourUnsigned(&_rCurrentValue).getTypeClass()
        != staruno::TypeClass_ENUM)
		return tryPropertyValue(_rConvertedValue, _rOldValue, _rValueToSet, _rCurrentValue);

	sal_Bool bModified(sal_False);
	ENUMTYPE aNewValue;
	::cppu::any2enum(aNewValue, _rValueToSet);
		// will throw an exception if not convertible

	if (aNewValue != _rCurrentValue)
	{
		_rConvertedValue <<= aNewValue;
		_rOldValue <<= _rCurrentValue;
		bModified = sal_True;
	}
	return bModified;
}

/** helper for implementing ::cppu::OPropertySetHelper::convertFastPropertyValue for boolean properties
	@param			_rConvertedValue	the conversion result (if successfull)
	@param			_rOldValue			the old value of the property, calculated from _rCurrentValue
	@param			_rValueToSet		the new value which is about to be set
	@param			_rCurrentValue		the current value of the property
	@return			sal_True, if the value could be converted and has changed
					sal_False, if the value could be converted and has not changed
	@exception		InvalidArgumentException thrown if the value could not be converted to a boolean type
*/
inline sal_Bool tryPropertyValue(staruno::Any& /*out*/_rConvertedValue, staruno::Any& /*out*/_rOldValue, const staruno::Any& _rValueToSet, sal_Bool _bCurrentValue)
{
	sal_Bool bModified(sal_False);
	sal_Bool bNewValue;
	::cppu::convertPropertyValue(bNewValue, _rValueToSet);
	if (bNewValue != _bCurrentValue)
	{
		_rConvertedValue.setValue(&bNewValue, ::getBooleanCppuType());
		_rOldValue.setValue(&_bCurrentValue, ::getBooleanCppuType());
		bModified = sal_True;
	}
	return bModified;
}

/** helper for implementing ::cppu::OPropertySetHelper::convertFastPropertyValue
	@param			_rConvertedValue	the conversion result (if successfull)
	@param			_rOldValue			the old value of the property, calculated from _rCurrentValue
	@param			_rValueToSet		the new value which is about to be set
	@param			_rCurrentValue		the current value of the property
	@param			_rExpectedType		the type which the property should have (if not void)
	@return			sal_True, if the value could be converted and has changed
					sal_False, if the value could be converted and has not changed
	@exception		InvalidArgumentException thrown if the value could not be converted to the requested type (which is the template argument)
*/
COMPHELPER_DLLPUBLIC sal_Bool tryPropertyValue(staruno::Any& _rConvertedValue, staruno::Any& _rOldValue, const staruno::Any& _rValueToSet, staruno::Any& _rCurrentValue, const staruno::Type& _rExpectedType);

//.........................................................................
}
//... namespace comphelper .......................................................

#endif // _COMPHELPER_PROPERTY_HXX_

