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