update dev300-m58
[ooovba.git] / configmgr / source / xml / elementparser.cxx
blob12ea5dde5c9857467ae074ba0db158aab6bbb97f
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: elementparser.cxx,v $
10 * $Revision: 1.16 $
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 "elementparser.hxx"
35 #include "xmlstrings.hxx"
36 #include "typeconverter.hxx"
38 #include <com/sun/star/configuration/backend/SchemaAttribute.hpp>
39 #include <com/sun/star/configuration/backend/NodeAttribute.hpp>
41 #include <rtl/ustrbuf.hxx>
43 // -----------------------------------------------------------------------------
45 namespace configmgr
47 // -----------------------------------------------------------------------------
48 namespace xml
50 // -----------------------------------------------------------------------------
51 namespace uno = ::com::sun::star::uno;
52 namespace sax = ::com::sun::star::xml::sax;
53 // -----------------------------------------------------------------------------
55 static
56 inline
57 sal_Int16 impl_getIndexByName(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString const& aAttributeName)
59 OSL_PRECOND( xAttribs.is(), "ERROR: NULL Attribute list");
61 sal_Int16 nIndex = xAttribs->getLength();
63 while (--nIndex >= 0)
65 if (xAttribs->getNameByIndex(nIndex).equals(aAttributeName))
66 break;
68 // nIndex == -1 if not found
70 return nIndex;
72 // -----------------------------------------------------------------------------
73 static
74 inline
75 bool impl_maybeGetAttribute(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString const& aAttributeName, /* OUT */ rtl::OUString& rAttributeValue)
77 OSL_PRECOND( xAttribs.is(), "ERROR: NULL Attribute list");
79 rtl::OUString aValue = xAttribs->getValueByName(aAttributeName);
80 if( aValue.getLength()!=0)
82 rAttributeValue = aValue;
83 return true;
85 return false;
87 // -----------------------------------------------------------------------------
89 /// retrieve the (almost) complete information for an element
90 ElementInfo ElementParser::parseElementInfo(rtl::OUString const& _sTag, uno::Reference< sax::XAttributeList > const& _xAttribs) const
92 ElementType::Enum aType = this->getNodeType(_sTag,_xAttribs);
94 ElementInfo aInfo( this->getName(_sTag,_xAttribs,aType), aType );
96 aInfo.op = this->getOperation(_xAttribs,aType);
97 aInfo.flags = this->getNodeFlags(_xAttribs,aType);
99 return aInfo;
101 // -----------------------------------------------------------------------------
103 ElementType::Enum ElementParser::getNodeType(rtl::OUString const& _sElementName, uno::Reference< sax::XAttributeList > const& _xAttribs) const
105 { (void)_xAttribs; }
106 OSL_PRECOND( _xAttribs.is(), "ERROR: NULL Attribute list");
108 // todo: make this use a table, if necessary
109 ElementType::Enum eResult = ElementType::unknown;
110 if (_sElementName.equals(TAG_VALUE))
111 eResult = ElementType::value;
113 else if (_sElementName.equals(TAG_PROP))
114 eResult = ElementType::property;
116 else if (_sElementName.equals(TAG_NODE))
117 eResult = ElementType::node;
119 else if (_sElementName.equals(TAG_GROUP))
120 eResult = ElementType::group;
122 else if (_sElementName.equals(TAG_SET))
123 eResult = ElementType::set;
125 else if (_sElementName.equals(TAG_INSTANCE))
126 eResult = ElementType::instance;
128 else if (_sElementName.equals(TAG_ITEMTYPE))
129 eResult = ElementType::item_type;
131 else if (_sElementName.equals(TAG_IMPORT))
132 eResult = ElementType::import;
134 else if (_sElementName.equals(TAG_LAYER))
135 eResult = ElementType::layer;
137 else if (_sElementName.equals(TAG_SCHEMA))
138 eResult = ElementType::schema;
140 else if (_sElementName.equals(TAG_COMPONENT))
141 eResult = ElementType::component;
143 else if (_sElementName.equals(TAG_TEMPLATES))
144 eResult = ElementType::templates;
146 else if (_sElementName.equals(TAG_USES))
147 eResult = ElementType::uses;
149 // #109668# maintain support for old tag on load
150 else if (_sElementName.equals(DEPRECATED_TAG_LAYER))
152 logger().warning("Layer starts with invalid root tag \"oor:node\". Use \"oor:component-data\" instead.",
153 "getNodeType()","configmgr::xml::ElementParser");
154 eResult = ElementType::layer;
157 else
158 eResult = ElementType::other;
160 return eResult;
162 // -----------------------------------------------------------------------------
164 /// takes the node name from either an attribute or the element name
165 rtl::OUString ElementParser::getName(rtl::OUString const& _sElementName, uno::Reference< sax::XAttributeList > const& _xAttribs, ElementType::Enum _eType) const
167 rtl::OUString aName;
168 rtl::OUString aPackage;
170 bool bNameFound = this->maybeGetAttribute(_xAttribs, ATTR_NAME, aName);
171 bool bPackage = false;
173 switch (_eType)
175 case ElementType::schema:
176 bPackage = this->maybeGetAttribute(_xAttribs,ATTR_PACKAGE,aPackage);
177 OSL_ENSURE(bPackage, "configmgr::xml::ElementParser: Found schema without package.");
178 break;
180 case ElementType::layer:
181 bPackage = this->maybeGetAttribute(_xAttribs,ATTR_PACKAGE,aPackage);
183 if (!bPackage) // for compatibility we still support 'oor:context'
185 bPackage = this->maybeGetAttribute(_xAttribs,ATTR_CONTEXT,aPackage);
187 if (bPackage)
189 // TODO: log this
190 OSL_TRACE("configmgr::xml::ElementParser: Found obsolete layer attribute "
191 "oor:context=\"%s\" in component \"%s\".\n",
192 rtl::OUStringToOString(aPackage,RTL_TEXTENCODING_ASCII_US).getStr(),
193 rtl::OUStringToOString(aName,RTL_TEXTENCODING_ASCII_US).getStr());
197 OSL_ENSURE(bPackage, "configmgr::xml::ElementParser: Found layer without package.");
198 break;
200 case ElementType::node:
201 case ElementType::set:
202 case ElementType::group:
203 case ElementType::instance:
204 case ElementType::property:
205 break;
207 // these have no name to speak of
208 case ElementType::value:
209 case ElementType::item_type:
210 case ElementType::import:
211 case ElementType::uses:
212 case ElementType::templates:
213 case ElementType::component:
214 OSL_ENSURE(!bNameFound, "Configuration Parser: Unexpected name attribute is ignored\n");
215 return _sElementName;
217 // for unknown prefer name to
218 case ElementType::unknown:
219 if (!bNameFound) return _sElementName;
221 bPackage = this->maybeGetAttribute(_xAttribs,ATTR_PACKAGE,aPackage);
222 break;
224 default:
225 if (!bNameFound) return _sElementName;
226 break;
229 OSL_ENSURE(aName.getLength(),"Found empty name tag on element");
231 if (bPackage)
233 static const sal_Unicode chPackageSep = '.';
235 aName = aPackage.concat(rtl::OUString(&chPackageSep,1)).concat(aName);
237 else
239 OSL_ENSURE(!this->maybeGetAttribute(_xAttribs,ATTR_PACKAGE,aPackage),
240 "configmgr::xml::ElementParser: Found unexpected 'oor:package' on inner or unknown node." );
243 return aName;
245 // -----------------------------------------------------------------------------
247 Operation::Enum ElementParser::getOperation(uno::Reference< sax::XAttributeList > const& xAttribs,ElementType::Enum _eType) const
249 rtl::OUString sOpName;
250 if ((_eType != ElementType::property) && (_eType !=ElementType::node))
252 return Operation::none;
255 if ( !this->maybeGetAttribute(xAttribs,ATTR_OPERATION, sOpName) )
256 return Operation::none;
258 if (sOpName.equals(OPERATION_MODIFY))
259 return Operation::modify;
261 else if (sOpName.equals(OPERATION_REPLACE))
262 return Operation::replace;
263 else if (sOpName.equals(OPERATION_FUSE))
264 return Operation::fuse;
266 else if (sOpName.equals(OPERATION_REMOVE))
267 return Operation::remove;
268 #if 0
269 else if (sOpName.equals(OPERATION_CLEAR))
270 return Operation::clear;
271 #endif
272 else
273 return Operation::unknown;
275 // -----------------------------------------------------------------------------
278 /// retrieve the locale stored in the attribute list
279 bool ElementParser::getLanguage(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString& _rsLanguage) const
281 return this->maybeGetAttribute(xAttribs, EXT_ATTR_LANGUAGE, _rsLanguage);
283 // -----------------------------------------------------------------------------
285 /// reads attributes for nodes from the attribute list
286 sal_Int16 ElementParser::getNodeFlags(uno::Reference< sax::XAttributeList > const& xAttribs,ElementType::Enum _eType) const
288 namespace NodeAttribute = ::com::sun::star::configuration::backend::NodeAttribute;
289 namespace SchemaAttribute = ::com::sun::star::configuration::backend::SchemaAttribute;
291 bool bValue;
293 sal_Int16 aResult = 0;
295 switch(_eType)
297 case ElementType::property :
298 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_NULLABLE, bValue) && ! bValue)
299 aResult |= SchemaAttribute::REQUIRED;
300 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_LOCALIZED, bValue) && bValue)
301 aResult |= SchemaAttribute::LOCALIZED;
302 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_READONLY, bValue) && bValue)
303 aResult |= NodeAttribute::READONLY;
304 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_FINALIZED, bValue) && bValue)
305 aResult |= NodeAttribute::FINALIZED;
306 break;
308 case ElementType::node:
309 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_FINALIZED, bValue) && bValue)
310 aResult |= NodeAttribute::FINALIZED;
311 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_MANDATORY, bValue) && bValue)
312 aResult |= NodeAttribute::MANDATORY;
313 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_READONLY, bValue) && bValue)
314 aResult |= NodeAttribute::READONLY;
315 break;
317 case ElementType::group:
318 case ElementType::set:
319 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_EXTENSIBLE, bValue) && bValue)
320 aResult |= SchemaAttribute::EXTENSIBLE;
321 break;
323 case ElementType::layer:
324 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_READONLY, bValue) && bValue)
325 aResult |= NodeAttribute::READONLY;
326 if (this->maybeGetAttribute(xAttribs, ATTR_FLAG_FINALIZED, bValue) && bValue)
327 aResult |= NodeAttribute::FINALIZED;
328 break;
330 default:
331 break;
334 return aResult;
336 // -----------------------------------------------------------------------------
337 static
338 void badValueType(Logger const & logger, sal_Char const * _pMsg, rtl::OUString const & _sType)
340 rtl::OUStringBuffer sMessageBuf;
341 sMessageBuf.appendAscii( "Configuration XML parser: Bad value type attribute: " );
342 if (_pMsg) sMessageBuf.appendAscii(_pMsg);
344 const sal_Unicode kQuote = '"';
345 sMessageBuf.append(kQuote).append(_sType).append(kQuote);
347 rtl::OUString const sMessage = sMessageBuf.makeStringAndClear();
348 logger.error(sMessage);
349 throw ElementParser::BadValueType(sMessage);
351 // -----------------------------------------------------------------------------
352 static
353 inline
354 sal_Bool matchNsPrefix(rtl::OUString const & _sString, rtl::OUString const & _sPrefix)
356 return _sString.match(_sPrefix) &&
357 _sString.getStr()[_sPrefix.getLength()] == k_NS_SEPARATOR;
359 // -----------------------------------------------------------------------------
360 static
361 inline
362 sal_Bool matchSuffix(rtl::OUString const & _sString, rtl::OUString const & _sSuffix)
364 sal_Int32 nSuffixStart = _sString.getLength() - _sSuffix.getLength();
365 if (nSuffixStart < 0)
366 return false;
368 return _sString.match(_sSuffix,nSuffixStart);
370 // -----------------------------------------------------------------------------
371 static
372 inline
373 rtl::OUString stripNsPrefix(rtl::OUString const & _sString, rtl::OUString const & _sPrefix)
375 OSL_ASSERT( matchNsPrefix(_sString,_sPrefix) );
377 return _sString.copy(_sPrefix.getLength() + 1);
379 // -----------------------------------------------------------------------------
380 static
381 inline
382 rtl::OUString stripSuffix(rtl::OUString const & _sString, rtl::OUString const & _sSuffix)
384 OSL_ASSERT( matchSuffix(_sString,_sSuffix) );
386 sal_Int32 nSuffixStart = _sString.getLength() - _sSuffix.getLength();
388 return _sString.copy(0,nSuffixStart);
390 // -----------------------------------------------------------------------------
391 static
392 inline
393 rtl::OUString stripTypeName(Logger const & logger, rtl::OUString const & _sString, rtl::OUString const & _sPrefix)
395 if ( matchNsPrefix(_sString,_sPrefix))
396 return stripNsPrefix(_sString, _sPrefix);
398 badValueType(logger, "Missing expected namespace prefix on type name: ", _sString);
400 return _sString;
402 // -----------------------------------------------------------------------------
403 static
404 uno::Type xmlToScalarType(const rtl::OUString& _rType)
406 uno::Type aRet;
408 if (_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_BOOLEAN))
409 aRet = ::getBooleanCppuType();
411 else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_SHORT))
412 aRet = ::getCppuType(static_cast<sal_Int16 const*>(0));
414 else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_INT))
415 aRet = ::getCppuType(static_cast<sal_Int32 const*>(0));
417 else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_LONG))
418 aRet = ::getCppuType(static_cast<sal_Int64 const*>(0));
420 else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_DOUBLE))
421 aRet = ::getCppuType(static_cast< double const*>(0));
423 else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_STRING))
424 aRet = ::getCppuType(static_cast<rtl::OUString const*>(0));
426 else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_BINARY))
427 aRet = ::getCppuType(static_cast<uno::Sequence<sal_Int8> const*>(0));
429 else if(_rType.equalsIgnoreAsciiCaseAscii(VALUETYPE_ANY))
430 aRet = ::getCppuType(static_cast<uno::Any const*>(0));
432 else
433 OSL_ENSURE(false,"Cannot parse: Unknown value type");
435 return aRet;
437 // -----------------------------------------------------------------------------
438 uno::Type xmlToListType(const rtl::OUString& _aElementType)
440 uno::Type aRet;
442 if (_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_BOOLEAN))
443 aRet = ::getCppuType(static_cast<uno::Sequence<sal_Bool> const*>(0));
445 else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_SHORT))
446 aRet = ::getCppuType(static_cast<uno::Sequence<sal_Int16> const*>(0));
448 else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_INT))
449 aRet = ::getCppuType(static_cast<uno::Sequence<sal_Int32> const*>(0));
451 else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_LONG))
452 aRet = ::getCppuType(static_cast<uno::Sequence<sal_Int64> const*>(0));
454 else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_DOUBLE))
455 aRet = ::getCppuType(static_cast<uno::Sequence<double> const*>(0));
457 else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_STRING))
458 aRet = ::getCppuType(static_cast<uno::Sequence<rtl::OUString> const*>(0));
460 else if(_aElementType.equalsIgnoreAsciiCaseAscii(VALUETYPE_BINARY))
461 aRet = ::getCppuType(static_cast<uno::Sequence<uno::Sequence<sal_Int8> > const*>(0));
463 else
464 OSL_ENSURE(false,"Cannot parse: Unknown list value type");
466 return aRet;
468 // -----------------------------------------------------------------------------
469 /// retrieve data type of a property,
470 uno::Type ElementParser::getPropertyValueType(uno::Reference< sax::XAttributeList > const& xAttribs) const
472 rtl::OUString sTypeName;
473 if (!this->maybeGetAttribute(xAttribs, ATTR_VALUETYPE, sTypeName))
474 return uno::Type(); // => VOID
476 uno::Type aType;
478 // valuetype names are either 'xs:<type>' or 'oor:<type>' or 'oor:<type>-list'
479 if (matchSuffix(sTypeName,VALUETYPE_LIST_SUFFIX))
481 rtl::OUString sBasicName = stripTypeName( mLogger, stripSuffix(sTypeName,VALUETYPE_LIST_SUFFIX), NS_PREFIX_OOR );
483 aType = xmlToListType(sBasicName);
485 else
487 rtl::OUString sPrefix = matchNsPrefix(sTypeName,NS_PREFIX_OOR) ? rtl::OUString( NS_PREFIX_OOR ) : rtl::OUString( NS_PREFIX_XS );
489 rtl::OUString sBasicName = stripTypeName( mLogger, sTypeName, sPrefix );
491 aType = xmlToScalarType(sBasicName);
494 if (aType == uno::Type())
495 badValueType(mLogger,"Unknown type name: ", sTypeName);
497 return aType;
499 // -----------------------------------------------------------------------------
501 /// retrieve element type and associated module name of a set,
502 bool ElementParser::getSetElementType(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString& aElementType, rtl::OUString& aElementTypeModule) const
504 if (!this->maybeGetAttribute(xAttribs, ATTR_ITEMTYPE, aElementType))
505 return false;
507 maybeGetAttribute(xAttribs, ATTR_ITEMTYPECOMPONENT, aElementTypeModule);
509 return true;
511 // -----------------------------------------------------------------------------
513 /// retrieve instance type and associated module name of a set,
514 bool ElementParser::getInstanceType(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString& aElementType, rtl::OUString& aElementTypeModule) const
516 if (!this->maybeGetAttribute(xAttribs, ATTR_ITEMTYPE, aElementType))
517 return false;
519 maybeGetAttribute(xAttribs, ATTR_ITEMTYPECOMPONENT, aElementTypeModule);
521 return true;
523 // -----------------------------------------------------------------------------
525 /// retrieve the component for an import or uses element,
526 bool ElementParser::getImportComponent(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString& _rsComponent) const
528 return this->maybeGetAttribute(xAttribs, ATTR_COMPONENT, _rsComponent);
530 // -----------------------------------------------------------------------------
532 /// reads attributes for values from the attribute list
533 bool ElementParser::isNull(uno::Reference< sax::XAttributeList > const& _xAttribs) const
535 bool bNull;
536 return maybeGetAttribute(_xAttribs, EXT_ATTR_NULL, bNull) && bNull;
538 // -----------------------------------------------------------------------------
540 /// reads attributes for values from the attribute list
541 rtl::OUString ElementParser::getSeparator(uno::Reference< sax::XAttributeList > const& _xAttribs) const
543 rtl::OUString aSeparator;
544 maybeGetAttribute(_xAttribs, ATTR_VALUESEPARATOR, aSeparator);
545 return aSeparator;
547 // -----------------------------------------------------------------------------
549 // low-level internal methods
550 /// checks for presence of a boolean attribute and assigns its value if it exists (and is a bool)
551 bool ElementParser::maybeGetAttribute(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString const& aAttributeName, bool& rAttributeValue) const
553 rtl::OUString sAttribute;
555 if ( !this->maybeGetAttribute(xAttribs, aAttributeName, sAttribute) )
557 return false;
560 else if (sAttribute.equals(ATTR_VALUE_TRUE))
561 rAttributeValue = true; // will return true
563 else if (sAttribute.equals(ATTR_VALUE_FALSE))
564 rAttributeValue = false; // will return true
566 else
568 OSL_ENSURE(sAttribute.getLength() == 0, "Invalid text found in boolean attribute");
569 return false;
572 return true;
574 // -----------------------------------------------------------------------------
576 /// checks for presence of an attribute and assigns its value if it exists
577 bool ElementParser::maybeGetAttribute(uno::Reference< sax::XAttributeList > const& xAttribs, rtl::OUString const& aAttributeName, rtl::OUString& rAttributeValue) const
579 return xAttribs.is() && impl_maybeGetAttribute(xAttribs, aAttributeName, rAttributeValue);
582 // -----------------------------------------------------------------------------
583 } // namespace
584 } // namespace