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