1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.data; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.net.Uri; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 222b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.app.GalleryApp; 232b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashSet; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 27705dc819661cb8c8e839a04577b0641bd6caad53John Reckpublic class ClusterAlbumSet extends MediaSet implements ContentListener { 287817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @SuppressWarnings("unused") 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "ClusterAlbumSet"; 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private GalleryApp mApplication; 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private MediaSet mBaseSet; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mKind; 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private ArrayList<ClusterAlbum> mAlbums = new ArrayList<ClusterAlbum>(); 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private boolean mFirstReloadDone; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public ClusterAlbumSet(Path path, GalleryApp application, 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin MediaSet baseSet, int kind) { 38705dc819661cb8c8e839a04577b0641bd6caad53John Reck super(path, INVALID_DATA_VERSION); 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mApplication = application; 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mBaseSet = baseSet; 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mKind = kind; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin baseSet.addContentListener(this); 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public MediaSet getSubMediaSet(int index) { 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mAlbums.get(index); 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public int getSubMediaSetCount() { 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mAlbums.size(); 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public String getName() { 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mBaseSet.getName(); 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 61705dc819661cb8c8e839a04577b0641bd6caad53John Reck public long reload() { 62705dc819661cb8c8e839a04577b0641bd6caad53John Reck if (mBaseSet.reload() > mDataVersion) { 63705dc819661cb8c8e839a04577b0641bd6caad53John Reck if (mFirstReloadDone) { 64705dc819661cb8c8e839a04577b0641bd6caad53John Reck updateClustersContents(); 65705dc819661cb8c8e839a04577b0641bd6caad53John Reck } else { 66705dc819661cb8c8e839a04577b0641bd6caad53John Reck updateClusters(); 67705dc819661cb8c8e839a04577b0641bd6caad53John Reck mFirstReloadDone = true; 68705dc819661cb8c8e839a04577b0641bd6caad53John Reck } 69705dc819661cb8c8e839a04577b0641bd6caad53John Reck mDataVersion = nextVersionNumber(); 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 71705dc819661cb8c8e839a04577b0641bd6caad53John Reck return mDataVersion; 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 747817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onContentDirty() { 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin notifyContentChanged(); 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateClusters() { 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mAlbums.clear(); 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Clustering clustering; 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Context context = mApplication.getAndroidContext(); 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin switch (mKind) { 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case ClusterSource.CLUSTER_ALBUMSET_TIME: 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin clustering = new TimeClustering(context); 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin break; 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case ClusterSource.CLUSTER_ALBUMSET_LOCATION: 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin clustering = new LocationClustering(context); 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin break; 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case ClusterSource.CLUSTER_ALBUMSET_TAG: 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin clustering = new TagClustering(context); 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin break; 93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case ClusterSource.CLUSTER_ALBUMSET_FACE: 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin clustering = new FaceClustering(context); 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin break; 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin default: /* CLUSTER_ALBUMSET_SIZE */ 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin clustering = new SizeClustering(context); 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin break; 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin clustering.run(mBaseSet); 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int n = clustering.getNumberOfClusters(); 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin DataManager dataManager = mApplication.getDataManager(); 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = 0; i < n; i++) { 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path childPath; 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin String childName = clustering.getClusterName(i); 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mKind == ClusterSource.CLUSTER_ALBUMSET_TAG) { 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin childPath = mPath.getChild(Uri.encode(childName)); 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else if (mKind == ClusterSource.CLUSTER_ALBUMSET_SIZE) { 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long minSize = ((SizeClustering) clustering).getMinSize(i); 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin childPath = mPath.getChild(minSize); 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } else { 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin childPath = mPath.getChild(i); 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 115676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin 116676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin ClusterAlbum album; 117676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin synchronized (DataManager.LOCK) { 118676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin album = (ClusterAlbum) dataManager.peekMediaObject(childPath); 119676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin if (album == null) { 120676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin album = new ClusterAlbum(childPath, dataManager, this); 121676d4762496eddae66930c6f8b0bae22a22b3ef6Owen Lin } 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin album.setMediaItems(clustering.getCluster(i)); 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin album.setName(childName); 12504a9a44fb85263c4590ca68f92adff6f9da360e9Ray Chen album.setCoverMediaItem(clustering.getClusterCover(i)); 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mAlbums.add(album); 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void updateClustersContents() { 131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin final HashSet<Path> existing = new HashSet<Path>(); 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mBaseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { 1337817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void consume(int index, MediaItem item) { 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin existing.add(item.getPath()); 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin }); 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int n = mAlbums.size(); 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The loop goes backwards because we may remove empty albums from 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // mAlbums. 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int i = n - 1; i >= 0; i--) { 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<Path> oldPaths = mAlbums.get(i).getMediaItems(); 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin ArrayList<Path> newPaths = new ArrayList<Path>(); 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int m = oldPaths.size(); 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin for (int j = 0; j < m; j++) { 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Path p = oldPaths.get(j); 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (existing.contains(p)) { 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin newPaths.add(p); 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mAlbums.get(i).setMediaItems(newPaths); 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (newPaths.isEmpty()) { 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mAlbums.remove(i); 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 160