Home | History | Annotate | Download | only in chips
      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 }