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 #ifndef OOX_CORE_CONTEXTHANDLER2_HXX 29 #define OOX_CORE_CONTEXTHANDLER2_HXX 30 31 #include <vector> 32 #include <boost/shared_ptr.hpp> 33 #include "oox/helper/attributelist.hxx" 34 #include "oox/helper/binaryinputstream.hxx" 35 #include "oox/core/contexthandler.hxx" 36 37 namespace oox { 38 namespace core { 39 40 // ============================================================================ 41 42 const sal_Int32 XML_ROOT_CONTEXT = SAL_MAX_INT32; 43 44 // ============================================================================ 45 46 struct ElementInfo; 47 48 /** Helper class that provides a context stack. 49 50 Fragment handlers and context handlers derived from this helper class will 51 track the identifiers of the visited elements in a stack. The idea is to 52 use the same instance of a fragment handler or context handler to process 53 several nested elements in an XML stream. For that, the abstract function 54 onCreateContext() has to return 'this' for the passed element. 55 56 Derived classes have to implement the createFastChildContext(), 57 startFastElement(), characters(), and endFastElement() functions from the 58 com.sun.star.xml.sax.XFastContextHandler interface by simply forwarding 59 them to the respective implCreateChildContext(), implStartElement(), 60 implCharacters(), and implEndElement() functions of this helper. This is 61 implemented already in the classes ContextHandler2 and FragmentHandler2. 62 The new abstract functions have to be implemented according to the elements 63 to be processed. 64 65 Similarly, for binary import, derived classes have to forward the 66 createRecordContext(), startRecord(), and endRecord() functions from the 67 ContextHandler class to the implCreateRecordContext(), implStartRecord(), 68 and implEndRecord() functions of this helper. Again, this is implemented 69 already in the classes ContextHandler2 and FragmentHandler2. 70 */ 71 class ContextHandler2Helper 72 { 73 public: 74 explicit ContextHandler2Helper( bool bEnableTrimSpace ); 75 explicit ContextHandler2Helper( const ContextHandler2Helper& rParent ); 76 virtual ~ContextHandler2Helper(); 77 78 // allow instances to be stored in ::rtl::Reference 79 virtual void SAL_CALL acquire() throw() = 0; 80 virtual void SAL_CALL release() throw() = 0; 81 82 // interface -------------------------------------------------------------- 83 84 /** Will be called to create a context handler for the passed element. 85 86 Usually 'this' can be returned to improve performance by reusing the 87 same instance to process several elements. Used by OOXML import only. 88 */ 89 virtual ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) = 0; 90 91 /** Will be called when a new element has been started. 92 93 This function is called at the context handler returned from 94 onCreateContext(), or, for root elements of an XML stream, at the 95 fragment handler itself. 96 97 The current element identifier can be accessed with getCurrentElement() 98 or isCurrentElement(). Used by OOXML import only. 99 */ 100 virtual void onStartElement( const AttributeList& rAttribs ) = 0; 101 102 /** Will be called before a new child element starts, or if the current 103 element is about to be left. 104 105 This helper function collects all text fragments received by the 106 characters() function (such as encoded characters which are passed in 107 separate calls to the characters() function), and passes the 108 concatenated and trimmed string. 109 110 The current element identifier can be accessed with getCurrentElement() 111 or isCurrentElement(). Used by OOXML import only. 112 */ 113 virtual void onCharacters( const ::rtl::OUString& rChars ) = 0; 114 115 /** Will be called when the current element is about to be left. 116 117 The current element identifier can be accessed with getCurrentElement() 118 or isCurrentElement(). Used by OOXML import only. 119 */ 120 virtual void onEndElement() = 0; 121 122 /** Will be called to create a context handler for the passed record. 123 124 Usually 'this' can be returned to improve performance by reusing the 125 same instance to process several records. Used by BIFF import only. 126 */ 127 virtual ContextHandlerRef onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) = 0; 128 129 /** Will be called when a new record block in a binary stream has been 130 started. 131 132 The current record identifier can be accessed with getCurrentElement() 133 or isCurrentElement(). Used by BIFF import only. 134 */ 135 virtual void onStartRecord( SequenceInputStream& rStrm ) = 0; 136 137 /** Will be called when the current record block is about to be left. 138 139 The current record identifier can be accessed with getCurrentElement() 140 or isCurrentElement(). Used by BIFF import only. 141 */ 142 virtual void onEndRecord() = 0; 143 144 // helpers ---------------------------------------------------------------- 145 146 /** Returns the identifier of the currently processed element. */ 147 sal_Int32 getCurrentElement() const; 148 149 /** Returns true, if nElement contains the identifier of the currently 150 processed element. */ 151 inline bool isCurrentElement( sal_Int32 nElement ) const 152 { return getCurrentElement() == nElement; } 153 154 /** Returns true, if either nElement1 or nElement2 contain the identifier 155 of the currently processed element. */ 156 inline bool isCurrentElement( sal_Int32 nElement1, sal_Int32 nElement2 ) const 157 { return isCurrentElement( nElement1 ) || isCurrentElement( nElement2 ); } 158 159 /** Returns the identifier of the specified parent element. */ 160 sal_Int32 getParentElement( sal_Int32 nCountBack = 1 ) const; 161 162 /** Returns true, if nElement contains the identifier of the specified 163 parent element. */ 164 inline sal_Int32 isParentElement( sal_Int32 nElement, sal_Int32 nCountBack = 1 ) const 165 { return getParentElement( nCountBack ) == nElement; } 166 167 /** Returns true, if the element currently processed is the root element of 168 the context or fragment handler. */ 169 bool isRootElement() const; 170 171 // implementation --------------------------------------------------------- 172 173 protected: 174 /** Must be called from createFastChildContext() in derived classes. */ 175 ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > 176 implCreateChildContext( 177 sal_Int32 nElement, 178 const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs ); 179 180 /** Must be called from startFastElement() in derived classes. */ 181 void implStartElement( 182 sal_Int32 nElement, 183 const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs ); 184 185 /** Must be called from characters() in derived classes. */ 186 void implCharacters( const ::rtl::OUString& rChars ); 187 188 /** Must be called from endFastElement() in derived classes. */ 189 void implEndElement( sal_Int32 nElement ); 190 191 /** Must be called from createRecordContext() in derived classes. */ 192 ContextHandlerRef implCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ); 193 194 /** Must be called from startRecord() in derived classes. */ 195 void implStartRecord( sal_Int32 nRecId, SequenceInputStream& rStrm ); 196 197 /** Must be called from endRecord() in derived classes. */ 198 void implEndRecord( sal_Int32 nRecId ); 199 200 private: 201 ContextHandler2Helper& operator=( const ContextHandler2Helper& ); 202 203 ElementInfo& pushElementInfo( sal_Int32 nElement ); 204 void popElementInfo(); 205 void processCollectedChars(); 206 207 private: 208 typedef ::std::vector< ElementInfo > ContextStack; 209 typedef ::boost::shared_ptr< ContextStack > ContextStackRef; 210 211 ContextStackRef mxContextStack; /// Stack of all processed elements. 212 size_t mnRootStackSize; /// Stack size on construction time. 213 bool mbEnableTrimSpace; /// True = trim whitespace in characters(). 214 }; 215 216 // ============================================================================ 217 218 class ContextHandler2 : public ContextHandler, public ContextHandler2Helper 219 { 220 public: 221 explicit ContextHandler2( ContextHandler2Helper& rParent ); 222 virtual ~ContextHandler2(); 223 224 // resolve ambiguity from base classes 225 virtual void SAL_CALL acquire() throw() { ContextHandler::acquire(); } 226 virtual void SAL_CALL release() throw() { ContextHandler::release(); } 227 228 // com.sun.star.xml.sax.XFastContextHandler interface --------------------- 229 230 virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL 231 createFastChildContext( 232 sal_Int32 nElement, 233 const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs ) 234 throw( ::com::sun::star::xml::sax::SAXException, 235 ::com::sun::star::uno::RuntimeException ); 236 237 virtual void SAL_CALL startFastElement( 238 sal_Int32 nElement, 239 const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs ) 240 throw( ::com::sun::star::xml::sax::SAXException, 241 ::com::sun::star::uno::RuntimeException ); 242 243 virtual void SAL_CALL characters( const ::rtl::OUString& rChars ) 244 throw( ::com::sun::star::xml::sax::SAXException, 245 ::com::sun::star::uno::RuntimeException ); 246 247 virtual void SAL_CALL endFastElement( sal_Int32 nElement ) 248 throw( ::com::sun::star::xml::sax::SAXException, 249 ::com::sun::star::uno::RuntimeException ); 250 251 // oox.core.ContextHandler interface -------------------------------------- 252 253 virtual ContextHandlerRef createRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ); 254 virtual void startRecord( sal_Int32 nRecId, SequenceInputStream& rStrm ); 255 virtual void endRecord( sal_Int32 nRecId ); 256 257 // oox.core.ContextHandler2Helper interface ------------------------------- 258 259 virtual ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ); 260 virtual void onStartElement( const AttributeList& rAttribs ); 261 virtual void onCharacters( const ::rtl::OUString& rChars ); 262 virtual void onEndElement(); 263 264 virtual ContextHandlerRef onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ); 265 virtual void onStartRecord( SequenceInputStream& rStrm ); 266 virtual void onEndRecord(); 267 }; 268 269 // ============================================================================ 270 271 } // namespace core 272 } // namespace oox 273 274 #endif 275