blob: cb82806913e14f5b14f0a2c518cbf817b28fee5a [file] [log] [blame]
/*
* Copyright (C) 2015 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.editor;
import com.android.contacts.common.model.RawContactDelta;
import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.model.dataitem.DataKind;
import com.android.contacts.common.model.RawContactModifier;
import android.util.Log;
import android.util.Pair;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Container for multiple {@link KindSectionData} objects. Provides convenience methods for
* interrogating the collection for a certain KindSectionData item (e.g. the first writable, or
* "primary", one. Also enforces that only items with the same DataKind/mime-type are added.
*/
public class KindSectionDataList extends ArrayList<KindSectionData> {
private static final String TAG = CompactRawContactsEditorView.TAG;
/**
* Returns the mime type for all DataKinds in this List.
*/
public String getMimeType() {
if (isEmpty()) return null;
return get(0).getDataKind().mimeType;
}
/**
* Returns the DataKind for all entries in this List.
*/
public DataKind getDataKind() {
return isEmpty() ? null : get(0).getDataKind();
}
/**
* Returns the primary KindSectionData and ValuesDelta that should be written for this List.
*/
public Pair<KindSectionData,ValuesDelta> getEntryToWrite(long id,
AccountWithDataSet primaryAccount, boolean isUserProfile) {
final String mimeType = getMimeType();
if (mimeType == null) return null;
if (!isUserProfile) {
if (id > 0) {
// Look for a match for the ID that was passed in
for (KindSectionData kindSectionData : this) {
if (kindSectionData.getAccountType().areContactsWritable()) {
final ValuesDelta valuesDelta = kindSectionData.getValuesDeltaById(id);
if (valuesDelta != null) {
vlog(mimeType + ": matched kind section data to write by ID");
return new Pair<>(kindSectionData, valuesDelta);
}
}
}
}
// Look for a super primary entry
for (KindSectionData kindSectionData : this) {
if (kindSectionData.getAccountType().areContactsWritable()) {
final ValuesDelta valuesDelta = kindSectionData.getSuperPrimaryValuesDelta();
if (valuesDelta != null) {
vlog(mimeType + ": matched kind section data to write by super primary");
return new Pair<>(kindSectionData, valuesDelta);
}
}
}
// Use the first writable contact that matches the primary account
if (primaryAccount != null) {
for (KindSectionData kindSectionData : this) {
if (kindSectionData.getAccountType().areContactsWritable()) {
if (matchesAccount(primaryAccount, kindSectionData.getRawContactDelta())
&& !kindSectionData.getValuesDeltas().isEmpty()) {
vlog(mimeType + ": matched kind section data to write by primary " +
"account");
return new Pair<>(kindSectionData,
kindSectionData.getValuesDeltas().get(0));
}
}
}
}
}
// Just return the first writable entry.
for (KindSectionData kindSectionData : this) {
if (kindSectionData.getAccountType().areContactsWritable()) {
// Create an entry if necessary
RawContactModifier.ensureKindExists(kindSectionData.getRawContactDelta(),
kindSectionData.getAccountType(), mimeType);
if (!kindSectionData.getValuesDeltas().isEmpty()) {
vlog(mimeType + ": falling back to first kind section data to write");
return new Pair<>(kindSectionData, kindSectionData.getValuesDeltas().get(0));
}
}
}
wlog(mimeType+ ": no writable kind section data found");
return null;
}
/** Whether the given RawContactDelta belong to the given account. */
private static boolean matchesAccount(AccountWithDataSet accountWithDataSet,
RawContactDelta rawContactDelta) {
return Objects.equals(accountWithDataSet.name, rawContactDelta.getAccountName())
&& Objects.equals(accountWithDataSet.type, rawContactDelta.getAccountType())
&& Objects.equals(accountWithDataSet.dataSet, rawContactDelta.getDataSet());
}
/**
* Returns the KindSectionData and ValuesDelta that should be displayed to the user.
*/
public Pair<KindSectionData,ValuesDelta> getEntryToDisplay(long id) {
final String mimeType = getMimeType();
if (mimeType == null) return null;
if (id > 0) {
// Look for a match for the ID that was passed in
for (KindSectionData kindSectionData : this) {
final ValuesDelta valuesDelta = kindSectionData.getValuesDeltaById(id);
if (valuesDelta != null) {
vlog(mimeType + ": matched kind section data to display by ID");
return new Pair<>(kindSectionData, valuesDelta);
}
}
}
// Look for a super primary entry
for (KindSectionData kindSectionData : this) {
final ValuesDelta valuesDelta = kindSectionData.getSuperPrimaryValuesDelta();
if (valuesDelta != null) {
vlog(mimeType + ": matched kind section data to display by super primary");
return new Pair<>(kindSectionData, valuesDelta);
}
}
// Fall back to the first non-empty value
for (KindSectionData kindSectionData : this) {
final ValuesDelta valuesDelta = kindSectionData.getFirstNonEmptyValuesDelta();
if (valuesDelta != null) {
vlog(mimeType + ": using first non empty value to display");
return new Pair<>(kindSectionData, valuesDelta);
}
}
for (KindSectionData kindSectionData : this) {
final List<ValuesDelta> valuesDeltaList = kindSectionData.getValuesDeltas();
if (!valuesDeltaList.isEmpty()) {
vlog(mimeType + ": falling back to first empty entry to display");
final ValuesDelta valuesDelta = valuesDeltaList.get(0);
return new Pair<>(kindSectionData, valuesDelta);
}
}
wlog(mimeType + ": no kind section data found to display");
return null;
}
@Override
public boolean add(KindSectionData kindSectionData) {
if (kindSectionData == null) throw new NullPointerException();
// Enforce that only entries of the same type are added to this list
final String listMimeType = getMimeType();
if (listMimeType != null) {
final String newEntryMimeType = kindSectionData.getDataKind().mimeType;
if (!listMimeType.equals(newEntryMimeType)) {
throw new IllegalArgumentException(
"Can't add " + newEntryMimeType + " to list with type " + listMimeType);
}
}
return super.add(kindSectionData);
}
private static void wlog(String message) {
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, message);
}
}
private static void vlog(String message) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, message);
}
}
}