1
/***************************************************************************
2
* Copyright (C) 2004-2010 by Thomas Fischer *
3
* fischer@unix-ag.uni-kl.de *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19
***************************************************************************/
20
#include <QTextStream>
22
#include <QCoreApplication>
23
#include <QStringList>
27
#include <kbibtexnamespace.h>
31
#include "fileimporterris.h"
33
#define appendValue(entry, fieldname, newvalue) { Value value = (entry)->value((fieldname)); value.append((newvalue)); (entry)->insert((fieldname), value); }
35
class FileImporterRIS::FileImporterRISPrivate
49
typedef QLinkedList<RISitem> RISitemList;
51
FileImporterRISPrivate(FileImporterRIS *parent)
52
: p(parent), referenceCounter(0), cancelFlag(false) {
56
RISitemList readElement(QTextStream &textStream) {
58
QString line = textStream.readLine();
59
while (!line.startsWith("TY - ") && !textStream.atEnd())
60
line = textStream.readLine();
61
if (textStream.atEnd())
65
while (!line.startsWith("ER -") && !textStream.atEnd()) {
66
if (line.mid(2, 3) == " -") {
67
if (!value.isEmpty()) {
75
value = line.mid(6).trimmed();
77
line = line.trimmed();
78
if (line.length() > 1) {
79
/// multi-line field are joined to one long line
84
line = textStream.readLine();
86
if (!value.isEmpty()) {
96
Element *nextElement(QTextStream &textStream) {
97
RISitemList list = readElement(textStream);
101
QString entryType = Entry::etMisc;
102
Entry *entry = new Entry(entryType, QString("RIS_%1").arg(referenceCounter++));
103
QString journalName, startPage, endPage, date;
104
int fieldCounter = 0;
106
for (RISitemList::iterator it = list.begin(); it != list.end(); ++it) {
107
if ((*it).key == "TY") {
108
if ((*it).value.startsWith("BOOK") || (*it).value.startsWith("SER"))
109
entryType = Entry::etBook;
110
else if ((*it).value.startsWith("CHAP"))
111
entryType = Entry::etInBook;
112
else if ((*it).value.startsWith("CONF"))
113
entryType = Entry::etInProceedings;
114
else if ((*it).value.startsWith("JFULL") || (*it).value.startsWith("JOUR") || (*it).value.startsWith("MGZN"))
115
entryType = Entry::etArticle;
116
else if ((*it).value.startsWith("RPRT"))
117
entryType = Entry::etTechReport;
118
else if ((*it).value.startsWith("THES"))
119
entryType = Entry::etPhDThesis;
120
else if ((*it).value.startsWith("UNPB"))
121
entryType = Entry::etUnpublished;
122
entry->setType(entryType);
123
} else if ((*it).key == "AU" || (*it).key == "A1") {
124
Person *person = splitName((*it).value);
126
appendValue(entry, Entry::ftAuthor, person);
127
} else if ((*it).key == "ED" || (*it).key == "A2") {
128
Person *person = splitName((*it).value);
130
appendValue(entry, Entry::ftEditor, person);
131
} else if ((*it).key == "ID") {
132
entry->setId((*it).value);
133
} else if ((*it).key == "Y1" || (*it).key == "PY") {
135
} else if ((*it).key == "Y2") {
138
} else if ((*it).key == "AB" || (*it).key == "N2") {
139
appendValue(entry, Entry::ftAbstract, new PlainText((*it).value));
140
} else if ((*it).key == "N1") {
141
appendValue(entry, Entry::ftNote, new PlainText((*it).value));
142
} else if ((*it).key == "KW") {
143
QString text = (*it).value;
145
if (text.contains(";"))
146
splitRegExp = QRegExp("\\s*[;\\n]\\s*");
147
else if (text.contains(","))
148
splitRegExp = QRegExp("\\s*[,\\n]\\s*");
150
splitRegExp = QRegExp("\\n");
151
QStringList newKeywords = text.split(splitRegExp, QString::SkipEmptyParts);
152
for (QStringList::Iterator it = newKeywords.begin(); it != newKeywords.end();
154
appendValue(entry, Entry::ftKeywords, new Keyword(*it));
155
} else if ((*it).key == "TI" || (*it).key == "T1") {
156
appendValue(entry, Entry::ftTitle, new PlainText((*it).value));
157
} else if ((*it).key == "T3") {
158
appendValue(entry, Entry::ftSeries, new PlainText((*it).value));
159
} else if ((*it).key == "JO" || (*it).key == "J1" || (*it).key == "J2") {
160
if (journalName.isEmpty())
161
journalName = (*it).value;
162
} else if ((*it).key == "JF" || (*it).key == "JA") {
163
journalName = (*it).value;
164
} else if ((*it).key == "VL") {
165
appendValue(entry, Entry::ftVolume, new PlainText((*it).value));
166
} else if ((*it).key == "CP") {
167
appendValue(entry, Entry::ftChapter, new PlainText((*it).value));
168
} else if ((*it).key == "IS") {
169
appendValue(entry, Entry::ftNumber, new PlainText((*it).value));
170
} else if ((*it).key == "PB") {
171
appendValue(entry, Entry::ftPublisher, new PlainText((*it).value));
172
} else if ((*it).key == "SN") {
173
const QString fieldName = entryType == Entry::etBook || entryType == Entry::etInBook ? Entry::ftISBN : Entry::ftISSN;
174
appendValue(entry, fieldName, new PlainText((*it).value));
175
} else if ((*it).key == "CY") {
176
appendValue(entry, Entry::ftLocation, new PlainText((*it).value));
177
} else if ((*it).key == "AD") {
178
appendValue(entry, Entry::ftAddress, new PlainText((*it).value));
179
} else if ((*it).key == "L1" || (*it).key == "L2" || (*it).key == "L3" || (*it).key == "UR") {
180
const QString fieldName = KBibTeX::doiRegExp.indexIn((*it).value) >= 0 ? Entry::ftDOI : Entry::ftUrl;
181
appendValue(entry, fieldName, new PlainText((*it).value));
182
} else if ((*it).key == "SP") {
183
startPage = (*it).value;
184
} else if ((*it).key == "EP") {
185
endPage = (*it).value;
187
const QString fieldName = QString("RISfield_%1_%2").arg(fieldCounter++).arg((*it).key.left(2));
188
appendValue(entry, fieldName, new PlainText((*it).value));
192
if (!journalName.isEmpty()) {
193
const QString fieldName = entryType == Entry::etInBook || entryType == Entry::etInProceedings ? Entry::ftBookTitle : Entry::ftJournal;
194
Value value = entry->value(fieldName);
195
value.append(new PlainText(journalName));
196
entry->insert(fieldName, value);
199
if (!startPage.isEmpty() || !endPage.isEmpty()) {
201
if (startPage.isEmpty())
203
else if (endPage.isEmpty())
206
page = startPage + QChar(0x2013) + endPage;
209
value.append(new PlainText(page));
210
entry->insert(Entry::ftPages, value);
213
QStringList dateFragments = date.split("/", QString::SkipEmptyParts);
214
if (dateFragments.count() > 0) {
216
int year = dateFragments[0].toInt(&ok);
217
if (ok && year > 1000 && year < 3000) {
218
Value value = entry->value(Entry::ftYear);
219
value.append(new PlainText(QString::number(year)));
220
entry->insert(Entry::ftYear, value);
222
kDebug() << "invalid year: " << year;
224
if (dateFragments.count() > 1) {
226
int month = dateFragments[1].toInt(&ok);
227
if (ok && month > 0 && month < 13) {
228
Value value = entry->value(Entry::ftMonth);
229
value.append(new PlainText(KBibTeX::MonthsTriple[month-1]));
230
entry->insert(Entry::ftMonth, value);
232
kDebug() << "invalid month: " << month;
240
FileImporterRIS::FileImporterRIS()
241
: FileImporter(), d(new FileImporterRISPrivate(this))
247
FileImporterRIS::~FileImporterRIS()
252
File* FileImporterRIS::load(QIODevice *iodevice)
254
d->cancelFlag = false;
255
d->referenceCounter = 0;
256
QTextStream textStream(iodevice);
258
File *result = new File();
259
while (!d->cancelFlag && !textStream.atEnd()) {
260
emit progress(textStream.pos(), iodevice->size());
261
QCoreApplication::instance()->processEvents();
262
Element * element = d->nextElement(textStream);
264
result->append(element);
265
QCoreApplication::instance()->processEvents();
267
emit progress(100, 100);
277
bool FileImporterRIS::guessCanDecode(const QString & text)
279
return text.indexOf("TY - ") >= 0;
282
void FileImporterRIS::cancel()
284
d->cancelFlag = true;