diff options
Diffstat (limited to 'src/com/android/contacts/model/account')
8 files changed, 0 insertions, 3376 deletions
diff --git a/src/com/android/contacts/model/account/AccountType.java b/src/com/android/contacts/model/account/AccountType.java deleted file mode 100644 index ca3dc6872..000000000 --- a/src/com/android/contacts/model/account/AccountType.java +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.contacts.model.account; - -import android.content.ContentValues; -import android.content.Context; -import android.content.pm.PackageManager; -import android.graphics.drawable.Drawable; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.RawContacts; -import android.view.inputmethod.EditorInfo; -import android.widget.EditText; - -import com.android.contacts.R; -import com.android.contacts.model.dataitem.DataKind; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -import java.text.Collator; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; - -/** - * Internal structure that represents constraints and styles for a specific data - * source, such as the various data types they support, including details on how - * those types should be rendered and edited. - * <p> - * In the future this may be inflated from XML defined by a data source. - */ -public abstract class AccountType { - private static final String TAG = "AccountType"; - - /** - * The {@link RawContacts#ACCOUNT_TYPE} these constraints apply to. - */ - public String accountType = null; - - /** - * The {@link RawContacts#DATA_SET} these constraints apply to. - */ - public String dataSet = null; - - /** - * Package that resources should be loaded from. Will be null for embedded types, in which - * case resources are stored in this package itself. - * - * TODO Clean up {@link #resourcePackageName}, {@link #syncAdapterPackageName} and - * {@link #getViewContactNotifyServicePackageName()}. - * - * There's the following invariants: - * - {@link #syncAdapterPackageName} is always set to the actual sync adapter package name. - * - {@link #resourcePackageName} too is set to the same value, unless {@link #isEmbedded()}, - * in which case it'll be null. - * There's an unfortunate exception of {@link FallbackAccountType}. Even though it - * {@link #isEmbedded()}, but we set non-null to {@link #resourcePackageName} for unit tests. - */ - public String resourcePackageName; - /** - * The package name for the authenticator (for the embedded types, i.e. Google and Exchange) - * or the sync adapter (for external type, including extensions). - */ - public String syncAdapterPackageName; - - public int titleRes; - public int iconRes; - - /** - * Set of {@link DataKind} supported by this source. - */ - private ArrayList<DataKind> mKinds = Lists.newArrayList(); - - /** - * Lookup map of {@link #mKinds} on {@link DataKind#mimeType}. - */ - private HashMap<String, DataKind> mMimeKinds = Maps.newHashMap(); - - protected boolean mIsInitialized; - - protected static class DefinitionException extends Exception { - public DefinitionException(String message) { - super(message); - } - - public DefinitionException(String message, Exception inner) { - super(message, inner); - } - } - - /** - * Whether this account type was able to be fully initialized. This may be false if - * (for example) the package name associated with the account type could not be found. - */ - public final boolean isInitialized() { - return mIsInitialized; - } - - /** - * @return Whether this type is an "embedded" type. i.e. any of {@link FallbackAccountType}, - * {@link GoogleAccountType} or {@link ExternalAccountType}. - * - * If an embedded type cannot be initialized (i.e. if {@link #isInitialized()} returns - * {@code false}) it's considered critical, and the application will crash. On the other - * hand if it's not an embedded type, we just skip loading the type. - */ - public boolean isEmbedded() { - return true; - } - - public boolean isExtension() { - return false; - } - - /** - * @return True if contacts can be created and edited using this app. If false, - * there could still be an external editor as provided by - * {@link #getEditContactActivityClassName()} or {@link #getCreateContactActivityClassName()} - */ - public abstract boolean areContactsWritable(); - - /** - * Returns an optional custom edit activity. - * - * Only makes sense for non-embedded account types. - * The activity class should reside in the sync adapter package as determined by - * {@link #syncAdapterPackageName}. - */ - public String getEditContactActivityClassName() { - return null; - } - - /** - * Returns an optional custom new contact activity. - * - * Only makes sense for non-embedded account types. - * The activity class should reside in the sync adapter package as determined by - * {@link #syncAdapterPackageName}. - */ - public String getCreateContactActivityClassName() { - return null; - } - - /** - * Returns an optional custom invite contact activity. - * - * Only makes sense for non-embedded account types. - * The activity class should reside in the sync adapter package as determined by - * {@link #syncAdapterPackageName}. - */ - public String getInviteContactActivityClassName() { - return null; - } - - /** - * Returns an optional service that can be launched whenever a contact is being looked at. - * This allows the sync adapter to provide more up-to-date information. - * - * The service class should reside in the sync adapter package as determined by - * {@link #getViewContactNotifyServicePackageName()}. - */ - public String getViewContactNotifyServiceClassName() { - return null; - } - - /** - * TODO This is way too hacky should be removed. - * - * This is introduced for {@link GoogleAccountType} where {@link #syncAdapterPackageName} - * is the authenticator package name but the notification service is in the sync adapter - * package. See {@link #resourcePackageName} -- we should clean up those. - */ - public String getViewContactNotifyServicePackageName() { - return syncAdapterPackageName; - } - - /** Returns an optional Activity string that can be used to view the group. */ - public String getViewGroupActivity() { - return null; - } - - /** Returns an optional Activity string that can be used to view the stream item. */ - public String getViewStreamItemActivity() { - return null; - } - - /** Returns an optional Activity string that can be used to view the stream item photo. */ - public String getViewStreamItemPhotoActivity() { - return null; - } - - public CharSequence getDisplayLabel(Context context) { - // Note this resource is defined in the sync adapter package, not resourcePackageName. - return getResourceText(context, syncAdapterPackageName, titleRes, accountType); - } - - /** - * @return resource ID for the "invite contact" action label, or -1 if not defined. - */ - protected int getInviteContactActionResId() { - return -1; - } - - /** - * @return resource ID for the "view group" label, or -1 if not defined. - */ - protected int getViewGroupLabelResId() { - return -1; - } - - /** - * Returns {@link AccountTypeWithDataSet} for this type. - */ - public AccountTypeWithDataSet getAccountTypeAndDataSet() { - return AccountTypeWithDataSet.get(accountType, dataSet); - } - - /** - * Returns a list of additional package names that should be inspected as additional - * external account types. This allows for a primary account type to indicate other packages - * that may not be sync adapters but which still provide contact data, perhaps under a - * separate data set within the account. - */ - public List<String> getExtensionPackageNames() { - return new ArrayList<String>(); - } - - /** - * Returns an optional custom label for the "invite contact" action, which will be shown on - * the contact card. (If not defined, returns null.) - */ - public CharSequence getInviteContactActionLabel(Context context) { - // Note this resource is defined in the sync adapter package, not resourcePackageName. - return getResourceText(context, syncAdapterPackageName, getInviteContactActionResId(), ""); - } - - /** - * Returns a label for the "view group" action. If not defined, this falls back to our - * own "View Updates" string - */ - public CharSequence getViewGroupLabel(Context context) { - // Note this resource is defined in the sync adapter package, not resourcePackageName. - final CharSequence customTitle = - getResourceText(context, syncAdapterPackageName, getViewGroupLabelResId(), null); - - return customTitle == null - ? context.getText(R.string.view_updates_from_group) - : customTitle; - } - - /** - * Return a string resource loaded from the given package (or the current package - * if {@code packageName} is null), unless {@code resId} is -1, in which case it returns - * {@code defaultValue}. - * - * (The behavior is undefined if the resource or package doesn't exist.) - */ - @VisibleForTesting - static CharSequence getResourceText(Context context, String packageName, int resId, - String defaultValue) { - if (resId != -1 && packageName != null) { - final PackageManager pm = context.getPackageManager(); - return pm.getText(packageName, resId, null); - } else if (resId != -1) { - return context.getText(resId); - } else { - return defaultValue; - } - } - - public Drawable getDisplayIcon(Context context) { - if (this.titleRes != -1 && this.syncAdapterPackageName != null) { - final PackageManager pm = context.getPackageManager(); - return pm.getDrawable(this.syncAdapterPackageName, this.iconRes, null); - } else if (this.titleRes != -1) { - return context.getResources().getDrawable(this.iconRes); - } else { - return null; - } - } - - /** - * Whether or not groups created under this account type have editable membership lists. - */ - abstract public boolean isGroupMembershipEditable(); - - /** - * {@link Comparator} to sort by {@link DataKind#weight}. - */ - private static Comparator<DataKind> sWeightComparator = new Comparator<DataKind>() { - @Override - public int compare(DataKind object1, DataKind object2) { - return object1.weight - object2.weight; - } - }; - - /** - * Return list of {@link DataKind} supported, sorted by - * {@link DataKind#weight}. - */ - public ArrayList<DataKind> getSortedDataKinds() { - // TODO: optimize by marking if already sorted - Collections.sort(mKinds, sWeightComparator); - return mKinds; - } - - /** - * Find the {@link DataKind} for a specific MIME-type, if it's handled by - * this data source. - */ - public DataKind getKindForMimetype(String mimeType) { - return this.mMimeKinds.get(mimeType); - } - - /** - * Add given {@link DataKind} to list of those provided by this source. - */ - public DataKind addKind(DataKind kind) throws DefinitionException { - if (kind.mimeType == null) { - throw new DefinitionException("null is not a valid mime type"); - } - if (mMimeKinds.get(kind.mimeType) != null) { - throw new DefinitionException( - "mime type '" + kind.mimeType + "' is already registered"); - } - - kind.resourcePackageName = this.resourcePackageName; - this.mKinds.add(kind); - this.mMimeKinds.put(kind.mimeType, kind); - return kind; - } - - /** - * Description of a specific "type" or "label" of a {@link DataKind} row, - * such as {@link Phone#TYPE_WORK}. Includes constraints on total number of - * rows a {@link Contacts} may have of this type, and details on how - * user-defined labels are stored. - */ - public static class EditType { - public int rawValue; - public int labelRes; - public boolean secondary; - /** - * The number of entries allowed for the type. -1 if not specified. - * @see DataKind#typeOverallMax - */ - public int specificMax; - public String customColumn; - - public EditType(int rawValue, int labelRes) { - this.rawValue = rawValue; - this.labelRes = labelRes; - this.specificMax = -1; - } - - public EditType setSecondary(boolean secondary) { - this.secondary = secondary; - return this; - } - - public EditType setSpecificMax(int specificMax) { - this.specificMax = specificMax; - return this; - } - - public EditType setCustomColumn(String customColumn) { - this.customColumn = customColumn; - return this; - } - - @Override - public boolean equals(Object object) { - if (object instanceof EditType) { - final EditType other = (EditType)object; - return other.rawValue == rawValue; - } - return false; - } - - @Override - public int hashCode() { - return rawValue; - } - - @Override - public String toString() { - return this.getClass().getSimpleName() - + " rawValue=" + rawValue - + " labelRes=" + labelRes - + " secondary=" + secondary - + " specificMax=" + specificMax - + " customColumn=" + customColumn; - } - } - - public static class EventEditType extends EditType { - private boolean mYearOptional; - - public EventEditType(int rawValue, int labelRes) { - super(rawValue, labelRes); - } - - public boolean isYearOptional() { - return mYearOptional; - } - - public EventEditType setYearOptional(boolean yearOptional) { - mYearOptional = yearOptional; - return this; - } - - @Override - public String toString() { - return super.toString() + " mYearOptional=" + mYearOptional; - } - } - - /** - * Description of a user-editable field on a {@link DataKind} row, such as - * {@link Phone#NUMBER}. Includes flags to apply to an {@link EditText}, and - * the column where this field is stored. - */ - public static final class EditField { - public String column; - public int titleRes; - public int inputType; - public int minLines; - public boolean optional; - public boolean shortForm; - public boolean longForm; - - public EditField(String column, int titleRes) { - this.column = column; - this.titleRes = titleRes; - } - - public EditField(String column, int titleRes, int inputType) { - this(column, titleRes); - this.inputType = inputType; - } - - public EditField setOptional(boolean optional) { - this.optional = optional; - return this; - } - - public EditField setShortForm(boolean shortForm) { - this.shortForm = shortForm; - return this; - } - - public EditField setLongForm(boolean longForm) { - this.longForm = longForm; - return this; - } - - public EditField setMinLines(int minLines) { - this.minLines = minLines; - return this; - } - - public boolean isMultiLine() { - return (inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) != 0; - } - - - @Override - public String toString() { - return this.getClass().getSimpleName() + ":" - + " column=" + column - + " titleRes=" + titleRes - + " inputType=" + inputType - + " minLines=" + minLines - + " optional=" + optional - + " shortForm=" + shortForm - + " longForm=" + longForm; - } - } - - /** - * Generic method of inflating a given {@link ContentValues} into a user-readable - * {@link CharSequence}. For example, an inflater could combine the multiple - * columns of {@link StructuredPostal} together using a string resource - * before presenting to the user. - */ - public interface StringInflater { - public CharSequence inflateUsing(Context context, ContentValues values); - } - - /** - * Compare two {@link AccountType} by their {@link AccountType#getDisplayLabel} with the - * current locale. - */ - public static class DisplayLabelComparator implements Comparator<AccountType> { - private final Context mContext; - /** {@link Comparator} for the current locale. */ - private final Collator mCollator = Collator.getInstance(); - - public DisplayLabelComparator(Context context) { - mContext = context; - } - - private String getDisplayLabel(AccountType type) { - CharSequence label = type.getDisplayLabel(mContext); - return (label == null) ? "" : label.toString(); - } - - @Override - public int compare(AccountType lhs, AccountType rhs) { - return mCollator.compare(getDisplayLabel(lhs), getDisplayLabel(rhs)); - } - } -} diff --git a/src/com/android/contacts/model/account/AccountTypeWithDataSet.java b/src/com/android/contacts/model/account/AccountTypeWithDataSet.java deleted file mode 100644 index ab0a8913e..000000000 --- a/src/com/android/contacts/model/account/AccountTypeWithDataSet.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.contacts.model.account; - -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.provider.BaseColumns; -import android.provider.ContactsContract; -import android.provider.ContactsContract.RawContacts; -import android.text.TextUtils; - -import com.google.common.base.Objects; - - -/** - * Encapsulates an "account type" string and a "data set" string. - */ -public class AccountTypeWithDataSet { - - private static final String[] ID_PROJECTION = new String[] {BaseColumns._ID}; - private static final Uri RAW_CONTACTS_URI_LIMIT_1 = RawContacts.CONTENT_URI.buildUpon() - .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, "1").build(); - - /** account type. Can be null for fallback type. */ - public final String accountType; - - /** dataSet may be null, but never be "". */ - public final String dataSet; - - private AccountTypeWithDataSet(String accountType, String dataSet) { - this.accountType = TextUtils.isEmpty(accountType) ? null : accountType; - this.dataSet = TextUtils.isEmpty(dataSet) ? null : dataSet; - } - - public static AccountTypeWithDataSet get(String accountType, String dataSet) { - return new AccountTypeWithDataSet(accountType, dataSet); - } - - /** - * Return true if there are any contacts in the database with this account type and data set. - * Touches DB. Don't use in the UI thread. - */ - public boolean hasData(Context context) { - final String BASE_SELECTION = RawContacts.ACCOUNT_TYPE + " = ?"; - final String selection; - final String[] args; - if (TextUtils.isEmpty(dataSet)) { - selection = BASE_SELECTION + " AND " + RawContacts.DATA_SET + " IS NULL"; - args = new String[] {accountType}; - } else { - selection = BASE_SELECTION + " AND " + RawContacts.DATA_SET + " = ?"; - args = new String[] {accountType, dataSet}; - } - - final Cursor c = context.getContentResolver().query(RAW_CONTACTS_URI_LIMIT_1, - ID_PROJECTION, selection, args, null); - if (c == null) return false; - try { - return c.moveToFirst(); - } finally { - c.close(); - } - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof AccountTypeWithDataSet)) return false; - - AccountTypeWithDataSet other = (AccountTypeWithDataSet) o; - return Objects.equal(accountType, other.accountType) - && Objects.equal(dataSet, other.dataSet); - } - - @Override - public int hashCode() { - return (accountType == null ? 0 : accountType.hashCode()) - ^ (dataSet == null ? 0 : dataSet.hashCode()); - } - - @Override - public String toString() { - return "[" + accountType + "/" + dataSet + "]"; - } -} diff --git a/src/com/android/contacts/model/account/AccountWithDataSet.java b/src/com/android/contacts/model/account/AccountWithDataSet.java deleted file mode 100644 index 03fcc02f4..000000000 --- a/src/com/android/contacts/model/account/AccountWithDataSet.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.contacts.model.account; - -import android.accounts.Account; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.os.Parcel; -import android.provider.BaseColumns; -import android.provider.ContactsContract; -import android.provider.ContactsContract.RawContacts; -import android.text.TextUtils; - -import com.android.internal.util.Objects; -import com.google.common.collect.Lists; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; - -/** - * Wrapper for an account that includes a data set (which may be null). - */ -public class AccountWithDataSet extends Account { - private static final String STRINGIFY_SEPARATOR = "\u0001"; - private static final String ARRAY_STRINGIFY_SEPARATOR = "\u0002"; - - private static final Pattern STRINGIFY_SEPARATOR_PAT = - Pattern.compile(Pattern.quote(STRINGIFY_SEPARATOR)); - private static final Pattern ARRAY_STRINGIFY_SEPARATOR_PAT = - Pattern.compile(Pattern.quote(ARRAY_STRINGIFY_SEPARATOR)); - - public final String dataSet; - private final AccountTypeWithDataSet mAccountTypeWithDataSet; - - private static final String[] ID_PROJECTION = new String[] {BaseColumns._ID}; - private static final Uri RAW_CONTACTS_URI_LIMIT_1 = RawContacts.CONTENT_URI.buildUpon() - .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, "1").build(); - - - public AccountWithDataSet(String name, String type, String dataSet) { - super(name, type); - this.dataSet = dataSet; - mAccountTypeWithDataSet = AccountTypeWithDataSet.get(type, dataSet); - } - - public AccountWithDataSet(Parcel in) { - super(in); - this.dataSet = in.readString(); - mAccountTypeWithDataSet = AccountTypeWithDataSet.get(type, dataSet); - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeString(dataSet); - } - - // For Parcelable - public static final Creator<AccountWithDataSet> CREATOR = new Creator<AccountWithDataSet>() { - public AccountWithDataSet createFromParcel(Parcel source) { - return new AccountWithDataSet(source); - } - - public AccountWithDataSet[] newArray(int size) { - return new AccountWithDataSet[size]; - } - }; - - public AccountTypeWithDataSet getAccountTypeWithDataSet() { - return mAccountTypeWithDataSet; - } - - /** - * Return {@code true} if this account has any contacts in the database. - * Touches DB. Don't use in the UI thread. - */ - public boolean hasData(Context context) { - final String BASE_SELECTION = - RawContacts.ACCOUNT_TYPE + " = ?" + " AND " + RawContacts.ACCOUNT_NAME + " = ?"; - final String selection; - final String[] args; - if (TextUtils.isEmpty(dataSet)) { - selection = BASE_SELECTION + " AND " + RawContacts.DATA_SET + " IS NULL"; - args = new String[] {type, name}; - } else { - selection = BASE_SELECTION + " AND " + RawContacts.DATA_SET + " = ?"; - args = new String[] {type, name, dataSet}; - } - - final Cursor c = context.getContentResolver().query(RAW_CONTACTS_URI_LIMIT_1, - ID_PROJECTION, selection, args, null); - if (c == null) return false; - try { - return c.moveToFirst(); - } finally { - c.close(); - } - } - - @Override - public boolean equals(Object o) { - return (o instanceof AccountWithDataSet) && super.equals(o) - && Objects.equal(((AccountWithDataSet) o).dataSet, dataSet); - } - - @Override - public int hashCode() { - return 31 * super.hashCode() - + (dataSet == null ? 0 : dataSet.hashCode()); - } - - @Override - public String toString() { - return "AccountWithDataSet {name=" + name + ", type=" + type + ", dataSet=" + dataSet + "}"; - } - - private static StringBuilder addStringified(StringBuilder sb, AccountWithDataSet account) { - sb.append(account.name); - sb.append(STRINGIFY_SEPARATOR); - sb.append(account.type); - sb.append(STRINGIFY_SEPARATOR); - if (!TextUtils.isEmpty(account.dataSet)) sb.append(account.dataSet); - - return sb; - } - - /** - * Pack the instance into a string. - */ - public String stringify() { - return addStringified(new StringBuilder(), this).toString(); - } - - /** - * Unpack a string created by {@link #stringify}. - * - * @throws IllegalArgumentException if it's an invalid string. - */ - public static AccountWithDataSet unstringify(String s) { - final String[] array = STRINGIFY_SEPARATOR_PAT.split(s, 3); - if (array.length < 3) { - throw new IllegalArgumentException("Invalid string " + s); - } - return new AccountWithDataSet(array[0], array[1], - TextUtils.isEmpty(array[2]) ? null : array[2]); - } - - /** - * Pack a list of {@link AccountWithDataSet} into a string. - */ - public static String stringifyList(List<AccountWithDataSet> accounts) { - final StringBuilder sb = new StringBuilder(); - - for (AccountWithDataSet account : accounts) { - if (sb.length() > 0) { - sb.append(ARRAY_STRINGIFY_SEPARATOR); - } - addStringified(sb, account); - } - - return sb.toString(); - } - - /** - * Unpack a list of {@link AccountWithDataSet} into a string. - * - * @throws IllegalArgumentException if it's an invalid string. - */ - public static List<AccountWithDataSet> unstringifyList(String s) { - final ArrayList<AccountWithDataSet> ret = Lists.newArrayList(); - if (TextUtils.isEmpty(s)) { - return ret; - } - - final String[] array = ARRAY_STRINGIFY_SEPARATOR_PAT.split(s); - - for (int i = 0; i < array.length; i++) { - ret.add(unstringify(array[i])); - } - - return ret; - } -} diff --git a/src/com/android/contacts/model/account/BaseAccountType.java b/src/com/android/contacts/model/account/BaseAccountType.java deleted file mode 100644 index 6b4d6234f..000000000 --- a/src/com/android/contacts/model/account/BaseAccountType.java +++ /dev/null @@ -1,1482 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.contacts.model.account; - -import android.content.ContentValues; -import android.content.Context; -import android.content.res.Resources; -import android.provider.ContactsContract.CommonDataKinds.BaseTypes; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.GroupMembership; -import android.provider.ContactsContract.CommonDataKinds.Im; -import android.provider.ContactsContract.CommonDataKinds.Nickname; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Organization; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.Relation; -import android.provider.ContactsContract.CommonDataKinds.SipAddress; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.CommonDataKinds.Website; -import android.util.AttributeSet; -import android.util.Log; -import android.view.inputmethod.EditorInfo; - -import com.android.contacts.R; -import com.android.contacts.common.util.ContactDisplayUtils; -import com.android.contacts.model.dataitem.DataKind; -import com.android.contacts.test.NeededForTesting; -import com.android.contacts.util.DateUtils; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -public abstract class BaseAccountType extends AccountType { - private static final String TAG = "BaseAccountType"; - - protected static final int FLAGS_PHONE = EditorInfo.TYPE_CLASS_PHONE; - protected static final int FLAGS_EMAIL = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; - protected static final int FLAGS_PERSON_NAME = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME; - protected static final int FLAGS_PHONETIC = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_VARIATION_PHONETIC; - protected static final int FLAGS_GENERIC_NAME = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS; - protected static final int FLAGS_NOTE = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE; - protected static final int FLAGS_EVENT = EditorInfo.TYPE_CLASS_TEXT; - protected static final int FLAGS_WEBSITE = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_VARIATION_URI; - protected static final int FLAGS_POSTAL = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS - | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE; - protected static final int FLAGS_SIP_ADDRESS = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; // since SIP addresses have the same - // basic format as email addresses - protected static final int FLAGS_RELATION = EditorInfo.TYPE_CLASS_TEXT - | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME; - - // Specify the maximum number of lines that can be used to display various field types. If no - // value is specified for a particular type, we use the default value from {@link DataKind}. - protected static final int MAX_LINES_FOR_POSTAL_ADDRESS = 10; - protected static final int MAX_LINES_FOR_GROUP = 10; - protected static final int MAX_LINES_FOR_NOTE = 100; - - private interface Tag { - static final String DATA_KIND = "DataKind"; - static final String TYPE = "Type"; - } - - private interface Attr { - static final String MAX_OCCURRENCE = "maxOccurs"; - static final String DATE_WITH_TIME = "dateWithTime"; - static final String YEAR_OPTIONAL = "yearOptional"; - static final String KIND = "kind"; - static final String TYPE = "type"; - } - - private interface Weight { - static final int NONE = -1; - static final int ORGANIZATION = 5; - static final int PHONE = 10; - static final int EMAIL = 15; - static final int IM = 20; - static final int STRUCTURED_POSTAL = 25; - static final int NOTE = 110; - static final int NICKNAME = 115; - static final int WEBSITE = 120; - static final int SIP_ADDRESS = 130; - static final int EVENT = 150; - static final int RELATIONSHIP = 160; - static final int GROUP_MEMBERSHIP = 999; - } - - public BaseAccountType() { - this.accountType = null; - this.dataSet = null; - this.titleRes = R.string.account_phone; - this.iconRes = R.mipmap.ic_launcher_contacts; - } - - protected static EditType buildPhoneType(int type) { - return new EditType(type, Phone.getTypeLabelResource(type)); - } - - protected static EditType buildEmailType(int type) { - return new EditType(type, Email.getTypeLabelResource(type)); - } - - protected static EditType buildPostalType(int type) { - return new EditType(type, StructuredPostal.getTypeLabelResource(type)); - } - - protected static EditType buildImType(int type) { - return new EditType(type, Im.getProtocolLabelResource(type)); - } - - protected static EditType buildEventType(int type, boolean yearOptional) { - return new EventEditType(type, Event.getTypeResource(type)).setYearOptional(yearOptional); - } - - protected static EditType buildRelationType(int type) { - return new EditType(type, Relation.getTypeLabelResource(type)); - } - - protected DataKind addDataKindStructuredName(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE, - R.string.nameLabelsGroup, -1, true, R.layout.structured_name_editor_view)); - kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup); - kind.actionBody = new SimpleInflater(Nickname.NAME); - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME, - R.string.full_name, FLAGS_PERSON_NAME)); - kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME, - R.string.name_phonetic_family, FLAGS_PHONETIC)); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME, - R.string.name_phonetic_middle, FLAGS_PHONETIC)); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME, - R.string.name_phonetic_given, FLAGS_PHONETIC)); - - return kind; - } - - protected DataKind addDataKindDisplayName(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME, - R.string.nameLabelsGroup, -1, true, R.layout.text_fields_editor_view)); - kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup); - kind.actionBody = new SimpleInflater(Nickname.NAME); - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME, - R.string.full_name, FLAGS_PERSON_NAME).setShortForm(true)); - - boolean displayOrderPrimary = - context.getResources().getBoolean(R.bool.config_editor_field_order_primary); - - if (!displayOrderPrimary) { - kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix, - FLAGS_PERSON_NAME).setLongForm(true)); - } else { - kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family, - FLAGS_PERSON_NAME).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix, - FLAGS_PERSON_NAME).setLongForm(true)); - } - - return kind; - } - - protected DataKind addDataKindPhoneticName(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME, - R.string.name_phonetic, -1, true, R.layout.phonetic_name_editor_view)); - kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup); - kind.actionBody = new SimpleInflater(Nickname.NAME); - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(DataKind.PSEUDO_COLUMN_PHONETIC_NAME, - R.string.name_phonetic, FLAGS_PHONETIC).setShortForm(true)); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME, - R.string.name_phonetic_family, FLAGS_PHONETIC).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME, - R.string.name_phonetic_middle, FLAGS_PHONETIC).setLongForm(true)); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME, - R.string.name_phonetic_given, FLAGS_PHONETIC).setLongForm(true)); - - return kind; - } - - protected DataKind addDataKindNickname(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE, - R.string.nicknameLabelsGroup, 115, true, R.layout.text_fields_editor_view)); - kind.typeOverallMax = 1; - kind.actionHeader = new SimpleInflater(R.string.nicknameLabelsGroup); - kind.actionBody = new SimpleInflater(Nickname.NAME); - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Nickname.TYPE, Nickname.TYPE_DEFAULT); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Nickname.NAME, R.string.nicknameLabelsGroup, - FLAGS_PERSON_NAME)); - - return kind; - } - - protected DataKind addDataKindPhone(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup, - 10, true, R.layout.text_fields_editor_view)); - kind.iconAltRes = R.drawable.ic_text_holo_light; - kind.iconAltDescriptionRes = R.string.sms; - kind.actionHeader = new PhoneActionInflater(); - kind.actionAltHeader = new PhoneActionAltInflater(); - kind.actionBody = new SimpleInflater(Phone.NUMBER); - kind.typeColumn = Phone.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE)); - kind.typeList.add(buildPhoneType(Phone.TYPE_HOME)); - kind.typeList.add(buildPhoneType(Phone.TYPE_WORK)); - kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER)); - kind.typeList.add( - buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true).setCustomColumn(Phone.LABEL)); - kind.typeList.add(buildPhoneType(Phone.TYPE_CALLBACK).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_CAR).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_COMPANY_MAIN).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_ISDN).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER_FAX).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_RADIO).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_TELEX).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_TTY_TDD).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_MOBILE).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_WORK_PAGER).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_ASSISTANT).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_MMS).setSecondary(true)); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE)); - - return kind; - } - - protected DataKind addDataKindEmail(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Email.CONTENT_ITEM_TYPE, R.string.emailLabelsGroup, - 15, true, R.layout.text_fields_editor_view)); - kind.actionHeader = new EmailActionInflater(); - kind.actionBody = new SimpleInflater(Email.DATA); - kind.typeColumn = Email.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildEmailType(Email.TYPE_HOME)); - kind.typeList.add(buildEmailType(Email.TYPE_WORK)); - kind.typeList.add(buildEmailType(Email.TYPE_OTHER)); - kind.typeList.add(buildEmailType(Email.TYPE_MOBILE)); - kind.typeList.add( - buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn(Email.LABEL)); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL)); - - return kind; - } - - protected DataKind addDataKindStructuredPostal(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(StructuredPostal.CONTENT_ITEM_TYPE, - R.string.postalLabelsGroup, 25, true, R.layout.text_fields_editor_view)); - kind.actionHeader = new PostalActionInflater(); - kind.actionBody = new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS); - kind.typeColumn = StructuredPostal.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildPostalType(StructuredPostal.TYPE_HOME)); - kind.typeList.add(buildPostalType(StructuredPostal.TYPE_WORK)); - kind.typeList.add(buildPostalType(StructuredPostal.TYPE_OTHER)); - kind.typeList.add(buildPostalType(StructuredPostal.TYPE_CUSTOM).setSecondary(true) - .setCustomColumn(StructuredPostal.LABEL)); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add( - new EditField(StructuredPostal.FORMATTED_ADDRESS, R.string.postal_address, - FLAGS_POSTAL)); - - kind.maxLinesForDisplay = MAX_LINES_FOR_POSTAL_ADDRESS; - - return kind; - } - - protected DataKind addDataKindIm(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup, 20, true, - R.layout.text_fields_editor_view)); - kind.actionHeader = new ImActionInflater(); - kind.actionBody = new SimpleInflater(Im.DATA); - - // NOTE: even though a traditional "type" exists, for editing - // purposes we're using the protocol to pick labels - - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Im.TYPE, Im.TYPE_OTHER); - - kind.typeColumn = Im.PROTOCOL; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildImType(Im.PROTOCOL_AIM)); - kind.typeList.add(buildImType(Im.PROTOCOL_MSN)); - kind.typeList.add(buildImType(Im.PROTOCOL_YAHOO)); - kind.typeList.add(buildImType(Im.PROTOCOL_SKYPE)); - kind.typeList.add(buildImType(Im.PROTOCOL_QQ)); - kind.typeList.add(buildImType(Im.PROTOCOL_GOOGLE_TALK)); - kind.typeList.add(buildImType(Im.PROTOCOL_ICQ)); - kind.typeList.add(buildImType(Im.PROTOCOL_JABBER)); - kind.typeList.add(buildImType(Im.PROTOCOL_CUSTOM).setSecondary(true).setCustomColumn( - Im.CUSTOM_PROTOCOL)); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Im.DATA, R.string.imLabelsGroup, FLAGS_EMAIL)); - - return kind; - } - - protected DataKind addDataKindOrganization(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Organization.CONTENT_ITEM_TYPE, - R.string.organizationLabelsGroup, 5, true, - R.layout.text_fields_editor_view)); - kind.actionHeader = new SimpleInflater(Organization.COMPANY); - kind.actionBody = new SimpleInflater(Organization.TITLE); - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Organization.COMPANY, R.string.ghostData_company, - FLAGS_GENERIC_NAME)); - kind.fieldList.add(new EditField(Organization.TITLE, R.string.ghostData_title, - FLAGS_GENERIC_NAME)); - - return kind; - } - - protected DataKind addDataKindPhoto(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, true, -1)); - kind.typeOverallMax = 1; - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1)); - return kind; - } - - protected DataKind addDataKindNote(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE, - R.string.label_notes, 110, true, R.layout.text_fields_editor_view)); - kind.typeOverallMax = 1; - kind.actionHeader = new SimpleInflater(R.string.label_notes); - kind.actionBody = new SimpleInflater(Note.NOTE); - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Note.NOTE, R.string.label_notes, FLAGS_NOTE)); - - kind.maxLinesForDisplay = MAX_LINES_FOR_NOTE; - - return kind; - } - - protected DataKind addDataKindWebsite(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Website.CONTENT_ITEM_TYPE, - R.string.websiteLabelsGroup, 120, true, R.layout.text_fields_editor_view)); - kind.actionHeader = new SimpleInflater(R.string.websiteLabelsGroup); - kind.actionBody = new SimpleInflater(Website.URL); - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Website.TYPE, Website.TYPE_OTHER); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Website.URL, R.string.websiteLabelsGroup, FLAGS_WEBSITE)); - - return kind; - } - - protected DataKind addDataKindSipAddress(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE, - R.string.label_sip_address, 130, true, R.layout.text_fields_editor_view)); - - kind.typeOverallMax = 1; - kind.actionHeader = new SimpleInflater(R.string.label_sip_address); - kind.actionBody = new SimpleInflater(SipAddress.SIP_ADDRESS); - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(SipAddress.SIP_ADDRESS, - R.string.label_sip_address, FLAGS_SIP_ADDRESS)); - - return kind; - } - - protected DataKind addDataKindGroupMembership(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(GroupMembership.CONTENT_ITEM_TYPE, - R.string.groupsLabel, 999, true, -1)); - - kind.typeOverallMax = 1; - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(GroupMembership.GROUP_ROW_ID, -1, -1)); - - kind.maxLinesForDisplay = MAX_LINES_FOR_GROUP; - - return kind; - } - - /** - * Simple inflater that assumes a string resource has a "%s" that will be - * filled from the given column. - */ - public static class SimpleInflater implements StringInflater { - private final int mStringRes; - private final String mColumnName; - - public SimpleInflater(int stringRes) { - this(stringRes, null); - } - - public SimpleInflater(String columnName) { - this(-1, columnName); - } - - public SimpleInflater(int stringRes, String columnName) { - mStringRes = stringRes; - mColumnName = columnName; - } - - @Override - public CharSequence inflateUsing(Context context, ContentValues values) { - final boolean validColumn = values.containsKey(mColumnName); - final boolean validString = mStringRes > 0; - - final CharSequence stringValue = validString ? context.getText(mStringRes) : null; - final CharSequence columnValue = validColumn ? values.getAsString(mColumnName) : null; - - if (validString && validColumn) { - return String.format(stringValue.toString(), columnValue); - } else if (validString) { - return stringValue; - } else if (validColumn) { - return columnValue; - } else { - return null; - } - } - - @Override - public String toString() { - return this.getClass().getSimpleName() - + " mStringRes=" + mStringRes - + " mColumnName" + mColumnName; - } - - @NeededForTesting - public String getColumnNameForTest() { - return mColumnName; - } - } - - public static abstract class CommonInflater implements StringInflater { - protected abstract int getTypeLabelResource(Integer type); - - protected boolean isCustom(Integer type) { - return type == BaseTypes.TYPE_CUSTOM; - } - - protected String getTypeColumn() { - return Phone.TYPE; - } - - protected String getLabelColumn() { - return Phone.LABEL; - } - - protected CharSequence getTypeLabel(Resources res, Integer type, CharSequence label) { - final int labelRes = getTypeLabelResource(type); - if (type == null) { - return res.getText(labelRes); - } else if (isCustom(type)) { - return res.getString(labelRes, label == null ? "" : label); - } else { - return res.getText(labelRes); - } - } - - @Override - public CharSequence inflateUsing(Context context, ContentValues values) { - final Integer type = values.getAsInteger(getTypeColumn()); - final String label = values.getAsString(getLabelColumn()); - return getTypeLabel(context.getResources(), type, label); - } - - @Override - public String toString() { - return this.getClass().getSimpleName(); - } - } - - public static class PhoneActionInflater extends CommonInflater { - @Override - protected boolean isCustom(Integer type) { - return ContactDisplayUtils.isCustomPhoneType(type); - } - - @Override - protected int getTypeLabelResource(Integer type) { - return ContactDisplayUtils.getPhoneLabelResourceId(type); - } - } - - public static class PhoneActionAltInflater extends CommonInflater { - @Override - protected boolean isCustom(Integer type) { - return ContactDisplayUtils.isCustomPhoneType(type); - } - - @Override - protected int getTypeLabelResource(Integer type) { - return ContactDisplayUtils.getSmsLabelResourceId(type); - } - } - - public static class EmailActionInflater extends CommonInflater { - @Override - protected int getTypeLabelResource(Integer type) { - if (type == null) return R.string.email; - switch (type) { - case Email.TYPE_HOME: return R.string.email_home; - case Email.TYPE_WORK: return R.string.email_work; - case Email.TYPE_OTHER: return R.string.email_other; - case Email.TYPE_MOBILE: return R.string.email_mobile; - default: return R.string.email_custom; - } - } - } - - public static class EventActionInflater extends CommonInflater { - @Override - protected int getTypeLabelResource(Integer type) { - return Event.getTypeResource(type); - } - } - - public static class RelationActionInflater extends CommonInflater { - @Override - protected int getTypeLabelResource(Integer type) { - return Relation.getTypeLabelResource(type == null ? Relation.TYPE_CUSTOM : type); - } - } - - public static class PostalActionInflater extends CommonInflater { - @Override - protected int getTypeLabelResource(Integer type) { - if (type == null) return R.string.map_other; - switch (type) { - case StructuredPostal.TYPE_HOME: return R.string.map_home; - case StructuredPostal.TYPE_WORK: return R.string.map_work; - case StructuredPostal.TYPE_OTHER: return R.string.map_other; - default: return R.string.map_custom; - } - } - } - - public static class ImActionInflater extends CommonInflater { - @Override - protected String getTypeColumn() { - return Im.PROTOCOL; - } - - @Override - protected String getLabelColumn() { - return Im.CUSTOM_PROTOCOL; - } - - @Override - protected int getTypeLabelResource(Integer type) { - if (type == null) return R.string.chat; - switch (type) { - case Im.PROTOCOL_AIM: return R.string.chat_aim; - case Im.PROTOCOL_MSN: return R.string.chat_msn; - case Im.PROTOCOL_YAHOO: return R.string.chat_yahoo; - case Im.PROTOCOL_SKYPE: return R.string.chat_skype; - case Im.PROTOCOL_QQ: return R.string.chat_qq; - case Im.PROTOCOL_GOOGLE_TALK: return R.string.chat_gtalk; - case Im.PROTOCOL_ICQ: return R.string.chat_icq; - case Im.PROTOCOL_JABBER: return R.string.chat_jabber; - case Im.PROTOCOL_NETMEETING: return R.string.chat; - default: return R.string.chat; - } - } - } - - @Override - public boolean isGroupMembershipEditable() { - return false; - } - - /** - * Parses the content of the EditSchema tag in contacts.xml. - */ - protected final void parseEditSchema(Context context, XmlPullParser parser, AttributeSet attrs) - throws XmlPullParserException, IOException, DefinitionException { - - final int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - final int depth = parser.getDepth(); - if (type != XmlPullParser.START_TAG || depth != outerDepth + 1) { - continue; // Not direct child tag - } - - final String tag = parser.getName(); - - if (Tag.DATA_KIND.equals(tag)) { - for (DataKind kind : KindParser.INSTANCE.parseDataKindTag(context, parser, attrs)) { - addKind(kind); - } - } else { - Log.w(TAG, "Skipping unknown tag " + tag); - } - } - } - - // Utility methods to keep code shorter. - private static boolean getAttr(AttributeSet attrs, String attribute, boolean defaultValue) { - return attrs.getAttributeBooleanValue(null, attribute, defaultValue); - } - - private static int getAttr(AttributeSet attrs, String attribute, int defaultValue) { - return attrs.getAttributeIntValue(null, attribute, defaultValue); - } - - private static String getAttr(AttributeSet attrs, String attribute) { - return attrs.getAttributeValue(null, attribute); - } - - // TODO Extract it to its own class, and move all KindBuilders to it as well. - private static class KindParser { - public static final KindParser INSTANCE = new KindParser(); - - private final Map<String, KindBuilder> mBuilders = Maps.newHashMap(); - - private KindParser() { - addBuilder(new NameKindBuilder()); - addBuilder(new NicknameKindBuilder()); - addBuilder(new PhoneKindBuilder()); - addBuilder(new EmailKindBuilder()); - addBuilder(new StructuredPostalKindBuilder()); - addBuilder(new ImKindBuilder()); - addBuilder(new OrganizationKindBuilder()); - addBuilder(new PhotoKindBuilder()); - addBuilder(new NoteKindBuilder()); - addBuilder(new WebsiteKindBuilder()); - addBuilder(new SipAddressKindBuilder()); - addBuilder(new GroupMembershipKindBuilder()); - addBuilder(new EventKindBuilder()); - addBuilder(new RelationshipKindBuilder()); - } - - private void addBuilder(KindBuilder builder) { - mBuilders.put(builder.getTagName(), builder); - } - - /** - * Takes a {@link XmlPullParser} at the start of a DataKind tag, parses it and returns - * {@link DataKind}s. (Usually just one, but there are three for the "name" kind.) - * - * This method returns a list, because we need to add 3 kinds for the name data kind. - * (structured, display and phonetic) - */ - public List<DataKind> parseDataKindTag(Context context, XmlPullParser parser, - AttributeSet attrs) - throws DefinitionException, XmlPullParserException, IOException { - final String kind = getAttr(attrs, Attr.KIND); - final KindBuilder builder = mBuilders.get(kind); - if (builder != null) { - return builder.parseDataKind(context, parser, attrs); - } else { - throw new DefinitionException("Undefined data kind '" + kind + "'"); - } - } - } - - private static abstract class KindBuilder { - - public abstract String getTagName(); - - /** - * DataKind tag parser specific to each kind. Subclasses must implement it. - */ - public abstract List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, IOException; - - /** - * Creates a new {@link DataKind}, and also parses the child Type tags in the DataKind - * tag. - */ - protected final DataKind newDataKind(Context context, XmlPullParser parser, - AttributeSet attrs, boolean isPseudo, String mimeType, String typeColumn, - int titleRes, int weight, int editorLayoutResourceId, - StringInflater actionHeader, StringInflater actionBody) - throws DefinitionException, XmlPullParserException, IOException { - - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "Adding DataKind: " + mimeType); - } - - final DataKind kind = new DataKind(mimeType, titleRes, weight, true, - editorLayoutResourceId); - kind.typeColumn = typeColumn; - kind.actionHeader = actionHeader; - kind.actionBody = actionBody; - kind.fieldList = Lists.newArrayList(); - - // Get more information from the tag... - // A pseudo data kind doesn't have corresponding tag the XML, so we skip this. - if (!isPseudo) { - kind.typeOverallMax = getAttr(attrs, Attr.MAX_OCCURRENCE, -1); - - // Process "Type" tags. - // If a kind has the type column, contacts.xml must have at least one type - // definition. Otherwise, it mustn't have a type definition. - if (kind.typeColumn != null) { - // Parse and add types. - kind.typeList = Lists.newArrayList(); - parseTypes(context, parser, attrs, kind, true); - if (kind.typeList.size() == 0) { - throw new DefinitionException( - "Kind " + kind.mimeType + " must have at least one type"); - } - } else { - // Make sure it has no types. - parseTypes(context, parser, attrs, kind, false /* can't have types */); - } - } - - return kind; - } - - /** - * Parses Type elements in a DataKind element, and if {@code canHaveTypes} is true adds - * them to the given {@link DataKind}. Otherwise the {@link DataKind} can't have a type, - * so throws {@link DefinitionException}. - */ - private void parseTypes(Context context, XmlPullParser parser, AttributeSet attrs, - DataKind kind, boolean canHaveTypes) - throws DefinitionException, XmlPullParserException, IOException { - final int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - final int depth = parser.getDepth(); - if (type != XmlPullParser.START_TAG || depth != outerDepth + 1) { - continue; // Not direct child tag - } - - final String tag = parser.getName(); - if (Tag.TYPE.equals(tag)) { - if (canHaveTypes) { - kind.typeList.add(parseTypeTag(parser, attrs, kind)); - } else { - throw new DefinitionException( - "Kind " + kind.mimeType + " can't have types"); - } - } else { - throw new DefinitionException("Unknown tag: " + tag); - } - } - } - - /** - * Parses a single Type element and returns an {@link EditType} built from it. Uses - * {@link #buildEditTypeForTypeTag} defined in subclasses to actually build an - * {@link EditType}. - */ - private EditType parseTypeTag(XmlPullParser parser, AttributeSet attrs, DataKind kind) - throws DefinitionException { - - final String typeName = getAttr(attrs, Attr.TYPE); - - final EditType et = buildEditTypeForTypeTag(attrs, typeName); - if (et == null) { - throw new DefinitionException( - "Undefined type '" + typeName + "' for data kind '" + kind.mimeType + "'"); - } - et.specificMax = getAttr(attrs, Attr.MAX_OCCURRENCE, -1); - - return et; - } - - /** - * Returns an {@link EditType} for the given "type". Subclasses may optionally use - * the attributes in the tag to set optional values. - * (e.g. "yearOptional" for the event kind) - */ - protected EditType buildEditTypeForTypeTag(AttributeSet attrs, String type) { - return null; - } - - protected final void throwIfList(DataKind kind) throws DefinitionException { - if (kind.typeOverallMax != 1) { - throw new DefinitionException( - "Kind " + kind.mimeType + " must have 'overallMax=\"1\"'"); - } - } - } - - /** - * DataKind parser for Name. (structured, display, phonetic) - */ - private static class NameKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "name"; - } - - private static void checkAttributeTrue(boolean value, String attrName) - throws DefinitionException { - if (!value) { - throw new DefinitionException(attrName + " must be true"); - } - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - - // Build 3 data kinds: - // - StructuredName.CONTENT_ITEM_TYPE - // - DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME - // - DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME - - final boolean displayOrderPrimary = - context.getResources().getBoolean(R.bool.config_editor_field_order_primary); - - final boolean supportsDisplayName = getAttr(attrs, "supportsDisplayName", false); - final boolean supportsPrefix = getAttr(attrs, "supportsPrefix", false); - final boolean supportsMiddleName = getAttr(attrs, "supportsMiddleName", false); - final boolean supportsSuffix = getAttr(attrs, "supportsSuffix", false); - final boolean supportsPhoneticFamilyName = - getAttr(attrs, "supportsPhoneticFamilyName", false); - final boolean supportsPhoneticMiddleName = - getAttr(attrs, "supportsPhoneticMiddleName", false); - final boolean supportsPhoneticGivenName = - getAttr(attrs, "supportsPhoneticGivenName", false); - - // For now, every things must be supported. - checkAttributeTrue(supportsDisplayName, "supportsDisplayName"); - checkAttributeTrue(supportsPrefix, "supportsPrefix"); - checkAttributeTrue(supportsMiddleName, "supportsMiddleName"); - checkAttributeTrue(supportsSuffix, "supportsSuffix"); - checkAttributeTrue(supportsPhoneticFamilyName, "supportsPhoneticFamilyName"); - checkAttributeTrue(supportsPhoneticMiddleName, "supportsPhoneticMiddleName"); - checkAttributeTrue(supportsPhoneticGivenName, "supportsPhoneticGivenName"); - - final List<DataKind> kinds = Lists.newArrayList(); - - // Structured name - final DataKind ks = newDataKind(context, parser, attrs, false, - StructuredName.CONTENT_ITEM_TYPE, null, R.string.nameLabelsGroup, Weight.NONE, - R.layout.structured_name_editor_view, - new SimpleInflater(R.string.nameLabelsGroup), - new SimpleInflater(Nickname.NAME)); - - throwIfList(ks); - kinds.add(ks); - - // Note about setLongForm/setShortForm below. - // We need to set this only when the type supports display name. (=supportsDisplayName) - // Otherwise (i.e. Exchange) we don't set these flags, but instead make some fields - // "optional". - - ks.fieldList.add(new EditField(StructuredName.DISPLAY_NAME, R.string.full_name, - FLAGS_PERSON_NAME)); - ks.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix, - FLAGS_PERSON_NAME).setLongForm(true)); - ks.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family, - FLAGS_PERSON_NAME).setLongForm(true)); - ks.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle, - FLAGS_PERSON_NAME).setLongForm(true)); - ks.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given, - FLAGS_PERSON_NAME).setLongForm(true)); - ks.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix, - FLAGS_PERSON_NAME).setLongForm(true)); - ks.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME, - R.string.name_phonetic_family, FLAGS_PHONETIC)); - ks.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME, - R.string.name_phonetic_middle, FLAGS_PHONETIC)); - ks.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME, - R.string.name_phonetic_given, FLAGS_PHONETIC)); - - // Display name - final DataKind kd = newDataKind(context, parser, attrs, true, - DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME, null, - R.string.nameLabelsGroup, Weight.NONE, R.layout.text_fields_editor_view, - new SimpleInflater(R.string.nameLabelsGroup), - new SimpleInflater(Nickname.NAME)); - kd.typeOverallMax = 1; - kinds.add(kd); - - kd.fieldList.add(new EditField(StructuredName.DISPLAY_NAME, - R.string.full_name, FLAGS_PERSON_NAME).setShortForm(true)); - - if (!displayOrderPrimary) { - kd.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix, - FLAGS_PERSON_NAME).setLongForm(true)); - kd.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family, - FLAGS_PERSON_NAME).setLongForm(true)); - kd.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle, - FLAGS_PERSON_NAME).setLongForm(true)); - kd.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given, - FLAGS_PERSON_NAME).setLongForm(true)); - kd.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix, - FLAGS_PERSON_NAME).setLongForm(true)); - } else { - kd.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix, - FLAGS_PERSON_NAME).setLongForm(true)); - kd.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given, - FLAGS_PERSON_NAME).setLongForm(true)); - kd.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, R.string.name_middle, - FLAGS_PERSON_NAME).setLongForm(true)); - kd.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family, - FLAGS_PERSON_NAME).setLongForm(true)); - kd.fieldList.add(new EditField(StructuredName.SUFFIX, R.string.name_suffix, - FLAGS_PERSON_NAME).setLongForm(true)); - } - - // Phonetic name - final DataKind kp = newDataKind(context, parser, attrs, true, - DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME, null, - R.string.name_phonetic, Weight.NONE, R.layout.phonetic_name_editor_view, - new SimpleInflater(R.string.nameLabelsGroup), - new SimpleInflater(Nickname.NAME)); - kp.typeOverallMax = 1; - kinds.add(kp); - - // We may want to change the order depending on displayOrderPrimary too. - kp.fieldList.add(new EditField(DataKind.PSEUDO_COLUMN_PHONETIC_NAME, - R.string.name_phonetic, FLAGS_PHONETIC).setShortForm(true)); - kp.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME, - R.string.name_phonetic_family, FLAGS_PHONETIC).setLongForm(true)); - kp.fieldList.add(new EditField(StructuredName.PHONETIC_MIDDLE_NAME, - R.string.name_phonetic_middle, FLAGS_PHONETIC).setLongForm(true)); - kp.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME, - R.string.name_phonetic_given, FLAGS_PHONETIC).setLongForm(true)); - return kinds; - } - } - - private static class NicknameKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "nickname"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Nickname.CONTENT_ITEM_TYPE, null, R.string.nicknameLabelsGroup, Weight.NICKNAME, - R.layout.text_fields_editor_view, - new SimpleInflater(R.string.nicknameLabelsGroup), - new SimpleInflater(Nickname.NAME)); - - kind.fieldList.add(new EditField(Nickname.NAME, R.string.nicknameLabelsGroup, - FLAGS_PERSON_NAME)); - - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Nickname.TYPE, Nickname.TYPE_DEFAULT); - - throwIfList(kind); - return Lists.newArrayList(kind); - } - } - - private static class PhoneKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "phone"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Phone.CONTENT_ITEM_TYPE, Phone.TYPE, R.string.phoneLabelsGroup, Weight.PHONE, - R.layout.text_fields_editor_view, - new PhoneActionInflater(), new SimpleInflater(Phone.NUMBER)); - - kind.iconAltRes = R.drawable.ic_text_holo_light; - kind.iconAltDescriptionRes = R.string.sms; - kind.actionAltHeader = new PhoneActionAltInflater(); - - kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE)); - - return Lists.newArrayList(kind); - } - - /** Just to avoid line-wrapping... */ - protected static EditType build(int type, boolean secondary) { - return new EditType(type, Phone.getTypeLabelResource(type)).setSecondary(secondary); - } - - @Override - protected EditType buildEditTypeForTypeTag(AttributeSet attrs, String type) { - if ("home".equals(type)) return build(Phone.TYPE_HOME, false); - if ("mobile".equals(type)) return build(Phone.TYPE_MOBILE, false); - if ("work".equals(type)) return build(Phone.TYPE_WORK, false); - if ("fax_work".equals(type)) return build(Phone.TYPE_FAX_WORK, true); - if ("fax_home".equals(type)) return build(Phone.TYPE_FAX_HOME, true); - if ("pager".equals(type)) return build(Phone.TYPE_PAGER, true); - if ("other".equals(type)) return build(Phone.TYPE_OTHER, false); - if ("callback".equals(type)) return build(Phone.TYPE_CALLBACK, true); - if ("car".equals(type)) return build(Phone.TYPE_CAR, true); - if ("company_main".equals(type)) return build(Phone.TYPE_COMPANY_MAIN, true); - if ("isdn".equals(type)) return build(Phone.TYPE_ISDN, true); - if ("main".equals(type)) return build(Phone.TYPE_MAIN, true); - if ("other_fax".equals(type)) return build(Phone.TYPE_OTHER_FAX, true); - if ("radio".equals(type)) return build(Phone.TYPE_RADIO, true); - if ("telex".equals(type)) return build(Phone.TYPE_TELEX, true); - if ("tty_tdd".equals(type)) return build(Phone.TYPE_TTY_TDD, true); - if ("work_mobile".equals(type)) return build(Phone.TYPE_WORK_MOBILE, true); - if ("work_pager".equals(type)) return build(Phone.TYPE_WORK_PAGER, true); - - // Note "assistant" used to be a custom column for the fallback type, but not anymore. - if ("assistant".equals(type)) return build(Phone.TYPE_ASSISTANT, true); - if ("mms".equals(type)) return build(Phone.TYPE_MMS, true); - if ("custom".equals(type)) { - return build(Phone.TYPE_CUSTOM, true).setCustomColumn(Phone.LABEL); - } - return null; - } - } - - private static class EmailKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "email"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Email.CONTENT_ITEM_TYPE, Email.TYPE, R.string.emailLabelsGroup, Weight.EMAIL, - R.layout.text_fields_editor_view, - new EmailActionInflater(), new SimpleInflater(Email.DATA)); - kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL)); - - return Lists.newArrayList(kind); - } - - @Override - protected EditType buildEditTypeForTypeTag(AttributeSet attrs, String type) { - // EditType is mutable, so we need to create a new instance every time. - if ("home".equals(type)) return buildEmailType(Email.TYPE_HOME); - if ("work".equals(type)) return buildEmailType(Email.TYPE_WORK); - if ("other".equals(type)) return buildEmailType(Email.TYPE_OTHER); - if ("mobile".equals(type)) return buildEmailType(Email.TYPE_MOBILE); - if ("custom".equals(type)) { - return buildEmailType(Email.TYPE_CUSTOM) - .setSecondary(true).setCustomColumn(Email.LABEL); - } - return null; - } - } - - private static class StructuredPostalKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "postal"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - StructuredPostal.CONTENT_ITEM_TYPE, StructuredPostal.TYPE, - R.string.postalLabelsGroup, Weight.STRUCTURED_POSTAL, - R.layout.text_fields_editor_view, new PostalActionInflater(), - new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS)); - - if (getAttr(attrs, "needsStructured", false)) { - if (Locale.JAPANESE.getLanguage().equals(Locale.getDefault().getLanguage())) { - // Japanese order - kind.fieldList.add(new EditField(StructuredPostal.COUNTRY, - R.string.postal_country, FLAGS_POSTAL).setOptional(true)); - kind.fieldList.add(new EditField(StructuredPostal.POSTCODE, - R.string.postal_postcode, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.REGION, - R.string.postal_region, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.CITY, - R.string.postal_city,FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.STREET, - R.string.postal_street, FLAGS_POSTAL)); - } else { - // Generic order - kind.fieldList.add(new EditField(StructuredPostal.STREET, - R.string.postal_street, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.CITY, - R.string.postal_city,FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.REGION, - R.string.postal_region, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.POSTCODE, - R.string.postal_postcode, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.COUNTRY, - R.string.postal_country, FLAGS_POSTAL).setOptional(true)); - } - } else { - kind.maxLinesForDisplay= MAX_LINES_FOR_POSTAL_ADDRESS; - kind.fieldList.add( - new EditField(StructuredPostal.FORMATTED_ADDRESS, R.string.postal_address, - FLAGS_POSTAL)); - } - - return Lists.newArrayList(kind); - } - - @Override - protected EditType buildEditTypeForTypeTag(AttributeSet attrs, String type) { - // EditType is mutable, so we need to create a new instance every time. - if ("home".equals(type)) return buildPostalType(StructuredPostal.TYPE_HOME); - if ("work".equals(type)) return buildPostalType(StructuredPostal.TYPE_WORK); - if ("other".equals(type)) return buildPostalType(StructuredPostal.TYPE_OTHER); - if ("custom".equals(type)) { - return buildPostalType(StructuredPostal.TYPE_CUSTOM) - .setSecondary(true).setCustomColumn(Email.LABEL); - } - return null; - } - } - - private static class ImKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "im"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - - // IM is special: - // - It uses "protocol" as the custom label field - // - Its TYPE is fixed to TYPE_OTHER - - final DataKind kind = newDataKind(context, parser, attrs, false, - Im.CONTENT_ITEM_TYPE, Im.PROTOCOL, R.string.imLabelsGroup, Weight.IM, - R.layout.text_fields_editor_view, - new ImActionInflater(), new SimpleInflater(Im.DATA) // header / action - ); - kind.fieldList.add(new EditField(Im.DATA, R.string.imLabelsGroup, FLAGS_EMAIL)); - - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Im.TYPE, Im.TYPE_OTHER); - - return Lists.newArrayList(kind); - } - - @Override - protected EditType buildEditTypeForTypeTag(AttributeSet attrs, String type) { - if ("aim".equals(type)) return buildImType(Im.PROTOCOL_AIM); - if ("msn".equals(type)) return buildImType(Im.PROTOCOL_MSN); - if ("yahoo".equals(type)) return buildImType(Im.PROTOCOL_YAHOO); - if ("skype".equals(type)) return buildImType(Im.PROTOCOL_SKYPE); - if ("qq".equals(type)) return buildImType(Im.PROTOCOL_QQ); - if ("google_talk".equals(type)) return buildImType(Im.PROTOCOL_GOOGLE_TALK); - if ("icq".equals(type)) return buildImType(Im.PROTOCOL_ICQ); - if ("jabber".equals(type)) return buildImType(Im.PROTOCOL_JABBER); - if ("custom".equals(type)) { - return buildImType(Im.PROTOCOL_CUSTOM).setSecondary(true) - .setCustomColumn(Im.CUSTOM_PROTOCOL); - } - return null; - } - } - - private static class OrganizationKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "organization"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Organization.CONTENT_ITEM_TYPE, null, R.string.organizationLabelsGroup, - Weight.ORGANIZATION, R.layout.text_fields_editor_view , - new SimpleInflater(Organization.COMPANY), - new SimpleInflater(Organization.TITLE)); - - kind.fieldList.add(new EditField(Organization.COMPANY, R.string.ghostData_company, - FLAGS_GENERIC_NAME)); - kind.fieldList.add(new EditField(Organization.TITLE, R.string.ghostData_title, - FLAGS_GENERIC_NAME)); - - throwIfList(kind); - - return Lists.newArrayList(kind); - } - } - - private static class PhotoKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "photo"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Photo.CONTENT_ITEM_TYPE, null /* no type */, -1, Weight.NONE, -1, - null, null // no header, no body - ); - - kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1)); - - throwIfList(kind); - - return Lists.newArrayList(kind); - } - } - - private static class NoteKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "note"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Note.CONTENT_ITEM_TYPE, null, R.string.label_notes, Weight.NOTE, - R.layout.text_fields_editor_view, - new SimpleInflater(R.string.label_notes), new SimpleInflater(Note.NOTE)); - - kind.fieldList.add(new EditField(Note.NOTE, R.string.label_notes, FLAGS_NOTE)); - kind.maxLinesForDisplay = MAX_LINES_FOR_NOTE; - - throwIfList(kind); - - return Lists.newArrayList(kind); - } - } - - private static class WebsiteKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "website"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Website.CONTENT_ITEM_TYPE, null, R.string.websiteLabelsGroup, Weight.WEBSITE, - R.layout.text_fields_editor_view, - new SimpleInflater(R.string.websiteLabelsGroup), - new SimpleInflater(Website.URL)); - - kind.fieldList.add(new EditField(Website.URL, R.string.websiteLabelsGroup, - FLAGS_WEBSITE)); - - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Website.TYPE, Website.TYPE_OTHER); - - return Lists.newArrayList(kind); - } - } - - private static class SipAddressKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "sip_address"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - SipAddress.CONTENT_ITEM_TYPE, null, R.string.label_sip_address, - Weight.SIP_ADDRESS, R.layout.text_fields_editor_view, - new SimpleInflater(R.string.label_sip_address), - new SimpleInflater(SipAddress.SIP_ADDRESS)); - - kind.fieldList.add(new EditField(SipAddress.SIP_ADDRESS, - R.string.label_sip_address, FLAGS_SIP_ADDRESS)); - - throwIfList(kind); - - return Lists.newArrayList(kind); - } - } - - private static class GroupMembershipKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "group_membership"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - GroupMembership.CONTENT_ITEM_TYPE, null, - R.string.groupsLabel, Weight.GROUP_MEMBERSHIP, -1, null, null); - - kind.fieldList.add(new EditField(GroupMembership.GROUP_ROW_ID, -1, -1)); - kind.maxLinesForDisplay = MAX_LINES_FOR_GROUP; - - throwIfList(kind); - - return Lists.newArrayList(kind); - } - } - - /** - * Event DataKind parser. - * - * Event DataKind is used only for Google/Exchange types, so this parser is not used for now. - */ - private static class EventKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "event"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Event.CONTENT_ITEM_TYPE, Event.TYPE, R.string.eventLabelsGroup, Weight.EVENT, - R.layout.event_field_editor_view, - new EventActionInflater(), new SimpleInflater(Event.START_DATE)); - - kind.fieldList.add(new EditField(Event.DATA, R.string.eventLabelsGroup, FLAGS_EVENT)); - - if (getAttr(attrs, Attr.DATE_WITH_TIME, false)) { - kind.dateFormatWithoutYear = DateUtils.NO_YEAR_DATE_AND_TIME_FORMAT; - kind.dateFormatWithYear = DateUtils.DATE_AND_TIME_FORMAT; - } else { - kind.dateFormatWithoutYear = DateUtils.NO_YEAR_DATE_FORMAT; - kind.dateFormatWithYear = DateUtils.FULL_DATE_FORMAT; - } - - return Lists.newArrayList(kind); - } - - @Override - protected EditType buildEditTypeForTypeTag(AttributeSet attrs, String type) { - final boolean yo = getAttr(attrs, Attr.YEAR_OPTIONAL, false); - - if ("birthday".equals(type)) { - return buildEventType(Event.TYPE_BIRTHDAY, yo).setSpecificMax(1); - } - if ("anniversary".equals(type)) return buildEventType(Event.TYPE_ANNIVERSARY, yo); - if ("other".equals(type)) return buildEventType(Event.TYPE_OTHER, yo); - if ("custom".equals(type)) { - return buildEventType(Event.TYPE_CUSTOM, yo) - .setSecondary(true).setCustomColumn(Event.LABEL); - } - return null; - } - } - - /** - * Relationship DataKind parser. - * - * Relationship DataKind is used only for Google/Exchange types, so this parser is not used for - * now. - */ - private static class RelationshipKindBuilder extends KindBuilder { - @Override - public String getTagName() { - return "relationship"; - } - - @Override - public List<DataKind> parseDataKind(Context context, XmlPullParser parser, - AttributeSet attrs) throws DefinitionException, XmlPullParserException, - IOException { - final DataKind kind = newDataKind(context, parser, attrs, false, - Relation.CONTENT_ITEM_TYPE, Relation.TYPE, - R.string.relationLabelsGroup, Weight.RELATIONSHIP, - R.layout.text_fields_editor_view, - new RelationActionInflater(), new SimpleInflater(Relation.NAME)); - - kind.fieldList.add(new EditField(Relation.DATA, R.string.relationLabelsGroup, - FLAGS_RELATION)); - - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Relation.TYPE, Relation.TYPE_SPOUSE); - - return Lists.newArrayList(kind); - } - - @Override - protected EditType buildEditTypeForTypeTag(AttributeSet attrs, String type) { - // EditType is mutable, so we need to create a new instance every time. - if ("assistant".equals(type)) return buildRelationType(Relation.TYPE_ASSISTANT); - if ("brother".equals(type)) return buildRelationType(Relation.TYPE_BROTHER); - if ("child".equals(type)) return buildRelationType(Relation.TYPE_CHILD); - if ("domestic_partner".equals(type)) { - return buildRelationType(Relation.TYPE_DOMESTIC_PARTNER); - } - if ("father".equals(type)) return buildRelationType(Relation.TYPE_FATHER); - if ("friend".equals(type)) return buildRelationType(Relation.TYPE_FRIEND); - if ("manager".equals(type)) return buildRelationType(Relation.TYPE_MANAGER); - if ("mother".equals(type)) return buildRelationType(Relation.TYPE_MOTHER); - if ("parent".equals(type)) return buildRelationType(Relation.TYPE_PARENT); - if ("partner".equals(type)) return buildRelationType(Relation.TYPE_PARTNER); - if ("referred_by".equals(type)) return buildRelationType(Relation.TYPE_REFERRED_BY); - if ("relative".equals(type)) return buildRelationType(Relation.TYPE_RELATIVE); - if ("sister".equals(type)) return buildRelationType(Relation.TYPE_SISTER); - if ("spouse".equals(type)) return buildRelationType(Relation.TYPE_SPOUSE); - if ("custom".equals(type)) { - return buildRelationType(Relation.TYPE_CUSTOM).setSecondary(true) - .setCustomColumn(Relation.LABEL); - } - return null; - } - } -} diff --git a/src/com/android/contacts/model/account/ExchangeAccountType.java b/src/com/android/contacts/model/account/ExchangeAccountType.java deleted file mode 100644 index 28b1f5c60..000000000 --- a/src/com/android/contacts/model/account/ExchangeAccountType.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.contacts.model.account; - -import android.content.ContentValues; -import android.content.Context; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.Im; -import android.provider.ContactsContract.CommonDataKinds.Nickname; -import android.provider.ContactsContract.CommonDataKinds.Note; -import android.provider.ContactsContract.CommonDataKinds.Organization; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; -import android.provider.ContactsContract.CommonDataKinds.Website; -import android.util.Log; - -import com.android.contacts.R; -import com.android.contacts.model.dataitem.DataKind; -import com.android.contacts.util.DateUtils; -import com.google.common.collect.Lists; - -import java.util.Locale; - -public class ExchangeAccountType extends BaseAccountType { - private static final String TAG = "ExchangeAccountType"; - - public static final String ACCOUNT_TYPE_AOSP = "com.android.exchange"; - public static final String ACCOUNT_TYPE_GOOGLE = "com.google.android.exchange"; - - public ExchangeAccountType(Context context, String authenticatorPackageName, String type) { - this.accountType = type; - this.resourcePackageName = null; - this.syncAdapterPackageName = authenticatorPackageName; - - try { - addDataKindStructuredName(context); - addDataKindDisplayName(context); - addDataKindPhoneticName(context); - addDataKindNickname(context); - addDataKindPhone(context); - addDataKindEmail(context); - addDataKindStructuredPostal(context); - addDataKindIm(context); - addDataKindOrganization(context); - addDataKindPhoto(context); - addDataKindNote(context); - addDataKindEvent(context); - addDataKindWebsite(context); - addDataKindGroupMembership(context); - - mIsInitialized = true; - } catch (DefinitionException e) { - Log.e(TAG, "Problem building account type", e); - } - } - - public static boolean isExchangeType(String type) { - return ACCOUNT_TYPE_AOSP.equals(type) || ACCOUNT_TYPE_GOOGLE.equals(type); - } - - @Override - protected DataKind addDataKindStructuredName(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE, - R.string.nameLabelsGroup, -1, true, R.layout.structured_name_editor_view)); - kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup); - kind.actionBody = new SimpleInflater(Nickname.NAME); - - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix, - FLAGS_PERSON_NAME).setOptional(true)); - kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, - R.string.name_family, FLAGS_PERSON_NAME)); - kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, - R.string.name_middle, FLAGS_PERSON_NAME)); - kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, - R.string.name_given, FLAGS_PERSON_NAME)); - kind.fieldList.add(new EditField(StructuredName.SUFFIX, - R.string.name_suffix, FLAGS_PERSON_NAME)); - - kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME, - R.string.name_phonetic_family, FLAGS_PHONETIC)); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME, - R.string.name_phonetic_given, FLAGS_PHONETIC)); - - return kind; - } - - @Override - protected DataKind addDataKindDisplayName(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME, - R.string.nameLabelsGroup, -1, true, R.layout.text_fields_editor_view)); - - boolean displayOrderPrimary = - context.getResources().getBoolean(R.bool.config_editor_field_order_primary); - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(StructuredName.PREFIX, R.string.name_prefix, - FLAGS_PERSON_NAME).setOptional(true)); - if (!displayOrderPrimary) { - kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, - R.string.name_family, FLAGS_PERSON_NAME)); - kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, - R.string.name_middle, FLAGS_PERSON_NAME).setOptional(true)); - kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, - R.string.name_given, FLAGS_PERSON_NAME)); - } else { - kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, - R.string.name_given, FLAGS_PERSON_NAME)); - kind.fieldList.add(new EditField(StructuredName.MIDDLE_NAME, - R.string.name_middle, FLAGS_PERSON_NAME).setOptional(true)); - kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, - R.string.name_family, FLAGS_PERSON_NAME)); - } - kind.fieldList.add(new EditField(StructuredName.SUFFIX, - R.string.name_suffix, FLAGS_PERSON_NAME).setOptional(true)); - - return kind; - } - - @Override - protected DataKind addDataKindPhoneticName(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME, - R.string.name_phonetic, -1, true, R.layout.phonetic_name_editor_view)); - kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup); - kind.actionBody = new SimpleInflater(Nickname.NAME); - - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_FAMILY_NAME, - R.string.name_phonetic_family, FLAGS_PHONETIC)); - kind.fieldList.add(new EditField(StructuredName.PHONETIC_GIVEN_NAME, - R.string.name_phonetic_given, FLAGS_PHONETIC)); - - return kind; - } - - @Override - protected DataKind addDataKindNickname(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindNickname(context); - - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Nickname.NAME, R.string.nicknameLabelsGroup, - FLAGS_PERSON_NAME)); - - return kind; - } - - @Override - protected DataKind addDataKindPhone(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindPhone(context); - - kind.typeColumn = Phone.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE).setSpecificMax(1)); - kind.typeList.add(buildPhoneType(Phone.TYPE_HOME).setSpecificMax(2)); - kind.typeList.add(buildPhoneType(Phone.TYPE_WORK).setSpecificMax(2)); - kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true) - .setSpecificMax(1)); - kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true) - .setSpecificMax(1)); - kind.typeList - .add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true).setSpecificMax(1)); - kind.typeList.add(buildPhoneType(Phone.TYPE_CAR).setSecondary(true).setSpecificMax(1)); - kind.typeList.add(buildPhoneType(Phone.TYPE_COMPANY_MAIN).setSecondary(true) - .setSpecificMax(1)); - kind.typeList.add(buildPhoneType(Phone.TYPE_MMS).setSecondary(true).setSpecificMax(1)); - kind.typeList - .add(buildPhoneType(Phone.TYPE_RADIO).setSecondary(true).setSpecificMax(1)); - kind.typeList.add(buildPhoneType(Phone.TYPE_ASSISTANT).setSecondary(true) - .setSpecificMax(1)); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE)); - - return kind; - } - - @Override - protected DataKind addDataKindEmail(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindEmail(context); - - kind.typeOverallMax = 3; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL)); - - return kind; - } - - @Override - protected DataKind addDataKindStructuredPostal(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindStructuredPostal(context); - - final boolean useJapaneseOrder = - Locale.JAPANESE.getLanguage().equals(Locale.getDefault().getLanguage()); - kind.typeColumn = StructuredPostal.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildPostalType(StructuredPostal.TYPE_WORK).setSpecificMax(1)); - kind.typeList.add(buildPostalType(StructuredPostal.TYPE_HOME).setSpecificMax(1)); - kind.typeList.add(buildPostalType(StructuredPostal.TYPE_OTHER).setSpecificMax(1)); - - kind.fieldList = Lists.newArrayList(); - if (useJapaneseOrder) { - kind.fieldList.add(new EditField(StructuredPostal.COUNTRY, - R.string.postal_country, FLAGS_POSTAL).setOptional(true)); - kind.fieldList.add(new EditField(StructuredPostal.POSTCODE, - R.string.postal_postcode, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.REGION, - R.string.postal_region, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.CITY, - R.string.postal_city,FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.STREET, - R.string.postal_street, FLAGS_POSTAL)); - } else { - kind.fieldList.add(new EditField(StructuredPostal.STREET, - R.string.postal_street, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.CITY, - R.string.postal_city,FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.REGION, - R.string.postal_region, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.POSTCODE, - R.string.postal_postcode, FLAGS_POSTAL)); - kind.fieldList.add(new EditField(StructuredPostal.COUNTRY, - R.string.postal_country, FLAGS_POSTAL).setOptional(true)); - } - - return kind; - } - - @Override - protected DataKind addDataKindIm(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindIm(context); - - // Types are not supported for IM. There can be 3 IMs, but OWA only shows only the first - kind.typeOverallMax = 3; - - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Im.TYPE, Im.TYPE_OTHER); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Im.DATA, R.string.imLabelsGroup, FLAGS_EMAIL)); - - return kind; - } - - @Override - protected DataKind addDataKindOrganization(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindOrganization(context); - - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Organization.COMPANY, R.string.ghostData_company, - FLAGS_GENERIC_NAME)); - kind.fieldList.add(new EditField(Organization.TITLE, R.string.ghostData_title, - FLAGS_GENERIC_NAME)); - - return kind; - } - - @Override - protected DataKind addDataKindPhoto(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindPhoto(context); - - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1)); - - return kind; - } - - @Override - protected DataKind addDataKindNote(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindNote(context); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Note.NOTE, R.string.label_notes, FLAGS_NOTE)); - - return kind; - } - - protected DataKind addDataKindEvent(Context context) throws DefinitionException { - DataKind kind = addKind( - new DataKind(Event.CONTENT_ITEM_TYPE, R.string.eventLabelsGroup, 150, true, - R.layout.event_field_editor_view)); - kind.actionHeader = new EventActionInflater(); - kind.actionBody = new SimpleInflater(Event.START_DATE); - - kind.typeOverallMax = 1; - - kind.typeColumn = Event.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildEventType(Event.TYPE_BIRTHDAY, false).setSpecificMax(1)); - - kind.dateFormatWithYear = DateUtils.DATE_AND_TIME_FORMAT; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Event.DATA, R.string.eventLabelsGroup, FLAGS_EVENT)); - - return kind; - } - - @Override - protected DataKind addDataKindWebsite(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindWebsite(context); - - kind.typeOverallMax = 1; - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Website.URL, R.string.websiteLabelsGroup, FLAGS_WEBSITE)); - - return kind; - } - - @Override - public boolean isGroupMembershipEditable() { - return true; - } - - @Override - public boolean areContactsWritable() { - return true; - } -} diff --git a/src/com/android/contacts/model/account/ExternalAccountType.java b/src/com/android/contacts/model/account/ExternalAccountType.java deleted file mode 100644 index 71dbebf6d..000000000 --- a/src/com/android/contacts/model/account/ExternalAccountType.java +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.contacts.model.account; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.ServiceInfo; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.provider.ContactsContract.CommonDataKinds.Photo; -import android.provider.ContactsContract.CommonDataKinds.StructuredName; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.util.Log; -import android.util.Xml; - -import com.android.contacts.model.dataitem.DataKind; -import com.google.common.annotations.VisibleForTesting; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * A general contacts account type descriptor. - */ -public class ExternalAccountType extends BaseAccountType { - private static final String TAG = "ExternalAccountType"; - - private static final String METADATA_CONTACTS = "android.provider.CONTACTS_STRUCTURE"; - - private static final String TAG_CONTACTS_SOURCE_LEGACY = "ContactsSource"; - private static final String TAG_CONTACTS_ACCOUNT_TYPE = "ContactsAccountType"; - private static final String TAG_CONTACTS_DATA_KIND = "ContactsDataKind"; - private static final String TAG_EDIT_SCHEMA = "EditSchema"; - - private static final String ATTR_EDIT_CONTACT_ACTIVITY = "editContactActivity"; - private static final String ATTR_CREATE_CONTACT_ACTIVITY = "createContactActivity"; - private static final String ATTR_INVITE_CONTACT_ACTIVITY = "inviteContactActivity"; - private static final String ATTR_INVITE_CONTACT_ACTION_LABEL = "inviteContactActionLabel"; - private static final String ATTR_VIEW_CONTACT_NOTIFY_SERVICE = "viewContactNotifyService"; - private static final String ATTR_VIEW_GROUP_ACTIVITY = "viewGroupActivity"; - private static final String ATTR_VIEW_GROUP_ACTION_LABEL = "viewGroupActionLabel"; - private static final String ATTR_VIEW_STREAM_ITEM_ACTIVITY = "viewStreamItemActivity"; - private static final String ATTR_VIEW_STREAM_ITEM_PHOTO_ACTIVITY = - "viewStreamItemPhotoActivity"; - private static final String ATTR_DATA_SET = "dataSet"; - private static final String ATTR_EXTENSION_PACKAGE_NAMES = "extensionPackageNames"; - - // The following attributes should only be set in non-sync-adapter account types. They allow - // for the account type and resource IDs to be specified without an associated authenticator. - private static final String ATTR_ACCOUNT_TYPE = "accountType"; - private static final String ATTR_ACCOUNT_LABEL = "accountTypeLabel"; - private static final String ATTR_ACCOUNT_ICON = "accountTypeIcon"; - - private final boolean mIsExtension; - - private String mEditContactActivityClassName; - private String mCreateContactActivityClassName; - private String mInviteContactActivity; - private String mInviteActionLabelAttribute; - private int mInviteActionLabelResId; - private String mViewContactNotifyService; - private String mViewGroupActivity; - private String mViewGroupLabelAttribute; - private int mViewGroupLabelResId; - private String mViewStreamItemActivity; - private String mViewStreamItemPhotoActivity; - private List<String> mExtensionPackageNames; - private String mAccountTypeLabelAttribute; - private String mAccountTypeIconAttribute; - private boolean mHasContactsMetadata; - private boolean mHasEditSchema; - - public ExternalAccountType(Context context, String resPackageName, boolean isExtension) { - this(context, resPackageName, isExtension, null); - } - - /** - * Constructor used for testing to initialize with any arbitrary XML. - * - * @param injectedMetadata If non-null, it'll be used to initialize the type. Only set by - * tests. If null, the metadata is loaded from the specified package. - */ - ExternalAccountType(Context context, String packageName, boolean isExtension, - XmlResourceParser injectedMetadata) { - this.mIsExtension = isExtension; - this.resourcePackageName = packageName; - this.syncAdapterPackageName = packageName; - - final PackageManager pm = context.getPackageManager(); - final XmlResourceParser parser; - if (injectedMetadata == null) { - try { - parser = loadContactsXml(context, packageName); - } catch (NameNotFoundException e1) { - // If the package name is not found, we can't initialize this account type. - return; - } - } else { - parser = injectedMetadata; - } - boolean needLineNumberInErrorLog = true; - try { - if (parser != null) { - inflate(context, parser); - } - - // Done parsing; line number no longer needed in error log. - needLineNumberInErrorLog = false; - if (mHasEditSchema) { - checkKindExists(StructuredName.CONTENT_ITEM_TYPE); - checkKindExists(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME); - checkKindExists(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME); - checkKindExists(Photo.CONTENT_ITEM_TYPE); - } else { - // Bring in name and photo from fallback source, which are non-optional - addDataKindStructuredName(context); - addDataKindDisplayName(context); - addDataKindPhoneticName(context); - addDataKindPhoto(context); - } - } catch (DefinitionException e) { - final StringBuilder error = new StringBuilder(); - error.append("Problem reading XML"); - if (needLineNumberInErrorLog && (parser != null)) { - error.append(" in line "); - error.append(parser.getLineNumber()); - } - error.append(" for external package "); - error.append(packageName); - - Log.e(TAG, error.toString(), e); - return; - } finally { - if (parser != null) { - parser.close(); - } - } - - mExtensionPackageNames = new ArrayList<String>(); - mInviteActionLabelResId = resolveExternalResId(context, mInviteActionLabelAttribute, - syncAdapterPackageName, ATTR_INVITE_CONTACT_ACTION_LABEL); - mViewGroupLabelResId = resolveExternalResId(context, mViewGroupLabelAttribute, - syncAdapterPackageName, ATTR_VIEW_GROUP_ACTION_LABEL); - titleRes = resolveExternalResId(context, mAccountTypeLabelAttribute, - syncAdapterPackageName, ATTR_ACCOUNT_LABEL); - iconRes = resolveExternalResId(context, mAccountTypeIconAttribute, - syncAdapterPackageName, ATTR_ACCOUNT_ICON); - - // If we reach this point, the account type has been successfully initialized. - mIsInitialized = true; - } - - /** - * Returns the CONTACTS_STRUCTURE metadata (aka "contacts.xml") in the given apk package. - * - * Unfortunately, there's no public way to determine which service defines a sync service for - * which account type, so this method looks through all services in the package, and just - * returns the first CONTACTS_STRUCTURE metadata defined in any of them. - * - * Returns {@code null} if the package has no CONTACTS_STRUCTURE metadata. In this case - * the account type *will* be initialized with minimal configuration. - * - * On the other hand, if the package is not found, it throws a {@link NameNotFoundException}, - * in which case the account type will *not* be initialized. - */ - private XmlResourceParser loadContactsXml(Context context, String resPackageName) - throws NameNotFoundException { - final PackageManager pm = context.getPackageManager(); - PackageInfo packageInfo = pm.getPackageInfo(resPackageName, - PackageManager.GET_SERVICES|PackageManager.GET_META_DATA); - for (ServiceInfo serviceInfo : packageInfo.services) { - final XmlResourceParser parser = serviceInfo.loadXmlMetaData(pm, - METADATA_CONTACTS); - if (parser != null) { - return parser; - } - } - // Package was found, but that doesn't contain the CONTACTS_STRUCTURE metadata. - return null; - } - - private void checkKindExists(String mimeType) throws DefinitionException { - if (getKindForMimetype(mimeType) == null) { - throw new DefinitionException(mimeType + " must be supported"); - } - } - - @Override - public boolean isEmbedded() { - return false; - } - - @Override - public boolean isExtension() { - return mIsExtension; - } - - @Override - public boolean areContactsWritable() { - return mHasEditSchema; - } - - /** - * Whether this account type has the android.provider.CONTACTS_STRUCTURE metadata xml. - */ - public boolean hasContactsMetadata() { - return mHasContactsMetadata; - } - - @Override - public String getEditContactActivityClassName() { - return mEditContactActivityClassName; - } - - @Override - public String getCreateContactActivityClassName() { - return mCreateContactActivityClassName; - } - - @Override - public String getInviteContactActivityClassName() { - return mInviteContactActivity; - } - - @Override - protected int getInviteContactActionResId() { - return mInviteActionLabelResId; - } - - @Override - public String getViewContactNotifyServiceClassName() { - return mViewContactNotifyService; - } - - @Override - public String getViewGroupActivity() { - return mViewGroupActivity; - } - - @Override - protected int getViewGroupLabelResId() { - return mViewGroupLabelResId; - } - - @Override - public String getViewStreamItemActivity() { - return mViewStreamItemActivity; - } - - @Override - public String getViewStreamItemPhotoActivity() { - return mViewStreamItemPhotoActivity; - } - - @Override - public List<String> getExtensionPackageNames() { - return mExtensionPackageNames; - } - - /** - * Inflate this {@link AccountType} from the given parser. This may only - * load details matching the publicly-defined schema. - */ - protected void inflate(Context context, XmlPullParser parser) throws DefinitionException { - final AttributeSet attrs = Xml.asAttributeSet(parser); - - try { - int type; - while ((type = parser.next()) != XmlPullParser.START_TAG - && type != XmlPullParser.END_DOCUMENT) { - // Drain comments and whitespace - } - - if (type != XmlPullParser.START_TAG) { - throw new IllegalStateException("No start tag found"); - } - - String rootTag = parser.getName(); - if (!TAG_CONTACTS_ACCOUNT_TYPE.equals(rootTag) && - !TAG_CONTACTS_SOURCE_LEGACY.equals(rootTag)) { - throw new IllegalStateException("Top level element must be " - + TAG_CONTACTS_ACCOUNT_TYPE + ", not " + rootTag); - } - - mHasContactsMetadata = true; - - int attributeCount = parser.getAttributeCount(); - for (int i = 0; i < attributeCount; i++) { - String attr = parser.getAttributeName(i); - String value = parser.getAttributeValue(i); - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, attr + "=" + value); - } - if (ATTR_EDIT_CONTACT_ACTIVITY.equals(attr)) { - mEditContactActivityClassName = value; - } else if (ATTR_CREATE_CONTACT_ACTIVITY.equals(attr)) { - mCreateContactActivityClassName = value; - } else if (ATTR_INVITE_CONTACT_ACTIVITY.equals(attr)) { - mInviteContactActivity = value; - } else if (ATTR_INVITE_CONTACT_ACTION_LABEL.equals(attr)) { - mInviteActionLabelAttribute = value; - } else if (ATTR_VIEW_CONTACT_NOTIFY_SERVICE.equals(attr)) { - mViewContactNotifyService = value; - } else if (ATTR_VIEW_GROUP_ACTIVITY.equals(attr)) { - mViewGroupActivity = value; - } else if (ATTR_VIEW_GROUP_ACTION_LABEL.equals(attr)) { - mViewGroupLabelAttribute = value; - } else if (ATTR_VIEW_STREAM_ITEM_ACTIVITY.equals(attr)) { - mViewStreamItemActivity = value; - } else if (ATTR_VIEW_STREAM_ITEM_PHOTO_ACTIVITY.equals(attr)) { - mViewStreamItemPhotoActivity = value; - } else if (ATTR_DATA_SET.equals(attr)) { - dataSet = value; - } else if (ATTR_EXTENSION_PACKAGE_NAMES.equals(attr)) { - mExtensionPackageNames.add(value); - } else if (ATTR_ACCOUNT_TYPE.equals(attr)) { - accountType = value; - } else if (ATTR_ACCOUNT_LABEL.equals(attr)) { - mAccountTypeLabelAttribute = value; - } else if (ATTR_ACCOUNT_ICON.equals(attr)) { - mAccountTypeIconAttribute = value; - } else { - Log.e(TAG, "Unsupported attribute " + attr); - } - } - - // Parse all children kinds - final int startDepth = parser.getDepth(); - while (((type = parser.next()) != XmlPullParser.END_TAG - || parser.getDepth() > startDepth) - && type != XmlPullParser.END_DOCUMENT) { - - if (type != XmlPullParser.START_TAG || parser.getDepth() != startDepth + 1) { - continue; // Not a direct child tag - } - - String tag = parser.getName(); - if (TAG_EDIT_SCHEMA.equals(tag)) { - mHasEditSchema = true; - parseEditSchema(context, parser, attrs); - } else if (TAG_CONTACTS_DATA_KIND.equals(tag)) { - final TypedArray a = context.obtainStyledAttributes(attrs, - android.R.styleable.ContactsDataKind); - final DataKind kind = new DataKind(); - - kind.mimeType = a - .getString(com.android.internal.R.styleable.ContactsDataKind_mimeType); - - final String summaryColumn = a.getString( - com.android.internal.R.styleable.ContactsDataKind_summaryColumn); - if (summaryColumn != null) { - // Inflate a specific column as summary when requested - kind.actionHeader = new SimpleInflater(summaryColumn); - } - - final String detailColumn = a.getString( - com.android.internal.R.styleable.ContactsDataKind_detailColumn); - final boolean detailSocialSummary = a.getBoolean( - com.android.internal.R.styleable.ContactsDataKind_detailSocialSummary, - false); - - if (detailSocialSummary) { - // Inflate social summary when requested - kind.actionBodySocial = true; - } - - if (detailColumn != null) { - // Inflate specific column as summary - kind.actionBody = new SimpleInflater(detailColumn); - } - - a.recycle(); - - addKind(kind); - } - } - } catch (XmlPullParserException e) { - throw new DefinitionException("Problem reading XML", e); - } catch (IOException e) { - throw new DefinitionException("Problem reading XML", e); - } - } - - /** - * Takes a string in the "@xxx/yyy" format and return the resource ID for the resource in - * the resource package. - * - * If the argument is in the invalid format or isn't a resource name, it returns -1. - * - * @param context context - * @param resourceName Resource name in the "@xxx/yyy" format, e.g. "@string/invite_lavbel" - * @param packageName name of the package containing the resource. - * @param xmlAttributeName attribute name which the resource came from. Used for logging. - */ - @VisibleForTesting - static int resolveExternalResId(Context context, String resourceName, - String packageName, String xmlAttributeName) { - if (TextUtils.isEmpty(resourceName)) { - return -1; // Empty text is okay. - } - if (resourceName.charAt(0) != '@') { - Log.e(TAG, xmlAttributeName + " must be a resource name beginnig with '@'"); - return -1; - } - final String name = resourceName.substring(1); - final Resources res; - try { - res = context.getPackageManager().getResourcesForApplication(packageName); - } catch (NameNotFoundException e) { - Log.e(TAG, "Unable to load package " + packageName); - return -1; - } - final int resId = res.getIdentifier(name, null, packageName); - if (resId == 0) { - Log.e(TAG, "Unable to load " + resourceName + " from package " + packageName); - return -1; - } - return resId; - } -} diff --git a/src/com/android/contacts/model/account/FallbackAccountType.java b/src/com/android/contacts/model/account/FallbackAccountType.java deleted file mode 100644 index dae288da8..000000000 --- a/src/com/android/contacts/model/account/FallbackAccountType.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.contacts.model.account; - -import android.content.Context; -import android.util.Log; - -import com.android.contacts.R; -import com.android.contacts.model.dataitem.DataKind; -import com.android.contacts.test.NeededForTesting; - -public class FallbackAccountType extends BaseAccountType { - private static final String TAG = "FallbackAccountType"; - - private FallbackAccountType(Context context, String resPackageName) { - this.accountType = null; - this.dataSet = null; - this.titleRes = R.string.account_phone; - this.iconRes = R.mipmap.ic_launcher_contacts; - - // Note those are only set for unit tests. - this.resourcePackageName = resPackageName; - this.syncAdapterPackageName = resPackageName; - - try { - addDataKindStructuredName(context); - addDataKindDisplayName(context); - addDataKindPhoneticName(context); - addDataKindNickname(context); - addDataKindPhone(context); - addDataKindEmail(context); - addDataKindStructuredPostal(context); - addDataKindIm(context); - addDataKindOrganization(context); - addDataKindPhoto(context); - addDataKindNote(context); - addDataKindWebsite(context); - addDataKindSipAddress(context); - - mIsInitialized = true; - } catch (DefinitionException e) { - Log.e(TAG, "Problem building account type", e); - } - } - - public FallbackAccountType(Context context) { - this(context, null); - } - - /** - * Used to compare with an {@link ExternalAccountType} built from a test contacts.xml. - * In order to build {@link DataKind}s with the same resource package name, - * {@code resPackageName} is injectable. - */ - @NeededForTesting - static AccountType createWithPackageNameForTest(Context context, String resPackageName) { - return new FallbackAccountType(context, resPackageName); - } - - @Override - public boolean areContactsWritable() { - return true; - } -} diff --git a/src/com/android/contacts/model/account/GoogleAccountType.java b/src/com/android/contacts/model/account/GoogleAccountType.java deleted file mode 100644 index 192c3d0e5..000000000 --- a/src/com/android/contacts/model/account/GoogleAccountType.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.contacts.model.account; - -import android.content.ContentValues; -import android.content.Context; -import android.provider.ContactsContract.CommonDataKinds.Email; -import android.provider.ContactsContract.CommonDataKinds.Event; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.CommonDataKinds.Relation; -import android.util.Log; - -import com.android.contacts.R; -import com.android.contacts.model.dataitem.DataKind; -import com.android.contacts.util.DateUtils; -import com.google.common.collect.Lists; - -import java.util.List; - -public class GoogleAccountType extends BaseAccountType { - private static final String TAG = "GoogleAccountType"; - - public static final String ACCOUNT_TYPE = "com.google"; - - private static final List<String> mExtensionPackages = - Lists.newArrayList("com.google.android.apps.plus"); - - public GoogleAccountType(Context context, String authenticatorPackageName) { - this.accountType = ACCOUNT_TYPE; - this.resourcePackageName = null; - this.syncAdapterPackageName = authenticatorPackageName; - - try { - addDataKindStructuredName(context); - addDataKindDisplayName(context); - addDataKindPhoneticName(context); - addDataKindNickname(context); - addDataKindPhone(context); - addDataKindEmail(context); - addDataKindStructuredPostal(context); - addDataKindIm(context); - addDataKindOrganization(context); - addDataKindPhoto(context); - addDataKindNote(context); - addDataKindWebsite(context); - addDataKindSipAddress(context); - addDataKindGroupMembership(context); - addDataKindRelation(context); - addDataKindEvent(context); - - mIsInitialized = true; - } catch (DefinitionException e) { - Log.e(TAG, "Problem building account type", e); - } - } - - @Override - public List<String> getExtensionPackageNames() { - return mExtensionPackages; - } - - @Override - protected DataKind addDataKindPhone(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindPhone(context); - - kind.typeColumn = Phone.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE)); - kind.typeList.add(buildPhoneType(Phone.TYPE_WORK)); - kind.typeList.add(buildPhoneType(Phone.TYPE_HOME)); - kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN)); - kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true)); - kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER)); - kind.typeList.add(buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true) - .setCustomColumn(Phone.LABEL)); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE)); - - return kind; - } - - @Override - protected DataKind addDataKindEmail(Context context) throws DefinitionException { - final DataKind kind = super.addDataKindEmail(context); - - kind.typeColumn = Email.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildEmailType(Email.TYPE_HOME)); - kind.typeList.add(buildEmailType(Email.TYPE_WORK)); - kind.typeList.add(buildEmailType(Email.TYPE_OTHER)); - kind.typeList.add(buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn( - Email.LABEL)); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL)); - - return kind; - } - - private DataKind addDataKindRelation(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Relation.CONTENT_ITEM_TYPE, - R.string.relationLabelsGroup, 160, true, R.layout.text_fields_editor_view)); - kind.actionHeader = new RelationActionInflater(); - kind.actionBody = new SimpleInflater(Relation.NAME); - - kind.typeColumn = Relation.TYPE; - kind.typeList = Lists.newArrayList(); - kind.typeList.add(buildRelationType(Relation.TYPE_ASSISTANT)); - kind.typeList.add(buildRelationType(Relation.TYPE_BROTHER)); - kind.typeList.add(buildRelationType(Relation.TYPE_CHILD)); - kind.typeList.add(buildRelationType(Relation.TYPE_DOMESTIC_PARTNER)); - kind.typeList.add(buildRelationType(Relation.TYPE_FATHER)); - kind.typeList.add(buildRelationType(Relation.TYPE_FRIEND)); - kind.typeList.add(buildRelationType(Relation.TYPE_MANAGER)); - kind.typeList.add(buildRelationType(Relation.TYPE_MOTHER)); - kind.typeList.add(buildRelationType(Relation.TYPE_PARENT)); - kind.typeList.add(buildRelationType(Relation.TYPE_PARTNER)); - kind.typeList.add(buildRelationType(Relation.TYPE_REFERRED_BY)); - kind.typeList.add(buildRelationType(Relation.TYPE_RELATIVE)); - kind.typeList.add(buildRelationType(Relation.TYPE_SISTER)); - kind.typeList.add(buildRelationType(Relation.TYPE_SPOUSE)); - kind.typeList.add(buildRelationType(Relation.TYPE_CUSTOM).setSecondary(true) - .setCustomColumn(Relation.LABEL)); - - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Relation.TYPE, Relation.TYPE_SPOUSE); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Relation.DATA, R.string.relationLabelsGroup, - FLAGS_RELATION)); - - return kind; - } - - private DataKind addDataKindEvent(Context context) throws DefinitionException { - DataKind kind = addKind(new DataKind(Event.CONTENT_ITEM_TYPE, - R.string.eventLabelsGroup, 150, true, R.layout.event_field_editor_view)); - kind.actionHeader = new EventActionInflater(); - kind.actionBody = new SimpleInflater(Event.START_DATE); - - kind.typeColumn = Event.TYPE; - kind.typeList = Lists.newArrayList(); - kind.dateFormatWithoutYear = DateUtils.NO_YEAR_DATE_FORMAT; - kind.dateFormatWithYear = DateUtils.FULL_DATE_FORMAT; - kind.typeList.add(buildEventType(Event.TYPE_BIRTHDAY, true).setSpecificMax(1)); - kind.typeList.add(buildEventType(Event.TYPE_ANNIVERSARY, false)); - kind.typeList.add(buildEventType(Event.TYPE_OTHER, false)); - kind.typeList.add(buildEventType(Event.TYPE_CUSTOM, false).setSecondary(true) - .setCustomColumn(Event.LABEL)); - - kind.defaultValues = new ContentValues(); - kind.defaultValues.put(Event.TYPE, Event.TYPE_BIRTHDAY); - - kind.fieldList = Lists.newArrayList(); - kind.fieldList.add(new EditField(Event.DATA, R.string.eventLabelsGroup, FLAGS_EVENT)); - - return kind; - } - - @Override - public boolean isGroupMembershipEditable() { - return true; - } - - @Override - public boolean areContactsWritable() { - return true; - } - - @Override - public String getViewContactNotifyServiceClassName() { - return "com.google.android.syncadapters.contacts." + - "SyncHighResPhotoIntentService"; - } - - @Override - public String getViewContactNotifyServicePackageName() { - return "com.google.android.syncadapters.contacts"; - } -} |