001: // The contents of this file are subject to the Mozilla Public License Version
002: // 1.1
003: //(the "License"); you may not use this file except in compliance with the
004: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
005: //
006: //Software distributed under the License is distributed on an "AS IS" basis,
007: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
008: //for the specific language governing rights and
009: //limitations under the License.
010: //
011: //The Original Code is "The Columba Project"
012: //
013: //The Initial Developers of the Original Code are Frederik Dietz and Timo
014: // Stich.
015: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
016: //
017: //All Rights Reserved.
018: package org.columba.calendar.parser;
019:
020: import java.util.Calendar;
021: import java.util.Enumeration;
022: import java.util.List;
023: import java.util.logging.Logger;
024:
025: import org.columba.calendar.base.UUIDGenerator;
026: import org.columba.calendar.model.Recurrence;
027: import org.columba.calendar.model.api.ICALENDAR;
028: import org.columba.calendar.model.api.IComponent.TYPE;
029: import org.jdom.Document;
030: import org.jdom.Element;
031:
032: import com.miginfocom.calendar.activity.recurrence.ByXXXRuleData;
033: import com.miginfocom.calendar.activity.recurrence.RecurrenceRule;
034:
035: public class XCSDocumentParser {
036:
037: /** JDK 1.4+ logging framework logger, used for logging. */
038: private static final Logger LOG = Logger
039: .getLogger("org.columba.calendar.store");
040:
041: private Document doc;
042:
043: private Element root;
044:
045: protected Element parentElement;
046:
047: protected Element vcalendarElement;
048:
049: protected Element componentElement;
050:
051: public XCSDocumentParser(TYPE type) {
052: if (type == null)
053: throw new IllegalArgumentException("type == null");
054:
055: doc = new Document();
056: root = new Element(ICALENDAR.ICALENDAR);
057: doc.addContent(root);
058:
059: // TODO fix doctype
060: /*
061: * DocType docType = factory .docType("iCalendar", "-//IETF//DTD
062: * XCAL/iCalendar XML//EN",
063: * "http://www.ietf.org/internet-drafts/draft-hare-xcalendar-01.txt");
064: * doc.setDocType(docType);
065: */
066:
067: vcalendarElement = new Element(ICALENDAR.VCALENDAR);
068: root.addContent(vcalendarElement);
069:
070: vcalendarElement.setAttribute(ICALENDAR.VCALENDAR_METHOD,
071: "PUBLISH");
072: vcalendarElement.setAttribute(ICALENDAR.VCALENDAR_VERSION,
073: "2.0");
074: vcalendarElement.setAttribute(ICALENDAR.VCALENDAR_PRODID,
075: "-//Columba Project //NONSGML Columba v1.0//EN");
076:
077: if (type == TYPE.EVENT) {
078: componentElement = new Element(ICALENDAR.VEVENT);
079: vcalendarElement.addContent(componentElement);
080:
081: } else if (type == TYPE.TODO) {
082: componentElement = new Element(ICALENDAR.VTODO);
083: vcalendarElement.addContent(componentElement);
084: } else
085: throw new IllegalArgumentException(
086: "invalid component specified: " + type);
087:
088: String uuid = new UUIDGenerator().newUUID();
089: Element uuidElement = new Element(ICALENDAR.UID);
090: uuidElement.setText(uuid);
091:
092: componentElement.addContent(uuidElement);
093:
094: parentElement = componentElement;
095: }
096:
097: public XCSDocumentParser(Document document)
098: throws IllegalArgumentException, SyntaxException {
099: if (document == null)
100: throw new IllegalArgumentException("document == null");
101:
102: this .doc = document;
103:
104: this .root = doc.getRootElement();
105:
106: if (!root.getName().equalsIgnoreCase("icalendar")) {
107: // wrong xml-format
108: throw new SyntaxException(
109: "Root element must be <icalendar>!");
110: }
111:
112: vcalendarElement = root.getChild("vcalendar");
113: if (vcalendarElement == null)
114: throw new SyntaxException(
115: "element name <vcalendar> expected");
116:
117: componentElement = vcalendarElement.getChild(ICALENDAR.VEVENT);
118: if (componentElement == null)
119: componentElement = vcalendarElement
120: .getChild(ICALENDAR.VTODO);
121:
122: if (componentElement == null)
123: throw new SyntaxException(
124: "wrong component type. Must be either <vevent> or <vtodo>.");
125:
126: parentElement = componentElement;
127: }
128:
129: public String getComponentType() {
130: return componentElement.getName();
131: }
132:
133: /**
134: * @see org.columba.calendar.model.api.IBasicDocumentModel#getRootElement()
135: */
136: public Element getRootElement() {
137: return root;
138: }
139:
140: /**
141: * @see org.columba.calendar.model.api.IBasicModel#set(java.lang.String,
142: * java.lang.String)
143: */
144: protected void set(String key, String value) {
145: Element child = getParentElement().getChild(key);
146: if (child == null) {
147: child = new Element(key);
148: getParentElement().addContent(child);
149: }
150: child.setText(value);
151: }
152:
153: /**
154: * @see org.columba.calendar.model.api.IBasicModel#set(java.lang.String,
155: * java.lang.String, java.lang.String)
156: */
157: protected void set(String key, String prefix, String value) {
158: Element child = getParentElement().getChild(key);
159: if (child == null) {
160: child = new Element(key);
161: getParentElement().addContent(child);
162: }
163: Element prefixchild = child.getChild(prefix);
164: if (prefixchild == null) {
165: prefixchild = new Element(prefix);
166: child.addContent(prefixchild);
167: }
168: prefixchild.setText(value);
169: }
170:
171: /**
172: * @see org.columba.calendar.model.api.IBasicModel#get(java.lang.String)
173: */
174: protected String get(String key) {
175: Element child = getParentElement().getChild(key);
176: if (child == null) {
177: child = new Element(key);
178: getParentElement().addContent(child);
179: }
180: return child.getTextNormalize();
181: }
182:
183: /**
184: * @see org.columba.calendar.model.api.IBasicModel#get(java.lang.String,
185: * java.lang.String)
186: */
187: protected String get(String key, String prefix) {
188: Element child = getParentElement().getChild(key);
189: if (child == null) {
190: child = new Element(key);
191: getParentElement().addContent(child);
192: }
193: Element prefixchild = child.getChild(prefix);
194: if (prefixchild == null) {
195: prefixchild = new Element(prefix);
196: child.addContent(prefixchild);
197: }
198:
199: return prefixchild.getTextNormalize();
200: }
201:
202: /**
203: * @see org.columba.calendar.model.api.IBasicModel#getDocument()
204: */
205: public Document getDocument() {
206: return doc;
207: }
208:
209: /**
210: * @return Returns the id.
211: */
212: public String getId() {
213: return get(ICALENDAR.UID);
214: }
215:
216: public void setId(String id) {
217: set(ICALENDAR.UID, id);
218: }
219:
220: /**
221: * @return Returns the parentElement.
222: */
223: protected Element getParentElement() {
224: return parentElement;
225: }
226:
227: public void setSummary(String s) {
228: set(ICALENDAR.SUMMARY, s);
229: }
230:
231: public String getSummary() {
232: return get(ICALENDAR.SUMMARY);
233: }
234:
235: public void setDescription(String s) {
236: set(ICALENDAR.DESCRIPTION, s);
237: }
238:
239: public String getDescription() {
240: return get(ICALENDAR.DESCRIPTION);
241: }
242:
243: public void setCalendar(String s) {
244: set(ICALENDAR.X_COLUMBA_CALENDAR, s);
245: }
246:
247: public String getCalendar() {
248: return get(ICALENDAR.X_COLUMBA_CALENDAR);
249: }
250:
251: public void setPriority(String s) {
252: set(ICALENDAR.PRIORITY, s);
253: }
254:
255: public String getPriority() {
256: return get(ICALENDAR.PRIORITY);
257: }
258:
259: public void setEventClass(String s) {
260: set(ICALENDAR.CLASS, s);
261: }
262:
263: public String getEventClass() {
264: return get(ICALENDAR.CLASS);
265: }
266:
267: public void setLocation(String s) {
268: set(ICALENDAR.LOCATION, s);
269: }
270:
271: public String getLocation() {
272: return get(ICALENDAR.LOCATION);
273: }
274:
275: public void setDTStart(Calendar c) {
276: set(ICALENDAR.DTSTART, DateParser.createStringFromCalendar(c));
277: }
278:
279: public Calendar getDTStart() {
280: String s = get(ICALENDAR.DTSTART);
281: Calendar c;
282: try {
283: c = DateParser.createCalendarFromString(s);
284: return c;
285: } catch (IllegalArgumentException e) {
286: LOG.severe("date parsing exception");
287:
288: e.printStackTrace();
289: }
290:
291: return Calendar.getInstance();
292: }
293:
294: public void setDTEnd(Calendar c) {
295: set(ICALENDAR.DTEND, DateParser.createStringFromCalendar(c));
296: }
297:
298: public Calendar getDTEnd() {
299: String s = get(ICALENDAR.DTEND);
300: Calendar c;
301: try {
302: c = DateParser.createCalendarFromString(s);
303: return c;
304: } catch (IllegalArgumentException e) {
305: LOG.severe("date parsing exception");
306:
307: e.printStackTrace();
308: }
309:
310: return Calendar.getInstance();
311: }
312:
313: public void setDTStamp(Calendar c) {
314: set(ICALENDAR.DTSTAMP, DateParser.createStringFromCalendar(c));
315: }
316:
317: public Calendar getDTStamp() {
318: String s = get(ICALENDAR.DTSTAMP);
319:
320: Calendar c;
321: try {
322: c = DateParser.createCalendarFromString(s);
323: return c;
324: } catch (IllegalArgumentException e) {
325: LOG.severe("date parsing exception");
326:
327: e.printStackTrace();
328: }
329:
330: return Calendar.getInstance();
331: }
332:
333: public void addCategory(String category) {
334: set(ICALENDAR.CATEGORIES, ICALENDAR.ITEM, category);
335: }
336:
337: public void removeCategory(String category) {
338: Element child = getParentElement().getChild(
339: ICALENDAR.CATEGORIES);
340: List list = child.getChildren();
341: for (int i = 0; i < list.size(); i++) {
342: Element e = (Element) list.get(i);
343: if (e.getText().equals(category)) {
344: // found category
345: child.removeContent(e);
346: }
347: }
348: }
349:
350: public Enumeration getCategoryEnumeration() {
351: //Element child = getParentElement().getChild(ICALENDAR.CATEGORIES);
352: //List list = child.getChildren();
353:
354: // TODO categoryEnumeration
355: return null;
356: }
357:
358: public RecurrenceRule getRecurrenceRule() {
359: // RRULE:FREQ=YEARLY;COUNT=5;INTERVAL=1
360: // RRULE:FREQ=WEEKLY;UNTIL=20060725T215959;INTERVAL=1;BYDAY=TU
361: // RRULE:FREQ=YEARLY;INTERVAL=1
362: String rrule = get(ICALENDAR.RRULE);
363: String freqS = getRValue(rrule, "FREQ");
364: String intervalS = getRValue(rrule, "INTERVAL");
365: String countS = getRValue(rrule, "COUNT");
366: String untilS = getRValue(rrule, "UNTIL");
367: int freq = -1;
368: int interval = -1;
369: int count = -1;
370: Calendar untildate = null;
371: try {
372: if (freqS.equals("YEARLY"))
373: freq = Recurrence.RECURRENCE_ANNUALLY;
374: else if (freqS.equals("MONTHLY"))
375: freq = Recurrence.RECURRENCE_MONTHLY;
376: else if (freqS.equals("WEEKLY"))
377: freq = Recurrence.RECURRENCE_WEEKLY;
378: else if (freqS.equals("DAILY"))
379: freq = Recurrence.RECURRENCE_DAILY;
380:
381: /*
382: else if (freqS.equals("HOURLY"))
383: freq = Recurrence.RECURRENCE_HOURLY;
384: else if (freqS.equals("MINUTELY"))
385: freq = Recurrence.RECURRENCE_HOURLY;
386: else if (freqS.equals("SECONDLY"))
387: freq = Recurrence.RECURRENCE_SECONDLY;
388: */
389:
390: if (intervalS.length() > 0)
391: interval = Integer.parseInt(intervalS);
392: if (countS.length() > 0)
393: count = Integer.parseInt(countS);
394: if (untilS.length() > 0)
395: try {
396: untildate = DateParser
397: .createCalendarFromDateString(untilS);
398: } catch (IllegalArgumentException e) {
399: LOG
400: .severe("getRecurrenceRule: date parsing exception");
401: }
402: } catch (NumberFormatException e) {
403: LOG.severe("getRecurrenceRule: number parsing exception");
404: }
405:
406: if (freq < 0)
407: return null;
408:
409: RecurrenceRule r = new RecurrenceRule();
410: r.setFrequency(Recurrence.toFrequency(freq));
411: if (interval > -1)
412: r.setInterval(interval);
413: if (count > -1)
414: r.setRepetitionCount(count);
415: if (untildate != null)
416: r.setUntilDate(untildate);
417: return r;
418: }
419:
420: public static String getRValue(String rrule, String property) {
421: // find the property in the rrule string
422: String irrule = rrule.toLowerCase();
423: String iproperty = property.toLowerCase() + "=";
424: String DELIMITER = ";";
425: if (irrule.indexOf(iproperty) > -1) {
426: int valuestart = irrule.indexOf(iproperty)
427: + iproperty.length();
428: int valueend = irrule.indexOf(DELIMITER, valuestart);
429: if (valueend < 0)
430: valueend = irrule.length();
431: return rrule.substring(valuestart, valueend);
432: }
433: return "";
434: }
435:
436: public void setRecurrenceRule(RecurrenceRule r) {
437:
438: // no recurrency, so nothing in the string
439: if (r == null) {
440: set(ICALENDAR.RRULE, "");
441: return;
442: }
443:
444: // build string
445: String freqString = null;
446: switch (r.getFrequency()) {
447: case Calendar.YEAR:
448: freqString = "YEARLY";
449: break;
450: case Calendar.MONTH:
451: freqString = "MONTHLY";
452: break;
453: case Calendar.WEEK_OF_YEAR:
454: freqString = "WEEKLY";
455: break;
456: case Calendar.DAY_OF_YEAR:
457: freqString = "DAILY";
458: break;
459: case Calendar.HOUR:
460: freqString = "HOURLY";
461: break;
462: case Calendar.MINUTE:
463: freqString = "MINUTELY";
464: break;
465: case Calendar.SECOND:
466: freqString = "SECONDLY";
467: }
468: if (freqString == null)
469: throw new IllegalArgumentException("freqString = null");
470:
471: if (r.getByXXXRules() != null) {
472: for (int i = 0; i < r.getByXXXRules().length; i++) {
473: ByXXXRuleData rr = r.getByXXXRules()[i];
474: System.out.println("weekdayiny = "
475: + rr.getRelativeWeekDayInYearOrMonth());
476: for (int j = 0; j < rr.getValues().length; j++) {
477: System.out.println(" value " + j + " = "
478: + rr.getValues()[j]);
479: }
480: System.out.println("calendarfield = "
481: + rr.getCalendarField());
482: }
483: }
484:
485: String rruleString = "FREQ=" + freqString;
486: // optional parts
487: if (r.getRepetitionCount() != null)
488: rruleString += ";COUNT=" + r.getRepetitionCount();
489: if (r.getInterval() > 0)
490: rruleString += ";INTERVAL=" + r.getInterval();
491: if (r.getUntilDate() != null)
492: //UNTIL=20070627T215959
493: rruleString += ";UNTIL=" + dateString(r.getUntilDate());
494:
495: set(ICALENDAR.RRULE, rruleString);
496: }
497:
498: private String dateString(Calendar d) {
499: String s = "";
500: s += d.get(Calendar.YEAR);
501: s += (d.get(Calendar.MONTH) < Calendar.OCTOBER ? "0"
502: + (d.get(Calendar.MONTH) + 1)
503: : d.get(Calendar.MONTH) + 1);
504: s += d.get(Calendar.DAY_OF_MONTH);
505: s += "T";
506: s += (d.get(Calendar.HOUR_OF_DAY) < 10 ? "0"
507: + d.get(Calendar.HOUR_OF_DAY) : d
508: .get(Calendar.HOUR_OF_DAY));
509: s += (d.get(Calendar.MINUTE) < 10 ? "0"
510: + d.get(Calendar.MINUTE) : d.get(Calendar.MINUTE));
511: s += (d.get(Calendar.SECOND) < 10 ? "0"
512: + d.get(Calendar.SECOND) : d.get(Calendar.SECOND));
513: return s;
514: }
515:
516: public void setCategories(String categories) {
517: set(ICALENDAR.CATEGORIES, categories);
518: }
519:
520: public String getCategories() {
521: return get(ICALENDAR.CATEGORIES);
522: }
523:
524: }
|