1/*
2 * Copyright (C) 2009 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
17package android.content;
18
19import android.text.TextUtils;
20import android.os.Parcelable;
21import android.os.Parcel;
22
23/**
24 * Value type that represents a SyncAdapterType. This object overrides {@link #equals} and
25 * {@link #hashCode}, making it suitable for use as the key of a {@link java.util.Map}
26 */
27public class SyncAdapterType implements Parcelable {
28    public final String authority;
29    public final String accountType;
30    public final boolean isKey;
31    private final boolean userVisible;
32    private final boolean supportsUploading;
33    private final boolean isAlwaysSyncable;
34    private final boolean allowParallelSyncs;
35    private final String settingsActivity;
36
37    public SyncAdapterType(String authority, String accountType, boolean userVisible,
38            boolean supportsUploading) {
39        if (TextUtils.isEmpty(authority)) {
40            throw new IllegalArgumentException("the authority must not be empty: " + authority);
41        }
42        if (TextUtils.isEmpty(accountType)) {
43            throw new IllegalArgumentException("the accountType must not be empty: " + accountType);
44        }
45        this.authority = authority;
46        this.accountType = accountType;
47        this.userVisible = userVisible;
48        this.supportsUploading = supportsUploading;
49        this.isAlwaysSyncable = false;
50        this.allowParallelSyncs = false;
51        this.settingsActivity = null;
52        this.isKey = false;
53    }
54
55    /** @hide */
56    public SyncAdapterType(String authority, String accountType, boolean userVisible,
57            boolean supportsUploading,
58            boolean isAlwaysSyncable,
59            boolean allowParallelSyncs,
60            String settingsActivity) {
61        if (TextUtils.isEmpty(authority)) {
62            throw new IllegalArgumentException("the authority must not be empty: " + authority);
63        }
64        if (TextUtils.isEmpty(accountType)) {
65            throw new IllegalArgumentException("the accountType must not be empty: " + accountType);
66        }
67        this.authority = authority;
68        this.accountType = accountType;
69        this.userVisible = userVisible;
70        this.supportsUploading = supportsUploading;
71        this.isAlwaysSyncable = isAlwaysSyncable;
72        this.allowParallelSyncs = allowParallelSyncs;
73        this.settingsActivity = settingsActivity;
74        this.isKey = false;
75    }
76
77    private SyncAdapterType(String authority, String accountType) {
78        if (TextUtils.isEmpty(authority)) {
79            throw new IllegalArgumentException("the authority must not be empty: " + authority);
80        }
81        if (TextUtils.isEmpty(accountType)) {
82            throw new IllegalArgumentException("the accountType must not be empty: " + accountType);
83        }
84        this.authority = authority;
85        this.accountType = accountType;
86        this.userVisible = true;
87        this.supportsUploading = true;
88        this.isAlwaysSyncable = false;
89        this.allowParallelSyncs = false;
90        this.settingsActivity = null;
91        this.isKey = true;
92    }
93
94    public boolean supportsUploading() {
95        if (isKey) {
96            throw new IllegalStateException(
97                    "this method is not allowed to be called when this is a key");
98        }
99        return supportsUploading;
100    }
101
102    public boolean isUserVisible() {
103        if (isKey) {
104            throw new IllegalStateException(
105                    "this method is not allowed to be called when this is a key");
106        }
107        return userVisible;
108    }
109
110    /**
111     * @return True if this SyncAdapter supports syncing multiple accounts simultaneously.
112     * If false then the SyncManager will take care to only start one sync at a time
113     * using this SyncAdapter.
114     */
115    public boolean allowParallelSyncs() {
116        if (isKey) {
117            throw new IllegalStateException(
118                    "this method is not allowed to be called when this is a key");
119        }
120        return allowParallelSyncs;
121    }
122
123    /**
124     * If true then the SyncManager will never issue an initialization sync to the SyncAdapter
125     * and will instead automatically call
126     * {@link ContentResolver#setIsSyncable(android.accounts.Account, String, int)} with a
127     * value of 1 for each account and provider that this sync adapter supports.
128     * @return true if the SyncAdapter does not require initialization and if it is ok for the
129     * SyncAdapter to treat it as syncable automatically.
130     */
131    public boolean isAlwaysSyncable() {
132        if (isKey) {
133            throw new IllegalStateException(
134                    "this method is not allowed to be called when this is a key");
135        }
136        return isAlwaysSyncable;
137    }
138
139    /**
140     * @return The activity to use to invoke this SyncAdapter's settings activity.
141     * May be null.
142     */
143    public String getSettingsActivity() {
144        if (isKey) {
145            throw new IllegalStateException(
146                    "this method is not allowed to be called when this is a key");
147        }
148        return settingsActivity;
149    }
150
151    public static SyncAdapterType newKey(String authority, String accountType) {
152        return new SyncAdapterType(authority, accountType);
153    }
154
155    public boolean equals(Object o) {
156        if (o == this) return true;
157        if (!(o instanceof SyncAdapterType)) return false;
158        final SyncAdapterType other = (SyncAdapterType)o;
159        // don't include userVisible or supportsUploading in the equality check
160        return authority.equals(other.authority) && accountType.equals(other.accountType);
161    }
162
163    public int hashCode() {
164        int result = 17;
165        result = 31 * result + authority.hashCode();
166        result = 31 * result + accountType.hashCode();
167        // don't include userVisible or supportsUploading  the hash
168        return result;
169    }
170
171    public String toString() {
172        if (isKey) {
173            return "SyncAdapterType Key {name=" + authority
174                    + ", type=" + accountType
175                    + "}";
176        } else {
177            return "SyncAdapterType {name=" + authority
178                    + ", type=" + accountType
179                    + ", userVisible=" + userVisible
180                    + ", supportsUploading=" + supportsUploading
181                    + ", isAlwaysSyncable=" + isAlwaysSyncable
182                    + ", allowParallelSyncs=" + allowParallelSyncs
183                    + ", settingsActivity=" + settingsActivity
184                    + "}";
185        }
186    }
187
188    public int describeContents() {
189        return 0;
190    }
191
192    public void writeToParcel(Parcel dest, int flags) {
193        if (isKey) {
194            throw new IllegalStateException("keys aren't parcelable");
195        }
196
197        dest.writeString(authority);
198        dest.writeString(accountType);
199        dest.writeInt(userVisible ? 1 : 0);
200        dest.writeInt(supportsUploading ? 1 : 0);
201        dest.writeInt(isAlwaysSyncable ? 1 : 0);
202        dest.writeInt(allowParallelSyncs ? 1 : 0);
203        dest.writeString(settingsActivity);
204    }
205
206    public SyncAdapterType(Parcel source) {
207        this(
208                source.readString(),
209                source.readString(),
210                source.readInt() != 0,
211                source.readInt() != 0,
212                source.readInt() != 0,
213                source.readInt() != 0,
214                source.readString());
215    }
216
217    public static final Creator<SyncAdapterType> CREATOR = new Creator<SyncAdapterType>() {
218        public SyncAdapterType createFromParcel(Parcel source) {
219            return new SyncAdapterType(source);
220        }
221
222        public SyncAdapterType[] newArray(int size) {
223            return new SyncAdapterType[size];
224        }
225    };
226}
227