1ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/* 2ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Copyright (C) 2009 The Android Open Source Project 3ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 4ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Licensed under the Apache License, Version 2.0 (the "License"); 5ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * you may not use this file except in compliance with the License. 6ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * You may obtain a copy of the License at 7ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 8ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * http://www.apache.org/licenses/LICENSE-2.0 9ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 10ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Unless required by applicable law or agreed to in writing, software 11ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * distributed under the License is distributed on an "AS IS" BASIS, 12ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * See the License for the specific language governing permissions and 14ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * limitations under the License. 15ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 16ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 17ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpackage com.android.contacts.common; 18ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 19ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport android.content.Context; 20ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.Iterator; 21ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianimport java.util.List; 22ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 23ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian/** 24ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Class used for collapsing data items into groups of similar items. The data items that should be 25ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * collapsible should implement the Collapsible interface. The class also contains a utility 26ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * function that takes an ArrayList of items and returns a list of the same items collapsed into 27ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * groups. 28ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 29ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanianpublic final class Collapser { 30ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 31ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /* 32ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * The Collapser uses an n^2 algorithm so we don't want it to run on 33ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * lists beyond a certain size. This specifies the maximum size to collapse. 34ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 35ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private static final int MAX_LISTSIZE_TO_COLLAPSE = 20; 36ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 37ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /* 38ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * This utility class cannot be instantiated. 39ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 40ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian private Collapser() {} 41ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 42ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /** 43ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Collapses a list of Collapsible items into a list of collapsed items. Items are collapsed if 44ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * {@link Collapsible#shouldCollapseWith(Object)} returns true, and are collapsed through the 45ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * {@Link Collapsible#collapseWith(Object)} function implemented by the data item. 46ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * 47ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * @param list List of Objects of type <T extends Collapsible<T>> to be collapsed. 48ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 49ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public static <T extends Collapsible<T>> void collapseList(List<T> list, Context context) { 50ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 51ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian int listSize = list.size(); 52ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // The algorithm below is n^2 so don't run on long lists 53ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (listSize > MAX_LISTSIZE_TO_COLLAPSE) { 54ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian return; 55ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 56ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 57ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (int i = 0; i < listSize; i++) { 58ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian T iItem = list.get(i); 59ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (iItem != null) { 60ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian for (int j = i + 1; j < listSize; j++) { 61ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian T jItem = list.get(j); 62ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (jItem != null) { 63ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (iItem.shouldCollapseWith(jItem, context)) { 64ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian iItem.collapseWith(jItem); 65ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian list.set(j, null); 66ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } else if (jItem.shouldCollapseWith(iItem, context)) { 67ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian jItem.collapseWith(iItem); 68ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian list.set(i, null); 69ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian break; 70ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 71ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 72ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 73ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 74ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 75ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 76ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian // Remove the null items 77ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian Iterator<T> itr = list.iterator(); 78ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian while (itr.hasNext()) { 79ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian if (itr.next() == null) { 80ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian itr.remove(); 81ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 82ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 83ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 84ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 85ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian /* 86ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * Interface implemented by data types that can be collapsed into groups of similar data. This 87ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian * can be used for example to collapse similar contact data items into a single item. 88ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian */ 89ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian public interface Collapsible<T> { 90ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 91ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian void collapseWith(T t); 92ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian 93ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian boolean shouldCollapseWith(T t, Context context); 94ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian } 95ccca31529c07970e89419fb85a9e8153a5396838Eric Erfanian} 96