reservationmanager.cpp 6.77 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
    Copyright (C) 2018 Volker Krause <vkrause@kde.org>

    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This program is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "reservationmanager.h"
19
#include "pkpassmanager.h"
20 21
#include "logging.h"

22 23
#include <KItinerary/ExtractorEngine>
#include <KItinerary/ExtractorPostprocessor>
24 25
#include <KItinerary/Flight>
#include <KItinerary/JsonLdDocument>
26
#include <KItinerary/MergeUtil>
27

28
#include <QDate>
29 30 31 32 33 34
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QStandardPaths>
Volker Krause's avatar
Volker Krause committed
35
#include <QUrl>
36 37 38
#include <QUuid>
#include <QVector>

39

40 41 42 43 44 45 46 47 48
using namespace KItinerary;

ReservationManager::ReservationManager(QObject* parent)
    : QObject(parent)
{
}

ReservationManager::~ReservationManager() = default;

49 50 51 52 53 54 55 56
void ReservationManager::setPkPassManager(PkPassManager* mgr)
{
    m_passMgr = mgr;
    connect(mgr, &PkPassManager::passAdded, this, &ReservationManager::passAdded);
    connect(mgr, &PkPassManager::passUpdated, this, &ReservationManager::passUpdated);
    connect(mgr, &PkPassManager::passRemoved, this, &ReservationManager::passRemoved);
}

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
QVector<QString> ReservationManager::reservations() const
{
    const auto basePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/reservations");
    QDir::root().mkpath(basePath);

    QVector<QString> resIds;
    for (QDirIterator it(basePath, QDir::NoDotAndDotDot | QDir::Files); it.hasNext();) {
        it.next();
        resIds.push_back(it.fileInfo().baseName());
    }

    return resIds;
}

QVariant ReservationManager::reservation(const QString& id) const
{
73 74 75 76
    if (id.isEmpty()) {
        return {};
    }

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
    const auto it = m_reservations.constFind(id);
    if (it != m_reservations.constEnd()) {
        return it.value();
    }

    const QString resPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/reservations/") + id + QLatin1String(".jsonld");
    QFile f(resPath);
    if (!f.open(QFile::ReadOnly)) {
        qCWarning(Log) << "Failed to open JSON-LD reservation data file:" << resPath << f.errorString();
        return {};
    }

    const auto doc = QJsonDocument::fromJson(f.readAll());
    if (!doc.isArray() && doc.array().size() != 1) {
        qCWarning(Log) << "Invalid JSON-LD reservation data file:" << resPath;
        return {};
    }

    const auto resData = JsonLdDocument::fromJson(doc.array());
    if (resData.size() != 1) {
        qCWarning(Log) << "Unable to parse JSON-LD reservation data file:" << resPath;
        return {};
    }

    m_reservations.insert(id, resData.at(0));
    return resData.at(0);
}

Volker Krause's avatar
Volker Krause committed
105
void ReservationManager::importReservation(const QUrl& filename)
106
{
Volker Krause's avatar
Volker Krause committed
107 108 109 110
    if (!filename.isLocalFile())
        return;

    QFile f(filename.toLocalFile());
111 112 113 114 115 116 117 118 119 120 121 122
    if (!f.open(QFile::ReadOnly)) {
        qCWarning(Log) << "Unable to open file:" << f.errorString();
        return;
    }

    const auto doc = QJsonDocument::fromJson(f.readAll());
    if (!doc.isArray()) {
        qCWarning(Log) << "Invalid JSON format.";
        return;
    }

    const auto resData = JsonLdDocument::fromJson(doc.array());
123 124 125 126 127
    importReservations(resData);
}

void ReservationManager::importReservations(const QVector<QVariant> &resData)
{
128 129 130 131
    ExtractorPostprocessor postproc;
    postproc.setContextDate(QDateTime(QDate::currentDate(), QTime(0, 0)));
    postproc.process(resData);

132 133 134
    const auto basePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/reservations/");
    QDir::root().mkpath(basePath);

135
    for (auto res : postproc.result()) {
136 137 138 139 140 141
        QString resId;
        bool oldResFound = false;

        // check if we know this one already, and update if that's the case
        for (const auto &oldResId : reservations()) {
            const auto oldRes = reservation(oldResId);
142
            if (MergeUtil::isSameReservation(oldRes, res)) {
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
                res = JsonLdDocument::apply(oldRes, res);
                resId = oldResId;
                oldResFound = true;
                break;
            }
        }

        if (resId.isEmpty()) {
            resId = QUuid::createUuid().toString();
        }

        const QString path = basePath + resId + QLatin1String(".jsonld");
        QFile f(path);
        if (!f.open(QFile::WriteOnly)) {
            qCWarning(Log) << "Unable to create file:" << f.errorString();
            continue;
        }
        f.write(QJsonDocument(JsonLdDocument::toJson({res})).toJson());
        m_reservations.insert(resId, res);

        if (oldResFound) {
            emit reservationUpdated(resId);
        } else {
            emit reservationAdded(resId);
        }
    }
}

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
void ReservationManager::addReservation(const QVariant &res)
{
    QString resId = QUuid::createUuid().toString();
    const auto basePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/reservations/");
    QDir::root().mkpath(basePath);
    const QString path = basePath + resId + QLatin1String(".jsonld");
    QFile f(path);
    if (!f.open(QFile::WriteOnly)) {
        qCWarning(Log) << "Unable to create file:" << f.errorString();
        return;
    }
    f.write(QJsonDocument(JsonLdDocument::toJson({res})).toJson());
    m_reservations.insert(resId, res);
    emit reservationAdded(resId);

}

188 189 190 191 192
void ReservationManager::removeReservation(const QString& id)
{
    const auto basePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/reservations/");
    QFile::remove(basePath + QLatin1Char('/') + id + QLatin1String(".jsonld"));
    emit reservationRemoved(id);
193
    m_reservations.remove(id);
194
}
195 196 197 198 199 200 201 202 203 204 205

void ReservationManager::passAdded(const QString& passId)
{
    const auto pass = m_passMgr->pass(passId);
    const auto extractors = m_extractorRepo.extractorsForPass(pass);
    for (const auto &extractor : extractors) {
        ExtractorEngine engine;
        engine.setExtractor(extractor);
        engine.setPass(pass);
        const auto data = engine.extract();
        const auto res = JsonLdDocument::fromJson(data);
206
        importReservations(res);
207 208 209 210 211 212 213 214 215 216 217 218 219
    }
}

void ReservationManager::passUpdated(const QString& passId)
{
    passAdded(passId);
}

void ReservationManager::passRemoved(const QString& passId)
{
    Q_UNUSED(passId);
    // TODO
}