RecipientEntry.java revision d2240c52c38d67ee6c340d625a240ded51e2ddae
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 17package com.android.ex.chips; 18 19import android.net.Uri; 20import android.provider.ContactsContract.CommonDataKinds.Email; 21import android.provider.ContactsContract.DisplayNameSources; 22import android.text.util.Rfc822Token; 23import android.text.util.Rfc822Tokenizer; 24 25/** 26 * Represents one entry inside recipient auto-complete list. 27 */ 28public 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 RecipientEntry(int entryType, String displayName, String destination, 78 int destinationType, String destinationLabel, long contactId, long dataId, 79 Uri photoThumbnailUri, boolean isFirstLevel, boolean isValid) { 80 mEntryType = entryType; 81 mIsFirstLevel = isFirstLevel; 82 mDisplayName = displayName; 83 mDestination = destination; 84 mDestinationType = destinationType; 85 mDestinationLabel = destinationLabel; 86 mContactId = contactId; 87 mDataId = dataId; 88 mPhotoThumbnailUri = photoThumbnailUri; 89 mPhotoBytes = null; 90 mIsDivider = false; 91 mIsValid = isValid; 92 } 93 94 public boolean isValid() { 95 return mIsValid; 96 } 97 98 /** 99 * Determine if this was a RecipientEntry created from recipient info or 100 * an entry from contacts. 101 */ 102 public static boolean isCreatedRecipient(long id) { 103 return id == RecipientEntry.INVALID_CONTACT || id == RecipientEntry.GENERATED_CONTACT; 104 } 105 106 /** 107 * Construct a RecipientEntry from just an address that has been entered. 108 * This address has not been resolved to a contact and therefore does not 109 * have a contact id or photo. 110 */ 111 public static RecipientEntry constructFakeEntry(final String address, final boolean isValid) { 112 final Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(address); 113 final String tokenizedAddress = tokens[0].getAddress(); 114 115 return new RecipientEntry(ENTRY_TYPE_PERSON, tokenizedAddress, tokenizedAddress, 116 INVALID_DESTINATION_TYPE, null, 117 INVALID_CONTACT, INVALID_CONTACT, null, true, isValid); 118 } 119 120 /** 121 * @return the display name for the entry. If the display name source is larger than 122 * {@link DisplayNameSources#PHONE} we use the contact's display name, but if not, 123 * i.e. the display name came from an email address or a phone number, we don't use it 124 * to avoid confusion and just use the destination instead. 125 */ 126 private static String pickDisplayName(int displayNameSource, String displayName, 127 String destination) { 128 return (displayNameSource > DisplayNameSources.PHONE) ? displayName : destination; 129 } 130 131 /** 132 * Construct a RecipientEntry from just an address that has been entered 133 * with both an associated display name. This address has not been resolved 134 * to a contact and therefore does not have a contact id or photo. 135 */ 136 public static RecipientEntry constructGeneratedEntry(String display, String address, 137 boolean isValid) { 138 return new RecipientEntry(ENTRY_TYPE_PERSON, display, address, INVALID_DESTINATION_TYPE, 139 null, GENERATED_CONTACT, GENERATED_CONTACT, null, true, isValid); 140 } 141 142 public static RecipientEntry constructTopLevelEntry(String displayName, int displayNameSource, 143 String destination, int destinationType, String destinationLabel, long contactId, 144 long dataId, Uri photoThumbnailUri, boolean isValid) { 145 return new RecipientEntry(ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, 146 displayName, destination), destination, destinationType, destinationLabel, 147 contactId, dataId, photoThumbnailUri, true, isValid); 148 } 149 150 public static RecipientEntry constructTopLevelEntry(String displayName, int displayNameSource, 151 String destination, int destinationType, String destinationLabel, long contactId, 152 long dataId, String thumbnailUriAsString, boolean isValid) { 153 return new RecipientEntry(ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, 154 displayName, destination), destination, destinationType, destinationLabel, 155 contactId, dataId, (thumbnailUriAsString != null ? Uri.parse(thumbnailUriAsString) 156 : null), true, isValid); 157 } 158 159 public static RecipientEntry constructSecondLevelEntry(String displayName, 160 int displayNameSource, String destination, int destinationType, 161 String destinationLabel, long contactId, long dataId, String thumbnailUriAsString, 162 boolean isValid) { 163 return new RecipientEntry(ENTRY_TYPE_PERSON, pickDisplayName(displayNameSource, 164 displayName, destination), destination, destinationType, destinationLabel, 165 contactId, dataId, (thumbnailUriAsString != null ? Uri.parse(thumbnailUriAsString) 166 : null), false, isValid); 167 } 168 169 public int getEntryType() { 170 return mEntryType; 171 } 172 173 public String getDisplayName() { 174 return mDisplayName; 175 } 176 177 public String getDestination() { 178 return mDestination; 179 } 180 181 public int getDestinationType() { 182 return mDestinationType; 183 } 184 185 public String getDestinationLabel() { 186 return mDestinationLabel; 187 } 188 189 public long getContactId() { 190 return mContactId; 191 } 192 193 public long getDataId() { 194 return mDataId; 195 } 196 197 public boolean isFirstLevel() { 198 return mIsFirstLevel; 199 } 200 201 public Uri getPhotoThumbnailUri() { 202 return mPhotoThumbnailUri; 203 } 204 205 /** This can be called outside main Looper thread. */ 206 public synchronized void setPhotoBytes(byte[] photoBytes) { 207 mPhotoBytes = photoBytes; 208 } 209 210 /** This can be called outside main Looper thread. */ 211 public synchronized byte[] getPhotoBytes() { 212 return mPhotoBytes; 213 } 214 215 public boolean isSeparator() { 216 return mIsDivider; 217 } 218 219 public boolean isSelectable() { 220 return mEntryType == ENTRY_TYPE_PERSON; 221 } 222 223 @Override 224 public String toString() { 225 return mDisplayName + " <" + mDestination + ">, isValid=" + mIsValid; 226 } 227}