blob: 443018e3b1b836c0962a4c8829a2ca78856810d9 [file] [log] [blame]
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mms.activity;
import com.google.android.mms.util.SqliteWrapper;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.Calendar;
import android.provider.Calendar.Calendars;
import android.syncml.pim.PropertyNode;
import android.syncml.pim.VDataBuilder;
import android.syncml.pim.VNode;
import android.syncml.pim.vcalendar.CalendarStruct;
import android.syncml.pim.vcalendar.VCalComposer;
import android.syncml.pim.vcalendar.VCalException;
import android.syncml.pim.vcalendar.VCalParser;
import android.text.format.Time;
import android.util.Log;
import java.util.HashMap;
import java.util.Set;
/**
* Provides the methods to handle the content provider of calendars for MMS activity client.
*/
public class VCalManager {
private static final String TAG = "VCalManager";
private static final String TIME_FORMAT_STRING = "%Y-%m-%d %H:%M:%S";
private ContentValues mVCalValues;
private final Context mContext;
private final ContentResolver mResolver;
private Uri mUri;
private HashMap<String, Long> mCalendars = null;
/**
* Constructor.
* @param context the context of the activity.
* @param data Calendar data.
* @throws IllegalArgumentException
*/
public VCalManager(Context context, String data) throws IllegalArgumentException {
if (context == null) {
throw new IllegalArgumentException();
}
mContext = context;
mResolver = mContext.getContentResolver();
mVCalValues = parseVCalendar(data);
}
/**
* Constructor.
* @param context the context of the activity.
* @param uri the stored event URI.
*/
public VCalManager(Context context, Uri uri) {
mContext = context;
mResolver = mContext.getContentResolver();
mUri = uri;
}
public String[] getCalendars() {
if (mCalendars == null) {
Cursor cursor = SqliteWrapper.query(mContext, mResolver, Calendars.CONTENT_URI,
new String[] {Calendars._ID, Calendars.DISPLAY_NAME},
null, null, null);
if (null == cursor) {
return null;
}
mCalendars = new HashMap<String, Long>();
try {
while (cursor.moveToNext()) {
long id = cursor.getLong(cursor.getColumnIndexOrThrow(Calendars._ID));
String name = cursor.getString(cursor.getColumnIndexOrThrow(Calendars.DISPLAY_NAME));
mCalendars.put(name, id);
}
} finally {
cursor.close();
}
}
Set<String> keySet = mCalendars.keySet();
int size = keySet.size();
if (size <= 0) {
return null;
}
String[] calendarArray = new String[size];
keySet.toArray(calendarArray);
return calendarArray;
}
/**
* Load the formatted data of the stored calendar event.
* @return the formatted data string.
*/
public String getData() {
if (mUri == null) {
Log.e(TAG, "Bad content URI.");
return null;
}
Cursor c = SqliteWrapper.query(mContext, mResolver, mUri,
null, null, null, null);
String uid = mUri.toString();
if (c == null) {
Log.e(TAG, "Cannot query the content from " + mUri);
return null;
}
try {
c.moveToFirst();
CalendarStruct calStruct = new CalendarStruct();
calStruct.timezone = c.getString(c.getColumnIndexOrThrow(Calendar.Events.EVENT_TIMEZONE));
//event list:
CalendarStruct.EventStruct evtStruct = new CalendarStruct.EventStruct();
evtStruct.uid = uid;
evtStruct.description = c.getString(c.getColumnIndexOrThrow(
Calendar.Events.DESCRIPTION));
evtStruct.dtend = convertLongToRFC2445DateTime(c.getLong(c.getColumnIndexOrThrow(
Calendar.Events.DTEND)));
evtStruct.dtstart = convertLongToRFC2445DateTime(c.getLong(c.getColumnIndexOrThrow(
Calendar.Events.DTSTART)));
evtStruct.duration = c.getString(c.getColumnIndexOrThrow(
Calendar.Events.DURATION));
evtStruct.event_location = c.getString(c.getColumnIndexOrThrow(
Calendar.Events.EVENT_LOCATION));
evtStruct.has_alarm = c.getString(c.getColumnIndexOrThrow(
Calendar.Events.HAS_ALARM));
evtStruct.last_date = convertLongToRFC2445DateTime(c.getLong(c.getColumnIndexOrThrow(
Calendar.Events.LAST_DATE)));
evtStruct.rrule = c.getString(c.getColumnIndexOrThrow(
Calendar.Events.RRULE));
evtStruct.status = c.getString(c.getColumnIndexOrThrow(
Calendar.Events.STATUS));
evtStruct.title = c.getString(c.getColumnIndexOrThrow(
Calendar.Events.TITLE));
if (!isNull(evtStruct.has_alarm)) {
getReminders(evtStruct, Uri.parse(uid).getLastPathSegment());
}
calStruct.addEventList(evtStruct);
try{ //build vcalendar:
VCalComposer composer = new VCalComposer();
return composer.createVCal(calStruct, VCalComposer.VERSION_VCAL10_INT);
} catch (Exception e) {
return null;
}
} finally {
c.close();
}
}
/**
* Get the name of the calendar event with ".vcs" suffix.
* @return the name of the calendar event.
*/
public String getName() {
if (mUri == null) {
Log.e(TAG, "Bad content URI.");
return null;
}
Cursor c = SqliteWrapper.query(mContext, mResolver, mUri,
null, null, null, null);
if (c == null) {
Log.e(TAG, "Cannot query the content from " + mUri);
return null;
}
try {
c.moveToFirst();
return c.getString(c.getColumnIndexOrThrow(Calendar.Events.TITLE)) + ".vcs";
} finally {
c.close();
}
}
/**
* Save the calendar data to local database.
*
* @param calendarName the calendar into which the vCal is saved.
* By calling method getCalendars(), user can get all calendar
* names as an string array.
* @return true if success, otherwise return false.
*/
public Uri save(String calendarName) {
Long id = mCalendars.get(calendarName);
if (null == id) {
return null;
}
mVCalValues.put(Calendar.Events.CALENDAR_ID, id);
return SqliteWrapper.insert(mContext, mResolver,
Calendar.Events.CONTENT_URI, mVCalValues);
}
/**
* Get the title of the calendar event.
* @return the title.
*/
public String getTitle() {
return (String) mVCalValues.get(Calendar.Events.TITLE);
}
/**
* Get the event location of the calendar event.
* @return the event location.
*/
public String getEventLocation() {
return (String) mVCalValues.get(Calendar.Events.EVENT_LOCATION);
}
/**
* Get the description of the calendar event.
* @return the description.
*/
public String getDescription() {
return (String) mVCalValues.get(Calendar.Events.DESCRIPTION);
}
/**
* Get the start time of the calendar event.
* @return the start time formatted as "%Y-%m-%d %H:%M:%S".
*/
public String getDateTimeStart() {
Long start = (Long) mVCalValues.get(Calendar.Events.DTSTART);
if (start == null) {
return null;
}
Time time = new Time();
time.set(start);
return time.format(TIME_FORMAT_STRING);
}
/**
* Get the end time of the calendar event.
* @return the end time formatted as "%Y-%m-%d %H:%M:%S".
*/
public String getDateTimeEnd() {
Long end = (Long) mVCalValues.get(Calendar.Events.DTEND);
if (end == null) {
return null;
}
Time time = new Time();
time.set(end);
return time.format(TIME_FORMAT_STRING);
}
/**
* Get the duration of the calendar event.
* @return the duration which is NOT formatted as "%Y-%m-%d %H:%M:%S".
*/
public String getDuration() {
return (String) mVCalValues.get(Calendar.Events.DURATION);
}
/**
* Get the rule of the calendar event.
* @return the rule.
*/
public String getRepeatRule() {
return (String) mVCalValues.get(Calendar.Events.RRULE);
}
/**
* Get the completed time of the calendar event.
* @return the completed time formatted as "%Y-%m-%d %H:%M:%S".
*/
public String getCompleted() {
Long complete = (Long) mVCalValues.get(Calendar.Events.LAST_DATE);
if (complete == null) {
return null;
}
Time time = new Time();
time.set(complete);
return time.format(TIME_FORMAT_STRING);
}
private ContentValues parseVCalendar(String data) {
VCalParser parser = new VCalParser();
VDataBuilder builder = new VDataBuilder();
if (null == data) {
return null;
}
try {
parser.parse(data, builder);
} catch (VCalException e) {
Log.e(TAG, "VCalException: ", e);
return null;
}
String curCalendarId = "";
for (VNode vnode : builder.vNodeList) {
// VCALENDAR field MUST present before VENENT and VTODO
if (vnode.VName.equalsIgnoreCase("VCALENDAR")) {
// If no Calendar, just set -1 as CalendarId, because user
// should view the content even if no calendar created.
curCalendarId = String.valueOf(getFirstIDFromCalendar());
} else if (vnode.VName.equalsIgnoreCase("VEVENT") ||
vnode.VName.equalsIgnoreCase("VTODO")) {
return setEventMap(vnode, curCalendarId);
}
}
return null;
}
private static ContentValues setEventMap(VNode vnode, String calId) {
ContentValues values = new ContentValues();
values.put(Calendar.Events.CALENDAR_ID, calId);
for (PropertyNode prop : vnode.propList) {
if (prop.propValue != null) {
Time time = new Time();
if (prop.propName.equalsIgnoreCase("DESCRIPTION")) {
values.put(Calendar.Events.DESCRIPTION, prop.propValue);
} else if (prop.propName.equalsIgnoreCase("DTEND")) {
time.parse(prop.propValue);
values.put(Calendar.Events.DTEND, time.toMillis(false /* use isDst */));
} else if (prop.propName.equalsIgnoreCase("DTSTART")) {
time.parse(prop.propValue);
values.put(Calendar.Events.DTSTART, time.toMillis(false /* use isDst */));
} else if (prop.propName.equalsIgnoreCase("SUMMARY")) {
values.put(Calendar.Events.TITLE, prop.propValue);
} else if (prop.propName.equalsIgnoreCase("LOCATION")) {
values.put(Calendar.Events.EVENT_LOCATION, prop.propValue);
} else if (prop.propName.equalsIgnoreCase("DUE")) {
values.put(Calendar.Events.DURATION, prop.propValue);
} else if (prop.propName.equalsIgnoreCase("RRULE")) {
values.put(Calendar.Events.RRULE, prop.propValue);
} else if (prop.propName.equalsIgnoreCase("COMPLETED")) {
time.parse(prop.propValue);
values.put(Calendar.Events.LAST_DATE, time.toMillis(false /* use isDst */));
}
}
}
return values;
}
private static boolean isNull(String str) {
if ((str == null) || str.trim().equals("")) {
return true;
}
return false;
}
private static String convertLongToRFC2445DateTime(long mills) {
Time time = new Time();
time.set(mills);
return time.format("%Y%m%dT%H%M%SZ");
}
private void getReminders(CalendarStruct.EventStruct evtStruct, String localid) {
Cursor c = SqliteWrapper.query(mContext, mResolver, Calendar.Reminders.CONTENT_URI,
null, "event_id=" + localid, null, null);
String data = "";
while ((c != null) && c.moveToNext()) {
data = c.getString(c.getColumnIndexOrThrow(Calendar.Reminders.METHOD));
evtStruct.addReminderList(data);
}
if (c != null) {
c.close();
}
}
private int getFirstIDFromCalendar() {
Cursor c = SqliteWrapper.query(mContext, mResolver, Calendar.Calendars.CONTENT_URI,
null, null, null, null);
if (c != null) {
while (c.moveToNext()) {
int id = c.getInt(c.getColumnIndexOrThrow("_id"));
c.close();
return id;
}
c.close();
}
return -1;
}
}