001: /*
002: Copyright (C) 2003-2005 Know Gate S.L. All rights reserved.
003: C/Oņa, 107 1š2 28050 Madrid (Spain)
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions
007: are met:
008:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011:
012: 2. The end-user documentation included with the redistribution,
013: if any, must include the following acknowledgment:
014: "This product includes software parts from hipergate
015: (http://www.hipergate.org/)."
016: Alternately, this acknowledgment may appear in the software itself,
017: if and wherever such third-party acknowledgments normally appear.
018:
019: 3. The name hipergate must not be used to endorse or promote products
020: derived from this software without prior written permission.
021: Products derived from this software may not be called hipergate,
022: nor may hipergate appear in their name, without prior written
023: permission.
024:
025: This library is distributed in the hope that it will be useful,
026: but WITHOUT ANY WARRANTY; without even the implied warranty of
027: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
028:
029: You should have received a copy of hipergate License with this code;
030: if not, visit http://www.hipergate.org or mail to info@hipergate.org
031: */
032:
033: package com.knowgate.addrbook.jical;
034:
035: import java.io.IOException;
036: import java.io.File;
037:
038: import java.util.Date;
039: import java.util.Locale;
040: import java.util.Iterator;
041: import java.sql.SQLException;
042:
043: import com.knowgate.jdc.JDCConnection;
044: import com.knowgate.acl.ACL;
045: import com.knowgate.acl.ACLUser;
046: import com.knowgate.debug.DebugFile;
047: import com.knowgate.misc.Gadgets;
048: import com.knowgate.dataobjs.DB;
049: import com.knowgate.dataobjs.DBSubset;
050: import com.knowgate.hipergate.DBLanguages;
051: import com.knowgate.addrbook.*;
052:
053: import org.jical.ICalendar;
054: import org.jical.ICalendarParser;
055: import org.jical.ICalendarVEvent;
056:
057: /**
058: * <p>Create an ICalendar object for a given hipergate Fellow meetings</p>
059: * @author Sergio Montoro Ten
060: * @version 1.0
061: */
062: public class ICalendarFactory {
063: public ICalendarFactory() {
064: }
065:
066: // ---------------------------------------------------------------------------
067:
068: private static String duration(Date dtStart, Date dtEnd) {
069: final long lSecond = 1000;
070: final long lMinute = lSecond * 60l;
071: final long lHour = lMinute * 60l;
072: final long lDay = lHour * 24l;
073: long lDuration = dtEnd.getTime() - dtStart.getTime();
074: return (lDuration >= 0 ? "" : "-") + "P"
075: + String.valueOf(lDuration / lDay) + "DT"
076: + String.valueOf(lDuration / lHour) + "H"
077: + String.valueOf(lDuration / lMinute) + "M"
078: + String.valueOf(lDuration / lSecond) + "S";
079: }
080:
081: // ---------------------------------------------------------------------------
082:
083: /**
084: * Get an <a href="http://www.ietf.org/rfc/rfc2445.txt">RFC 2445</a> calendar for a Fellow
085: * @param oConn JDCConnection
086: * @param sGuFellow String Fellow GUID from k_fellows table
087: * @param dtFrom Date from which to start exporting meetings
088: * @param dtTo Date when stop exporting meetings
089: * @param sLanguage String Two letter identifier of language to be used if this parameter is <b>null</b> then the default Locale is used.
090: * @return ICalendar
091: * @throws SQLException If not fellow with specified GUID is found at k_fellows table
092: * @throws IllegalArgumentException if dtFrom>dtTo
093: * @throws NullPointerException if sGuFellow or dtFrom or dtTo is <b>null</b>
094: */
095: public static ICalendar createICalendar(JDCConnection oConn,
096: String sGuFellow, Date dtFrom, Date dtTo, String sLanguage)
097: throws SQLException, IllegalArgumentException,
098: NullPointerException {
099: ICalendarVEvent oEvt;
100: String sTpRoom, sOrganizerName, sOrganizerMail;
101: Date dtNow = new Date();
102:
103: if (DebugFile.trace) {
104: DebugFile.writeln("Begin ICalendarFactory([JDCConnection],"
105: + sGuFellow + "," + dtFrom.toString() + ","
106: + dtTo.toString() + "," + sLanguage + ")");
107: DebugFile.incIdent();
108: }
109:
110: if (sGuFellow == null) {
111: if (DebugFile.trace)
112: DebugFile.decIdent();
113: throw new NullPointerException(
114: "ICalendarFactory.createICalendar() Fellow GUID parameter is required");
115: }
116:
117: if (dtFrom == null || dtTo == null) {
118: if (DebugFile.trace)
119: DebugFile.decIdent();
120: throw new NullPointerException(
121: "ICalendarFactory.createICalendar() Both start and end date are required");
122: }
123:
124: if (dtFrom.compareTo(dtTo) > 0) {
125: if (DebugFile.trace)
126: DebugFile.decIdent();
127: throw new IllegalArgumentException(
128: "ICalendarFactory.createICalendar() End date cannot be prior to start date");
129: }
130:
131: if (sLanguage == null)
132: sLanguage = Locale.getDefault().getLanguage();
133:
134: Fellow oFlw = new Fellow();
135: if (!oFlw.load(oConn, new Object[] { sGuFellow })) {
136: if (DebugFile.trace)
137: DebugFile.decIdent();
138: throw new SQLException("Fellow " + sGuFellow
139: + " not found at " + DB.k_fellows + " table");
140: }
141: DBSubset oMeetings = new DBSubset(DB.k_meetings + " m,"
142: + DB.k_x_meeting_fellow + " f", "m." + DB.gu_meeting
143: + ",m." + DB.dt_start + ",m." + DB.dt_end + "," + "m."
144: + DB.bo_private + ",m." + DB.gu_writer + ",m."
145: + DB.df_before + "," + "m." + DB.tp_meeting + ",m."
146: + DB.tx_meeting + ",m." + DB.de_meeting + "," + "m."
147: + DB.tx_status, "f." + DB.gu_fellow + "=? AND m."
148: + DB.gu_fellow + "=f." + DB.gu_fellow, 100);
149: int iMeetings = oMeetings.load(oConn,
150: new Object[] { sGuFellow });
151:
152: if (DebugFile.trace)
153: DebugFile.writeln(String.valueOf(iMeetings)
154: + " meetings found");
155:
156: DBSubset oRooms = new DBSubset(DB.k_x_meeting_room + " x,"
157: + DB.k_rooms + " r", "r." + DB.gu_workarea + ",r."
158: + DB.tp_room + ",r." + DB.nm_room + "," + "r."
159: + DB.tx_location, "x." + DB.gu_meeting + "=? AND "
160: + "x." + DB.nm_room + "=r." + DB.nm_room, 2);
161: int iRooms;
162:
163: ICalendar oCal = new ICalendar();
164: oCal.setProdId("JICAL");
165: oCal.setVersion("2.0");
166: for (int m = 0; m < iMeetings; m++) {
167: if (DebugFile.trace)
168: DebugFile.writeln("Loading meeting "
169: + oMeetings.getStringNull(7, m, ""));
170: oEvt = new ICalendarVEvent(oMeetings.getDate(1, m),
171: oMeetings.getDate(2, m), oMeetings.getStringNull(8,
172: m, ""), duration(oMeetings.getDate(1, m),
173: oMeetings.getDate(2, m)), oMeetings
174: .getStringNull(7, m, ""), null, null);
175: oEvt.setSequence(0);
176: oEvt.setDateStamp(dtNow);
177: oEvt.setCreated(dtNow);
178: oEvt.setLastModified(dtNow);
179: oEvt.setEventClass(oMeetings.getShort(3, m) == 0 ? "PUBLIC"
180: : "PRIVATE");
181: oEvt.setTransparency("OPAQUE");
182: if (!oMeetings.isNull(6, m))
183: oEvt.setCategories(oMeetings.getString(6, m));
184: if (oMeetings.isNull(4, m)
185: || sGuFellow.equals(oMeetings.get(4, m))) {
186: sOrganizerName = (oFlw.getStringNull(DB.tx_name, "")
187: + " " + oFlw.getStringNull(DB.tx_surname, ""))
188: .trim();
189: sOrganizerMail = oFlw.getStringNull(DB.tx_email, "");
190: } else {
191: ACLUser oWrt = new ACLUser();
192: if (oWrt.load(oConn,
193: new Object[] { oMeetings.get(4, m) })) {
194: sOrganizerName = (oFlw
195: .getStringNull(DB.nm_user, "")
196: + " "
197: + oFlw.getStringNull(DB.tx_surname1, "")
198: + " " + oFlw.getStringNull(DB.tx_surname2,
199: "")).trim();
200: sOrganizerMail = oFlw.getStringNull(
201: DB.tx_main_email, "");
202: } else {
203: sOrganizerName = (oFlw
204: .getStringNull(DB.tx_name, "")
205: + " " + oFlw.getStringNull(DB.tx_surname,
206: "")).trim();
207: sOrganizerMail = oFlw
208: .getStringNull(DB.tx_email, "");
209: }
210: }
211: if (DebugFile.trace)
212: DebugFile.writeln("Organizer is \"" + sOrganizerName
213: + "\" <" + sOrganizerMail + ">");
214: oEvt.setOrganizer("CN=:\""
215: + sOrganizerName.replace((char) 34, (char) 32)
216: + "\":MAILTO:" + sOrganizerMail);
217: oEvt.setUid("hipergate-" + oMeetings.getString(0, m));
218: oEvt.setPriority(3);
219: if (!oMeetings.isNull(9, m))
220: oEvt.setStatus(oMeetings.getString(9, m));
221: iRooms = oRooms.load(oConn, new Object[] { oMeetings
222: .getString(0, m) });
223: if (iRooms > 0) {
224: if (DebugFile.trace)
225: DebugFile.writeln(String.valueOf(iRooms)
226: + " rooms found");
227: if (sLanguage != null)
228: sTpRoom = DBLanguages.getLookUpTranslation(oConn,
229: DB.k_rooms_lookup, oRooms.getString(1, 0),
230: DB.tp_room, sLanguage, oRooms.getString(2,
231: 0));
232: else
233: sTpRoom = null;
234: if (null == sTpRoom)
235: sTpRoom = "";
236: else
237: sTpRoom += " ";
238: oEvt.setLocation(sTpRoom
239: + oRooms.getString(2, 0)
240: + (oRooms.isNull(3, 0) ? "" : " "
241: + oRooms.getStringNull(3, 0, "")));
242: }
243: oCal.icalEventCollection.add(oEvt);
244: } // next
245: if (DebugFile.trace) {
246: DebugFile.decIdent();
247: DebugFile.writeln("End ICalendarFactory()");
248: }
249: return oCal;
250: }
251:
252: // ---------------------------------------------------------------------------
253:
254: /**
255: * Get an <a href="http://www.ietf.org/rfc/rfc2445.txt">RFC 2445</a> calendar for a Fellow
256: * @param oConn JDCConnection
257: * @param sTxEmail String Fellow e-mail. Must be that of tx_main-email of the corresponding User at k_users table.
258: * @param sTxPwd String User password in clear text.
259: * @param dtFrom Date from which to start exporting meetings
260: * @param dtTo Date when stop exporting meetings
261: * @param sLanguage String Two letter identifier of language to be used if this parameter is <b>null</b> then the default Locale is used.
262: * @return ICalendar
263: * @throws SQLException If not fellow with specified e-amil is found at k_users table
264: * @throws IllegalArgumentException if dtFrom>dtTo
265: * @throws NullPointerException if sGuFellow or dtFrom or dtTo is <b>null</b>
266: * @throws SecurityException e-mail/password pair does not match the one set at the database
267: */
268: public static ICalendar createICalendar(JDCConnection oConn,
269: String sTxEmail, String sTxPwd, Date dtFrom, Date dtTo,
270: String sLanguage) throws SQLException,
271: IllegalArgumentException, NullPointerException,
272: SecurityException {
273:
274: String sGuFellow = ACLUser.getIdFromEmail(oConn, sTxEmail);
275:
276: if (null == sGuFellow)
277: throw new SQLException(ACL
278: .getErrorMessage(ACL.USER_NOT_FOUND));
279:
280: short iAuth = ACL.autenticate(oConn, sGuFellow, sTxPwd,
281: ACL.PWD_CLEAR_TEXT);
282: if (iAuth < 0)
283: throw new SecurityException(ACL.getErrorMessage(iAuth));
284:
285: return createICalendar(oConn, sGuFellow, dtFrom, dtTo,
286: sLanguage);
287: }
288:
289: // ---------------------------------------------------------------------------
290:
291: /**
292: * <p>Load a calendar file into k_meetings table</p>
293: * @param oConn JDCConnection
294: * @param sGuFellow String
295: * @param oCalFile File
296: * @param sEncoding String
297: * @throws SQLException
298: */
299: public static void loadCalendar(JDCConnection oConn,
300: String sGuFellow, File oCalFile, String sEncoding)
301: throws SQLException {
302:
303: Meeting oMeet;
304: String sGuid;
305: String sCats;
306: Fellow oFllw = new Fellow();
307: if (!oFllw.load(oConn, new Object[] { sGuFellow })) {
308: throw new SQLException(ACL
309: .getErrorMessage(ACL.USER_NOT_FOUND));
310: }
311: Room oRoom = new Room();
312: oRoom.put(DB.gu_workarea, oFllw.getString(DB.gu_workarea));
313:
314: ICalendarVEvent oEvnt;
315: ICalendarParser oPrsr = new ICalendarParser();
316: ICalendar oCal = oPrsr.parse(oCalFile, sEncoding);
317: Iterator oIter = oCal.icalEventCollection.iterator();
318: while (oIter.hasNext()) {
319: oEvnt = (ICalendarVEvent) oIter.next();
320: // remove - from Mozilla UIDs
321: sGuid = Gadgets.removeChar(oEvnt.getUid(), '-').trim();
322: sCats = oEvnt.getCategories();
323: if (sCats != null)
324: sCats = (Gadgets.split(sCats, ','))[0];
325: oMeet = new Meeting();
326: if (oMeet.load(oConn, new Object[] { sGuid })) {
327: // Current meeting is only modified if the one comming in the iCalendar file is newer
328: if (oMeet.lastModified().compareTo(
329: oEvnt.getLastModified() == null ? new Date()
330: : oEvnt.getLastModified()) < 0) {
331: oMeet.replace(DB.dt_start, oEvnt.getDateStart());
332: oMeet.replace(DB.dt_end, oEvnt.getDateEnd());
333: if (null == oEvnt.getEventClass())
334: oMeet.replace(DB.bo_private, (short) 1);
335: else
336: oMeet.replace(DB.bo_private, (short) (oEvnt
337: .getEventClass().equals("PRIVATE") ? 1
338: : 0));
339: oMeet.replace(DB.tx_status, oEvnt.getStatus());
340: oMeet.replace(DB.tp_meeting, sCats);
341: oMeet.replace(DB.tx_meeting, oEvnt.getSummary());
342: oMeet
343: .replace(DB.tx_meeting, oEvnt
344: .getDescription());
345: oMeet.store(oConn);
346: }
347: } else {
348: oMeet.put(DB.gu_meeting, sGuid);
349: oMeet.put(DB.gu_workarea, oFllw
350: .getString(DB.gu_workarea));
351: oMeet.put(DB.id_domain, oFllw.getInt(DB.id_domain));
352: oMeet.put(DB.gu_fellow, sGuFellow);
353: oMeet.put(DB.gu_writer, sGuFellow);
354: oMeet.put(DB.dt_start, oEvnt.getDateStart());
355: oMeet.put(DB.dt_end, oEvnt.getDateEnd());
356: if (null == oEvnt.getEventClass())
357: oMeet.put(DB.bo_private, (short) 1);
358: else
359: oMeet
360: .put(DB.bo_private,
361: (short) (oEvnt.getEventClass()
362: .equals("PRIVATE") ? 1 : 0));
363: oMeet.put(DB.tx_status, oEvnt.getStatus());
364: oMeet.replace(DB.tp_meeting, sCats);
365: oMeet.put(DB.tx_meeting, oEvnt.getSummary());
366: oMeet.put(DB.tx_meeting, oEvnt.getDescription());
367: oMeet.store(oConn);
368: oMeet.setAttendant(oConn, sGuFellow);
369: }
370: if (oEvnt.getLocation() != null) {
371: oRoom.replace(DB.nm_room, oEvnt.getLocation());
372: if (oRoom.exists(oConn))
373: oMeet.setRoom(oConn, oEvnt.getLocation());
374: } // fi (getLocation())
375: } // wend
376: } // loadCalendar
377:
378: // ---------------------------------------------------------------------------
379:
380: }
|