1750e8ec8af168afd318d47082b326b95f1cca517Angus Kong/*
2750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * Copyright (C) 2013 The Android Open Source Project
3750e8ec8af168afd318d47082b326b95f1cca517Angus Kong *
4750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * Licensed under the Apache License, Version 2.0 (the "License");
5750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * you may not use this file except in compliance with the License.
6750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * You may obtain a copy of the License at
7750e8ec8af168afd318d47082b326b95f1cca517Angus Kong *
8750e8ec8af168afd318d47082b326b95f1cca517Angus Kong *      http://www.apache.org/licenses/LICENSE-2.0
9750e8ec8af168afd318d47082b326b95f1cca517Angus Kong *
10750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * Unless required by applicable law or agreed to in writing, software
11750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * distributed under the License is distributed on an "AS IS" BASIS,
12750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * See the License for the specific language governing permissions and
14750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * limitations under the License.
15750e8ec8af168afd318d47082b326b95f1cca517Angus Kong */
16750e8ec8af168afd318d47082b326b95f1cca517Angus Kong
17750e8ec8af168afd318d47082b326b95f1cca517Angus Kongpackage com.android.camera.data;
18750e8ec8af168afd318d47082b326b95f1cca517Angus Kong
19750e8ec8af168afd318d47082b326b95f1cca517Angus Kongimport android.content.Context;
208a2350a3d557465b53445685db0f9ac838cf90c5Angus Kongimport android.os.Bundle;
21750e8ec8af168afd318d47082b326b95f1cca517Angus Kongimport android.view.View;
222bca210e5fc8a77685775ffb403096167b017dceAngus Kongimport com.android.camera.debug.Log;
2301054e922aa547b937a71131ad04c6bd15356240Angus Kongimport com.android.camera.filmstrip.ImageData;
24bd26069d391830856c57c2141cd2efbc8423d871Angus Kong
25bd26069d391830856c57c2141cd2efbc8423d871Angus Kongimport java.util.Comparator;
26750e8ec8af168afd318d47082b326b95f1cca517Angus Kong
27f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling/**
28f1f5186f7d3fd8bf35009d9e65a43914c664d82bSascha Haeberling * An abstract interface that represents the local media data. Also implements
29750e8ec8af168afd318d47082b326b95f1cca517Angus Kong * Comparable interface so we can sort in DataAdapter.
30a16e7b50f3148f581439509279f242092e254309ztenghui * Note that all the sub-class of LocalData are designed to be immutable, i.e:
31a16e7b50f3148f581439509279f242092e254309ztenghui * all the members need to be final, and there is no setter. In this way, we
32a16e7b50f3148f581439509279f242092e254309ztenghui * can guarantee thread safety for LocalData.
33750e8ec8af168afd318d47082b326b95f1cca517Angus Kong */
3401054e922aa547b937a71131ad04c6bd15356240Angus Kongpublic interface LocalData extends ImageData {
352bca210e5fc8a77685775ffb403096167b017dceAngus Kong    static final Log.Tag TAG = new Log.Tag("LocalData");
36750e8ec8af168afd318d47082b326b95f1cca517Angus Kong
37a16e7b50f3148f581439509279f242092e254309ztenghui    public static final String MIME_TYPE_JPEG = "image/jpeg";
38a16e7b50f3148f581439509279f242092e254309ztenghui
39740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong    // Data actions.
40740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong    public static final int DATA_ACTION_NONE = 0;
41740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong    public static final int DATA_ACTION_PLAY = 1;
42740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong    public static final int DATA_ACTION_DELETE = (1 << 1);
43740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong    public static final int DATA_ACTION_EDIT = (1 << 2);
44e0aff89f3e05eb6008651b290ba79d484de55970Angus Kong    public static final int DATA_ACTION_SHARE = (1 << 3);
45082210302a595e665ef0e34e9be216e554b13698Angus Kong
46c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong    // Local data types. Returned by getLocalDataType().
47cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    /**
48cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware     * Constant for denoting a camera preview.
49cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware     */
50cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    public static final int LOCAL_CAMERA_PREVIEW   = 1;
51cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    /**
52cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware     * Constant for denoting an arbitrary view.
53cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware     */
54cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    public static final int LOCAL_VIEW             = 2;
55cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    /**
56cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware     * Constant for denoting a still image.
57cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware     */
58cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    public static final int LOCAL_IMAGE            = 3;
59cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    /**
60cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware     * Constant for denoting a video.
61cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware     */
62cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    public static final int LOCAL_VIDEO            = 4;
63cd2eeb0efc4370f20e9836e20eb11cb974e3b00dMangesh Ghiware    /**
643250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong     * Constant for denoting an in-progress item which should not be touched
653250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong     * before the related task is done. Data of this type should not support
663250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong     * any actions like sharing, editing, etc.
673250987bd014d1c5463b8a39bbe988165ab1cc3fAngus Kong     */
688a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong    public static final int LOCAL_IN_PROGRESS_DATA = 5;
69280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling
70c67c07b42eaf918c26cbb785b211a08a6ebc88a1Sascha Haeberling    // TODO: Re-think how the in-progress logic works. We shouldn't need to pass
71c67c07b42eaf918c26cbb785b211a08a6ebc88a1Sascha Haeberling    // in the information about whether this session is in progress.
72caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers
73caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers    /**
74caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     * Creates View to represent media.
75caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     *
76caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     * @param context The {@link android.content.Context} to create the view.
77632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd     * @param thumbWidth Width in pixels of the suggested zoomed out view/image size.
78632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd     * @param thumbHeight Height in pixels of the suggested zoomed out view/image size.
79caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     * @param adapter Data adapter for this data item.
80caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     */
81632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd    View getView(Context context, View recycled, int thumbWidth, int thumbHeight,
82632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd        int placeHolderResourceId, LocalDataAdapter adapter, boolean isInProgress);
8337f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
8443bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd    /** Returns a unique identifier for the view created by this data so that the view
8543bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd     * can be reused.
8643bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd     *
8743bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd     * @see android.widget.BaseAdapter#getItemViewType(int)
8843bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd     */
8943bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd    LocalDataViewType getItemViewType();
9043bf03f6e7f9a71b7553e7282b5799798997caf7Sam Judd
91caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers   /**
92caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     * Request resize of View created by getView().
93caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     *
94caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     * @param context The {@link android.content.Context} to create the view.
95632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd     * @param thumbWidth Width in pixels of the suggested zoomed out view/image size.
96632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd     * @param thumbHeight Height in pixels of the suggested zoomed out view/image size.
97caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     * @param view View created by getView();
98caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     * @param adapter Data adapter for this data item.
99caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers     */
100632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd    public void loadFullImage(Context context, int thumbWidth, int thumbHeight, View view,
101632eaafda53eb59b15c81ddeaf2080e6d8515f59Sam Judd        LocalDataAdapter adapter);
102caca8c7b2e97bd76e4df1ea98c08acaa48b21557Andy Huibers
10337f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    /**
10437f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * Gets the date when this data is created. The returned date is also used
105b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers     * for sorting data. Value is epoch milliseconds.
10637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     *
10737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * @return The date when this data is created.
10837f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * @see {@link NewestFirstComparator}
10937f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     */
110082210302a595e665ef0e34e9be216e554b13698Angus Kong    long getDateTaken();
11137f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
11237f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    /**
11337f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * Gets the date when this data is modified. The returned date is also used
114b8600b2b798f6b28e405380a17bd5f6fc23fcc82Andy Huibers     * for sorting data. Value is epoch seconds.
11537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     *
11637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * @return The date when this data is modified.
11737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * @see {@link NewestFirstComparator}
11837f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     */
119082210302a595e665ef0e34e9be216e554b13698Angus Kong    long getDateModified();
12037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
12137f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    /** Gets the title of this data */
122082210302a595e665ef0e34e9be216e554b13698Angus Kong    String getTitle();
12337f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
12437f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    /**
12537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * Checks if the data actions (delete/play ...) can be applied on this data.
12637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     *
12737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * @param actions The actions to check.
12837f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * @return Whether all the actions are supported.
12937f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     */
13037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    boolean isDataActionSupported(int actions);
13137f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
1324ff5a1ab360577c6a7ec953f9197778c84c9d334Angus Kong    /** Removes the data from the storage if possible. */
133082210302a595e665ef0e34e9be216e554b13698Angus Kong    boolean delete(Context c);
13437f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
1358e5e4eedb25a4589342660b928935acca4375fc7Angus Kong    void onFullScreen(boolean fullScreen);
13637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
13737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    /** Returns {@code true} if it allows swipe to filmstrip in full screen. */
1388e5e4eedb25a4589342660b928935acca4375fc7Angus Kong    boolean canSwipeInFullScreen();
13937f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
14037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    /**
14137f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * Returns the path to the data on the storage.
14237f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     *
14337f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * @return Empty path if there's none.
14437f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     */
1458e5e4eedb25a4589342660b928935acca4375fc7Angus Kong    String getPath();
146750e8ec8af168afd318d47082b326b95f1cca517Angus Kong
14737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling    /**
14888ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling     * @return The mimetype of this data item, or null, if this item has no
14988ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling     *         mimetype associated with it.
15088ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling     */
15188ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling    String getMimeType();
15288ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling
15388ef7664ba6a888fa5da8693091674e152b56192Sascha Haeberling    /**
15426795a9258c0815ca2a92d2c660438066f001022Angus Kong     * @return The media details (such as EXIF) for the data. {@code null} if
15526795a9258c0815ca2a92d2c660438066f001022Angus Kong     * not available for the data.
1566f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling     */
1576f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling    MediaDetails getMediaDetails(Context context);
1586f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling
1596f64b50db6565bc6454304fd20c0c4020b297bb7Sascha Haeberling    /**
160c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong     * Returns the type of the local data defined by {@link LocalData}.
161c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong     *
162c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong     * @return The local data type. Could be one of the following:
163c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong     * {@code LOCAL_CAMERA_PREVIEW}, {@code LOCAL_VIEW}, {@code LOCAL_IMAGE},
164280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling     * {@code LOCAL_VIDEO}, {@code LOCAL_PHOTO_SPHERE},
165280fd3edae1dc35ac1015bcc9532477169fad3aaSascha Haeberling     * {@code LOCAL_360_PHOTO_SPHERE}, and {@code LOCAL_RGBZ}
166c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong     */
167fae11a165e344a38811770c7d348eda214683edcSascha Haeberling    int getLocalDataType();
168c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong
169c27d21bc3b9322936004827ab005fb7d1facfacfAngus Kong    /**
170a16e7b50f3148f581439509279f242092e254309ztenghui     * @return The size of the data in bytes
171a16e7b50f3148f581439509279f242092e254309ztenghui     */
172a16e7b50f3148f581439509279f242092e254309ztenghui    long getSizeInBytes();
173a16e7b50f3148f581439509279f242092e254309ztenghui
174a16e7b50f3148f581439509279f242092e254309ztenghui    /**
17537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     * Refresh the data content.
17637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     *
1778a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong     * @param context The Android {@link android.content.Context}.
178a16e7b50f3148f581439509279f242092e254309ztenghui     * @return A new LocalData object if success, null otherwise.
17937f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling     */
1808a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong    LocalData refresh(Context context);
18137f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling
182740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong    /**
1838a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong     * @return the {@link android.content.ContentResolver} Id of the data.
184740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong     */
1858a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong    long getContentId();
186740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong
187740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong    /**
1888a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong     * @return the metadata. Should never be {@code null}.
1898a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong     */
1908a2350a3d557465b53445685db0f9ac838cf90c5Angus Kong    Bundle getMetadata();
191e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong
192e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong    /**
1934021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd     * Any media store attribute that can potentially change the local data
1944021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd     * should be included in this signature, primarily oriented at detecting
1954021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd     * edits.
1964021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd     *
1974021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd     * @return A string identifying the set of changeable attributes.
1984021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd     */
1994021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd    String getSignature();
2004021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd
2014021c896985d9ba43db0199f259ce4b8bfc0dc88Sam Judd    /**
202e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong     * @return whether the metadata is updated.
203e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong     */
204e2f4c03eaea059e15adf34d8782c433b1f7164dcAngus Kong    public boolean isMetadataUpdated();
205740cbeef73e8b8fad7605cf0723a647d81f73962Angus Kong
206750e8ec8af168afd318d47082b326b95f1cca517Angus Kong    static class NewestFirstComparator implements Comparator<LocalData> {
207750e8ec8af168afd318d47082b326b95f1cca517Angus Kong
2088e5e4eedb25a4589342660b928935acca4375fc7Angus Kong        /** Compare taken/modified date of LocalData in descent order to make
2098e5e4eedb25a4589342660b928935acca4375fc7Angus Kong         newer data in the front.
2108e5e4eedb25a4589342660b928935acca4375fc7Angus Kong         The negative numbers here are always considered "bigger" than
2118e5e4eedb25a4589342660b928935acca4375fc7Angus Kong         positive ones. Thus, if any one of the numbers is negative, the logic
2128e5e4eedb25a4589342660b928935acca4375fc7Angus Kong         is reversed. */
213dff672d644f3db07d13f6d58bfceb2b1cc10d345Angus Kong        private static int compareDate(long v1, long v2) {
214dff672d644f3db07d13f6d58bfceb2b1cc10d345Angus Kong            if (v1 >= 0 && v2 >= 0) {
2157283c609ccca310cfc39a3d25bb1c58f4198a341Angus Kong                return ((v1 < v2) ? 1 : ((v1 > v2) ? -1 : 0));
216750e8ec8af168afd318d47082b326b95f1cca517Angus Kong            }
2177283c609ccca310cfc39a3d25bb1c58f4198a341Angus Kong            return ((v2 < v1) ? 1 : ((v2 > v1) ? -1 : 0));
218750e8ec8af168afd318d47082b326b95f1cca517Angus Kong        }
219750e8ec8af168afd318d47082b326b95f1cca517Angus Kong
220750e8ec8af168afd318d47082b326b95f1cca517Angus Kong        @Override
221750e8ec8af168afd318d47082b326b95f1cca517Angus Kong        public int compare(LocalData d1, LocalData d2) {
222dff672d644f3db07d13f6d58bfceb2b1cc10d345Angus Kong            int cmp = compareDate(d1.getDateTaken(), d2.getDateTaken());
223750e8ec8af168afd318d47082b326b95f1cca517Angus Kong            if (cmp == 0) {
224dff672d644f3db07d13f6d58bfceb2b1cc10d345Angus Kong                cmp = compareDate(d1.getDateModified(), d2.getDateModified());
225750e8ec8af168afd318d47082b326b95f1cca517Angus Kong            }
226750e8ec8af168afd318d47082b326b95f1cca517Angus Kong            if (cmp == 0) {
227750e8ec8af168afd318d47082b326b95f1cca517Angus Kong                cmp = d1.getTitle().compareTo(d2.getTitle());
228750e8ec8af168afd318d47082b326b95f1cca517Angus Kong            }
229750e8ec8af168afd318d47082b326b95f1cca517Angus Kong            return cmp;
230750e8ec8af168afd318d47082b326b95f1cca517Angus Kong        }
231750e8ec8af168afd318d47082b326b95f1cca517Angus Kong    }
232750e8ec8af168afd318d47082b326b95f1cca517Angus Kong}
233