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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include "MergeElemTContext.hxx"
31 #include "MutableAttrList.hxx"
32 #ifndef _XMLOFF_TRANSFORMERBASE_HXX
33 #include "TransformerBase.hxx"
34 #endif
35 #include "TransformerActions.hxx"
36 #include "AttrTransformerAction.hxx"
37 #include "ElemTransformerAction.hxx"
38 #include "IgnoreTContext.hxx"
39 #include "xmloff/xmlnmspe.hxx"
40 
41 using ::rtl::OUString;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::xml::sax;
44 using namespace ::xmloff::token;
45 
46 class XMLParagraphTransformerContext : public XMLTransformerContext
47 {
48 public:
49 	TYPEINFO();
50 
51 	XMLParagraphTransformerContext( XMLTransformerBase& rTransformer,
52 						   const ::rtl::OUString& rQName );
53 
54 	virtual ~XMLParagraphTransformerContext();
55 
56 	// Create a childs element context. By default, the import's
57 	// CreateContext method is called to create a new default context.
58 	virtual XMLTransformerContext *CreateChildContext( sal_uInt16 nPrefix,
59 								   const ::rtl::OUString& rLocalName,
60 								   const ::rtl::OUString& rQName,
61 								   const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
62 
63 	// StartElement is called after a context has been constructed and
64 	// before a elements context is parsed. It may be used for actions that
65 	// require virtual methods. The default is to do nothing.
66 	virtual void StartElement( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& xAttrList );
67 
68 	// EndElement is called before a context will be destructed, but
69 	// after a elements context has been parsed. It may be used for actions
70 	// that require virtual methods. The default is to do nothing.
71 	virtual void EndElement();
72 
73 	// This method is called for all characters that are contained in the
74 	// current element. The default is to ignore them.
75 	virtual void Characters( const ::rtl::OUString& rChars );
76 };
77 
78 TYPEINIT1( XMLParagraphTransformerContext, XMLTransformerContext );
79 
80 XMLParagraphTransformerContext::XMLParagraphTransformerContext(
81 		XMLTransformerBase& rImp,
82 		const OUString& rQName ) :
83 	XMLTransformerContext( rImp, rQName )
84 {
85 }
86 
87 XMLParagraphTransformerContext::~XMLParagraphTransformerContext()
88 {
89 }
90 
91 XMLTransformerContext *XMLParagraphTransformerContext::CreateChildContext(
92 		sal_uInt16 /*nPrefix*/,
93 		const OUString& /*rLocalName*/,
94 		const OUString& rQName,
95 		const Reference< XAttributeList >& )
96 {
97 	XMLTransformerContext *pContext = 0;
98 
99     pContext = new XMLIgnoreTransformerContext( GetTransformer(),
100 												rQName, sal_True );
101 
102 	return pContext;
103 }
104 
105 void XMLParagraphTransformerContext::StartElement( const Reference< XAttributeList >& rAttrList )
106 {
107     XMLTransformerContext::StartElement( rAttrList );
108 }
109 
110 void XMLParagraphTransformerContext::EndElement()
111 {
112     XMLTransformerContext::EndElement();
113 }
114 
115 void XMLParagraphTransformerContext::Characters( const OUString& rChars )
116 {
117     XMLTransformerContext::Characters( rChars );
118 }
119 
120 class XMLPersTextContentRNGTransformTContext : public XMLPersTextContentTContext
121 {
122 public:
123 	TYPEINFO();
124 
125     XMLPersTextContentRNGTransformTContext(
126         XMLTransformerBase& rTransformer,
127         const ::rtl::OUString& rQName,
128         sal_uInt16 nPrefix,
129         ::xmloff::token::XMLTokenEnum eToken );
130     virtual ~XMLPersTextContentRNGTransformTContext();
131 
132 	virtual void Characters( const ::rtl::OUString& rChars );
133 };
134 
135 TYPEINIT1( XMLPersTextContentRNGTransformTContext, XMLPersAttrListTContext );
136 
137 XMLPersTextContentRNGTransformTContext::XMLPersTextContentRNGTransformTContext(
138     XMLTransformerBase& rTransformer,
139     const ::rtl::OUString& rQName,
140     sal_uInt16 nPrefix,
141     ::xmloff::token::XMLTokenEnum eToken ) :
142         XMLPersTextContentTContext(
143             rTransformer, rQName, nPrefix, eToken )
144 {}
145 
146 XMLPersTextContentRNGTransformTContext::~XMLPersTextContentRNGTransformTContext()
147 {}
148 
149 void XMLPersTextContentRNGTransformTContext::Characters( const ::rtl::OUString& rChars )
150 {
151     OUString aConvChars( rChars );
152     GetTransformer().ConvertRNGDateTimeToISO( aConvChars );
153     XMLPersTextContentTContext::Characters( aConvChars );
154 }
155 
156 
157 TYPEINIT1( XMLMergeElemTransformerContext, XMLTransformerContext );
158 
159 void XMLMergeElemTransformerContext::ExportStartElement()
160 {
161 	XMLPersTextContentTContextVector::iterator aIter = m_aChildContexts.begin();
162 
163 	for( ; aIter != m_aChildContexts.end(); ++aIter )
164 	{
165 		XMLPersTextContentTContext *pContext = (*aIter).get();
166 		static_cast< XMLMutableAttributeList * >( m_xAttrList.get() )
167 			->AddAttribute( pContext->GetExportQName(),
168 							pContext->GetTextContent() );
169 	}
170 	XMLTransformerContext::StartElement( m_xAttrList );
171 
172 	m_bStartElementExported = sal_True;
173 }
174 
175 XMLMergeElemTransformerContext::XMLMergeElemTransformerContext(
176 		XMLTransformerBase& rImp,
177 		const OUString& rQName,
178 	   sal_uInt16 nActionMap ) :
179 	XMLTransformerContext( rImp, rQName ),
180 	m_nActionMap( nActionMap ),
181 	m_bStartElementExported( sal_False )
182 {
183 }
184 
185 XMLMergeElemTransformerContext::~XMLMergeElemTransformerContext()
186 {
187 }
188 
189 void XMLMergeElemTransformerContext::StartElement(
190 	const Reference< XAttributeList >& rAttrList )
191 {
192 	XMLMutableAttributeList *pMutableAttrList =
193 		new XMLMutableAttributeList( rAttrList, sal_True );
194 	m_xAttrList = pMutableAttrList;
195 
196 	sal_Int16 nAttrCount = m_xAttrList.is() ? m_xAttrList->getLength() : 0;
197 	for( sal_Int16 i=0; i < nAttrCount; i++ )
198 	{
199 		const OUString& rAttrName = m_xAttrList->getNameByIndex( i );
200 		OUString aLocalName;
201 		sal_uInt16 nPrefix =
202 			GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName,
203 																&aLocalName );
204         sal_Bool bRemove = sal_True;
205         if( XML_NAMESPACE_OFFICE == nPrefix)
206         {
207             if (IsXMLToken( aLocalName, XML_DISPLAY ) )
208                 bRemove = sal_False;
209             else if (IsXMLToken( aLocalName, XML_AUTHOR ) )
210                 bRemove = sal_False;
211             else if (IsXMLToken( aLocalName, XML_CREATE_DATE ) )
212                 bRemove = sal_False;
213             else if (IsXMLToken( aLocalName, XML_CREATE_DATE_STRING ) )
214                 bRemove = sal_False;
215         }
216         if (bRemove)
217         {
218             pMutableAttrList->RemoveAttributeByIndex( i );
219             --i;
220             --nAttrCount;
221         }
222 	}
223 }
224 
225 XMLTransformerContext *XMLMergeElemTransformerContext::CreateChildContext(
226 		sal_uInt16 nPrefix,
227 		const OUString& rLocalName,
228 		const OUString& rQName,
229 		const Reference< XAttributeList >& rAttrList )
230 {
231 	XMLTransformerContext *pContext = 0;
232 
233 	if( !m_bStartElementExported )
234 	{
235 		XMLTransformerActions *pActions =
236 			GetTransformer().GetUserDefinedActions( m_nActionMap );
237 		OSL_ENSURE( pActions, "go no actions" );
238 		if( pActions )
239 		{
240 			XMLTransformerActions::key_type aKey( nPrefix, rLocalName );
241 			XMLTransformerActions::const_iterator aIter =
242 				pActions->find( aKey );
243 
244 			if( !(aIter == pActions->end()) )
245 			{
246 				switch( (*aIter).second.m_nActionType )
247 				{
248 				case XML_ATACTION_MOVE_FROM_ELEM_RNG2ISO_DATETIME:
249 					{
250 						XMLPersTextContentTContext *pTC =
251 							new XMLPersTextContentRNGTransformTContext(
252 									GetTransformer(), rQName,
253 								    (*aIter).second.GetQNamePrefixFromParam1(),
254 									(*aIter).second.GetQNameTokenFromParam1() );
255 						XMLPersTextContentTContextVector::value_type aVal(pTC);
256 						m_aChildContexts.push_back( aVal );
257 						pContext = pTC;
258 					}
259 					break;
260                 case XML_ATACTION_MOVE_FROM_ELEM:
261 					{
262 						XMLPersTextContentTContext *pTC =
263 							new XMLPersTextContentTContext(
264 									GetTransformer(), rQName,
265 								    (*aIter).second.GetQNamePrefixFromParam1(),
266 									(*aIter).second.GetQNameTokenFromParam1() );
267 						XMLPersTextContentTContextVector::value_type aVal(pTC);
268 						m_aChildContexts.push_back( aVal );
269 						pContext = pTC;
270 					}
271 					break;
272                 case XML_ETACTION_EXTRACT_CHARACTERS:
273                     {
274 		                if( !m_bStartElementExported )
275 			                ExportStartElement();
276                         XMLParagraphTransformerContext* pPTC =
277 	                        new XMLParagraphTransformerContext( GetTransformer(),
278 						    rQName);
279 						pContext = pPTC;
280                     }
281                     break;
282 				default:
283 					OSL_ENSURE( !this, "unknown action" );
284 					break;
285 				}
286 			}
287 		}
288 	}
289     else
290 	{
291 		XMLTransformerActions *pActions =
292 			GetTransformer().GetUserDefinedActions( m_nActionMap );
293 		OSL_ENSURE( pActions, "go no actions" );
294 		if( pActions )
295 		{
296 			XMLTransformerActions::key_type aKey( nPrefix, rLocalName );
297 			XMLTransformerActions::const_iterator aIter =
298 				pActions->find( aKey );
299 
300 			if( !(aIter == pActions->end()) )
301 			{
302 				switch( (*aIter).second.m_nActionType )
303 				{
304                 case XML_ETACTION_EXTRACT_CHARACTERS:
305                     {
306 		                if( !m_bStartElementExported )
307 			                ExportStartElement();
308                         XMLParagraphTransformerContext* pPTC =
309 	                        new XMLParagraphTransformerContext( GetTransformer(),
310 						    rQName);
311 						pContext = pPTC;
312                     }
313                     break;
314 				default:
315 					OSL_ENSURE( !this, "unknown action" );
316 					break;
317 				}
318 			}
319 		}
320 	}
321 
322 	// default is copying
323 	if( !pContext )
324 	{
325 		if( !m_bStartElementExported )
326 			ExportStartElement();
327 		pContext = XMLTransformerContext::CreateChildContext( nPrefix,
328 															  rLocalName,
329 															  rQName,
330 															  rAttrList );
331 	}
332 
333 	return pContext;
334 }
335 
336 void XMLMergeElemTransformerContext::EndElement()
337 {
338 	if( !m_bStartElementExported )
339 		ExportStartElement();
340 	XMLTransformerContext::EndElement();
341 }
342 
343 void XMLMergeElemTransformerContext::Characters( const OUString& )
344 {
345 	// ignore
346 }
347