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