calendar-webapp/source/calendarwebapp/event.d

208 lines
5.3 KiB
D
Raw Normal View History

2017-09-17 17:52:41 +02:00
module calendarwebapp.event;
import poodinis;
import std.algorithm : filter, map;
2017-10-30 02:31:48 +01:00
import std.conv : to;
2017-09-17 17:52:41 +02:00
import std.datetime : Date;
import std.range.interfaces : InputRange, inputRangeObject;
import std.typecons : Nullable;
import vibe.data.bson : Bson, BsonObjectID, deserializeBson, serializeToBson;
import vibe.data.serialization : serializationName = name;
import vibe.db.mongo.collection : MongoCollection;
interface EventStore
{
2017-10-30 02:31:48 +01:00
Event getEvent(string id);
InputRange!Event getAllEvents();
void addEvent(Event);
2017-12-10 00:44:05 +01:00
InputRange!Event getEventsBeginningBetween(Date begin, Date end);
2017-10-30 02:31:48 +01:00
void removeEvent(string id);
2017-09-17 17:52:41 +02:00
}
class MongoDBEventStore(Collection = MongoCollection) : EventStore
{
public:
2017-10-30 02:31:48 +01:00
Event getEvent(string id) @safe
2017-09-17 17:52:41 +02:00
{
return events.findOne(["_id" : id]).deserializeBson!Event;
}
InputRange!Event getAllEvents() @safe
{
return events.find().map!(deserializeBson!Event).inputRangeObject;
}
void addEvent(Event event) @safe
{
2017-10-30 02:31:48 +01:00
import std.conv : ConvException;
try
{
if (!BsonObjectID.fromString(event.id).valid)
throw new ConvException("invalid BsonObjectID.");
}
catch (ConvException)
{
event.id = BsonObjectID.generate.to!string;
}
2017-09-17 17:52:41 +02:00
events.insert(event.serializeToBson);
}
InputRange!Event getEventsBeginningBetween(Date begin, Date end) @safe
{
2017-10-30 02:31:48 +01:00
return events.find(["$and" : [["date" : ["$gte" : begin.serializeToBson]],
2017-12-03 01:27:00 +01:00
["date" : ["$lt" : end.serializeToBson]]]]).map!(deserializeBson!Event)
2017-09-17 17:52:41 +02:00
.inputRangeObject;
}
2017-10-30 02:31:48 +01:00
void removeEvent(string id) @safe
2017-09-17 17:52:41 +02:00
{
events.remove(["_id" : id]);
}
private:
@Value("events")
Collection events;
}
2017-10-30 02:31:48 +01:00
class MySQLEventStore : EventStore
{
private:
import mysql;
@Value("mysql.table.events") string eventsTableName;
2017-10-30 02:31:48 +01:00
public:
Event getEvent(string id)
{
auto cn = pool.lockConnection();
scope (exit)
cn.close;
auto prepared = cn.prepare(
"SELECT id begin end name description type shout FROM "
~ eventsTableName ~ " WHERE id = ?");
2017-10-30 02:31:48 +01:00
prepared.setArg(0, id.to!uint);
return toEvent(prepared.query.front);
}
InputRange!Event getAllEvents()
{
auto cn = pool.lockConnection();
scope (exit)
cn.close;
auto prepared = cn.prepare(
"SELECT id, begin, end, name, description, type, shout FROM " ~ eventsTableName ~ "");
2017-10-30 02:31:48 +01:00
return prepared.querySet.map!(r => toEvent(r)).inputRangeObject;
}
void addEvent(Event event)
{
auto cn = pool.lockConnection();
scope (exit)
cn.close;
auto prepared = cn.prepare(
"INSERT INTO " ~ eventsTableName
~ " (begin, end, name, description, type, shout) VALUES(?, ?, ?, ?, ?, ?)");
2017-10-30 02:31:48 +01:00
prepared.setArgs(event.begin, event.end, event.name, event.description,
event.type.to!uint, event.shout);
prepared.exec();
}
2017-12-10 00:44:05 +01:00
InputRange!Event getEventsBeginningBetween(Date begin, Date end)
2017-10-30 02:31:48 +01:00
{
2017-12-03 01:27:00 +01:00
auto cn = pool.lockConnection();
scope (exit)
cn.close;
auto prepared = cn.prepare(
"SELECT id, begin, end, name, description, type, shout FROM events WHERE begin >= ? and end < ?");
prepared.setArgs(begin, end);
return prepared.querySet.map!(r => toEvent(r)).inputRangeObject;
}
2017-10-30 02:31:48 +01:00
void removeEvent(string id)
{
auto cn = pool.lockConnection();
scope (exit)
cn.close;
auto prepared = cn.prepare("DELETE FROM " ~ eventsTableName ~ " WHERE id = ?");
2017-10-30 02:31:48 +01:00
prepared.setArg(0, id.to!uint);
prepared.exec();
}
private:
@Autowire MySQLPool pool;
Event toEvent(Row r)
{
Event event;
event.id = r[0].get!uint.to!string;
event.begin = r[1].get!Date;
if (r[2].hasValue)
event.end = r[2].get!Date;
event.name = r[3].get!string;
event.description = r[4].get!string;
event.type = r[5].get!uint.to!EventType;
event.shout = r[6].get!byte.to!bool;
return event;
}
}
class StubEventStore : EventStore
{
private:
Event[string] events;
public:
Event getEvent(string id) @safe
{
import std.exception : enforce;
enforce((id in events) != null, "No event with id \"" ~ id ~ "\".");
return events[id];
}
InputRange!Event getAllEvents() nothrow
{
return events.byValue.inputRangeObject;
}
void addEvent(Event event) @safe nothrow
{
events[event.id] = event;
}
InputRange!Event getEventsBeginningBetween(Date begin, Date end) nothrow
{
return events.byValue.filter!(event => event.begin >= begin
&& event.begin < end).inputRangeObject;
}
void removeEvent(string id) @safe nothrow
{
events.remove(id);
}
}
2017-09-17 17:52:41 +02:00
enum EventType
{
Holiday,
Birthday,
FSI_Event,
General_University_Event,
Any
}
struct Event
{
2017-10-30 02:31:48 +01:00
@serializationName("_id") string id;
2017-09-17 17:52:41 +02:00
@serializationName("date") Date begin;
@serializationName("end_date") Nullable!Date end;
string name;
@serializationName("desc") string description;
@serializationName("etype") EventType type;
bool shout;
}