Nut/src/phrase.h

392 lines
12 KiB
C++

/**************************************************************************
**
** This file is part of Nut project.
** https://github.com/HamedMasafi/Nut
**
** Nut is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Nut 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with Nut. If not, see <http://www.gnu.org/licenses/>.
**
**************************************************************************/
#ifndef PHRASE_H
#define PHRASE_H
#include <QSharedPointer>
#include <QString>
#include <QVariant>
#include <QtGlobal>
#if __cplusplus >= 201103L
# include <initializer_list>
#endif
#include "defines.h"
NUT_BEGIN_NAMESPACE
#define SPECIALIZATION_NUMERIC_MEMBER(type, op, cond) \
ConditionalPhrase operator op(const QVariant &other) \
{ \
return ConditionalPhrase(this, cond, other); \
}
class AbstractFieldPhrase;
class AssignmentPhrase;
class PhraseList;
class PhraseData
{
public:
enum Condition {
NotAssign = 0,
Equal,
Less,
LessEqual,
Null,
In,
Like,
Not = 10,
NotEqual,
GreaterEqual,
Greater,
NotNull,
NotIn,
NotLike,
And = 20,
Or,
// Append,
// Set,
Add,
Minus,
Multiple,
Divide,
Mod,
Between,
//date and time
AddYears,
AddMonths,
AddDays,
AddHours,
AddMinutes,
AddSeconds
// // special types
// Distance
};
enum Type { Field, WithVariant, WithOther, WithoutOperand };
const char *className;
const char *fieldName;
Type type;
Condition operatorCond;
const PhraseData *left;
const PhraseData *right;
QVariant operand;
bool isNot;
PhraseData(const char *className, const char *fieldName);
PhraseData(PhraseData *l, Condition o);
PhraseData(PhraseData *l, Condition o, const PhraseData *r);
PhraseData(PhraseData *l, Condition o, QVariant r);
PhraseData(const PhraseData *other);
QString toString() const;
~PhraseData();
};
class AssignmentPhraseList
{
public:
QList<PhraseData*> data;
AssignmentPhraseList(const AssignmentPhrase &l);
AssignmentPhraseList(AssignmentPhraseList *l, const AssignmentPhrase *r);
AssignmentPhraseList(AssignmentPhrase *l, const AssignmentPhrase *r);
AssignmentPhraseList operator &(const AssignmentPhrase &ph);
};
class AssignmentPhrase
{
public:
PhraseData *data;
AssignmentPhrase(AbstractFieldPhrase *l, QVariant r);
AssignmentPhrase(AbstractFieldPhrase *l, const AssignmentPhrase *r);
// AssignmentPhrase(AssignmentPhrase *l, const AssignmentPhrase *r);
AssignmentPhraseList operator &(const AssignmentPhrase &other);
};
class PhraseList{
public:
bool isValid;
QList<const PhraseData*> data;
PhraseList();
PhraseList(const AbstractFieldPhrase &other);
PhraseList(AbstractFieldPhrase *left, const AbstractFieldPhrase *right);
PhraseList(PhraseList *left, PhraseList *right);
PhraseList(PhraseList *left, const AbstractFieldPhrase *right);
virtual ~PhraseList();
PhraseList operator |(PhraseList &other);
PhraseList operator |(const AbstractFieldPhrase &other);
};
class ConditionalPhrase
{
public:
PhraseData *data;
QSharedPointer<PhraseData> leftDataPointer;
QSharedPointer<PhraseData> rightDataPointer;
ConditionalPhrase();
ConditionalPhrase(const ConditionalPhrase &other);
ConditionalPhrase(const ConditionalPhrase &&other);
ConditionalPhrase(const PhraseData *data);
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition);
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition, const QVariant &v);
ConditionalPhrase(AbstractFieldPhrase *, PhraseData::Condition, const AbstractFieldPhrase &v);
ConditionalPhrase(AbstractFieldPhrase *l, PhraseData::Condition cond, ConditionalPhrase &r);
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, const AbstractFieldPhrase &r);
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, const QVariant &r);
ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, ConditionalPhrase &r);
virtual ~ConditionalPhrase();
ConditionalPhrase operator =(const ConditionalPhrase &other);
ConditionalPhrase operator ==(const QVariant &other);
ConditionalPhrase operator ==(const AbstractFieldPhrase &other);
ConditionalPhrase operator &&(const ConditionalPhrase &other);
ConditionalPhrase operator ||(const ConditionalPhrase &other);
ConditionalPhrase operator !();
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
};
class AbstractFieldPhrase
{
public:
PhraseData *data;
AbstractFieldPhrase(const char *className, const char *fieldName);
AbstractFieldPhrase(const AbstractFieldPhrase &other);
virtual ~AbstractFieldPhrase();
PhraseList operator |(const AbstractFieldPhrase &other);
template<typename T>
ConditionalPhrase in(QList<T> list)
{
QVariantList vlist;
foreach (T t, list)
vlist.append(QVariant::fromValue(t));
return ConditionalPhrase(this, PhraseData::In, vlist);
}
#if __cplusplus >= 201103L
ConditionalPhrase in(std::initializer_list<int> list) {
QVariantList vlist;
std::initializer_list<int>::iterator it;
for (it = list.begin(); it != list.end(); ++it)
vlist.append(*it);
return ConditionalPhrase(this, PhraseData::In, vlist);
}
#endif
ConditionalPhrase isNull();
ConditionalPhrase operator ==(const QVariant &other);
ConditionalPhrase operator ==(const ConditionalPhrase &other);
ConditionalPhrase operator !=(const QVariant &other);
ConditionalPhrase operator ==(const AbstractFieldPhrase &other);
ConditionalPhrase operator !=(const AbstractFieldPhrase &other);
ConditionalPhrase operator <(const AbstractFieldPhrase &other);
ConditionalPhrase operator >(const AbstractFieldPhrase &other);
ConditionalPhrase operator <=(const AbstractFieldPhrase &other);
ConditionalPhrase operator >=(const AbstractFieldPhrase &other);
AbstractFieldPhrase operator !();
AssignmentPhrase operator =(const QVariant &other);
AssignmentPhrase operator <<(const QVariant &other);
};
template<typename T>
class FieldPhrase : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s) :
AbstractFieldPhrase(className, s)
{}
AssignmentPhrase operator =(const QVariant &other) {
return AssignmentPhrase(this, other);
}
};
template<>
class FieldPhrase<QString> : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s) :
AbstractFieldPhrase(className, s)
{}
ConditionalPhrase like(const QString &term) {
return ConditionalPhrase(this, PhraseData::Like, term);
}
AssignmentPhrase operator =(const QVariant &other) {
return AssignmentPhrase(this, other);
}
};
#define SPECIALIZATION_NUMERIC(type) \
template<> \
class FieldPhrase<type> : public AbstractFieldPhrase \
{ \
public: \
FieldPhrase(const char *className, const char *s) : \
AbstractFieldPhrase(className, s) \
{} \
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less) \
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual) \
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater) \
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual) \
SPECIALIZATION_NUMERIC_MEMBER(type, %, PhraseData::Mod) \
\
SPECIALIZATION_NUMERIC_MEMBER(type, +, PhraseData::Add) \
SPECIALIZATION_NUMERIC_MEMBER(type, -, PhraseData::Minus) \
SPECIALIZATION_NUMERIC_MEMBER(type, *, PhraseData::Multiple) \
SPECIALIZATION_NUMERIC_MEMBER(type, /, PhraseData::Divide) \
AssignmentPhrase operator =(const QVariant &other) { \
return AssignmentPhrase(this, other); \
} \
ConditionalPhrase between(const QVariant &min, const QVariant &max) \
{ \
return ConditionalPhrase(this, PhraseData::Between, \
QVariantList() << min << max); \
} \
};
SPECIALIZATION_NUMERIC(qint8)
SPECIALIZATION_NUMERIC(qint16)
SPECIALIZATION_NUMERIC(qint32)
SPECIALIZATION_NUMERIC(qint64)
SPECIALIZATION_NUMERIC(quint8)
SPECIALIZATION_NUMERIC(quint16)
SPECIALIZATION_NUMERIC(quint32)
SPECIALIZATION_NUMERIC(quint64)
SPECIALIZATION_NUMERIC(qreal)
//Date and time
#define CONDITIONAL_VARIANT_METHOD(name, cond) \
ConditionalPhrase name(int val) \
{ \
return ConditionalPhrase(this, cond, val); \
}
template<>
class FieldPhrase<QDate> : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s) :
AbstractFieldPhrase(className, s)
{}
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
AssignmentPhrase operator =(const QDate &other) {
return AssignmentPhrase(this, other);
}
ConditionalPhrase between(const QDate &min, const QDate &max)
{
return ConditionalPhrase(this, PhraseData::Between,
QVariantList() << min << max);
}
CONDITIONAL_VARIANT_METHOD(addYears, PhraseData::AddYears)
CONDITIONAL_VARIANT_METHOD(addMonths, PhraseData::AddMonths)
CONDITIONAL_VARIANT_METHOD(addDays, PhraseData::AddDays)
};
template<>
class FieldPhrase<QTime> : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s) :
AbstractFieldPhrase(className, s)
{}
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
AssignmentPhrase operator =(const QTime &other) {
return AssignmentPhrase(this, other);
}
ConditionalPhrase between(const QTime &min, const QTime &max)
{
return ConditionalPhrase(this, PhraseData::Between,
QVariantList() << min << max);
}
CONDITIONAL_VARIANT_METHOD(addHours, PhraseData::AddHours)
CONDITIONAL_VARIANT_METHOD(addMinutes, PhraseData::AddMinutes)
CONDITIONAL_VARIANT_METHOD(addSeconds, PhraseData::AddSeconds)
};
template<>
class FieldPhrase<QDateTime> : public AbstractFieldPhrase
{
public:
FieldPhrase(const char *className, const char *s) :
AbstractFieldPhrase(className, s)
{}
SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less)
SPECIALIZATION_NUMERIC_MEMBER(type, <=, PhraseData::LessEqual)
SPECIALIZATION_NUMERIC_MEMBER(type, >, PhraseData::Greater)
SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual)
AssignmentPhrase operator =(const QDateTime &other) {
return AssignmentPhrase(this, other);
}
ConditionalPhrase between(const QDateTime &min, const QDateTime &max)
{
return ConditionalPhrase(this, PhraseData::Between,
QVariantList() << min << max);
}
CONDITIONAL_VARIANT_METHOD(addYears, PhraseData::AddYears)
CONDITIONAL_VARIANT_METHOD(addMonths, PhraseData::AddMonths)
CONDITIONAL_VARIANT_METHOD(addDays, PhraseData::AddDays)
CONDITIONAL_VARIANT_METHOD(addHours, PhraseData::AddHours)
CONDITIONAL_VARIANT_METHOD(addMinutes, PhraseData::AddMinutes)
CONDITIONAL_VARIANT_METHOD(addSeconds, PhraseData::AddSeconds)
};
NUT_END_NAMESPACE
#endif // PHRASE_H