/* * Copyright (C) 2007 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 android.pim; import android.content.ContentValues; import android.database.Cursor; import android.os.Bundle; import android.provider.Calendar; import android.text.TextUtils; import android.text.format.Time; import android.util.Config; import android.util.Log; import java.util.List; /** * Basic information about a recurrence, following RFC 2445 Section 4.8.5. * Contains the RRULEs, RDATE, EXRULEs, and EXDATE properties. */ public class RecurrenceSet { private final static String TAG = "CalendarProvider"; private final static String RULE_SEPARATOR = "\n"; // TODO: make these final? public EventRecurrence[] rrules = null; public long[] rdates = null; public EventRecurrence[] exrules = null; public long[] exdates = null; /** * Creates a new RecurrenceSet from information stored in the * events table in the CalendarProvider. * @param values The values retrieved from the Events table. */ public RecurrenceSet(ContentValues values) throws EventRecurrence.InvalidFormatException { String rruleStr = values.getAsString(Calendar.Events.RRULE); String rdateStr = values.getAsString(Calendar.Events.RDATE); String exruleStr = values.getAsString(Calendar.Events.EXRULE); String exdateStr = values.getAsString(Calendar.Events.EXDATE); init(rruleStr, rdateStr, exruleStr, exdateStr); } /** * Creates a new RecurrenceSet from information stored in a database * {@link Cursor} pointing to the events table in the * CalendarProvider. The cursor must contain the RRULE, RDATE, EXRULE, * and EXDATE columns. * * @param cursor The cursor containing the RRULE, RDATE, EXRULE, and EXDATE * columns. */ public RecurrenceSet(Cursor cursor) throws EventRecurrence.InvalidFormatException { int rruleColumn = cursor.getColumnIndex(Calendar.Events.RRULE); int rdateColumn = cursor.getColumnIndex(Calendar.Events.RDATE); int exruleColumn = cursor.getColumnIndex(Calendar.Events.EXRULE); int exdateColumn = cursor.getColumnIndex(Calendar.Events.EXDATE); String rruleStr = cursor.getString(rruleColumn); String rdateStr = cursor.getString(rdateColumn); String exruleStr = cursor.getString(exruleColumn); String exdateStr = cursor.getString(exdateColumn); init(rruleStr, rdateStr, exruleStr, exdateStr); } public RecurrenceSet(String rruleStr, String rdateStr, String exruleStr, String exdateStr) throws EventRecurrence.InvalidFormatException { init(rruleStr, rdateStr, exruleStr, exdateStr); } private void init(String rruleStr, String rdateStr, String exruleStr, String exdateStr) throws EventRecurrence.InvalidFormatException { if (!TextUtils.isEmpty(rruleStr) || !TextUtils.isEmpty(rdateStr)) { if (!TextUtils.isEmpty(rruleStr)) { String[] rruleStrs = rruleStr.split(RULE_SEPARATOR); rrules = new EventRecurrence[rruleStrs.length]; for (int i = 0; i < rruleStrs.length; ++i) { EventRecurrence rrule = new EventRecurrence(); rrule.parse(rruleStrs[i]); rrules[i] = rrule; } } if (!TextUtils.isEmpty(rdateStr)) { rdates = parseRecurrenceDates(rdateStr); } if (!TextUtils.isEmpty(exruleStr)) { String[] exruleStrs = exruleStr.split(RULE_SEPARATOR); exrules = new EventRecurrence[exruleStrs.length]; for (int i = 0; i < exruleStrs.length; ++i) { EventRecurrence exrule = new EventRecurrence(); exrule.parse(exruleStr); exrules[i] = exrule; } } if (!TextUtils.isEmpty(exdateStr)) { exdates = parseRecurrenceDates(exdateStr); } } } /** * Returns whether or not a recurrence is defined in this RecurrenceSet. * @return Whether or not a recurrence is defined in this RecurrenceSet. */ public boolean hasRecurrence() { return (rrules != null || rdates != null); } /** * Parses the provided RDATE or EXDATE string into an array of longs * representing each date/time in the recurrence. * @param recurrence The recurrence to be parsed. * @return The list of date/times. */ public static long[] parseRecurrenceDates(String recurrence) { // TODO: use "local" time as the default. will need to handle times // that end in "z" (UTC time) explicitly at that point. String tz = Time.TIMEZONE_UTC; int tzidx = recurrence.indexOf(";"); if (tzidx != -1) { tz = recurrence.substring(0, tzidx); recurrence = recurrence.substring(tzidx + 1); } Time time = new Time(tz); String[] rawDates = recurrence.split(","); int n = rawDates.length; long[] dates = new long[n]; for (int i = 0; i properties = component.getProperties(name); if (properties == null || properties.isEmpty()) { return null; } if (properties.size() == 1) { return properties.get(0).getValue(); } StringBuilder sb = new StringBuilder(); boolean first = true; for (ICalendar.Property property : component.getProperties(name)) { if (first) { first = false; } else { // TODO: use commas. our RECUR parsing should handle that // anyway. sb.append(RULE_SEPARATOR); } sb.append(property.getValue()); } return sb.toString(); } private static String extractDates(ICalendar.Property recurrence) { if (recurrence == null) { return null; } ICalendar.Parameter tzidParam = recurrence.getFirstParameter("TZID"); if (tzidParam != null) { return tzidParam.value + ";" + recurrence.getValue(); } return recurrence.getValue(); } }