001: /*
002: * Lucane - a collaborative platform
003: * Copyright (C) 2003 Vincent Fiack <vfiack@mail15.com>
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package org.lucane.applications.calendar;
021:
022: import java.sql.*;
023: import java.util.*;
024:
025: import org.lucane.common.*;
026: import org.lucane.common.net.ObjectConnection;
027: import org.lucane.server.*;
028: import org.lucane.server.database.DatabaseAbstractionLayer;
029: import org.lucane.server.database.util.Sequence;
030: import org.lucane.server.store.Store;
031:
032: public class CalendarService extends Service {
033: private Store store;
034: private DatabaseAbstractionLayer layer;
035: private Sequence sequence;
036:
037: /**
038: * Initialize the service.
039: * Called every time the server is started.
040: *
041: * @param parent the Server
042: */
043: public void init(Server parent) {
044: this .store = parent.getStore();
045: this .layer = parent.getDBLayer();
046: this .sequence = new Sequence("CalEvents", "id");
047: }
048:
049: /**
050: * Install the service.
051: * Only called the first time a service is initialized.
052: */
053: public void install() {
054: try {
055: String dbDescription = getDirectory() + "db-calendar.xml";
056: layer.getTableCreator().createFromXml(dbDescription);
057: this .addType("type.default", 170, 140, 220, "default.png");
058: this .addType("type.meeting", 220, 140, 170, "meeting.png");
059: this .addType("type.presentation", 100, 40, 50,
060: "presentation.png");
061: this .addType("type.training", 40, 100, 80, "training.png");
062: this
063: .addType("type.vacation", 140, 220, 220,
064: "vacation.png");
065: } catch (Exception e) {
066: Logging.getLogger().severe(
067: "Unable to install CalendarService !");
068: e.printStackTrace();
069: }
070: }
071:
072: public void process(ObjectConnection oc, Message message) {
073: CalendarAction ca = (CalendarAction) message.getData();
074: String user, resource;
075: long start, end;
076: boolean showAll;
077: ArrayList list;
078:
079: try {
080: switch (ca.action) {
081: case CalendarAction.STORE_EVENT:
082: storeEvent((Event) ca.get("event"));
083: oc.write("OK");
084: break;
085:
086: case CalendarAction.REMOVE_EVENT:
087: removeEvent((Event) ca.get("event"));
088: oc.write("OK");
089: break;
090:
091: case CalendarAction.GET_EVENTS_FOR_USER:
092: user = (String) ca.get("user");
093: showAll = ((Boolean) ca.get("showAll")).booleanValue();
094: start = ((Long) ca.get("startTime")).longValue();
095: end = ((Long) ca.get("endTime")).longValue();
096:
097: list = getEventsForUser(user, showAll, start, end);
098: oc.write("OK");
099: oc.write(list);
100: break;
101:
102: case CalendarAction.GET_EVENTS_FOR_RESOURCE:
103: resource = (String) ca.get("resource");
104: start = ((Long) ca.get("startTime")).longValue();
105: end = ((Long) ca.get("endTime")).longValue();
106:
107: list = getEventsForResource(resource, start, end);
108: oc.write("OK");
109: oc.write(list);
110: break;
111:
112: case CalendarAction.GET_RESOURCES:
113: list = getResources();
114: oc.write("OK");
115: oc.write(list);
116: break;
117:
118: case CalendarAction.GET_USERS:
119: list = getUsers();
120: oc.write("OK");
121: oc.write(list);
122: break;
123:
124: case CalendarAction.GET_GROUPS:
125: list = getGroups();
126: oc.write("OK");
127: oc.write(list);
128: break;
129:
130: case CalendarAction.GET_EVENT_TYPES:
131: list = getEventTypes();
132: oc.write("OK");
133: oc.write(list);
134: break;
135: }
136: } catch (Exception e) {
137: try {
138: oc.write("FAILED " + e);
139: } catch (Exception e2) {
140: }
141:
142: e.printStackTrace();
143: }
144:
145: }
146:
147: //-- set
148:
149: public void storeEvent(Event event) throws Exception {
150: Logging.getLogger().fine("Storing event : " + event.getTitle());
151:
152: boolean newEvent = event.getId() < 0;
153: if (newEvent)
154: event.setId(sequence.getNextId());
155: else
156: removeEvent(event);
157:
158: Connection c = layer.getConnection();
159: PreparedStatement insert = c
160: .prepareStatement("INSERT INTO CalEvents VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
161:
162: insert.setInt(1, event.getId());
163: insert.setString(2, event.getTitle());
164: insert.setString(3, event.getType());
165: insert.setString(4, event.getOrganizer());
166: insert.setInt(5, event.isPublic() ? 1 : 0);
167: insert.setInt(6, event.isEditable() ? 1 : 0);
168: insert.setLong(7, event.getStartDate().getTime());
169: insert.setLong(8, event.getEndDate().getTime());
170: insert.setInt(9, event.getRecurrence());
171: insert.setString(10, event.getDescription());
172:
173: insert.execute();
174: insert.close();
175:
176: storeAttendees(event);
177: storeResources(event);
178:
179: if (newEvent)
180: new MailThread(event, getDirectory() + "event-new.mail")
181: .start();
182: else
183: new MailThread(event, getDirectory() + "event-update.mail")
184: .start();
185:
186: c.close();
187: }
188:
189: private void storeAttendees(Event event) throws Exception {
190: Connection c = layer.getConnection();
191: PreparedStatement insert = c
192: .prepareStatement("INSERT INTO CalAttendees VALUES(?, ?, ?, ?)");
193:
194: Iterator attendees = event.getAttendees();
195: while (attendees.hasNext()) {
196: Attendee attendee = (Attendee) attendees.next();
197: insert.setInt(1, event.getId());
198: insert.setString(2, attendee.getUser());
199: insert.setInt(3, attendee.isMandatory() ? 1 : 0);
200: insert.setInt(4, attendee.getStatus());
201: insert.execute();
202: }
203:
204: insert.close();
205: c.close();
206: }
207:
208: private void storeResources(Event event) throws Exception {
209: Connection c = layer.getConnection();
210: PreparedStatement insert = c
211: .prepareStatement("INSERT INTO CalResources VALUES(?, ?)");
212:
213: Iterator resources = event.getResources();
214: while (resources.hasNext()) {
215: String resource = (String) resources.next();
216: insert.setInt(1, event.getId());
217: insert.setString(2, resource);
218: insert.execute();
219: }
220:
221: insert.close();
222: c.close();
223: }
224:
225: //-- remove
226:
227: public void removeEvent(Event event) throws Exception {
228: if (event.getId() < 0)
229: return;
230:
231: Logging.getLogger()
232: .fine("Removing event : " + event.getTitle());
233: Connection c = layer.getConnection();
234: PreparedStatement delete;
235:
236: delete = c.prepareStatement("DELETE FROM CalEvents WHERE id=?");
237: delete.setInt(1, event.getId());
238: delete.execute();
239: delete.close();
240:
241: delete = c
242: .prepareStatement("DELETE FROM CalAttendees WHERE eventId=?");
243: delete.setInt(1, event.getId());
244: delete.execute();
245: delete.close();
246:
247: delete = c
248: .prepareStatement("DELETE FROM CalResources WHERE eventId=?");
249: delete.setInt(1, event.getId());
250: delete.execute();
251: delete.close();
252:
253: c.close();
254: }
255:
256: //-- get
257:
258: public ArrayList getEventsForUser(String user, boolean showAll,
259: long start, long end) throws Exception {
260: ArrayList events = new ArrayList();
261: Connection c = layer.getConnection();
262:
263: //events where the user is organizer
264: PreparedStatement select = c
265: .prepareStatement("SELECT * FROM CalEvents WHERE "
266: + "organizer = ? AND ("
267: + "(startTime >= ? AND startTime <= ?) "
268: + "OR (endTime >= ? AND endTime <= ?) "
269: + "OR (startTime <= ? AND endTime >= ?) "
270: + "OR recurrence > 0) " + "ORDER BY startTime");
271:
272: select.setString(1, user);
273: select.setLong(2, start);
274: select.setLong(3, end);
275: select.setLong(4, start);
276: select.setLong(5, end);
277: select.setLong(6, start);
278: select.setLong(7, start);
279: ResultSet rs = select.executeQuery();
280: addEventsFromQuery(rs, events, showAll);
281: rs.close();
282: select.close();
283:
284: //events where the user is an attendee
285: select = c
286: .prepareStatement("SELECT * FROM CalEvents e, CalAttendees a WHERE "
287: + "e.id = a.eventId AND "
288: + "a.userName = ? AND ("
289: + "(startTime >= ? AND startTime <= ?) "
290: + "OR (endTime >= ? AND endTime <= ?) "
291: + "OR (startTime <= ? AND endTime >= ?) "
292: + "OR recurrence > 0)");
293:
294: select.setString(1, user);
295: select.setLong(2, start);
296: select.setLong(3, end);
297: select.setLong(4, start);
298: select.setLong(5, end);
299: select.setLong(6, start);
300: select.setLong(7, start);
301: rs = select.executeQuery();
302: addEventsFromQuery(rs, events, showAll);
303: rs.close();
304: select.close();
305:
306: c.close();
307:
308: return filterEvents(events, start, end);
309: }
310:
311: public Event getEventById(String user, int id) throws Exception {
312: ArrayList events = new ArrayList();
313: Connection c = layer.getConnection();
314:
315: //events where the user is organizer
316: PreparedStatement select = c
317: .prepareStatement("SELECT * FROM CalEvents WHERE "
318: + "id=?");
319:
320: select.setInt(1, id);
321: ResultSet rs = select.executeQuery();
322: addEventsFromQuery(rs, events, false);
323: rs.close();
324: select.close();
325: c.close();
326:
327: if (events.size() != 1)
328: throw new Exception("No such event: " + id);
329:
330: Event event = (Event) events.get(0);
331:
332: //private events
333: if (!event.isPublic() && !event.getOrganizer().equals(user)) {
334: event = new Event(id, "private", "private", "", false,
335: false, event.getStartDate().getTime(), event
336: .getEndDate().getTime(), event
337: .getRecurrence(), "");
338: event.setIconFile("private.png");
339: event.setColor(150, 150, 150);
340: }
341:
342: return event;
343: }
344:
345: private void addEventsFromQuery(ResultSet r, ArrayList events,
346: boolean showAll) throws Exception {
347: while (r.next()) {
348: int id = r.getInt(1);
349: String title = r.getString(2);
350: String type = r.getString(3);
351: String organizer = r.getString(4);
352: boolean isPublic = (r.getInt(5) == 1);
353: boolean isEditable = (r.getInt(6) == 1);
354: long mystart = r.getLong(7);
355: long myend = r.getLong(8);
356: int recurrence = r.getInt(9);
357: String description = r.getString(10);
358:
359: if (showAll || isPublic) {
360: Event event = new Event(id, type, title, organizer,
361: isPublic, isEditable, mystart, myend,
362: recurrence, description);
363: loadTypeInfos(event);
364: loadAttendees(event);
365: loadResources(event);
366: events.add(event);
367: } else {
368: Event event = new Event(id, "private", "private", "",
369: isPublic, isEditable, mystart, myend,
370: recurrence, "");
371: event.setIconFile("private.png");
372: event.setColor(150, 150, 150);
373: events.add(event);
374: }
375: }
376: }
377:
378: private ArrayList filterEvents(ArrayList events, long start,
379: long end) {
380: ArrayList newEvents = new ArrayList();
381:
382: Iterator i = events.iterator();
383: while (i.hasNext()) {
384: Event event = (Event) i.next();
385: if (event.getRecurrence() == Event.RECUR_NONE) {
386: newEvents.add(event);
387: } else {
388: //get the fist event after the start time
389: Calendar time = Calendar.getInstance();
390: time.setTime(event.getStartDate());
391: while (time.getTime().getTime() < start) {
392: if (event.getRecurrence() == Event.RECUR_DAY)
393: time.add(Calendar.DAY_OF_YEAR, 1);
394: else if (event.getRecurrence() == Event.RECUR_WEEK)
395: time.add(Calendar.WEEK_OF_YEAR, 1);
396: else if (event.getRecurrence() == Event.RECUR_MONTH)
397: time.add(Calendar.MONTH, 1);
398: else if (event.getRecurrence() == Event.RECUR_YEAR)
399: time.add(Calendar.YEAR, 1);
400: }
401:
402: //create all events until the end time
403: long duration = event.getEndDate().getTime()
404: - event.getStartDate().getTime();
405: while (time.getTime().getTime() < end) {
406: long mytime = time.getTime().getTime();
407: Event e = new Event(event.getId(), event.getType(),
408: event.getTitle(), event.getOrganizer(),
409: event.isPublic(), event.isEditable(),
410: mytime, mytime + duration, event
411: .getRecurrence(), event
412: .getDescription());
413: e.setIconFile(event.getIconFile());
414: e.setColor(event.getColorRed(), event
415: .getColorGreen(), event.getColorBlue());
416: newEvents.add(e);
417:
418: if (event.getRecurrence() == Event.RECUR_DAY)
419: time.add(Calendar.DAY_OF_YEAR, 1);
420: else if (event.getRecurrence() == Event.RECUR_WEEK)
421: time.add(Calendar.WEEK_OF_YEAR, 1);
422: else if (event.getRecurrence() == Event.RECUR_MONTH)
423: time.add(Calendar.MONTH, 1);
424: else if (event.getRecurrence() == Event.RECUR_YEAR)
425: time.add(Calendar.YEAR, 1);
426: }
427: }
428: }
429:
430: return newEvents;
431: }
432:
433: public ArrayList getEventsForResource(String object, long start,
434: long end) throws Exception {
435: ArrayList events = new ArrayList();
436:
437: Connection c = layer.getConnection();
438: PreparedStatement select = c
439: .prepareStatement("SELECT e.* FROM CalEvents e, CalResources r WHERE "
440: + "e.id = r.eventId AND r.object = ?");
441:
442: select.setString(1, object);
443:
444: ResultSet r = select.executeQuery();
445: while (r.next()) {
446: int id = r.getInt(1);
447: String title = r.getString(2);
448: String type = r.getString(3);
449: String organizer = r.getString(4);
450: boolean isPublic = (r.getInt(5) == 1);
451: boolean isEditable = (r.getInt(6) == 1);
452: long mystart = r.getLong(7);
453: long myend = r.getLong(8);
454: int recurrence = r.getInt(9);
455: String description = r.getString(10);
456:
457: if (isPublic) {
458: Event event = new Event(id, type, title, organizer,
459: isPublic, isEditable, mystart, myend,
460: recurrence, description);
461: loadTypeInfos(event);
462: loadAttendees(event);
463: loadResources(event);
464: events.add(event);
465: } else {
466: Event event = new Event(id, "private", "private", "",
467: isPublic, isEditable, mystart, myend,
468: recurrence, "");
469: event.setColor(150, 150, 150);
470: event.setIconFile("private.png");
471: events.add(event);
472: }
473: }
474:
475: select.close();
476: c.close();
477:
478: return events;
479: }
480:
481: public ArrayList getResources() throws Exception {
482: ArrayList resources = new ArrayList();
483:
484: Connection c = layer.getConnection();
485: PreparedStatement select = c
486: .prepareStatement("SELECT * FROM CalObjects");
487:
488: ResultSet r = select.executeQuery();
489: while (r.next()) {
490: String object = r.getString(1);
491: resources.add(object);
492: }
493:
494: select.close();
495: c.close();
496:
497: return resources;
498: }
499:
500: public ArrayList getUsers() throws Exception {
501: ArrayList users = new ArrayList();
502: Iterator i = store.getUserStore().getAllUsers();
503: while (i.hasNext())
504: users.add(i.next());
505:
506: return users;
507: }
508:
509: private ArrayList getGroups() throws Exception {
510: ArrayList groups = new ArrayList();
511: Iterator i = store.getGroupStore().getAllGroups();
512: while (i.hasNext())
513: groups.add(i.next());
514:
515: return groups;
516: }
517:
518: private void loadTypeInfos(Event event) throws Exception {
519: Connection c = layer.getConnection();
520: PreparedStatement select = c
521: .prepareStatement("SELECT * FROM CalEventTypes WHERE type = ?");
522:
523: select.setString(1, event.getType());
524:
525: ResultSet r = select.executeQuery();
526: if (r.next()) {
527: int red = r.getInt(2);
528: int green = r.getInt(3);
529: int blue = r.getInt(4);
530: String icon = r.getString(5);
531:
532: event.setColor(red, green, blue);
533: event.setIconFile(icon);
534: }
535:
536: r.close();
537: select.close();
538: c.close();
539: }
540:
541: public ArrayList getEventTypes() throws Exception {
542: ArrayList types = new ArrayList();
543: Connection c = layer.getConnection();
544: PreparedStatement select = c
545: .prepareStatement("SELECT * FROM CalEventTypes");
546:
547: ResultSet r = select.executeQuery();
548: while (r.next())
549: types.add(r.getString(1));
550:
551: r.close();
552: select.close();
553: c.close();
554:
555: return types;
556: }
557:
558: private void loadAttendees(Event event) throws Exception {
559: ArrayList attendees = new ArrayList();
560: Connection c = layer.getConnection();
561: PreparedStatement select = c
562: .prepareStatement("SELECT * FROM CalAttendees WHERE eventId = ?");
563:
564: select.setInt(1, event.getId());
565:
566: ResultSet r = select.executeQuery();
567: while (r.next()) {
568: String user = r.getString(2);
569: boolean mandatory = (r.getInt(3) == 1);
570: int status = r.getInt(4);
571:
572: Attendee attendee = new Attendee(user, mandatory, status);
573: attendees.add(attendee);
574: }
575:
576: event.setAttendees(attendees);
577:
578: r.close();
579: select.close();
580: c.close();
581: }
582:
583: private void loadResources(Event event) throws Exception {
584: ArrayList resources = new ArrayList();
585: Connection c = layer.getConnection();
586: PreparedStatement select = c
587: .prepareStatement("SELECT * FROM CalResources WHERE eventId = ?");
588:
589: select.setInt(1, event.getId());
590:
591: ResultSet r = select.executeQuery();
592: while (r.next()) {
593: String object = r.getString(2);
594: resources.add(object);
595: }
596:
597: event.setResources(resources);
598:
599: r.close();
600: select.close();
601: c.close();
602: }
603:
604: private void addType(String name, int red, int green, int blue,
605: String icon) throws Exception {
606: Connection c = layer.getConnection();
607: PreparedStatement insert = c
608: .prepareStatement("INSERT INTO CalEventTypes VALUES(?, ?, ?, ?, ?)");
609:
610: insert.setString(1, name);
611: insert.setInt(2, red);
612: insert.setInt(3, green);
613: insert.setInt(4, blue);
614: insert.setString(5, icon);
615:
616: insert.execute();
617: insert.close();
618: c.close();
619: }
620: }
|