/src/xmlpatterns/parser/qmaintainingreader.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 274 lines · 189 code · 32 blank · 53 comment · 23 complexity · 3a1554e4cc7ba9cb34a71a88bb1074b6 MD5 · raw file

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  6. **
  7. ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:LGPL$
  10. ** GNU Lesser General Public License Usage
  11. ** This file may be used under the terms of the GNU Lesser General Public
  12. ** License version 2.1 as published by the Free Software Foundation and
  13. ** appearing in the file LICENSE.LGPL included in the packaging of this
  14. ** file. Please review the following information to ensure the GNU Lesser
  15. ** General Public License version 2.1 requirements will be met:
  16. ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  17. **
  18. ** In addition, as a special exception, Nokia gives you certain additional
  19. ** rights. These rights are described in the Nokia Qt LGPL Exception
  20. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  21. **
  22. ** GNU General Public License Usage
  23. ** Alternatively, this file may be used under the terms of the GNU General
  24. ** Public License version 3.0 as published by the Free Software Foundation
  25. ** and appearing in the file LICENSE.GPL included in the packaging of this
  26. ** file. Please review the following information to ensure the GNU General
  27. ** Public License version 3.0 requirements will be met:
  28. ** http://www.gnu.org/copyleft/gpl.html.
  29. **
  30. ** Other Usage
  31. ** Alternatively, this file may be used in accordance with the terms and
  32. ** conditions contained in a signed written agreement between you and Nokia.
  33. **
  34. **
  35. **
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. /**
  42. * @file
  43. * @short This file is included by qcastingplatform_p.h.
  44. * If you need includes in this file, put them in CasttingPlatform.h,
  45. * outside of the namespace.
  46. */
  47. template<typename TokenLookupClass,
  48. typename LookupKey>
  49. MaintainingReader<TokenLookupClass, LookupKey>::MaintainingReader(const typename ElementDescription<TokenLookupClass, LookupKey>::Hash &elementDescriptions,
  50. const QSet<typename TokenLookupClass::NodeName> &standardAttributes,
  51. const ReportContext::Ptr &context,
  52. QIODevice *const queryDevice) : QXmlStreamReader(queryDevice)
  53. , m_hasHandledStandardAttributes(false)
  54. , m_context(context)
  55. , m_elementDescriptions(elementDescriptions)
  56. , m_standardAttributes(standardAttributes)
  57. {
  58. Q_ASSERT(m_context);
  59. Q_ASSERT(!m_elementDescriptions.isEmpty());
  60. /* We start with stripping. */
  61. m_stripWhitespace.push(true);
  62. }
  63. template<typename TokenLookupClass,
  64. typename LookupKey>
  65. MaintainingReader<TokenLookupClass, LookupKey>::~MaintainingReader()
  66. {
  67. }
  68. template<typename TokenLookupClass,
  69. typename LookupKey>
  70. QSourceLocation MaintainingReader<TokenLookupClass, LookupKey>::currentLocation() const
  71. {
  72. return QSourceLocation(documentURI(),
  73. lineNumber(),
  74. columnNumber());
  75. }
  76. template<typename TokenLookupClass,
  77. typename LookupKey>
  78. QXmlStreamReader::TokenType MaintainingReader<TokenLookupClass, LookupKey>::readNext()
  79. {
  80. const TokenType retval = QXmlStreamReader::readNext();
  81. switch(retval)
  82. {
  83. case StartElement:
  84. {
  85. m_currentElementName = TokenLookupClass::toToken(name());
  86. m_currentAttributes = attributes();
  87. m_hasHandledStandardAttributes = false;
  88. if(!m_currentAttributes.hasAttribute(QLatin1String("xml:space")))
  89. m_stripWhitespace.push(m_stripWhitespace.top());
  90. break;
  91. }
  92. case EndElement:
  93. m_currentElementName = TokenLookupClass::toToken(name());
  94. m_stripWhitespace.pop();
  95. break;
  96. default:
  97. break;
  98. }
  99. return retval;
  100. }
  101. template<typename TokenLookupClass,
  102. typename LookupKey>
  103. bool MaintainingReader<TokenLookupClass, LookupKey>::isWhitespace() const
  104. {
  105. return QXmlStreamReader::isWhitespace()
  106. || XPathHelper::isWhitespaceOnly(text());
  107. }
  108. template<typename TokenLookupClass,
  109. typename LookupKey>
  110. void MaintainingReader<TokenLookupClass, LookupKey>::error(const QString &message,
  111. const ReportContext::ErrorCode code) const
  112. {
  113. m_context->error(message, code, currentLocation());
  114. }
  115. template<typename TokenLookupClass,
  116. typename LookupKey>
  117. void MaintainingReader<TokenLookupClass, LookupKey>::warning(const QString &message) const
  118. {
  119. m_context->warning(message, currentLocation());
  120. }
  121. template<typename TokenLookupClass,
  122. typename LookupKey>
  123. typename TokenLookupClass::NodeName MaintainingReader<TokenLookupClass, LookupKey>::currentElementName() const
  124. {
  125. return m_currentElementName;
  126. }
  127. template<typename TokenLookupClass,
  128. typename LookupKey>
  129. void MaintainingReader<TokenLookupClass, LookupKey>::validateElement(const LookupKey elementName) const
  130. {
  131. Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
  132. if(m_elementDescriptions.contains(elementName))
  133. {
  134. // QHash::value breaks in Metrowerks Compiler
  135. const ElementDescription<TokenLookupClass, LookupKey> &desc = *m_elementDescriptions.find(elementName);
  136. const int attCount = m_currentAttributes.count();
  137. QSet<typename TokenLookupClass::NodeName> encounteredXSLTAtts;
  138. for(int i = 0; i < attCount; ++i)
  139. {
  140. const QXmlStreamAttribute &attr = m_currentAttributes.at(i);
  141. if(attr.namespaceUri().isEmpty())
  142. {
  143. const typename TokenLookupClass::NodeName attrName(TokenLookupClass::toToken(attr.name()));
  144. encounteredXSLTAtts.insert(attrName);
  145. if(!desc.requiredAttributes.contains(attrName) &&
  146. !desc.optionalAttributes.contains(attrName) &&
  147. !m_standardAttributes.contains(attrName) &&
  148. !isAnyAttributeAllowed())
  149. {
  150. QString translationString;
  151. QList<typename TokenLookupClass::NodeName> all(desc.requiredAttributes.toList() + desc.optionalAttributes.toList());
  152. const int totalCount = all.count();
  153. QStringList allowed;
  154. for(int i = 0; i < totalCount; ++i)
  155. allowed.append(QPatternist::formatKeyword(TokenLookupClass::toString(all.at(i))));
  156. /* Note, we can't run toString() on attrName, because we're in this branch,
  157. * the token lookup doesn't have the string(!).*/
  158. const QString stringedName(attr.name().toString());
  159. if(totalCount == 0)
  160. {
  161. translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Only the standard attributes can appear.")
  162. .arg(formatKeyword(stringedName),
  163. formatKeyword(name()));
  164. }
  165. else if(totalCount == 1)
  166. {
  167. translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes.")
  168. .arg(formatKeyword(stringedName),
  169. formatKeyword(name()),
  170. allowed.first());
  171. }
  172. else if(totalCount == 1)
  173. {
  174. /* Note, allowed has already had formatKeyword() applied. */
  175. translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes.")
  176. .arg(formatKeyword(stringedName),
  177. formatKeyword(name()),
  178. allowed.first(),
  179. allowed.last());
  180. }
  181. else
  182. {
  183. /* Note, allowed has already had formatKeyword() applied. */
  184. translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes.")
  185. .arg(formatKeyword(stringedName),
  186. formatKeyword(name()),
  187. allowed.join(QLatin1String(", ")));
  188. }
  189. m_context->error(translationString,
  190. ReportContext::XTSE0090,
  191. currentLocation());
  192. }
  193. }
  194. else if(attr.namespaceUri() == namespaceUri())
  195. {
  196. m_context->error(QtXmlPatterns::tr("XSL-T attributes on XSL-T elements must be in the null namespace, not in the XSL-T namespace which %1 is.")
  197. .arg(formatKeyword(attr.name())),
  198. ReportContext::XTSE0090,
  199. currentLocation());
  200. }
  201. /* Else, attributes in other namespaces are allowed, continue. */
  202. }
  203. const QSet<typename TokenLookupClass::NodeName> requiredButMissing(QSet<typename TokenLookupClass::NodeName>(desc.requiredAttributes).subtract(encounteredXSLTAtts));
  204. if(!requiredButMissing.isEmpty())
  205. {
  206. error(QtXmlPatterns::tr("The attribute %1 must appear on element %2.")
  207. .arg(QPatternist::formatKeyword(TokenLookupClass::toString(*requiredButMissing.constBegin())),
  208. formatKeyword(name())),
  209. ReportContext::XTSE0010);
  210. }
  211. }
  212. else
  213. {
  214. error(QtXmlPatterns::tr("The element with local name %1 does not exist in XSL-T.").arg(formatKeyword(name())),
  215. ReportContext::XTSE0010);
  216. }
  217. }
  218. template<typename TokenLookupClass,
  219. typename LookupKey>
  220. bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &namespaceURI,
  221. const QString &localName) const
  222. {
  223. Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
  224. return m_currentAttributes.hasAttribute(namespaceURI, localName);
  225. }
  226. template<typename TokenLookupClass,
  227. typename LookupKey>
  228. bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &localName) const
  229. {
  230. return hasAttribute(QString(), localName);
  231. }
  232. template<typename TokenLookupClass,
  233. typename LookupKey>
  234. QString MaintainingReader<TokenLookupClass, LookupKey>::readAttribute(const QString &localName,
  235. const QString &namespaceURI) const
  236. {
  237. Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
  238. Q_ASSERT_X(m_currentAttributes.hasAttribute(namespaceURI, localName),
  239. Q_FUNC_INFO,
  240. "Validation must be done before this function is called.");
  241. return m_currentAttributes.value(namespaceURI, localName).toString();
  242. }