1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #include "oox/core/contexthandler2.hxx"
29*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir namespace oox {
32*cdf0e10cSrcweir namespace core {
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir // ============================================================================
35*cdf0e10cSrcweir 
36*cdf0e10cSrcweir using namespace ::com::sun::star::uno;
37*cdf0e10cSrcweir using namespace ::com::sun::star::xml::sax;
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir using ::rtl::OUString;
40*cdf0e10cSrcweir using ::rtl::OUStringBuffer;
41*cdf0e10cSrcweir 
42*cdf0e10cSrcweir // ============================================================================
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir /** Information about a processed element. */
45*cdf0e10cSrcweir struct ElementInfo
46*cdf0e10cSrcweir {
47*cdf0e10cSrcweir     OUStringBuffer      maChars;            /// Collected element characters.
48*cdf0e10cSrcweir     sal_Int32           mnElement;          /// The element identifier.
49*cdf0e10cSrcweir     bool                mbTrimSpaces;       /// True = trims leading/trailing spaces from text data.
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir     inline explicit     ElementInfo() : mnElement( XML_TOKEN_INVALID ), mbTrimSpaces( false ) {}
52*cdf0e10cSrcweir };
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir // ============================================================================
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir ContextHandler2Helper::ContextHandler2Helper( bool bEnableTrimSpace ) :
57*cdf0e10cSrcweir     mxContextStack( new ContextStack ),
58*cdf0e10cSrcweir     mnRootStackSize( 0 ),
59*cdf0e10cSrcweir     mbEnableTrimSpace( bEnableTrimSpace )
60*cdf0e10cSrcweir {
61*cdf0e10cSrcweir     pushElementInfo( XML_ROOT_CONTEXT );
62*cdf0e10cSrcweir }
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir ContextHandler2Helper::ContextHandler2Helper( const ContextHandler2Helper& rParent ) :
65*cdf0e10cSrcweir     mxContextStack( rParent.mxContextStack ),
66*cdf0e10cSrcweir     mnRootStackSize( rParent.mxContextStack->size() ),
67*cdf0e10cSrcweir     mbEnableTrimSpace( rParent.mbEnableTrimSpace )
68*cdf0e10cSrcweir {
69*cdf0e10cSrcweir }
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir ContextHandler2Helper::~ContextHandler2Helper()
72*cdf0e10cSrcweir {
73*cdf0e10cSrcweir }
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir sal_Int32 ContextHandler2Helper::getCurrentElement() const
76*cdf0e10cSrcweir {
77*cdf0e10cSrcweir     return mxContextStack->empty() ? XML_ROOT_CONTEXT : mxContextStack->back().mnElement;
78*cdf0e10cSrcweir }
79*cdf0e10cSrcweir 
80*cdf0e10cSrcweir sal_Int32 ContextHandler2Helper::getParentElement( sal_Int32 nCountBack ) const
81*cdf0e10cSrcweir {
82*cdf0e10cSrcweir     if( (nCountBack < 0) || (mxContextStack->size() < static_cast< size_t >( nCountBack )) )
83*cdf0e10cSrcweir         return XML_TOKEN_INVALID;
84*cdf0e10cSrcweir     return (mxContextStack->size() == static_cast< size_t >( nCountBack )) ?
85*cdf0e10cSrcweir         XML_ROOT_CONTEXT : (*mxContextStack)[ mxContextStack->size() - nCountBack - 1 ].mnElement;
86*cdf0e10cSrcweir }
87*cdf0e10cSrcweir 
88*cdf0e10cSrcweir bool ContextHandler2Helper::isRootElement() const
89*cdf0e10cSrcweir {
90*cdf0e10cSrcweir     return mxContextStack->size() == mnRootStackSize + 1;
91*cdf0e10cSrcweir }
92*cdf0e10cSrcweir 
93*cdf0e10cSrcweir Reference< XFastContextHandler > ContextHandler2Helper::implCreateChildContext(
94*cdf0e10cSrcweir         sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs )
95*cdf0e10cSrcweir {
96*cdf0e10cSrcweir     // #i76091# process collected characters (calls onCharacters() if needed)
97*cdf0e10cSrcweir     processCollectedChars();
98*cdf0e10cSrcweir     ContextHandlerRef xContext = onCreateContext( nElement, AttributeList( rxAttribs ) );
99*cdf0e10cSrcweir     return Reference< XFastContextHandler >( xContext.get() );
100*cdf0e10cSrcweir }
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir void ContextHandler2Helper::implStartElement( sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs )
103*cdf0e10cSrcweir {
104*cdf0e10cSrcweir     AttributeList aAttribs( rxAttribs );
105*cdf0e10cSrcweir     pushElementInfo( nElement ).mbTrimSpaces = aAttribs.getToken( XML_TOKEN( space ), XML_TOKEN_INVALID ) != XML_preserve;
106*cdf0e10cSrcweir     onStartElement( aAttribs );
107*cdf0e10cSrcweir }
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir void ContextHandler2Helper::implCharacters( const OUString& rChars )
110*cdf0e10cSrcweir {
111*cdf0e10cSrcweir     // #i76091# collect characters until new element starts or this element ends
112*cdf0e10cSrcweir     if( !mxContextStack->empty() )
113*cdf0e10cSrcweir         mxContextStack->back().maChars.append( rChars );
114*cdf0e10cSrcweir }
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir void ContextHandler2Helper::implEndElement( sal_Int32 nElement )
117*cdf0e10cSrcweir {
118*cdf0e10cSrcweir     (void)nElement;     // prevent "unused parameter" warning in product build
119*cdf0e10cSrcweir     OSL_ENSURE( getCurrentElement() == nElement, "ContextHandler2Helper::implEndElement - context stack broken" );
120*cdf0e10cSrcweir     if( !mxContextStack->empty() )
121*cdf0e10cSrcweir     {
122*cdf0e10cSrcweir         // #i76091# process collected characters (calls onCharacters() if needed)
123*cdf0e10cSrcweir         processCollectedChars();
124*cdf0e10cSrcweir         onEndElement();
125*cdf0e10cSrcweir         popElementInfo();
126*cdf0e10cSrcweir     }
127*cdf0e10cSrcweir }
128*cdf0e10cSrcweir 
129*cdf0e10cSrcweir ContextHandlerRef ContextHandler2Helper::implCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
130*cdf0e10cSrcweir {
131*cdf0e10cSrcweir     return onCreateRecordContext( nRecId, rStrm );
132*cdf0e10cSrcweir }
133*cdf0e10cSrcweir 
134*cdf0e10cSrcweir void ContextHandler2Helper::implStartRecord( sal_Int32 nRecId, SequenceInputStream& rStrm )
135*cdf0e10cSrcweir {
136*cdf0e10cSrcweir     pushElementInfo( nRecId );
137*cdf0e10cSrcweir     onStartRecord( rStrm );
138*cdf0e10cSrcweir }
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir void ContextHandler2Helper::implEndRecord( sal_Int32 nRecId )
141*cdf0e10cSrcweir {
142*cdf0e10cSrcweir     (void)nRecId;   // prevent "unused parameter" warning in product build
143*cdf0e10cSrcweir     OSL_ENSURE( getCurrentElement() == nRecId, "ContextHandler2Helper::implEndRecord - context stack broken" );
144*cdf0e10cSrcweir     if( !mxContextStack->empty() )
145*cdf0e10cSrcweir     {
146*cdf0e10cSrcweir         onEndRecord();
147*cdf0e10cSrcweir         popElementInfo();
148*cdf0e10cSrcweir     }
149*cdf0e10cSrcweir }
150*cdf0e10cSrcweir 
151*cdf0e10cSrcweir ElementInfo& ContextHandler2Helper::pushElementInfo( sal_Int32 nElement )
152*cdf0e10cSrcweir {
153*cdf0e10cSrcweir     mxContextStack->resize( mxContextStack->size() + 1 );
154*cdf0e10cSrcweir     ElementInfo& rInfo = mxContextStack->back();
155*cdf0e10cSrcweir     rInfo.mnElement = nElement;
156*cdf0e10cSrcweir     return rInfo;
157*cdf0e10cSrcweir }
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir void ContextHandler2Helper::popElementInfo()
160*cdf0e10cSrcweir {
161*cdf0e10cSrcweir     OSL_ENSURE( !mxContextStack->empty(), "ContextHandler2Helper::popElementInfo - context stack broken" );
162*cdf0e10cSrcweir     if( !mxContextStack->empty() )
163*cdf0e10cSrcweir         mxContextStack->pop_back();
164*cdf0e10cSrcweir }
165*cdf0e10cSrcweir 
166*cdf0e10cSrcweir void ContextHandler2Helper::processCollectedChars()
167*cdf0e10cSrcweir {
168*cdf0e10cSrcweir     OSL_ENSURE( !mxContextStack->empty(), "ContextHandler2Helper::processCollectedChars - no context info" );
169*cdf0e10cSrcweir     ElementInfo& rInfo = mxContextStack->back();
170*cdf0e10cSrcweir     if( rInfo.maChars.getLength() > 0 )
171*cdf0e10cSrcweir     {
172*cdf0e10cSrcweir         OUString aChars = rInfo.maChars.makeStringAndClear();
173*cdf0e10cSrcweir         if( mbEnableTrimSpace && rInfo.mbTrimSpaces )
174*cdf0e10cSrcweir             aChars = aChars.trim();
175*cdf0e10cSrcweir         if( aChars.getLength() > 0 )
176*cdf0e10cSrcweir             onCharacters( aChars );
177*cdf0e10cSrcweir     }
178*cdf0e10cSrcweir }
179*cdf0e10cSrcweir 
180*cdf0e10cSrcweir // ============================================================================
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir ContextHandler2::ContextHandler2( ContextHandler2Helper& rParent ) :
183*cdf0e10cSrcweir     ContextHandler( dynamic_cast< ContextHandler& >( rParent ) ),
184*cdf0e10cSrcweir     ContextHandler2Helper( rParent )
185*cdf0e10cSrcweir {
186*cdf0e10cSrcweir }
187*cdf0e10cSrcweir 
188*cdf0e10cSrcweir ContextHandler2::~ContextHandler2()
189*cdf0e10cSrcweir {
190*cdf0e10cSrcweir }
191*cdf0e10cSrcweir 
192*cdf0e10cSrcweir // com.sun.star.xml.sax.XFastContextHandler interface -------------------------
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir Reference< XFastContextHandler > SAL_CALL ContextHandler2::createFastChildContext(
195*cdf0e10cSrcweir         sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw( SAXException, RuntimeException )
196*cdf0e10cSrcweir {
197*cdf0e10cSrcweir     return implCreateChildContext( nElement, rxAttribs );
198*cdf0e10cSrcweir }
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir void SAL_CALL ContextHandler2::startFastElement(
201*cdf0e10cSrcweir         sal_Int32 nElement, const Reference< XFastAttributeList >& rxAttribs ) throw( SAXException, RuntimeException )
202*cdf0e10cSrcweir {
203*cdf0e10cSrcweir     implStartElement( nElement, rxAttribs );
204*cdf0e10cSrcweir }
205*cdf0e10cSrcweir 
206*cdf0e10cSrcweir void SAL_CALL ContextHandler2::characters( const OUString& rChars ) throw( SAXException, RuntimeException )
207*cdf0e10cSrcweir {
208*cdf0e10cSrcweir     implCharacters( rChars );
209*cdf0e10cSrcweir }
210*cdf0e10cSrcweir 
211*cdf0e10cSrcweir void SAL_CALL ContextHandler2::endFastElement( sal_Int32 nElement ) throw( SAXException, RuntimeException )
212*cdf0e10cSrcweir {
213*cdf0e10cSrcweir     implEndElement( nElement );
214*cdf0e10cSrcweir }
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir // oox.core.RecordContext interface -------------------------------------------
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir ContextHandlerRef ContextHandler2::createRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
219*cdf0e10cSrcweir {
220*cdf0e10cSrcweir     return implCreateRecordContext( nRecId, rStrm );
221*cdf0e10cSrcweir }
222*cdf0e10cSrcweir 
223*cdf0e10cSrcweir void ContextHandler2::startRecord( sal_Int32 nRecId, SequenceInputStream& rStrm )
224*cdf0e10cSrcweir {
225*cdf0e10cSrcweir     implStartRecord( nRecId, rStrm );
226*cdf0e10cSrcweir }
227*cdf0e10cSrcweir 
228*cdf0e10cSrcweir void ContextHandler2::endRecord( sal_Int32 nRecId )
229*cdf0e10cSrcweir {
230*cdf0e10cSrcweir     implEndRecord( nRecId );
231*cdf0e10cSrcweir }
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir // oox.core.ContextHandler2Helper interface -----------------------------------
234*cdf0e10cSrcweir 
235*cdf0e10cSrcweir ContextHandlerRef ContextHandler2::onCreateContext( sal_Int32, const AttributeList& )
236*cdf0e10cSrcweir {
237*cdf0e10cSrcweir     return 0;
238*cdf0e10cSrcweir }
239*cdf0e10cSrcweir 
240*cdf0e10cSrcweir void ContextHandler2::onStartElement( const AttributeList& )
241*cdf0e10cSrcweir {
242*cdf0e10cSrcweir }
243*cdf0e10cSrcweir 
244*cdf0e10cSrcweir void ContextHandler2::onCharacters( const OUString& )
245*cdf0e10cSrcweir {
246*cdf0e10cSrcweir }
247*cdf0e10cSrcweir 
248*cdf0e10cSrcweir void ContextHandler2::onEndElement()
249*cdf0e10cSrcweir {
250*cdf0e10cSrcweir }
251*cdf0e10cSrcweir 
252*cdf0e10cSrcweir ContextHandlerRef ContextHandler2::onCreateRecordContext( sal_Int32, SequenceInputStream& )
253*cdf0e10cSrcweir {
254*cdf0e10cSrcweir     return 0;
255*cdf0e10cSrcweir }
256*cdf0e10cSrcweir 
257*cdf0e10cSrcweir void ContextHandler2::onStartRecord( SequenceInputStream& )
258*cdf0e10cSrcweir {
259*cdf0e10cSrcweir }
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir void ContextHandler2::onEndRecord()
262*cdf0e10cSrcweir {
263*cdf0e10cSrcweir }
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir // ============================================================================
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir } // namespace core
268*cdf0e10cSrcweir } // namespace oox
269