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