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 
33 #include "svx/UnoNamespaceMap.hxx"
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 
37 #ifndef _CPPUHELPER_IMPLBASE3_HXX_
38 #include <cppuhelper/implbase2.hxx>
39 #endif
40 #include <osl/diagnose.h>
41 #include <osl/mutex.hxx>
42 #include <comphelper/stl_types.hxx>
43 #include <svl/itempool.hxx>
44 #include "svx/unoapi.hxx"
45 #include "editeng/xmlcnitm.hxx"
46 
47 
48 using namespace ::comphelper;
49 using namespace ::osl;
50 using namespace ::cppu;
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::container;
54 using namespace ::com::sun::star::drawing;
55 using namespace ::com::sun::star::lang;
56 using namespace ::com::sun::star::beans;
57 
58 namespace svx
59 {
60 	/**	implements a component to export namespaces of all SvXMLAttrContainerItem inside
61 		one or two pools with a variable count of which ids.
62 	*/
63 	class NamespaceMap : public WeakImplHelper2< XNameAccess, XServiceInfo >
64 	{
65 	private:
66 		sal_uInt16* mpWhichIds;
67 		SfxItemPool* mpPool;
68 
69 	public:
70 		NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool );
71 		virtual ~NamespaceMap();
72 
73 		// XNameAccess
74 		virtual Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
75 		virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (RuntimeException);
76 		virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (RuntimeException);
77 
78 		// XElementAccess
79 		virtual Type SAL_CALL getElementType(  ) throw (RuntimeException);
80 		virtual sal_Bool SAL_CALL hasElements(  ) throw (RuntimeException);
81 
82 		// XServiceInfo
83 		virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(RuntimeException);
84 		virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw(RuntimeException);
85 		virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(RuntimeException);
86 	};
87 
88 	Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool1, SfxItemPool* )
89 	{
90 		return (XWeak*)new NamespaceMap( pWhichIds, pPool1 );
91 	}
92 
93 	Reference< XInterface > SAL_CALL NamespaceMap_createInstance( sal_uInt16* pWhichIds, SfxItemPool* pPool )
94 	{
95 		return (XWeak*)new NamespaceMap( pWhichIds, pPool );
96 	}
97 
98 	Sequence< ::rtl::OUString > SAL_CALL NamespaceMap_getSupportedServiceNames()
99 		throw()
100 	{
101 		Sequence< ::rtl::OUString > aSupportedServiceNames( 1 );
102 		aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.NamespaceMap" ) );
103 		return aSupportedServiceNames;
104 	}
105 
106 	::rtl::OUString SAL_CALL NamespaceMap_getImplementationName()
107 		throw()
108 	{
109 		return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.NamespaceMap" ) );
110 	}
111 
112 
113 
114 	class NamespaceIteratorImpl
115 	{
116 	private:
117 		SfxItemPool* mpPool;
118 
119 		sal_uInt16* mpWhichId;
120 
121 		sal_uInt32 mnItemCount;
122 		sal_uInt32 mnItem;
123 
124 		const SvXMLAttrContainerItem* mpCurrentAttr;
125 		sal_uInt16 mnCurrentAttr;
126 
127 	public:
128 
129 		NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool );
130 
131 		sal_Bool next( ::rtl::OUString& rPrefix, ::rtl::OUString& rURL );
132 	};
133 }
134 
135 using namespace ::svx;
136 
137 // -------------
138 
139 NamespaceIteratorImpl::NamespaceIteratorImpl( sal_uInt16* pWhichIds, SfxItemPool* pPool )
140 {
141 	mpPool = pPool;
142 	mpCurrentAttr = NULL;
143 	mnCurrentAttr = 0;
144 
145 	mpWhichId = pWhichIds;
146 
147 	mnItem = 0;
148 	mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount2( *mpWhichId ) : 0;
149 }
150 
151 sal_Bool NamespaceIteratorImpl::next( ::rtl::OUString& rPrefix, ::rtl::OUString& rURL )
152 {
153 	// we still need to process the current attribute
154 	if( mpCurrentAttr && (mnCurrentAttr != USHRT_MAX) )
155 	{
156 		rPrefix = mpCurrentAttr->GetPrefix( mnCurrentAttr );
157 		rURL = mpCurrentAttr->GetNamespace( mnCurrentAttr );
158 
159 		mnCurrentAttr = mpCurrentAttr->GetNextNamespaceIndex( mnCurrentAttr );
160 		return sal_True;
161 	}
162 
163 	// we need the next namespace item
164 	mpCurrentAttr = NULL;
165 
166 	const SfxPoolItem* pItem = 0;
167 	// look for the next available item in the current pool
168 	while( (mnItem < mnItemCount) && ( NULL == (pItem = mpPool->GetItem2( *mpWhichId, mnItem ) ) ) )
169 		mnItem++;
170 
171 	// are we finished with the current whichid?
172 	if( mnItem == mnItemCount )
173 	{
174 		mpWhichId++;
175 
176 		// are we finished with the current pool?
177 		if( 0 != *mpWhichId )
178 		{
179 			mnItem = 0;
180 			mnItemCount = (mpWhichId && (0 != *mpWhichId) && mpPool) ? mpPool->GetItemCount2( *mpWhichId ) : 0;
181 			return next( rPrefix, rURL );
182 		}
183 
184 		pItem = NULL;
185 	}
186 
187 	if( pItem )
188 	{
189 		mnItem++;
190 
191 		// get that item and see if there namespaces inside
192 		const SvXMLAttrContainerItem *pUnknown = (const SvXMLAttrContainerItem *)pItem;
193 		if( (pUnknown->GetAttrCount() > 0) )
194 		{
195 			mpCurrentAttr = pUnknown;
196 			mnCurrentAttr = pUnknown->GetFirstNamespaceIndex();
197 		}
198 		return next( rPrefix, rURL );
199 	}
200 
201 	return false;
202 }
203 
204 // -------------
205 
206 NamespaceMap::NamespaceMap( sal_uInt16* pWhichIds, SfxItemPool* pPool )
207 : mpWhichIds( pWhichIds ), mpPool( pPool )
208 {
209 }
210 
211 NamespaceMap::~NamespaceMap()
212 {
213 }
214 
215 // XNameAccess
216 Any SAL_CALL NamespaceMap::getByName( const ::rtl::OUString& aName ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
217 {
218 	NamespaceIteratorImpl aIter( mpWhichIds, mpPool );
219 
220 	::rtl::OUString aPrefix;
221 	::rtl::OUString aURL;
222 
223 	sal_Bool bFound;
224 
225 	do
226 	{
227 		bFound = aIter.next( aPrefix, aURL );
228 	}
229 	while( bFound && (aPrefix != aName ) );
230 
231 	if( !bFound )
232 		throw NoSuchElementException();
233 
234 	return makeAny( aURL );
235 }
236 
237 Sequence< ::rtl::OUString > SAL_CALL NamespaceMap::getElementNames() throw (RuntimeException)
238 {
239 	NamespaceIteratorImpl aIter( mpWhichIds, mpPool );
240 
241 	::rtl::OUString aPrefix;
242 	::rtl::OUString aURL;
243 
244 	std::set< ::rtl::OUString, comphelper::UStringLess > aPrefixSet;
245 
246 	while( aIter.next( aPrefix, aURL ) )
247 		aPrefixSet.insert( aPrefix );
248 
249 	Sequence< ::rtl::OUString > aSeq( aPrefixSet.size() );
250 	::rtl::OUString* pPrefixes = aSeq.getArray();
251 
252 	std::set< ::rtl::OUString, comphelper::UStringLess >::iterator aPrefixIter( aPrefixSet.begin() );
253 	const std::set< ::rtl::OUString, comphelper::UStringLess >::iterator aEnd( aPrefixSet.end() );
254 
255 	while( aPrefixIter != aEnd )
256 	{
257 		*pPrefixes++ = *aPrefixIter++;
258 	}
259 
260 	return aSeq;
261 }
262 
263 sal_Bool SAL_CALL NamespaceMap::hasByName( const ::rtl::OUString& aName ) throw (RuntimeException)
264 {
265 	NamespaceIteratorImpl aIter( mpWhichIds, mpPool );
266 
267 	::rtl::OUString aPrefix;
268 	::rtl::OUString aURL;
269 
270 	sal_Bool bFound;
271 
272 	do
273 	{
274 		bFound = aIter.next( aPrefix, aURL );
275 	}
276 	while( bFound && (aPrefix != aName ) );
277 
278 	return bFound;
279 }
280 
281 // XElementAccess
282 Type SAL_CALL NamespaceMap::getElementType() throw (RuntimeException)
283 {
284 	return ::getCppuType( (const ::rtl::OUString*) 0 );
285 }
286 
287 sal_Bool SAL_CALL NamespaceMap::hasElements() throw (RuntimeException)
288 {
289 	NamespaceIteratorImpl aIter( mpWhichIds, mpPool );
290 
291 	::rtl::OUString aPrefix;
292 	::rtl::OUString aURL;
293 
294 	return aIter.next( aPrefix, aURL );
295 }
296 
297 // XServiceInfo
298 ::rtl::OUString SAL_CALL NamespaceMap::getImplementationName(  )
299 	throw(RuntimeException)
300 {
301 	return NamespaceMap_getImplementationName();
302 }
303 
304 sal_Bool SAL_CALL NamespaceMap::supportsService( const ::rtl::OUString& )
305 	throw(RuntimeException)
306 {
307 	return sal_True;
308 }
309 
310 Sequence< ::rtl::OUString > SAL_CALL NamespaceMap::getSupportedServiceNames(  )
311 	throw(RuntimeException)
312 {
313 	return NamespaceMap_getSupportedServiceNames();
314 }
315