1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ex.chips; 18 19 import android.net.Uri; 20 import android.provider.ContactsContract.CommonDataKinds.Email; 21 import android.provider.ContactsContract.DisplayNameSources; 22 23 /** 24 * Represents one entry inside recipient auto-complete list. 25 */ 26 public class RecipientEntry { 27 /* package */ static final int INVALID_CONTACT = -1; 28 /** 29 * A GENERATED_CONTACT is one that was created based entirely on 30 * information passed in to the RecipientEntry from an external source 31 * that is not a real contact. 32 */ 33 /* package */ static final int GENERATED_CONTACT = -2; 34 35 /** Used when {@link #mDestinationType} is invalid and thus shouldn't be used for display. */ 36 /* package */ static final int INVALID_DESTINATION_TYPE = -1; 37 38 public static final int ENTRY_TYPE_PERSON = 0; 39 40 public static final int ENTRY_TYPE_SIZE = 1; 41 42 private final int mEntryType; 43 44 /** 45 * True when this entry is the first entry in a group, which should have a photo and display 46 * name, while the second or later entries won't. 47 */ 48 private boolean mIsFirstLevel; 49 private final String mDisplayName; 50 51 /** Destination for this contact entry. Would be an email address or a phone number. */ 52 private final String mDestination; 53 /** Type of the destination like {@link Email#TYPE_HOME} */ 54 private final int mDestinationType; 55 /** 56 * Label of the destination which will be used when type was {@link Email#TYPE_CUSTOM}. 57 * Can be null when {@link #mDestinationType} is {@link #INVALID_DESTINATION_TYPE}. 58 */ 59 private final String mDestinationLabel; 60 /** ID for the person */ 61 private final long mContactId; 62 /** ID for the destination */ 63 private final long mDataId; 64 private final boolean mIsDivider; 65 66 private final Uri mPhotoThumbnailUri; 67 68 /** 69 * This can be updated after this object being constructed, when the photo is fetched 70 * from remote directories. 71 */ 72 private byte[] mPhotoBytes; 73 74 private RecipientEntry(int entryType) { 75 mEntryType = entryType; 76 mDisplayName = null; 77 mDestination = null; 78 mDestinationType = INVALID_DESTINATION_TYPE; 79 mDestinationLabel = null; 80 mContactId = -1; 81 mDataId = -1; 82 mPhotoThumbnailUri = null; 83 mPhotoBytes = null; 84 mIsDivider = true; 85 } 86 87 private RecipientEntry( 88 int entryType, String displayName, 89 String destination, int destinationType, String destinationLabel, 90 long contactId, long dataId, Uri photoThumbnailUri, boolean isFirstLevel) { 91 mEntryType = entryType; 92 mIsFirstLevel = isFirstLevel; 93 mDisplayName = displayName; 94 mDestination = destination; 95 mDestinationType = destinationType; 96 mDestinationLabel = destinationLabel; 97 mContactId = contactId; 98 mDataId = dataId; 99 mPhotoThumbnailUri = photoThumbnailUri; 100 mPhotoBytes = null; 101 mIsDivider = false; 102 } 103 104 /** 105 * Determine if this was a RecipientEntry created from recipient info or 106 * an entry from contacts. 107 */ 108 public static boolean isCreatedRecipient(long id) { 109 return id == RecipientEntry.INVALID_CONTACT || id == RecipientEntry.GENERATED_CONTACT; 110 } 111 112 /** 113 * Construct a RecipientEntry from just an address that has been entered. 114 * This address has not been resolved to a contact and therefore does not 115 * have a contact id or photo. 116 */ 117 public static RecipientEntry constructFakeEntry(String address) { 118 return new RecipientEntry(ENTRY_TYPE_PERSON, address, address, 119 INVALID_DESTINATION_TYPE, null, 120 INVALID_CONTACT, INVALID_CONTACT, null, true); 121 } 122 123 /** 124 * @return the display name for the entry. If the display name source is larger than 125 * {@link DisplayNameSources#PHONE} we use the contact's display name, but if not, 126 * i.e. the display name came from an email address or a phone number, we don't use it 127 * to avoid confusion and just use the destination instead. 128 */ 129 private static String pickDisplayName(int displayNameSource, String displayName, 130 String destination) { 131 return (displayNameSource > DisplayNameSources.PHONE) ? displayName : destination; 132 } 133 134 /** 135 * Construct a RecipientEntry from just an address that has been entered 136 * with both an associated display name. This address has not been resolved 137 * to a contact and therefore does not have a contact id or photo. 138 */ 139 public static RecipientEntry constructGeneratedEntry(String display, String address) { 140 return new RecipientEntry(ENTRY_TYPE_PERSON, display, 141 address, INVALID_DESTINATION_TYPE, null, 142 GENERATED_CONTACT, GENERATED_CONTACT, null, true); 143 } 144 145 public static RecipientEntry constructTopLevelEntry( 146 String displayName, int displayNameSource, String destination, int destinationType, 147 String destinationLabel, long contactId, long dataId, Uri photoThumbnailUri) { 148 return new RecipientEntry(ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, displayName, 149 destination), 150 destination, destinationType, destinationLabel, 151 contactId, dataId, 152 photoThumbnailUri, true); 153 } 154 155 public static RecipientEntry constructTopLevelEntry( 156 String displayName, int displayNameSource, String destination, int destinationType, 157 String destinationLabel, long contactId, long dataId, 158 String thumbnailUriAsString) { 159 return new RecipientEntry( 160 ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, displayName, destination), 161 destination, destinationType, destinationLabel, 162 contactId, dataId, 163 (thumbnailUriAsString != null ? Uri.parse(thumbnailUriAsString) : null), true); 164 } 165 166 public static RecipientEntry constructSecondLevelEntry( 167 String displayName, int displayNameSource, String destination, int destinationType, 168 String destinationLabel, long contactId, long dataId, String thumbnailUriAsString) { 169 return new RecipientEntry( 170 ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, displayName, destination), 171 destination, destinationType, destinationLabel, 172 contactId, dataId, 173 (thumbnailUriAsString != null ? Uri.parse(thumbnailUriAsString) : null), false); 174 } 175 176 public int getEntryType() { 177 return mEntryType; 178 } 179 180 public String getDisplayName() { 181 return mDisplayName; 182 } 183 184 public String getDestination() { 185 return mDestination; 186 } 187 188 public int getDestinationType() { 189 return mDestinationType; 190 } 191 192 public String getDestinationLabel() { 193 return mDestinationLabel; 194 } 195 196 public long getContactId() { 197 return mContactId; 198 } 199 200 public long getDataId() { 201 return mDataId; 202 } 203 204 public boolean isFirstLevel() { 205 return mIsFirstLevel; 206 } 207 208 public Uri getPhotoThumbnailUri() { 209 return mPhotoThumbnailUri; 210 } 211 212 /** This can be called outside main Looper thread. */ 213 public synchronized void setPhotoBytes(byte[] photoBytes) { 214 mPhotoBytes = photoBytes; 215 } 216 217 /** This can be called outside main Looper thread. */ 218 public synchronized byte[] getPhotoBytes() { 219 return mPhotoBytes; 220 } 221 222 public boolean isSeparator() { 223 return mIsDivider; 224 } 225 226 public boolean isSelectable() { 227 return mEntryType == ENTRY_TYPE_PERSON; 228 } 229 }