1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_unotools.hxx" 26 27 #include <unotools/atom.hxx> 28 29 using namespace utl; 30 using namespace ::com::sun::star::uno; 31 using namespace ::com::sun::star::util; 32 #define NMSP_UTIL ::com::sun::star::util 33 34 AtomProvider::AtomProvider() 35 { 36 m_nAtoms = 1; 37 } 38 39 AtomProvider::~AtomProvider() 40 { 41 } 42 43 int AtomProvider::getAtom( const ::rtl::OUString& rString, sal_Bool bCreate ) 44 { 45 ::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::iterator it = m_aAtomMap.find( rString ); 46 if( it != m_aAtomMap.end() ) 47 return it->second; 48 if( ! bCreate ) 49 return INVALID_ATOM; 50 m_aAtomMap[ rString ] = m_nAtoms; 51 m_aStringMap[ m_nAtoms ] = rString; 52 m_nAtoms++; 53 return m_nAtoms-1; 54 } 55 56 void AtomProvider::getAll( ::std::list< ::utl::AtomDescription >& atoms ) 57 { 58 atoms.clear(); 59 ::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::const_iterator it = m_aAtomMap.begin(); 60 61 ::utl::AtomDescription aDesc; 62 while( it != m_aAtomMap.end() ) 63 { 64 aDesc.atom = it->second; 65 aDesc.description = it->first; 66 atoms.push_back( aDesc ); 67 ++it; 68 } 69 } 70 71 void AtomProvider::getRecent( int atom, ::std::list< ::utl::AtomDescription >& atoms ) 72 { 73 atoms.clear(); 74 75 ::std::hash_map< ::rtl::OUString, int, ::rtl::OUStringHash >::const_iterator it = m_aAtomMap.begin(); 76 77 ::utl::AtomDescription aDesc; 78 while( it != m_aAtomMap.end() ) 79 { 80 if( it->second > atom ) 81 { 82 aDesc.atom = it->second; 83 aDesc.description = it->first; 84 atoms.push_back( aDesc ); 85 } 86 ++it; 87 } 88 } 89 90 const ::rtl::OUString& AtomProvider::getString( int nAtom ) const 91 { 92 static ::rtl::OUString aEmpty; 93 ::std::hash_map< int, ::rtl::OUString, ::std::hash< int > >::const_iterator it = m_aStringMap.find( nAtom ); 94 95 return it == m_aStringMap.end() ? aEmpty : it->second; 96 } 97 98 void AtomProvider::overrideAtom( int atom, const ::rtl::OUString& description ) 99 { 100 m_aAtomMap[ description ] = atom; 101 m_aStringMap[ atom ] = description; 102 if( m_nAtoms <= atom ) 103 m_nAtoms=atom+1; 104 } 105 106 sal_Bool AtomProvider::hasAtom( int atom ) const 107 { 108 return m_aStringMap.find( atom ) != m_aStringMap.end() ? sal_True : sal_False; 109 } 110 111 // ----------------------------------------------------------------------- 112 113 MultiAtomProvider::MultiAtomProvider() 114 { 115 } 116 117 MultiAtomProvider::~MultiAtomProvider() 118 { 119 for( ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it = m_aAtomLists.begin(); it != m_aAtomLists.end(); ++it ) 120 delete it->second; 121 } 122 123 124 sal_Bool MultiAtomProvider::insertAtomClass( int atomClass ) 125 { 126 ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it = 127 m_aAtomLists.find( atomClass ); 128 if( it != m_aAtomLists.end() ) 129 return sal_False; 130 m_aAtomLists[ atomClass ] = new AtomProvider(); 131 return sal_True; 132 } 133 134 int MultiAtomProvider::getAtom( int atomClass, const ::rtl::OUString& rString, sal_Bool bCreate ) 135 { 136 ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::iterator it = 137 m_aAtomLists.find( atomClass ); 138 if( it != m_aAtomLists.end() ) 139 return it->second->getAtom( rString, bCreate ); 140 141 if( bCreate ) 142 { 143 AtomProvider* pNewClass; 144 m_aAtomLists[ atomClass ] = pNewClass = new AtomProvider(); 145 return pNewClass->getAtom( rString, bCreate ); 146 } 147 return INVALID_ATOM; 148 } 149 150 int MultiAtomProvider::getLastAtom( int atomClass ) const 151 { 152 ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = 153 m_aAtomLists.find( atomClass ); 154 155 return it != m_aAtomLists.end() ? it->second->getLastAtom() : INVALID_ATOM; 156 } 157 158 void MultiAtomProvider::getRecent( int atomClass, int atom, ::std::list< ::utl::AtomDescription >& atoms ) 159 { 160 ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = 161 m_aAtomLists.find( atomClass ); 162 if( it != m_aAtomLists.end() ) 163 it->second->getRecent( atom, atoms ); 164 else 165 atoms.clear(); 166 } 167 168 const ::rtl::OUString& MultiAtomProvider::getString( int atomClass, int atom ) const 169 { 170 ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = 171 m_aAtomLists.find( atomClass ); 172 if( it != m_aAtomLists.end() ) 173 return it->second->getString( atom ); 174 175 static ::rtl::OUString aEmpty; 176 return aEmpty; 177 } 178 179 sal_Bool MultiAtomProvider::hasAtom( int atomClass, int atom ) const 180 { 181 ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass ); 182 return it != m_aAtomLists.end() ? it->second->hasAtom( atom ) : sal_False; 183 } 184 185 void MultiAtomProvider::getClass( int atomClass, ::std::list< ::utl::AtomDescription >& atoms) const 186 { 187 ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass ); 188 189 if( it != m_aAtomLists.end() ) 190 it->second->getAll( atoms ); 191 else 192 atoms.clear(); 193 } 194 195 void MultiAtomProvider::overrideAtom( int atomClass, int atom, const ::rtl::OUString& description ) 196 { 197 ::std::hash_map< int, AtomProvider*, ::std::hash< int > >::const_iterator it = m_aAtomLists.find( atomClass ); 198 if( it == m_aAtomLists.end() ) 199 m_aAtomLists[ atomClass ] = new AtomProvider(); 200 m_aAtomLists[ atomClass ]->overrideAtom( atom, description ); 201 } 202 203 // ----------------------------------------------------------------------- 204 205 AtomServer::AtomServer() 206 { 207 } 208 209 AtomServer::~AtomServer() 210 { 211 } 212 213 sal_Int32 AtomServer::getAtom( sal_Int32 atomClass, const ::rtl::OUString& description, sal_Bool create ) throw() 214 { 215 ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); 216 217 return m_aProvider.getAtom( atomClass, description, create ); 218 } 219 220 Sequence< Sequence< NMSP_UTIL::AtomDescription > > AtomServer::getClasses( const Sequence< sal_Int32 >& atomClasses ) throw() 221 { 222 ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); 223 224 Sequence< Sequence< NMSP_UTIL::AtomDescription > > aRet( atomClasses.getLength() ); 225 for( int i = 0; i < atomClasses.getLength(); i++ ) 226 { 227 aRet.getArray()[i] = getClass( atomClasses.getConstArray()[i] ); 228 } 229 return aRet; 230 } 231 232 Sequence< NMSP_UTIL::AtomDescription > AtomServer::getClass( sal_Int32 atomClass ) throw() 233 { 234 ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); 235 236 ::std::list< ::utl::AtomDescription > atoms; 237 m_aProvider.getClass( atomClass, atoms ); 238 239 Sequence< NMSP_UTIL::AtomDescription > aRet( atoms.size() ); 240 for( int i = aRet.getLength()-1; i >= 0; i-- ) 241 { 242 aRet.getArray()[i].atom = atoms.back().atom; 243 aRet.getArray()[i].description = atoms.back().description; 244 atoms.pop_back(); 245 } 246 247 return aRet; 248 } 249 250 Sequence< NMSP_UTIL::AtomDescription > AtomServer::getRecentAtoms( sal_Int32 atomClass, sal_Int32 atom ) throw() 251 { 252 ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); 253 254 ::std::list< ::utl::AtomDescription > atoms; 255 m_aProvider.getRecent( atomClass, atom, atoms ); 256 257 Sequence< NMSP_UTIL::AtomDescription > aRet( atoms.size() ); 258 for( int i = aRet.getLength()-1; i >= 0; i-- ) 259 { 260 aRet.getArray()[i].atom = atoms.back().atom; 261 aRet.getArray()[i].description = atoms.back().description; 262 atoms.pop_back(); 263 } 264 265 return aRet; 266 } 267 268 Sequence< ::rtl::OUString > AtomServer::getAtomDescriptions( const Sequence< AtomClassRequest >& atoms ) throw() 269 { 270 ::osl::Guard< ::osl::Mutex > guard( m_aMutex ); 271 272 int nStrings = 0, i; 273 for( i = 0; i < atoms.getLength(); i++ ) 274 nStrings += atoms.getConstArray()[ i ].atoms.getLength(); 275 Sequence< ::rtl::OUString > aRet( nStrings ); 276 for( i = 0, nStrings = 0; i < atoms.getLength(); i++ ) 277 { 278 const AtomClassRequest& rRequest = atoms.getConstArray()[i]; 279 for( int n = 0; n < rRequest.atoms.getLength(); n++ ) 280 aRet.getArray()[ nStrings++ ] = m_aProvider.getString( rRequest.atomClass, rRequest.atoms.getConstArray()[ n ] ); 281 } 282 return aRet; 283 } 284 285 // ----------------------------------------------------------------------- 286 287 AtomClient::AtomClient( const Reference< XAtomServer >& xServer ) : 288 m_xServer( xServer ) 289 { 290 } 291 292 AtomClient::~AtomClient() 293 { 294 } 295 296 int AtomClient::getAtom( int atomClass, const ::rtl::OUString& description, sal_Bool bCreate ) 297 { 298 int nAtom = m_aProvider.getAtom( atomClass, description, sal_False ); 299 if( nAtom == INVALID_ATOM && bCreate ) 300 { 301 try 302 { 303 nAtom = m_xServer->getAtom( atomClass, description, bCreate ); 304 } 305 catch( RuntimeException& ) 306 { 307 return INVALID_ATOM; 308 } 309 if( nAtom != INVALID_ATOM ) 310 m_aProvider.overrideAtom( atomClass, nAtom, description ); 311 } 312 return nAtom; 313 } 314 315 const ::rtl::OUString& AtomClient::getString( int atomClass, int atom ) 316 { 317 static ::rtl::OUString aEmpty; 318 319 if( ! m_aProvider.hasAtom( atomClass, atom ) ) 320 { 321 Sequence< NMSP_UTIL::AtomDescription > aSeq; 322 try 323 { 324 aSeq = m_xServer->getRecentAtoms( atomClass, m_aProvider.getLastAtom( atomClass ) ); 325 } 326 catch( RuntimeException& ) 327 { 328 return aEmpty; 329 } 330 const NMSP_UTIL::AtomDescription* pDescriptions = aSeq.getConstArray(); 331 for( int i = 0; i < aSeq.getLength(); i++ ) 332 m_aProvider.overrideAtom( atomClass, 333 pDescriptions[i].atom, 334 pDescriptions[i].description 335 ); 336 337 if( ! m_aProvider.hasAtom( atomClass, atom ) ) 338 { 339 // holes may occur by the above procedure! 340 Sequence< AtomClassRequest > aReq( 1 ); 341 aReq.getArray()[0].atomClass = atomClass; 342 aReq.getArray()[0].atoms.realloc( 1 ); 343 aReq.getArray()[0].atoms.getArray()[0] = atom; 344 Sequence< ::rtl::OUString > aRet; 345 try 346 { 347 aRet = m_xServer->getAtomDescriptions( aReq ); 348 } 349 catch( RuntimeException& ) 350 { 351 return aEmpty; 352 } 353 if( aRet.getLength() == 1 ) 354 m_aProvider.overrideAtom( atomClass, atom, aRet.getConstArray()[0] ); 355 } 356 } 357 return m_aProvider.getString( atomClass, atom ); 358 } 359 360 void AtomClient::updateAtomClasses( const Sequence< sal_Int32 >& atomClasses ) 361 { 362 Sequence< Sequence< NMSP_UTIL::AtomDescription > > aUpdate; 363 try 364 { 365 aUpdate = m_xServer->getClasses( atomClasses ); 366 } 367 catch( RuntimeException& ) 368 { 369 return; 370 } 371 for( int i = 0; i < atomClasses.getLength(); i++ ) 372 { 373 int nClass = atomClasses.getConstArray()[i]; 374 const Sequence< NMSP_UTIL::AtomDescription >& rClass = aUpdate.getConstArray()[i]; 375 const NMSP_UTIL::AtomDescription* pDesc = rClass.getConstArray(); 376 for( int n = 0; n < rClass.getLength(); n++, pDesc++ ) 377 m_aProvider.overrideAtom( nClass, pDesc->atom, pDesc->description ); 378 } 379 } 380