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_stoc.hxx"
30 #include <rtl/strbuf.hxx>
31 
32 #include <com/sun/star/reflection/XIdlField.hpp>
33 #include <com/sun/star/reflection/XIdlField2.hpp>
34 #include "com/sun/star/uno/TypeClass.hpp"
35 
36 #include "base.hxx"
37 
38 
39 namespace stoc_corefl
40 {
41 
42 //==================================================================================================
43 class IdlCompFieldImpl
44 	: public IdlMemberImpl
45 	, public XIdlField
46 	, public XIdlField2
47 {
48 	sal_Int32					_nOffset;
49 
50 public:
51 	IdlCompFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName,
52 					  typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr,
53 					  sal_Int32 nOffset )
54 		: IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr )
55 		, _nOffset( nOffset )
56 		{}
57 
58 	// XInterface
59 	virtual Any SAL_CALL queryInterface( const Type & rType ) throw (::com::sun::star::uno::RuntimeException);
60 	virtual void SAL_CALL acquire() throw ();
61 	virtual void SAL_CALL release() throw ();
62 
63 	// XTypeProvider
64 	virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException);
65 	virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException);
66 
67 	// XIdlMember
68     virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() throw(::com::sun::star::uno::RuntimeException);
69     virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
70 	// XIdlField
71     virtual Reference< XIdlClass > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException);
72     virtual FieldAccessMode SAL_CALL getAccessMode() throw(::com::sun::star::uno::RuntimeException);
73     virtual Any SAL_CALL get( const Any & rObj ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
74     virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException);
75 	// XIdlField2: getType, getAccessMode and get are equal to XIdlField
76     virtual void SAL_CALL set( Any & rObj, const Any & rValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException);
77 };
78 
79 // XInterface
80 //__________________________________________________________________________________________________
81 Any IdlCompFieldImpl::queryInterface( const Type & rType )
82 	throw(::com::sun::star::uno::RuntimeException)
83 {
84 	Any aRet( ::cppu::queryInterface( rType,
85     								  static_cast< XIdlField * >( this ),
86     								  static_cast< XIdlField2 * >( this ) ) );
87 	return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType ));
88 }
89 //__________________________________________________________________________________________________
90 void IdlCompFieldImpl::acquire() throw()
91 {
92 	IdlMemberImpl::acquire();
93 }
94 //__________________________________________________________________________________________________
95 void IdlCompFieldImpl::release() throw()
96 {
97 	IdlMemberImpl::release();
98 }
99 
100 // XTypeProvider
101 //__________________________________________________________________________________________________
102 Sequence< Type > IdlCompFieldImpl::getTypes()
103 	throw (::com::sun::star::uno::RuntimeException)
104 {
105 	static OTypeCollection * s_pTypes = 0;
106 	if (! s_pTypes)
107 	{
108 		MutexGuard aGuard( getMutexAccess() );
109 		if (! s_pTypes)
110 		{
111 			static OTypeCollection s_aTypes(
112 				::getCppuType( (const Reference< XIdlField2 > *)0 ),
113 				::getCppuType( (const Reference< XIdlField > *)0 ),
114 				IdlMemberImpl::getTypes() );
115 			s_pTypes = &s_aTypes;
116 		}
117 	}
118 	return s_pTypes->getTypes();
119 }
120 //__________________________________________________________________________________________________
121 Sequence< sal_Int8 > IdlCompFieldImpl::getImplementationId()
122 	throw (::com::sun::star::uno::RuntimeException)
123 {
124 	static OImplementationId * s_pId = 0;
125 	if (! s_pId)
126 	{
127 		MutexGuard aGuard( getMutexAccess() );
128 		if (! s_pId)
129 		{
130 			static OImplementationId s_aId;
131 			s_pId = &s_aId;
132 		}
133 	}
134 	return s_pId->getImplementationId();
135 }
136 
137 // XIdlMember
138 //__________________________________________________________________________________________________
139 Reference< XIdlClass > IdlCompFieldImpl::getDeclaringClass()
140 	throw(::com::sun::star::uno::RuntimeException)
141 {
142 	if (! _xDeclClass.is())
143 	{
144 		MutexGuard aGuard( getMutexAccess() );
145 		if (! _xDeclClass.is())
146 		{
147 			typelib_CompoundTypeDescription * pTD =
148 				(typelib_CompoundTypeDescription *)getDeclTypeDescr();
149 			while (pTD)
150 			{
151 				typelib_TypeDescriptionReference ** ppTypeRefs = pTD->ppTypeRefs;
152 				for ( sal_Int32 nPos = pTD->nMembers; nPos--; )
153 				{
154 					if (td_equals( (typelib_TypeDescription *)getTypeDescr(), ppTypeRefs[nPos] ))
155 					{
156 						_xDeclClass = getReflection()->forType( (typelib_TypeDescription *)pTD );
157 						return _xDeclClass;
158 					}
159 				}
160 				pTD = pTD->pBaseTypeDescription;
161 			}
162 		}
163 	}
164 	return _xDeclClass;
165 }
166 //__________________________________________________________________________________________________
167 OUString IdlCompFieldImpl::getName()
168 	throw(::com::sun::star::uno::RuntimeException)
169 {
170 	return IdlMemberImpl::getName();
171 }
172 
173 // XIdlField
174 //__________________________________________________________________________________________________
175 Reference< XIdlClass > IdlCompFieldImpl::getType()
176 	throw(::com::sun::star::uno::RuntimeException)
177 {
178 	return getReflection()->forType( getTypeDescr() );
179 }
180 //__________________________________________________________________________________________________
181 FieldAccessMode IdlCompFieldImpl::getAccessMode()
182 	throw(::com::sun::star::uno::RuntimeException)
183 {
184     return FieldAccessMode_READWRITE;
185 }
186 //__________________________________________________________________________________________________
187 Any IdlCompFieldImpl::get( const Any & rObj )
188 	throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
189 {
190 	if (rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_STRUCT ||
191 		rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_EXCEPTION)
192 	{
193 		typelib_TypeDescription * pObjTD = 0;
194 		TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() );
195 
196 		typelib_TypeDescription * pTD = pObjTD;
197 		typelib_TypeDescription * pDeclTD = getDeclTypeDescr();
198 		while (pTD && !typelib_typedescription_equals( pTD, pDeclTD ))
199 			pTD = (typelib_TypeDescription *)((typelib_CompoundTypeDescription *)pTD)->pBaseTypeDescription;
200 
201 		OSL_ENSURE( pTD, "### illegal object type!" );
202 		if (pTD)
203 		{
204 			TYPELIB_DANGER_RELEASE( pObjTD );
205 			Any aRet;
206 			uno_any_destruct(
207                 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
208 			uno_any_construct(
209                 &aRet, (char *)rObj.getValue() + _nOffset, getTypeDescr(),
210                 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
211 			return aRet;
212 		}
213 		TYPELIB_DANGER_RELEASE( pObjTD );
214 	}
215 	throw IllegalArgumentException(
216 		OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ),
217 		(XWeak *)(OWeakObject *)this, 0 );
218 }
219 //__________________________________________________________________________________________________
220 void IdlCompFieldImpl::set( const Any & rObj, const Any & rValue )
221 	throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException)
222 {
223 	if (rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_STRUCT ||
224 		rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_EXCEPTION)
225 	{
226 		typelib_TypeDescription * pObjTD = 0;
227 		TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() );
228 
229 		typelib_TypeDescription * pTD = pObjTD;
230 		typelib_TypeDescription * pDeclTD = getDeclTypeDescr();
231 		while (pTD && !typelib_typedescription_equals( pTD, pDeclTD ))
232 			pTD = (typelib_TypeDescription *)((typelib_CompoundTypeDescription *)pTD)->pBaseTypeDescription;
233 
234 		OSL_ENSURE( pTD, "### illegal object type!" );
235 		if (pTD)
236 		{
237 			TYPELIB_DANGER_RELEASE( pObjTD );
238 			if (coerce_assign( (char *)rObj.getValue() + _nOffset, getTypeDescr(), rValue, getReflection() ))
239 			{
240 				return;
241 			}
242 			else
243 			{
244 				throw IllegalArgumentException(
245 					OUString( RTL_CONSTASCII_USTRINGPARAM("illegal value given!") ),
246 					(XWeak *)(OWeakObject *)this, 1 );
247 			}
248 		}
249 		TYPELIB_DANGER_RELEASE( pObjTD );
250 	}
251 	throw IllegalArgumentException(
252 		OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ),
253 		(XWeak *)(OWeakObject *)this, 0 );
254 }
255 
256 //__________________________________________________________________________________________________
257 void IdlCompFieldImpl::set( Any & rObj, const Any & rValue )
258 	throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException)
259 {
260 	if (rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_STRUCT ||
261 		rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_EXCEPTION)
262 	{
263 		typelib_TypeDescription * pObjTD = 0;
264 		TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() );
265 
266 		typelib_TypeDescription * pTD = pObjTD;
267 		typelib_TypeDescription * pDeclTD = getDeclTypeDescr();
268 		while (pTD && !typelib_typedescription_equals( pTD, pDeclTD ))
269 			pTD = (typelib_TypeDescription *)((typelib_CompoundTypeDescription *)pTD)->pBaseTypeDescription;
270 
271 		OSL_ENSURE( pTD, "### illegal object type!" );
272 		if (pTD)
273 		{
274 			TYPELIB_DANGER_RELEASE( pObjTD );
275 			if (coerce_assign( (char *)rObj.getValue() + _nOffset, getTypeDescr(), rValue, getReflection() ))
276 			{
277 				return;
278 			}
279 			else
280 			{
281 				throw IllegalArgumentException(
282 					OUString( RTL_CONSTASCII_USTRINGPARAM("illegal value given!") ),
283 					(XWeak *)(OWeakObject *)this, 1 );
284 			}
285 		}
286 		TYPELIB_DANGER_RELEASE( pObjTD );
287 	}
288 	throw IllegalArgumentException(
289 		OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ),
290 		(XWeak *)(OWeakObject *)this, 0 );
291 }
292 
293 //##################################################################################################
294 //##################################################################################################
295 //##################################################################################################
296 
297 
298 //__________________________________________________________________________________________________
299 CompoundIdlClassImpl::~CompoundIdlClassImpl()
300 {
301 	delete _pFields;
302 }
303 
304 //__________________________________________________________________________________________________
305 sal_Bool CompoundIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType )
306 	throw(::com::sun::star::uno::RuntimeException)
307 {
308 	if (xType.is())
309 	{
310 		TypeClass eTC = xType->getTypeClass();
311 		if (eTC == TypeClass_STRUCT || eTC == TypeClass_EXCEPTION)
312 		{
313 			if (equals( xType ))
314 				return sal_True;
315 			else
316 			{
317 				const Sequence< Reference< XIdlClass > > & rSeq = xType->getSuperclasses();
318 				if (rSeq.getLength())
319 				{
320 					OSL_ENSURE( rSeq.getLength() == 1, "### unexpected len of super classes!" );
321 					return isAssignableFrom( rSeq[0] );
322 				}
323 			}
324 		}
325 	}
326 	return sal_False;
327 }
328 //__________________________________________________________________________________________________
329 Sequence< Reference< XIdlClass > > CompoundIdlClassImpl::getSuperclasses()
330 	throw(::com::sun::star::uno::RuntimeException)
331 {
332 	if (! _xSuperClass.is())
333 	{
334 		MutexGuard aGuard( getMutexAccess() );
335 		if (! _xSuperClass.is())
336 		{
337 			typelib_CompoundTypeDescription * pCompTypeDescr = getTypeDescr()->pBaseTypeDescription;
338 			if (pCompTypeDescr)
339 				_xSuperClass = getReflection()->forType( (typelib_TypeDescription *)pCompTypeDescr );
340 		}
341 	}
342 	if (_xSuperClass.is())
343 		return Sequence< Reference< XIdlClass > >( &_xSuperClass, 1 );
344 	else
345 		return Sequence< Reference< XIdlClass > >();
346 }
347 //__________________________________________________________________________________________________
348 Reference< XIdlField > CompoundIdlClassImpl::getField( const OUString & rName )
349 	throw(::com::sun::star::uno::RuntimeException)
350 {
351 	if (! _pFields)
352 		getFields(); // init fields
353 
354 	const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) );
355 	if (iFind != _aName2Field.end())
356 		return Reference< XIdlField >( (*iFind).second );
357 	else
358 		return Reference< XIdlField >();
359 }
360 //__________________________________________________________________________________________________
361 Sequence< Reference< XIdlField > > CompoundIdlClassImpl::getFields()
362 	throw(::com::sun::star::uno::RuntimeException)
363 {
364 	MutexGuard aGuard( getMutexAccess() );
365 	if (! _pFields)
366 	{
367 		sal_Int32 nAll = 0;
368 		typelib_CompoundTypeDescription * pCompTypeDescr = getTypeDescr();
369 		for ( ; pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
370 			nAll += pCompTypeDescr->nMembers;
371 
372 		Sequence< Reference< XIdlField > > * pFields =
373 			new Sequence< Reference< XIdlField > >( nAll );
374 		Reference< XIdlField > * pSeq = pFields->getArray();
375 
376 		for ( pCompTypeDescr = getTypeDescr(); pCompTypeDescr;
377 			  pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
378 		{
379 			typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs;
380 			rtl_uString ** ppNames						   = pCompTypeDescr->ppMemberNames;
381 			sal_Int32 * pMemberOffsets					   = pCompTypeDescr->pMemberOffsets;
382 
383 			for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; )
384 			{
385 				typelib_TypeDescription * pTD = 0;
386 				TYPELIB_DANGER_GET( &pTD, ppTypeRefs[nPos] );
387 				OSL_ENSURE( pTD, "### cannot get field in struct!" );
388 				if (pTD)
389 				{
390 					OUString aName( ppNames[nPos] );
391 					_aName2Field[aName] = pSeq[--nAll] = new IdlCompFieldImpl(
392 						getReflection(), aName, pTD, IdlClassImpl::getTypeDescr(), pMemberOffsets[nPos] );
393 					TYPELIB_DANGER_RELEASE( pTD );
394 				}
395 			}
396 		}
397 
398 		_pFields = pFields;
399 	}
400 	return *_pFields;
401 }
402 
403 }
404 
405 
406