refs #649, refs #656, move swift DB classes to own namespace/directory

This commit is contained in:
Klaus Basan
2016-05-24 00:01:00 +02:00
parent f7659e9021
commit 7767e53652
24 changed files with 1926 additions and 1881 deletions

View File

@@ -0,0 +1,205 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "blackmisc/db/datastore.h"
#include "blackmisc/comparefunctions.h"
#include "blackmisc/db/datastoreutility.h"
#include "blackmisc/icon.h"
#include "blackmisc/iconlist.h"
#include "blackmisc/icons.h"
#include <QDateTime>
#include <QtGlobal>
namespace BlackMisc
{
namespace Db
{
QString IDatastoreObjectWithIntegerKey::getDbKeyAsString() const
{
if (this->m_dbKey < 0) { return ""; }
return QString::number(this->m_dbKey);
}
QString IDatastoreObjectWithIntegerKey::getDbKeyAsStringInParentheses() const
{
if (this->m_dbKey < 0) { return ""; }
return "(" + QString::number(this->m_dbKey) + ")";
}
void IDatastoreObjectWithIntegerKey::setDbKey(const QString &key)
{
bool ok;
int k = key.toInt(&ok);
if (!ok) { k = -1; }
this->m_dbKey = k;
}
const CIcon &IDatastoreObjectWithIntegerKey::toDatabaseIcon() const
{
static const CIcon empty;
if (this->hasValidDbKey()) { return CIconList::iconByIndex(CIcons::StandardIconDatabaseKey16); }
return empty;
}
int IDatastoreObjectWithIntegerKey::stringToDbKey(const QString &candidate)
{
if (candidate.isEmpty()) { return invalidDbKey(); }
bool ok;
int k = candidate.toInt(&ok);
return ok ? k : invalidDbKey();
}
QJsonValue IDatastoreObjectWithIntegerKey::getDbKeyAsJsonValue() const
{
if (this->hasValidDbKey()) { return QJsonValue(this->m_dbKey); }
return QJsonValue();
}
void IDatastoreObjectWithIntegerKey::setKeyAndTimestampFromDatabaseJson(const QJsonObject &json, const QString &prefix)
{
int dbKey = json.value(prefix + "id").toInt(-1);
const QString timestampString(json.value(prefix + "lastupdated").toString());
const QDateTime ts(CDatastoreUtility::parseTimestamp(timestampString));
this->setDbKey(dbKey);
this->setUtcTimestamp(ts);
}
bool IDatastoreObjectWithIntegerKey::existsKey(const QJsonObject &json, const QString &prefix)
{
return !json.value(prefix + "id").isNull();
}
CVariant IDatastoreObjectWithIntegerKey::propertyByIndex(const CPropertyIndex &index) const
{
if (ITimestampBased::canHandleIndex(index)) { return ITimestampBased::propertyByIndex(index); }
ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexDbIntegerKey: return CVariant::from(this->m_dbKey);
case IndexDatabaseIcon: return CVariant::from(this->toDatabaseIcon());
default: break;
}
return CVariant();
}
void IDatastoreObjectWithIntegerKey::setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant)
{
if (ITimestampBased::canHandleIndex(index)) { ITimestampBased::setPropertyByIndex(index, variant); return; }
ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexDbIntegerKey:
this->m_dbKey = variant.toInt();
break;
default:
break;
}
}
int IDatastoreObjectWithIntegerKey::comparePropertyByIndex(const CPropertyIndex &index, const IDatastoreObjectWithIntegerKey &compareValue) const
{
if (ITimestampBased::canHandleIndex(index)) { return ITimestampBased::comparePropertyByIndex(index, compareValue); }
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexDbIntegerKey: return Compare::compare(this->m_dbKey, compareValue.getDbKey());
case IndexDatabaseIcon: return Compare::compare(this->hasValidDbKey(), compareValue.hasValidDbKey());
default: break;
}
Q_ASSERT_X(false, Q_FUNC_INFO, "Compare failed");
return 0;
}
bool IDatastoreObjectWithIntegerKey::canHandleIndex(const BlackMisc::CPropertyIndex &index)
{
if (ITimestampBased::canHandleIndex(index)) { return true;}
int i = index.frontCasted<int>();
return (i >= static_cast<int>(IndexDbIntegerKey)) && (i <= static_cast<int>(IndexDatabaseIcon));
}
QJsonValue IDatastoreObjectWithStringKey::getDbKeyAsJsonValue() const
{
if (this->hasValidDbKey()) { return QJsonValue(this->m_dbKey); }
static const QJsonValue null;
return null;
}
const CIcon &IDatastoreObjectWithStringKey::toDatabaseIcon() const
{
static const CIcon empty;
if (this->hasValidDbKey()) { return CIconList::iconByIndex(CIcons::StandardIconDatabaseKey16); }
return empty;
}
void IDatastoreObjectWithStringKey::setKeyAndTimestampFromDatabaseJson(const QJsonObject &json, const QString &prefix)
{
QString dbKey = json.value(prefix + "id").toString();
QDateTime ts(CDatastoreUtility::parseTimestamp(json.value(prefix + "lastupdated").toString()));
this->setDbKey(dbKey);
this->setUtcTimestamp(ts);
}
bool IDatastoreObjectWithStringKey::existsKey(const QJsonObject &json, const QString &prefix)
{
return !json.value(prefix + "id").isNull();
}
CVariant IDatastoreObjectWithStringKey::propertyByIndex(const CPropertyIndex &index) const
{
if (ITimestampBased::canHandleIndex(index)) { return ITimestampBased::propertyByIndex(index); }
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexDbStringKey: return CVariant::from(this->m_dbKey);
case IndexDatabaseIcon: return CVariant::from(this->toDatabaseIcon());
default:
break;
}
return CVariant();
}
void IDatastoreObjectWithStringKey::setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant)
{
if (ITimestampBased::canHandleIndex(index)) { ITimestampBased::setPropertyByIndex(index, variant); return; }
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexDbStringKey:
this->m_dbKey = variant.value<QString>();
break;
default:
break;
}
}
int IDatastoreObjectWithStringKey::comparePropertyByIndex(const CPropertyIndex &index, const IDatastoreObjectWithStringKey &compareValue) const
{
if (ITimestampBased::canHandleIndex(index)) { return ITimestampBased::comparePropertyByIndex(index, compareValue); }
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexDbStringKey: return this->m_dbKey.compare(compareValue.getDbKey());
case IndexDatabaseIcon: return Compare::compare(this->hasValidDbKey(), compareValue.hasValidDbKey());
default:
break;
}
Q_ASSERT_X(false, Q_FUNC_INFO, "Compare failed");
return 0;
}
bool IDatastoreObjectWithStringKey::canHandleIndex(const CPropertyIndex &index)
{
if (index.isEmpty()) { return false; }
if (ITimestampBased::canHandleIndex(index)) { return true;}
int i = index.frontCasted<int>();
return (i >= static_cast<int>(IndexDbStringKey)) && (i <= static_cast<int>(IndexDatabaseIcon));
}
}
} // namespace

