/* * * Created on August 3, 2002, 9:01 PM * * Stores an icalendar Time Zone as a java object. * There can be more than one iCal time zone per Calendar. * To make it easy, all times are recorded as GMT. * */ package org.jical; /** * * @author sfg RFC 2445 * @author David Wellington * */ import java.io.ByteArrayInputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * @hibernate.class * table="ICALVEVENT" * dynamic-update="false" * dynamic-insert="false" * * @hibernate.discriminator * column="class" */ public class ICalendarVEvent implements Cloneable { private static SimpleDateFormat localDateFormatter = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); private static SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss"); private static final SimpleDateFormat VEVENTformatter = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'"); private Date dateStamp; private String organizer; private String organizerEmail; private Date created; private Date lastModified; private int priority; private String attach; private String location; private String percentComplete; private String status; private String comment; private boolean recurrenceId; private String url; private String geo; private float geoX; private float geoY; private String resources; private String contact; private String relatedTo; private String requestStatus; private String id; /** * * @hibernate.id * generator-class="uuid.hex" * column="ID" * * @hibernate.column * name="ID" * sql-type="VARCHAR(255)" * */ public String getId() { return this.id; } public void setId(String id) { this.id = id; } private String uid; /** * * @hibernate.property * column="UID" * * @hibernate.column * name="uid" * sql-type="VARCHAR(255)" * */ public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } private String transparency; /** * * @hibernate.property * column="TRANSPARENCY" * * @hibernate.column * name="transparency" * sql-type="VARCHAR(255)" * */ public String getTransparency() { return this.transparency; } public void setTransparency(String transparency) { this.transparency = transparency; } private Date dateStart; /** * * @hibernate.property * column="DATE_START" * * @hibernate.column * name="dateStart" * sql-type="TIMESTAMP" * */ public Date getDateStart() { return this.dateStart; } public void setDateStart(Date dateStart) { this.dateStart = dateStart; } private Date dateEnd; /** * * @hibernate.property * column="DATE_END" * * @hibernate.column * name="dateEnd" * sql-type="TIMESTAMP" * */ public Date getDateEnd() { return this.dateEnd; } public void setDateEnd(Date dateEnd) { this.dateEnd = dateEnd; } private String duration; /** Getter for property duration. /** * * @hibernate.property * column="DURATION" * * @hibernate.column * name="duration" * sql-type="VARCHAR(255)" * */ public String getDuration() { return this.duration; } public void setDuration(String duration) { this.duration = duration; /* * Currently, use this duration to create a DateEnd. This is not optimal * but works for Apple iCal and is strictly true. */ if (getDateStart() != null && getDateEnd() == null) { //System.err.println("Generating a DateEnd"); // PT15M char durationArray[] = duration.substring(2).toCharArray(); // Now read each char and build up numerics into a number and // non-numerics // indicate a unit of time. Convert all units of time into secs then // add // to the result. String timeBuilt = ""; int totalSecs = 0; for (int ctr = 0; ctr < durationArray.length; ctr++) { String thisChar = String.valueOf(durationArray[ctr]); // Is this a number or a letter. int timeUnit = thisChar.indexOf("HMS"); if (timeUnit != -1) { // This is a time unit! Multiply by seconds if (timeUnit == 0) totalSecs = totalSecs + Integer.parseInt(timeBuilt) * 3600; if (timeUnit == 1) totalSecs = totalSecs + Integer.parseInt(timeBuilt) * 60; if (timeUnit == 2) totalSecs = totalSecs + Integer.parseInt(timeBuilt); timeBuilt = ""; } else { // Build up total time for time unit. timeBuilt = timeBuilt.concat(thisChar); } } // Now adjust the dateEnd to dateStart + secs. int dateRepeatUnit = Calendar.SECOND; Calendar workDateEnd = new GregorianCalendar(); workDateEnd.setTime(getDateStart()); workDateEnd.add(dateRepeatUnit, totalSecs); setDateEnd(workDateEnd.getTime()); } } private String description; /** * * @hibernate.property * column="DESCRIPTION" * * @hibernate.column * name="description" * sql-type="VARCHAR(255)" * */ public String getDescription() { return this.description; } public void setDescription(String description) { this.description = description; } private String summary; /** * * @hibernate.property * column="SUMMARY" * * @hibernate.column * name="summary" * sql-type="VARCHAR(255)" * */ public String getSummary() { return this.summary; } public void setSummary(String summary) { this.summary = summary; } private int sequence; /** * * @hibernate.property * column="SEQUENCE" * * @hibernate.column * name="sequence" * sql-type="INTEGER" * */ public int getSequence() { return this.sequence; } public void setSequence(int sequence) { this.sequence = sequence; } private String categories; /** * * @hibernate.property * column="CATEGORIES" * * @hibernate.column * name="categories" * sql-type="VARCHAR(255)" * */ public String getCategories() { return this.categories; } public void setCategories(String categories) { this.categories = categories; } private String eventClass; /** * * @hibernate.property * column="CLASS_OF_EVENT" * * @hibernate.column * name="classOfEvent" * sql-type="VARCHAR(255)" * */ public String getEventClass() { return this.eventClass; } public void setEventClass(String eventClass) { this.eventClass = eventClass; //System.err.println("icalevent>>" +eventClass); } private String rRule; /** * * @hibernate.property * column="RRULE" * * @hibernate.column * name="rrule" * sql-type="VARCHAR(255)" * */ public String getRRule() { return this.rRule; } public void setRRule(String rRule) { this.rRule = rRule; } private int repeatCount; /** * * @hibernate.property * column="REPEAT_COUNT" * * @hibernate.column * name="repeatCount" * sql-type="INTEGER" * */ public int getRepeatCount() { return this.repeatCount; } public void setRepeatCount(int repeatCount) { this.repeatCount = repeatCount; } public Collection exDateCollection; public Collection getExDateCollection() { return this.exDateCollection; } public void setExDateCollection(Collection exDateCollection) { this.exDateCollection = exDateCollection; } private boolean exDatesExist; /** * * @hibernate.property * column="EXDATES_EXIST" * * @hibernate.column * name="exDatesExist" * sql-type="Boolean" * */ public boolean isExDatesExist() { return this.exDatesExist; } public void setExDatesExist(boolean exDatesExist) { this.exDatesExist = exDatesExist; } /** Holds value of property repeatRules. */ private RepeatRules repeatRules; /** Getter for property repeatRules. * @return Value of property repeatRules. * */ public RepeatRules getRepeatRules() { return this.repeatRules; } /** Setter for property repeatRules. * @param repeatRules New value of property repeatRules. * */ public void setRepeatRules(RepeatRules repeatRules) { this.repeatRules = repeatRules; } public ICalendarVEvent() { this.exDateCollection = new ArrayList(); this.eventClass = null; this.repeatCount = 0; this.repeatRules = new RepeatRules(); this.categories = null; this.dateStart = null; this.dateEnd = null; this.description = null; this.duration = null; this.eventClass = null; this.exDatesExist = false; this.rRule = null; this.sequence = 0; this.summary = null; this.transparency = null; this.uid = null; } public ICalendarVEvent(Date dateStart, Date dateEnd, String description, String duration, String summary, ArrayList exDates, RepeatRules repRules) { this.exDateCollection = exDates; this.eventClass = null; this.repeatCount = 0; this.repeatRules = repRules; this.categories = null; this.dateStart = dateStart; this.dateEnd = dateEnd; this.description = description; this.duration = duration; this.eventClass = null; this.exDatesExist = false; this.rRule = null; this.sequence = 0; this.summary = summary; this.transparency = null; this.uid = null; } public Object clone() throws CloneNotSupportedException { return super.clone(); } /* * To VEVENT * * * This will create a VEVENT if applicable. * * Note there is plenty to be improved here. Not least the rule that wraps lines to 78 chars.. * * BEGIN:VEVENT DTSTAMP:20041029T184718Z ORGANIZER:MAILTO:sfg@eurekait.com CREATED:20041029T021927Z UID:libkcal-2020175830.1064 SEQUENCE:0 LAST-MODIFIED:20041029T021927Z SUMMARY:Hibernate integrate to Claims CLASS:PUBLIC PRIORITY:3 DTSTART:20041028T131500Z DTEND:20041028T223000Z TRANSP:OPAQUE END:VEVENT * */ public String toVEvent() { //VEVENTformatter.setTimeZone(TimeZone.getDefault().getTimeZone("GMT")); StringBuffer vEventBuffer = new StringBuffer(); vEventBuffer.append(ICalUtil.makeVEventLines("BEGIN:VEVENT","")); vEventBuffer.append(ICalUtil.makeVEventLines("UID:",this.uid)); vEventBuffer.append(ICalUtil.makeVEventLines("TRANSP:",this.transparency)); vEventBuffer.append(ICalUtil.makeVEventLines("DTSTART;",getVEventLocalTime(this.dateStart))); vEventBuffer.append(ICalUtil.makeVEventLines("DTEND;",getVEventLocalTime(this.dateEnd))); vEventBuffer.append(ICalUtil.makeVEventLines("DTSTAMP:",VEVENTformatter.format(this.dateStamp))); vEventBuffer.append(ICalUtil.makeVEventLines("ORGANIZER:",this.organizer)); vEventBuffer.append(ICalUtil.makeVEventLines("CREATED:",VEVENTformatter.format(this.created))); vEventBuffer.append(ICalUtil.makeVEventLines("LAST-MODIFIED:",VEVENTformatter.format(this.lastModified))); vEventBuffer.append(ICalUtil.makeVEventLines("SUMMARY:",this.summary)); vEventBuffer.append(ICalUtil.makeVEventLines("DESCRIPTION:",this.description)); vEventBuffer.append(ICalUtil.makeVEventLines("SEQUENCE:",new Integer(this.sequence).toString())); vEventBuffer.append(ICalUtil.makeVEventLines("CLASS:",this.eventClass)); vEventBuffer.append(ICalUtil.makeVEventLines("ATTACH:",this.attach)); vEventBuffer.append(ICalUtil.makeVEventLines("END:VEVENT","")); return vEventBuffer.toString(); } /* * Make this locale dependent... */ public String getVEventLocalTime(Date localTime) { if (localTime!=null) return "VALUE=DATE-TIME;TZID=/softwarestudio.org/Olson_20011030_5/"+TimeZone.getDefault().getID()+":"+localDateFormatter.format(localTime); else return ""; } /* * To XML method Originally built so as to enable a collection of expanded * dates to be created. */ public String toXML() { StringBuffer buffer = new StringBuffer(); buffer.append("<vevent>"); buffer.append("<uid>").append(this.uid).append("</uid>"); // Only add element if it has a value if ( this.transparency != null && this.transparency.length() > 0) { buffer.append("<transparency>"); buffer.append(this.transparency); buffer.append("</transparency>"); } // Add new elements for additional iCal fields added if ( this.location != null && this.location.length() > 0) { buffer.append("<location>"); buffer.append("<![CDATA["); buffer.append(this.location); buffer.append("]]>"); buffer.append("</location>"); } if ( this.url != null && this.url.length() > 0) { buffer.append("<url>"); buffer.append(this.url); buffer.append("</url>"); } if ( this.organizer != null && this.organizer.length() > 0) { buffer.append("<organizer>"); buffer.append(this.organizer); buffer.append("</organizer>"); } if ( this.organizerEmail != null && this.organizerEmail.length() > 0) { buffer.append("<organizeremail>"); buffer.append("<![CDATA["); buffer.append(this.organizerEmail); buffer.append("]]>"); buffer.append("</organizeremail>"); } if ( getStatus() != null && getStatus().length() > 0) { buffer.append("<status>"); buffer.append(getStatus()); buffer.append("</status>"); } buffer.append("<datestart>"); if ( this.dateStart != null ) buffer.append(formatter.format(this.dateStart)); buffer.append("</datestart>"); buffer.append("<dateend>"); if ( this.dateEnd != null ) buffer.append(formatter.format(this.dateEnd)); buffer.append("</dateend>"); if ( this.description != null && this.description.length() > 0) { buffer.append("<description>"); buffer.append("<![CDATA[").append(this.description).append("]]>"); buffer.append("</description>"); } buffer.append("<summary>"); if ( this.summary != null ) buffer.append("<![CDATA[").append(this.summary).append("]]>"); buffer.append("</summary>"); buffer.append("<sequence>"); if ( java.lang.Integer.toString(this.sequence) != null ) buffer.append(java.lang.Integer.toString(this.sequence)); buffer.append("</sequence>"); if ( this.categories != null && this.categories.length() > 0) { buffer.append("<categories>"); buffer.append(this.categories); buffer.append("</categories>"); } if ( this.eventClass != null && this.eventClass.length() > 0) { buffer.append("<eventclass>"); buffer.append(this.eventClass); buffer.append("</eventclass>"); } buffer.append("</vevent>"); return buffer.toString(); } /* * Reads XML back into event class Originally built so as to enable a * collection of expanded dates to be created. */ public void fromXML(String inXML) { try { DocumentBuilderFactory docuBuilderFactory = DocumentBuilderFactory .newInstance(); docuBuilderFactory.setValidating(false); DocumentBuilder docuBuilder = docuBuilderFactory .newDocumentBuilder(); ByteArrayInputStream bais = new ByteArrayInputStream(inXML .getBytes()); Document doc = docuBuilder.parse(bais); NodeList nl = doc.getFirstChild().getChildNodes(); for (int ctr = 0; ctr < nl.getLength(); ctr++) { Node ni = nl.item(ctr); // System.err.println("ctr:" +ctr); String nodeName = ni.getNodeName(); Node nodeChild = ni.getFirstChild(); String nodeValue = ""; try { nodeValue = nodeChild.getNodeValue(); } catch (Exception e) { // Ignore catch, process next.. as NULL } // System.err.println("Node/Value:" +nodeName +nodeValue); if (nodeValue != null) { if (nodeName.equals("uid")) this.setUid(nodeValue); else if (nodeName.equals("transparency")) this.setTransparency(nodeValue); else if (nodeName.equals("datestart")) this.setDateStart((Date) formatter.parse(nodeValue)); else if (nodeName.equals("dateend")) this.setDateEnd((Date) formatter.parse(nodeValue)); else if (nodeName.equals("description")) this.setDescription(nodeValue); else if (nodeName.equals("summary")) this.setSummary(nodeValue); else if (nodeName.equals("categories")) this.setCategories(nodeValue); else if (nodeName.equals("eventclass")) this.setEventClass(nodeValue); // Add new iCal fields else if (nodeName.equals("location")) this.setLocation(nodeValue); else if (nodeName.equals("url")) this.setUrl(nodeValue); else if (nodeName.equals("organizer")) this.setOrganizer(nodeValue); else if (nodeName.equals("organizeremail")) this.setOrganizerEmail(nodeValue); else if (nodeName.equals("status")) this.setPercentComplete(nodeValue); } } } catch (Exception e) { System.err.println("XML Parser exception: fromXML:" + e); } } public boolean equals(Object o) { if (o instanceof ICalendarVEvent) { ICalendarVEvent e = (ICalendarVEvent) o; return uid.equals(e.uid) && dateStart.equals(e.dateStart) && dateEnd.equals(e.dateEnd); } return false; } public int hashCode() { return uid.hashCode() ^ dateStart.hashCode() ^ dateEnd.hashCode(); } public static class StartDateComparator implements Comparator { public int compare(Object o1, Object o2) { ICalendarVEvent e1 = (ICalendarVEvent) o1; ICalendarVEvent e2 = (ICalendarVEvent) o2; return e1.getDateStart().compareTo(e2.getDateStart()); } public boolean equals(Object obj) { return (obj instanceof StartDateComparator); } } public static class StartDateUIDComparator implements Comparator { public int compare(Object o1, Object o2) { ICalendarVEvent e1 = (ICalendarVEvent) o1; ICalendarVEvent e2 = (ICalendarVEvent) o2; int out = e1.getDateStart().compareTo(e2.getDateStart()); if (out == 0) { out = e1.getUid().compareTo(e2.getUid()); } return out; } public boolean equals(Object obj) { return (obj instanceof StartDateUIDComparator); } } /** * * @hibernate.property * column="DATE_CREATED" * * @hibernate.column * name="created" * sql-type="TIMESTAMP" * */ public Date getCreated() { return created; } public void setCreated(Date created) { this.created = created; } /** * * @hibernate.property * column="DATE_STAMP" * * @hibernate.column * name="dateStamp" * sql-type="TIMESTAMP" * */ public Date getDateStamp() { return dateStamp; } public void setDateStamp(Date dateStamp) { this.dateStamp = dateStamp; } /** * * @hibernate.property * column="LAST_MODIFIED" * * @hibernate.column * name="lastModified" * sql-type="TIMESTAMP" * */ public Date getLastModified() { return lastModified; } public void setLastModified(Date lastModified) { this.lastModified = lastModified; } /** * * @hibernate.property * column="ORGANIZER" * * @hibernate.column * name="organizer" * sql-type="VARCHAR" * */ public String getOrganizer() { return organizer; } public void setOrganizer(String organizer) { this.organizer = organizer; } /** * * @hibernate.property * column="PRIORITY" * * @hibernate.column * name="priority" * sql-type="INTEGER" * */ public int getPriority() { return priority; } public void setPriority(int priority) { this.priority = priority; } /** * * @hibernate.property * column="ATTACH" * * @hibernate.column * name="attach" * sql-type="VARCHAR(255)" * */ public String getAttach() { return attach; } public void setAttach(String attach) { this.attach = attach; } /** * * @hibernate.property * column="LOCATION" * * @hibernate.column * name="location" * sql-type="VARCHAR(255)" * */ public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } /** * * @hibernate.property * column="PERCENTCOMPLETE" * * @hibernate.column * name="percentComplete" * sql-type="VARCHAR(255)" * */ public String getPercentComplete() { return percentComplete; } public void setPercentComplete(String percentComplete) { this.percentComplete = percentComplete; } public boolean isRecurrenceId() { return recurrenceId; } public void setRecurrenceId(boolean recurrenceId) { this.recurrenceId = recurrenceId; } /** * * @hibernate.property * column="URL" * * @hibernate.column * name="url" * sql-type="VARCHAR(255)" * */ public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } /** * * @hibernate.property * column="ORGANISEREMAIL" * * @hibernate.column * name="organizerEmail" * sql-type="VARCHAR(255)" * */ public String getOrganizerEmail() { return organizerEmail; } public void setOrganizerEmail(String organizerEmail) { this.organizerEmail = organizerEmail; } public String getStatus() { return status; } public void setStatus(String s) { status = s; } public String getComment() { return comment; } public void setComment(String comment) { this.comment = comment; } public String getGeo() { return geo; } public void setGeo(String geo) { this.geo = geo; } public float getGeoX() { return geoX; } public void setGeoX(float geoX) { this.geoX = geoX; } public float getGeoY() { return geoY; } public void setGeoY(float geoY) { this.geoY = geoY; } public String getResources() { return resources; } public void setResources(String resources) { this.resources = resources; } public String getContact() { return contact; } public void setContact(String contact) { this.contact = contact; } public String getRelatedTo() { return relatedTo; } public void setRelatedTo(String relatedTo) { this.relatedTo = relatedTo; } public String getRequestStatus() { return requestStatus; } public void setRequestStatus(String requestStatus) { this.requestStatus = requestStatus; } }