merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / xml / basicparser.cxx
blobfc30410dfa0631f09e889d11457a4e3cc350a837
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: basicparser.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "basicparser.hxx"
35 #include <com/sun/star/xml/sax/SAXException.hpp>
36 #include "valuetypeconverter.hxx"
37 // -----------------------------------------------------------------------------
39 namespace configmgr
41 // -----------------------------------------------------------------------------
42 namespace xml
44 // -----------------------------------------------------------------------------
45 namespace uno = ::com::sun::star::uno;
46 namespace sax = ::com::sun::star::xml::sax;
47 // -----------------------------------------------------------------------------
49 namespace
51 static inline
52 uno::Reference< script::XTypeConverter > createTCV(uno::Reference< uno::XComponentContext > const & _xContext)
54 OSL_ENSURE(_xContext.is(),"Cannot create Parser without a Context");
56 static const rtl::OUString k_sTCVService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter"));
58 uno::Reference< lang::XMultiComponentFactory > xSvcFactory = _xContext->getServiceManager();
59 return uno::Reference< script::XTypeConverter >::query(xSvcFactory->createInstanceWithContext(k_sTCVService,_xContext));
62 // -----------------------------------------------------------------------------
64 struct BasicParser::ValueData : ValueConverter
66 rtl::OUString content;
67 rtl::OUString locale;
68 bool isLocalized;
70 ValueData(uno::Type const& _aType, uno::Reference< script::XTypeConverter > const & _xTCV)
71 : ValueConverter(_aType, _xTCV)
72 , content()
73 , locale()
74 , isLocalized(false)
78 uno::Any convertToAny() const
80 return ValueConverter::convertToAny(this->content);
83 rtl::OUString toString() const
85 return this->content;
88 uno::Sequence<rtl::OUString> toStringList() const
90 return ValueConverter::splitStringList(this->content);
93 void setLocalized(rtl::OUString const & _aLocale)
95 isLocalized = true;
96 locale = _aLocale;
99 // -----------------------------------------------------------------------------
101 BasicParser::BasicParser(uno::Reference< uno::XComponentContext > const & _xContext)
102 : m_xTypeConverter( createTCV(_xContext) )
103 , m_xLocator(NULL)
104 , m_aDataParser(Logger(_xContext))
105 , m_aNodes()
106 , m_aValueType()
107 , m_pValueData(NULL)
108 , m_nSkipLevels(0)
109 , m_bEmpty(true)
110 , m_bInProperty(false)
112 if (!m_xTypeConverter.is())
113 throw uno::RuntimeException();
115 OSL_DEBUG_ONLY( dbgUpdateLocation() );
117 // -----------------------------------------------------------------------------
119 BasicParser::~BasicParser()
121 delete m_pValueData;
123 // -----------------------------------------------------------------------------
125 #if OSL_DEBUG_LEVEL > 0
126 void BasicParser::dbgUpdateLocation()
128 #ifndef DBG_UTIL
129 rtl::OUString dbgPublicId, dbgSystemId;
130 sal_Int32 dbgLineNo, dbgColumnNo;
131 #endif // OSL_DEBUG_LEVEL
133 if (m_xLocator.is())
135 dbgPublicId = m_xLocator->getPublicId();
136 dbgSystemId = m_xLocator->getSystemId();
137 dbgLineNo = m_xLocator->getLineNumber();
138 dbgColumnNo = m_xLocator->getColumnNumber();
140 else
142 dbgPublicId = dbgSystemId = rtl::OUString::createFromAscii("<<<unknown>>>");
143 dbgLineNo = dbgColumnNo = -1;
146 #endif
147 // -----------------------------------------------------------------------------
148 void SAL_CALL BasicParser::startDocument( )
149 throw (sax::SAXException, uno::RuntimeException)
151 m_aDataParser.reset();
152 m_aValueType = uno::Type();
153 m_bInProperty = false;
154 m_nSkipLevels = 0;
156 delete m_pValueData, m_pValueData = NULL;
158 while (!m_aNodes.empty()) m_aNodes.pop();
160 m_bEmpty = true;
162 OSL_DEBUG_ONLY( dbgUpdateLocation() );
164 // -----------------------------------------------------------------------------
166 void SAL_CALL BasicParser::endDocument( ) throw (sax::SAXException, uno::RuntimeException)
168 OSL_DEBUG_ONLY( dbgUpdateLocation() );
170 if (!m_aNodes.empty() || isSkipping() || isInValueData())
171 raiseParseException( "Configuration XML Parser - Invalid XML: Unexpected end of document" );
173 m_xLocator.clear();
175 // -----------------------------------------------------------------------------
177 void SAL_CALL BasicParser::characters( const rtl::OUString& aChars )
178 throw (sax::SAXException, uno::RuntimeException)
180 OSL_DEBUG_ONLY( dbgUpdateLocation() );
182 if (isInValueData())
184 m_pValueData->content += aChars;
186 #ifdef CONFIG_XMLPARSER_VALIDATE_WHITESPACE
187 else
188 OSL_ENSURE( isSkipping() || aChars.trim().getLength() == 0, "Unexpected text content in configuration XML");
189 #endif
191 // -----------------------------------------------------------------------------
193 void SAL_CALL BasicParser::ignorableWhitespace( const rtl::OUString& aWhitespaces )
194 throw (sax::SAXException, uno::RuntimeException)
196 OSL_DEBUG_ONLY( dbgUpdateLocation() );
197 if (isInValueData())
199 OSL_ENSURE(false, "Configuration XML: Unexpected ignorable (!) whitespace instruction in value data");
200 if (!m_pValueData->isNull())
201 m_pValueData->content += aWhitespaces;
203 #ifdef CONFIG_XMLPARSER_VALIDATE_WHITESPACE
204 else
205 OSL_ENSURE( aChars.trim().getLength() == 0, "Unexpected non-space content in ignorable whitespace");
206 #endif
208 // -----------------------------------------------------------------------------
210 void SAL_CALL BasicParser::processingInstruction( const rtl::OUString& /*aTarget*/, const rtl::OUString& /*aData*/ )
211 throw (sax::SAXException, uno::RuntimeException)
213 OSL_DEBUG_ONLY( dbgUpdateLocation() );
214 OSL_ENSURE(false, "Unexpected processing instruction in Configuration XML");
216 // -----------------------------------------------------------------------------
218 void SAL_CALL BasicParser::setDocumentLocator( const uno::Reference< sax::XLocator >& xLocator )
219 throw (sax::SAXException, uno::RuntimeException)
221 m_xLocator = xLocator;
222 OSL_DEBUG_ONLY( dbgUpdateLocation() );
224 // -----------------------------------------------------------------------------
226 void BasicParser::startNode( ElementInfo const & aInfo, const uno::Reference< sax::XAttributeList >& /*xAttribs*/ )
228 { (void)aInfo; }
229 OSL_DEBUG_ONLY( dbgUpdateLocation() );
231 OSL_ENSURE( !isSkipping(), "While skipping, call startSkipping() instead of startNode()");
232 OSL_ENSURE( aInfo.type != ElementType::property, "For properties, call startProperty() instead of startNode()");
234 if (isInProperty())
235 raiseParseException( "Configuration XML Parser - Invalid Data: Cannot have a node nested in a property" );
237 m_aNodes.push(aInfo);
238 m_bEmpty = (aInfo.flags != 0) || (aInfo.op > Operation::modify);
240 OSL_POSTCOND( isInNode(), "Could not start a node ");
242 // -----------------------------------------------------------------------------
244 void BasicParser::endNode( )
246 OSL_DEBUG_ONLY( dbgUpdateLocation() );
248 OSL_ENSURE( !isSkipping(), "While skipping, honor wasSkipping() instead of calling endNode()");
249 OSL_ENSURE( !isInProperty(), "For properties, call endProperty() instead of endNode()" );
251 ensureInNode();
253 m_aNodes.pop();
254 m_bEmpty = false;
256 // -----------------------------------------------------------------------------
258 void BasicParser::ensureInNode( )
260 if (!isInNode())
261 raiseParseException("Unexpected endElement without matching startElement");
263 // -----------------------------------------------------------------------------
265 bool BasicParser::isInNode( )
267 return ! m_aNodes.empty();
269 // -----------------------------------------------------------------------------
271 bool BasicParser::isEmptyNode( )
273 return m_bEmpty;
275 // -----------------------------------------------------------------------------
277 ElementInfo const & BasicParser::getActiveNodeInfo( )
279 ensureInNode();
281 return m_aNodes.top();
283 // -----------------------------------------------------------------------------
285 void BasicParser::startProperty( ElementInfo const & aInfo, const uno::Reference< sax::XAttributeList >& xAttribs )
287 OSL_DEBUG_ONLY( dbgUpdateLocation() );
289 OSL_ENSURE( !isSkipping(), "While skipping, call startSkipping() instead of startProperty()");
290 OSL_ENSURE( aInfo.type == ElementType::property, "For non-property nodes, call startNode() instead of startProperty()");
292 if (isInProperty())
293 raiseParseException( "Configuration XML Parser - Invalid Data: Properties may not nest" );
295 try
297 m_aValueType = getDataParser().getPropertyValueType(xAttribs);
299 catch (ElementParser::BadValueType & error)
301 raiseParseException(error.message());
304 m_bInProperty = true;
306 m_aNodes.push(aInfo);
307 m_bEmpty = true;
309 OSL_POSTCOND( isInProperty(), "Could not get data to start a property" );
310 OSL_POSTCOND( isInUnhandledProperty(), "Could not mark property as unhandled");
312 // -----------------------------------------------------------------------------
314 void BasicParser::endProperty( )
316 OSL_DEBUG_ONLY( dbgUpdateLocation() );
318 OSL_ENSURE( !isSkipping(), "While skipping, honor wasSkipping() instead of calling endProperty()");
319 OSL_ENSURE( isInProperty(), "For non-property nodes, call endNode() instead of endProperty()" );
321 ensureInNode();
323 m_aNodes.pop();
324 m_bEmpty = false;
326 m_aValueType = uno::Type();
327 m_bInProperty = false;
329 OSL_POSTCOND( !isInProperty(), "Could not get mark end of property" );
331 // -----------------------------------------------------------------------------
333 uno::Type BasicParser::getActivePropertyType()
335 return m_aValueType;
337 // -----------------------------------------------------------------------------
339 bool BasicParser::isInProperty()
341 return m_bInProperty;
343 // -----------------------------------------------------------------------------
345 bool BasicParser::isInUnhandledProperty()
347 return m_bEmpty && m_bInProperty;
349 // -----------------------------------------------------------------------------
351 void BasicParser::startValueData(const uno::Reference< sax::XAttributeList >& xAttribs)
353 OSL_DEBUG_ONLY( dbgUpdateLocation() );
355 if (!isInProperty())
356 raiseParseException( "Configuration XML Parser - Invalid Data: A value may occur only within a property" );
358 if (m_aValueType.getTypeClass() == uno::TypeClass_ANY)
359 raiseParseException( "Configuration XML Parser - Invalid Data: Cannot have values for properties of type 'Any'" );
361 if (isInValueData())
362 raiseParseException( "Configuration XML Parser - Invalid Data: Unexpected element while parsing value data" );
364 m_pValueData = new ValueData(m_aValueType, m_xTypeConverter);
366 m_pValueData->setIsNull( getDataParser().isNull(xAttribs) );
368 m_pValueData->setSeparator( getDataParser().getSeparator(xAttribs) );
370 OSL_ENSURE( !m_pValueData->hasSeparator() ||
371 !m_pValueData->isTypeSet() ||
372 m_pValueData->isList(),
373 "Warning: Spurious oor:separator on value that is not a list");
374 OSL_ENSURE( !m_pValueData->hasSeparator() ||
375 !m_pValueData->isNull(),
376 "Warning: Spurious oor:separator on value that is not a list");
378 rtl::OUString aLocale;
379 if ( getDataParser().getLanguage(xAttribs,aLocale) )
380 m_pValueData->setLocalized( aLocale );
382 // -----------------------------------------------------------------------------
384 bool BasicParser::isInValueData()
386 return m_pValueData != NULL;
388 // -----------------------------------------------------------------------------
390 bool BasicParser::isValueDataLocalized()
392 OSL_ENSURE(isInValueData(), "There is no value data that could be localized");
394 return m_pValueData && m_pValueData->isLocalized;
396 // -----------------------------------------------------------------------------
398 rtl::OUString BasicParser::getValueDataLocale()
400 OSL_ENSURE(isValueDataLocalized(), "There is no value data or it is not localized");
402 return m_pValueData->locale;
404 // -----------------------------------------------------------------------------
406 uno::Any BasicParser::getCurrentValue()
408 OSL_DEBUG_ONLY( dbgUpdateLocation() );
410 OSL_ASSERT( isInValueData() );
412 uno::Any aResult;
414 if (m_pValueData->isTypeSet())
417 aResult = m_pValueData->convertToAny();
419 catch (script::CannotConvertException & e)
421 this->raiseParseException(uno::makeAny(e),"Configuration XML Parser - Invalid Data: Cannot convert value to type of property" );
423 else if (m_pValueData->isNull())
425 // nothing to do
427 else if (m_pValueData->hasSeparator() || m_pValueData->isList())
429 aResult <<= m_pValueData->toStringList();
431 else
433 aResult <<= m_pValueData->toString();
435 return aResult;
437 // -----------------------------------------------------------------------------
439 /// end collecting data for a value
440 void BasicParser::endValueData()
442 OSL_DEBUG_ONLY( dbgUpdateLocation() );
444 OSL_ASSERT( isInValueData() );
446 delete m_pValueData, m_pValueData = NULL;
447 m_bEmpty = false;
449 OSL_POSTCOND( !isInValueData(), "Could not end value data tag" );
450 OSL_POSTCOND( !isInUnhandledProperty(), "Could not mark property as handled" );
452 // -----------------------------------------------------------------------------
454 void BasicParser::startSkipping( const rtl::OUString& aName, const uno::Reference< sax::XAttributeList >& /*xAttribs*/ )
456 OSL_DEBUG_ONLY( dbgUpdateLocation() );
458 m_aNodes.push( ElementInfo(aName) );
459 ++m_nSkipLevels;
461 // -----------------------------------------------------------------------------
463 bool BasicParser::wasSkipping( const rtl::OUString& aName )
465 OSL_DEBUG_ONLY( dbgUpdateLocation() );
467 if (m_nSkipLevels == 0) return false;
469 if (m_aNodes.empty())
470 raiseParseException( "Configuration XML Parser - Invalid XML: Unexpected end of element (while skipping data)" );
472 if (aName != m_aNodes.top().name)
473 raiseParseException( "Configuration XML Parser - Invalid XML: End tag does not match start tag (while skipping data)" );
475 --m_nSkipLevels;
476 m_aNodes.pop();
478 return true;
480 // -----------------------------------------------------------------------------
482 bool BasicParser::isSkipping( )
484 return m_nSkipLevels != 0;
486 // -----------------------------------------------------------------------------
488 void BasicParser::raiseParseException( uno::Any const & _aTargetException, sal_Char const * _pMsg )
489 SAL_THROW((sax::SAXException, uno::RuntimeException))
491 OSL_DEBUG_ONLY( dbgUpdateLocation() );
493 if (_pMsg == 0) _pMsg = "Configuration XML Parser: Invalid Data: ";
495 rtl::OUString sMessage = rtl::OUString::createFromAscii(_pMsg);
497 uno::Exception aEx;
498 if (_aTargetException >>= aEx)
499 sMessage += aEx.Message;
501 getLogger().error(sMessage,"parse","configuration::xml::BasicParser");
502 throw sax::SAXException( sMessage, *this, _aTargetException );
504 // -----------------------------------------------------------------------------
506 void BasicParser::raiseParseException( sal_Char const * _pMsg )
507 SAL_THROW((sax::SAXException, uno::RuntimeException))
509 OSL_DEBUG_ONLY( dbgUpdateLocation() );
511 if (_pMsg == 0) _pMsg = "Configuration XML Parser: Invalid XML";
513 rtl::OUString const sMessage = rtl::OUString::createFromAscii(_pMsg);
515 getLogger().error(sMessage,"parse","configuration::xml::BasicParser");
516 throw sax::SAXException( sMessage, *this, uno::Any() );
518 // -----------------------------------------------------------------------------
520 void BasicParser::raiseParseException( rtl::OUString const & sMessage )
521 SAL_THROW((sax::SAXException, uno::RuntimeException))
523 OSL_DEBUG_ONLY( dbgUpdateLocation() );
525 if (sMessage.getLength() == 0) raiseParseException(NULL);
527 getLogger().error(sMessage,"parse","configuration::xml::BasicParser");
528 throw sax::SAXException( sMessage, *this, uno::Any() );
530 // -----------------------------------------------------------------------------
531 // -----------------------------------------------------------------------------
532 } // namespace
534 // -----------------------------------------------------------------------------
535 } // namespace