1 /***************************************************************************
2 Copyright (C) 2012 Robby Stephenson <robby@periapsis.org>
3 ***************************************************************************/
4
5 /***************************************************************************
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License as *
9 * published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) version 3 or any later version *
11 * accepted by the membership of KDE e.V. (or its successor approved *
12 * by the membership of KDE e.V.), which shall act as a proxy *
13 * defined in Section 14 of version 3 of the license. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
22 * *
23 ***************************************************************************/
24
25 #include "springerfetcher.h"
26 #include "../entry.h"
27 #include "../utils/isbnvalidator.h"
28 #include "../tellico_debug.h"
29
30 #include <KLocalizedString>
31 #include <KConfigGroup>
32 #include <QUrl>
33
34 #include <QLabel>
35 #include <QVBoxLayout>
36 #include <QDomDocument>
37 #include <QUrlQuery>
38
39 namespace {
40 static const char* SPRINGER_BASE_URL = "http://api.springer.com/metadata/pam";
41 static const char* SPRINGER_API_KEY = "m2z42cbw68qhhjcrm8tbj2hc";
42 static const int SPRINGER_QUERY_COUNT = 10;
43 }
44
45 using namespace Tellico;
46 using Tellico::Fetch::SpringerFetcher;
47
SpringerFetcher(QObject * parent_)48 SpringerFetcher::SpringerFetcher(QObject* parent_)
49 : XMLFetcher(parent_), m_start(0), m_total(-1) {
50 setLimit(SPRINGER_QUERY_COUNT);
51 setXSLTFilename(QStringLiteral("springer2tellico.xsl"));
52 }
53
~SpringerFetcher()54 SpringerFetcher::~SpringerFetcher() {
55 }
56
source() const57 QString SpringerFetcher::source() const {
58 return m_name.isEmpty() ? defaultName() : m_name;
59 }
60
attribution() const61 QString SpringerFetcher::attribution() const {
62 return i18n("This data is licensed under <a href=""%1"">specific terms</a>.",
63 QLatin1String("https://dev.springernature.com/"));
64 }
65
canSearch(Fetch::FetchKey k) const66 bool SpringerFetcher::canSearch(Fetch::FetchKey k) const {
67 return k == Title || k == Person || k == Keyword || k == ISBN || k == DOI || k == Raw;
68 }
69
canFetch(int type) const70 bool SpringerFetcher::canFetch(int type) const {
71 return type == Data::Collection::Bibtex;
72 }
73
readConfigHook(const KConfigGroup &)74 void SpringerFetcher::readConfigHook(const KConfigGroup&) {
75 }
76
resetSearch()77 void SpringerFetcher::resetSearch() {
78 m_start = 0;
79 m_total = -1;
80 }
81
searchUrl()82 QUrl SpringerFetcher::searchUrl() {
83 QUrl u(QString::fromLatin1(SPRINGER_BASE_URL));
84 QUrlQuery q;
85 q.addQueryItem(QStringLiteral("api_key"), QLatin1String(SPRINGER_API_KEY));
86 q.addQueryItem(QStringLiteral("s"), QString::number(m_start + 1));
87 q.addQueryItem(QStringLiteral("p"), QString::number(SPRINGER_QUERY_COUNT));
88
89 switch(request().key()) {
90 case Title:
91 q.addQueryItem(QStringLiteral("q"), QStringLiteral("title:\"%1\" OR book:\"%1\"").arg(request().value()));
92 break;
93
94 case Person:
95 q.addQueryItem(QStringLiteral("q"), QStringLiteral("name:%1").arg(request().value()));
96 break;
97
98 case Keyword:
99 q.addQueryItem(QStringLiteral("q"), QStringLiteral("\"%1\"").arg(request().value()));
100 break;
101
102 case ISBN:
103 {
104 // only grab first value
105 QString v = request().value().section(QLatin1Char(';'), 0);
106 v = ISBNValidator::isbn13(v);
107 q.addQueryItem(QStringLiteral("q"), QStringLiteral("isbn:%1").arg(v));
108 }
109 break;
110
111 case DOI:
112 q.addQueryItem(QStringLiteral("q"), QStringLiteral("doi:%1").arg(request().value()));
113 break;
114
115 case Raw:
116 q.addQueryItem(QStringLiteral("q"), request().value());
117 break;
118
119 default:
120 return QUrl();
121 }
122 u.setQuery(q);
123
124 // myDebug() << "url:" << u.url();
125 return u;
126 }
127
parseData(QByteArray & data_)128 void SpringerFetcher::parseData(QByteArray& data_) {
129 QDomDocument dom;
130 if(!dom.setContent(data_, false)) {
131 myWarning() << "server did not return valid XML.";
132 return;
133 }
134 // total is /response/result/total
135 QDomNode n = dom.documentElement().namedItem(QStringLiteral("result"))
136 .namedItem(QStringLiteral("total"));
137 QDomElement e = n.toElement();
138 if(!e.isNull()) {
139 m_total = e.text().toInt();
140 // myDebug() << "total = " << m_total;
141 }
142 }
143
checkMoreResults(int count_)144 void SpringerFetcher::checkMoreResults(int count_) {
145 m_start = count_;
146 m_hasMoreResults = m_start < m_total;
147 }
148
updateRequest(Data::EntryPtr entry_)149 Tellico::Fetch::FetchRequest SpringerFetcher::updateRequest(Data::EntryPtr entry_) {
150 const QString doi = entry_->field(QStringLiteral("doi"));
151 if(!doi.isEmpty()) {
152 return FetchRequest(Fetch::DOI, doi);
153 }
154
155 const QString isbn = entry_->field(QStringLiteral("isbn"));
156 if(!isbn.isEmpty()) {
157 return FetchRequest(Fetch::ISBN, isbn);
158 }
159
160 const QString title = entry_->field(QStringLiteral("title"));
161 if(!title.isEmpty()) {
162 return FetchRequest(Fetch::Title, title);
163 }
164
165 return FetchRequest();
166 }
167
configWidget(QWidget * parent_) const168 Tellico::Fetch::ConfigWidget* SpringerFetcher::configWidget(QWidget* parent_) const {
169 return new SpringerFetcher::ConfigWidget(parent_, this);
170 }
171
defaultName()172 QString SpringerFetcher::defaultName() {
173 return QStringLiteral("SpringerLink");
174 }
175
defaultIcon()176 QString SpringerFetcher::defaultIcon() {
177 return favIcon("https://link.springer.com/static/sites/link/images/favicon-32x32.png");
178 }
179
ConfigWidget(QWidget * parent_,const SpringerFetcher * fetcher_)180 SpringerFetcher::ConfigWidget::ConfigWidget(QWidget* parent_, const SpringerFetcher* fetcher_)
181 : Fetch::ConfigWidget(parent_) {
182 QVBoxLayout* l = new QVBoxLayout(optionsWidget());
183 l->addWidget(new QLabel(i18n("This source has no options."), optionsWidget()));
184 l->addStretch();
185
186 // now add additional fields widget
187 addFieldsWidget(SpringerFetcher::allOptionalFields(), fetcher_ ? fetcher_->optionalFields() : QStringList());
188 }
189
saveConfigHook(KConfigGroup &)190 void SpringerFetcher::ConfigWidget::saveConfigHook(KConfigGroup&) {
191 }
192
preferredName() const193 QString SpringerFetcher::ConfigWidget::preferredName() const {
194 return SpringerFetcher::defaultName();
195 }
196