1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <cppuhelper/queryinterface.hxx>
21 #include <cppuhelper/typeprovider.hxx>
22 
23 #include <com/sun/star/reflection/XIdlField.hpp>
24 #include <com/sun/star/reflection/XIdlField2.hpp>
25 #include <com/sun/star/uno/TypeClass.hpp>
26 
27 #include "base.hxx"
28 
29 using namespace css::lang;
30 using namespace css::reflection;
31 using namespace css::uno;
32 
33 namespace stoc_corefl
34 {
35 
36 
37 class IdlCompFieldImpl
38     : public IdlMemberImpl
39     , public XIdlField
40     , public XIdlField2
41 {
42     sal_Int32 const             _nOffset;
43 
44 public:
IdlCompFieldImpl(IdlReflectionServiceImpl * pReflection,const OUString & rName,typelib_TypeDescription * pTypeDescr,typelib_TypeDescription * pDeclTypeDescr,sal_Int32 nOffset)45     IdlCompFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName,
46                       typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr,
47                       sal_Int32 nOffset )
48         : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr )
49         , _nOffset( nOffset )
50         {}
51 
52     // XInterface
53     virtual Any SAL_CALL queryInterface( const Type & rType ) override;
54     virtual void SAL_CALL acquire() throw () override;
55     virtual void SAL_CALL release() throw () override;
56 
57     // XTypeProvider
58     virtual Sequence< Type > SAL_CALL getTypes() override;
59     virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
60 
61     // XIdlMember
62     virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() override;
63     virtual OUString SAL_CALL getName() override;
64     // XIdlField
65     virtual Reference< XIdlClass > SAL_CALL getType() override;
66     virtual FieldAccessMode SAL_CALL getAccessMode() override;
67     virtual Any SAL_CALL get( const Any & rObj ) override;
68     virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) override;
69     // XIdlField2: getType, getAccessMode and get are equal to XIdlField
70     virtual void SAL_CALL set( Any & rObj, const Any & rValue ) override;
71 };
72 
73 // XInterface
74 
queryInterface(const Type & rType)75 Any IdlCompFieldImpl::queryInterface( const Type & rType )
76 {
77     Any aRet( ::cppu::queryInterface( rType,
78                                       static_cast< XIdlField * >( this ),
79                                       static_cast< XIdlField2 * >( this ) ) );
80     return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType ));
81 }
82 
acquire()83 void IdlCompFieldImpl::acquire() throw()
84 {
85     IdlMemberImpl::acquire();
86 }
87 
release()88 void IdlCompFieldImpl::release() throw()
89 {
90     IdlMemberImpl::release();
91 }
92 
93 // XTypeProvider
94 
getTypes()95 Sequence< Type > IdlCompFieldImpl::getTypes()
96 {
97     static cppu::OTypeCollection s_aTypes(
98         cppu::UnoType<XIdlField2>::get(),
99         cppu::UnoType<XIdlField>::get(),
100         IdlMemberImpl::getTypes() );
101 
102     return s_aTypes.getTypes();
103 }
104 
getImplementationId()105 Sequence< sal_Int8 > IdlCompFieldImpl::getImplementationId()
106 {
107     return css::uno::Sequence<sal_Int8>();
108 }
109 
110 // XIdlMember
111 
getDeclaringClass()112 Reference< XIdlClass > IdlCompFieldImpl::getDeclaringClass()
113 {
114     if (! _xDeclClass.is())
115     {
116         ::osl::MutexGuard aGuard( getMutexAccess() );
117         if (! _xDeclClass.is())
118         {
119             typelib_CompoundTypeDescription * pTD =
120                 reinterpret_cast<typelib_CompoundTypeDescription *>(getDeclTypeDescr());
121             while (pTD)
122             {
123                 typelib_TypeDescriptionReference ** ppTypeRefs = pTD->ppTypeRefs;
124                 for ( sal_Int32 nPos = pTD->nMembers; nPos--; )
125                 {
126                     if (td_equals( getTypeDescr(), ppTypeRefs[nPos] ))
127                     {
128                         _xDeclClass = getReflection()->forType( &pTD->aBase );
129                         return _xDeclClass;
130                     }
131                 }
132                 pTD = pTD->pBaseTypeDescription;
133             }
134         }
135     }
136     return _xDeclClass;
137 }
138 
getName()139 OUString IdlCompFieldImpl::getName()
140 {
141     return IdlMemberImpl::getName();
142 }
143 
144 // XIdlField
145 
getType()146 Reference< XIdlClass > IdlCompFieldImpl::getType()
147 {
148     return getReflection()->forType( getTypeDescr() );
149 }
150 
getAccessMode()151 FieldAccessMode IdlCompFieldImpl::getAccessMode()
152 {
153     return FieldAccessMode_READWRITE;
154 }
155 
get(const Any & rObj)156 Any IdlCompFieldImpl::get( const Any & rObj )
157 {
158     if (rObj.getValueTypeClass() == css::uno::TypeClass_STRUCT ||
159         rObj.getValueTypeClass() == css::uno::TypeClass_EXCEPTION)
160     {
161         typelib_TypeDescription * pObjTD = nullptr;
162         TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() );
163 
164         typelib_TypeDescription * pTD = pObjTD;
165         typelib_TypeDescription * pDeclTD = getDeclTypeDescr();
166         while (pTD && !typelib_typedescription_equals( pTD, pDeclTD ))
167             pTD = &reinterpret_cast<typelib_CompoundTypeDescription *>(pTD)->pBaseTypeDescription->aBase;
168 
169         OSL_ENSURE( pTD, "### illegal object type!" );
170         if (pTD)
171         {
172             TYPELIB_DANGER_RELEASE( pObjTD );
173             Any aRet;
174             uno_any_destruct(
175                 &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) );
176             uno_any_construct(
177                 &aRet, const_cast<char *>(static_cast<char const *>(rObj.getValue()) + _nOffset), getTypeDescr(),
178                 reinterpret_cast< uno_AcquireFunc >(cpp_acquire) );
179             return aRet;
180         }
181         TYPELIB_DANGER_RELEASE( pObjTD );
182     }
183     throw IllegalArgumentException(
184         "expected struct or exception, got " + rObj.getValueType().getTypeName(),
185         static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
186 }
187 
set(const Any & rObj,const Any & rValue)188 void IdlCompFieldImpl::set( const Any & rObj, const Any & rValue )
189 {
190     if (rObj.getValueTypeClass() == css::uno::TypeClass_STRUCT ||
191         rObj.getValueTypeClass() == css::uno::TypeClass_EXCEPTION)
192     {
193         typelib_TypeDescription * pObjTD = nullptr;
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 = &reinterpret_cast<typelib_CompoundTypeDescription *>(pTD)->pBaseTypeDescription->aBase;
200 
201         OSL_ENSURE( pTD, "### illegal object type!" );
202         if (pTD)
203         {
204             TYPELIB_DANGER_RELEASE( pObjTD );
205             if (!coerce_assign( const_cast<char *>(static_cast<char const *>(rObj.getValue()) + _nOffset), getTypeDescr(), rValue, getReflection() ))
206             {
207                 throw IllegalArgumentException(
208                     "cannot assign value to destination",
209                     static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 1 );
210             }
211             return;
212         }
213         TYPELIB_DANGER_RELEASE( pObjTD );
214     }
215     throw IllegalArgumentException(
216         "expected struct or exception, got " + rObj.getValueType().getTypeName(),
217         static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
218 }
219 
220 
set(Any & rObj,const Any & rValue)221 void IdlCompFieldImpl::set( Any & rObj, const Any & rValue )
222 {
223     if (rObj.getValueTypeClass() == css::uno::TypeClass_STRUCT ||
224         rObj.getValueTypeClass() == css::uno::TypeClass_EXCEPTION)
225     {
226         typelib_TypeDescription * pObjTD = nullptr;
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 = &reinterpret_cast<typelib_CompoundTypeDescription *>(pTD)->pBaseTypeDescription->aBase;
233 
234         OSL_ENSURE( pTD, "### illegal object type!" );
235         if (pTD)
236         {
237             TYPELIB_DANGER_RELEASE( pObjTD );
238             if (!coerce_assign( const_cast<char *>(static_cast<char const *>(rObj.getValue()) + _nOffset), getTypeDescr(), rValue, getReflection() ))
239             {
240                 throw IllegalArgumentException(
241                     "cannot assign to destination",
242                     static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 1 );
243             }
244             return;
245         }
246         TYPELIB_DANGER_RELEASE( pObjTD );
247     }
248     throw IllegalArgumentException(
249         "expected struct or exception, got " + rObj.getValueType().getTypeName(),
250         static_cast<XWeak *>(static_cast<OWeakObject *>(this)), 0 );
251 }
252 
253 
~CompoundIdlClassImpl()254 CompoundIdlClassImpl::~CompoundIdlClassImpl()
255 {
256 }
257 
258 
isAssignableFrom(const Reference<XIdlClass> & xType)259 sal_Bool CompoundIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType )
260 {
261     if (xType.is())
262     {
263         TypeClass eTC = xType->getTypeClass();
264         if (eTC == TypeClass_STRUCT || eTC == TypeClass_EXCEPTION)
265         {
266             if (equals( xType ))
267                 return true;
268             else
269             {
270                 const Sequence< Reference< XIdlClass > > & rSeq = xType->getSuperclasses();
271                 if (rSeq.hasElements())
272                 {
273                     OSL_ENSURE( rSeq.getLength() == 1, "### unexpected len of super classes!" );
274                     return isAssignableFrom( rSeq[0] );
275                 }
276             }
277         }
278     }
279     return false;
280 }
281 
getSuperclasses()282 Sequence< Reference< XIdlClass > > CompoundIdlClassImpl::getSuperclasses()
283 {
284     if (! _xSuperClass.is())
285     {
286         ::osl::MutexGuard aGuard( getMutexAccess() );
287         if (! _xSuperClass.is())
288         {
289             typelib_CompoundTypeDescription * pCompTypeDescr = getTypeDescr()->pBaseTypeDescription;
290             if (pCompTypeDescr)
291                 _xSuperClass = getReflection()->forType( &pCompTypeDescr->aBase );
292         }
293     }
294     if (_xSuperClass.is())
295         return Sequence< Reference< XIdlClass > >( &_xSuperClass, 1 );
296     else
297         return Sequence< Reference< XIdlClass > >();
298 }
299 
getField(const OUString & rName)300 Reference< XIdlField > CompoundIdlClassImpl::getField( const OUString & rName )
301 {
302     if (! _pFields)
303         getFields(); // init fields
304 
305     const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) );
306     if (iFind != _aName2Field.end())
307         return Reference< XIdlField >( (*iFind).second );
308     else
309         return Reference< XIdlField >();
310 }
311 
getFields()312 Sequence< Reference< XIdlField > > CompoundIdlClassImpl::getFields()
313 {
314     ::osl::MutexGuard aGuard( getMutexAccess() );
315     if (! _pFields)
316     {
317         sal_Int32 nAll = 0;
318         typelib_CompoundTypeDescription * pCompTypeDescr = getTypeDescr();
319         for ( ; pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
320             nAll += pCompTypeDescr->nMembers;
321 
322         Sequence< Reference< XIdlField > > * pFields =
323             new Sequence< Reference< XIdlField > >( nAll );
324         Reference< XIdlField > * pSeq = pFields->getArray();
325 
326         for ( pCompTypeDescr = getTypeDescr(); pCompTypeDescr;
327               pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription )
328         {
329             typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs;
330             rtl_uString ** ppNames                         = pCompTypeDescr->ppMemberNames;
331             sal_Int32 * pMemberOffsets                     = pCompTypeDescr->pMemberOffsets;
332 
333             for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; )
334             {
335                 typelib_TypeDescription * pTD = nullptr;
336                 TYPELIB_DANGER_GET( &pTD, ppTypeRefs[nPos] );
337                 OSL_ENSURE( pTD, "### cannot get field in struct!" );
338                 if (pTD)
339                 {
340                     OUString aName( ppNames[nPos] );
341                     _aName2Field[aName] = pSeq[--nAll] = new IdlCompFieldImpl(
342                         getReflection(), aName, pTD, IdlClassImpl::getTypeDescr(), pMemberOffsets[nPos] );
343                     TYPELIB_DANGER_RELEASE( pTD );
344                 }
345             }
346         }
347 
348         _pFields.reset( pFields );
349     }
350     return *_pFields;
351 }
352 
353 }
354 
355 
356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
357