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