1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.sync.internal_api.pub.base;
6
7import android.util.Log;
8
9import com.google.common.annotations.VisibleForTesting;
10import com.google.common.collect.Sets;
11import com.google.ipc.invalidation.external.client.types.ObjectId;
12import com.google.protos.ipc.invalidation.Types;
13
14import java.util.Collection;
15import java.util.Set;
16
17/**
18 * The model types that are synced in Chrome for Android.
19 */
20public enum ModelType {
21    /**
22     * An autofill object.
23     */
24    AUTOFILL("AUTOFILL"),
25    /**
26     * An autofill profile object.
27     */
28    AUTOFILL_PROFILE("AUTOFILL_PROFILE"),
29    /**
30     * A bookmark folder or a bookmark URL object.
31     */
32    BOOKMARK("BOOKMARK"),
33    /**
34     * Flags to enable experimental features.
35     */
36    EXPERIMENTS("EXPERIMENTS"),
37    /**
38     * An object representing a set of Nigori keys.
39     */
40    NIGORI("NIGORI"),
41    /**
42     * A password entry.
43     */
44    PASSWORD("PASSWORD"),
45    /**
46     * An object representing a browser session or tab.
47     */
48    SESSION("SESSION"),
49    /**
50     * A typed_url folder or a typed_url object.
51     */
52    TYPED_URL("TYPED_URL"),
53    /**
54     * A history delete directive object.
55     */
56    HISTORY_DELETE_DIRECTIVE("HISTORY_DELETE_DIRECTIVE"),
57    /**
58     * A device info object.
59     */
60    DEVICE_INFO("DEVICE_INFO"),
61    /**
62     * A proxy tabs object (placeholder for sessions).
63     */
64    PROXY_TABS("NULL", true),
65    /**
66     * A favicon image object.
67     */
68    FAVICON_IMAGE("FAVICON_IMAGE"),
69    /**
70     * A favicon tracking object.
71     */
72    FAVICON_TRACKING("FAVICON_TRACKING");
73
74    /** Special type representing all possible types. */
75    public static final String ALL_TYPES_TYPE = "ALL_TYPES";
76
77    private static final String TAG = "ModelType";
78
79    private final String mModelType;
80
81    private final boolean mNonInvalidationType;
82
83    ModelType(String modelType, boolean nonInvalidationType) {
84        mModelType = modelType;
85        mNonInvalidationType = nonInvalidationType;
86    }
87
88    ModelType(String modelType) {
89        this(modelType, false);
90    }
91
92    /**
93     * Returns the {@link ObjectId} representation of this {@link ModelType}.
94     *
95     * This should be used with caution, since it converts even {@link ModelType} instances with
96     * |mNonInvalidationType| set. For automatically stripping such {@link ModelType} entries out,
97     * use {@link ModelType#modelTypesToObjectIds(java.util.Set)} instead.
98     */
99    @VisibleForTesting
100    public ObjectId toObjectId() {
101        return ObjectId.newInstance(Types.ObjectSource.Type.CHROME_SYNC.getNumber(),
102                mModelType.getBytes());
103    }
104
105    public static ModelType fromObjectId(ObjectId objectId) {
106        try {
107            return valueOf(new String(objectId.getName()));
108        } catch (IllegalArgumentException e) {
109            return null;
110        }
111    }
112
113    /**
114     * Converts string representations of types to sync to {@link ModelType}s.
115     * <p>
116     * If {@code syncTypes} contains {@link #ALL_TYPES_TYPE}, then the returned
117     * set contains all values of the {@code ModelType} enum.
118     * <p>
119     * Otherwise, the returned set contains the {@code ModelType} values for all elements of
120     * {@code syncTypes} for which {@link ModelType#valueOf(String)} successfully returns; other
121     * elements are dropped.
122     */
123    public static Set<ModelType> syncTypesToModelTypes(Collection<String> syncTypes) {
124        if (syncTypes.contains(ALL_TYPES_TYPE)) {
125            return Sets.newHashSet(ModelType.values());
126        } else {
127            Set<ModelType> modelTypes = Sets.newHashSetWithExpectedSize(syncTypes.size());
128            for (String syncType : syncTypes) {
129                try {
130                    modelTypes.add(valueOf(syncType));
131                } catch (IllegalArgumentException exception) {
132                    // Drop invalid sync types.
133                    Log.w(TAG, "Could not translate sync type to model type: " + syncType);
134                }
135            }
136            return modelTypes;
137        }
138    }
139
140    /**
141     * Converts a set of sync types {@link String} to a set of {@link ObjectId}.
142     *
143     * This strips out any {@link ModelType} that is not an invalidation type.
144     */
145    public static Set<ObjectId> syncTypesToObjectIds(Collection<String> syncTypes) {
146        return modelTypesToObjectIds(syncTypesToModelTypes(syncTypes));
147    }
148
149    /**
150     * Converts a set of {@link ModelType} to a set of {@link ObjectId}.
151     *
152     * This strips out any {@link ModelType} that is not an invalidation type.
153     */
154    public static Set<ObjectId> modelTypesToObjectIds(Set<ModelType> modelTypes) {
155        Set<ObjectId> objectIds = Sets.newHashSetWithExpectedSize(modelTypes.size());
156        for (ModelType modelType : modelTypes) {
157            if (!modelType.mNonInvalidationType) {
158                objectIds.add(modelType.toObjectId());
159            }
160        }
161        return objectIds;
162    }
163
164    /** Converts a set of {@link ModelType} to a set of string names. */
165    public static Set<String> modelTypesToSyncTypes(Set<ModelType> modelTypes) {
166        Set<String> objectIds = Sets.newHashSetWithExpectedSize(modelTypes.size());
167        for (ModelType modelType : modelTypes) {
168            objectIds.add(modelType.toString());
169        }
170        return objectIds;
171    }
172}
173