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/core/contexthandler2.hxx" 29 #include <rtl/ustrbuf.hxx> 30 31 namespace oox { 32 namespace core { 33 34 // ============================================================================ 35 36 using namespace ::com::sun::star::uno; 37 using namespace ::com::sun::star::xml::sax; 38 39 using ::rtl::OUString; 40 using ::rtl::OUStringBuffer; 41 42 // ============================================================================ 43 44 /** Information about a processed element. */ 45 struct ElementInfo 46 { 47 OUStringBuffer maChars; /// Collected element characters. 48 sal_Int32 mnElement; /// The element identifier. 49 bool mbTrimSpaces; /// True = trims leading/trailing spaces from text data. 50 51 inline explicit ElementInfo() : mnElement( XML_TOKEN_INVALID ), mbTrimSpaces( false ) {} 52 }; 53 54 // ============================================================================ 55 56 ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace ) : 57 mxContextStack( new ContextStack ), 58 mnRootStackSize( 0 ), 59 mbEnableTrimSpace( bEnableTrimSpace ) 60 { 61 pushElementInfo( XML_ROOT_CONTEXT ); 62 } 63 64 ContextHandler2Helper::ContextHandler2Helper( const ContextHandler2Helper& rParent ) : 65 mxContextStack( rParent.mxContextStack ), 66 mnRootStackSize( rParent.mxContextStack->size() ), 67 mbEnableTrimSpace( rParent.mbEnableTrimSpace ) 68 { 69 } 70 71 ContextHandler2Helper::~ContextHandler2Helper() 72 { 73 } 74 75 sal_Int32 ContextHandler2Helper::getCurrentElement() const 76 { 77 return mxContextStack->empty() ? XML_ROOT_CONTEXT : mxContextStack->back().mnElement; 78 } 79 80 sal_Int32 ContextHandler2Helper::getParentElement( sal_Int32 nCountBack ) const 81 { 82 if( (nCountBack < 0) || (mxContextStack->size() < static_cast< size_t >( nCountBack )) ) 83 return XML_TOKEN_INVALID; 84 return (mxContextStack->size() == static_cast< size_t >( nCountBack )) ? 85 XML_ROOT_CONTEXT : (*mxContextStack)[ mxContextStack->size() - nCountBack - 1 ].mnElement; 86 } 87 88 bool ContextHandler2Helper::isRootElement() const 89 { 90 return mxContextStack->size() == mnRootStackSize + 1; 91 } 92 93 Reference< XFastContextHandler > ContextHandler2Helper::implCreateChildContext( 94 sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) 95 { 96 // #i76091# process collected characters (calls onCharacters() if needed) 97 processCollectedChars(); 98 ContextHandlerRef xContext = onCreateContext( nElement, AttributeList( rxAttribs ) ); 99 return Reference< XFastContextHandler >( xContext.get() ); 100 } 101 102 void ContextHandler2Helper::implStartElement( sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) 103 { 104 AttributeList aAttribs( rxAttribs ); 105 pushElementInfo( nElement ).mbTrimSpaces = aAttribs.getToken( XML_TOKEN( space ), XML_TOKEN_INVALID ) != XML_preserve; 106 onStartElement( aAttribs ); 107 } 108 109 void ContextHandler2Helper::implCharacters( const OUString& rChars ) 110 { 111 // #i76091# collect characters until new element starts or this element ends 112 if( !mxContextStack->empty() ) 113 mxContextStack->back().maChars.append( rChars ); 114 } 115 116 void ContextHandler2Helper::implEndElement( sal_Int32 nElement ) 117 { 118 (void)nElement; // prevent "unused parameter" warning in product build 119 OSL_ENSURE( getCurrentElement() == nElement, "ContextHandler2Helper::implEndElement - context stack broken" ); 120 if( !mxContextStack->empty() ) 121 { 122 // #i76091# process collected characters (calls onCharacters() if needed) 123 processCollectedChars(); 124 onEndElement(); 125 popElementInfo(); 126 } 127 } 128 129 ContextHandlerRef ContextHandler2Helper::implCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) 130 { 131 return onCreateRecordContext( nRecId, rStrm ); 132 } 133 134 void ContextHandler2Helper::implStartRecord( sal_Int32 nRecId, SequenceInputStream& rStrm ) 135 { 136 pushElementInfo( nRecId ); 137 onStartRecord( rStrm ); 138 } 139 140 void ContextHandler2Helper::implEndRecord( sal_Int32 nRecId ) 141 { 142 (void)nRecId; // prevent "unused parameter" warning in product build 143 OSL_ENSURE( getCurrentElement() == nRecId, "ContextHandler2Helper::implEndRecord - context stack broken" ); 144 if( !mxContextStack->empty() ) 145 { 146 onEndRecord(); 147 popElementInfo(); 148 } 149 } 150 151 ElementInfo& ContextHandler2Helper::pushElementInfo( sal_Int32 nElement ) 152 { 153 mxContextStack->resize( mxContextStack->size() + 1 ); 154 ElementInfo& rInfo = mxContextStack->back(); 155 rInfo.mnElement = nElement; 156 return rInfo; 157 } 158 159 void ContextHandler2Helper::popElementInfo() 160 { 161 OSL_ENSURE( !mxContextStack->empty(), "ContextHandler2Helper::popElementInfo - context stack broken" ); 162 if( !mxContextStack->empty() ) 163 mxContextStack->pop_back(); 164 } 165 166 void ContextHandler2Helper::processCollectedChars() 167 { 168 OSL_ENSURE( !mxContextStack->empty(), "ContextHandler2Helper::processCollectedChars - no context info" ); 169 ElementInfo& rInfo = mxContextStack->back(); 170 if( rInfo.maChars.getLength() > 0 ) 171 { 172 OUString aChars = rInfo.maChars.makeStringAndClear(); 173 if( mbEnableTrimSpace && rInfo.mbTrimSpaces ) 174 aChars = aChars.trim(); 175 if( aChars.getLength() > 0 ) 176 onCharacters( aChars ); 177 } 178 } 179 180 // ============================================================================ 181 182 ContextHandler2::ContextHandler2( ContextHandler2Helper& rParent ) : 183 ContextHandler( dynamic_cast< ContextHandler& >( rParent ) ), 184 ContextHandler2Helper( rParent ) 185 { 186 } 187 188 ContextHandler2::~ContextHandler2() 189 { 190 } 191 192 // com.sun.star.xml.sax.XFastContextHandler interface ------------------------- 193 194 Reference< XFastContextHandler > SAL_CALL ContextHandler2::createFastChildContext( 195 sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw( SAXException, RuntimeException ) 196 { 197 return implCreateChildContext( nElement, rxAttribs ); 198 } 199 200 void SAL_CALL ContextHandler2::startFastElement( 201 sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw( SAXException, RuntimeException ) 202 { 203 implStartElement( nElement, rxAttribs ); 204 } 205 206 void SAL_CALL ContextHandler2::characters( const OUString& rChars ) throw( SAXException, RuntimeException ) 207 { 208 implCharacters( rChars ); 209 } 210 211 void SAL_CALL ContextHandler2::endFastElement( sal_Int32 nElement ) throw( SAXException, RuntimeException ) 212 { 213 implEndElement( nElement ); 214 } 215 216 // oox.core.RecordContext interface ------------------------------------------- 217 218 ContextHandlerRef ContextHandler2::createRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) 219 { 220 return implCreateRecordContext( nRecId, rStrm ); 221 } 222 223 void ContextHandler2::startRecord( sal_Int32 nRecId, SequenceInputStream& rStrm ) 224 { 225 implStartRecord( nRecId, rStrm ); 226 } 227 228 void ContextHandler2::endRecord( sal_Int32 nRecId ) 229 { 230 implEndRecord( nRecId ); 231 } 232 233 // oox.core.ContextHandler2Helper interface ----------------------------------- 234 235 ContextHandlerRef ContextHandler2::onCreateContext( sal_Int32, const AttributeList& ) 236 { 237 return 0; 238 } 239 240 void ContextHandler2::onStartElement( const AttributeList& ) 241 { 242 } 243 244 void ContextHandler2::onCharacters( const OUString& ) 245 { 246 } 247 248 void ContextHandler2::onEndElement() 249 { 250 } 251 252 ContextHandlerRef ContextHandler2::onCreateRecordContext( sal_Int32, SequenceInputStream& ) 253 { 254 return 0; 255 } 256 257 void ContextHandler2::onStartRecord( SequenceInputStream& ) 258 { 259 } 260 261 void ContextHandler2::onEndRecord() 262 { 263 } 264 265 // ============================================================================ 266 267 } // namespace core 268 } // namespace oox 269