173714169d34a55fc01e14b30897a1ebbacf9934eErik/*
273714169d34a55fc01e14b30897a1ebbacf9934eErik * Copyright (C) 2010 The Android Open Source Project
373714169d34a55fc01e14b30897a1ebbacf9934eErik *
473714169d34a55fc01e14b30897a1ebbacf9934eErik * Licensed under the Apache License, Version 2.0 (the "License"); you may not
573714169d34a55fc01e14b30897a1ebbacf9934eErik * use this file except in compliance with the License. You may obtain a copy of
673714169d34a55fc01e14b30897a1ebbacf9934eErik * the License at
773714169d34a55fc01e14b30897a1ebbacf9934eErik *
873714169d34a55fc01e14b30897a1ebbacf9934eErik * http://www.apache.org/licenses/LICENSE-2.0
973714169d34a55fc01e14b30897a1ebbacf9934eErik *
1073714169d34a55fc01e14b30897a1ebbacf9934eErik * Unless required by applicable law or agreed to in writing, software
1173714169d34a55fc01e14b30897a1ebbacf9934eErik * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1273714169d34a55fc01e14b30897a1ebbacf9934eErik * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1373714169d34a55fc01e14b30897a1ebbacf9934eErik * License for the specific language governing permissions and limitations under
1473714169d34a55fc01e14b30897a1ebbacf9934eErik * the License.
1573714169d34a55fc01e14b30897a1ebbacf9934eErik */
1673714169d34a55fc01e14b30897a1ebbacf9934eErik
1773714169d34a55fc01e14b30897a1ebbacf9934eErikpackage com.android.calendar;
1873714169d34a55fc01e14b30897a1ebbacf9934eErik
1918cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereiraimport com.android.calendar.event.EditEventHelper;
2018cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereiraimport com.android.common.Rfc822Validator;
2118cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira
226ae7d69b90f22fd51ab677036ba987dbdc35a62dErikimport android.content.Context;
236ae7d69b90f22fd51ab677036ba987dbdc35a62dErikimport android.content.Intent;
246ae7d69b90f22fd51ab677036ba987dbdc35a62dErikimport android.content.SharedPreferences;
25a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees;
26a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars;
27a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Events;
28a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Reminders;
2973714169d34a55fc01e14b30897a1ebbacf9934eErikimport android.text.TextUtils;
3018cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereiraimport android.text.util.Rfc822Token;
3173714169d34a55fc01e14b30897a1ebbacf9934eErik
3259ead671b50514b49749fcd6a1d4186a270239d2Erikimport java.io.Serializable;
3373714169d34a55fc01e14b30897a1ebbacf9934eErikimport java.util.ArrayList;
34fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFaddenimport java.util.Collections;
35d845fbe558d5229102b58cce70a1b29fe6cb6967Erikimport java.util.LinkedHashMap;
3618cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereiraimport java.util.LinkedHashSet;
376ae7d69b90f22fd51ab677036ba987dbdc35a62dErikimport java.util.TimeZone;
3873714169d34a55fc01e14b30897a1ebbacf9934eErik
3973714169d34a55fc01e14b30897a1ebbacf9934eErik/**
4073714169d34a55fc01e14b30897a1ebbacf9934eErik * Stores all the information needed to fill out an entry in the events table.
41eca82e9468c002590045338f98588ad3ce1a0bb3Erik * This is a convenient way for storing information needed by the UI to write to
42eca82e9468c002590045338f98588ad3ce1a0bb3Erik * the events table. Only fields that are important to the UI are included.
4373714169d34a55fc01e14b30897a1ebbacf9934eErik */
4459ead671b50514b49749fcd6a1d4186a270239d2Erikpublic class CalendarEventModel implements Serializable {
45ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden    private static final String TAG = "CalendarEventModel";
46ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden
4759ead671b50514b49749fcd6a1d4186a270239d2Erik    public static class Attendee implements Serializable {
48d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        @Override
49d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        public int hashCode() {
50d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            return (mEmail == null) ? 0 : mEmail.hashCode();
51d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        }
52d845fbe558d5229102b58cce70a1b29fe6cb6967Erik
53d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        @Override
54d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        public boolean equals(Object obj) {
55d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            if (this == obj) {
56d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                return true;
57d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            }
58d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            if (!(obj instanceof Attendee)) {
59d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                return false;
60d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            }
61d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            Attendee other = (Attendee) obj;
62d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            if (!TextUtils.equals(mEmail, other.mEmail)) {
63d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                return false;
64d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            }
65d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            return true;
66d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        }
67d845fbe558d5229102b58cce70a1b29fe6cb6967Erik
68016d576c1f0fbcbf060fab132d8e6a1016dd7091Isaac Katzenelson        String getDisplayName() {
69016d576c1f0fbcbf060fab132d8e6a1016dd7091Isaac Katzenelson            if (TextUtils.isEmpty(mName)) {
70016d576c1f0fbcbf060fab132d8e6a1016dd7091Isaac Katzenelson                return mEmail;
71016d576c1f0fbcbf060fab132d8e6a1016dd7091Isaac Katzenelson            } else {
72016d576c1f0fbcbf060fab132d8e6a1016dd7091Isaac Katzenelson                return mName;
73016d576c1f0fbcbf060fab132d8e6a1016dd7091Isaac Katzenelson            }
74016d576c1f0fbcbf060fab132d8e6a1016dd7091Isaac Katzenelson        }
75016d576c1f0fbcbf060fab132d8e6a1016dd7091Isaac Katzenelson
76d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        public String mName;
77d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        public String mEmail;
78d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        public int mStatus;
79ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        public String mIdentity;
80ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        public String mIdNamespace;
81d845fbe558d5229102b58cce70a1b29fe6cb6967Erik
82d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        public Attendee(String name, String email) {
83ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            this(name, email, Attendees.ATTENDEE_STATUS_NONE, null, null);
84d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        }
85ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        public Attendee(String name, String email, int status, String identity,
86ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                String idNamespace) {
87667af28a8e9729e14831f3db456ff3edb2c4c29aIsaac Katzenelson            mName = name;
88667af28a8e9729e14831f3db456ff3edb2c4c29aIsaac Katzenelson            mEmail = email;
89667af28a8e9729e14831f3db456ff3edb2c4c29aIsaac Katzenelson            mStatus = status;
90ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            mIdentity = identity;
91ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            mIdNamespace = idNamespace;
92667af28a8e9729e14831f3db456ff3edb2c4c29aIsaac Katzenelson        }
93d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    }
94d845fbe558d5229102b58cce70a1b29fe6cb6967Erik
95fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden    /**
96fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden     * A single reminder entry.
97fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden     *
98fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden     * Instances of the class are immutable.
99fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden     */
100c27e56f7150b77da3d8ae22e48a4b3699bd2e19cAndy McFadden    public static class ReminderEntry implements Comparable<ReminderEntry>, Serializable {
101fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        private final int mMinutes;
102fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        private final int mMethod;
103fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
104fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        /**
105fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         * Returns a new ReminderEntry, with the specified minutes and method.
106fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         *
107fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         * @param minutes Number of minutes before the start of the event that the alert will fire.
108fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         * @param method Type of alert ({@link Reminders#METHOD_ALERT}, etc).
109fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         */
110fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        public static ReminderEntry valueOf(int minutes, int method) {
111fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            // TODO: cache common instances
112fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return new ReminderEntry(minutes, method);
113fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
114fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
115fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        /**
116fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         * Returns a ReminderEntry, with the specified number of minutes and a default alert method.
117fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         *
118fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         * @param minutes Number of minutes before the start of the event that the alert will fire.
119fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         */
1209645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden        public static ReminderEntry valueOf(int minutes) {
121fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return valueOf(minutes, Reminders.METHOD_DEFAULT);
122fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
123fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
124fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        /**
125fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         * Constructs a new ReminderEntry.
126fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         *
127fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         * @param minutes Number of minutes before the start of the event that the alert will fire.
128fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         * @param method Type of alert ({@link Reminders#METHOD_ALERT}, etc).
129fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden         */
130fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        private ReminderEntry(int minutes, int method) {
131fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            // TODO: error-check args
132fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            mMinutes = minutes;
133fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            mMethod = method;
134fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
135fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
136fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        @Override
137fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        public int hashCode() {
138fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return mMinutes * 10 + mMethod;
139fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
140fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
141fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        @Override
142fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        public boolean equals(Object obj) {
1439645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            if (this == obj) {
144fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden                return true;
1459645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            }
146fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            if (!(obj instanceof ReminderEntry)) {
147fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden                return false;
148fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            }
149fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
150fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            ReminderEntry re = (ReminderEntry) obj;
151fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
1529645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            if (re.mMinutes != mMinutes) {
153fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden                return false;
1549645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            }
155fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
1569645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            // Treat ALERT and DEFAULT as equivalent.  This is useful during the "has anything
1579645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            // "changed" test, so that if DEFAULT is present, but we don't change anything,
1589645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            // the internal conversion of DEFAULT to ALERT doesn't force a database update.
159fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return re.mMethod == mMethod ||
160fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden                (re.mMethod == Reminders.METHOD_DEFAULT && mMethod == Reminders.METHOD_ALERT) ||
161fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden                (re.mMethod == Reminders.METHOD_ALERT && mMethod == Reminders.METHOD_DEFAULT);
162fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
163fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
164fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        @Override
165fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        public String toString() {
166fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return "ReminderEntry min=" + mMinutes + " meth=" + mMethod;
167fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
168fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
169c27e56f7150b77da3d8ae22e48a4b3699bd2e19cAndy McFadden        /**
1709645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden         * Comparison function for a sort ordered primarily descending by minutes,
1719645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden         * secondarily ascending by method type.
172c27e56f7150b77da3d8ae22e48a4b3699bd2e19cAndy McFadden         */
173fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        public int compareTo(ReminderEntry re) {
174fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            if (re.mMinutes != mMinutes) {
175fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden                return re.mMinutes - mMinutes;
176fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            }
177fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            if (re.mMethod != mMethod) {
1789645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden                return mMethod - re.mMethod;
179fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            }
180fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return 0;
181fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
182fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
183fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        /** Returns the minutes. */
184fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        public int getMinutes() {
185fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return mMinutes;
186fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
187fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
188fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        /** Returns the alert method. */
189fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        public int getMethod() {
190fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return mMethod;
191fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
192fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden    }
193fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
19473714169d34a55fc01e14b30897a1ebbacf9934eErik    // TODO strip out fields that don't ever get used
1956ae7d69b90f22fd51ab677036ba987dbdc35a62dErik    /**
1966ae7d69b90f22fd51ab677036ba987dbdc35a62dErik     * The uri of the event in the db. This should only be null for new events.
1976ae7d69b90f22fd51ab677036ba987dbdc35a62dErik     */
19859ead671b50514b49749fcd6a1d4186a270239d2Erik    public String mUri = null;
199eca82e9468c002590045338f98588ad3ce1a0bb3Erik    public long mId = -1;
200eca82e9468c002590045338f98588ad3ce1a0bb3Erik    public long mCalendarId = -1;
2019d5f351e45e20ff04da6f9118031cc2cc7419905Michael Chan    public String mCalendarDisplayName = ""; // Make sure this is in sync with the mCalendarId
2023400a2bfc1e6be435ea2bb0f436a6ef338446504Erik    public int mCalendarColor = 0;
2039645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden    public int mCalendarMaxReminders;
2049645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden    public String mCalendarAllowedReminders;
205c6680c5819b6ad0d1914420902746fe5f86ba403RoboErik    public String mCalendarAllowedAttendeeTypes;
206c6680c5819b6ad0d1914420902746fe5f86ba403RoboErik    public String mCalendarAllowedAvailability;
2079d5f351e45e20ff04da6f9118031cc2cc7419905Michael Chan
20873714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mSyncId = null;
20973714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mSyncAccount = null;
21073714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mSyncAccountType = null;
211eca82e9468c002590045338f98588ad3ce1a0bb3Erik
21273714169d34a55fc01e14b30897a1ebbacf9934eErik    // PROVIDER_NOTES owner account comes from the calendars table
21373714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mOwnerAccount = null;
21473714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mTitle = null;
21573714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mLocation = null;
21673714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mDescription = null;
21773714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mRrule = null;
21873714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mOrganizer = null;
219352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    public String mOrganizerDisplayName = null;
220352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    /**
221352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan     * Read-Only - Derived from other fields
222352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan     */
223eca82e9468c002590045338f98588ad3ce1a0bb3Erik    public boolean mIsOrganizer = true;
22473714169d34a55fc01e14b30897a1ebbacf9934eErik    public boolean mIsFirstEventInSeries = true;
22573714169d34a55fc01e14b30897a1ebbacf9934eErik
22673714169d34a55fc01e14b30897a1ebbacf9934eErik    // This should be set the same as mStart when created and is used for making changes to
22773714169d34a55fc01e14b30897a1ebbacf9934eErik    // recurring events. It should not be updated after it is initially set.
22873714169d34a55fc01e14b30897a1ebbacf9934eErik    public long mOriginalStart = -1;
22973714169d34a55fc01e14b30897a1ebbacf9934eErik    public long mStart = -1;
230eca82e9468c002590045338f98588ad3ce1a0bb3Erik
23173714169d34a55fc01e14b30897a1ebbacf9934eErik    // This should be set the same as mEnd when created and is used for making changes to
23273714169d34a55fc01e14b30897a1ebbacf9934eErik    // recurring events. It should not be updated after it is initially set.
23373714169d34a55fc01e14b30897a1ebbacf9934eErik    public long mOriginalEnd = -1;
23473714169d34a55fc01e14b30897a1ebbacf9934eErik    public long mEnd = -1;
23573714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mDuration = null;
23673714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mTimezone = null;
23773714169d34a55fc01e14b30897a1ebbacf9934eErik    public String mTimezone2 = null;
23873714169d34a55fc01e14b30897a1ebbacf9934eErik    public boolean mAllDay = false;
23973714169d34a55fc01e14b30897a1ebbacf9934eErik    public boolean mHasAlarm = false;
240c6680c5819b6ad0d1914420902746fe5f86ba403RoboErik    public int mAvailability = Events.AVAILABILITY_BUSY;
24173714169d34a55fc01e14b30897a1ebbacf9934eErik
24273714169d34a55fc01e14b30897a1ebbacf9934eErik    // PROVIDER_NOTES How does an event not have attendee data? The owner is added
24373714169d34a55fc01e14b30897a1ebbacf9934eErik    // as an attendee by default.
2446ae7d69b90f22fd51ab677036ba987dbdc35a62dErik    public boolean mHasAttendeeData = true;
24573714169d34a55fc01e14b30897a1ebbacf9934eErik    public int mSelfAttendeeStatus = -1;
246d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    public int mOwnerAttendeeId = -1;
24728dab653f55caccbed32f700274f5274abaee089RoboErik    public String mOriginalSyncId = null;
24828dab653f55caccbed32f700274f5274abaee089RoboErik    public long mOriginalId = -1;
24973714169d34a55fc01e14b30897a1ebbacf9934eErik    public Long mOriginalTime = null;
25073714169d34a55fc01e14b30897a1ebbacf9934eErik    public Boolean mOriginalAllDay = null;
25173714169d34a55fc01e14b30897a1ebbacf9934eErik    public boolean mGuestsCanModify = false;
25273714169d34a55fc01e14b30897a1ebbacf9934eErik    public boolean mGuestsCanInviteOthers = false;
25373714169d34a55fc01e14b30897a1ebbacf9934eErik    public boolean mGuestsCanSeeGuests = false;
25473714169d34a55fc01e14b30897a1ebbacf9934eErik
255352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    public boolean mOrganizerCanRespond = false;
256ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik    public int mCalendarAccessLevel = Calendars.CAL_ACCESS_CONTRIBUTOR;
257352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
258e3f85db16cfc50b25b97c64d8ab99820d579e5deMichael Chan    public int mEventStatus = Events.STATUS_CONFIRMED;
259e3f85db16cfc50b25b97c64d8ab99820d579e5deMichael Chan
260352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    // The model can't be updated with a calendar cursor until it has been
261352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    // updated with an event cursor.
262352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    public boolean mModelUpdatedWithEventCursor;
263352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
264ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan    public int mAccessLevel = 0;
265fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden    public ArrayList<ReminderEntry> mReminders;
2669645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden    public ArrayList<ReminderEntry> mDefaultReminders;
267eca82e9468c002590045338f98588ad3ce1a0bb3Erik
26873714169d34a55fc01e14b30897a1ebbacf9934eErik    // PROVIDER_NOTES Using EditEventHelper the owner should not be included in this
26973714169d34a55fc01e14b30897a1ebbacf9934eErik    // list and will instead be added by saveEvent. Is this what we want?
270d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    public LinkedHashMap<String, Attendee> mAttendeesList;
27173714169d34a55fc01e14b30897a1ebbacf9934eErik
27273714169d34a55fc01e14b30897a1ebbacf9934eErik    public CalendarEventModel() {
273fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        mReminders = new ArrayList<ReminderEntry>();
2749645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden        mDefaultReminders = new ArrayList<ReminderEntry>();
275d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        mAttendeesList = new LinkedHashMap<String, Attendee>();
2766ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        mTimezone = TimeZone.getDefault().getID();
27773714169d34a55fc01e14b30897a1ebbacf9934eErik    }
27873714169d34a55fc01e14b30897a1ebbacf9934eErik
2796ae7d69b90f22fd51ab677036ba987dbdc35a62dErik    public CalendarEventModel(Context context) {
2806ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        this();
2816ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
2828a5489641442c022089ae1b00e498e2c1a0ba480Erik        mTimezone = Utils.getTimeZone(context, null);
2834b441bd6544fe6d11be75f974a41afd8fa040a4fDaisuke Miyakawa        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context);
2849d8a376b89fcc36c44d4df0c5cbf6991306131c4Michael Chan
2859d8a376b89fcc36c44d4df0c5cbf6991306131c4Michael Chan        String defaultReminder = prefs.getString(
2869d8a376b89fcc36c44d4df0c5cbf6991306131c4Michael Chan                GeneralPreferences.KEY_DEFAULT_REMINDER, GeneralPreferences.NO_REMINDER_STRING);
2876ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        int defaultReminderMins = Integer.parseInt(defaultReminder);
2889d8a376b89fcc36c44d4df0c5cbf6991306131c4Michael Chan        if (defaultReminderMins != GeneralPreferences.NO_REMINDER) {
2899645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            // Assume all calendars allow at least one reminder.
2906ae7d69b90f22fd51ab677036ba987dbdc35a62dErik            mHasAlarm = true;
291fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            mReminders.add(ReminderEntry.valueOf(defaultReminderMins));
2929645d9c3e9b2cfd35c5fc89f41caf6e99153ba10Andy McFadden            mDefaultReminders.add(ReminderEntry.valueOf(defaultReminderMins));
2936ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        }
2946ae7d69b90f22fd51ab677036ba987dbdc35a62dErik    }
2956ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
2966ae7d69b90f22fd51ab677036ba987dbdc35a62dErik    public CalendarEventModel(Context context, Intent intent) {
2976ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        this(context);
2986ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
299c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan        if (intent == null) {
300c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan            return;
301c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan        }
302c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan
3036ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        String title = intent.getStringExtra(Events.TITLE);
3046ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        if (title != null) {
3056ae7d69b90f22fd51ab677036ba987dbdc35a62dErik            mTitle = title;
3066ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        }
3076ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
3086ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        String location = intent.getStringExtra(Events.EVENT_LOCATION);
3096ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        if (location != null) {
3106ae7d69b90f22fd51ab677036ba987dbdc35a62dErik            mLocation = location;
3116ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        }
3126ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
3136ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        String description = intent.getStringExtra(Events.DESCRIPTION);
3146ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        if (description != null) {
3156ae7d69b90f22fd51ab677036ba987dbdc35a62dErik            mDescription = description;
3166ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        }
3176ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
318ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan        int availability = intent.getIntExtra(Events.AVAILABILITY, -1);
319ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan        if (availability != -1) {
320c6680c5819b6ad0d1914420902746fe5f86ba403RoboErik            mAvailability = availability;
3216ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        }
3226ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
323ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan        int accessLevel = intent.getIntExtra(Events.ACCESS_LEVEL, -1);
324ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan        if (accessLevel != -1) {
325510e5ab4f1f6c8e8d9fb9684ed29d4a9c0d03cdeRoboErik            if (accessLevel > 0) {
326510e5ab4f1f6c8e8d9fb9684ed29d4a9c0d03cdeRoboErik                // TODO remove this if we add support for
327510e5ab4f1f6c8e8d9fb9684ed29d4a9c0d03cdeRoboErik                // Events.ACCESS_CONFIDENTIAL
328510e5ab4f1f6c8e8d9fb9684ed29d4a9c0d03cdeRoboErik                accessLevel--;
329510e5ab4f1f6c8e8d9fb9684ed29d4a9c0d03cdeRoboErik            }
330ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan            mAccessLevel = accessLevel;
3316ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        }
3326ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
3336ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        String rrule = intent.getStringExtra(Events.RRULE);
33466b2067e0a389180f909eb0a528bea5f6becca23Michael Chan        if (!TextUtils.isEmpty(rrule)) {
3356ae7d69b90f22fd51ab677036ba987dbdc35a62dErik            mRrule = rrule;
3366ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        }
337c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan
338c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan        String emails = intent.getStringExtra(Intent.EXTRA_EMAIL);
339c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan        if (!TextUtils.isEmpty(emails)) {
340c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan            String[] emailArray = emails.split("[ ,;]");
341c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan            for (String email : emailArray) {
342c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan                if (!TextUtils.isEmpty(email) && email.contains("@")) {
343c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan                    email = email.trim();
344c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan                    if (!mAttendeesList.containsKey(email)) {
345c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan                        mAttendeesList.put(email, new Attendee("", email));
346c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan                    }
347c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan                }
348c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan            }
349c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9Michael Chan        }
3506ae7d69b90f22fd51ab677036ba987dbdc35a62dErik    }
3516ae7d69b90f22fd51ab677036ba987dbdc35a62dErik
35273714169d34a55fc01e14b30897a1ebbacf9934eErik    public boolean isValid() {
35373714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mCalendarId == -1) {
35473714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
35573714169d34a55fc01e14b30897a1ebbacf9934eErik        }
35673714169d34a55fc01e14b30897a1ebbacf9934eErik        if (TextUtils.isEmpty(mOwnerAccount)) {
35773714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
35873714169d34a55fc01e14b30897a1ebbacf9934eErik        }
35973714169d34a55fc01e14b30897a1ebbacf9934eErik        return true;
36073714169d34a55fc01e14b30897a1ebbacf9934eErik    }
36173714169d34a55fc01e14b30897a1ebbacf9934eErik
36273714169d34a55fc01e14b30897a1ebbacf9934eErik    private boolean isEmpty() {
363d0fb2dd416a59e29f85435255ace75045a72886cMichael Chan        if (mTitle != null && mTitle.length() > 0) {
36473714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
36573714169d34a55fc01e14b30897a1ebbacf9934eErik        }
36673714169d34a55fc01e14b30897a1ebbacf9934eErik
367d0fb2dd416a59e29f85435255ace75045a72886cMichael Chan        if (mLocation != null && mLocation.length() > 0) {
36873714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
36973714169d34a55fc01e14b30897a1ebbacf9934eErik        }
37073714169d34a55fc01e14b30897a1ebbacf9934eErik
371d0fb2dd416a59e29f85435255ace75045a72886cMichael Chan        if (mDescription != null && mDescription.length() > 0) {
37273714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
37373714169d34a55fc01e14b30897a1ebbacf9934eErik        }
37473714169d34a55fc01e14b30897a1ebbacf9934eErik
37573714169d34a55fc01e14b30897a1ebbacf9934eErik        return true;
37673714169d34a55fc01e14b30897a1ebbacf9934eErik    }
37773714169d34a55fc01e14b30897a1ebbacf9934eErik
37873714169d34a55fc01e14b30897a1ebbacf9934eErik    public void clear() {
37973714169d34a55fc01e14b30897a1ebbacf9934eErik        mUri = null;
38073714169d34a55fc01e14b30897a1ebbacf9934eErik        mId = -1;
38173714169d34a55fc01e14b30897a1ebbacf9934eErik        mCalendarId = -1;
38273714169d34a55fc01e14b30897a1ebbacf9934eErik
38373714169d34a55fc01e14b30897a1ebbacf9934eErik        mSyncId = null;
38473714169d34a55fc01e14b30897a1ebbacf9934eErik        mSyncAccount = null;
38573714169d34a55fc01e14b30897a1ebbacf9934eErik        mSyncAccountType = null;
38673714169d34a55fc01e14b30897a1ebbacf9934eErik        mOwnerAccount = null;
38773714169d34a55fc01e14b30897a1ebbacf9934eErik
38873714169d34a55fc01e14b30897a1ebbacf9934eErik        mTitle = null;
38973714169d34a55fc01e14b30897a1ebbacf9934eErik        mLocation = null;
39073714169d34a55fc01e14b30897a1ebbacf9934eErik        mDescription = null;
39173714169d34a55fc01e14b30897a1ebbacf9934eErik        mRrule = null;
39273714169d34a55fc01e14b30897a1ebbacf9934eErik        mOrganizer = null;
393352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan        mOrganizerDisplayName = null;
394eca82e9468c002590045338f98588ad3ce1a0bb3Erik        mIsOrganizer = true;
39573714169d34a55fc01e14b30897a1ebbacf9934eErik        mIsFirstEventInSeries = true;
39673714169d34a55fc01e14b30897a1ebbacf9934eErik
39773714169d34a55fc01e14b30897a1ebbacf9934eErik        mOriginalStart = -1;
39873714169d34a55fc01e14b30897a1ebbacf9934eErik        mStart = -1;
39973714169d34a55fc01e14b30897a1ebbacf9934eErik        mOriginalEnd = -1;
40073714169d34a55fc01e14b30897a1ebbacf9934eErik        mEnd = -1;
40173714169d34a55fc01e14b30897a1ebbacf9934eErik        mDuration = null;
40273714169d34a55fc01e14b30897a1ebbacf9934eErik        mTimezone = null;
40373714169d34a55fc01e14b30897a1ebbacf9934eErik        mTimezone2 = null;
40473714169d34a55fc01e14b30897a1ebbacf9934eErik        mAllDay = false;
40573714169d34a55fc01e14b30897a1ebbacf9934eErik        mHasAlarm = false;
40673714169d34a55fc01e14b30897a1ebbacf9934eErik
4076ae7d69b90f22fd51ab677036ba987dbdc35a62dErik        mHasAttendeeData = true;
40873714169d34a55fc01e14b30897a1ebbacf9934eErik        mSelfAttendeeStatus = -1;
409d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        mOwnerAttendeeId = -1;
41028dab653f55caccbed32f700274f5274abaee089RoboErik        mOriginalId = -1;
41128dab653f55caccbed32f700274f5274abaee089RoboErik        mOriginalSyncId = null;
41273714169d34a55fc01e14b30897a1ebbacf9934eErik        mOriginalTime = null;
41373714169d34a55fc01e14b30897a1ebbacf9934eErik        mOriginalAllDay = null;
41473714169d34a55fc01e14b30897a1ebbacf9934eErik
41573714169d34a55fc01e14b30897a1ebbacf9934eErik        mGuestsCanModify = false;
41673714169d34a55fc01e14b30897a1ebbacf9934eErik        mGuestsCanInviteOthers = false;
41773714169d34a55fc01e14b30897a1ebbacf9934eErik        mGuestsCanSeeGuests = false;
418ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan        mAccessLevel = 0;
419e3f85db16cfc50b25b97c64d8ab99820d579e5deMichael Chan        mEventStatus = Events.STATUS_CONFIRMED;
420304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan        mOrganizerCanRespond = false;
421ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik        mCalendarAccessLevel = Calendars.CAL_ACCESS_CONTRIBUTOR;
422304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan        mModelUpdatedWithEventCursor = false;
423c6680c5819b6ad0d1914420902746fe5f86ba403RoboErik        mCalendarAllowedReminders = null;
424c6680c5819b6ad0d1914420902746fe5f86ba403RoboErik        mCalendarAllowedAttendeeTypes = null;
425c6680c5819b6ad0d1914420902746fe5f86ba403RoboErik        mCalendarAllowedAvailability = null;
42673714169d34a55fc01e14b30897a1ebbacf9934eErik
427fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        mReminders = new ArrayList<ReminderEntry>();
428d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        mAttendeesList.clear();
429d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    }
430d845fbe558d5229102b58cce70a1b29fe6cb6967Erik
431d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    public void addAttendee(Attendee attendee) {
432d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        mAttendeesList.put(attendee.mEmail, attendee);
433d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    }
434d845fbe558d5229102b58cce70a1b29fe6cb6967Erik
43518cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira    public void addAttendees(String attendees, Rfc822Validator validator) {
43618cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira        final LinkedHashSet<Rfc822Token> addresses = EditEventHelper.getAddressesFromList(
43718cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira                attendees, validator);
43818cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira        synchronized (this) {
43918cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira            for (final Rfc822Token address : addresses) {
44018cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira                final Attendee attendee = new Attendee(address.getName(), address.getAddress());
44118cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira                if (TextUtils.isEmpty(attendee.mName)) {
44218cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira                    attendee.mName = attendee.mEmail;
44318cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira                }
44418cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira                addAttendee(attendee);
44518cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira            }
44618cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira        }
44718cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira    }
44818cabd263b91d7d09f3b93b0bf6c78533bbc2c6aMindy Pereira
449d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    public void removeAttendee(Attendee attendee) {
450d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        mAttendeesList.remove(attendee.mEmail);
451d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    }
452d845fbe558d5229102b58cce70a1b29fe6cb6967Erik
453d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    public String getAttendeesString() {
454d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        StringBuilder b = new StringBuilder();
455d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        for (Attendee attendee : mAttendeesList.values()) {
456d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            String name = attendee.mName;
457d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            String email = attendee.mEmail;
458d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            String status = Integer.toString(attendee.mStatus);
459d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            b.append("name:").append(name);
460d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            b.append(" email:").append(email);
461d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            b.append(" status:").append(status);
462d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        }
463d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        return b.toString();
46473714169d34a55fc01e14b30897a1ebbacf9934eErik    }
46573714169d34a55fc01e14b30897a1ebbacf9934eErik
46673714169d34a55fc01e14b30897a1ebbacf9934eErik    @Override
46773714169d34a55fc01e14b30897a1ebbacf9934eErik    public int hashCode() {
46873714169d34a55fc01e14b30897a1ebbacf9934eErik        final int prime = 31;
46973714169d34a55fc01e14b30897a1ebbacf9934eErik        int result = 1;
47073714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (mAllDay ? 1231 : 1237);
471d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        result = prime * result + ((mAttendeesList == null) ? 0 : getAttendeesString().hashCode());
472eca82e9468c002590045338f98588ad3ce1a0bb3Erik        result = prime * result + (int) (mCalendarId ^ (mCalendarId >>> 32));
47373714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mDescription == null) ? 0 : mDescription.hashCode());
47473714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mDuration == null) ? 0 : mDuration.hashCode());
47573714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (int) (mEnd ^ (mEnd >>> 32));
47673714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (mGuestsCanInviteOthers ? 1231 : 1237);
47773714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (mGuestsCanModify ? 1231 : 1237);
47873714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (mGuestsCanSeeGuests ? 1231 : 1237);
479304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan        result = prime * result + (mOrganizerCanRespond ? 1231 : 1237);
480304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan        result = prime * result + (mModelUpdatedWithEventCursor ? 1231 : 1237);
481304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan        result = prime * result + mCalendarAccessLevel;
48273714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (mHasAlarm ? 1231 : 1237);
48373714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (mHasAttendeeData ? 1231 : 1237);
484eca82e9468c002590045338f98588ad3ce1a0bb3Erik        result = prime * result + (int) (mId ^ (mId >>> 32));
48573714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (mIsFirstEventInSeries ? 1231 : 1237);
48673714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (mIsOrganizer ? 1231 : 1237);
48773714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mLocation == null) ? 0 : mLocation.hashCode());
48873714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mOrganizer == null) ? 0 : mOrganizer.hashCode());
48973714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mOriginalAllDay == null) ? 0 : mOriginalAllDay.hashCode());
49073714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (int) (mOriginalEnd ^ (mOriginalEnd >>> 32));
49128dab653f55caccbed32f700274f5274abaee089RoboErik        result = prime * result + ((mOriginalSyncId == null) ? 0 : mOriginalSyncId.hashCode());
49228dab653f55caccbed32f700274f5274abaee089RoboErik        result = prime * result + (int) (mOriginalId ^ (mOriginalEnd >>> 32));
49373714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (int) (mOriginalStart ^ (mOriginalStart >>> 32));
49473714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mOriginalTime == null) ? 0 : mOriginalTime.hashCode());
49573714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mOwnerAccount == null) ? 0 : mOwnerAccount.hashCode());
496fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        result = prime * result + ((mReminders == null) ? 0 : mReminders.hashCode());
49773714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mRrule == null) ? 0 : mRrule.hashCode());
49873714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + mSelfAttendeeStatus;
499d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        result = prime * result + mOwnerAttendeeId;
50073714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + (int) (mStart ^ (mStart >>> 32));
50173714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mSyncAccount == null) ? 0 : mSyncAccount.hashCode());
50273714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mSyncAccountType == null) ? 0 : mSyncAccountType.hashCode());
50373714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mSyncId == null) ? 0 : mSyncId.hashCode());
50473714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mTimezone == null) ? 0 : mTimezone.hashCode());
50573714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mTimezone2 == null) ? 0 : mTimezone2.hashCode());
50673714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mTitle == null) ? 0 : mTitle.hashCode());
507c6680c5819b6ad0d1914420902746fe5f86ba403RoboErik        result = prime * result + (mAvailability);
50873714169d34a55fc01e14b30897a1ebbacf9934eErik        result = prime * result + ((mUri == null) ? 0 : mUri.hashCode());
509ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan        result = prime * result + mAccessLevel;
510e3f85db16cfc50b25b97c64d8ab99820d579e5deMichael Chan        result = prime * result + mEventStatus;
51173714169d34a55fc01e14b30897a1ebbacf9934eErik        return result;
51273714169d34a55fc01e14b30897a1ebbacf9934eErik    }
51373714169d34a55fc01e14b30897a1ebbacf9934eErik
51473714169d34a55fc01e14b30897a1ebbacf9934eErik    // Autogenerated equals method
51573714169d34a55fc01e14b30897a1ebbacf9934eErik    @Override
51673714169d34a55fc01e14b30897a1ebbacf9934eErik    public boolean equals(Object obj) {
51773714169d34a55fc01e14b30897a1ebbacf9934eErik        if (this == obj) {
51873714169d34a55fc01e14b30897a1ebbacf9934eErik            return true;
51973714169d34a55fc01e14b30897a1ebbacf9934eErik        }
52073714169d34a55fc01e14b30897a1ebbacf9934eErik        if (obj == null) {
52173714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
52273714169d34a55fc01e14b30897a1ebbacf9934eErik        }
52373714169d34a55fc01e14b30897a1ebbacf9934eErik        if (!(obj instanceof CalendarEventModel)) {
52473714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
52573714169d34a55fc01e14b30897a1ebbacf9934eErik        }
52673714169d34a55fc01e14b30897a1ebbacf9934eErik
52773714169d34a55fc01e14b30897a1ebbacf9934eErik        CalendarEventModel other = (CalendarEventModel) obj;
528a7694eead7cbb293990bc89c3906e17bad36194cErik        if (!checkOriginalModelFields(other)) {
529a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
530a7694eead7cbb293990bc89c3906e17bad36194cErik        }
531a7694eead7cbb293990bc89c3906e17bad36194cErik
53228dab653f55caccbed32f700274f5274abaee089RoboErik        if (mLocation == null) {
53328dab653f55caccbed32f700274f5274abaee089RoboErik            if (other.mLocation != null) {
53428dab653f55caccbed32f700274f5274abaee089RoboErik                return false;
53528dab653f55caccbed32f700274f5274abaee089RoboErik            }
53628dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mLocation.equals(other.mLocation)) {
53728dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
53828dab653f55caccbed32f700274f5274abaee089RoboErik        }
53928dab653f55caccbed32f700274f5274abaee089RoboErik
54028dab653f55caccbed32f700274f5274abaee089RoboErik        if (mTitle == null) {
54128dab653f55caccbed32f700274f5274abaee089RoboErik            if (other.mTitle != null) {
54228dab653f55caccbed32f700274f5274abaee089RoboErik                return false;
54328dab653f55caccbed32f700274f5274abaee089RoboErik            }
54428dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mTitle.equals(other.mTitle)) {
54528dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
54628dab653f55caccbed32f700274f5274abaee089RoboErik        }
54728dab653f55caccbed32f700274f5274abaee089RoboErik
54828dab653f55caccbed32f700274f5274abaee089RoboErik        if (mDescription == null) {
54928dab653f55caccbed32f700274f5274abaee089RoboErik            if (other.mDescription != null) {
55028dab653f55caccbed32f700274f5274abaee089RoboErik                return false;
55128dab653f55caccbed32f700274f5274abaee089RoboErik            }
55228dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mDescription.equals(other.mDescription)) {
55328dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
55428dab653f55caccbed32f700274f5274abaee089RoboErik        }
55528dab653f55caccbed32f700274f5274abaee089RoboErik
55628dab653f55caccbed32f700274f5274abaee089RoboErik        if (mDuration == null) {
55728dab653f55caccbed32f700274f5274abaee089RoboErik            if (other.mDuration != null) {
55828dab653f55caccbed32f700274f5274abaee089RoboErik                return false;
55928dab653f55caccbed32f700274f5274abaee089RoboErik            }
56028dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mDuration.equals(other.mDuration)) {
56128dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
56228dab653f55caccbed32f700274f5274abaee089RoboErik        }
56328dab653f55caccbed32f700274f5274abaee089RoboErik
564a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mEnd != other.mEnd) {
565a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
566a7694eead7cbb293990bc89c3906e17bad36194cErik        }
567a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mIsFirstEventInSeries != other.mIsFirstEventInSeries) {
568a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
569a7694eead7cbb293990bc89c3906e17bad36194cErik        }
570a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mOriginalEnd != other.mOriginalEnd) {
571a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
572a7694eead7cbb293990bc89c3906e17bad36194cErik        }
573a7694eead7cbb293990bc89c3906e17bad36194cErik
574a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mOriginalStart != other.mOriginalStart) {
575a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
576a7694eead7cbb293990bc89c3906e17bad36194cErik        }
577a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mStart != other.mStart) {
578a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
579a7694eead7cbb293990bc89c3906e17bad36194cErik        }
58031eb9e37d743f4286378ab697cad3a89ba3522abErik
58128dab653f55caccbed32f700274f5274abaee089RoboErik        if (mOriginalId != other.mOriginalId) {
58228dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
58328dab653f55caccbed32f700274f5274abaee089RoboErik        }
58428dab653f55caccbed32f700274f5274abaee089RoboErik
58528dab653f55caccbed32f700274f5274abaee089RoboErik        if (mOriginalSyncId == null) {
58628dab653f55caccbed32f700274f5274abaee089RoboErik            if (other.mOriginalSyncId != null) {
58731eb9e37d743f4286378ab697cad3a89ba3522abErik                return false;
58831eb9e37d743f4286378ab697cad3a89ba3522abErik            }
58928dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mOriginalSyncId.equals(other.mOriginalSyncId)) {
59031eb9e37d743f4286378ab697cad3a89ba3522abErik            return false;
59131eb9e37d743f4286378ab697cad3a89ba3522abErik        }
59231eb9e37d743f4286378ab697cad3a89ba3522abErik
59331eb9e37d743f4286378ab697cad3a89ba3522abErik        if (mRrule == null) {
59431eb9e37d743f4286378ab697cad3a89ba3522abErik            if (other.mRrule != null) {
59531eb9e37d743f4286378ab697cad3a89ba3522abErik                return false;
59631eb9e37d743f4286378ab697cad3a89ba3522abErik            }
59731eb9e37d743f4286378ab697cad3a89ba3522abErik        } else if (!mRrule.equals(other.mRrule)) {
59831eb9e37d743f4286378ab697cad3a89ba3522abErik            return false;
59931eb9e37d743f4286378ab697cad3a89ba3522abErik        }
600a7694eead7cbb293990bc89c3906e17bad36194cErik        return true;
601a7694eead7cbb293990bc89c3906e17bad36194cErik    }
602a7694eead7cbb293990bc89c3906e17bad36194cErik
603a7694eead7cbb293990bc89c3906e17bad36194cErik    /**
604a7694eead7cbb293990bc89c3906e17bad36194cErik     * Whether the event has been modified based on its original model.
605a7694eead7cbb293990bc89c3906e17bad36194cErik     *
606a7694eead7cbb293990bc89c3906e17bad36194cErik     * @param originalModel
607a7694eead7cbb293990bc89c3906e17bad36194cErik     * @return true if the model is unchanged, false otherwise
608a7694eead7cbb293990bc89c3906e17bad36194cErik     */
609a7694eead7cbb293990bc89c3906e17bad36194cErik    public boolean isUnchanged(CalendarEventModel originalModel) {
610a7694eead7cbb293990bc89c3906e17bad36194cErik        if (this == originalModel) {
611a7694eead7cbb293990bc89c3906e17bad36194cErik            return true;
612a7694eead7cbb293990bc89c3906e17bad36194cErik        }
613a7694eead7cbb293990bc89c3906e17bad36194cErik        if (originalModel == null) {
614a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
615a7694eead7cbb293990bc89c3906e17bad36194cErik        }
616a7694eead7cbb293990bc89c3906e17bad36194cErik
617a7694eead7cbb293990bc89c3906e17bad36194cErik        if (!checkOriginalModelFields(originalModel)) {
618a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
619a7694eead7cbb293990bc89c3906e17bad36194cErik        }
62028dab653f55caccbed32f700274f5274abaee089RoboErik
62128dab653f55caccbed32f700274f5274abaee089RoboErik        if (TextUtils.isEmpty(mLocation)) {
62228dab653f55caccbed32f700274f5274abaee089RoboErik            if (!TextUtils.isEmpty(originalModel.mLocation)) {
62328dab653f55caccbed32f700274f5274abaee089RoboErik                return false;
62428dab653f55caccbed32f700274f5274abaee089RoboErik            }
62528dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mLocation.equals(originalModel.mLocation)) {
62628dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
62728dab653f55caccbed32f700274f5274abaee089RoboErik        }
62828dab653f55caccbed32f700274f5274abaee089RoboErik
62928dab653f55caccbed32f700274f5274abaee089RoboErik        if (TextUtils.isEmpty(mTitle)) {
63028dab653f55caccbed32f700274f5274abaee089RoboErik            if (!TextUtils.isEmpty(originalModel.mTitle)) {
63128dab653f55caccbed32f700274f5274abaee089RoboErik                return false;
63228dab653f55caccbed32f700274f5274abaee089RoboErik            }
63328dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mTitle.equals(originalModel.mTitle)) {
63428dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
63528dab653f55caccbed32f700274f5274abaee089RoboErik        }
63628dab653f55caccbed32f700274f5274abaee089RoboErik
63728dab653f55caccbed32f700274f5274abaee089RoboErik        if (TextUtils.isEmpty(mDescription)) {
63828dab653f55caccbed32f700274f5274abaee089RoboErik            if (!TextUtils.isEmpty(originalModel.mDescription)) {
63928dab653f55caccbed32f700274f5274abaee089RoboErik                return false;
64028dab653f55caccbed32f700274f5274abaee089RoboErik            }
64128dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mDescription.equals(originalModel.mDescription)) {
64228dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
64328dab653f55caccbed32f700274f5274abaee089RoboErik        }
64428dab653f55caccbed32f700274f5274abaee089RoboErik
64528dab653f55caccbed32f700274f5274abaee089RoboErik        if (TextUtils.isEmpty(mDuration)) {
64628dab653f55caccbed32f700274f5274abaee089RoboErik            if (!TextUtils.isEmpty(originalModel.mDuration)) {
64728dab653f55caccbed32f700274f5274abaee089RoboErik                return false;
64828dab653f55caccbed32f700274f5274abaee089RoboErik            }
64928dab653f55caccbed32f700274f5274abaee089RoboErik        } else if (!mDuration.equals(originalModel.mDuration)) {
65028dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
65128dab653f55caccbed32f700274f5274abaee089RoboErik        }
65228dab653f55caccbed32f700274f5274abaee089RoboErik
653a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mEnd != mOriginalEnd) {
654a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
655a7694eead7cbb293990bc89c3906e17bad36194cErik        }
656a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mStart != mOriginalStart) {
657a7694eead7cbb293990bc89c3906e17bad36194cErik            return false;
658a7694eead7cbb293990bc89c3906e17bad36194cErik        }
659a7694eead7cbb293990bc89c3906e17bad36194cErik
66028dab653f55caccbed32f700274f5274abaee089RoboErik        // If this changed the original id and it's not just an exception to the
66128dab653f55caccbed32f700274f5274abaee089RoboErik        // original event
66228dab653f55caccbed32f700274f5274abaee089RoboErik        if (mOriginalId != originalModel.mOriginalId && mOriginalId != originalModel.mId) {
66328dab653f55caccbed32f700274f5274abaee089RoboErik            return false;
66428dab653f55caccbed32f700274f5274abaee089RoboErik        }
66528dab653f55caccbed32f700274f5274abaee089RoboErik
66628dab653f55caccbed32f700274f5274abaee089RoboErik        if (TextUtils.isEmpty(mRrule)) {
66728dab653f55caccbed32f700274f5274abaee089RoboErik            // if the rrule is no longer empty check if this is an exception
66828dab653f55caccbed32f700274f5274abaee089RoboErik            if (!TextUtils.isEmpty(originalModel.mRrule)) {
66928dab653f55caccbed32f700274f5274abaee089RoboErik                boolean syncIdNotReferenced = mOriginalSyncId == null
67028dab653f55caccbed32f700274f5274abaee089RoboErik                        || !mOriginalSyncId.equals(originalModel.mSyncId);
67128dab653f55caccbed32f700274f5274abaee089RoboErik                boolean localIdNotReferenced = mOriginalId == -1
67228dab653f55caccbed32f700274f5274abaee089RoboErik                        || !(mOriginalId == originalModel.mId);
67328dab653f55caccbed32f700274f5274abaee089RoboErik                if (syncIdNotReferenced && localIdNotReferenced) {
67431eb9e37d743f4286378ab697cad3a89ba3522abErik                    return false;
67531eb9e37d743f4286378ab697cad3a89ba3522abErik                }
67631eb9e37d743f4286378ab697cad3a89ba3522abErik            }
67731eb9e37d743f4286378ab697cad3a89ba3522abErik        } else if (!mRrule.equals(originalModel.mRrule)) {
67831eb9e37d743f4286378ab697cad3a89ba3522abErik            return false;
67931eb9e37d743f4286378ab697cad3a89ba3522abErik        }
68031eb9e37d743f4286378ab697cad3a89ba3522abErik
681a7694eead7cbb293990bc89c3906e17bad36194cErik        return true;
682a7694eead7cbb293990bc89c3906e17bad36194cErik    }
683a7694eead7cbb293990bc89c3906e17bad36194cErik
684a7694eead7cbb293990bc89c3906e17bad36194cErik    /**
685a7694eead7cbb293990bc89c3906e17bad36194cErik     * Checks against an original model for changes to an event. This covers all
686a7694eead7cbb293990bc89c3906e17bad36194cErik     * the fields that should remain consistent between an original event model
687a7694eead7cbb293990bc89c3906e17bad36194cErik     * and the new one if nothing in the event was modified. This is also the
688a7694eead7cbb293990bc89c3906e17bad36194cErik     * portion that overlaps with equality between two event models.
689a7694eead7cbb293990bc89c3906e17bad36194cErik     *
690a7694eead7cbb293990bc89c3906e17bad36194cErik     * @param originalModel
691a7694eead7cbb293990bc89c3906e17bad36194cErik     * @return true if these fields are unchanged, false otherwise
692a7694eead7cbb293990bc89c3906e17bad36194cErik     */
693a7694eead7cbb293990bc89c3906e17bad36194cErik    protected boolean checkOriginalModelFields(CalendarEventModel originalModel) {
694a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mAllDay != originalModel.mAllDay) {
69573714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
69673714169d34a55fc01e14b30897a1ebbacf9934eErik        }
697d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        if (mAttendeesList == null) {
698a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mAttendeesList != null) {
69973714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
70073714169d34a55fc01e14b30897a1ebbacf9934eErik            }
701d0fb2dd416a59e29f85435255ace75045a72886cMichael Chan        } else if (!mAttendeesList.equals(originalModel.mAttendeesList)) {
70273714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
70373714169d34a55fc01e14b30897a1ebbacf9934eErik        }
70473714169d34a55fc01e14b30897a1ebbacf9934eErik
705a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mCalendarId != originalModel.mCalendarId) {
70673714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
70773714169d34a55fc01e14b30897a1ebbacf9934eErik        }
70873714169d34a55fc01e14b30897a1ebbacf9934eErik
709a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mGuestsCanInviteOthers != originalModel.mGuestsCanInviteOthers) {
71073714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
71173714169d34a55fc01e14b30897a1ebbacf9934eErik        }
712a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mGuestsCanModify != originalModel.mGuestsCanModify) {
71373714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
71473714169d34a55fc01e14b30897a1ebbacf9934eErik        }
715a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mGuestsCanSeeGuests != originalModel.mGuestsCanSeeGuests) {
71673714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
71773714169d34a55fc01e14b30897a1ebbacf9934eErik        }
718a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mOrganizerCanRespond != originalModel.mOrganizerCanRespond) {
71973714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
72073714169d34a55fc01e14b30897a1ebbacf9934eErik        }
721a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mCalendarAccessLevel != originalModel.mCalendarAccessLevel) {
722304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan            return false;
723304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan        }
724a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mModelUpdatedWithEventCursor != originalModel.mModelUpdatedWithEventCursor) {
725304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan            return false;
726304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan        }
727a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mHasAlarm != originalModel.mHasAlarm) {
728304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan            return false;
729304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan        }
730a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mHasAttendeeData != originalModel.mHasAttendeeData) {
73173714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
73273714169d34a55fc01e14b30897a1ebbacf9934eErik        }
733a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mId != originalModel.mId) {
73473714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
73573714169d34a55fc01e14b30897a1ebbacf9934eErik        }
736a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mIsOrganizer != originalModel.mIsOrganizer) {
73773714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
73873714169d34a55fc01e14b30897a1ebbacf9934eErik        }
73973714169d34a55fc01e14b30897a1ebbacf9934eErik
74073714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mOrganizer == null) {
741a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mOrganizer != null) {
74273714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
74373714169d34a55fc01e14b30897a1ebbacf9934eErik            }
744a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mOrganizer.equals(originalModel.mOrganizer)) {
74573714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
74673714169d34a55fc01e14b30897a1ebbacf9934eErik        }
74773714169d34a55fc01e14b30897a1ebbacf9934eErik
74873714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mOriginalAllDay == null) {
749a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mOriginalAllDay != null) {
75073714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
75173714169d34a55fc01e14b30897a1ebbacf9934eErik            }
752a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mOriginalAllDay.equals(originalModel.mOriginalAllDay)) {
75373714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
75473714169d34a55fc01e14b30897a1ebbacf9934eErik        }
75573714169d34a55fc01e14b30897a1ebbacf9934eErik
75673714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mOriginalTime == null) {
757a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mOriginalTime != null) {
75873714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
75973714169d34a55fc01e14b30897a1ebbacf9934eErik            }
760a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mOriginalTime.equals(originalModel.mOriginalTime)) {
76173714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
76273714169d34a55fc01e14b30897a1ebbacf9934eErik        }
76373714169d34a55fc01e14b30897a1ebbacf9934eErik
76473714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mOwnerAccount == null) {
765a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mOwnerAccount != null) {
76673714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
76773714169d34a55fc01e14b30897a1ebbacf9934eErik            }
768a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mOwnerAccount.equals(originalModel.mOwnerAccount)) {
76973714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
77073714169d34a55fc01e14b30897a1ebbacf9934eErik        }
77173714169d34a55fc01e14b30897a1ebbacf9934eErik
772fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        if (mReminders == null) {
773fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            if (originalModel.mReminders != null) {
77473714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
77573714169d34a55fc01e14b30897a1ebbacf9934eErik            }
776fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        } else if (!mReminders.equals(originalModel.mReminders)) {
77773714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
77873714169d34a55fc01e14b30897a1ebbacf9934eErik        }
77973714169d34a55fc01e14b30897a1ebbacf9934eErik
780a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mSelfAttendeeStatus != originalModel.mSelfAttendeeStatus) {
78173714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
78273714169d34a55fc01e14b30897a1ebbacf9934eErik        }
783a7694eead7cbb293990bc89c3906e17bad36194cErik        if (mOwnerAttendeeId != originalModel.mOwnerAttendeeId) {
78473714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
78573714169d34a55fc01e14b30897a1ebbacf9934eErik        }
78673714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mSyncAccount == null) {
787a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mSyncAccount != null) {
78873714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
78973714169d34a55fc01e14b30897a1ebbacf9934eErik            }
790a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mSyncAccount.equals(originalModel.mSyncAccount)) {
79173714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
79273714169d34a55fc01e14b30897a1ebbacf9934eErik        }
79373714169d34a55fc01e14b30897a1ebbacf9934eErik
79473714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mSyncAccountType == null) {
795a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mSyncAccountType != null) {
79673714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
79773714169d34a55fc01e14b30897a1ebbacf9934eErik            }
798a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mSyncAccountType.equals(originalModel.mSyncAccountType)) {
79973714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
80073714169d34a55fc01e14b30897a1ebbacf9934eErik        }
80173714169d34a55fc01e14b30897a1ebbacf9934eErik
80273714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mSyncId == null) {
803a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mSyncId != null) {
80473714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
80573714169d34a55fc01e14b30897a1ebbacf9934eErik            }
806a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mSyncId.equals(originalModel.mSyncId)) {
80773714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
80873714169d34a55fc01e14b30897a1ebbacf9934eErik        }
80973714169d34a55fc01e14b30897a1ebbacf9934eErik
81073714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mTimezone == null) {
811a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mTimezone != null) {
81273714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
81373714169d34a55fc01e14b30897a1ebbacf9934eErik            }
814a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mTimezone.equals(originalModel.mTimezone)) {
81573714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
81673714169d34a55fc01e14b30897a1ebbacf9934eErik        }
81773714169d34a55fc01e14b30897a1ebbacf9934eErik
81873714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mTimezone2 == null) {
819a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mTimezone2 != null) {
82073714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
82173714169d34a55fc01e14b30897a1ebbacf9934eErik            }
822a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mTimezone2.equals(originalModel.mTimezone2)) {
82373714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
82473714169d34a55fc01e14b30897a1ebbacf9934eErik        }
82573714169d34a55fc01e14b30897a1ebbacf9934eErik
826ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan        if (mAvailability != originalModel.mAvailability) {
82773714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
82873714169d34a55fc01e14b30897a1ebbacf9934eErik        }
82973714169d34a55fc01e14b30897a1ebbacf9934eErik
83073714169d34a55fc01e14b30897a1ebbacf9934eErik        if (mUri == null) {
831a7694eead7cbb293990bc89c3906e17bad36194cErik            if (originalModel.mUri != null) {
83273714169d34a55fc01e14b30897a1ebbacf9934eErik                return false;
83373714169d34a55fc01e14b30897a1ebbacf9934eErik            }
834a7694eead7cbb293990bc89c3906e17bad36194cErik        } else if (!mUri.equals(originalModel.mUri)) {
83573714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
83673714169d34a55fc01e14b30897a1ebbacf9934eErik        }
83773714169d34a55fc01e14b30897a1ebbacf9934eErik
838ced0eb67ef49c3203f72520c296e73d9cb4f654bMichael Chan        if (mAccessLevel != originalModel.mAccessLevel) {
83973714169d34a55fc01e14b30897a1ebbacf9934eErik            return false;
84073714169d34a55fc01e14b30897a1ebbacf9934eErik        }
841e3f85db16cfc50b25b97c64d8ab99820d579e5deMichael Chan
842e3f85db16cfc50b25b97c64d8ab99820d579e5deMichael Chan        if (mEventStatus != originalModel.mEventStatus) {
843e3f85db16cfc50b25b97c64d8ab99820d579e5deMichael Chan            return false;
844e3f85db16cfc50b25b97c64d8ab99820d579e5deMichael Chan        }
84573714169d34a55fc01e14b30897a1ebbacf9934eErik        return true;
84673714169d34a55fc01e14b30897a1ebbacf9934eErik    }
847ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden
848ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden    /**
849ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden     * Sort and uniquify mReminderMinutes.
850ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden     *
851fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden     * @return true (for convenience of caller)
852ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden     */
853ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden    public boolean normalizeReminders() {
854fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        if (mReminders.size() <= 1) {
855fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            return true;
856fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        }
857ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden
858fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        // sort
859fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        Collections.sort(mReminders);
860ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden
861fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        // remove duplicates
862fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        ReminderEntry prev = mReminders.get(mReminders.size()-1);
863fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden        for (int i = mReminders.size()-2; i >= 0; --i) {
864fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            ReminderEntry cur = mReminders.get(i);
865fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            if (prev.equals(cur)) {
866fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden                // match, remove later entry
867fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden                mReminders.remove(i+1);
868ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden            }
869fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden            prev = cur;
870ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden        }
871fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden
872ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden        return true;
873ae5bcce4a24c1ef3a2db2493b3dedd64a6aa35ffAndy McFadden    }
874fea9af5d69ad3e5687a4efd72d7d3adfb8d056c8Andy McFadden}
875