Change copyrights from Nokia to Digia
[profile/ivi/qtxmlpatterns.git] / src / xmlpatterns / projection / qdocumentprojector.cpp
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 #include "qdocumentprojector_p.h"
43
44 QT_BEGIN_NAMESPACE
45
46 using namespace QPatternist;
47
48 DocumentProjector::DocumentProjector(const ProjectedExpression::Vector &paths,
49                                      QAbstractXmlReceiver *const receiver) : m_paths(paths)
50                                                                            , m_pathCount(paths.count())
51                                                                            , m_action(ProjectedExpression::Move)
52                                                                            , m_nodesInProcess(0)
53                                                                            , m_receiver(receiver)
54 {
55     Q_ASSERT_X(paths.count() > 0, Q_FUNC_INFO,
56                "Using DocumentProjector with no paths is an "
57                "overhead and has also undefined behavior.");
58     Q_ASSERT(m_receiver);
59 }
60
61 void DocumentProjector::startElement(const QXmlName name)
62 {
63     Q_UNUSED(name);
64
65     switch(m_action)
66     {
67         case ProjectedExpression::KeepSubtree:
68         {
69             m_receiver->startElement(name);
70             /* Fallthrough. */
71         }
72         case ProjectedExpression::Skip:
73         {
74             ++m_nodesInProcess;
75             return;
76         }
77         default:
78         {
79             Q_ASSERT_X(m_action == ProjectedExpression::Move, Q_FUNC_INFO,
80                        "We're not supposed to receive Keep here, because "
81                        "endElement() should always end that state.");
82
83             for(int i = 0; i < m_pathCount; ++i)
84             {
85                 m_action = m_paths.at(i)->actionForElement(name, m_paths[i]);
86
87                 switch(m_action)
88                 {
89                     case ProjectedExpression::Keep:
90                     {
91                         m_action = ProjectedExpression::Keep;
92                         continue;
93                     }
94                     case ProjectedExpression::KeepSubtree:
95                     {
96                         /* Ok, at least one path wanted this node. Pass it on,
97                          * and exit. */
98                         m_receiver->startElement(name);
99                         ++m_nodesInProcess;
100                         return;
101                     }
102                     case ProjectedExpression::Skip:
103                     {
104                         /* This particular path doesn't need it, but
105                          * some other path might, so continue looping. */
106                         continue;
107                     }
108                     case ProjectedExpression::Move:
109                         Q_ASSERT_X(false, Q_FUNC_INFO, "The action functions can never return Move.");
110                 }
111             }
112
113             ++m_nodesInProcess;
114
115             if(m_action == ProjectedExpression::Keep)
116                 m_receiver->startElement(name);
117             else
118             {
119                 Q_ASSERT(m_action == ProjectedExpression::Skip);
120             }
121         }
122     }
123 }
124
125 void DocumentProjector::endElement()
126 {
127     if(m_action == ProjectedExpression::Keep)
128     {
129         Q_ASSERT(m_nodesInProcess == 1);
130
131         m_receiver->endElement();
132
133         /* We have now kept the single node, and now wants to skip
134          * all its children. */
135         m_action = ProjectedExpression::Skip;
136         m_nodesInProcess = 0;
137     }
138     else if(m_action == ProjectedExpression::KeepSubtree)
139     {
140         m_receiver->endElement();
141         --m_nodesInProcess;
142
143         if(m_nodesInProcess == 0)
144         {
145             /* We have now skipped all the children, let's do
146              * a new path analysis. */
147             m_action = ProjectedExpression::Move;
148         }
149     }
150     else
151     {
152         Q_ASSERT_X(m_action == ProjectedExpression::Skip, Q_FUNC_INFO,
153                    "We're not supposed to be in a Move action here.");
154         /* We skip calling m_receiver's endElement() here since we're
155          * skipping. */
156         Q_ASSERT(m_nodesInProcess > 0);
157         --m_nodesInProcess;
158
159         if(m_nodesInProcess == 0)
160         {
161             /* Ok, we've skipped them all, let's do something
162              * new -- let's Move on to the next path! */
163             m_action = ProjectedExpression::Move;
164         }
165     }
166 }
167
168 void DocumentProjector::attribute(const QXmlName name,
169                                   const QString &value)
170 {
171     Q_UNUSED(name);
172     Q_UNUSED(value);
173 }
174
175 void DocumentProjector::namespaceBinding(const QXmlName nb)
176 {
177     Q_UNUSED(nb);
178 }
179
180 void DocumentProjector::comment(const QString &value)
181 {
182     Q_ASSERT_X(!value.contains(QLatin1String("--")), Q_FUNC_INFO,
183                "Invalid input; it's the caller's responsibility to ensure the input is correct.");
184     Q_UNUSED(value);
185 }
186
187 void DocumentProjector::characters(const QString &value)
188 {
189     Q_UNUSED(value);
190 }
191
192 void DocumentProjector::processingInstruction(const QXmlName name,
193                                               const QString &value)
194 {
195     Q_ASSERT_X(!value.contains(QLatin1String("?>")), Q_FUNC_INFO,
196                "Invalid input; it's the caller's responsibility to ensure the input is correct.");
197     Q_UNUSED(name);
198     Q_UNUSED(value);
199 }
200
201 void DocumentProjector::item(const Item &outputItem)
202 {
203     Q_UNUSED(outputItem);
204 }
205
206 void DocumentProjector::startDocument()
207 {
208 }
209
210 void DocumentProjector::endDocument()
211 {
212 }
213
214 QT_END_NAMESPACE