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 <uielement/constitemcontainer.hxx>
21 #include <uielement/itemcontainer.hxx>
22 
23 #include <com/sun/star/beans/PropertyAttribute.hpp>
24 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
25 
26 #include <comphelper/propertysetinfo.hxx>
27 #include <comphelper/servicehelper.hxx>
28 #include <rtl/ref.hxx>
29 
30 using namespace cppu;
31 using namespace com::sun::star::uno;
32 using namespace com::sun::star::lang;
33 using namespace com::sun::star::beans;
34 using namespace com::sun::star::container;
35 
36 const int PROPHANDLE_UINAME     = 1;
37 constexpr OUStringLiteral PROPNAME_UINAME = u"UIName";
38 
39 namespace framework
40 {
41 
ConstItemContainer()42 ConstItemContainer::ConstItemContainer()
43 {
44 }
45 
ConstItemContainer(const ItemContainer & rItemContainer)46 ConstItemContainer::ConstItemContainer( const ItemContainer& rItemContainer )
47 {
48     ShareGuard aLock( rItemContainer.m_aShareMutex );
49     copyItemContainer( rItemContainer.m_aItemVector );
50 }
51 
ConstItemContainer(const Reference<XIndexAccess> & rSourceContainer,bool bFastCopy)52 ConstItemContainer::ConstItemContainer( const Reference< XIndexAccess >& rSourceContainer, bool bFastCopy )
53 {
54     // We also have to copy the UIName property
55     try
56     {
57         Reference< XPropertySet > xPropSet( rSourceContainer, UNO_QUERY );
58         if ( xPropSet.is() )
59         {
60             xPropSet->getPropertyValue("UIName") >>= m_aUIName;
61         }
62     }
63     catch ( const Exception& )
64     {
65     }
66 
67     if ( !rSourceContainer.is() )
68         return;
69 
70     try
71     {
72         sal_Int32 nCount = rSourceContainer->getCount();
73         m_aItemVector.reserve(nCount);
74         if ( bFastCopy )
75         {
76             for ( sal_Int32 i = 0; i < nCount; i++ )
77             {
78                 Sequence< PropertyValue > aPropSeq;
79                 if ( rSourceContainer->getByIndex( i ) >>= aPropSeq )
80                     m_aItemVector.push_back( aPropSeq );
81             }
82         }
83         else
84         {
85             for ( sal_Int32 i = 0; i < nCount; i++ )
86             {
87                 Sequence< PropertyValue > aPropSeq;
88                 if ( rSourceContainer->getByIndex( i ) >>= aPropSeq )
89                 {
90                     sal_Int32 nContainerIndex = -1;
91                     Reference< XIndexAccess > xIndexAccess;
92                     for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ )
93                     {
94                         if ( aPropSeq[j].Name == "ItemDescriptorContainer" )
95                         {
96                             aPropSeq[j].Value >>= xIndexAccess;
97                             nContainerIndex = j;
98                             break;
99                         }
100                     }
101 
102                     if ( xIndexAccess.is() && nContainerIndex >= 0 )
103                         aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess );
104 
105                     m_aItemVector.push_back( aPropSeq );
106                 }
107             }
108         }
109     }
110     catch ( const IndexOutOfBoundsException& )
111     {
112     }
113 }
114 
~ConstItemContainer()115 ConstItemContainer::~ConstItemContainer()
116 {
117 }
118 
119 // private
copyItemContainer(const std::vector<Sequence<PropertyValue>> & rSourceVector)120 void ConstItemContainer::copyItemContainer( const std::vector< Sequence< PropertyValue > >& rSourceVector )
121 {
122     const sal_uInt32 nCount = rSourceVector.size();
123     for ( sal_uInt32 i = 0; i < nCount; i++ )
124     {
125         sal_Int32 nContainerIndex = -1;
126         Sequence< PropertyValue > aPropSeq( rSourceVector[i] );
127         Reference< XIndexAccess > xIndexAccess;
128         for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ )
129         {
130             if ( aPropSeq[j].Name == "ItemDescriptorContainer" )
131             {
132                 aPropSeq[j].Value >>= xIndexAccess;
133                 nContainerIndex = j;
134                 break;
135             }
136         }
137 
138         if ( xIndexAccess.is() && nContainerIndex >= 0 )
139             aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess );
140 
141         m_aItemVector.push_back( aPropSeq );
142     }
143 }
144 
deepCopyContainer(const Reference<XIndexAccess> & rSubContainer)145 Reference< XIndexAccess > ConstItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer )
146 {
147     Reference< XIndexAccess > xReturn;
148     if ( rSubContainer.is() )
149     {
150         ItemContainer*      pSource = comphelper::getUnoTunnelImplementation<ItemContainer>( rSubContainer );
151         rtl::Reference<ConstItemContainer> pSubContainer;
152         if ( pSource )
153             pSubContainer = new ConstItemContainer( *pSource );
154         else
155             pSubContainer = new ConstItemContainer( rSubContainer );
156         xReturn = pSubContainer;
157     }
158 
159     return xReturn;
160 }
161 
162 // XUnoTunnel
getSomething(const css::uno::Sequence<sal_Int8> & rIdentifier)163 sal_Int64 ConstItemContainer::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
164 {
165     if( isUnoTunnelId<ConstItemContainer>(rIdentifier) )
166     {
167         return reinterpret_cast< sal_Int64 >( this );
168     }
169     return 0;
170 }
171 
getUnoTunnelId()172 const Sequence< sal_Int8 >& ConstItemContainer::getUnoTunnelId() noexcept
173 {
174     static const UnoTunnelIdInit theConstItemContainerUnoTunnelId;
175     return theConstItemContainerUnoTunnelId.getSeq();
176 }
177 
178 // XElementAccess
hasElements()179 sal_Bool SAL_CALL ConstItemContainer::hasElements()
180 {
181     return ( !m_aItemVector.empty() );
182 }
183 
184 // XIndexAccess
getCount()185 sal_Int32 SAL_CALL ConstItemContainer::getCount()
186 {
187     return m_aItemVector.size();
188 }
189 
getByIndex(sal_Int32 Index)190 Any SAL_CALL ConstItemContainer::getByIndex( sal_Int32 Index )
191 {
192     if ( sal_Int32( m_aItemVector.size()) <= Index )
193         throw IndexOutOfBoundsException( OUString(), static_cast<OWeakObject *>(this) );
194     return makeAny( m_aItemVector[Index] );
195 }
196 
197 // XPropertySet
getPropertySetInfo()198 Reference< XPropertySetInfo > SAL_CALL ConstItemContainer::getPropertySetInfo()
199 {
200     // Create structure of propertysetinfo for baseclass "OPropertySetHelper".
201     // (Use method "getInfoHelper()".)
202     static Reference< XPropertySetInfo > xInfo(new comphelper::PropertySetInfo(getInfoHelper().getProperties()));
203 
204     return xInfo;
205 }
206 
setPropertyValue(const OUString &,const Any &)207 void SAL_CALL ConstItemContainer::setPropertyValue( const OUString&, const Any& )
208 {
209 }
210 
getPropertyValue(const OUString & PropertyName)211 Any SAL_CALL ConstItemContainer::getPropertyValue( const OUString& PropertyName )
212 {
213     if ( PropertyName == PROPNAME_UINAME )
214         return makeAny( m_aUIName );
215 
216     throw UnknownPropertyException(PropertyName);
217 }
218 
addPropertyChangeListener(const OUString &,const css::uno::Reference<css::beans::XPropertyChangeListener> &)219 void SAL_CALL ConstItemContainer::addPropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& )
220 {
221 }
222 
removePropertyChangeListener(const OUString &,const css::uno::Reference<css::beans::XPropertyChangeListener> &)223 void SAL_CALL ConstItemContainer::removePropertyChangeListener( const OUString&, const css::uno::Reference< css::beans::XPropertyChangeListener >& )
224 {
225     // Only read-only properties - do nothing
226 }
227 
addVetoableChangeListener(const OUString &,const css::uno::Reference<css::beans::XVetoableChangeListener> &)228 void SAL_CALL ConstItemContainer::addVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& )
229 {
230     // Only read-only properties - do nothing
231 }
232 
removeVetoableChangeListener(const OUString &,const css::uno::Reference<css::beans::XVetoableChangeListener> &)233 void SAL_CALL ConstItemContainer::removeVetoableChangeListener( const OUString&, const css::uno::Reference< css::beans::XVetoableChangeListener >& )
234 {
235     // Only read-only properties - do nothing
236 }
237 
238 // XFastPropertySet
setFastPropertyValue(sal_Int32,const css::uno::Any &)239 void SAL_CALL ConstItemContainer::setFastPropertyValue( sal_Int32, const css::uno::Any& )
240 {
241 }
242 
getFastPropertyValue(sal_Int32 nHandle)243 Any SAL_CALL ConstItemContainer::getFastPropertyValue( sal_Int32 nHandle )
244 {
245     if ( nHandle == PROPHANDLE_UINAME )
246         return makeAny( m_aUIName );
247 
248     throw UnknownPropertyException(OUString::number(nHandle));
249 }
250 
getInfoHelper()251 ::cppu::IPropertyArrayHelper& ConstItemContainer::getInfoHelper()
252 {
253     // Define static member to give structure of properties to baseclass "OPropertySetHelper".
254     // "impl_getStaticPropertyDescriptor" is a non exported and static function, who will define a static propertytable.
255     // "true" say: Table is sorted by name.
256     static ::cppu::OPropertyArrayHelper ourInfoHelper( impl_getStaticPropertyDescriptor(), true );
257 
258     return ourInfoHelper;
259 }
260 
impl_getStaticPropertyDescriptor()261 css::uno::Sequence< css::beans::Property > ConstItemContainer::impl_getStaticPropertyDescriptor()
262 {
263     // Create a property array to initialize sequence!
264     // Table of all predefined properties of this class. It's used from OPropertySetHelper-class!
265     // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!!
266     // It's necessary for methods of OPropertySetHelper.
267     // ATTENTION:
268     //      YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!!
269 
270     return
271     {
272         css::beans::Property( PROPNAME_UINAME, PROPHANDLE_UINAME ,
273                               cppu::UnoType<OUString>::get(),
274                               css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY  )
275     };
276 }
277 
278 } // namespace framework
279 
280 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
281