CalendarEventModel.java revision e3f85db16cfc50b25b97c64d8ab99820d579e5de
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17package com.android.calendar; 18 19import com.android.calendar.event.EditEventHelper; 20import com.android.common.Rfc822Validator; 21 22import android.content.Context; 23import android.content.Intent; 24import android.content.SharedPreferences; 25import android.provider.CalendarContract.Attendees; 26import android.provider.CalendarContract.Calendars; 27import android.provider.CalendarContract.Events; 28import android.provider.CalendarContract.Reminders; 29import android.text.TextUtils; 30import android.text.util.Rfc822Token; 31 32import java.io.Serializable; 33import java.util.ArrayList; 34import java.util.Collections; 35import java.util.LinkedHashMap; 36import java.util.LinkedHashSet; 37import java.util.TimeZone; 38 39/** 40 * Stores all the information needed to fill out an entry in the events table. 41 * This is a convenient way for storing information needed by the UI to write to 42 * the events table. Only fields that are important to the UI are included. 43 */ 44public class CalendarEventModel implements Serializable { 45 private static final String TAG = "CalendarEventModel"; 46 47 public static class Attendee implements Serializable { 48 @Override 49 public int hashCode() { 50 return (mEmail == null) ? 0 : mEmail.hashCode(); 51 } 52 53 @Override 54 public boolean equals(Object obj) { 55 if (this == obj) { 56 return true; 57 } 58 if (!(obj instanceof Attendee)) { 59 return false; 60 } 61 Attendee other = (Attendee) obj; 62 if (!TextUtils.equals(mEmail, other.mEmail)) { 63 return false; 64 } 65 return true; 66 } 67 68 String getDisplayName() { 69 if (TextUtils.isEmpty(mName)) { 70 return mEmail; 71 } else { 72 return mName; 73 } 74 } 75 76 public String mName; 77 public String mEmail; 78 public int mStatus; 79 80 public Attendee(String name, String email) { 81 mName = name; 82 mEmail = email; 83 mStatus = Attendees.ATTENDEE_STATUS_NONE; 84 } 85 public Attendee(String name, String email, int status) { 86 mName = name; 87 mEmail = email; 88 mStatus = status; 89 } 90 } 91 92 /** 93 * A single reminder entry. 94 * 95 * Instances of the class are immutable. 96 */ 97 public static class ReminderEntry implements Comparable<ReminderEntry>, Serializable { 98 private final int mMinutes; 99 private final int mMethod; 100 101 /** 102 * Returns a new ReminderEntry, with the specified minutes and method. 103 * 104 * @param minutes Number of minutes before the start of the event that the alert will fire. 105 * @param method Type of alert ({@link Reminders#METHOD_ALERT}, etc). 106 */ 107 public static ReminderEntry valueOf(int minutes, int method) { 108 // TODO: cache common instances 109 return new ReminderEntry(minutes, method); 110 } 111 112 /** 113 * Returns a ReminderEntry, with the specified number of minutes and a default alert method. 114 * 115 * @param minutes Number of minutes before the start of the event that the alert will fire. 116 */ 117 public static ReminderEntry valueOf(int minutes) { 118 return valueOf(minutes, Reminders.METHOD_DEFAULT); 119 } 120 121 /** 122 * Constructs a new ReminderEntry. 123 * 124 * @param minutes Number of minutes before the start of the event that the alert will fire. 125 * @param method Type of alert ({@link Reminders#METHOD_ALERT}, etc). 126 */ 127 private ReminderEntry(int minutes, int method) { 128 // TODO: error-check args 129 mMinutes = minutes; 130 mMethod = method; 131 } 132 133 @Override 134 public int hashCode() { 135 return mMinutes * 10 + mMethod; 136 } 137 138 @Override 139 public boolean equals(Object obj) { 140 if (this == obj) { 141 return true; 142 } 143 if (!(obj instanceof ReminderEntry)) { 144 return false; 145 } 146 147 ReminderEntry re = (ReminderEntry) obj; 148 149 if (re.mMinutes != mMinutes) { 150 return false; 151 } 152 153 // Treat ALERT and DEFAULT as equivalent. This is useful during the "has anything 154 // "changed" test, so that if DEFAULT is present, but we don't change anything, 155 // the internal conversion of DEFAULT to ALERT doesn't force a database update. 156 return re.mMethod == mMethod || 157 (re.mMethod == Reminders.METHOD_DEFAULT && mMethod == Reminders.METHOD_ALERT) || 158 (re.mMethod == Reminders.METHOD_ALERT && mMethod == Reminders.METHOD_DEFAULT); 159 } 160 161 @Override 162 public String toString() { 163 return "ReminderEntry min=" + mMinutes + " meth=" + mMethod; 164 } 165 166 /** 167 * Comparison function for a sort ordered primarily descending by minutes, 168 * secondarily ascending by method type. 169 */ 170 public int compareTo(ReminderEntry re) { 171 if (re.mMinutes != mMinutes) { 172 return re.mMinutes - mMinutes; 173 } 174 if (re.mMethod != mMethod) { 175 return mMethod - re.mMethod; 176 } 177 return 0; 178 } 179 180 /** Returns the minutes. */ 181 public int getMinutes() { 182 return mMinutes; 183 } 184 185 /** Returns the alert method. */ 186 public int getMethod() { 187 return mMethod; 188 } 189 } 190 191 // TODO strip out fields that don't ever get used 192 /** 193 * The uri of the event in the db. This should only be null for new events. 194 */ 195 public String mUri = null; 196 public long mId = -1; 197 public long mCalendarId = -1; 198 public String mCalendarDisplayName = ""; // Make sure this is in sync with the mCalendarId 199 public int mCalendarColor = 0; 200 public int mCalendarMaxReminders; 201 public String mCalendarAllowedReminders; 202 public String mCalendarAllowedAttendeeTypes; 203 public String mCalendarAllowedAvailability; 204 205 public String mSyncId = null; 206 public String mSyncAccount = null; 207 public String mSyncAccountType = null; 208 209 // PROVIDER_NOTES owner account comes from the calendars table 210 public String mOwnerAccount = null; 211 public String mTitle = null; 212 public String mLocation = null; 213 public String mDescription = null; 214 public String mRrule = null; 215 public String mOrganizer = null; 216 public String mOrganizerDisplayName = null; 217 /** 218 * Read-Only - Derived from other fields 219 */ 220 public boolean mIsOrganizer = true; 221 public boolean mIsFirstEventInSeries = true; 222 223 // This should be set the same as mStart when created and is used for making changes to 224 // recurring events. It should not be updated after it is initially set. 225 public long mOriginalStart = -1; 226 public long mStart = -1; 227 228 // This should be set the same as mEnd when created and is used for making changes to 229 // recurring events. It should not be updated after it is initially set. 230 public long mOriginalEnd = -1; 231 public long mEnd = -1; 232 public String mDuration = null; 233 public String mTimezone = null; 234 public String mTimezone2 = null; 235 public boolean mAllDay = false; 236 public boolean mHasAlarm = false; 237 public int mAvailability = Events.AVAILABILITY_BUSY; 238 239 // PROVIDER_NOTES How does an event not have attendee data? The owner is added 240 // as an attendee by default. 241 public boolean mHasAttendeeData = true; 242 public int mSelfAttendeeStatus = -1; 243 public int mOwnerAttendeeId = -1; 244 public String mOriginalSyncId = null; 245 public long mOriginalId = -1; 246 public Long mOriginalTime = null; 247 public Boolean mOriginalAllDay = null; 248 public boolean mGuestsCanModify = false; 249 public boolean mGuestsCanInviteOthers = false; 250 public boolean mGuestsCanSeeGuests = false; 251 252 public boolean mOrganizerCanRespond = false; 253 public int mCalendarAccessLevel = Calendars.CAL_ACCESS_CONTRIBUTOR; 254 255 public int mEventStatus = Events.STATUS_CONFIRMED; 256 257 // The model can't be updated with a calendar cursor until it has been 258 // updated with an event cursor. 259 public boolean mModelUpdatedWithEventCursor; 260 261 public int mAccessLevel = 0; 262 public ArrayList<ReminderEntry> mReminders; 263 public ArrayList<ReminderEntry> mDefaultReminders; 264 265 // PROVIDER_NOTES Using EditEventHelper the owner should not be included in this 266 // list and will instead be added by saveEvent. Is this what we want? 267 public LinkedHashMap<String, Attendee> mAttendeesList; 268 269 public CalendarEventModel() { 270 mReminders = new ArrayList<ReminderEntry>(); 271 mDefaultReminders = new ArrayList<ReminderEntry>(); 272 mAttendeesList = new LinkedHashMap<String, Attendee>(); 273 mTimezone = TimeZone.getDefault().getID(); 274 } 275 276 public CalendarEventModel(Context context) { 277 this(); 278 279 mTimezone = Utils.getTimeZone(context, null); 280 SharedPreferences prefs = GeneralPreferences.getSharedPreferences(context); 281 282 String defaultReminder = prefs.getString( 283 GeneralPreferences.KEY_DEFAULT_REMINDER, GeneralPreferences.NO_REMINDER_STRING); 284 int defaultReminderMins = Integer.parseInt(defaultReminder); 285 if (defaultReminderMins != GeneralPreferences.NO_REMINDER) { 286 // Assume all calendars allow at least one reminder. 287 mHasAlarm = true; 288 mReminders.add(ReminderEntry.valueOf(defaultReminderMins)); 289 mDefaultReminders.add(ReminderEntry.valueOf(defaultReminderMins)); 290 } 291 } 292 293 public CalendarEventModel(Context context, Intent intent) { 294 this(context); 295 296 if (intent == null) { 297 return; 298 } 299 300 String title = intent.getStringExtra(Events.TITLE); 301 if (title != null) { 302 mTitle = title; 303 } 304 305 String location = intent.getStringExtra(Events.EVENT_LOCATION); 306 if (location != null) { 307 mLocation = location; 308 } 309 310 String description = intent.getStringExtra(Events.DESCRIPTION); 311 if (description != null) { 312 mDescription = description; 313 } 314 315 int availability = intent.getIntExtra(Events.AVAILABILITY, -1); 316 if (availability != -1) { 317 mAvailability = availability; 318 } 319 320 int accessLevel = intent.getIntExtra(Events.ACCESS_LEVEL, -1); 321 if (accessLevel != -1) { 322 if (accessLevel > 0) { 323 // TODO remove this if we add support for 324 // Events.ACCESS_CONFIDENTIAL 325 accessLevel--; 326 } 327 mAccessLevel = accessLevel; 328 } 329 330 String rrule = intent.getStringExtra(Events.RRULE); 331 if (!TextUtils.isEmpty(rrule)) { 332 mRrule = rrule; 333 } 334 335 String emails = intent.getStringExtra(Intent.EXTRA_EMAIL); 336 if (!TextUtils.isEmpty(emails)) { 337 String[] emailArray = emails.split("[ ,;]"); 338 for (String email : emailArray) { 339 if (!TextUtils.isEmpty(email) && email.contains("@")) { 340 email = email.trim(); 341 if (!mAttendeesList.containsKey(email)) { 342 mAttendeesList.put(email, new Attendee("", email)); 343 } 344 } 345 } 346 } 347 } 348 349 public boolean isValid() { 350 if (mCalendarId == -1) { 351 return false; 352 } 353 if (TextUtils.isEmpty(mOwnerAccount)) { 354 return false; 355 } 356 return true; 357 } 358 359 private boolean isEmpty() { 360 if (mTitle != null && mTitle.length() > 0) { 361 return false; 362 } 363 364 if (mLocation != null && mLocation.length() > 0) { 365 return false; 366 } 367 368 if (mDescription != null && mDescription.length() > 0) { 369 return false; 370 } 371 372 return true; 373 } 374 375 public void clear() { 376 mUri = null; 377 mId = -1; 378 mCalendarId = -1; 379 380 mSyncId = null; 381 mSyncAccount = null; 382 mSyncAccountType = null; 383 mOwnerAccount = null; 384 385 mTitle = null; 386 mLocation = null; 387 mDescription = null; 388 mRrule = null; 389 mOrganizer = null; 390 mOrganizerDisplayName = null; 391 mIsOrganizer = true; 392 mIsFirstEventInSeries = true; 393 394 mOriginalStart = -1; 395 mStart = -1; 396 mOriginalEnd = -1; 397 mEnd = -1; 398 mDuration = null; 399 mTimezone = null; 400 mTimezone2 = null; 401 mAllDay = false; 402 mHasAlarm = false; 403 404 mHasAttendeeData = true; 405 mSelfAttendeeStatus = -1; 406 mOwnerAttendeeId = -1; 407 mOriginalId = -1; 408 mOriginalSyncId = null; 409 mOriginalTime = null; 410 mOriginalAllDay = null; 411 412 mGuestsCanModify = false; 413 mGuestsCanInviteOthers = false; 414 mGuestsCanSeeGuests = false; 415 mAccessLevel = 0; 416 mEventStatus = Events.STATUS_CONFIRMED; 417 mOrganizerCanRespond = false; 418 mCalendarAccessLevel = Calendars.CAL_ACCESS_CONTRIBUTOR; 419 mModelUpdatedWithEventCursor = false; 420 mCalendarAllowedReminders = null; 421 mCalendarAllowedAttendeeTypes = null; 422 mCalendarAllowedAvailability = null; 423 424 mReminders = new ArrayList<ReminderEntry>(); 425 mAttendeesList.clear(); 426 } 427 428 public void addAttendee(Attendee attendee) { 429 mAttendeesList.put(attendee.mEmail, attendee); 430 } 431 432 public void addAttendees(String attendees, Rfc822Validator validator) { 433 final LinkedHashSet<Rfc822Token> addresses = EditEventHelper.getAddressesFromList( 434 attendees, validator); 435 synchronized (this) { 436 for (final Rfc822Token address : addresses) { 437 final Attendee attendee = new Attendee(address.getName(), address.getAddress()); 438 if (TextUtils.isEmpty(attendee.mName)) { 439 attendee.mName = attendee.mEmail; 440 } 441 addAttendee(attendee); 442 } 443 } 444 } 445 446 public void removeAttendee(Attendee attendee) { 447 mAttendeesList.remove(attendee.mEmail); 448 } 449 450 public String getAttendeesString() { 451 StringBuilder b = new StringBuilder(); 452 for (Attendee attendee : mAttendeesList.values()) { 453 String name = attendee.mName; 454 String email = attendee.mEmail; 455 String status = Integer.toString(attendee.mStatus); 456 b.append("name:").append(name); 457 b.append(" email:").append(email); 458 b.append(" status:").append(status); 459 } 460 return b.toString(); 461 } 462 463 @Override 464 public int hashCode() { 465 final int prime = 31; 466 int result = 1; 467 result = prime * result + (mAllDay ? 1231 : 1237); 468 result = prime * result + ((mAttendeesList == null) ? 0 : getAttendeesString().hashCode()); 469 result = prime * result + (int) (mCalendarId ^ (mCalendarId >>> 32)); 470 result = prime * result + ((mDescription == null) ? 0 : mDescription.hashCode()); 471 result = prime * result + ((mDuration == null) ? 0 : mDuration.hashCode()); 472 result = prime * result + (int) (mEnd ^ (mEnd >>> 32)); 473 result = prime * result + (mGuestsCanInviteOthers ? 1231 : 1237); 474 result = prime * result + (mGuestsCanModify ? 1231 : 1237); 475 result = prime * result + (mGuestsCanSeeGuests ? 1231 : 1237); 476 result = prime * result + (mOrganizerCanRespond ? 1231 : 1237); 477 result = prime * result + (mModelUpdatedWithEventCursor ? 1231 : 1237); 478 result = prime * result + mCalendarAccessLevel; 479 result = prime * result + (mHasAlarm ? 1231 : 1237); 480 result = prime * result + (mHasAttendeeData ? 1231 : 1237); 481 result = prime * result + (int) (mId ^ (mId >>> 32)); 482 result = prime * result + (mIsFirstEventInSeries ? 1231 : 1237); 483 result = prime * result + (mIsOrganizer ? 1231 : 1237); 484 result = prime * result + ((mLocation == null) ? 0 : mLocation.hashCode()); 485 result = prime * result + ((mOrganizer == null) ? 0 : mOrganizer.hashCode()); 486 result = prime * result + ((mOriginalAllDay == null) ? 0 : mOriginalAllDay.hashCode()); 487 result = prime * result + (int) (mOriginalEnd ^ (mOriginalEnd >>> 32)); 488 result = prime * result + ((mOriginalSyncId == null) ? 0 : mOriginalSyncId.hashCode()); 489 result = prime * result + (int) (mOriginalId ^ (mOriginalEnd >>> 32)); 490 result = prime * result + (int) (mOriginalStart ^ (mOriginalStart >>> 32)); 491 result = prime * result + ((mOriginalTime == null) ? 0 : mOriginalTime.hashCode()); 492 result = prime * result + ((mOwnerAccount == null) ? 0 : mOwnerAccount.hashCode()); 493 result = prime * result + ((mReminders == null) ? 0 : mReminders.hashCode()); 494 result = prime * result + ((mRrule == null) ? 0 : mRrule.hashCode()); 495 result = prime * result + mSelfAttendeeStatus; 496 result = prime * result + mOwnerAttendeeId; 497 result = prime * result + (int) (mStart ^ (mStart >>> 32)); 498 result = prime * result + ((mSyncAccount == null) ? 0 : mSyncAccount.hashCode()); 499 result = prime * result + ((mSyncAccountType == null) ? 0 : mSyncAccountType.hashCode()); 500 result = prime * result + ((mSyncId == null) ? 0 : mSyncId.hashCode()); 501 result = prime * result + ((mTimezone == null) ? 0 : mTimezone.hashCode()); 502 result = prime * result + ((mTimezone2 == null) ? 0 : mTimezone2.hashCode()); 503 result = prime * result + ((mTitle == null) ? 0 : mTitle.hashCode()); 504 result = prime * result + (mAvailability); 505 result = prime * result + ((mUri == null) ? 0 : mUri.hashCode()); 506 result = prime * result + mAccessLevel; 507 result = prime * result + mEventStatus; 508 return result; 509 } 510 511 // Autogenerated equals method 512 @Override 513 public boolean equals(Object obj) { 514 if (this == obj) { 515 return true; 516 } 517 if (obj == null) { 518 return false; 519 } 520 if (!(obj instanceof CalendarEventModel)) { 521 return false; 522 } 523 524 CalendarEventModel other = (CalendarEventModel) obj; 525 if (!checkOriginalModelFields(other)) { 526 return false; 527 } 528 529 if (mLocation == null) { 530 if (other.mLocation != null) { 531 return false; 532 } 533 } else if (!mLocation.equals(other.mLocation)) { 534 return false; 535 } 536 537 if (mTitle == null) { 538 if (other.mTitle != null) { 539 return false; 540 } 541 } else if (!mTitle.equals(other.mTitle)) { 542 return false; 543 } 544 545 if (mDescription == null) { 546 if (other.mDescription != null) { 547 return false; 548 } 549 } else if (!mDescription.equals(other.mDescription)) { 550 return false; 551 } 552 553 if (mDuration == null) { 554 if (other.mDuration != null) { 555 return false; 556 } 557 } else if (!mDuration.equals(other.mDuration)) { 558 return false; 559 } 560 561 if (mEnd != other.mEnd) { 562 return false; 563 } 564 if (mIsFirstEventInSeries != other.mIsFirstEventInSeries) { 565 return false; 566 } 567 if (mOriginalEnd != other.mOriginalEnd) { 568 return false; 569 } 570 571 if (mOriginalStart != other.mOriginalStart) { 572 return false; 573 } 574 if (mStart != other.mStart) { 575 return false; 576 } 577 578 if (mOriginalId != other.mOriginalId) { 579 return false; 580 } 581 582 if (mOriginalSyncId == null) { 583 if (other.mOriginalSyncId != null) { 584 return false; 585 } 586 } else if (!mOriginalSyncId.equals(other.mOriginalSyncId)) { 587 return false; 588 } 589 590 if (mRrule == null) { 591 if (other.mRrule != null) { 592 return false; 593 } 594 } else if (!mRrule.equals(other.mRrule)) { 595 return false; 596 } 597 return true; 598 } 599 600 /** 601 * Whether the event has been modified based on its original model. 602 * 603 * @param originalModel 604 * @return true if the model is unchanged, false otherwise 605 */ 606 public boolean isUnchanged(CalendarEventModel originalModel) { 607 if (this == originalModel) { 608 return true; 609 } 610 if (originalModel == null) { 611 return false; 612 } 613 614 if (!checkOriginalModelFields(originalModel)) { 615 return false; 616 } 617 618 if (TextUtils.isEmpty(mLocation)) { 619 if (!TextUtils.isEmpty(originalModel.mLocation)) { 620 return false; 621 } 622 } else if (!mLocation.equals(originalModel.mLocation)) { 623 return false; 624 } 625 626 if (TextUtils.isEmpty(mTitle)) { 627 if (!TextUtils.isEmpty(originalModel.mTitle)) { 628 return false; 629 } 630 } else if (!mTitle.equals(originalModel.mTitle)) { 631 return false; 632 } 633 634 if (TextUtils.isEmpty(mDescription)) { 635 if (!TextUtils.isEmpty(originalModel.mDescription)) { 636 return false; 637 } 638 } else if (!mDescription.equals(originalModel.mDescription)) { 639 return false; 640 } 641 642 if (TextUtils.isEmpty(mDuration)) { 643 if (!TextUtils.isEmpty(originalModel.mDuration)) { 644 return false; 645 } 646 } else if (!mDuration.equals(originalModel.mDuration)) { 647 return false; 648 } 649 650 if (mEnd != mOriginalEnd) { 651 return false; 652 } 653 if (mStart != mOriginalStart) { 654 return false; 655 } 656 657 // If this changed the original id and it's not just an exception to the 658 // original event 659 if (mOriginalId != originalModel.mOriginalId && mOriginalId != originalModel.mId) { 660 return false; 661 } 662 663 if (TextUtils.isEmpty(mRrule)) { 664 // if the rrule is no longer empty check if this is an exception 665 if (!TextUtils.isEmpty(originalModel.mRrule)) { 666 boolean syncIdNotReferenced = mOriginalSyncId == null 667 || !mOriginalSyncId.equals(originalModel.mSyncId); 668 boolean localIdNotReferenced = mOriginalId == -1 669 || !(mOriginalId == originalModel.mId); 670 if (syncIdNotReferenced && localIdNotReferenced) { 671 return false; 672 } 673 } 674 } else if (!mRrule.equals(originalModel.mRrule)) { 675 return false; 676 } 677 678 return true; 679 } 680 681 /** 682 * Checks against an original model for changes to an event. This covers all 683 * the fields that should remain consistent between an original event model 684 * and the new one if nothing in the event was modified. This is also the 685 * portion that overlaps with equality between two event models. 686 * 687 * @param originalModel 688 * @return true if these fields are unchanged, false otherwise 689 */ 690 protected boolean checkOriginalModelFields(CalendarEventModel originalModel) { 691 if (mAllDay != originalModel.mAllDay) { 692 return false; 693 } 694 if (mAttendeesList == null) { 695 if (originalModel.mAttendeesList != null) { 696 return false; 697 } 698 } else if (!mAttendeesList.equals(originalModel.mAttendeesList)) { 699 return false; 700 } 701 702 if (mCalendarId != originalModel.mCalendarId) { 703 return false; 704 } 705 706 if (mGuestsCanInviteOthers != originalModel.mGuestsCanInviteOthers) { 707 return false; 708 } 709 if (mGuestsCanModify != originalModel.mGuestsCanModify) { 710 return false; 711 } 712 if (mGuestsCanSeeGuests != originalModel.mGuestsCanSeeGuests) { 713 return false; 714 } 715 if (mOrganizerCanRespond != originalModel.mOrganizerCanRespond) { 716 return false; 717 } 718 if (mCalendarAccessLevel != originalModel.mCalendarAccessLevel) { 719 return false; 720 } 721 if (mModelUpdatedWithEventCursor != originalModel.mModelUpdatedWithEventCursor) { 722 return false; 723 } 724 if (mHasAlarm != originalModel.mHasAlarm) { 725 return false; 726 } 727 if (mHasAttendeeData != originalModel.mHasAttendeeData) { 728 return false; 729 } 730 if (mId != originalModel.mId) { 731 return false; 732 } 733 if (mIsOrganizer != originalModel.mIsOrganizer) { 734 return false; 735 } 736 737 if (mOrganizer == null) { 738 if (originalModel.mOrganizer != null) { 739 return false; 740 } 741 } else if (!mOrganizer.equals(originalModel.mOrganizer)) { 742 return false; 743 } 744 745 if (mOriginalAllDay == null) { 746 if (originalModel.mOriginalAllDay != null) { 747 return false; 748 } 749 } else if (!mOriginalAllDay.equals(originalModel.mOriginalAllDay)) { 750 return false; 751 } 752 753 if (mOriginalTime == null) { 754 if (originalModel.mOriginalTime != null) { 755 return false; 756 } 757 } else if (!mOriginalTime.equals(originalModel.mOriginalTime)) { 758 return false; 759 } 760 761 if (mOwnerAccount == null) { 762 if (originalModel.mOwnerAccount != null) { 763 return false; 764 } 765 } else if (!mOwnerAccount.equals(originalModel.mOwnerAccount)) { 766 return false; 767 } 768 769 if (mReminders == null) { 770 if (originalModel.mReminders != null) { 771 return false; 772 } 773 } else if (!mReminders.equals(originalModel.mReminders)) { 774 return false; 775 } 776 777 if (mSelfAttendeeStatus != originalModel.mSelfAttendeeStatus) { 778 return false; 779 } 780 if (mOwnerAttendeeId != originalModel.mOwnerAttendeeId) { 781 return false; 782 } 783 if (mSyncAccount == null) { 784 if (originalModel.mSyncAccount != null) { 785 return false; 786 } 787 } else if (!mSyncAccount.equals(originalModel.mSyncAccount)) { 788 return false; 789 } 790 791 if (mSyncAccountType == null) { 792 if (originalModel.mSyncAccountType != null) { 793 return false; 794 } 795 } else if (!mSyncAccountType.equals(originalModel.mSyncAccountType)) { 796 return false; 797 } 798 799 if (mSyncId == null) { 800 if (originalModel.mSyncId != null) { 801 return false; 802 } 803 } else if (!mSyncId.equals(originalModel.mSyncId)) { 804 return false; 805 } 806 807 if (mTimezone == null) { 808 if (originalModel.mTimezone != null) { 809 return false; 810 } 811 } else if (!mTimezone.equals(originalModel.mTimezone)) { 812 return false; 813 } 814 815 if (mTimezone2 == null) { 816 if (originalModel.mTimezone2 != null) { 817 return false; 818 } 819 } else if (!mTimezone2.equals(originalModel.mTimezone2)) { 820 return false; 821 } 822 823 if (mAvailability != originalModel.mAvailability) { 824 return false; 825 } 826 827 if (mUri == null) { 828 if (originalModel.mUri != null) { 829 return false; 830 } 831 } else if (!mUri.equals(originalModel.mUri)) { 832 return false; 833 } 834 835 if (mAccessLevel != originalModel.mAccessLevel) { 836 return false; 837 } 838 839 if (mEventStatus != originalModel.mEventStatus) { 840 return false; 841 } 842 return true; 843 } 844 845 /** 846 * Sort and uniquify mReminderMinutes. 847 * 848 * @return true (for convenience of caller) 849 */ 850 public boolean normalizeReminders() { 851 if (mReminders.size() <= 1) { 852 return true; 853 } 854 855 // sort 856 Collections.sort(mReminders); 857 858 // remove duplicates 859 ReminderEntry prev = mReminders.get(mReminders.size()-1); 860 for (int i = mReminders.size()-2; i >= 0; --i) { 861 ReminderEntry cur = mReminders.get(i); 862 if (prev.equals(cur)) { 863 // match, remove later entry 864 mReminders.remove(i+1); 865 } 866 prev = cur; 867 } 868 869 return true; 870 } 871} 872