View File

@@ -0,0 +1,166 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_DB_DATASTORE_H
#define BLACKMISC_DB_DATASTORE_H
#include "blackmisc/blackmiscexport.h"
#include "blackmisc/propertyindex.h"
#include "blackmisc/timestampbased.h"
#include "blackmisc/variant.h"
#include <QJsonObject>
#include <QJsonValue>
#include <QObject>
#include <QString>
namespace BlackMisc
{
class CIcon;
namespace Db
{
/*!
* Class from which a derived class can inherit datastore-related functions.
*/
class BLACKMISC_EXPORT IDatastoreObjectWithIntegerKey : public ITimestampBased
{
public:
//! Property index
enum ColumnIndex
{
IndexDbIntegerKey = CPropertyIndex::GlobalIndexIDatastoreInteger,
IndexDatabaseIcon
};
//! Get DB key.
int getDbKey() const { return m_dbKey; }
//! DB key as string
QString getDbKeyAsString() const;
//! Key as JSON value, or null
QJsonValue getDbKeyAsJsonValue() const;
//! Db ley in parentheses, e.g. "(3)"
QString getDbKeyAsStringInParentheses() const;
//! Set the DB key
void setDbKey(int key) { m_dbKey = key; }
//! DB key passed as string
void setDbKey(const QString &key);
//! Has valid DB key
bool hasValidDbKey() const { return m_dbKey >= 0; }
//! Database icon if this has valid key, otherwise empty
const CIcon &toDatabaseIcon() const;
//! Invalid key
static int invalidDbKey() { return -1; }
//! Convert string to DB key
static int stringToDbKey(const QString &candidate);
protected:
//! Constructor
IDatastoreObjectWithIntegerKey() {}
//! Constructor
IDatastoreObjectWithIntegerKey(int key) : m_dbKey(key) {}
//! Set key and timestamp values
void setKeyAndTimestampFromDatabaseJson(const QJsonObject &json, const QString &prefix = QString());
//! Is a key available?
static bool existsKey(const QJsonObject &json, const QString &prefix = QString());
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const;
//! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
void setPropertyByIndex(const BlackMisc::CPropertyIndex &index, const CVariant &variant);
//! Compare by index
int comparePropertyByIndex(const CPropertyIndex &index, const IDatastoreObjectWithIntegerKey &compareValue) const;
//! Can given index be handled?
static bool canHandleIndex(const BlackMisc::CPropertyIndex &index);
int m_dbKey = -1; //!< key
};
/*!
* Class from which a derived class can inherit datastore-related functions.
*/
class BLACKMISC_EXPORT IDatastoreObjectWithStringKey : public ITimestampBased
{
public:
//! Property index
enum ColumnIndex
{
IndexDbStringKey = CPropertyIndex::GlobalIndexIDatastoreString,
IndexDatabaseIcon
};
//! Get DB key.
const QString &getDbKey() const { return m_dbKey; }
//! Key as JSON value, or null
QJsonValue getDbKeyAsJsonValue() const;
//! Set the DB key
void setDbKey(const QString &key) { m_dbKey = key.trimmed().toUpper(); }
//! Has valid DB key
bool hasValidDbKey() const { return !m_dbKey.isEmpty(); }
//! Database icon if this has valid key, otherwise empty
const CIcon &toDatabaseIcon() const;
//! Invalid key
static QString invalidDbKey() { return ""; }
protected:
//! Constructor
IDatastoreObjectWithStringKey() {}
//! Constructor
IDatastoreObjectWithStringKey(const QString &key) : m_dbKey(key) {}
//! Set key and timestamp values
void setKeyAndTimestampFromDatabaseJson(const QJsonObject &json, const QString &prefix = QString());
//! Is a key available?
static bool existsKey(const QJsonObject &json, const QString &prefix = QString());
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const;
//! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
void setPropertyByIndex(const BlackMisc::CPropertyIndex &index, const CVariant &variant);
//! Compare by index
int comparePropertyByIndex(const BlackMisc::CPropertyIndex &index, const IDatastoreObjectWithStringKey &compareValue) const;
//! Can given index be handled
static bool canHandleIndex(const BlackMisc::CPropertyIndex &index);
QString m_dbKey; //!< key
};
} // ns
} // ns
Q_DECLARE_INTERFACE(BlackMisc::Db::IDatastoreObjectWithIntegerKey, "org.swift-project.blackmisc.db.idatastoreobjectwithintegerkey")
Q_DECLARE_INTERFACE(BlackMisc::Db::IDatastoreObjectWithStringKey, "org.swift-project.blackmisc.db.idatastoreobjectwithstringkey")
#endif // guard

