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_svx.hxx"
30 
31 #include <set>
32 #include <svl/itempool.hxx>
33 #include <svl/itemset.hxx>
34 #include <svl/style.hxx>
35 #include <comphelper/stl_types.hxx>
36 
37 #include <svx/svdmodel.hxx>
38 #include "UnoNameItemTable.hxx"
39 #include <vos/mutex.hxx>
40 #include <vcl/svapp.hxx>
41 
42 #include "svx/unoapi.hxx"
43 
44 using namespace ::com::sun::star;
45 using namespace ::rtl;
46 using namespace ::cppu;
47 using namespace ::vos;
48 
49 SvxUnoNameItemTable::SvxUnoNameItemTable( SdrModel* pModel, sal_uInt16 nWhich, sal_uInt8 nMemberId ) throw()
50 : mpModel( pModel ),
51   mpModelPool( pModel ? &pModel->GetItemPool() : NULL ),
52   mnWhich( nWhich ), mnMemberId( nMemberId )
53 {
54 	if( pModel )
55 		StartListening( *pModel );
56 }
57 
58 SvxUnoNameItemTable::~SvxUnoNameItemTable() throw()
59 {
60 	if( mpModel )
61 		EndListening( *mpModel );
62 	dispose();
63 }
64 
65 bool SvxUnoNameItemTable::isValid( const NameOrIndex* pItem ) const
66 {
67 	return pItem && (pItem->GetName().Len() != 0);
68 }
69 
70 void SvxUnoNameItemTable::dispose()
71 {
72 	ItemPoolVector::iterator aIter = maItemSetVector.begin();
73 	const ItemPoolVector::iterator aEnd = maItemSetVector.end();
74 
75 	while( aIter != aEnd )
76 	{
77 		delete (*aIter++);
78 	}
79 
80 	maItemSetVector.clear();
81 }
82 
83 void SvxUnoNameItemTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) throw()
84 {
85 	const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
86 
87 	if( pSdrHint && HINT_MODELCLEARED == pSdrHint->GetKind() )
88 		dispose();
89 }
90 
91 sal_Bool SAL_CALL SvxUnoNameItemTable::supportsService( const  OUString& ServiceName ) throw(uno::RuntimeException)
92 {
93     uno::Sequence< OUString > aSNL( getSupportedServiceNames() );
94     const OUString * pArray = aSNL.getConstArray();
95 
96     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
97         if( pArray[i] == ServiceName )
98             return sal_True;
99 
100     return sal_False;
101 }
102 
103 void SAL_CALL SvxUnoNameItemTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement )
104 {
105 	SfxItemSet* mpInSet = new SfxItemSet( *mpModelPool, mnWhich, mnWhich );
106 	maItemSetVector.push_back( mpInSet );
107 
108 	NameOrIndex* pNewItem = createItem();
109 	pNewItem->SetName( String( aName ) );
110 	pNewItem->PutValue( aElement, mnMemberId );
111 	mpInSet->Put( *pNewItem, mnWhich );
112 	delete pNewItem;
113 }
114 
115 // XNameContainer
116 void SAL_CALL SvxUnoNameItemTable::insertByName( const OUString& aApiName, const uno::Any& aElement )
117 	throw( lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException )
118 {
119 	OGuard aGuard( Application::GetSolarMutex() );
120 
121 	if( hasByName( aApiName ) )
122 		throw container::ElementExistException();
123 
124 	String aName;
125 	SvxUnogetInternalNameForItem( mnWhich, aApiName, aName );
126 
127 	ImplInsertByName( aName, aElement );
128 }
129 
130 
131 
132 void SAL_CALL SvxUnoNameItemTable::removeByName( const OUString& aApiName )
133 	throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
134 {
135 	OGuard aGuard( Application::GetSolarMutex() );
136 
137 	// a little quickfix for 2.0 to let applications clear api
138 	// created items that are not used
139 	if( aApiName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("~clear~") ) )
140 	{
141 		dispose();
142 		return;
143 	}
144 
145 	String Name;
146 	SvxUnogetInternalNameForItem( mnWhich, aApiName, Name );
147 
148 	ItemPoolVector::iterator aIter = maItemSetVector.begin();
149 	const ItemPoolVector::iterator aEnd = maItemSetVector.end();
150 
151 	NameOrIndex *pItem;
152 	const String aSearchName( Name );
153 
154 	while( aIter != aEnd )
155 	{
156 		pItem = (NameOrIndex *)&((*aIter)->Get( mnWhich ) );
157 		if( pItem->GetName() == aSearchName )
158 		{
159 			delete (*aIter);
160 			maItemSetVector.erase( aIter );
161 			return;
162 		}
163 		aIter++;
164 	}
165 
166 	if( !hasByName( Name ) )
167 		throw container::NoSuchElementException();
168 }
169 
170 // XNameReplace
171 void SAL_CALL SvxUnoNameItemTable::replaceByName( const OUString& aApiName, const uno::Any& aElement )
172 	throw( lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException )
173 {
174 	OGuard aGuard( Application::GetSolarMutex() );
175 
176 	String aName;
177 	SvxUnogetInternalNameForItem( mnWhich, aApiName, aName );
178 
179 	ItemPoolVector::iterator aIter = maItemSetVector.begin();
180 	const ItemPoolVector::iterator aEnd = maItemSetVector.end();
181 
182 	NameOrIndex *pItem;
183 	const String aSearchName( aName );
184 
185 	while( aIter != aEnd )
186 	{
187 		pItem = (NameOrIndex *)&((*aIter)->Get( mnWhich ) );
188 		if( pItem->GetName() == aSearchName )
189 		{
190 			NameOrIndex* pNewItem = createItem();
191 			pNewItem->SetName( aSearchName );
192 			if( !pNewItem->PutValue( aElement, mnMemberId ) || !isValid( pNewItem ) )
193 				throw lang::IllegalArgumentException();
194 
195 			(*aIter)->Put( *pNewItem );
196 			return;
197 		}
198 		aIter++;
199 	}
200 
201 	// if it is not in our own sets, modify the pool!
202 	sal_Bool bFound = sal_False;
203 
204 	sal_uInt32 nSurrogate;
205 	sal_uInt32 nCount = mpModelPool ? mpModelPool->GetItemCount2( mnWhich ) : 0;
206 	for( nSurrogate = 0; nSurrogate < nCount; nSurrogate++ )
207 	{
208 		pItem = (NameOrIndex*)mpModelPool->GetItem2( mnWhich, nSurrogate);
209 		if( pItem && pItem->GetName() == aSearchName )
210 		{
211 			pItem->PutValue( aElement, mnMemberId );
212 			bFound = sal_True;
213 			break;
214 		}
215 	}
216 
217 	if( bFound )
218 		ImplInsertByName( aName, aElement );
219 	else
220 		throw container::NoSuchElementException();
221 
222 	if( !hasByName( aName ) )
223 		throw container::NoSuchElementException();
224 }
225 
226 // XNameAccess
227 uno::Any SAL_CALL SvxUnoNameItemTable::getByName( const OUString& aApiName )
228 	throw( container::NoSuchElementException,  lang::WrappedTargetException, uno::RuntimeException)
229 {
230 	OGuard aGuard( Application::GetSolarMutex() );
231 
232 	String aName;
233 	SvxUnogetInternalNameForItem( mnWhich, aApiName, aName );
234 
235 	uno::Any aAny;
236 
237 	if( mpModelPool && aName.Len() != 0 )
238 	{
239 		const String aSearchName( aName );
240 		NameOrIndex *pItem;
241 		sal_uInt32 nSurrogate;
242 
243 		sal_uInt32 nSurrogateCount = mpModelPool ? mpModelPool->GetItemCount2( mnWhich ) : 0;
244 		for( nSurrogate = 0; nSurrogate < nSurrogateCount; nSurrogate++ )
245 		{
246 			pItem = (NameOrIndex*)mpModelPool->GetItem2( mnWhich, nSurrogate );
247 
248 			if( isValid( pItem ) && (pItem->GetName() == aSearchName) )
249 			{
250 				pItem->QueryValue( aAny, mnMemberId );
251 				return aAny;
252 			}
253 		}
254 	}
255 
256 	throw container::NoSuchElementException();
257 }
258 
259 uno::Sequence< OUString > SAL_CALL SvxUnoNameItemTable::getElementNames(  )
260 	throw( uno::RuntimeException )
261 {
262 	OGuard aGuard( Application::GetSolarMutex() );
263 
264 	std::set< OUString, comphelper::UStringLess > aNameSet;
265 
266 	NameOrIndex *pItem;
267 	OUString aApiName;
268 
269 	const sal_uInt32 nSurrogateCount = mpModelPool ? mpModelPool->GetItemCount2( mnWhich ) : 0;
270 	sal_uInt32 nSurrogate;
271 	for( nSurrogate = 0; nSurrogate < nSurrogateCount; nSurrogate++ )
272 	{
273 		pItem = (NameOrIndex*)mpModelPool->GetItem2( mnWhich, nSurrogate );
274 
275 		if( !isValid( pItem ) )
276 			continue;
277 
278 		SvxUnogetApiNameForItem( mnWhich, pItem->GetName(), aApiName );
279 		aNameSet.insert( aApiName );
280 	}
281 
282 	uno::Sequence< OUString > aSeq( aNameSet.size() );
283 	OUString* pNames = aSeq.getArray();
284 
285 	std::set< OUString, comphelper::UStringLess >::iterator aIter( aNameSet.begin() );
286 	const std::set< OUString, comphelper::UStringLess >::iterator aEnd( aNameSet.end() );
287 
288 	while( aIter != aEnd )
289 	{
290 		*pNames++ = *aIter++;
291 	}
292 
293 	return aSeq;
294 }
295 
296 sal_Bool SAL_CALL SvxUnoNameItemTable::hasByName( const OUString& aApiName )
297 	throw( uno::RuntimeException )
298 {
299 	OGuard aGuard( Application::GetSolarMutex() );
300 
301 	String aName;
302 	SvxUnogetInternalNameForItem( mnWhich, aApiName, aName );
303 
304 	if( aName.Len() == 0 )
305 		return sal_False;
306 
307 	const String aSearchName( aName );
308 	sal_uInt32 nSurrogate;
309 
310 	const NameOrIndex *pItem;
311 
312 	sal_uInt32 nCount = mpModelPool ? mpModelPool->GetItemCount2( mnWhich ) : 0;
313 	for( nSurrogate = 0; nSurrogate < nCount; nSurrogate++ )
314 	{
315 		pItem = (NameOrIndex*)mpModelPool->GetItem2( mnWhich, nSurrogate );
316 		if( isValid( pItem ) && (pItem->GetName() == aSearchName) )
317 			return sal_True;
318 	}
319 
320 	return sal_False;
321 }
322 
323 sal_Bool SAL_CALL SvxUnoNameItemTable::hasElements(  )
324 	throw( uno::RuntimeException )
325 {
326 	OGuard aGuard( Application::GetSolarMutex() );
327 
328 	const NameOrIndex *pItem;
329 
330 	sal_uInt32 nSurrogate;
331 	const sal_uInt32 nSurrogateCount = mpModelPool ? mpModelPool->GetItemCount2( mnWhich ) : 0;
332 	for( nSurrogate = 0; nSurrogate < nSurrogateCount; nSurrogate++ )
333 	{
334 		pItem = (NameOrIndex*)mpModelPool->GetItem2( mnWhich, nSurrogate );
335 
336 		if( isValid( pItem ) )
337 			return sal_True;
338 	}
339 
340 	return sal_False;
341 }
342