blob: 3186fb409e3da206d71e98630dbe67dc7e6271f7 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef OOX_CORE_CONTEXTHANDLER2_HXX
#define OOX_CORE_CONTEXTHANDLER2_HXX
#include <vector>
#include <boost/shared_ptr.hpp>
#include "oox/helper/attributelist.hxx"
#include "oox/helper/binaryinputstream.hxx"
#include "oox/core/contexthandler.hxx"
namespace oox {
namespace core {
// ============================================================================
const sal_Int32 XML_ROOT_CONTEXT = SAL_MAX_INT32;
// ============================================================================
struct ElementInfo;
/** Helper class that provides a context stack.
Fragment handlers and context handlers derived from this helper class will
track the identifiers of the visited elements in a stack. The idea is to
use the same instance of a fragment handler or context handler to process
several nested elements in an XML stream. For that, the abstract function
onCreateContext() has to return 'this' for the passed element.
Derived classes have to implement the createFastChildContext(),
startFastElement(), characters(), and endFastElement() functions from the
com.sun.star.xml.sax.XFastContextHandler interface by simply forwarding
them to the respective implCreateChildContext(), implStartElement(),
implCharacters(), and implEndElement() functions of this helper. This is
implemented already in the classes ContextHandler2 and FragmentHandler2.
The new abstract functions have to be implemented according to the elements
to be processed.
Similarly, for binary import, derived classes have to forward the
createRecordContext(), startRecord(), and endRecord() functions from the
ContextHandler class to the implCreateRecordContext(), implStartRecord(),
and implEndRecord() functions of this helper. Again, this is implemented
already in the classes ContextHandler2 and FragmentHandler2.
*/
class ContextHandler2Helper
{
public:
explicit ContextHandler2Helper( bool bEnableTrimSpace );
explicit ContextHandler2Helper( const ContextHandler2Helper& rParent );
virtual ~ContextHandler2Helper();
// allow instances to be stored in ::rtl::Reference
virtual void SAL_CALL acquire() throw() = 0;
virtual void SAL_CALL release() throw() = 0;
// interface --------------------------------------------------------------
/** Will be called to create a context handler for the passed element.
Usually 'this' can be returned to improve performance by reusing the
same instance to process several elements. Used by OOXML import only.
*/
virtual ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) = 0;
/** Will be called when a new element has been started.
This function is called at the context handler returned from
onCreateContext(), or, for root elements of an XML stream, at the
fragment handler itself.
The current element identifier can be accessed with getCurrentElement()
or isCurrentElement(). Used by OOXML import only.
*/
virtual void onStartElement( const AttributeList& rAttribs ) = 0;
/** Will be called before a new child element starts, or if the current
element is about to be left.
This helper function collects all text fragments received by the
characters() function (such as encoded characters which are passed in
separate calls to the characters() function), and passes the
concatenated and trimmed string.
The current element identifier can be accessed with getCurrentElement()
or isCurrentElement(). Used by OOXML import only.
*/
virtual void onCharacters( const ::rtl::OUString& rChars ) = 0;
/** Will be called when the current element is about to be left.
The current element identifier can be accessed with getCurrentElement()
or isCurrentElement(). Used by OOXML import only.
*/
virtual void onEndElement() = 0;
/** Will be called to create a context handler for the passed record.
Usually 'this' can be returned to improve performance by reusing the
same instance to process several records. Used by BIFF import only.
*/
virtual ContextHandlerRef onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) = 0;
/** Will be called when a new record block in a binary stream has been
started.
The current record identifier can be accessed with getCurrentElement()
or isCurrentElement(). Used by BIFF import only.
*/
virtual void onStartRecord( SequenceInputStream& rStrm ) = 0;
/** Will be called when the current record block is about to be left.
The current record identifier can be accessed with getCurrentElement()
or isCurrentElement(). Used by BIFF import only.
*/
virtual void onEndRecord() = 0;
// helpers ----------------------------------------------------------------
/** Returns the identifier of the currently processed element. */
sal_Int32 getCurrentElement() const;
/** Returns true, if nElement contains the identifier of the currently
processed element. */
inline bool isCurrentElement( sal_Int32 nElement ) const
{ return getCurrentElement() == nElement; }
/** Returns true, if either nElement1 or nElement2 contain the identifier
of the currently processed element. */
inline bool isCurrentElement( sal_Int32 nElement1, sal_Int32 nElement2 ) const
{ return isCurrentElement( nElement1 ) || isCurrentElement( nElement2 ); }
/** Returns the identifier of the specified parent element. */
sal_Int32 getParentElement( sal_Int32 nCountBack = 1 ) const;
/** Returns true, if nElement contains the identifier of the specified
parent element. */
inline sal_Int32 isParentElement( sal_Int32 nElement, sal_Int32 nCountBack = 1 ) const
{ return getParentElement( nCountBack ) == nElement; }
/** Returns true, if the element currently processed is the root element of
the context or fragment handler. */
bool isRootElement() const;
// implementation ---------------------------------------------------------
protected:
/** Must be called from createFastChildContext() in derived classes. */
::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler >
implCreateChildContext(
sal_Int32 nElement,
const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs );
/** Must be called from startFastElement() in derived classes. */
void implStartElement(
sal_Int32 nElement,
const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs );
/** Must be called from characters() in derived classes. */
void implCharacters( const ::rtl::OUString& rChars );
/** Must be called from endFastElement() in derived classes. */
void implEndElement( sal_Int32 nElement );
/** Must be called from createRecordContext() in derived classes. */
ContextHandlerRef implCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm );
/** Must be called from startRecord() in derived classes. */
void implStartRecord( sal_Int32 nRecId, SequenceInputStream& rStrm );
/** Must be called from endRecord() in derived classes. */
void implEndRecord( sal_Int32 nRecId );
private:
ContextHandler2Helper& operator=( const ContextHandler2Helper& );
ElementInfo& pushElementInfo( sal_Int32 nElement );
void popElementInfo();
void processCollectedChars();
private:
typedef ::std::vector< ElementInfo > ContextStack;
typedef ::boost::shared_ptr< ContextStack > ContextStackRef;
ContextStackRef mxContextStack; /// Stack of all processed elements.
size_t mnRootStackSize; /// Stack size on construction time.
bool mbEnableTrimSpace; /// True = trim whitespace in characters().
};
// ============================================================================
class ContextHandler2 : public ContextHandler, public ContextHandler2Helper
{
public:
explicit ContextHandler2( ContextHandler2Helper& rParent );
virtual ~ContextHandler2();
// resolve ambiguity from base classes
virtual void SAL_CALL acquire() throw() { ContextHandler::acquire(); }
virtual void SAL_CALL release() throw() { ContextHandler::release(); }
// com.sun.star.xml.sax.XFastContextHandler interface ---------------------
virtual ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastContextHandler > SAL_CALL
createFastChildContext(
sal_Int32 nElement,
const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs )
throw( ::com::sun::star::xml::sax::SAXException,
::com::sun::star::uno::RuntimeException );
virtual void SAL_CALL startFastElement(
sal_Int32 nElement,
const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& rxAttribs )
throw( ::com::sun::star::xml::sax::SAXException,
::com::sun::star::uno::RuntimeException );
virtual void SAL_CALL characters( const ::rtl::OUString& rChars )
throw( ::com::sun::star::xml::sax::SAXException,
::com::sun::star::uno::RuntimeException );
virtual void SAL_CALL endFastElement( sal_Int32 nElement )
throw( ::com::sun::star::xml::sax::SAXException,
::com::sun::star::uno::RuntimeException );
// oox.core.ContextHandler interface --------------------------------------
virtual ContextHandlerRef createRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm );
virtual void startRecord( sal_Int32 nRecId, SequenceInputStream& rStrm );
virtual void endRecord( sal_Int32 nRecId );
// oox.core.ContextHandler2Helper interface -------------------------------
virtual ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs );
virtual void onStartElement( const AttributeList& rAttribs );
virtual void onCharacters( const ::rtl::OUString& rChars );
virtual void onEndElement();
virtual ContextHandlerRef onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm );
virtual void onStartRecord( SequenceInputStream& rStrm );
virtual void onEndRecord();
};
// ============================================================================
} // namespace core
} // namespace oox
#endif