~ubuntu-branches/ubuntu/raring/kbibtex/raring

« back to all changes in this revision

Viewing changes to src/libkbibtexio/fileimporterris.cpp

  • Committer: Package Import Robot
  • Author(s): Michael Hanke
  • Date: 2011-07-18 09:29:48 UTC
  • mfrom: (1.1.6) (2.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20110718092948-ksxjmg7kdfamolmg
Tags: 0.3-1
* First upstream release for KDE4 (Closes: #634255). A number of search
  engines are still missing, in comparison to the 0.2 series.
* Bumped Standards-Version to 3.9.2, no changes necessary.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
*   Copyright (C) 2004-2010 by Thomas Fischer                             *
 
3
*   fischer@unix-ag.uni-kl.de                                             *
 
4
*                                                                         *
 
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.                                   *
 
9
*                                                                         *
 
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.                          *
 
14
*                                                                         *
 
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>
 
21
#include <QRegExp>
 
22
#include <QCoreApplication>
 
23
#include <QStringList>
 
24
 
 
25
#include <KDebug>
 
26
 
 
27
#include <kbibtexnamespace.h>
 
28
#include "entry.h"
 
29
#include "value.h"
 
30
 
 
31
#include "fileimporterris.h"
 
32
 
 
33
#define appendValue(entry, fieldname, newvalue) { Value value = (entry)->value((fieldname)); value.append((newvalue)); (entry)->insert((fieldname), value); }
 
34
 
 
35
class FileImporterRIS::FileImporterRISPrivate
 
36
{
 
37
private:
 
38
    FileImporterRIS *p;
 
39
 
 
40
public:
 
41
    int referenceCounter;
 
42
    bool cancelFlag;
 
43
 
 
44
    typedef struct {
 
45
        QString key;
 
46
        QString value;
 
47
    }
 
48
    RISitem;
 
49
    typedef QLinkedList<RISitem> RISitemList;
 
50
 
 
51
    FileImporterRISPrivate(FileImporterRIS *parent)
 
52
            : p(parent), referenceCounter(0), cancelFlag(false) {
 
53
        // nothing
 
54
    }
 
55
 
 
56
    RISitemList readElement(QTextStream &textStream) {
 
57
        RISitemList result;
 
58
        QString line = textStream.readLine();
 
59
        while (!line.startsWith("TY  - ") && !textStream.atEnd())
 
60
            line = textStream.readLine();
 
61
        if (textStream.atEnd())
 
62
            return result;
 
63
 
 
64
        QString key, value;
 
65
        while (!line.startsWith("ER  -") && !textStream.atEnd()) {
 
66
            if (line.mid(2, 3) == "  -") {
 
67
                if (!value.isEmpty()) {
 
68
                    RISitem item;
 
69
                    item.key = key;
 
70
                    item.value = value;
 
71
                    result.append(item);
 
72
                }
 
73
 
 
74
                key = line.left(2);
 
75
                value = line.mid(6).trimmed();
 
76
            } else {
 
77
                line = line.trimmed();
 
78
                if (line.length() > 1) {
 
79
                    /// multi-line field are joined to one long line
 
80
                    value += ' ' + line;
 
81
                }
 
82
            }
 
83
 
 
84
            line = textStream.readLine();
 
85
        }
 
86
        if (!value.isEmpty()) {
 
87
            RISitem item;
 
88
            item.key = key;
 
89
            item.value = value;
 
90
            result.append(item);
 
91
        }
 
92
 
 
93
        return result;
 
94
    }
 
95
 
 
96
    Element *nextElement(QTextStream &textStream) {
 
97
        RISitemList list = readElement(textStream);
 
98
        if (list.empty())
 
99
            return NULL;
 
100
 
 
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;
 
105
 
 
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);
 
125
                if (person != NULL)
 
126
                    appendValue(entry, Entry::ftAuthor, person);
 
127
            } else if ((*it).key == "ED" || (*it).key == "A2") {
 
128
                Person *person = splitName((*it).value);
 
129
                if (person != NULL)
 
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") {
 
134
                date = (*it).value;
 
135
            } else if ((*it).key == "Y2") {
 
136
                if (date.isEmpty())
 
137
                    date = (*it).value;
 
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;
 
144
                QRegExp splitRegExp;
 
145
                if (text.contains(";"))
 
146
                    splitRegExp = QRegExp("\\s*[;\\n]\\s*");
 
147
                else if (text.contains(","))
 
148
                    splitRegExp = QRegExp("\\s*[,\\n]\\s*");
 
149
                else
 
150
                    splitRegExp = QRegExp("\\n");
 
151
                QStringList newKeywords = text.split(splitRegExp, QString::SkipEmptyParts);
 
152
                for (QStringList::Iterator it = newKeywords.begin(); it != newKeywords.end();
 
153
                        ++it)
 
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;
 
186
            } else {
 
187
                const QString fieldName = QString("RISfield_%1_%2").arg(fieldCounter++).arg((*it).key.left(2));
 
188
                appendValue(entry, fieldName, new PlainText((*it).value));
 
189
            }
 
190
        }
 
191
 
 
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);
 
197
        }
 
198
 
 
199
        if (!startPage.isEmpty() || !endPage.isEmpty()) {
 
200
            QString page;
 
201
            if (startPage.isEmpty())
 
202
                page = endPage;
 
203
            else if (endPage.isEmpty())
 
204
                page = startPage;
 
205
            else
 
206
                page = startPage + QChar(0x2013) + endPage;
 
207
 
 
208
            Value value;
 
209
            value.append(new PlainText(page));
 
210
            entry->insert(Entry::ftPages, value);
 
211
        }
 
212
 
 
213
        QStringList dateFragments = date.split("/", QString::SkipEmptyParts);
 
214
        if (dateFragments.count() > 0) {
 
215
            bool ok;
 
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);
 
221
            } else
 
222
                kDebug() << "invalid year: " << year;
 
223
        }
 
224
        if (dateFragments.count() > 1) {
 
225
            bool ok;
 
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);
 
231
            } else
 
232
                kDebug() << "invalid month: " << month;
 
233
        }
 
234
 
 
235
        return entry;
 
236
    }
 
237
 
 
238
};
 
239
 
 
240
FileImporterRIS::FileImporterRIS()
 
241
        : FileImporter(), d(new FileImporterRISPrivate(this))
 
242
{
 
243
// nothing
 
244
}
 
245
 
 
246
 
 
247
FileImporterRIS::~FileImporterRIS()
 
248
{
 
249
// nothing
 
250
}
 
251
 
 
252
File* FileImporterRIS::load(QIODevice *iodevice)
 
253
{
 
254
    d->cancelFlag = false;
 
255
    d->referenceCounter = 0;
 
256
    QTextStream textStream(iodevice);
 
257
 
 
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);
 
263
        if (element != NULL)
 
264
            result->append(element);
 
265
        QCoreApplication::instance()->processEvents();
 
266
    }
 
267
    emit progress(100, 100);
 
268
 
 
269
    if (d->cancelFlag) {
 
270
        delete result;
 
271
        result = NULL;
 
272
    }
 
273
 
 
274
    return result;
 
275
}
 
276
 
 
277
bool FileImporterRIS::guessCanDecode(const QString & text)
 
278
{
 
279
    return text.indexOf("TY  - ") >= 0;
 
280
}
 
281
 
 
282
void FileImporterRIS::cancel()
 
283
{
 
284
    d->cancelFlag = true;
 
285
}