Update licenseheader text in source files for qtxmlpatterns Qt module
[profile/ivi/qtxmlpatterns.git] / src / xmlpatterns / projection / qdocumentprojector.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 #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