00001 #include "tasktype.h"
00002
00003 #include "clock.h"
00004 #include "task.h"
00005 #include "invitation.h"
00006 #include "user.h"
00007 #include "usertype.h"
00008 #include "resourcetype.h"
00009 #include "reservation.h"
00010
00011 #include <QVariant>
00012 #include "resource.h"
00013 #include <tools/invaliddataexception.h>
00014
00015 namespace domain
00016 {
00017
00018 struct TaskTypePrivate
00019 {
00020 QList<Field> fields;
00021 QList<Requirement*> requirements;
00022 QList<UserType*> potentialOwners;
00023 TaskType* q;
00024
00025 TaskTypePrivate(TaskType* qq) : q(qq)
00026 {
00027 }
00028
00029 ~TaskTypePrivate()
00030 {
00031 qDeleteAll(requirements);
00032 }
00033
00034 template<typename T>
00035 QList<Requirement*> requirementByType()
00036 {
00037 QList<Requirement*> ret;
00038
00039 Q_FOREACH (Requirement* req, requirements)
00040 {
00041 if (qobject_cast<T>(req->type) != 0)
00042 ret << req;
00043 }
00044
00045 return ret;
00046 }
00047
00048 template<typename Req, typename Type>
00049 Req* addRequirement(Type* type, unsigned min, unsigned max)
00050 {
00051 if (max < min)
00052 {
00053 throw tools::InvalidDataException(QString("Invalid arguments for "
00054 "requirement of type %1. Maximum value (%2) is less than minimum "
00055 "value (%3)").arg(type->name()).arg(min).arg(max));
00056 }
00057
00058 Q_FOREACH (Requirement* req, requirements)
00059 {
00060 if (req->type == type)
00061 {
00062 throw tools::InvalidDataException(QString("Cannot have multiple "
00063 "requirements for type %1").arg(type->name()));
00064 }
00065 }
00066
00067 Req* req = new Req(type);
00068 req->min = min;
00069 req->max = max;
00070 requirements << req;
00071
00072 emit q->dataChanged();
00073
00074 return req;
00075 }
00076 };
00077
00078 TaskType::TaskType(const QString& id, const QString& name) : Type(id, name),
00079 d(new TaskTypePrivate(this))
00080 {
00081 }
00082
00083 TaskType::~TaskType()
00084 {
00085 delete d;
00086 }
00087
00088 const QList<Field>& TaskType::fields() const
00089 {
00090 return d->fields;
00091 }
00092
00093 const QList<Requirement*>& TaskType::requirements() const
00094 {
00095 return d->requirements;
00096 }
00097
00098 QList<Requirement*> TaskType::resourceRequirements() const
00099 {
00100 return d->requirementByType<ResourceType*>();
00101 }
00102
00103 QList<Requirement*> TaskType::userRequirements() const
00104 {
00105 return d->requirementByType<UserType*>();
00106 }
00107
00108 bool TaskType::requirementsAreFulfilled(const Task* task) const
00109 {
00110 if (task->taskType() != this)
00111 return false;
00112
00113 Q_FOREACH (Requirement* requirement, d->requirements)
00114 {
00115 if (!requirement->isFulfilled(task))
00116 return false;
00117 }
00118
00119 return true;
00120 }
00121
00122 bool TaskType::canBeSuccessful(const domain::Task* task) const
00123 {
00124 Q_FOREACH (Requirement* requirement, d->requirements)
00125 {
00126 if (!requirement->canBeSuccessful(task))
00127 return false;
00128 }
00129
00130 return true;
00131 }
00132
00133 const QList<UserType*>& TaskType::potentialOwners() const
00134 {
00135 return d->potentialOwners;
00136 }
00137
00138 bool TaskType::userCanCreate (UserType* userType) const
00139 {
00140 return potentialOwners().contains(userType);
00141 }
00142
00143 void TaskType::addField(const domain::Field& field)
00144 {
00145 if (!field.isValid())
00146 {
00147 throw tools::InvalidDataException(QString("Invalid field to add to "
00148 "tasktype %1: field insufficiently instantiated").arg(this->name()));
00149 }
00150 else if (!this->fieldById(field.id).isNull())
00151 {
00152 throw tools::InvalidDataException(QString("Invalid field to add to "
00153 "tasktype %1. Duplicate ID %2").arg(this->name()).arg(field.id));
00154 }
00155
00156 d->fields << field;
00157 emit dataChanged();
00158 }
00159
00160 UserRequirement* TaskType::addRequirement(
00161 UserType* type, unsigned int min, unsigned int max)
00162 {
00163 return d->addRequirement<UserRequirement>(type, min, max);
00164 }
00165
00166 ResourceRequirement* TaskType::addRequirement(
00167 ResourceType* type, unsigned int min, unsigned int max)
00168 {
00169 return d->addRequirement<ResourceRequirement>(type, min, max);
00170 }
00171 void TaskType::addPotentialOwner(UserType* owner)
00172 {
00173 if (!potentialOwners().contains(owner))
00174 {
00175 d->potentialOwners << owner;
00176 emit dataChanged();
00177 }
00178 }
00179
00180 Field TaskType::fieldById(const QString& id) const
00181 {
00182 Q_FOREACH (Field field, d->fields)
00183 {
00184 if (field.id == id)
00185 return field;
00186 }
00187
00188 return Field();
00189 }
00190
00191 Requirement* TaskType::requirementByType(Type* type) const
00192 {
00193 Q_FOREACH (Requirement* req, d->requirements)
00194 {
00195 if (req->type == type)
00196 return req;
00197 }
00198
00199 return 0;
00200 }
00201
00202 bool Field::isValid(const QVariant& val) const
00203 {
00204 QVariant value = val;
00205
00206 if (value.toString().isEmpty())
00207 return false;
00208
00209 if (nature == Textual)
00210 return value.convert(QVariant::String);
00211 else
00212 return value.convert(QVariant::Int);
00213 }
00214
00215 bool Field::isNull() const
00216 {
00217 return id.isEmpty();
00218 }
00219
00220 bool Field::isValid() const
00221 {
00222 return !(id.isEmpty() || name.isEmpty());
00223 }
00224
00225 Requirement::Requirement(Type* type) : type(type)
00226 {
00227 }
00228
00229 UserRequirement::UserRequirement(UserType* userType) : Requirement(userType)
00230 {
00231 }
00232
00233 UserRequirement::~UserRequirement()
00234 {
00235 }
00236
00237 bool UserRequirement::isFulfilled(const Task* task) const
00238 {
00239 unsigned count = 0;
00240
00241 Q_FOREACH (const Invitation* invitation, task->invitations())
00242 {
00243 if (invitation->user()->userType() == type &&
00244 invitation->state() == Invitation::Accepted)
00245 {
00246 count++;
00247 }
00248 }
00249
00250 return count >= min && count <= max;
00251 }
00252
00253 bool UserRequirement::canBeSuccessful(const domain::Task* task) const
00254 {
00255 return isFulfilled(task);
00256 }
00257
00258 ResourceRequirement::ResourceRequirement(ResourceType* resourceType) :
00259 Requirement(resourceType)
00260 {
00261 }
00262
00263 ResourceRequirement::~ResourceRequirement()
00264 {
00265 }
00266
00267 bool ResourceRequirement::isFulfilled(const Task* task) const
00268 {
00269 unsigned count = 0;
00270
00271 Q_FOREACH (const Reservation* reservation, task->reservations())
00272 {
00273 if (reservation->resource()->resourceType() == type &&
00274 reservation->isActive())
00275 {
00276 count++;
00277 }
00278 }
00279
00280 return count >= min && count <= max;
00281 }
00282
00283 bool ResourceRequirement::canBeSuccessful(const domain::Task* task) const
00284 {
00285 unsigned count = 0;
00286
00287 Q_FOREACH (const Reservation* reservation, task->reservations())
00288 {
00289 if (reservation->resource()->resourceType() == type &&
00290 reservation->time() <= Clock::currentTime())
00291 {
00292 count++;
00293 }
00294 }
00295
00296 return count >= min && count <= max;
00297
00298 }
00299
00300 }