1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40//
41// W A R N I N G
42// -------------
43//
44// This file is not part of the Qt API. It exists purely as an
45// implementation detail. This header file may change from version to
46// version without notice, or even be removed.
47//
48// We mean it.
49//
50
51/**
52 * @file
53 * @short This file is included by qcastingplatform_p.h.
54 * If you need includes in this file, put them in CasttingPlatform.h,
55 * outside of the namespace.
56 */
57
58template<typename TokenLookupClass,
59 typename LookupKey>
60MaintainingReader<TokenLookupClass, LookupKey>::MaintainingReader(const typename ElementDescription<TokenLookupClass, LookupKey>::Hash &elementDescriptions,
61 const QSet<typename TokenLookupClass::NodeName> &standardAttributes,
62 const ReportContext::Ptr &context,
63 QIODevice *const queryDevice) : QXmlStreamReader(queryDevice)
64 , m_hasHandledStandardAttributes(false)
65 , m_context(context)
66 , m_elementDescriptions(elementDescriptions)
67 , m_standardAttributes(standardAttributes)
68{
69 Q_ASSERT(m_context);
70 Q_ASSERT(!m_elementDescriptions.isEmpty());
71
72 /* We start with stripping. */
73 m_stripWhitespace.push(t: true);
74}
75
76template<typename TokenLookupClass,
77 typename LookupKey>
78MaintainingReader<TokenLookupClass, LookupKey>::~MaintainingReader()
79{
80}
81
82template<typename TokenLookupClass,
83 typename LookupKey>
84QSourceLocation MaintainingReader<TokenLookupClass, LookupKey>::currentLocation() const
85{
86 return QSourceLocation(documentURI(),
87 lineNumber(),
88 columnNumber());
89}
90
91template<typename TokenLookupClass,
92 typename LookupKey>
93QXmlStreamReader::TokenType MaintainingReader<TokenLookupClass, LookupKey>::readNext()
94{
95 const TokenType retval = QXmlStreamReader::readNext();
96
97 switch(retval)
98 {
99 case StartElement:
100 {
101 m_currentElementName = TokenLookupClass::toToken(name());
102 m_currentAttributes = attributes();
103 m_hasHandledStandardAttributes = false;
104
105 if(!m_currentAttributes.hasAttribute(qualifiedName: QLatin1String("xml:space")))
106 m_stripWhitespace.push(t: m_stripWhitespace.top());
107 break;
108 }
109 case EndElement:
110 m_currentElementName = TokenLookupClass::toToken(name());
111 m_stripWhitespace.pop();
112 break;
113 default:
114 break;
115 }
116
117 return retval;
118}
119
120template<typename TokenLookupClass,
121 typename LookupKey>
122bool MaintainingReader<TokenLookupClass, LookupKey>::isWhitespace() const
123{
124 return QXmlStreamReader::isWhitespace()
125 || XPathHelper::isWhitespaceOnly(text());
126}
127
128
129template<typename TokenLookupClass,
130 typename LookupKey>
131void MaintainingReader<TokenLookupClass, LookupKey>::error(const QString &message,
132 const ReportContext::ErrorCode code) const
133{
134 m_context->error(message, code, currentLocation());
135}
136
137template<typename TokenLookupClass,
138 typename LookupKey>
139void MaintainingReader<TokenLookupClass, LookupKey>::warning(const QString &message) const
140{
141 m_context->warning(message, sourceLocation: currentLocation());
142}
143
144template<typename TokenLookupClass,
145 typename LookupKey>
146typename TokenLookupClass::NodeName MaintainingReader<TokenLookupClass, LookupKey>::currentElementName() const
147{
148 return m_currentElementName;
149}
150
151template<typename TokenLookupClass,
152 typename LookupKey>
153void MaintainingReader<TokenLookupClass, LookupKey>::validateElement(const LookupKey elementName) const
154{
155 Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
156
157 if(m_elementDescriptions.contains(elementName))
158 {
159 // QHash::value breaks in Metrowerks Compiler
160 const ElementDescription<TokenLookupClass, LookupKey> &desc = *m_elementDescriptions.find(elementName);
161 const int attCount = m_currentAttributes.count();
162
163 QSet<typename TokenLookupClass::NodeName> encounteredXSLTAtts;
164
165 for(int i = 0; i < attCount; ++i)
166 {
167 const QXmlStreamAttribute &attr = m_currentAttributes.at(i);
168 if(attr.namespaceUri().isEmpty())
169 {
170 const typename TokenLookupClass::NodeName attrName(TokenLookupClass::toToken(attr.name()));
171 encounteredXSLTAtts.insert(attrName);
172
173 if(!desc.requiredAttributes.contains(attrName) &&
174 !desc.optionalAttributes.contains(attrName) &&
175 !m_standardAttributes.contains(attrName) &&
176 !isAnyAttributeAllowed())
177 {
178 QString translationString;
179
180 QList<typename TokenLookupClass::NodeName> all(desc.requiredAttributes.values() + desc.optionalAttributes.values());
181 const int totalCount = all.count();
182 QStringList allowed;
183
184 for(int i = 0; i < totalCount; ++i)
185 allowed.append(QPatternist::formatKeyword(TokenLookupClass::toString(all.at(i))));
186
187 /* Note, we can't run toString() on attrName, because we're in this branch,
188 * the token lookup doesn't have the string(!).*/
189 const QString stringedName(attr.name().toString());
190
191 if(totalCount == 0)
192 {
193 translationString = QtXmlPatterns::tr(sourceText: "Attribute %1 cannot appear on the element %2. Only the standard attributes can appear.")
194 .arg(formatKeyword(keyword: stringedName),
195 formatKeyword(name()));
196 }
197 else if(totalCount == 1)
198 {
199 translationString = QtXmlPatterns::tr(sourceText: "Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes.")
200 .arg(formatKeyword(keyword: stringedName),
201 formatKeyword(name()),
202 allowed.first());
203 }
204 else if(totalCount == 2)
205 {
206 /* Note, allowed has already had formatKeyword() applied. */
207 translationString = QtXmlPatterns::tr(sourceText: "Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes.")
208 .arg(formatKeyword(keyword: stringedName),
209 formatKeyword(name()),
210 allowed.first(),
211 allowed.last());
212 }
213 else
214 {
215 /* Note, allowed has already had formatKeyword() applied. */
216 translationString = QtXmlPatterns::tr(sourceText: "Attribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes.")
217 .arg(formatKeyword(keyword: stringedName),
218 formatKeyword(name()),
219 allowed.join(sep: QLatin1String(", ")));
220 }
221
222 m_context->error(translationString,
223 ReportContext::XTSE0090,
224 currentLocation());
225 }
226 }
227 else if(attr.namespaceUri() == namespaceUri())
228 {
229 m_context->error(QtXmlPatterns::tr(sourceText: "XSL-T attributes on XSL-T elements must be in the null namespace, not in the XSL-T namespace which %1 is.")
230 .arg(a: formatKeyword(keyword: attr.name())),
231 ReportContext::XTSE0090,
232 currentLocation());
233 }
234 /* Else, attributes in other namespaces are allowed, continue. */
235 }
236
237 const QSet<typename TokenLookupClass::NodeName> requiredButMissing(QSet<typename TokenLookupClass::NodeName>(desc.requiredAttributes).subtract(encounteredXSLTAtts));
238
239 if(!requiredButMissing.isEmpty())
240 {
241 error(message: QtXmlPatterns::tr(sourceText: "The attribute %1 must appear on element %2.")
242 .arg(QPatternist::formatKeyword(TokenLookupClass::toString(*requiredButMissing.constBegin())),
243 formatKeyword(name())),
244 code: ReportContext::XTSE0010);
245 }
246 }
247 else
248 {
249 error(message: QtXmlPatterns::tr(sourceText: "The element with local name %1 does not exist in XSL-T.").arg(formatKeyword(name())),
250 code: ReportContext::XTSE0010);
251 }
252}
253
254template<typename TokenLookupClass,
255 typename LookupKey>
256bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &namespaceURI,
257 const QString &localName) const
258{
259 Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
260 return m_currentAttributes.hasAttribute(namespaceUri: namespaceURI, name: localName);
261}
262
263template<typename TokenLookupClass,
264 typename LookupKey>
265bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &localName) const
266{
267 return hasAttribute(QString(), localName);
268}
269
270template<typename TokenLookupClass,
271 typename LookupKey>
272QString MaintainingReader<TokenLookupClass, LookupKey>::readAttribute(const QString &localName,
273 const QString &namespaceURI) const
274{
275 Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
276
277 Q_ASSERT_X(m_currentAttributes.hasAttribute(namespaceURI, localName),
278 Q_FUNC_INFO,
279 "Validation must be done before this function is called.");
280
281 return m_currentAttributes.value(namespaceUri: namespaceURI, name: localName).toString();
282}
283
284

source code of qtxmlpatterns/src/xmlpatterns/parser/qmaintainingreader_tpl_p.h