ClusterAlbumSet.java revision f9a0a4306d589b4a4e20554fed512a603426bfa1
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 com.android.gallery3d.app.GalleryApp;
20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context;
22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.net.Uri;
23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.ArrayList;
25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashSet;
26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class ClusterAlbumSet extends MediaSet implements ContentListener {
28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "ClusterAlbumSet";
29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private GalleryApp mApplication;
30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private MediaSet mBaseSet;
31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private int mKind;
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private ArrayList<ClusterAlbum> mAlbums = new ArrayList<ClusterAlbum>();
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mFirstReloadDone;
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public ClusterAlbumSet(Path path, GalleryApp application,
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            MediaSet baseSet, int kind) {
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super(path, INVALID_DATA_VERSION);
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mApplication = application;
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mBaseSet = baseSet;
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mKind = kind;
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        baseSet.addContentListener(this);
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public MediaSet getSubMediaSet(int index) {
46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mAlbums.get(index);
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public int getSubMediaSetCount() {
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mAlbums.size();
52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public String getName() {
56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mBaseSet.getName();
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public long reload() {
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mBaseSet.reload() > mDataVersion) {
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mFirstReloadDone) {
63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                updateClustersContents();
64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else {
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                updateClusters();
66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mFirstReloadDone = true;
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mDataVersion = nextVersionNumber();
69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return mDataVersion;
71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onContentDirty() {
74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        notifyContentChanged();
75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void updateClusters() {
78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mAlbums.clear();
79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Clustering clustering;
80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Context context = mApplication.getAndroidContext();
81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        switch (mKind) {
82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case ClusterSource.CLUSTER_ALBUMSET_TIME:
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                clustering = new TimeClustering(context);
84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                break;
85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case ClusterSource.CLUSTER_ALBUMSET_LOCATION:
86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                clustering = new LocationClustering(context);
87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                break;
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case ClusterSource.CLUSTER_ALBUMSET_TAG:
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                clustering = new TagClustering(context);
90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                break;
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case ClusterSource.CLUSTER_ALBUMSET_FACE:
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                clustering = new FaceClustering(context);
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                break;
94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            default: /* CLUSTER_ALBUMSET_SIZE */
95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                clustering = new SizeClustering(context);
96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                break;
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        clustering.run(mBaseSet);
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int n = clustering.getNumberOfClusters();
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        DataManager dataManager = mApplication.getDataManager();
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = 0; i < n; i++) {
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            Path childPath;
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            String childName = clustering.getClusterName(i);
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mKind == ClusterSource.CLUSTER_ALBUMSET_TAG) {
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                childPath = mPath.getChild(Uri.encode(childName));
107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else if (mKind == ClusterSource.CLUSTER_ALBUMSET_SIZE) {
108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                long minSize = ((SizeClustering) clustering).getMinSize(i);
109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                childPath = mPath.getChild(minSize);
110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else {
111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                childPath = mPath.getChild(i);
112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            ClusterAlbum album = (ClusterAlbum) dataManager.peekMediaObject(
114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        childPath);
115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (album == null) {
116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                album = new ClusterAlbum(childPath, dataManager, this);
117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            album.setMediaItems(clustering.getCluster(i));
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            album.setName(childName);
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mAlbums.add(album);
121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void updateClustersContents() {
125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        final HashSet<Path> existing = new HashSet<Path>();
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mBaseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            public void consume(int index, MediaItem item) {
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                existing.add(item.getPath());
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
130f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        });
131f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int n = mAlbums.size();
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // The loop goes backwards because we may remove empty albums from
135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        // mAlbums.
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        for (int i = n - 1; i >= 0; i--) {
137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            ArrayList<Path> oldPaths = mAlbums.get(i).getMediaItems();
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            ArrayList<Path> newPaths = new ArrayList<Path>();
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int m = oldPaths.size();
140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            for (int j = 0; j < m; j++) {
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                Path p = oldPaths.get(j);
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                if (existing.contains(p)) {
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    newPaths.add(p);
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mAlbums.get(i).setMediaItems(newPaths);
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (newPaths.isEmpty()) {
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mAlbums.remove(i);
149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
153