1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 
31 
32 #include <comphelper/property.hxx>
33 #include <comphelper/sequence.hxx>
34 #include <comphelper/types.hxx>
35 #include <osl/diagnose.h>
36 
37 #if OSL_DEBUG_LEVEL > 0
38     #include <rtl/strbuf.hxx>
39     #include <cppuhelper/exc_hlp.hxx>
40     #include <osl/thread.h>
41     #include <com/sun/star/lang/XServiceInfo.hpp>
42     #include <typeinfo>
43 #endif
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
45 #include <com/sun/star/lang/IllegalArgumentException.hpp>
46 #include <com/sun/star/uno/genfunc.h>
47 
48 #include <algorithm>
49 #include <boost/bind.hpp>
50 
51 //.........................................................................
52 namespace comphelper
53 {
54 
55     /** === begin UNO using === **/
56     using ::com::sun::star::uno::Reference;
57     using ::com::sun::star::beans::XPropertySet;
58     using ::com::sun::star::beans::XPropertySetInfo;
59     using ::com::sun::star::beans::Property;
60     using ::com::sun::star::uno::Sequence;
61     using ::com::sun::star::uno::Exception;
62     using ::com::sun::star::uno::Any;
63     using ::com::sun::star::uno::Type;
64     using ::com::sun::star::uno::cpp_queryInterface;
65     using ::com::sun::star::uno::cpp_acquire;
66     using ::com::sun::star::uno::cpp_release;
67 #if OSL_DEBUG_LEVEL > 0
68     using ::com::sun::star::lang::XServiceInfo;
69 #endif
70     using ::com::sun::star::uno::UNO_QUERY;
71     /** === end UNO using === **/
72     namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
73 
74 //------------------------------------------------------------------
75 void copyProperties(const Reference<XPropertySet>& _rxSource,
76 					const Reference<XPropertySet>& _rxDest)
77 {
78 	if (!_rxSource.is() || !_rxDest.is())
79 	{
80 		OSL_ENSURE(sal_False, "copyProperties: invalid arguments !");
81         return;
82 	}
83 
84 	Reference< XPropertySetInfo > xSourceProps = _rxSource->getPropertySetInfo();
85 	Reference< XPropertySetInfo > xDestProps = _rxDest->getPropertySetInfo();
86 
87 	Sequence< Property > aSourceProps = xSourceProps->getProperties();
88 	const Property* pSourceProps = aSourceProps.getConstArray();
89 	Property aDestProp;
90 	for (sal_Int32 i=0; i<aSourceProps.getLength(); ++i, ++pSourceProps)
91 	{
92 		if ( xDestProps->hasPropertyByName(pSourceProps->Name) )
93 		{
94 			try
95 			{
96 				aDestProp = xDestProps->getPropertyByName(pSourceProps->Name);
97 				if (0 == (aDestProp.Attributes & PropertyAttribute::READONLY) )
98                 {
99                     const Any aSourceValue = _rxSource->getPropertyValue(pSourceProps->Name);
100                     if ( 0 != (aDestProp.Attributes & PropertyAttribute::MAYBEVOID) || aSourceValue.hasValue() )
101 					    _rxDest->setPropertyValue(pSourceProps->Name, aSourceValue);
102                 }
103 			}
104 			catch (Exception&)
105 			{
106 #if OSL_DEBUG_LEVEL > 0
107                 ::rtl::OStringBuffer aBuffer;
108                 aBuffer.append( "::comphelper::copyProperties: could not copy property '" );
109                 aBuffer.append( ::rtl::OString( pSourceProps->Name.getStr(), pSourceProps->Name.getLength(), RTL_TEXTENCODING_ASCII_US ) );
110                 aBuffer.append( "' to the destination set (a '" );
111 
112                 Reference< XServiceInfo > xSI( _rxDest, UNO_QUERY );
113                 if ( xSI.is() )
114                 {
115                     aBuffer.append( ::rtl::OUStringToOString( xSI->getImplementationName(), osl_getThreadTextEncoding() ) );
116                 }
117                 else
118                 {
119                     aBuffer.append( typeid( *_rxDest.get() ).name() );
120                 }
121                 aBuffer.append( "' implementation).\n" );
122 
123                 Any aException( ::cppu::getCaughtException() );
124                 aBuffer.append( "Caught an exception of type '" );
125                 ::rtl::OUString sExceptionType( aException.getValueTypeName() );
126                 aBuffer.append( ::rtl::OString( sExceptionType.getStr(), sExceptionType.getLength(), RTL_TEXTENCODING_ASCII_US ) );
127                 aBuffer.append( "'" );
128 
129                 Exception aBaseException;
130                 if ( ( aException >>= aBaseException ) && aBaseException.Message.getLength() )
131                 {
132                     aBuffer.append( ", saying '" );
133                     aBuffer.append( ::rtl::OString( aBaseException.Message.getStr(), aBaseException.Message.getLength(), osl_getThreadTextEncoding() ) );
134                     aBuffer.append( "'" );
135                 }
136                 aBuffer.append( "." );
137 
138                 OSL_ENSURE( sal_False, aBuffer.getStr() );
139 #endif
140 			}
141 		}
142 	}
143 }
144 
145 //------------------------------------------------------------------
146 sal_Bool hasProperty(const rtl::OUString& _rName, const Reference<XPropertySet>& _rxSet)
147 {
148 	if (_rxSet.is())
149 	{
150 		//	XPropertySetInfoRef xInfo(rxSet->getPropertySetInfo());
151 		return _rxSet->getPropertySetInfo()->hasPropertyByName(_rName);
152 	}
153 	return sal_False;
154 }
155 
156 //------------------------------------------------------------------
157 bool findProperty(Property&              o_rProp,
158                   Sequence<Property>&    i_seqProps,
159                   const ::rtl::OUString& i_rPropName)
160 {
161     const Property* pAry(i_seqProps.getConstArray());
162     const sal_Int32 nLen(i_seqProps.getLength());
163     const Property* pRes(
164         std::find_if(pAry,pAry+nLen,
165                      boost::bind(PropertyStringEqualFunctor(),
166                                  _1,
167                                  boost::cref(i_rPropName))));
168     if( pRes == pAry+nLen )
169         return false;
170 
171     o_rProp = *pRes;
172     return true;
173 }
174 
175 //------------------------------------------------------------------
176 void RemoveProperty(Sequence<Property>& _rProps, const rtl::OUString& _rPropName)
177 {
178 	sal_Int32 nLen = _rProps.getLength();
179 
180 	// binaere Suche
181 	const Property* pProperties = _rProps.getConstArray();
182 	const Property* pResult = ::std::lower_bound(pProperties, pProperties + nLen, _rPropName,PropertyStringLessFunctor());
183 
184 	// gefunden ?
185 	if ( pResult && (pResult != pProperties + nLen) && (pResult->Name == _rPropName) )
186 	{
187 		OSL_ENSURE(pResult->Name.equals(_rPropName), "::RemoveProperty Properties nicht sortiert");
188 		removeElementAt(_rProps, pResult - pProperties);
189 	}
190 }
191 
192 //------------------------------------------------------------------
193 void ModifyPropertyAttributes(Sequence<Property>& seqProps, const ::rtl::OUString& sPropName, sal_Int16 nAddAttrib, sal_Int16 nRemoveAttrib)
194 {
195 	sal_Int32 nLen = seqProps.getLength();
196 
197 	// binaere Suche
198 	Property* pProperties = seqProps.getArray();
199 	Property* pResult = ::std::lower_bound(pProperties, pProperties + nLen,sPropName, PropertyStringLessFunctor());
200 
201 	// gefunden ?
202 	if ( pResult && (pResult != pProperties + nLen) && (pResult->Name == sPropName) )
203 	{
204 		pResult->Attributes |= nAddAttrib;
205 		pResult->Attributes &= ~nRemoveAttrib;
206 	}
207 }
208 
209 //------------------------------------------------------------------
210 sal_Bool tryPropertyValue(Any& _rConvertedValue, Any& _rOldValue, const Any& _rValueToSet, const Any& _rCurrentValue, const Type& _rExpectedType)
211 {
212 	sal_Bool bModified(sal_False);
213 	if (_rCurrentValue.getValue() != _rValueToSet.getValue())
214 	{
215         if ( _rValueToSet.hasValue() && ( !_rExpectedType.equals( _rValueToSet.getValueType() ) ) )
216         {
217             _rConvertedValue = Any( NULL, _rExpectedType.getTypeLibType() );
218 
219             if  ( !uno_type_assignData(
220                     const_cast< void* >( _rConvertedValue.getValue() ), _rConvertedValue.getValueType().getTypeLibType(),
221                     const_cast< void* >( _rValueToSet.getValue() ), _rValueToSet.getValueType().getTypeLibType(),
222                     reinterpret_cast< uno_QueryInterfaceFunc >(
223                         cpp_queryInterface),
224                     reinterpret_cast< uno_AcquireFunc >(cpp_acquire),
225                     reinterpret_cast< uno_ReleaseFunc >(cpp_release)
226                   )
227                 )
228                 throw starlang::IllegalArgumentException();
229         }
230         else
231             _rConvertedValue = _rValueToSet;
232 
233 		if ( _rCurrentValue != _rConvertedValue )
234 		{
235 			_rOldValue = _rCurrentValue;
236 			bModified = sal_True;
237 		}
238 	}
239 	return bModified;
240 }
241 
242 //.........................................................................
243 }
244 //.........................................................................
245 
246