/***************************************************************************
 *   Copyright (C) 2004-2009 by Pere Constans
 *   constans@molspaces.com
 *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
 *   See the LICENSE file that comes with this distribution.
 ***************************************************************************/
#include "pubmedXml.h"

#include "cb2bib_utilities.h"

pubmedXml::pubmedXml(const QString& xml) : QXmlStreamReader()
{
    // toQtXmlString and fromQtXmlString are workarounds for Qt < 4.5
    addData(c2bUtils::toQtXmlString(xml));
    _reference.clearReference();
    readReference();
    QMutableHashIterator<QString, QString> it(_reference);
    while (it.hasNext())
    {
        it.next();
        it.value() = c2bUtils::fromQtXmlString(it.value());
    }
}

pubmedXml::~pubmedXml()
{}


void pubmedXml::readReference()
{
    while (reading("PubmedArticle"))
        if (name() == "Journal")
            readJournal();
        else if (name() == "AuthorList")
            readAuthors();
        else if (name() == "MeshHeadingList")
            readKeywords();
        else if (name() == "ArticleTitle")
            readField("title");
        else if (name() == "AbstractText")
            readField("abstract");
        else if (name() == "MedlinePgn")
            readField("pages");
        else if (name() == "PMID")
        {
            readNext();
            _reference["url"] = c2bUtils::pubmedUrl.arg(text().toString());
        }
        else if (name() == "ArticleId")
        {
            if (attributes().count() > 0)
                if (attributes().first().value().toString() == "doi")
                    readField("doi");
        }
}

void pubmedXml::readField(const QString& field)
{
    readNext();
    _reference[field] = text().toString();
}

void pubmedXml::readAuthors()
{
    QStringList authors;
    while (reading("AuthorList"))
    {
        QString a;
        while (reading("Author"))
            if (name() == "LastName")
            {
                readNext();
                a = a + ' ' + text().toString();
            }
            else if (name() == "ForeName" || name() == "FirstName")
            {
                readNext();
                a = text().toString() + ' ' + a;
            }
            else if (name() == "Suffix")
            {
                readNext();
                a = a + ' ' + text().toString();
            }
        authors.append(a);
    }
    _reference["author"] = authors.join(", ");
}

void pubmedXml::readJournal()
{
    QString ja, jf;
    while (reading("Journal"))
        if (name() == "ISOAbbreviation")
        {
            readNext();
            ja = text().toString();
        }
        else if (name() == "Title")
        {
            readNext();
            jf = text().toString();
        }
        else if (name() == "Volume")
            readField("volume");
        else if (name() == "Issue")
            readField("number");
        else if (name() == "Year")
            readField("year");
    if (ja.isEmpty())
        _reference["journal"] = jf;
    else
        _reference["journal"] = ja;
}

void pubmedXml::readKeywords()
{
    QStringList k;
    while (reading("MeshHeadingList"))
        if (name() == "DescriptorName")
        {
            readNext();
            k.append(text().toString());
        }
    _reference["keywords"] = k.join(", ");
}

bool pubmedXml::reading(const QString& tag)
{
    while (!atEnd())
    {
        TokenType t = readNext();
        if (t == StartElement)
            return true;
        else if (t == EndElement)
            if (name() == tag)
                return false;
    }
    return false;
}
