xref: /AOO41X/main/oox/inc/oox/core/contexthandler2.hxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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