Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.sync;
7 import java.util.Collections;
8 import java.util.HashMap;
9 import java.util.Map;
10 import java.util.Map.Entry;
12 import org.mozilla.gecko.background.common.log.Logger;
14 /**
15 * Fetches the timestamp information in <code>info/collections</code> on the
16 * Sync server. Provides access to those timestamps, along with logic to check
17 * for whether a collection requires an update.
18 */
19 public class InfoCollections {
20 private static final String LOG_TAG = "InfoCollections";
22 /**
23 * Fields fetched from the server, or <code>null</code> if not yet fetched.
24 * <p>
25 * Rather than storing decimal/double timestamps, as provided by the server,
26 * we convert immediately to milliseconds since epoch.
27 */
28 final Map<String, Long> timestamps;
30 public InfoCollections() {
31 this(new ExtendedJSONObject());
32 }
34 public InfoCollections(final ExtendedJSONObject record) {
35 Logger.debug(LOG_TAG, "info/collections is " + record.toJSONString());
36 HashMap<String, Long> map = new HashMap<String, Long>();
38 for (Entry<String, Object> entry : record.entrySet()) {
39 final String key = entry.getKey();
40 final Object value = entry.getValue();
42 // These objects are most likely going to be Doubles. Regardless, we
43 // want to get them in a more sane time format.
44 if (value instanceof Double) {
45 map.put(key, Utils.decimalSecondsToMilliseconds((Double) value));
46 continue;
47 }
48 if (value instanceof Long) {
49 map.put(key, Utils.decimalSecondsToMilliseconds((Long) value));
50 continue;
51 }
52 if (value instanceof Integer) {
53 map.put(key, Utils.decimalSecondsToMilliseconds((Integer) value));
54 continue;
55 }
56 Logger.warn(LOG_TAG, "Skipping info/collections entry for " + key);
57 }
59 this.timestamps = Collections.unmodifiableMap(map);
60 }
62 /**
63 * Return the timestamp for the given collection, or null if the timestamps
64 * have not been fetched or the given collection does not have a timestamp.
65 *
66 * @param collection
67 * The collection to inspect.
68 * @return the timestamp in milliseconds since epoch.
69 */
70 public Long getTimestamp(String collection) {
71 if (timestamps == null) {
72 return null;
73 }
74 return timestamps.get(collection);
75 }
77 /**
78 * Test if a given collection needs to be updated.
79 *
80 * @param collection
81 * The collection to test.
82 * @param lastModified
83 * Timestamp when local record was last modified.
84 */
85 public boolean updateNeeded(String collection, long lastModified) {
86 Logger.trace(LOG_TAG, "Testing " + collection + " for updateNeeded. Local last modified is " + lastModified + ".");
88 // No local record of modification time? Need an update.
89 if (lastModified <= 0) {
90 return true;
91 }
93 // No meta/global on the server? We need an update. The server fetch will fail and
94 // then we will upload a fresh meta/global.
95 Long serverLastModified = getTimestamp(collection);
96 if (serverLastModified == null) {
97 return true;
98 }
100 // Otherwise, we need an update if our modification time is stale.
101 return (serverLastModified.longValue() > lastModified);
102 }
103 }