View File

@@ -0,0 +1,175 @@
/* Copyright (C) 2015
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "blackmisc/db/datastoreobjectlist.h"
#include "blackmisc/predicates.h"
#include "blackmisc/countrylist.h"
#include "blackmisc/aviation/liverylist.h"
#include "blackmisc/aviation/aircrafticaocodelist.h"
#include "blackmisc/aviation/airlineicaocodelist.h"
#include "blackmisc/db/dbinfolist.h"
#include "blackmisc/simulation/aircraftmodellist.h"
#include "blackmisc/simulation/distributorlist.h"
#include <QJsonObject>
#include <QJsonValue>
#include <algorithm>
#include <iterator>
#include <type_traits>
namespace BlackMisc
{
namespace Db
{
template <class OBJ, class CONTAINER, typename KEYTYPE>
IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::IDatastoreObjectList()
{
constexpr bool hasIntegerKey = std::is_base_of<IDatastoreObjectWithIntegerKey, OBJ>::value && std::is_same<int, KEYTYPE>::value;
constexpr bool hasStringKey = std::is_base_of<IDatastoreObjectWithStringKey, OBJ>::value && std::is_base_of<QString, KEYTYPE>::value;
static_assert(hasIntegerKey || hasStringKey, "ObjectType needs to implement IDatastoreObjectWithXXXXKey and have appropriate KeyType");
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
OBJ IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::findByKey(KEYTYPE key, const OBJ &notFound) const
{
return this->container().findFirstByOrDefault(&OBJ::getDbKey, key, notFound);
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
OBJ IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::maxKeyObject() const
{
if (this->container().isEmpty()) { return OBJ(); }
const OBJ max = *std::max_element(this->container().begin(), this->container().end(), [](const OBJ & obj1, const OBJ & obj2)
{
bool v1 = obj1.hasValidDbKey();
bool v2 = obj2.hasValidDbKey();
if (v1 && v2)
{
return obj1.getDbKey() < obj2.getDbKey();
}
return v2;
});
return max;
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
void IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::sortByKey()
{
this->container().sort(BlackMisc::Predicates::MemberLess(&OBJ::getDbKey));
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
QList<KEYTYPE> IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::toDbKeyList() const
{
QList<KEYTYPE> keys;
for (const OBJ &obj : ITimestampObjectList<OBJ, CONTAINER>::container())
{
if (!obj.hasValidDbKey()) { continue; }
keys.append(obj.getDbKey());
}
return keys;
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
KEYTYPE IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::getMaxKey(bool *ok) const
{
QList<KEYTYPE> keys(this->toDbKeyList());
if (keys.isEmpty())
{
if (ok) { *ok = false; }
return KEYTYPE();
}
KEYTYPE max = *std::max_element(keys.begin(), keys.end());
if (ok) { *ok = true; }
return max;
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
int IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::removeObjectsWithKeys(const QList<KEYTYPE> &keys)
{
if (keys.isEmpty()) { return 0; }
if (this->container().isEmpty()) { return 0; }
CONTAINER newValues;
for (const OBJ &obj : ITimestampObjectList<OBJ, CONTAINER>::container())
{
if (keys.contains(obj.getDbKey())) { continue; }
newValues.push_back(obj);
}
int delta = this->container().size() - newValues.size();
this->container() = newValues;
return delta;
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
int IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::removeObjectsWithoutDbKey()
{
if (this->container().isEmpty()) { return 0; }
CONTAINER newValues;
for (const OBJ &obj : ITimestampObjectList<OBJ, CONTAINER>::container())
{
if (!obj.hasValidDbKey()) { continue; }
newValues.push_back(obj);
}
int delta = this->container().size() - newValues.size();
this->container() = newValues;
return delta;
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
int IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::replaceOrAddObjectsByKey(const CONTAINER &container)
{
if (container.isEmpty()) { return 0; }
if (this->container().isEmpty())
{
this->container() = container;
return this->container().size();
}
CONTAINER newValues(this->container());
const QList<KEYTYPE> keys(container.toDbKeyList());
newValues.removeObjectsWithKeys(keys);
int removeSize = newValues.size(); // size after removing data
newValues.push_back(container);
this->container() = newValues;
return newValues.size() - removeSize;
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
CONTAINER IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::fromDatabaseJson(const QJsonArray &array)
{
CONTAINER container;
for (const QJsonValue &value : array)
{
container.push_back(OBJ::fromDatabaseJson(value.toObject()));
}
return container;
}
template <class OBJ, class CONTAINER, typename KEYTYPE>
CONTAINER IDatastoreObjectList<OBJ, CONTAINER, KEYTYPE>::fromDatabaseJson(const QJsonArray &array, const QString &prefix)
{
CONTAINER container;
for (const QJsonValue &value : array)
{
container.push_back(OBJ::fromDatabaseJson(value.toObject(), prefix));
}
return container;
}
// see here for the reason of thess forward instantiations
// http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html
template class IDatastoreObjectList<BlackMisc::Aviation::CLivery, BlackMisc::Aviation::CLiveryList, int>;
template class IDatastoreObjectList<BlackMisc::Aviation::CAircraftIcaoCode, BlackMisc::Aviation::CAircraftIcaoCodeList, int>;
template class IDatastoreObjectList<BlackMisc::Aviation::CAirlineIcaoCode, BlackMisc::Aviation::CAirlineIcaoCodeList, int>;
template class IDatastoreObjectList<BlackMisc::Db::CDbInfo, BlackMisc::Db::CDbInfoList, int>;
template class IDatastoreObjectList<BlackMisc::Simulation::CAircraftModel, BlackMisc::Simulation::CAircraftModelList, int>;
template class IDatastoreObjectList<BlackMisc::Simulation::CDistributor, BlackMisc::Simulation::CDistributorList, QString>;
template class IDatastoreObjectList<BlackMisc::CCountry, BlackMisc::CCountryList, QString>;
} // ns
} // ns

View File

@@ -0,0 +1,95 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_DB_DATABASEOBJECTLIST_H
#define BLACKMISC_DB_DATABASEOBJECTLIST_H
#include "blackmisc/timestampobjectlist.h"
#include <QJsonArray>
#include <QList>
#include <QString>
namespace BlackMisc
{
namespace Db
{
//! List of objects read from database.
//! Such objects should implement \sa ITimestampBased and \sa IDatastoreObjectWithIntegerKey or \sa IDatastoreObjectWithStringKey
template<class OBJ, class CONTAINER, typename KEYTYPE> class IDatastoreObjectList : public ITimestampObjectList<OBJ, CONTAINER>
{
public:
//! Object with key, notFound otherwise
OBJ findByKey(KEYTYPE key, const OBJ &notFound = OBJ()) const;
//! Object with max.key
OBJ maxKeyObject() const;
//! Sort by timestamp
void sortByKey();
//! All keys as list
QList<KEYTYPE> toDbKeyList() const;
//! Max.key value (making sense with integer key)
KEYTYPE getMaxKey(bool *ok = nullptr) const;
//! Remove objects with key
int removeObjectsWithKeys(const QList<KEYTYPE> &keys);
//! Remove objects without key
int removeObjectsWithoutDbKey();
//! Update or insert data (based on DB key)
int replaceOrAddObjectsByKey(const CONTAINER &container);
//! From DB JSON with default prefixes
static CONTAINER fromDatabaseJson(const QJsonArray &array);
//! From DB JSON
static CONTAINER fromDatabaseJson(const QJsonArray &array, const QString &prefix);
protected:
//! Constructor
IDatastoreObjectList();
};
//! \cond PRIVATE
class CDbInfo;
class CDbInfoList;
namespace Aviation
{
class CLivery;
class CLiveryList;
}
namespace Simulation
{
class CDistributor;
class CDistributorList;
class CAircraftModel;
class CAircraftModelList;
}
extern template class BLACKMISC_EXPORT_TEMPLATE IDatastoreObjectList<BlackMisc::Aviation::CLivery, BlackMisc::Aviation::CLiveryList, int>;
extern template class BLACKMISC_EXPORT_TEMPLATE IDatastoreObjectList<BlackMisc::Aviation::CAircraftIcaoCode, BlackMisc::Aviation::CAircraftIcaoCodeList, int>;
extern template class BLACKMISC_EXPORT_TEMPLATE IDatastoreObjectList<BlackMisc::Aviation::CAirlineIcaoCode, BlackMisc::Aviation::CAirlineIcaoCodeList, int>;
extern template class BLACKMISC_EXPORT_TEMPLATE IDatastoreObjectList<BlackMisc::Db::CDbInfo, BlackMisc::Db::CDbInfoList, int>;
extern template class BLACKMISC_EXPORT_TEMPLATE IDatastoreObjectList<BlackMisc::Simulation::CAircraftModel, BlackMisc::Simulation::CAircraftModelList, int>;
extern template class BLACKMISC_EXPORT_TEMPLATE IDatastoreObjectList<BlackMisc::Simulation::CDistributor, BlackMisc::Simulation::CDistributorList, QString>;
extern template class BLACKMISC_EXPORT_TEMPLATE IDatastoreObjectList<BlackMisc::CCountry, BlackMisc::CCountryList, QString>;
//! \endcond
} // ns
} //ns
#endif //guard

View File

@@ -0,0 +1,150 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "blackmisc/db/datastoreutility.h"
#include "blackmisc/logcategory.h"
#include "blackmisc/logcategorylist.h"
#include "blackmisc/simulation/aircraftmodellist.h"
#include "blackmisc/statusmessage.h"
#include "blackmisc/statusmessagelist.h"
#include "blackmisc/stringutils.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QRegExp>
#include <QTimeZone>
using namespace BlackMisc;
using namespace BlackMisc::Simulation;
namespace BlackMisc
{
namespace Db
{
bool CDatastoreUtility::dbBoolStringToBool(const QString &dbBool)
{
return BlackMisc::stringToBool(dbBool);
}
const QString &CDatastoreUtility::boolToDbYN(bool v)
{
static const QString y("Y");
static const QString n("N");
return v ? y : n;
}
int CDatastoreUtility::extractIntegerKey(const QString &stringWithKey)
{
QString ks(stringWithKey.trimmed());
if (ks.isEmpty()) { return -1; }
bool ok = false;
int key = ks.toInt(&ok);
if (ok) { return key; } // only a number
// key in string with ()
int i1 = ks.lastIndexOf('(');
if (i1 < 0) { return -1; }
int i2 = ks.lastIndexOf(')');
if (i2 <= i1 + 1) { return -1;}
QString n(ks.mid(i1 + 1, i2 - i1 - 1));
ok = false;
key = n.toInt(&ok);
return ok ? key : -1;
}
QDateTime CDatastoreUtility::parseTimestamp(const QString &timestamp)
{
if (!timestamp.isEmpty())
{
QString ts(timestamp.trimmed().remove(' ').remove('-').remove(':')); // normalize
QDateTime dt = QDateTime::fromString(ts, "yyyyMMddHHmmss");
dt.setTimeZone(QTimeZone::utc());
return dt;
}
else
{
return QDateTime();
}
}
bool CDatastoreUtility::parseSwiftPublishResponse(const QString &jsonResponse, CAircraftModelList &publishedModels, CAircraftModelList &skippedModels, CStatusMessageList &messages)
{
static const CLogCategoryList cats({ CLogCategory::swiftDbWebservice()});
if (jsonResponse.isEmpty())
{
messages.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, "Empty JSON data"));
return false;
}
QJsonDocument jsonDoc(QJsonDocument::fromJson(jsonResponse.toUtf8()));
// array of messages
if (jsonDoc.isArray())
{
CStatusMessageList msgs(CStatusMessageList::fromDatabaseJson(jsonDoc.array()));
messages.push_back(msgs);
return true;
}
// no object -> most likely some fucked up HTML string with the PHP error
if (!jsonDoc.isObject())
{
QString phpError(jsonResponse);
phpError.remove(QRegExp("<[^>]*>"));
messages.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, phpError));
return false;
}
// fully blown object
QJsonObject json(jsonDoc.object());
bool data = false;
if (json.contains("msgs"))
{
QJsonValue msgJson(json.take("msgs"));
CStatusMessageList msgs(CStatusMessageList::fromDatabaseJson(msgJson.toArray()));
if (!msgs.isEmpty())
{
messages.push_back(msgs);
data = true;
}
}
if (json.contains("publishedModels"))
{
QJsonValue publishedJson(json.take("publishedModels"));
CAircraftModelList published = CAircraftModelList::fromDatabaseJson(publishedJson.toArray(), "");
if (!published.isEmpty())
{
publishedModels.push_back(published);
data = true;
}
}
if (json.contains("skippedModels"))
{
QJsonValue skippedJson(json.take("skippedModels"));
CAircraftModelList skipped = CAircraftModelList::fromDatabaseJson(skippedJson.toArray(), "");
if (!skipped.isEmpty())
{
skippedModels.push_back(skipped);
data = true;
}
}
if (!data)
{
messages.push_back(CStatusMessage(cats, CStatusMessage::SeverityError, "Received response, but no JSON data"));
}
return data;
}
} // ns
} // ns

View File

@@ -0,0 +1,54 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_DB_DATASTOREUTILITY_H
#define BLACKMISC_DB_DATASTOREUTILITY_H
#include "blackmisc/blackmiscexport.h"
#include <QDateTime>
#include <QString>
namespace BlackMisc
{
class CStatusMessageList;
namespace Simulation { class CAircraftModelList; }
namespace Db
{
/*!
* Class with datastore related utilities
*/
class BLACKMISC_EXPORT CDatastoreUtility
{
public:
//! No constructor
CDatastoreUtility() = delete;
//! DB Bool value to bool
static bool dbBoolStringToBool(const QString &dbBool);
//! Bool to DB yes/no
static const QString &boolToDbYN(bool v);
//! Extract key from string like "MyAircraft (33)"
static int extractIntegerKey(const QString &stringWithKey);
//! Parse a timestamp object
static QDateTime parseTimestamp(const QString &timestamp);
//! Get data from a DB response
static bool parseSwiftPublishResponse(const QString &jsonResponse, BlackMisc::Simulation::CAircraftModelList &publishedModels, BlackMisc::Simulation::CAircraftModelList &skippedModels, BlackMisc::CStatusMessageList &messages);
};
} // namespace
} // namespace
#endif // guard