xref: /aoo41x/main/unotools/source/misc/atom.cxx (revision cdf0e10c)
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_unotools.hxx"
30 
31 #include <unotools/atom.hxx>
32 
33 using namespace utl;
34 using namespace ::com::sun::star::uno;
35 using namespace ::com::sun::star::util;
36 #define NMSP_UTIL ::com::sun::star::util
37 
38 AtomProvider::AtomProvider()
39 {
40 	m_nAtoms = 1;
41 }
42 
43 AtomProvider::~AtomProvider()
44 {
45 }
46 
47 int AtomProvider::getAtom( const ::rtl::OUString& rString, sal_Bool bCreate )
48 {
49 	::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::iterator it = m_aAtomMap.find( rString );
50 	if( it != m_aAtomMap.end() )
51 		return it->second;
52 	if( ! bCreate )
53 		return INVALID_ATOM;
54 	m_aAtomMap[ rString ] = m_nAtoms;
55 	m_aStringMap[ m_nAtoms ] = rString;
56 	m_nAtoms++;
57 	return m_nAtoms-1;
58 }
59 
60 void AtomProvider::getAll( ::std::list< ::utl::AtomDescription >& atoms )
61 {
62 	atoms.clear();
63 	::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::const_iterator it = m_aAtomMap.begin();
64 
65 	::utl::AtomDescription aDesc;
66 	while( it != m_aAtomMap.end() )
67 	{
68 		aDesc.atom			= it->second;
69 		aDesc.description	= it->first;
70 		atoms.push_back( aDesc );
71 		++it;
72 	}
73 }
74 
75 void AtomProvider::getRecent( int atom, ::std::list< ::utl::AtomDescription >& atoms )
76 {
77 	atoms.clear();
78 
79 	::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::const_iterator it = m_aAtomMap.begin();
80 
81 	::utl::AtomDescription aDesc;
82 	while( it != m_aAtomMap.end() )
83 	{
84 		if( it->second > atom )
85 		{
86 			aDesc.atom			= it->second;
87 			aDesc.description	= it->first;
88 			atoms.push_back( aDesc );
89 		}
90 		++it;
91 	}
92 }
93 
94 const ::rtl::OUString& AtomProvider::getString( int nAtom ) const
95 {
96 	static ::rtl::OUString aEmpty;
97 	::std::hash_map< int, ::rtl::OUString, ::std::hash< int > >::const_iterator it = m_aStringMap.find( nAtom );
98 
99 	return it == m_aStringMap.end() ? aEmpty : it->second;
100 }
101 
102 void AtomProvider::overrideAtom( int atom, const ::rtl::OUString& description )
103 {
104 	m_aAtomMap[ description ] = atom;
105 	m_aStringMap[ atom ] = description;
106 	if( m_nAtoms <= atom )
107 		m_nAtoms=atom+1;
108 }
109 
110 sal_Bool AtomProvider::hasAtom( int atom ) const
111 {
112 	return m_aStringMap.find( atom ) != m_aStringMap.end() ? sal_True : sal_False;
113 }
114 
115 // -----------------------------------------------------------------------
116 
117 MultiAtomProvider::MultiAtomProvider()
118 {
119 }
120 
121 MultiAtomProvider::~MultiAtomProvider()
122 {
123 	for( ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it = m_aAtomLists.begin(); it != m_aAtomLists.end(); ++it )
124 		delete it->second;
125 }
126 
127 
128 sal_Bool MultiAtomProvider::insertAtomClass( int atomClass )
129 {
130 	::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it =
131 		  m_aAtomLists.find( atomClass );
132 	if( it != m_aAtomLists.end() )
133 		return sal_False;
134 	m_aAtomLists[ atomClass ] = new AtomProvider();
135 	return sal_True;
136 }
137 
138 int MultiAtomProvider::getAtom( int atomClass, const ::rtl::OUString& rString, sal_Bool bCreate )
139 {
140 	::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it =
141 		  m_aAtomLists.find( atomClass );
142 	if( it != m_aAtomLists.end() )
143 		return it->second->getAtom( rString, bCreate );
144 
145 	if( bCreate )
146 	{
147 		AtomProvider* pNewClass;
148 		m_aAtomLists[ atomClass ] = pNewClass = new AtomProvider();
149 		return pNewClass->getAtom( rString, bCreate );
150 	}
151 	return INVALID_ATOM;
152 }
153 
154 int MultiAtomProvider::getLastAtom( int atomClass ) const
155 {
156 	::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it =
157 		  m_aAtomLists.find( atomClass );
158 
159 	return it != m_aAtomLists.end() ? it->second->getLastAtom() : INVALID_ATOM;
160 }
161 
162 void MultiAtomProvider::getRecent( int atomClass, int atom, ::std::list< ::utl::AtomDescription >& atoms )
163 {
164 	::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it =
165 		  m_aAtomLists.find( atomClass );
166 	if( it != m_aAtomLists.end() )
167 		it->second->getRecent( atom, atoms );
168 	else
169 		atoms.clear();
170 }
171 
172 const ::rtl::OUString& MultiAtomProvider::getString( int atomClass, int atom ) const
173 {
174 	::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it =
175 		  m_aAtomLists.find( atomClass );
176 	if( it != m_aAtomLists.end() )
177 		return it->second->getString( atom );
178 
179 	static ::rtl::OUString aEmpty;
180 	return aEmpty;
181 }
182 
183 sal_Bool MultiAtomProvider::hasAtom( int atomClass, int atom ) const
184 {
185 	::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass );
186 	return it != m_aAtomLists.end() ? it->second->hasAtom( atom ) : sal_False;
187 }
188 
189 void MultiAtomProvider::getClass( int atomClass, ::std::list< ::utl::AtomDescription >& atoms) const
190 {
191 	::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass );
192 
193 	if( it != m_aAtomLists.end() )
194 		it->second->getAll( atoms );
195 	else
196 		atoms.clear();
197 }
198 
199 void MultiAtomProvider::overrideAtom( int atomClass, int atom, const ::rtl::OUString& description )
200 {
201 	::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass );
202 	if( it == m_aAtomLists.end() )
203 		m_aAtomLists[ atomClass ] = new AtomProvider();
204 	m_aAtomLists[ atomClass ]->overrideAtom( atom, description );
205 }
206 
207 // -----------------------------------------------------------------------
208 
209 AtomServer::AtomServer()
210 {
211 }
212 
213 AtomServer::~AtomServer()
214 {
215 }
216 
217 sal_Int32 AtomServer::getAtom( sal_Int32 atomClass, const ::rtl::OUString& description, sal_Bool create ) throw()
218 {
219 	::osl::Guard< ::osl::Mutex > guard( m_aMutex );
220 
221 	return m_aProvider.getAtom( atomClass, description, create );
222 }
223 
224 Sequence< Sequence< NMSP_UTIL::AtomDescription > > AtomServer::getClasses( const Sequence< sal_Int32 >& atomClasses ) throw()
225 {
226 	::osl::Guard< ::osl::Mutex > guard( m_aMutex );
227 
228 	Sequence< Sequence< NMSP_UTIL::AtomDescription > > aRet( atomClasses.getLength() );
229 	for( int i = 0; i < atomClasses.getLength(); i++ )
230 	{
231 		aRet.getArray()[i] = getClass( atomClasses.getConstArray()[i] );
232 	}
233 	return aRet;
234 }
235 
236 Sequence< NMSP_UTIL::AtomDescription > AtomServer::getClass( sal_Int32 atomClass ) throw()
237 {
238 	::osl::Guard< ::osl::Mutex > guard( m_aMutex );
239 
240 	::std::list< ::utl::AtomDescription > atoms;
241 	m_aProvider.getClass( atomClass, atoms );
242 
243 	Sequence< NMSP_UTIL::AtomDescription > aRet( atoms.size() );
244 	for( int i = aRet.getLength()-1; i >= 0; i-- )
245 	{
246 		aRet.getArray()[i].atom			= atoms.back().atom;
247 		aRet.getArray()[i].description	= atoms.back().description;
248 		atoms.pop_back();
249 	}
250 
251 	return aRet;
252 }
253 
254 Sequence< NMSP_UTIL::AtomDescription > AtomServer::getRecentAtoms( sal_Int32 atomClass, sal_Int32 atom ) throw()
255 {
256 	::osl::Guard< ::osl::Mutex > guard( m_aMutex );
257 
258 	::std::list< ::utl::AtomDescription > atoms;
259 	m_aProvider.getRecent( atomClass, atom, atoms );
260 
261 	Sequence< NMSP_UTIL::AtomDescription > aRet( atoms.size() );
262 	for( int i = aRet.getLength()-1; i >= 0; i-- )
263 	{
264 		aRet.getArray()[i].atom			= atoms.back().atom;
265 		aRet.getArray()[i].description	= atoms.back().description;
266 		atoms.pop_back();
267 	}
268 
269 	return aRet;
270 }
271 
272 Sequence< ::rtl::OUString > AtomServer::getAtomDescriptions( const Sequence< AtomClassRequest >& atoms ) throw()
273 {
274 	::osl::Guard< ::osl::Mutex > guard( m_aMutex );
275 
276 	int nStrings = 0, i;
277 	for( i = 0; i < atoms.getLength(); i++ )
278 		nStrings += atoms.getConstArray()[ i ].atoms.getLength();
279 	Sequence< ::rtl::OUString > aRet( nStrings );
280 	for( i = 0, nStrings = 0; i < atoms.getLength(); i++ )
281 	{
282 		const AtomClassRequest& rRequest = atoms.getConstArray()[i];
283 		for( int n = 0; n < rRequest.atoms.getLength(); n++ )
284 			aRet.getArray()[ nStrings++ ] = m_aProvider.getString( rRequest.atomClass, rRequest.atoms.getConstArray()[ n ] );
285 	}
286 	return aRet;
287 }
288 
289 // -----------------------------------------------------------------------
290 
291 AtomClient::AtomClient( const Reference< XAtomServer >& xServer ) :
292 		m_xServer( xServer )
293 {
294 }
295 
296 AtomClient::~AtomClient()
297 {
298 }
299 
300 int AtomClient::getAtom( int atomClass, const ::rtl::OUString& description, sal_Bool bCreate )
301 {
302 	int nAtom = m_aProvider.getAtom( atomClass, description, sal_False );
303 	if( nAtom == INVALID_ATOM && bCreate )
304 	{
305         try
306         {
307 		    nAtom = m_xServer->getAtom( atomClass, description, bCreate );
308         }
309         catch( RuntimeException& )
310         {
311             return INVALID_ATOM;
312         }
313 		if( nAtom != INVALID_ATOM )
314 			m_aProvider.overrideAtom( atomClass, nAtom, description );
315 	}
316 	return nAtom;
317 }
318 
319 const ::rtl::OUString& AtomClient::getString( int atomClass, int atom )
320 {
321     static ::rtl::OUString aEmpty;
322 
323 	if( ! m_aProvider.hasAtom( atomClass, atom ) )
324 	{
325 		Sequence< NMSP_UTIL::AtomDescription > aSeq;
326         try
327         {
328 		    aSeq = m_xServer->getRecentAtoms( atomClass, m_aProvider.getLastAtom( atomClass ) );
329         }
330         catch( RuntimeException& )
331         {
332             return aEmpty;
333         }
334 		const NMSP_UTIL::AtomDescription* pDescriptions = aSeq.getConstArray();
335 		for( int i = 0; i < aSeq.getLength(); i++ )
336 			m_aProvider.overrideAtom( atomClass,
337 									  pDescriptions[i].atom,
338 									  pDescriptions[i].description
339 									  );
340 
341 		if( ! m_aProvider.hasAtom( atomClass, atom ) )
342 		{
343 			// holes may occur by the above procedure!
344 			Sequence< AtomClassRequest > aReq( 1 );
345 			aReq.getArray()[0].atomClass = atomClass;
346 			aReq.getArray()[0].atoms.realloc( 1 );
347 			aReq.getArray()[0].atoms.getArray()[0] = atom;
348             Sequence< ::rtl::OUString > aRet;
349             try
350             {
351 			    aRet = m_xServer->getAtomDescriptions( aReq );
352             }
353             catch( RuntimeException& )
354             {
355                 return aEmpty;
356             }
357 			if( aRet.getLength() == 1 )
358 				m_aProvider.overrideAtom( atomClass, atom, aRet.getConstArray()[0] );
359 		}
360 	}
361 	return m_aProvider.getString( atomClass, atom );
362 }
363 
364 void AtomClient::updateAtomClasses( const Sequence< sal_Int32 >& atomClasses )
365 {
366 	Sequence< Sequence< NMSP_UTIL::AtomDescription > > aUpdate;
367     try
368     {
369         aUpdate = m_xServer->getClasses( atomClasses );
370     }
371     catch( RuntimeException& )
372     {
373         return;
374     }
375 	for( int i = 0; i < atomClasses.getLength(); i++ )
376 	{
377 		int nClass = atomClasses.getConstArray()[i];
378 		const Sequence< NMSP_UTIL::AtomDescription >& rClass = aUpdate.getConstArray()[i];
379 		const NMSP_UTIL::AtomDescription* pDesc = rClass.getConstArray();
380 		for( int n = 0; n < rClass.getLength(); n++, pDesc++ )
381 			m_aProvider.overrideAtom( nClass, pDesc->atom, pDesc->description );
382 	}
383 }
384