1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ca5ec200SAndrew Rist  * distributed with this work for additional information
6*ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*ca5ec200SAndrew Rist  *
11*ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist  *
13*ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist  * under the License.
19*ca5ec200SAndrew Rist  *
20*ca5ec200SAndrew Rist  *************************************************************/
21*ca5ec200SAndrew Rist 
22*ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/core/contexthandler2.hxx"
25cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
26cdf0e10cSrcweir 
27cdf0e10cSrcweir namespace oox {
28cdf0e10cSrcweir namespace core {
29cdf0e10cSrcweir 
30cdf0e10cSrcweir // ============================================================================
31cdf0e10cSrcweir 
32cdf0e10cSrcweir using namespace ::com::sun::star::uno;
33cdf0e10cSrcweir using namespace ::com::sun::star::xml::sax;
34cdf0e10cSrcweir 
35cdf0e10cSrcweir using ::rtl::OUString;
36cdf0e10cSrcweir using ::rtl::OUStringBuffer;
37cdf0e10cSrcweir 
38cdf0e10cSrcweir // ============================================================================
39cdf0e10cSrcweir 
40cdf0e10cSrcweir /** Information about a processed element. */
41cdf0e10cSrcweir struct ElementInfo
42cdf0e10cSrcweir {
43cdf0e10cSrcweir     OUStringBuffer      maChars;            /// Collected element characters.
44cdf0e10cSrcweir     sal_Int32           mnElement;          /// The element identifier.
45cdf0e10cSrcweir     bool                mbTrimSpaces;       /// True = trims leading/trailing spaces from text data.
46cdf0e10cSrcweir 
ElementInfooox::core::ElementInfo47cdf0e10cSrcweir     inline explicit     ElementInfo() : mnElement( XML_TOKEN_INVALID ), mbTrimSpaces( false ) {}
48cdf0e10cSrcweir };
49cdf0e10cSrcweir 
50cdf0e10cSrcweir // ============================================================================
51cdf0e10cSrcweir 
ContextHandler2Helper(bool bEnableTrimSpace)52cdf0e10cSrcweir ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace ) :
53cdf0e10cSrcweir     mxContextStack( new ContextStack ),
54cdf0e10cSrcweir     mnRootStackSize( 0 ),
55cdf0e10cSrcweir     mbEnableTrimSpace( bEnableTrimSpace )
56cdf0e10cSrcweir {
57cdf0e10cSrcweir     pushElementInfo( XML_ROOT_CONTEXT );
58cdf0e10cSrcweir }
59cdf0e10cSrcweir 
ContextHandler2Helper(const ContextHandler2Helper & rParent)60cdf0e10cSrcweir ContextHandler2Helper::ContextHandler2Helper( const ContextHandler2Helper& rParent ) :
61cdf0e10cSrcweir     mxContextStack( rParent.mxContextStack ),
62cdf0e10cSrcweir     mnRootStackSize( rParent.mxContextStack->size() ),
63cdf0e10cSrcweir     mbEnableTrimSpace( rParent.mbEnableTrimSpace )
64cdf0e10cSrcweir {
65cdf0e10cSrcweir }
66cdf0e10cSrcweir 
~ContextHandler2Helper()67cdf0e10cSrcweir ContextHandler2Helper::~ContextHandler2Helper()
68cdf0e10cSrcweir {
69cdf0e10cSrcweir }
70cdf0e10cSrcweir 
getCurrentElement() const71cdf0e10cSrcweir sal_Int32 ContextHandler2Helper::getCurrentElement() const
72cdf0e10cSrcweir {
73cdf0e10cSrcweir     return mxContextStack->empty() ? XML_ROOT_CONTEXT : mxContextStack->back().mnElement;
74cdf0e10cSrcweir }
75cdf0e10cSrcweir 
getParentElement(sal_Int32 nCountBack) const76cdf0e10cSrcweir sal_Int32 ContextHandler2Helper::getParentElement( sal_Int32 nCountBack ) const
77cdf0e10cSrcweir {
78cdf0e10cSrcweir     if( (nCountBack < 0) || (mxContextStack->size() < static_cast< size_t >( nCountBack )) )
79cdf0e10cSrcweir         return XML_TOKEN_INVALID;
80cdf0e10cSrcweir     return (mxContextStack->size() == static_cast< size_t >( nCountBack )) ?
81cdf0e10cSrcweir         XML_ROOT_CONTEXT : (*mxContextStack)[ mxContextStack->size() - nCountBack - 1 ].mnElement;
82cdf0e10cSrcweir }
83cdf0e10cSrcweir 
isRootElement() const84cdf0e10cSrcweir bool ContextHandler2Helper::isRootElement() const
85cdf0e10cSrcweir {
86cdf0e10cSrcweir     return mxContextStack->size() == mnRootStackSize + 1;
87cdf0e10cSrcweir }
88cdf0e10cSrcweir 
implCreateChildContext(sal_Int32 nElement,const Reference<XFastAttributeList> & rxAttribs)89cdf0e10cSrcweir Reference< XFastContextHandler > ContextHandler2Helper::implCreateChildContext(
90cdf0e10cSrcweir         sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs )
91cdf0e10cSrcweir {
92cdf0e10cSrcweir     // #i76091# process collected characters (calls onCharacters() if needed)
93cdf0e10cSrcweir     processCollectedChars();
94cdf0e10cSrcweir     ContextHandlerRef xContext = onCreateContext( nElement, AttributeList( rxAttribs ) );
95cdf0e10cSrcweir     return Reference< XFastContextHandler >( xContext.get() );
96cdf0e10cSrcweir }
97cdf0e10cSrcweir 
implStartElement(sal_Int32 nElement,const Reference<XFastAttributeList> & rxAttribs)98cdf0e10cSrcweir void ContextHandler2Helper::implStartElement( sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs )
99cdf0e10cSrcweir {
100cdf0e10cSrcweir     AttributeList aAttribs( rxAttribs );
101cdf0e10cSrcweir     pushElementInfo( nElement ).mbTrimSpaces = aAttribs.getToken( XML_TOKEN( space ), XML_TOKEN_INVALID ) != XML_preserve;
102cdf0e10cSrcweir     onStartElement( aAttribs );
103cdf0e10cSrcweir }
104cdf0e10cSrcweir 
implCharacters(const OUString & rChars)105cdf0e10cSrcweir void ContextHandler2Helper::implCharacters( const OUString& rChars )
106cdf0e10cSrcweir {
107cdf0e10cSrcweir     // #i76091# collect characters until new element starts or this element ends
108cdf0e10cSrcweir     if( !mxContextStack->empty() )
109cdf0e10cSrcweir         mxContextStack->back().maChars.append( rChars );
110cdf0e10cSrcweir }
111cdf0e10cSrcweir 
implEndElement(sal_Int32 nElement)112cdf0e10cSrcweir void ContextHandler2Helper::implEndElement( sal_Int32 nElement )
113cdf0e10cSrcweir {
114cdf0e10cSrcweir     (void)nElement;     // prevent "unused parameter" warning in product build
115cdf0e10cSrcweir     OSL_ENSURE( getCurrentElement() == nElement, "ContextHandler2Helper::implEndElement - context stack broken" );
116cdf0e10cSrcweir     if( !mxContextStack->empty() )
117cdf0e10cSrcweir     {
118cdf0e10cSrcweir         // #i76091# process collected characters (calls onCharacters() if needed)
119cdf0e10cSrcweir         processCollectedChars();
120cdf0e10cSrcweir         onEndElement();
121cdf0e10cSrcweir         popElementInfo();
122cdf0e10cSrcweir     }
123cdf0e10cSrcweir }
124cdf0e10cSrcweir 
implCreateRecordContext(sal_Int32 nRecId,SequenceInputStream & rStrm)125cdf0e10cSrcweir ContextHandlerRef ContextHandler2Helper::implCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
126cdf0e10cSrcweir {
127cdf0e10cSrcweir     return onCreateRecordContext( nRecId, rStrm );
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
implStartRecord(sal_Int32 nRecId,SequenceInputStream & rStrm)130cdf0e10cSrcweir void ContextHandler2Helper::implStartRecord( sal_Int32 nRecId, SequenceInputStream& rStrm )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir     pushElementInfo( nRecId );
133cdf0e10cSrcweir     onStartRecord( rStrm );
134cdf0e10cSrcweir }
135cdf0e10cSrcweir 
implEndRecord(sal_Int32 nRecId)136cdf0e10cSrcweir void ContextHandler2Helper::implEndRecord( sal_Int32 nRecId )
137cdf0e10cSrcweir {
138cdf0e10cSrcweir     (void)nRecId;   // prevent "unused parameter" warning in product build
139cdf0e10cSrcweir     OSL_ENSURE( getCurrentElement() == nRecId, "ContextHandler2Helper::implEndRecord - context stack broken" );
140cdf0e10cSrcweir     if( !mxContextStack->empty() )
141cdf0e10cSrcweir     {
142cdf0e10cSrcweir         onEndRecord();
143cdf0e10cSrcweir         popElementInfo();
144cdf0e10cSrcweir     }
145cdf0e10cSrcweir }
146cdf0e10cSrcweir 
pushElementInfo(sal_Int32 nElement)147cdf0e10cSrcweir ElementInfo& ContextHandler2Helper::pushElementInfo( sal_Int32 nElement )
148cdf0e10cSrcweir {
149cdf0e10cSrcweir     mxContextStack->resize( mxContextStack->size() + 1 );
150cdf0e10cSrcweir     ElementInfo& rInfo = mxContextStack->back();
151cdf0e10cSrcweir     rInfo.mnElement = nElement;
152cdf0e10cSrcweir     return rInfo;
153cdf0e10cSrcweir }
154cdf0e10cSrcweir 
popElementInfo()155cdf0e10cSrcweir void ContextHandler2Helper::popElementInfo()
156cdf0e10cSrcweir {
157cdf0e10cSrcweir     OSL_ENSURE( !mxContextStack->empty(), "ContextHandler2Helper::popElementInfo - context stack broken" );
158cdf0e10cSrcweir     if( !mxContextStack->empty() )
159cdf0e10cSrcweir         mxContextStack->pop_back();
160cdf0e10cSrcweir }
161cdf0e10cSrcweir 
processCollectedChars()162cdf0e10cSrcweir void ContextHandler2Helper::processCollectedChars()
163cdf0e10cSrcweir {
164cdf0e10cSrcweir     OSL_ENSURE( !mxContextStack->empty(), "ContextHandler2Helper::processCollectedChars - no context info" );
165cdf0e10cSrcweir     ElementInfo& rInfo = mxContextStack->back();
166cdf0e10cSrcweir     if( rInfo.maChars.getLength() > 0 )
167cdf0e10cSrcweir     {
168cdf0e10cSrcweir         OUString aChars = rInfo.maChars.makeStringAndClear();
169cdf0e10cSrcweir         if( mbEnableTrimSpace && rInfo.mbTrimSpaces )
170cdf0e10cSrcweir             aChars = aChars.trim();
171cdf0e10cSrcweir         if( aChars.getLength() > 0 )
172cdf0e10cSrcweir             onCharacters( aChars );
173cdf0e10cSrcweir     }
174cdf0e10cSrcweir }
175cdf0e10cSrcweir 
176cdf0e10cSrcweir // ============================================================================
177cdf0e10cSrcweir 
ContextHandler2(ContextHandler2Helper & rParent)178cdf0e10cSrcweir ContextHandler2::ContextHandler2( ContextHandler2Helper& rParent ) :
179cdf0e10cSrcweir     ContextHandler( dynamic_cast< ContextHandler& >( rParent ) ),
180cdf0e10cSrcweir     ContextHandler2Helper( rParent )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir }
183cdf0e10cSrcweir 
~ContextHandler2()184cdf0e10cSrcweir ContextHandler2::~ContextHandler2()
185cdf0e10cSrcweir {
186cdf0e10cSrcweir }
187cdf0e10cSrcweir 
188cdf0e10cSrcweir // com.sun.star.xml.sax.XFastContextHandler interface -------------------------
189cdf0e10cSrcweir 
createFastChildContext(sal_Int32 nElement,const Reference<XFastAttributeList> & rxAttribs)190cdf0e10cSrcweir Reference< XFastContextHandler > SAL_CALL ContextHandler2::createFastChildContext(
191cdf0e10cSrcweir         sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw( SAXException, RuntimeException )
192cdf0e10cSrcweir {
193cdf0e10cSrcweir     return implCreateChildContext( nElement, rxAttribs );
194cdf0e10cSrcweir }
195cdf0e10cSrcweir 
startFastElement(sal_Int32 nElement,const Reference<XFastAttributeList> & rxAttribs)196cdf0e10cSrcweir void SAL_CALL ContextHandler2::startFastElement(
197cdf0e10cSrcweir         sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw( SAXException, RuntimeException )
198cdf0e10cSrcweir {
199cdf0e10cSrcweir     implStartElement( nElement, rxAttribs );
200cdf0e10cSrcweir }
201cdf0e10cSrcweir 
characters(const OUString & rChars)202cdf0e10cSrcweir void SAL_CALL ContextHandler2::characters( const OUString& rChars ) throw( SAXException, RuntimeException )
203cdf0e10cSrcweir {
204cdf0e10cSrcweir     implCharacters( rChars );
205cdf0e10cSrcweir }
206cdf0e10cSrcweir 
endFastElement(sal_Int32 nElement)207cdf0e10cSrcweir void SAL_CALL ContextHandler2::endFastElement( sal_Int32 nElement ) throw( SAXException, RuntimeException )
208cdf0e10cSrcweir {
209cdf0e10cSrcweir     implEndElement( nElement );
210cdf0e10cSrcweir }
211cdf0e10cSrcweir 
212cdf0e10cSrcweir // oox.core.RecordContext interface -------------------------------------------
213cdf0e10cSrcweir 
createRecordContext(sal_Int32 nRecId,SequenceInputStream & rStrm)214cdf0e10cSrcweir ContextHandlerRef ContextHandler2::createRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
215cdf0e10cSrcweir {
216cdf0e10cSrcweir     return implCreateRecordContext( nRecId, rStrm );
217cdf0e10cSrcweir }
218cdf0e10cSrcweir 
startRecord(sal_Int32 nRecId,SequenceInputStream & rStrm)219cdf0e10cSrcweir void ContextHandler2::startRecord( sal_Int32 nRecId, SequenceInputStream& rStrm )
220cdf0e10cSrcweir {
221cdf0e10cSrcweir     implStartRecord( nRecId, rStrm );
222cdf0e10cSrcweir }
223cdf0e10cSrcweir 
endRecord(sal_Int32 nRecId)224cdf0e10cSrcweir void ContextHandler2::endRecord( sal_Int32 nRecId )
225cdf0e10cSrcweir {
226cdf0e10cSrcweir     implEndRecord( nRecId );
227cdf0e10cSrcweir }
228cdf0e10cSrcweir 
229cdf0e10cSrcweir // oox.core.ContextHandler2Helper interface -----------------------------------
230cdf0e10cSrcweir 
onCreateContext(sal_Int32,const AttributeList &)231cdf0e10cSrcweir ContextHandlerRef ContextHandler2::onCreateContext( sal_Int32, const AttributeList& )
232cdf0e10cSrcweir {
233cdf0e10cSrcweir     return 0;
234cdf0e10cSrcweir }
235cdf0e10cSrcweir 
onStartElement(const AttributeList &)236cdf0e10cSrcweir void ContextHandler2::onStartElement( const AttributeList& )
237cdf0e10cSrcweir {
238cdf0e10cSrcweir }
239cdf0e10cSrcweir 
onCharacters(const OUString &)240cdf0e10cSrcweir void ContextHandler2::onCharacters( const OUString& )
241cdf0e10cSrcweir {
242cdf0e10cSrcweir }
243cdf0e10cSrcweir 
onEndElement()244cdf0e10cSrcweir void ContextHandler2::onEndElement()
245cdf0e10cSrcweir {
246cdf0e10cSrcweir }
247cdf0e10cSrcweir 
onCreateRecordContext(sal_Int32,SequenceInputStream &)248cdf0e10cSrcweir ContextHandlerRef ContextHandler2::onCreateRecordContext( sal_Int32, SequenceInputStream& )
249cdf0e10cSrcweir {
250cdf0e10cSrcweir     return 0;
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
onStartRecord(SequenceInputStream &)253cdf0e10cSrcweir void ContextHandler2::onStartRecord( SequenceInputStream& )
254cdf0e10cSrcweir {
255cdf0e10cSrcweir }
256cdf0e10cSrcweir 
onEndRecord()257cdf0e10cSrcweir void ContextHandler2::onEndRecord()
258cdf0e10cSrcweir {
259cdf0e10cSrcweir }
260cdf0e10cSrcweir 
261cdf0e10cSrcweir // ============================================================================
262cdf0e10cSrcweir 
263cdf0e10cSrcweir } // namespace core
264cdf0e10cSrcweir } // namespace oox
265