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