1/*
2 * This file is part of the syndication library
3 *
4 * Copyright (C) 2005 Frank Osterfeld <osterfeld@kde.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifndef SYNDICATION_PARSERCOLLECTIONIMPL_H
24#define SYNDICATION_PARSERCOLLECTIONIMPL_H
25
26#include <syndication/specificdocument.h>
27#include <syndication/abstractparser.h>
28#include <syndication/documentsource.h>
29#include <syndication/parsercollection.h>
30#include <syndication/feed.h>
31#include <syndication/global.h>
32#include <syndication/mapper.h>
33
34#include <QtXml/QDomDocument>
35#include <QtCore/QHash>
36#include <QtCore/QString>
37
38namespace Syndication {
39
40//@cond PRIVATE
41/** @internal
42 */
43// default implementation of ParserCollection. This is separated
44// from the interface to move the implementation out of the public API
45// (template classes require implementations to be in the header)
46
47template <class T>
48class SYNDICATION_EXPORT ParserCollectionImpl : public ParserCollection<T>
49{
50 public:
51
52 ParserCollectionImpl();
53
54 virtual ~ParserCollectionImpl();
55
56 boost::shared_ptr<T> parse(const DocumentSource& source,
57 const QString& formatHint=QString());
58
59
60 bool registerParser(AbstractParser* parser, Mapper<T>* mapper);
61
62 void changeMapper(const QString& format, Mapper<T>* mapper);
63
64 ErrorCode lastError() const;
65
66 private:
67
68 ParserCollectionImpl(const ParserCollectionImpl&);
69 ParserCollectionImpl& operator=(const ParserCollectionImpl&);
70 QHash<QString, AbstractParser*> m_parsers;
71 QHash<QString, Mapper<T>*> m_mappers;
72 QList<AbstractParser*> m_parserList;
73
74 ErrorCode m_lastError;
75};
76
77//@endcond
78
79//template <class T>
80//class ParserCollectionImpl<T>::ParserCollectionImplPrivate
81
82template <class T>
83ParserCollectionImpl<T>::ParserCollectionImpl()
84{
85}
86
87template <class T>
88ParserCollectionImpl<T>::~ParserCollectionImpl()
89{
90 QList<AbstractParser*> list = m_parsers.values();
91 QList<AbstractParser*>::ConstIterator it = list.constBegin();
92 QList<AbstractParser*>::ConstIterator end = list.constEnd();
93
94 for ( ; it != end; ++it)
95 delete *it;
96
97 QList<QString> m = m_mappers.keys();
98 QList<QString>::ConstIterator itm = m.constBegin();
99 QList<QString>::ConstIterator endm = m.constEnd();
100
101 for ( ; itm != endm; ++itm)
102 delete m_mappers[*itm];
103
104}
105
106template <class T>
107bool ParserCollectionImpl<T>::registerParser(AbstractParser* parser, Mapper<T>* mapper)
108{
109 if (m_parsers.contains(parser->format()))
110 return false;
111
112 m_parserList.append(parser);
113 m_parsers.insert(parser->format(), parser);
114 m_mappers.insert(parser->format(), mapper);
115 return true;
116}
117template <class T>
118void ParserCollectionImpl<T>::changeMapper(const QString& format, Mapper<T>* mapper)
119{
120 m_mappers[format] = mapper;
121}
122
123template <class T>
124boost::shared_ptr<T> ParserCollectionImpl<T>::parse(const DocumentSource& source, const QString& formatHint)
125{
126 m_lastError = Syndication::Success;
127
128 if (!formatHint.isNull() && m_parsers.contains(formatHint))
129 {
130 if (m_parsers[formatHint]->accept(source))
131 {
132 SpecificDocumentPtr doc = m_parsers[formatHint]->parse(source);
133 if (!doc->isValid())
134 {
135 m_lastError = InvalidFormat;
136 return FeedPtr();
137 }
138
139 return m_mappers[formatHint]->map(doc);
140 }
141 }
142
143 Q_FOREACH (AbstractParser* i, m_parserList)
144 {
145 if (i->accept(source))
146 {
147 SpecificDocumentPtr doc = i->parse(source);
148 if (!doc->isValid())
149 {
150 m_lastError = InvalidFormat;
151 return FeedPtr();
152 }
153
154 return m_mappers[i->format()]->map(doc);
155 }
156 }
157 if (source.asDomDocument().isNull())
158 m_lastError = InvalidXml;
159 else
160 m_lastError = XmlNotAccepted;
161
162 return FeedPtr();
163}
164
165template <class T>
166Syndication::ErrorCode ParserCollectionImpl<T>::lastError() const
167{
168 return m_lastError;
169}
170
171template <class T>
172ParserCollectionImpl<T>::ParserCollectionImpl(const ParserCollectionImpl&)
173{
174}
175
176template <class T>
177ParserCollectionImpl<T>& ParserCollectionImpl<T>::operator=(const ParserCollectionImpl&)
178{
179 return *this;
180}
181
182} // namespace Syndication
183
184#endif // SYNDICATION_PARSERCOLLECTIONIMPL_H
185