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      * This builds the data string depending on the type of data item by using the generic
    150      * DataKind object underneath.
    151      */
    152     public String buildDataString(Context context, DataKind kind) {
    153         if (kind.actionBody == null) {
    154             return null;
    155         }
    156         CharSequence actionBody = kind.actionBody.inflateUsing(context, mContentValues);
    157         return actionBody == null ? null : actionBody.toString();
    158     }
    159 
    160     /**
    161      * This builds the data string(intended for display) depending on the type of data item. It
    162      * returns the same value as {@link #buildDataString} by default, but certain data items can
    163      * override it to provide their version of formatted data strings.
    164      *
    165      * @return Data string representing the data item, possibly formatted for display
    166      */
    167     public String buildDataStringForDisplay(Context context, DataKind kind) {
    168         return buildDataString(context, kind);
    169     }
    170 
    171     public void setDataKind(DataKind kind) {
    172         mKind = kind;
    173     }
    174 
    175     public DataKind getDataKind() {
    176         return mKind;
    177     }
    178 
    179     public Integer getTimesUsed() {
    180         return mContentValues.getAsInteger(Entity.TIMES_USED);
    181     }
    182 
    183     public Long getLastTimeUsed() {
    184         return mContentValues.getAsLong(Entity.LAST_TIME_USED);
    185     }
    186 
    187     @Override
    188     public void collapseWith(DataItem that) {
    189         DataKind thisKind = getDataKind();
    190         DataKind thatKind = that.getDataKind();
    191         // If this does not have a type and that does, or if that's type is higher precedence,
    192         // use that's type
    193         if ((!hasKindTypeColumn(thisKind) && that.hasKindTypeColumn(thatKind)) ||
    194                 that.hasKindTypeColumn(thatKind) &&
    195                 RawContactModifier.getTypePrecedence(thisKind, getKindTypeColumn(thisKind))
    196                 >
    197                 RawContactModifier.getTypePrecedence(thatKind, that.getKindTypeColumn(thatKind))) {
    198             mContentValues.put(thatKind.typeColumn, that.getKindTypeColumn(thatKind));
    199             mKind = thatKind;
    200         }
    201 
    202         // Choose the max of the maxLines and maxLabelLines values.
    203         mKind.maxLinesForDisplay = Math.max(thisKind.maxLinesForDisplay,
    204                 thatKind.maxLinesForDisplay);
    205 
    206         // If any of the collapsed entries are super primary make the whole thing super primary.
    207         if (isSuperPrimary() || that.isSuperPrimary()) {
    208             mContentValues.put(Data.IS_SUPER_PRIMARY, 1);
    209             mContentValues.put(Data.IS_PRIMARY, 1);
    210         }
    211 
    212         // If any of the collapsed entries are primary make the whole thing primary.
    213         if (isPrimary() || that.isPrimary()) {
    214             mContentValues.put(Data.IS_PRIMARY, 1);
    215         }
    216 
    217         // Add up the times used
    218         mContentValues.put(Entity.TIMES_USED, (getTimesUsed() == null ? 0 : getTimesUsed()) +
    219                 (that.getTimesUsed() == null ? 0 : that.getTimesUsed()));
    220 
    221         // Use the most recent time
    222         mContentValues.put(Entity.LAST_TIME_USED,
    223                 Math.max(getLastTimeUsed() == null ? 0 : getLastTimeUsed(),
    224                         that.getLastTimeUsed() == null ? 0 : that.getLastTimeUsed()));
    225     }
    226 
    227     @Override
    228     public boolean shouldCollapseWith(DataItem t, Context context) {
    229         if (mKind == null || t.getDataKind() == null) {
    230             return false;
    231         }
    232         return MoreContactUtils.shouldCollapse(getMimeType(), buildDataString(context, mKind),
    233                 t.getMimeType(), t.buildDataString(context, t.getDataKind()));
    234     }
    235 }
    236