"Fossies" - the Fresh Open Source Software Archive

Member "cb2bib-2.0.1/src/c2b/crJson.cpp" (12 Feb 2021, 9012 Bytes) of package /linux/privat/cb2bib-2.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "crJson.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.0.0_vs_2.0.1.

    1 /***************************************************************************
    2  *   Copyright (C) 2004-2021 by Pere Constans
    3  *   constans@molspaces.com
    4  *   cb2Bib version 2.0.1. Licensed under the GNU GPL version 3.
    5  *   See the LICENSE file that comes with this distribution.
    6  ***************************************************************************/
    7 #include "crJson.h"
    8 
    9 #include "cb2bib_utilities.h"
   10 
   11 #include <QJsonArray>
   12 #include <QJsonDocument>
   13 #include <QJsonObject>
   14 
   15 #include <cmath>
   16 
   17 
   18 crJson::crJson(const QString& json)
   19 {
   20     _reference.clearReference();
   21     readReference(json);
   22 }
   23 
   24 
   25 void crJson::readReference(const QString& json)
   26 {
   27     _has_error = true;
   28     _error_string.clear();
   29 
   30     QJsonParseError jerr;
   31     QJsonDocument jdoc(QJsonDocument::fromJson(json.toUtf8(), &jerr));
   32     if (jdoc.isNull() || jdoc.isEmpty())
   33     {
   34         _error_string =
   35             QObject::tr("Invalid data%1").arg(jerr.errorString().isEmpty() ? QString() : ": " + jerr.errorString());
   36         return;
   37     }
   38     QJsonObject jobj(jdoc.object().value("message").toObject());
   39     if (jobj.isEmpty())
   40     {
   41         _error_string = QObject::tr("Invalid reference data");
   42         return;
   43     }
   44 
   45 #ifdef C2B_DEBUG
   46     for (QJsonObject::const_iterator i = jobj.constBegin(); i != jobj.constEnd(); ++i)
   47         qDebug() << "[crjson] " << i.key() << i.value();
   48 #endif
   49 
   50     if (jobj.value("DOI").isUndefined())
   51     {
   52         _error_string = QObject::tr("Invalid reference data: no DOI parsed");
   53         return;
   54     }
   55     _reference["doi"] = jobj.value("DOI").toString();
   56 
   57     if (!jobj.value("published-print").isUndefined())
   58     {
   59         const QJsonValue jyear(
   60             jobj.value("published-print").toObject().value("date-parts").toArray().first().toArray().first());
   61         if (!jyear.isUndefined())
   62             _reference["year"] = QString::number(jyear.toDouble());
   63     }
   64     else if (!jobj.value("published-online").isUndefined())
   65     {
   66         // For articles no longer published in print
   67         const QJsonValue jyear(
   68             jobj.value("published-online").toObject().value("date-parts").toArray().first().toArray().first());
   69         if (!jyear.isUndefined())
   70             _reference["year"] = QString::number(jyear.toDouble());
   71     }
   72 
   73     _reference["volume"] = jobj.value("volume").toString();
   74     _reference["number"] = jobj.value("issue").toString();
   75     _reference["pages"] = jobj.value("page").toString();
   76 
   77     QStringList authors;
   78     const QJsonArray jauthors(jobj.value("author").toArray());
   79     for (QJsonArray::const_iterator i = jauthors.constBegin(); i != jauthors.constEnd(); ++i)
   80     {
   81         const QJsonObject ja((*i).toObject());
   82         authors.append(ja.value("given").toString() + ' ' + ja.value("family").toString());
   83     }
   84     _reference["author"] = authors.join(", ");
   85 
   86     QStringList editors;
   87     const QJsonArray jeditors(jobj.value("editor").toArray());
   88     for (QJsonArray::const_iterator i = jeditors.constBegin(); i != jeditors.constEnd(); ++i)
   89     {
   90         const QJsonObject je((*i).toObject());
   91         editors.append(je.value("given").toString() + ' ' + je.value("family").toString());
   92     }
   93     _reference["editor"] = editors.join(", ");
   94 
   95     QStringList titles;
   96     const QJsonArray jtitles(jobj.value("title").toArray());
   97     for (QJsonArray::const_iterator i = jtitles.constBegin(); i != jtitles.constEnd(); ++i)
   98         titles.append((*i).toString());
   99     _normalize_jtitles(&titles);
  100 
  101     QStringList subtitles;
  102     const QJsonArray jsubtitles(jobj.value("subtitle").toArray());
  103     for (QJsonArray::const_iterator i = jsubtitles.constBegin(); i != jsubtitles.constEnd(); ++i)
  104         subtitles.append((*i).toString());
  105     _normalize_jtitles(&subtitles);
  106 
  107     QStringList containertitles;
  108     const QJsonArray jcontainertitles(jobj.value("container-title").toArray());
  109     for (QJsonArray::const_iterator i = jcontainertitles.constBegin(); i != jcontainertitles.constEnd(); ++i)
  110         containertitles.append((*i).toString());
  111     _normalize_jtitles(&containertitles);
  112 
  113     const QString jisbn(jobj.value("ISBN").toArray().first().toString());
  114     const QString jpublisher(jobj.value("publisher").toString());
  115     const QString jabstract(jobj.value("abstract").toString());
  116     _reference["abstract"] = _normalize_jabstract(jabstract);
  117     _reference["title"] = _bibtex_title(titles, subtitles);
  118 
  119     const QString jtype(jobj.value("type").toString());
  120 
  121     if (jtype == "journal-article")
  122     {
  123         _reference.typeName = "article";
  124         _reference["journal"] = containertitles.count() > 0 ? containertitles.first() : QString();
  125     }
  126     else if (jtype == "proceedings-article")
  127     {
  128         _reference.typeName = "inproceedings";
  129         _reference["booktitle"] = _bibtex_booktitle(containertitles);
  130         _reference["series"] = _bibtex_series(containertitles);
  131         _reference["isbn"] = jisbn;
  132         _reference["publisher"] = jpublisher;
  133     }
  134     else if (jtype == "book")
  135     {
  136         _reference.typeName = "book";
  137         _reference["series"] = containertitles.count() > 0 ? containertitles.first() : QString();
  138         _reference["isbn"] = jisbn;
  139         _reference["publisher"] = jpublisher;
  140     }
  141     else if (jtype == "book-chapter")
  142     {
  143         _reference.typeName = "inbook";
  144         _reference["booktitle"] = _bibtex_booktitle(containertitles);
  145         _reference["series"] = _bibtex_series(containertitles);
  146         _reference["isbn"] = jisbn;
  147         _reference["publisher"] = jpublisher;
  148     }
  149     else
  150     {
  151         // jtype == "other"
  152         _reference.typeName = "misc";
  153         _reference["booktitle"] = _bibtex_booktitle(containertitles);
  154         _reference["series"] = _bibtex_series(containertitles);
  155         _reference["isbn"] = jisbn;
  156         _reference["publisher"] = jpublisher;
  157     }
  158 
  159     if (_reference.value("series") == _reference.value("booktitle"))
  160         _reference["series"] = QString();
  161     if (jtype == "book-chapter" && !_reference.value("series").isEmpty())
  162         _reference.typeName = "incollection";
  163 
  164 #ifdef C2B_DEBUG
  165     qDebug() << "[crjson]  TITLES" << titles;
  166     qDebug() << "[crjson]  SUBTITLES" << subtitles;
  167     qDebug() << "[crjson]  CONTAINERTITLES" << containertitles;
  168 
  169     qDebug() << "[crjson]  BIBTEX";
  170     qDebug() << "[crjson]  type       " << _reference.typeName;
  171     qDebug() << "[crjson]  title      " << _reference.value("title");
  172     qDebug() << "[crjson]  booktitle  " << _reference.value("booktitle");
  173     qDebug() << "[crjson]  series     " << _reference.value("series");
  174     qDebug() << "[crjson]  publisher  " << _reference.value("publisher");
  175     qDebug() << "[crjson]  isbn       " << _reference.value("isbn");
  176     qDebug() << "[crjson]  year       " << _reference.value("year");
  177 #endif
  178 
  179     _has_error = false;
  180 }
  181 
  182 void crJson::_normalize_jtitles(QStringList* titles)
  183 {
  184     if (titles->count() == 0)
  185         return;
  186     titles->removeDuplicates();
  187     for (int i = 0; i < titles->count(); ++i)
  188     {
  189         QString t(titles->at(i).simplified());
  190         for (int j = 0; j < t.length(); ++j)
  191             if (t.at(j).category() == QChar::Punctuation_Dash)
  192                 t[j] = '-';
  193         t.replace(" - ", ": ");
  194         t.replace(" : ", ": ");
  195         (*titles)[i] = t;
  196     }
  197 }
  198 
  199 QString crJson::_normalize_jabstract(const QString& abstract)
  200 {
  201     if (abstract.isEmpty())
  202         return abstract;
  203     QString na(abstract);
  204     na.replace("&lt;", "<");
  205     na.replace("&gt;", ">");
  206     na.replace(QRegExp("<[^>]+>"), " ");
  207     na.remove(QRegExp("^\\W*(abstract|synopsis|summary)\\.*", Qt::CaseInsensitive));
  208     return na.simplified();
  209 }
  210 
  211 QString crJson::_bibtex_title(const QStringList& titles, const QStringList& subtitles)
  212 {
  213     if (titles.count() > 0 && subtitles.count() > 0 && !titles.first().contains(": "))
  214     {
  215         const int wt(_words(titles.first()));
  216         const int ws(_words(subtitles.first()));
  217         const int wu(_words(titles.first() + ' ' + subtitles.first()));
  218         const int s(100 * (wt + ws - wu) / sqrt(double(wt * ws)));
  219         if (s < 30)
  220             return titles.first() + ": " + subtitles.first();
  221     }
  222     return titles.count() > 0 ? titles.first() : QString();
  223 }
  224 
  225 QString crJson::_bibtex_booktitle(const QStringList& titles)
  226 {
  227     if (titles.count() == 0)
  228         return QString();
  229     if (titles.count() == 2)
  230         return (!titles.at(1).contains(
  231                     QRegExp("(advances|series|lecture notes|studies in|topics in)", Qt::CaseInsensitive)))
  232                ? titles.at(1)
  233                : titles.at(0);
  234     return titles.first();
  235 }
  236 
  237 QString crJson::_bibtex_series(const QStringList& titles)
  238 {
  239     if (titles.count() == 2)
  240         return (titles.at(1).contains(
  241                     QRegExp("(advances|series|lecture notes|studies in|topics in)", Qt::CaseInsensitive)))
  242                ? titles.at(1)
  243                : titles.at(0);
  244     return QString();
  245 }
  246 
  247 int crJson::_words(const QString& s)
  248 {
  249     QStringList wl(s.split(QRegExp("\\W"), QString::SkipEmptyParts));
  250     wl.removeDuplicates();
  251     return wl.count();
  252 }