Home | History | Annotate | Download | only in dataitem
      1 /*
      2  * Copyright (C) 2012 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.contacts.common.model.dataitem;
     18 
     19 import android.content.ContentValues;
     20 import android.content.Context;
     21 import android.provider.ContactsContract.CommonDataKinds.Email;
     22 import android.provider.ContactsContract.CommonDataKinds.Event;
     23 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
     24 import android.provider.ContactsContract.CommonDataKinds.Identity;
     25 import android.provider.ContactsContract.CommonDataKinds.Im;
     26 import android.provider.ContactsContract.CommonDataKinds.Nickname;
     27 import android.provider.ContactsContract.CommonDataKinds.Note;
     28 import android.provider.ContactsContract.CommonDataKinds.Organization;
     29 import android.provider.ContactsContract.CommonDataKinds.Phone;
     30 import android.provider.ContactsContract.CommonDataKinds.Photo;
     31 import android.provider.ContactsContract.CommonDataKinds.Relation;
     32 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
     33 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
     34 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
     35 import android.provider.ContactsContract.CommonDataKinds.Website;
     36 import android.provider.ContactsContract.Contacts.Data;
     37 import android.provider.ContactsContract.Contacts.Entity;
     38 
     39 import com.android.contacts.common.Collapser;
     40 import com.android.contacts.common.MoreContactUtils;
     41 import com.android.contacts.common.model.RawContactModifier;
     42 
     43 /**
     44  * This is the base class for data items, which represents a row from the Data table.
     45  */
     46 public class DataItem implements Collapser.Collapsible<DataItem> {
     47 
     48     private final ContentValues mContentValues;
     49     protected DataKind mKind;
     50 
     51     protected DataItem(ContentValues values) {
     52         mContentValues = values;
     53     }
     54 
     55     /**
     56      * Factory for creating subclasses of DataItem objects based on the mimetype in the
     57      * content values.  Raw contact is the raw contact that this data item is associated with.
     58      */
     59     public static DataItem createFrom(ContentValues values) {
     60         final String mimeType = values.getAsString(Data.MIMETYPE);
     61         if (GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {
     62             return new GroupMembershipDataItem(values);
     63         } else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
     64             return new StructuredNameDataItem(values);
     65         } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
     66             return new PhoneDataItem(values);
     67         } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
     68             return new EmailDataItem(values);
     69         } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
     70             return new StructuredPostalDataItem(values);
     71         } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
     72             return new ImDataItem(values);
     73         } else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
     74             return new OrganizationDataItem(values);
     75         } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
     76             return new NicknameDataItem(values);
     77         } else if (Note.CONTENT_ITEM_TYPE.equals(mimeType)) {
     78             return new NoteDataItem(values);
     79         } else if (Website.CONTENT_ITEM_TYPE.equals(mimeType)) {
     80             return new WebsiteDataItem(values);
     81         } else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType)) {
     82             return new SipAddressDataItem(values);
     83         } else if (Event.CONTENT_ITEM_TYPE.equals(mimeType)) {
     84             return new EventDataItem(values);
     85         } else if (Relation.CONTENT_ITEM_TYPE.equals(mimeType)) {
     86             return new RelationDataItem(values);
     87         } else if (Identity.CONTENT_ITEM_TYPE.equals(mimeType)) {
     88             return new IdentityDataItem(values);
     89         } else if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
     90             return new PhotoDataItem(values);
     91         }
     92 
     93         // generic
     94         return new DataItem(values);
     95     }
     96 
     97     public ContentValues getContentValues() {
     98         return mContentValues;
     99     }
    100 
    101     public void setRawContactId(long rawContactId) {
    102         mContentValues.put(Data.RAW_CONTACT_ID, rawContactId);
    103     }
    104 
    105     public Long getRawContactId() {
    106         return mContentValues.getAsLong(Data.RAW_CONTACT_ID);
    107     }
    108 
    109     /**
    110      * Returns the data id.
    111      */
    112     public long getId() {
    113         return mContentValues.getAsLong(Data._ID);
    114     }
    115 
    116     /**
    117      * Returns the mimetype of the data.
    118      */
    119     public String getMimeType() {
    120         return mContentValues.getAsString(Data.MIMETYPE);
    121     }
    122 
    123     public void setMimeType(String mimeType) {
    124         mContentValues.put(Data.MIMETYPE, mimeType);
    125     }
    126 
    127     public boolean isPrimary() {
    128         Integer primary = mContentValues.getAsInteger(Data.IS_PRIMARY);
    129         return primary != null && primary != 0;
    130     }
    131 
    132     public boolean isSuperPrimary() {
    133         Integer superPrimary = mContentValues.getAsInteger(Data.IS_SUPER_PRIMARY);
    134         return superPrimary != null && superPrimary != 0;
    135     }
    136 
    137     public boolean hasKindTypeColumn(DataKind kind) {
    138         final String key = kind.typeColumn;
    139         return key != null && mContentValues.containsKey(key) &&
    140             mContentValues.getAsInteger(key) != null;
    141     }
    142 
    143     public int getKindTypeColumn(DataKind kind) {
    144         final String key = kind.typeColumn;
    145         return mContentValues.getAsInteger(key);
    146     }
    147 
    148     /**
    149      * Indicates the carrier presence value for the current {@link DataItem}.
    150      *
    151      * @return {@link Data#CARRIER_PRESENCE_VT_CAPABLE} if the {@link DataItem} supports carrier
    152      *      video calling, {@code 0} otherwise.
    153      */
    154     public int getCarrierPresence() {
    155         return mContentValues.getAsInteger(Data.CARRIER_PRESENCE);
    156     }
    157 
    158     /**
    159      * This builds the data string depending on the type of data item by using the generic
    160      * DataKind object underneath.
    161      */
    162     public String buildDataString(Context context, DataKind kind) {
    163         if (kind.actionBody == null) {
    164             return null;
    165         }
    166         CharSequence actionBody = kind.actionBody.inflateUsing(context, mContentValues);
    167         return actionBody == null ? null : actionBody.toString();
    168     }
    169 
    170     /**
    171      * This builds the data string(intended for display) depending on the type of data item. It
    172      * returns the same value as {@link #buildDataString} by default, but certain data items can
    173      * override it to provide their version of formatted data strings.
    174      *
    175      * @return Data string representing the data item, possibly formatted for display
    176      */
    177     public String buildDataStringForDisplay(Context context, DataKind kind) {
    178         return buildDataString(context, kind);
    179     }
    180 
    181     public void setDataKind(DataKind kind) {
    182         mKind = kind;
    183     }
    184 
    185     public DataKind getDataKind() {
    186         return mKind;
    187     }
    188 
    189     public Integer getTimesUsed() {
    190         return mContentValues.getAsInteger(Entity.TIMES_USED);
    191     }
    192 
    193     public Long getLastTimeUsed() {
    194         return mContentValues.getAsLong(Entity.LAST_TIME_USED);
    195     }
    196 
    197     @Override
    198     public void collapseWith(DataItem that) {
    199         DataKind thisKind = getDataKind();
    200         DataKind thatKind = that.getDataKind();
    201         // If this does not have a type and that does, or if that's type is higher precedence,
    202         // use that's type
    203         if ((!hasKindTypeColumn(thisKind) && that.hasKindTypeColumn(thatKind)) ||
    204                 that.hasKindTypeColumn(thatKind) &&
    205                 RawContactModifier.getTypePrecedence(thisKind, getKindTypeColumn(thisKind))
    206                 >
    207                 RawContactModifier.getTypePrecedence(thatKind, that.getKindTypeColumn(thatKind))) {
    208             mContentValues.put(thatKind.typeColumn, that.getKindTypeColumn(thatKind));
    209             mKind = thatKind;
    210         }
    211 
    212         // Choose the max of the maxLines and maxLabelLines values.
    213         mKind.maxLinesForDisplay = Math.max(thisKind.maxLinesForDisplay,
    214                 thatKind.maxLinesForDisplay);
    215 
    216         // If any of the collapsed entries are super primary make the whole thing super primary.
    217         if (isSuperPrimary() || that.isSuperPrimary()) {
    218             mContentValues.put(Data.IS_SUPER_PRIMARY, 1);
    219             mContentValues.put(Data.IS_PRIMARY, 1);
    220         }
    221 
    222         // If any of the collapsed entries are primary make the whole thing primary.
    223         if (isPrimary() || that.isPrimary()) {
    224             mContentValues.put(Data.IS_PRIMARY, 1);
    225         }
    226 
    227         // Add up the times used
    228         mContentValues.put(Entity.TIMES_USED, (getTimesUsed() == null ? 0 : getTimesUsed()) +
    229                 (that.getTimesUsed() == null ? 0 : that.getTimesUsed()));
    230 
    231         // Use the most recent time
    232         mContentValues.put(Entity.LAST_TIME_USED,
    233                 Math.max(getLastTimeUsed() == null ? 0 : getLastTimeUsed(),
    234                         that.getLastTimeUsed() == null ? 0 : that.getLastTimeUsed()));
    235     }
    236 
    237     @Override
    238     public boolean shouldCollapseWith(DataItem t, Context context) {
    239         if (mKind == null || t.getDataKind() == null) {
    240             return false;
    241         }
    242         return MoreContactUtils.shouldCollapse(getMimeType(), buildDataString(context, mKind),
    243                 t.getMimeType(), t.buildDataString(context, t.getDataKind()));
    244     }
    245 }
    246