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 #include "oox/helper/containerhelper.hxx" 29 30 #include <com/sun/star/container/XIndexContainer.hpp> 31 #include <com/sun/star/container/XNameContainer.hpp> 32 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 33 #include <com/sun/star/uno/XComponentContext.hpp> 34 #include <rtl/ustrbuf.hxx> 35 #include "oox/helper/helper.hxx" 36 37 namespace oox { 38 39 // ============================================================================ 40 41 using namespace ::com::sun::star::container; 42 using namespace ::com::sun::star::lang; 43 using namespace ::com::sun::star::uno; 44 45 using ::rtl::OUString; 46 using ::rtl::OUStringBuffer; 47 48 // ============================================================================ 49 50 namespace { 51 52 struct ValueRangeComp 53 { 54 inline bool operator()( const ValueRange& rRange, sal_Int32 nValue ) const { return rRange.mnLast < nValue; } 55 }; 56 57 } // namespace 58 59 // ---------------------------------------------------------------------------- 60 61 void ValueRangeSet::insert( const ValueRange& rRange ) 62 { 63 // find the first range that contains or follows the starting point of the passed range 64 ValueRangeVector::iterator aBeg = maRanges.begin(); 65 ValueRangeVector::iterator aEnd = maRanges.end(); 66 ValueRangeVector::iterator aIt = ::std::lower_bound( aBeg, aEnd, rRange.mnFirst, ValueRangeComp() ); 67 // nothing to do if found range contains passed range 68 if( (aIt != aEnd) && aIt->contains( rRange ) ) return; 69 // check if previous range can be used to merge with the passed range 70 if( (aIt != aBeg) && ((aIt - 1)->mnLast + 1 == rRange.mnFirst) ) --aIt; 71 // check if current range (aIt) can be used to merge with passed range 72 if( (aIt != aEnd) && aIt->intersects( rRange ) ) 73 { 74 // set new start value to existing range 75 aIt->mnFirst = ::std::min( aIt->mnFirst, rRange.mnFirst ); 76 // search first range that cannot be merged anymore (aNext) 77 ValueRangeVector::iterator aNext = aIt + 1; 78 while( (aNext != aEnd) && aNext->intersects( rRange ) ) ++aNext; 79 // set new end value to existing range 80 aIt->mnLast = ::std::max( (aNext - 1)->mnLast, rRange.mnLast ); 81 // remove ranges covered by new existing range (aIt) 82 maRanges.erase( aIt + 1, aNext ); 83 } 84 else 85 { 86 // merging not possible: insert new range 87 maRanges.insert( aIt, rRange ); 88 } 89 } 90 91 ValueRangeVector ValueRangeSet::getIntersection( const ValueRange& rRange ) const 92 { 93 ValueRangeVector aRanges; 94 // find the range that contains nFirst or the first range that follows nFirst 95 ValueRangeVector::const_iterator aIt = ::std::lower_bound( maRanges.begin(), maRanges.end(), rRange.mnFirst, ValueRangeComp() ); 96 for( ValueRangeVector::const_iterator aEnd = maRanges.end(); (aIt != aEnd) && (aIt->mnFirst <= rRange.mnLast); ++aIt ) 97 aRanges.push_back( ValueRange( ::std::max( aIt->mnFirst, rRange.mnFirst ), ::std::min( aIt->mnLast, rRange.mnLast ) ) ); 98 return aRanges; 99 } 100 101 // ============================================================================ 102 103 Reference< XIndexContainer > ContainerHelper::createIndexContainer( const Reference< XComponentContext >& rxContext ) 104 { 105 Reference< XIndexContainer > xContainer; 106 if( rxContext.is() ) try 107 { 108 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 109 xContainer.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.IndexedPropertyValues" ) ), UNO_QUERY_THROW ); 110 } 111 catch( Exception& ) 112 { 113 } 114 OSL_ENSURE( xContainer.is(), "ContainerHelper::createIndexContainer - cannot create container" ); 115 return xContainer; 116 } 117 118 bool ContainerHelper::insertByIndex( 119 const Reference< XIndexContainer >& rxIndexContainer, 120 sal_Int32 nIndex, const Any& rObject ) 121 { 122 OSL_ENSURE( rxIndexContainer.is(), "ContainerHelper::insertByIndex - missing XIndexContainer interface" ); 123 bool bRet = false; 124 try 125 { 126 rxIndexContainer->insertByIndex( nIndex, rObject ); 127 bRet = true; 128 } 129 catch( Exception& ) 130 { 131 } 132 OSL_ENSURE( bRet, "ContainerHelper::insertByIndex - cannot insert object" ); 133 return bRet; 134 } 135 136 Reference< XNameContainer > ContainerHelper::createNameContainer( const Reference< XComponentContext >& rxContext ) 137 { 138 Reference< XNameContainer > xContainer; 139 if( rxContext.is() ) try 140 { 141 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 142 xContainer.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.NamedPropertyValues" ) ), UNO_QUERY_THROW ); 143 } 144 catch( Exception& ) 145 { 146 } 147 OSL_ENSURE( xContainer.is(), "ContainerHelper::createNameContainer - cannot create container" ); 148 return xContainer; 149 } 150 151 OUString ContainerHelper::getUnusedName( 152 const Reference< XNameAccess >& rxNameAccess, const OUString& rSuggestedName, 153 sal_Unicode cSeparator, sal_Int32 nFirstIndexToAppend ) 154 { 155 OSL_ENSURE( rxNameAccess.is(), "ContainerHelper::getUnusedName - missing XNameAccess interface" ); 156 157 OUString aNewName = rSuggestedName; 158 sal_Int32 nIndex = nFirstIndexToAppend; 159 while( rxNameAccess->hasByName( aNewName ) ) 160 aNewName = OUStringBuffer( rSuggestedName ).append( cSeparator ).append( nIndex++ ).makeStringAndClear(); 161 return aNewName; 162 } 163 164 bool ContainerHelper::insertByName( 165 const Reference< XNameContainer >& rxNameContainer, 166 const OUString& rName, const Any& rObject, bool bReplaceOldExisting ) 167 { 168 OSL_ENSURE( rxNameContainer.is(), "ContainerHelper::insertByName - missing XNameContainer interface" ); 169 bool bRet = false; 170 try 171 { 172 if( bReplaceOldExisting && rxNameContainer->hasByName( rName ) ) 173 rxNameContainer->replaceByName( rName, rObject ); 174 else 175 rxNameContainer->insertByName( rName, rObject ); 176 bRet = true; 177 } 178 catch( Exception& ) 179 { 180 } 181 OSL_ENSURE( bRet, "ContainerHelper::insertByName - cannot insert object" ); 182 return bRet; 183 } 184 185 OUString ContainerHelper::insertByUnusedName( 186 const Reference< XNameContainer >& rxNameContainer, 187 const OUString& rSuggestedName, sal_Unicode cSeparator, 188 const Any& rObject, bool bRenameOldExisting ) 189 { 190 OSL_ENSURE( rxNameContainer.is(), "ContainerHelper::insertByUnusedName - missing XNameContainer interface" ); 191 192 // find an unused name 193 Reference< XNameAccess > xNameAccess( rxNameContainer, UNO_QUERY ); 194 OUString aNewName = getUnusedName( xNameAccess, rSuggestedName, cSeparator ); 195 196 // rename existing object 197 if( bRenameOldExisting && rxNameContainer->hasByName( rSuggestedName ) ) 198 { 199 try 200 { 201 Any aOldObject = rxNameContainer->getByName( rSuggestedName ); 202 rxNameContainer->removeByName( rSuggestedName ); 203 rxNameContainer->insertByName( aNewName, aOldObject ); 204 aNewName = rSuggestedName; 205 } 206 catch( Exception& ) 207 { 208 OSL_ENSURE( false, "ContainerHelper::insertByUnusedName - cannot rename old object" ); 209 } 210 } 211 212 // insert the new object and return its resulting name 213 insertByName( rxNameContainer, aNewName, rObject ); 214 return aNewName; 215 } 216 217 // ============================================================================ 218 219 } // namespace oox 220