diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 | 
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 | 
| commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/pim | |
| parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
| download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/pim')
| -rw-r--r-- | core/java/android/pim/ContactsAsyncHelper.java | 336 | ||||
| -rw-r--r-- | core/java/android/pim/DateException.java | 26 | ||||
| -rw-r--r-- | core/java/android/pim/EventRecurrence.java | 421 | ||||
| -rw-r--r-- | core/java/android/pim/ICalendar.java | 643 | ||||
| -rw-r--r-- | core/java/android/pim/RecurrenceSet.java | 398 | ||||
| -rw-r--r-- | core/java/android/pim/package.html | 7 | 
6 files changed, 0 insertions, 1831 deletions
| diff --git a/core/java/android/pim/ContactsAsyncHelper.java b/core/java/android/pim/ContactsAsyncHelper.java deleted file mode 100644 index a21281e..0000000 --- a/core/java/android/pim/ContactsAsyncHelper.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (C) 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 android.pim; - -import com.android.internal.telephony.CallerInfo; -import com.android.internal.telephony.Connection; - -import android.content.ContentUris; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.provider.Contacts; -import android.provider.Contacts.People; -import android.util.Log; -import android.view.View; -import android.widget.ImageView; - -import java.io.InputStream; - -/** - * Helper class for async access of images. - */ -public class ContactsAsyncHelper extends Handler { -     -    private static final boolean DBG = false; -    private static final String LOG_TAG = "ContactsAsyncHelper"; -     -    /** -     * Interface for a WorkerHandler result return. -     */ -    public interface OnImageLoadCompleteListener { -        /** -         * Called when the image load is complete. -         *  -         * @param imagePresent true if an image was found -         */   -        public void onImageLoadComplete(int token, Object cookie, ImageView iView, -                boolean imagePresent); -    } -      -    // constants -    private static final int EVENT_LOAD_IMAGE = 1; -    private static final int DEFAULT_TOKEN = -1; -     -    // static objects -    private static Handler sThreadHandler; -    private static ContactsAsyncHelper sInstance; -     -    static { -        sInstance = new ContactsAsyncHelper(); -    } -     -    private static final class WorkerArgs { -        public Context context; -        public ImageView view; -        public Uri uri; -        public int defaultResource; -        public Object result; -        public Object cookie; -        public OnImageLoadCompleteListener listener; -        public CallerInfo info; -    } -     -    /** -     * public inner class to help out the ContactsAsyncHelper callers  -     * with tracking the state of the CallerInfo Queries and image  -     * loading. -     *  -     * Logic contained herein is used to remove the race conditions -     * that exist as the CallerInfo queries run and mix with the image -     * loads, which then mix with the Phone state changes. -     */ -    public static class ImageTracker { - -        // Image display states -        public static final int DISPLAY_UNDEFINED = 0; -        public static final int DISPLAY_IMAGE = -1; -        public static final int DISPLAY_DEFAULT = -2; -         -        // State of the image on the imageview. -        private CallerInfo mCurrentCallerInfo; -        private int displayMode; -         -        public ImageTracker() { -            mCurrentCallerInfo = null; -            displayMode = DISPLAY_UNDEFINED; -        } - -        /** -         * Used to see if the requested call / connection has a -         * different caller attached to it than the one we currently -         * have in the CallCard.  -         */ -        public boolean isDifferentImageRequest(CallerInfo ci) { -            // note, since the connections are around for the lifetime of the -            // call, and the CallerInfo-related items as well, we can  -            // definitely use a simple != comparison. -            return (mCurrentCallerInfo != ci); -        } -         -        public boolean isDifferentImageRequest(Connection connection) { -            // if the connection does not exist, see if the  -            // mCurrentCallerInfo is also null to match. -            if (connection == null) { -                if (DBG) Log.d(LOG_TAG, "isDifferentImageRequest: connection is null"); -                return (mCurrentCallerInfo != null); -            } -            Object o = connection.getUserData(); - -            // if the call does NOT have a callerInfo attached -            // then it is ok to query. -            boolean runQuery = true; -            if (o instanceof CallerInfo) { -                runQuery = isDifferentImageRequest((CallerInfo) o); -            } -            return runQuery; -        } -         -        /** -         * Simple setter for the CallerInfo object.  -         */ -        public void setPhotoRequest(CallerInfo ci) { -            mCurrentCallerInfo = ci;  -        } -         -        /** -         * Convenience method used to retrieve the URI  -         * representing the Photo file recorded in the attached  -         * CallerInfo Object.  -         */ -        public Uri getPhotoUri() { -            if (mCurrentCallerInfo != null) { -                return ContentUris.withAppendedId(People.CONTENT_URI,  -                        mCurrentCallerInfo.person_id); -            } -            return null;  -        } -         -        /** -         * Simple setter for the Photo state.  -         */ -        public void setPhotoState(int state) { -            displayMode = state; -        } -         -        /** -         * Simple getter for the Photo state.  -         */ -        public int getPhotoState() { -            return displayMode; -        } -    } -     -    /** -     * Thread worker class that handles the task of opening the stream and loading  -     * the images. -     */ -    private class WorkerHandler extends Handler { -        public WorkerHandler(Looper looper) { -            super(looper); -        } -         -        public void handleMessage(Message msg) { -            WorkerArgs args = (WorkerArgs) msg.obj; -             -            switch (msg.arg1) { -                case EVENT_LOAD_IMAGE: -                    InputStream inputStream = Contacts.People.openContactPhotoInputStream( -                            args.context.getContentResolver(), args.uri); -                    if (inputStream != null) { -                        args.result = Drawable.createFromStream(inputStream, args.uri.toString()); - -                        if (DBG) Log.d(LOG_TAG, "Loading image: " + msg.arg1 + -                                " token: " + msg.what + " image URI: " + args.uri); -                    } else { -                        args.result = null; -                        if (DBG) Log.d(LOG_TAG, "Problem with image: " + msg.arg1 +  -                                " token: " + msg.what + " image URI: " + args.uri +  -                                ", using default image."); -                    } -                    break; -                default: -            } -             -            // send the reply to the enclosing class.  -            Message reply = ContactsAsyncHelper.this.obtainMessage(msg.what); -            reply.arg1 = msg.arg1; -            reply.obj = msg.obj; -            reply.sendToTarget(); -        } -    } -     -    /** -     * Private constructor for static class -     */ -    private ContactsAsyncHelper() { -        HandlerThread thread = new HandlerThread("ContactsAsyncWorker"); -        thread.start(); -        sThreadHandler = new WorkerHandler(thread.getLooper()); -    } -     -    /** -     * Convenience method for calls that do not want to deal with listeners and tokens. -     */ -    public static final void updateImageViewWithContactPhotoAsync(Context context,  -            ImageView imageView, Uri person, int placeholderImageResource) { -        // Added additional Cookie field in the callee. -        updateImageViewWithContactPhotoAsync (null, DEFAULT_TOKEN, null, null, context,  -                imageView, person, placeholderImageResource); -    } - -    /** -     * Convenience method for calls that do not want to deal with listeners and tokens, but have -     * a CallerInfo object to cache the image to. -     */ -    public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, Context context,  -            ImageView imageView, Uri person, int placeholderImageResource) { -        // Added additional Cookie field in the callee. -        updateImageViewWithContactPhotoAsync (info, DEFAULT_TOKEN, null, null, context,  -                imageView, person, placeholderImageResource); -    } - -     -    /** -     * Start an image load, attach the result to the specified CallerInfo object. -     * Note, when the query is started, we make the ImageView INVISIBLE if the -     * placeholderImageResource value is -1.  When we're given a valid (!= -1) -     * placeholderImageResource value, we make sure the image is visible. -     */ -    public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, int token,  -            OnImageLoadCompleteListener listener, Object cookie, Context context,  -            ImageView imageView, Uri person, int placeholderImageResource) { -         -        // in case the source caller info is null, the URI will be null as well. -        // just update using the placeholder image in this case. -        if (person == null) { -            if (DBG) Log.d(LOG_TAG, "target image is null, just display placeholder."); -            imageView.setVisibility(View.VISIBLE); -            imageView.setImageResource(placeholderImageResource); -            return; -        } -         -        // Added additional Cookie field in the callee to handle arguments -        // sent to the callback function. -         -        // setup arguments -        WorkerArgs args = new WorkerArgs(); -        args.cookie = cookie; -        args.context = context; -        args.view = imageView; -        args.uri = person; -        args.defaultResource = placeholderImageResource; -        args.listener = listener; -        args.info = info; -         -        // setup message arguments -        Message msg = sThreadHandler.obtainMessage(token); -        msg.arg1 = EVENT_LOAD_IMAGE; -        msg.obj = args; -         -        if (DBG) Log.d(LOG_TAG, "Begin loading image: " + args.uri +  -                ", displaying default image for now."); -         -        // set the default image first, when the query is complete, we will -        // replace the image with the correct one. -        if (placeholderImageResource != -1) { -            imageView.setVisibility(View.VISIBLE); -            imageView.setImageResource(placeholderImageResource); -        } else { -            imageView.setVisibility(View.INVISIBLE); -        } -         -        // notify the thread to begin working -        sThreadHandler.sendMessage(msg); -    } -     -    /** -     * Called when loading is done. -     */ -    @Override -    public void handleMessage(Message msg) { -        WorkerArgs args = (WorkerArgs) msg.obj; -        switch (msg.arg1) { -            case EVENT_LOAD_IMAGE: -                boolean imagePresent = false; - -                // if the image has been loaded then display it, otherwise set default. -                // in either case, make sure the image is visible. -                if (args.result != null) { -                    args.view.setVisibility(View.VISIBLE); -                    args.view.setImageDrawable((Drawable) args.result); -                    // make sure the cached photo data is updated. -                    if (args.info != null) { -                        args.info.cachedPhoto = (Drawable) args.result; -                    } -                    imagePresent = true; -                } else if (args.defaultResource != -1) { -                    args.view.setVisibility(View.VISIBLE); -                    args.view.setImageResource(args.defaultResource); -                } -                 -                // Note that the data is cached. -                if (args.info != null) { -                    args.info.isCachedPhotoCurrent = true; -                } -                 -                // notify the listener if it is there. -                if (args.listener != null) { -                    if (DBG) Log.d(LOG_TAG, "Notifying listener: " + args.listener.toString() +  -                            " image: " + args.uri + " completed"); -                    args.listener.onImageLoadComplete(msg.what, args.cookie, args.view, -                            imagePresent); -                } -                break; -            default:     -        } -    } -} diff --git a/core/java/android/pim/DateException.java b/core/java/android/pim/DateException.java deleted file mode 100644 index 90bfe7f..0000000 --- a/core/java/android/pim/DateException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2006 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; - -public class DateException extends Exception -{ -    public DateException(String message) -    { -        super(message); -    } -} - diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java deleted file mode 100644 index edf69ee..0000000 --- a/core/java/android/pim/EventRecurrence.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (C) 2006 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.res.Resources; -import android.text.TextUtils; -import android.text.format.Time; - -import java.util.Calendar; - -public class EventRecurrence -{ -    /** -     * Thrown when a recurrence string provided can not be parsed according -     * to RFC2445. -     */ -    public static class InvalidFormatException extends RuntimeException -    { -        InvalidFormatException(String s) { -            super(s); -        } -    } - -    public EventRecurrence() -    { -        wkst = MO; -    } -     -    /** -     * Parse an iCalendar/RFC2445 recur type according to Section 4.3.10. -     */ -    public native void parse(String recur); - -    public void setStartDate(Time date) { -        startDate = date; -    } -     -    public static final int SECONDLY = 1; -    public static final int MINUTELY = 2; -    public static final int HOURLY = 3; -    public static final int DAILY = 4; -    public static final int WEEKLY = 5; -    public static final int MONTHLY = 6; -    public static final int YEARLY = 7; - -    public static final int SU = 0x00010000; -    public static final int MO = 0x00020000; -    public static final int TU = 0x00040000; -    public static final int WE = 0x00080000; -    public static final int TH = 0x00100000; -    public static final int FR = 0x00200000; -    public static final int SA = 0x00400000; - -    public Time      startDate; -    public int       freq; -    public String    until; -    public int       count; -    public int       interval; -    public int       wkst; - -    public int[]     bysecond; -    public int       bysecondCount; -    public int[]     byminute; -    public int       byminuteCount; -    public int[]     byhour; -    public int       byhourCount; -    public int[]     byday; -    public int[]     bydayNum; -    public int       bydayCount;    -    public int[]     bymonthday; -    public int       bymonthdayCount; -    public int[]     byyearday; -    public int       byyeardayCount; -    public int[]     byweekno; -    public int       byweeknoCount; -    public int[]     bymonth; -    public int       bymonthCount; -    public int[]     bysetpos; -    public int       bysetposCount; - -    /** -     * Converts one of the Calendar.SUNDAY constants to the SU, MO, etc. -     * constants.  btw, I think we should switch to those here too, to -     * get rid of this function, if possible. -     */ -    public static int calendarDay2Day(int day) -    { -        switch (day) -        { -            case Calendar.SUNDAY: -                return SU; -            case Calendar.MONDAY: -                return MO; -            case Calendar.TUESDAY: -                return TU; -            case Calendar.WEDNESDAY: -                return WE; -            case Calendar.THURSDAY: -                return TH; -            case Calendar.FRIDAY: -                return FR; -            case Calendar.SATURDAY: -                return SA; -            default: -                throw new RuntimeException("bad day of week: " + day); -        } -    } -     -    public static int timeDay2Day(int day) -    { -        switch (day) -        { -            case Time.SUNDAY: -                return SU; -            case Time.MONDAY: -                return MO; -            case Time.TUESDAY: -                return TU; -            case Time.WEDNESDAY: -                return WE; -            case Time.THURSDAY: -                return TH; -            case Time.FRIDAY: -                return FR; -            case Time.SATURDAY: -                return SA; -            default: -                throw new RuntimeException("bad day of week: " + day); -        } -    } -    public static int day2TimeDay(int day) -    { -        switch (day) -        { -            case SU: -                return Time.SUNDAY; -            case MO: -                return Time.MONDAY; -            case TU: -                return Time.TUESDAY; -            case WE: -                return Time.WEDNESDAY; -            case TH: -                return Time.THURSDAY; -            case FR: -                return Time.FRIDAY; -            case SA: -                return Time.SATURDAY; -            default: -                throw new RuntimeException("bad day of week: " + day); -        } -    } - -    /** -     * Converts one of the SU, MO, etc. constants to the Calendar.SUNDAY -     * constants.  btw, I think we should switch to those here too, to -     * get rid of this function, if possible. -     */ -    public static int day2CalendarDay(int day) -    { -        switch (day) -        { -            case SU: -                return Calendar.SUNDAY; -            case MO: -                return Calendar.MONDAY; -            case TU: -                return Calendar.TUESDAY; -            case WE: -                return Calendar.WEDNESDAY; -            case TH: -                return Calendar.THURSDAY; -            case FR: -                return Calendar.FRIDAY; -            case SA: -                return Calendar.SATURDAY; -            default: -                throw new RuntimeException("bad day of week: " + day); -        } -    } -     -    /** -     * Converts one of the internal day constants (SU, MO, etc.) to the -     * two-letter string representing that constant. -     *  -     * @throws IllegalArgumentException Thrown if the day argument is not one of -     * the defined day constants. -     *  -     * @param day one the internal constants SU, MO, etc. -     * @return the two-letter string for the day ("SU", "MO", etc.) -     */ -    private static String day2String(int day) { -        switch (day) { -        case SU: -            return "SU"; -        case MO: -            return "MO"; -        case TU: -            return "TU"; -        case WE: -            return "WE"; -        case TH: -            return "TH"; -        case FR: -            return "FR"; -        case SA: -            return "SA"; -        default: -            throw new IllegalArgumentException("bad day argument: " + day); -        } -    } - -    private static void appendNumbers(StringBuilder s, String label, -                                        int count, int[] values) -    { -        if (count > 0) { -            s.append(label); -            count--; -            for (int i=0; i<count; i++) { -                s.append(values[i]); -                s.append(","); -            } -            s.append(values[count]); -        } -    } - -    private void appendByDay(StringBuilder s, int i) -    { -        int n = this.bydayNum[i]; -        if (n != 0) { -            s.append(n); -        } - -        String str = day2String(this.byday[i]); -        s.append(str); -    } - -    @Override -    public String toString() -    { -        StringBuilder s = new StringBuilder(); - -        s.append("FREQ="); -        switch (this.freq) -        { -            case SECONDLY: -                s.append("SECONDLY"); -                break; -            case MINUTELY: -                s.append("MINUTELY"); -                break; -            case HOURLY: -                s.append("HOURLY"); -                break; -            case DAILY: -                s.append("DAILY"); -                break; -            case WEEKLY: -                s.append("WEEKLY"); -                break; -            case MONTHLY: -                s.append("MONTHLY"); -                break; -            case YEARLY: -                s.append("YEARLY"); -                break; -        } - -        if (!TextUtils.isEmpty(this.until)) { -            s.append(";UNTIL="); -            s.append(until); -        } -         -        if (this.count != 0) { -            s.append(";COUNT="); -            s.append(this.count); -        } - -        if (this.interval != 0) { -            s.append(";INTERVAL="); -            s.append(this.interval); -        } - -        if (this.wkst != 0) { -            s.append(";WKST="); -            s.append(day2String(this.wkst)); -        } - -        appendNumbers(s, ";BYSECOND=", this.bysecondCount, this.bysecond); -        appendNumbers(s, ";BYMINUTE=", this.byminuteCount, this.byminute); -        appendNumbers(s, ";BYSECOND=", this.byhourCount, this.byhour); - -        // day -        int count = this.bydayCount; -        if (count > 0) { -            s.append(";BYDAY="); -            count--; -            for (int i=0; i<count; i++) { -                appendByDay(s, i); -                s.append(","); -            } -            appendByDay(s, count); -        } - -        appendNumbers(s, ";BYMONTHDAY=", this.bymonthdayCount, this.bymonthday); -        appendNumbers(s, ";BYYEARDAY=", this.byyeardayCount, this.byyearday); -        appendNumbers(s, ";BYWEEKNO=", this.byweeknoCount, this.byweekno); -        appendNumbers(s, ";BYMONTH=", this.bymonthCount, this.bymonth); -        appendNumbers(s, ";BYSETPOS=", this.bysetposCount, this.bysetpos); - -        return s.toString(); -    } -     -    public String getRepeatString() { -        Resources r = Resources.getSystem(); -         -        // TODO Implement "Until" portion of string, as well as custom settings -        switch (this.freq) { -            case DAILY: -                return r.getString(com.android.internal.R.string.daily); -            case WEEKLY: { -                if (repeatsOnEveryWeekDay()) { -                    return r.getString(com.android.internal.R.string.every_weekday); -                } else { -                    String format = r.getString(com.android.internal.R.string.weekly); -                    StringBuilder days = new StringBuilder(); -                 -                    // Do one less iteration in the loop so the last element is added out of the -                    // loop. This is done so the comma is not placed after the last item. -                    int count = this.bydayCount - 1; -                    if (count >= 0) { -                        for (int i = 0 ; i < count ; i++) { -                            days.append(dayToString(r, this.byday[i])); -                            days.append(","); -                        } -                        days.append(dayToString(r, this.byday[count])); -                     -                        return String.format(format, days.toString()); -                    } -                     -                    // There is no "BYDAY" specifier, so use the day of the -                    // first event.  For this to work, the setStartDate() -                    // method must have been used by the caller to set the -                    // date of the first event in the recurrence. -                    if (startDate == null) { -                        return null; -                    } -                     -                    int day = timeDay2Day(startDate.weekDay); -                    return String.format(format, dayToString(r, day)); -                } -            } -            case MONTHLY: { -                return r.getString(com.android.internal.R.string.monthly); -            } -            case YEARLY: -                return r.getString(com.android.internal.R.string.yearly); -        } - -        return null; -    } -     -    public boolean repeatsOnEveryWeekDay() { -        if (this.freq != WEEKLY) { -            return false;  -        } -         -        int count = this.bydayCount; -        if (count != 5) { -            return false; -        } -         -        for (int i = 0 ; i < count ; i++) { -            int day = byday[i]; -            if (day == SU || day == SA) { -                return false; -            } -        } -         -        return true; -    } -     -    public boolean repeatsMonthlyOnDayCount() { -        if (this.freq != MONTHLY) { -            return false; -        } -         -        if (bydayCount != 1 || bymonthdayCount != 0) { -            return false; -        } -         -        return true; -    } -     -    private String dayToString(Resources r, int day) { -        switch (day) { -        case SU: return r.getString(com.android.internal.R.string.sunday); -        case MO: return r.getString(com.android.internal.R.string.monday); -        case TU: return r.getString(com.android.internal.R.string.tuesday); -        case WE: return r.getString(com.android.internal.R.string.wednesday); -        case TH: return r.getString(com.android.internal.R.string.thursday); -        case FR: return r.getString(com.android.internal.R.string.friday); -        case SA: return r.getString(com.android.internal.R.string.saturday); -        default: throw new IllegalArgumentException("bad day argument: " + day); -        } -    } -} diff --git a/core/java/android/pim/ICalendar.java b/core/java/android/pim/ICalendar.java deleted file mode 100644 index 4a5d7e4..0000000 --- a/core/java/android/pim/ICalendar.java +++ /dev/null @@ -1,643 +0,0 @@ -/* - * 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.util.Log; -import android.util.Config; - -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.ArrayList; - -/** - * Parses RFC 2445 iCalendar objects. - */ -public class ICalendar { - -    private static final String TAG = "Sync"; - -    // TODO: keep track of VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, VALARM -    // components, by type field or by subclass?  subclass would allow us to -    // enforce grammars. - -    /** -     * Exception thrown when an iCalendar object has invalid syntax. -     */ -    public static class FormatException extends Exception { -        public FormatException() { -            super(); -        } - -        public FormatException(String msg) { -            super(msg); -        } - -        public FormatException(String msg, Throwable cause) { -            super(msg, cause); -        } -    } - -    /** -     * A component within an iCalendar (VEVENT, VTODO, VJOURNAL, VFEEBUSY, -     * VTIMEZONE, VALARM). -     */ -    public static class Component { - -        // components -        private static final String BEGIN = "BEGIN"; -        private static final String END = "END"; -        private static final String NEWLINE = "\n"; -        public static final String VCALENDAR = "VCALENDAR"; -        public static final String VEVENT = "VEVENT"; -        public static final String VTODO = "VTODO"; -        public static final String VJOURNAL = "VJOURNAL"; -        public static final String VFREEBUSY = "VFREEBUSY"; -        public static final String VTIMEZONE = "VTIMEZONE"; -        public static final String VALARM = "VALARM"; - -        private final String mName; -        private final Component mParent; // see if we can get rid of this -        private LinkedList<Component> mChildren = null; -        private final LinkedHashMap<String, ArrayList<Property>> mPropsMap = -                new LinkedHashMap<String, ArrayList<Property>>(); - -        /** -         * Creates a new component with the provided name. -         * @param name The name of the component. -         */ -        public Component(String name, Component parent) { -            mName = name; -            mParent = parent; -        } - -        /** -         * Returns the name of the component. -         * @return The name of the component. -         */ -        public String getName() { -            return mName; -        } - -        /** -         * Returns the parent of this component. -         * @return The parent of this component. -         */ -        public Component getParent() { -            return mParent; -        } - -        /** -         * Helper that lazily gets/creates the list of children. -         * @return The list of children. -         */ -        protected LinkedList<Component> getOrCreateChildren() { -            if (mChildren == null) { -                mChildren = new LinkedList<Component>(); -            } -            return mChildren; -        } - -        /** -         * Adds a child component to this component. -         * @param child The child component. -         */ -        public void addChild(Component child) { -            getOrCreateChildren().add(child); -        } - -        /** -         * Returns a list of the Component children of this component.  May be -         * null, if there are no children. -         * -         * @return A list of the children. -         */ -        public List<Component> getComponents() { -            return mChildren; -        } - -        /** -         * Adds a Property to this component. -         * @param prop -         */ -        public void addProperty(Property prop) { -            String name= prop.getName(); -            ArrayList<Property> props = mPropsMap.get(name); -            if (props == null) { -                props = new ArrayList<Property>(); -                mPropsMap.put(name, props); -            } -            props.add(prop); -        } - -        /** -         * Returns a set of the property names within this component. -         * @return A set of property names within this component. -         */ -        public Set<String> getPropertyNames() { -            return mPropsMap.keySet(); -        } - -        /** -         * Returns a list of properties with the specified name.  Returns null -         * if there are no such properties. -         * @param name The name of the property that should be returned. -         * @return A list of properties with the requested name. -         */ -        public List<Property> getProperties(String name) { -            return mPropsMap.get(name); -        } - -        /** -         * Returns the first property with the specified name.  Returns null -         * if there is no such property. -         * @param name The name of the property that should be returned. -         * @return The first property with the specified name. -         */ -        public Property getFirstProperty(String name) { -            List<Property> props = mPropsMap.get(name); -            if (props == null || props.size() == 0) { -                return null; -            } -            return props.get(0); -        } - -        @Override -        public String toString() { -            StringBuilder sb = new StringBuilder(); -            toString(sb); -            sb.append(NEWLINE); -            return sb.toString(); -        } - -        /** -         * Helper method that appends this component to a StringBuilder.  The -         * caller is responsible for appending a newline at the end of the -         * component. -         */ -        public void toString(StringBuilder sb) { -            sb.append(BEGIN); -            sb.append(":"); -            sb.append(mName); -            sb.append(NEWLINE); - -            // append the properties -            for (String propertyName : getPropertyNames()) { -                for (Property property : getProperties(propertyName)) { -                    property.toString(sb); -                    sb.append(NEWLINE); -                } -            } - -            // append the sub-components -            if (mChildren != null) { -                for (Component component : mChildren) { -                    component.toString(sb); -                    sb.append(NEWLINE); -                } -            } - -            sb.append(END); -            sb.append(":"); -            sb.append(mName); -        } -    } - -    /** -     * A property within an iCalendar component (e.g., DTSTART, DTEND, etc., -     * within a VEVENT). -     */ -    public static class Property { -        // properties -        // TODO: do we want to list these here?  the complete list is long. -        public static final String DTSTART = "DTSTART"; -        public static final String DTEND = "DTEND"; -        public static final String DURATION = "DURATION"; -        public static final String RRULE = "RRULE"; -        public static final String RDATE = "RDATE"; -        public static final String EXRULE = "EXRULE"; -        public static final String EXDATE = "EXDATE"; -        // ... need to add more. -         -        private final String mName; -        private LinkedHashMap<String, ArrayList<Parameter>> mParamsMap = -                new LinkedHashMap<String, ArrayList<Parameter>>(); -        private String mValue; // TODO: make this final? - -        /** -         * Creates a new property with the provided name. -         * @param name The name of the property. -         */ -        public Property(String name) { -            mName = name; -        } - -        /** -         * Creates a new property with the provided name and value. -         * @param name The name of the property. -         * @param value The value of the property. -         */ -        public Property(String name, String value) { -            mName = name; -            mValue = value; -        } - -        /** -         * Returns the name of the property. -         * @return The name of the property. -         */ -        public String getName() { -            return mName; -        } - -        /** -         * Returns the value of this property. -         * @return The value of this property. -         */ -        public String getValue() { -            return mValue; -        } - -        /** -         * Sets the value of this property. -         * @param value The desired value for this property. -         */ -        public void setValue(String value) { -            mValue = value; -        }         - -        /** -         * Adds a {@link Parameter} to this property. -         * @param param The parameter that should be added. -         */ -        public void addParameter(Parameter param) { -            ArrayList<Parameter> params = mParamsMap.get(param.name); -            if (params == null) { -                params = new ArrayList<Parameter>(); -                mParamsMap.put(param.name, params); -            } -            params.add(param); -        } - -        /** -         * Returns the set of parameter names for this property. -         * @return The set of parameter names for this property. -         */ -        public Set<String> getParameterNames() { -            return mParamsMap.keySet(); -        } - -        /** -         * Returns the list of parameters with the specified name.  May return -         * null if there are no such parameters. -         * @param name The name of the parameters that should be returned. -         * @return The list of parameters with the specified name. -         */ -        public List<Parameter> getParameters(String name) { -            return mParamsMap.get(name); -        } - -        /** -         * Returns the first parameter with the specified name.  May return -         * nll if there is no such parameter. -         * @param name The name of the parameter that should be returned. -         * @return The first parameter with the specified name. -         */ -        public Parameter getFirstParameter(String name) { -            ArrayList<Parameter> params = mParamsMap.get(name); -            if (params == null || params.size() == 0) { -                return null; -            } -            return params.get(0); -        } - -        @Override -        public String toString() { -            StringBuilder sb = new StringBuilder(); -            toString(sb); -            return sb.toString(); -        } - -        /** -         * Helper method that appends this property to a StringBuilder.  The -         * caller is responsible for appending a newline after this property. -         */ -        public void toString(StringBuilder sb) { -            sb.append(mName); -            Set<String> parameterNames = getParameterNames(); -            for (String parameterName : parameterNames) { -                for (Parameter param : getParameters(parameterName)) { -                    sb.append(";"); -                    param.toString(sb); -                } -            } -            sb.append(":"); -            sb.append(mValue); -        } -    } - -    /** -     * A parameter defined for an iCalendar property. -     */ -    // TODO: make this a proper class rather than a struct? -    public static class Parameter { -        public String name; -        public String value; - -        /** -         * Creates a new empty parameter. -         */ -        public Parameter() { -        } - -        /** -         * Creates a new parameter with the specified name and value. -         * @param name The name of the parameter. -         * @param value The value of the parameter. -         */ -        public Parameter(String name, String value) { -            this.name = name; -            this.value = value; -        } - -        @Override -        public String toString() { -            StringBuilder sb = new StringBuilder(); -            toString(sb); -            return sb.toString(); -        } - -        /** -         * Helper method that appends this parameter to a StringBuilder. -         */ -        public void toString(StringBuilder sb) { -            sb.append(name); -            sb.append("="); -            sb.append(value); -        } -    } - -    private static final class ParserState { -        // public int lineNumber = 0; -        public String line; // TODO: just point to original text -        public int index; -    } - -    // use factory method -    private ICalendar() { -    } - -    // TODO: get rid of this -- handle all of the parsing in one pass through -    // the text. -    private static String normalizeText(String text) { -        // first we deal with line folding, by replacing all "\r\n " strings -        // with nothing -        text = text.replaceAll("\r\n ", ""); - -        // it's supposed to be \r\n, but not everyone does that -        text = text.replaceAll("\r\n", "\n"); -        text = text.replaceAll("\r", "\n"); -        return text; -    } - -    /** -     * Parses text into an iCalendar component.  Parses into the provided -     * component, if not null, or parses into a new component.  In the latter -     * case, expects a BEGIN as the first line.  Returns the provided or newly -     * created top-level component. -     */ -    // TODO: use an index into the text, so we can make this a recursive -    // function? -    private static Component parseComponentImpl(Component component, -                                                String text) -            throws FormatException { -        Component current = component; -        ParserState state = new ParserState(); -        state.index = 0; - -        // split into lines -        String[] lines = text.split("\n"); - -        // each line is of the format: -        // name *(";" param) ":" value -        for (String line : lines) { -            try { -                current = parseLine(line, state, current); -                // if the provided component was null, we will return the root -                // NOTE: in this case, if the first line is not a BEGIN, a -                // FormatException will get thrown. -                if (component == null) { -                    component = current; -                } -            } catch (FormatException fe) { -                if (Config.LOGV) { -                    Log.v(TAG, "Cannot parse " + line, fe); -                } -                // for now, we ignore the parse error.  Google Calendar seems -                // to be emitting some misformatted iCalendar objects. -            } -            continue; -        } -        return component; -    } - -    /** -     * Parses a line into the provided component.  Creates a new component if -     * the line is a BEGIN, adding the newly created component to the provided -     * parent.  Returns whatever component is the current one (to which new -     * properties will be added) in the parse. -     */ -    private static Component parseLine(String line, ParserState state, -                                       Component component) -            throws FormatException { -        state.line = line; -        int len = state.line.length(); - -        // grab the name -        char c = 0; -        for (state.index = 0; state.index < len; ++state.index) { -            c = line.charAt(state.index); -            if (c == ';' || c == ':') { -                break; -            } -        } -        String name = line.substring(0, state.index); - -        if (component == null) { -            if (!Component.BEGIN.equals(name)) { -                throw new FormatException("Expected BEGIN"); -            } -        } - -        Property property; -        if (Component.BEGIN.equals(name)) { -            // start a new component -            String componentName = extractValue(state); -            Component child = new Component(componentName, component); -            if (component != null) { -                component.addChild(child); -            } -            return child; -        } else if (Component.END.equals(name)) { -            // finish the current component -            String componentName = extractValue(state); -            if (component == null || -                    !componentName.equals(component.getName())) { -                throw new FormatException("Unexpected END " + componentName); -            } -            return component.getParent(); -        } else { -            property = new Property(name); -        } - -        if (c == ';') { -            Parameter parameter = null; -            while ((parameter = extractParameter(state)) != null) { -                property.addParameter(parameter); -            } -        } -        String value = extractValue(state); -        property.setValue(value); -        component.addProperty(property); -        return component; -    } - -    /** -     * Extracts the value ":..." on the current line.  The first character must -     * be a ':'. -     */ -    private static String extractValue(ParserState state) -            throws FormatException { -        String line = state.line; -        char c = line.charAt(state.index); -        if (c != ':') { -            throw new FormatException("Expected ':' before end of line in " -                    + line); -        } -        String value = line.substring(state.index + 1); -        state.index = line.length() - 1; -        return value; -    } - -    /** -     * Extracts the next parameter from the line, if any.  If there are no more -     * parameters, returns null. -     */ -    private static Parameter extractParameter(ParserState state) -            throws FormatException { -        String text = state.line; -        int len = text.length(); -        Parameter parameter = null; -        int startIndex = -1; -        int equalIndex = -1; -        while (state.index < len) { -            char c = text.charAt(state.index); -            if (c == ':') { -                if (parameter != null) { -                    if (equalIndex == -1) { -                        throw new FormatException("Expected '=' within " -                                + "parameter in " + text); -                    } -                    parameter.value = text.substring(equalIndex + 1, -                                                     state.index); -                } -                return parameter; // may be null -            } else if (c == ';') { -                if (parameter != null) { -                    if (equalIndex == -1) { -                        throw new FormatException("Expected '=' within " -                                + "parameter in " + text); -                    } -                    parameter.value = text.substring(equalIndex + 1, -                                                     state.index); -                    return parameter; -                } else { -                    parameter = new Parameter(); -                    startIndex = state.index; -                } -            } else if (c == '=') { -                equalIndex = state.index; -                if ((parameter == null) || (startIndex == -1)) { -                    throw new FormatException("Expected ';' before '=' in " -                            + text); -                } -                parameter.name = text.substring(startIndex + 1, equalIndex); -            } -            ++state.index; -        } -        throw new FormatException("Expected ':' before end of line in " + text); -    } - -    /** -     * Parses the provided text into an iCalendar object.  The top-level -     * component must be of type VCALENDAR. -     * @param text The text to be parsed. -     * @return The top-level VCALENDAR component. -     * @throws FormatException Thrown if the text could not be parsed into an -     * iCalendar VCALENDAR object. -     */ -    public static Component parseCalendar(String text) throws FormatException { -        Component calendar = parseComponent(null, text); -        if (calendar == null || !Component.VCALENDAR.equals(calendar.getName())) { -            throw new FormatException("Expected " + Component.VCALENDAR); -        } -        return calendar; -    } - -    /** -     * Parses the provided text into an iCalendar event.  The top-level -     * component must be of type VEVENT. -     * @param text The text to be parsed. -     * @return The top-level VEVENT component. -     * @throws FormatException Thrown if the text could not be parsed into an -     * iCalendar VEVENT. -     */ -    public static Component parseEvent(String text) throws FormatException { -        Component event = parseComponent(null, text); -        if (event == null || !Component.VEVENT.equals(event.getName())) { -            throw new FormatException("Expected " + Component.VEVENT); -        } -        return event; -    } - -    /** -     * Parses the provided text into an iCalendar component. -     * @param text The text to be parsed. -     * @return The top-level component. -     * @throws FormatException Thrown if the text could not be parsed into an -     * iCalendar component. -     */ -    public static Component parseComponent(String text) throws FormatException { -        return parseComponent(null, text); -    } - -    /** -     * Parses the provided text, adding to the provided component. -     * @param component The component to which the parsed iCalendar data should -     * be added. -     * @param text The text to be parsed. -     * @return The top-level component. -     * @throws FormatException Thrown if the text could not be parsed as an -     * iCalendar object. -     */ -    public static Component parseComponent(Component component, String text) -        throws FormatException { -        text = normalizeText(text); -        return parseComponentImpl(component, text); -    } -} diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java deleted file mode 100644 index 1a287c8..0000000 --- a/core/java/android/pim/RecurrenceSet.java +++ /dev/null @@ -1,398 +0,0 @@ -/* - * 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) { -        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) { -        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) { -        init(rruleStr, rdateStr, exruleStr, exdateStr); -    } - -    private void init(String rruleStr, String rdateStr, -                      String exruleStr, String exdateStr) { -        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<n; ++i) { -            // The timezone is updated to UTC if the time string specified 'Z'. -            time.parse(rawDates[i]); -            dates[i] = time.toMillis(false /* use isDst */); -            time.timezone = tz; -        } -        return dates; -    } - -    /** -     * Populates the database map of values with the appropriate RRULE, RDATE, -     * EXRULE, and EXDATE values extracted from the parsed iCalendar component. -     * @param component The iCalendar component containing the desired -     * recurrence specification. -     * @param values The db values that should be updated. -     * @return true if the component contained the necessary information -     * to specify a recurrence.  The required fields are DTSTART, -     * one of DTEND/DURATION, and one of RRULE/RDATE.  Returns false if -     * there was an error, including if the date is out of range. -     */ -    public static boolean populateContentValues(ICalendar.Component component, -            ContentValues values) { -        ICalendar.Property dtstartProperty = -                component.getFirstProperty("DTSTART"); -        String dtstart = dtstartProperty.getValue(); -        ICalendar.Parameter tzidParam = -                dtstartProperty.getFirstParameter("TZID"); -        // NOTE: the timezone may be null, if this is a floating time. -        String tzid = tzidParam == null ? null : tzidParam.value; -        Time start = new Time(tzidParam == null ? Time.TIMEZONE_UTC : tzid); -        boolean inUtc = start.parse(dtstart); -        boolean allDay = start.allDay; - -        if (inUtc) { -            tzid = Time.TIMEZONE_UTC; -        } -                 -        String duration = computeDuration(start, component); -        String rrule = flattenProperties(component, "RRULE"); -        String rdate = extractDates(component.getFirstProperty("RDATE")); -        String exrule = flattenProperties(component, "EXRULE"); -        String exdate = extractDates(component.getFirstProperty("EXDATE")); - -        if ((TextUtils.isEmpty(dtstart))|| -                (TextUtils.isEmpty(duration))|| -                ((TextUtils.isEmpty(rrule))&& -                        (TextUtils.isEmpty(rdate)))) { -                if (Config.LOGD) { -                    Log.d(TAG, "Recurrence missing DTSTART, DTEND/DURATION, " -                                + "or RRULE/RDATE: " -                                + component.toString()); -                } -                return false; -        } -         -        if (allDay) { -        	// TODO: also change tzid to be UTC?  that would be consistent, but -        	// that would not reflect the original timezone value back to the -        	// server. -        	start.timezone = Time.TIMEZONE_UTC; -        } -        long millis = start.toMillis(false /* use isDst */); -        values.put(Calendar.Events.DTSTART, millis); -        if (millis == -1) { -            if (Config.LOGD) { -                Log.d(TAG, "DTSTART is out of range: " + component.toString()); -            } -            return false; -        } -         -        values.put(Calendar.Events.RRULE, rrule); -        values.put(Calendar.Events.RDATE, rdate); -        values.put(Calendar.Events.EXRULE, exrule); -        values.put(Calendar.Events.EXDATE, exdate); -        values.put(Calendar.Events.EVENT_TIMEZONE, tzid); -        values.put(Calendar.Events.DURATION, duration); -        values.put(Calendar.Events.ALL_DAY, allDay ? 1 : 0); -        return true; -    } - -    public static boolean populateComponent(Cursor cursor, -                                            ICalendar.Component component) { -         -        int dtstartColumn = cursor.getColumnIndex(Calendar.Events.DTSTART); -        int durationColumn = cursor.getColumnIndex(Calendar.Events.DURATION); -        int tzidColumn = cursor.getColumnIndex(Calendar.Events.EVENT_TIMEZONE); -        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); -        int allDayColumn = cursor.getColumnIndex(Calendar.Events.ALL_DAY); - - -        long dtstart = -1; -        if (!cursor.isNull(dtstartColumn)) { -            dtstart = cursor.getLong(dtstartColumn); -        } -        String duration = cursor.getString(durationColumn); -        String tzid = cursor.getString(tzidColumn); -        String rruleStr = cursor.getString(rruleColumn); -        String rdateStr = cursor.getString(rdateColumn); -        String exruleStr = cursor.getString(exruleColumn); -        String exdateStr = cursor.getString(exdateColumn); -        boolean allDay = cursor.getInt(allDayColumn) == 1; - -        if ((dtstart == -1) || -            (TextUtils.isEmpty(duration))|| -            ((TextUtils.isEmpty(rruleStr))&& -                (TextUtils.isEmpty(rdateStr)))) { -                // no recurrence. -                return false; -        } - -        ICalendar.Property dtstartProp = new ICalendar.Property("DTSTART"); -        Time dtstartTime = null; -        if (!TextUtils.isEmpty(tzid)) { -            if (!allDay) { -                dtstartProp.addParameter(new ICalendar.Parameter("TZID", tzid)); -            } -            dtstartTime = new Time(tzid); -        } else { -            // use the "floating" timezone -            dtstartTime = new Time(Time.TIMEZONE_UTC); -        } -         -        dtstartTime.set(dtstart); -        // make sure the time is printed just as a date, if all day. -        // TODO: android.pim.Time really should take care of this for us. -        if (allDay) { -            dtstartProp.addParameter(new ICalendar.Parameter("VALUE", "DATE")); -            dtstartTime.allDay = true; -            dtstartTime.hour = 0; -            dtstartTime.minute = 0; -            dtstartTime.second = 0; -        } - -        dtstartProp.setValue(dtstartTime.format2445()); -        component.addProperty(dtstartProp); -        ICalendar.Property durationProp = new ICalendar.Property("DURATION"); -        durationProp.setValue(duration); -        component.addProperty(durationProp); - -        addPropertiesForRuleStr(component, "RRULE", rruleStr); -        addPropertyForDateStr(component, "RDATE", rdateStr); -        addPropertiesForRuleStr(component, "EXRULE", exruleStr); -        addPropertyForDateStr(component, "EXDATE", exdateStr); -        return true; -    } - -    private static void addPropertiesForRuleStr(ICalendar.Component component, -                                                String propertyName, -                                                String ruleStr) { -        if (TextUtils.isEmpty(ruleStr)) { -            return; -        } -        String[] rrules = ruleStr.split(RULE_SEPARATOR); -        for (String rrule : rrules) { -            ICalendar.Property prop = new ICalendar.Property(propertyName); -            prop.setValue(rrule); -            component.addProperty(prop); -        } -    } - -    private static void addPropertyForDateStr(ICalendar.Component component, -                                              String propertyName, -                                              String dateStr) { -        if (TextUtils.isEmpty(dateStr)) { -            return; -        } - -        ICalendar.Property prop = new ICalendar.Property(propertyName); -        String tz = null; -        int tzidx = dateStr.indexOf(";"); -        if (tzidx != -1) { -            tz = dateStr.substring(0, tzidx); -            dateStr = dateStr.substring(tzidx + 1); -        } -        if (!TextUtils.isEmpty(tz)) { -            prop.addParameter(new ICalendar.Parameter("TZID", tz)); -        } -        prop.setValue(dateStr); -        component.addProperty(prop); -    } -     -    private static String computeDuration(Time start, -                                          ICalendar.Component component) { -        // see if a duration is defined -        ICalendar.Property durationProperty = -                component.getFirstProperty("DURATION"); -        if (durationProperty != null) { -            // just return the duration -            return durationProperty.getValue(); -        } - -        // must compute a duration from the DTEND -        ICalendar.Property dtendProperty = -                component.getFirstProperty("DTEND"); -        if (dtendProperty == null) { -            // no DURATION, no DTEND: 0 second duration -            return "+P0S"; -        } -        ICalendar.Parameter endTzidParameter = -                dtendProperty.getFirstParameter("TZID"); -        String endTzid = (endTzidParameter == null) -                ? start.timezone : endTzidParameter.value; - -        Time end = new Time(endTzid); -        end.parse(dtendProperty.getValue()); -        long durationMillis = end.toMillis(false /* use isDst */)  -                - start.toMillis(false /* use isDst */); -        long durationSeconds = (durationMillis / 1000); -        return "P" + durationSeconds + "S"; -    } - -    private static String flattenProperties(ICalendar.Component component, -                                            String name) { -        List<ICalendar.Property> 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(); -    } -} diff --git a/core/java/android/pim/package.html b/core/java/android/pim/package.html deleted file mode 100644 index 75237c9..0000000 --- a/core/java/android/pim/package.html +++ /dev/null @@ -1,7 +0,0 @@ -<HTML> -<BODY> -{@hide} -Provides helpers for working with PIM (Personal Information Manager) data used -by contact lists and calendars. -</BODY> -</HTML>
\ No newline at end of file | 
