xref: /trunk/main/comphelper/source/property/property.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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