1 /*
2  * Copyright (C) 2013 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.camera.data;
18 
19 import com.google.common.base.Preconditions;
20 
21 import java.util.Comparator;
22 import java.util.Date;
23 
24 /**
25  * Sort filmstrip items by newest first, then by most recently modified
26  * then by title comparison.
27  */
28 public class NewestFirstComparator implements Comparator<FilmstripItem> {
29     private final Date mNow;
30 
31     private static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
32 
33     /**
34      * Construct a comparator that sorts items by newest first. We ignore future
35      * creation dates using the supplied current date as a baseline.
36      *
37      * @param now present date to be used in comparisons to rule out dates in
38      *            the future.
39      */
NewestFirstComparator(Date now)40     public NewestFirstComparator(Date now) {
41         Preconditions.checkNotNull(now);
42         // Buffer by 24 hours to protect against false positives due to intraday
43         // time zone issues.
44         mNow = new Date(now.getTime() + MILLIS_IN_DAY);
45     }
46 
47     @Override
compare(FilmstripItem d1, FilmstripItem d2)48     public int compare(FilmstripItem d1, FilmstripItem d2) {
49         FilmstripItemData d1Data = d1.getData();
50         FilmstripItemData d2Data = d2.getData();
51 
52         // If creation date is in future, fall back to modified, b/19565464.
53         Date d1PrimaryDate = isFuture(d1Data.getCreationDate()) ?
54                 d1Data.getLastModifiedDate() : d1Data.getCreationDate();
55         Date d2PrimaryDate = isFuture(d2Data.getCreationDate()) ?
56                 d2Data.getLastModifiedDate() : d2Data.getCreationDate();
57 
58         int cmp = compareDate(d1PrimaryDate, d2PrimaryDate);
59         if (cmp == 0) {
60             cmp = compareDate(d1Data.getLastModifiedDate(),
61                   d2Data.getLastModifiedDate());
62         }
63         if (cmp == 0) {
64             cmp = d1Data.getTitle().compareTo(d2Data.getTitle());
65         }
66         return cmp;
67     }
68 
69     /**
70      * Normal date comparison will sort these oldest first,
71      * so invert the order by multiplying by -1.
72      */
compareDate(Date v1, Date v2)73     private int compareDate(Date v1, Date v2) {
74         return v1.compareTo(v2) * -1;
75     }
76 
77     /**
78      * Is the Date in the future from a base date. If the date is in the future
79      * (larger) than the base date provided, return true.
80      *
81      * @param date The date to check whether it is in the future
82      * @param base The date to use as a baseline 'present'
83      * @return true if date is in the future from base
84      */
isFuture(Date date)85     private boolean isFuture(Date date) {
86         return mNow.compareTo(date) < 0;
87     }
88 }