File indexing completed on 2024-05-19 05:05:47

0001 /***************************************************************************
0002  *   SPDX-License-Identifier: GPL-2.0-or-later
0003  *                                                                         *
0004  *   SPDX-FileCopyrightText: 2004-2018 Thomas Fischer <fischer@unix-ag.uni-kl.de>
0005  *                                                                         *
0006  *   This program is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  *   This program is distributed in the hope that it will be useful,       *
0012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0014  *   GNU General Public License for more details.                          *
0015  *                                                                         *
0016  *   You should have received a copy of the GNU General Public License     *
0017  *   along with this program; if not, see <https://www.gnu.org/licenses/>. *
0018  ***************************************************************************/
0019 
0020 #include "journalabbreviations.h"
0021 
0022 #include <QHash>
0023 #include <QFile>
0024 #include <QTextStream>
0025 #include <QRegularExpression>
0026 #include <QStandardPaths>
0027 
0028 #include "logging_processing.h"
0029 
0030 class JournalAbbreviations::Private
0031 {
0032 private:
0033     const QString journalFilename;
0034 
0035     QHash<QString, QString> leftToRightMap, rightToLeftMap;
0036 
0037 public:
0038     Private(JournalAbbreviations *parent)
0039             : journalFilename(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kbibtex/jabref_journalabbrevlist.txt")))
0040     {
0041         Q_UNUSED(parent)
0042     }
0043 
0044     bool loadMapping() {
0045         leftToRightMap.clear();
0046         rightToLeftMap.clear();
0047 
0048         QFile journalFile(journalFilename);
0049         if (journalFile.open(QFile::ReadOnly)) {
0050             static const QRegularExpression splitRegExp(QStringLiteral("\\s*[=;]\\s*"));
0051 
0052             QTextStream ts(&journalFile);
0053             // https://forum.qt.io/topic/135724/qt-6-replacement-for-qtextcodec
0054 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
0055             ts.setCodec("utf8");
0056 #else
0057             ts.setEncoding(QStringConverter::Utf8);
0058 #endif
0059 
0060             QString line;
0061             while (!(line = ts.readLine().trimmed()).isNull()) {
0062                 /// Skip empty lines or comments
0063                 if (line.isEmpty() || line.startsWith(QLatin1Char('#'))) continue;
0064                 const QStringList columns = line.split(splitRegExp);
0065                 /// Skip lines that do not have at least two columns
0066                 if (columns.count() < 2) continue;
0067                 /// At this point, a given line like
0068                 ///    Accounts of Chemical Research=Acc. Chem. Res.;ACHRE4;M
0069                 /// may have been split into the columns of
0070                 ///    Accounts of Chemical Research
0071                 ///    Acc. Chem. Res.
0072                 ///    ACHRE4
0073                 ///    M
0074                 /// The last two columns are optional and are not processed here.
0075                 /// The first column is the journal's full name, the second column
0076                 /// is its abbreviation.
0077                 /// QHash leftToRightMap maps from full name to abbreviation,
0078                 /// QHash rightToLeftMap maps from abbreviation to full name.
0079 
0080                 const QString alreadyInLeftToRightMap = leftToRightMap[columns[0]];
0081                 if (!alreadyInLeftToRightMap.isEmpty()) {
0082                     if (alreadyInLeftToRightMap.length() > columns[1].length())
0083                         /// If there is already an existing mapping from full name to
0084                         /// abbreviation, replace it if the newly found abbreviation
0085                         /// is longer.
0086                         leftToRightMap.insert(columns[0], columns[1]);
0087                 } else
0088                     /// Previously unknown journal full name, so add it to mapping.
0089                     leftToRightMap.insert(columns[0], columns[1]);
0090                 /// Always add/replace mapping from abbreviation to full name.
0091                 rightToLeftMap.insert(columns[1], columns[0]);
0092             }
0093 
0094             journalFile.close();
0095 
0096             /// Success means at least one mapping has been recorded.
0097             return !leftToRightMap.isEmpty();
0098         } else {
0099             qCWarning(LOG_KBIBTEX_PROCESSING) << "Cannot open journal abbreviation list file at" << journalFilename;
0100             return false;
0101         }
0102     }
0103 
0104     QString leftToRight(const QString &left) {
0105         if (leftToRightMap.isEmpty())
0106             loadMapping(); ///< lazy loading of mapping, i.e. only when data gets requested the first time
0107         return leftToRightMap.value(left, left);
0108     }
0109 
0110     QString rightToLeft(const QString &right) {
0111         if (rightToLeftMap.isEmpty())
0112             loadMapping(); ///< lazy loading of mapping, i.e. only when data gets requested the first time
0113         return rightToLeftMap.value(right, right);
0114     }
0115 };
0116 
0117 
0118 JournalAbbreviations::JournalAbbreviations()
0119         : d(new JournalAbbreviations::Private(this))
0120 {
0121     /// nothing
0122 }
0123 
0124 JournalAbbreviations::~JournalAbbreviations()
0125 {
0126     delete d;
0127 }
0128 
0129 const JournalAbbreviations &JournalAbbreviations::instance() {
0130     static JournalAbbreviations singleton;
0131     return singleton;
0132 }
0133 
0134 QString JournalAbbreviations::toShortName(const QString &longName) const {
0135     return d->leftToRight(longName);
0136 }
0137 
0138 QString JournalAbbreviations::toLongName(const QString &shortName) const {
0139     return d->rightToLeft(shortName);
0140 }