1/*******************************************************************************
2 *      Copyright (C) 2012 Google Inc.
3 *      Licensed to The Android Open Source Project.
4 *
5 *      Licensed under the Apache License, Version 2.0 (the "License");
6 *      you may not use this file except in compliance with the License.
7 *      You may obtain a copy of the License at
8 *
9 *           http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *      Unless required by applicable law or agreed to in writing, software
12 *      distributed under the License is distributed on an "AS IS" BASIS,
13 *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *      See the License for the specific language governing permissions and
15 *      limitations under the License.
16 *******************************************************************************/
17
18package com.android.mail.ui;
19
20import com.android.mail.providers.Folder;
21import com.android.mail.utils.LogTag;
22import com.android.mail.utils.LogUtils;
23
24import com.google.common.collect.Lists;
25import com.google.common.collect.Maps;
26
27import java.util.List;
28import java.util.Map;
29import java.util.Set;
30
31/**
32 * Object that contains a list of folder operations (application/removals of folders)
33 *
34 */
35// This was earlier called FolderOperations
36public class FolderOperations {
37    /**
38     * Map of the Folders that that either need to be applied or removed
39     * The key is the canonical name of the Folder, and the value is a boolean,
40     * when true, the Folder should be added, and when false, the Folder
41     * should be removed
42     */
43    private final Map<String, Operation> mOperations;
44
45    private static final String LOG_TAG = LogTag.getLogTag();
46
47    public FolderOperations() {
48        mOperations = Maps.newHashMap();
49    }
50
51    public FolderOperations(Folder folder, boolean add) {
52        this();
53        if (folder != null) {
54            add(folder, add);
55        } else {
56            LogUtils.e(LOG_TAG, "FolderOperation created with null Folder object");
57        }
58    }
59
60    /**
61     * Adds an operation to the list of folder operations to be applied. The last
62     * operation for a folder will be retained in the list of operations.
63     * @param folder Folder to be applied
64     * @param add True if the folder should be applied, or false if the folder should be removed
65     */
66    public void add(Folder folder, boolean add) {
67        Operation operation = new Operation(folder, add);
68
69        mOperations.put(folder.name, operation);
70    }
71
72    /**
73     * Returns true if there is an operation for the specified folder
74     * @param folder Folder
75     * @return Returns true if there is a add or remove operation for
76     * the specified folder
77     */
78    public boolean hasOperation(Folder folder) {
79        return hasOperation(folder.name);
80    }
81
82    /**
83     * Returns true if there is an operation for the specified folder
84     * @param canonicalName Canonical name of the folder
85     * @return Returns true if there is a add or remove operation for
86     * the specified folder
87     */
88    public boolean hasOperation(String canonicalName) {
89        return mOperations.containsKey(canonicalName);
90    }
91
92    /**
93     * Returns true if the specified folder will be applied
94     * @param folder Folder
95     * @return Returns true if there is an operation that will apply the folder
96     */
97    public boolean hasApplyOperation(Folder folder) {
98        return hasApplyOperation(folder.name);
99    }
100
101    /**
102     * Returns true if the specified folder will be applied
103     * @param canonicalName Canonical name of the folder
104     * @return Returns true if there is an operation that will apply the folder
105     */
106    public boolean hasApplyOperation(String canonicalName) {
107        if (hasOperation(canonicalName)) {
108            Operation operation = mOperations.get(canonicalName);
109            return operation.mAdd;
110        }
111        return false;
112    }
113
114    /**
115     * Returns true if the specified folder will be removed
116     * @param folder folder
117     * @return Returns true if there is an operation that will remove the folder
118     */
119    public boolean hasRemoveOperation(Folder folder) {
120        return hasRemoveOperation(folder.name);
121    }
122
123    /**
124     * Returns true if the specified folder will be removed
125     * @param canonicalName Canonical name of the folder
126     * @return Returns true if there is an operation that will remove the folder
127     */
128    public boolean hasRemoveOperation(String canonicalName) {
129        if (hasOperation(canonicalName)) {
130            Operation operation = mOperations.get(canonicalName);
131            return !operation.mAdd;
132        }
133        return false;
134    }
135
136    public void clear() {
137        mOperations.clear();
138    }
139
140    /**
141     * Return the number of folder operations
142     */
143    public int count() {
144        return mOperations.size();
145    }
146
147    /**
148     * Returns a FolderOperations object that will revert the operations described in
149     * this FolderOperations instance
150     * @return FolderOperations object that will revert
151     */
152    public FolderOperations undoOperation() {
153        FolderOperations undoOperations = new FolderOperations();
154        Set<Map.Entry<String, Operation>> operationSet = mOperations.entrySet();
155        for (Map.Entry<String, Operation> operationItem : operationSet) {
156            Operation operationToUndo = operationItem.getValue();
157            undoOperations.add(operationToUndo.mFolder, !operationToUndo.mAdd);
158        }
159        return undoOperations;
160    }
161
162    /**
163     * Returns an array of the folder operations
164     * @return Array of the folder operations to perform
165     */
166    public List<Operation> getOperationList() {
167        List<Operation> results = Lists.newArrayList();
168        Set<Map.Entry<String, Operation>> operationSet = mOperations.entrySet();
169        for (Map.Entry<String, Operation> operationItem : operationSet) {
170            results.add(operationItem.getValue());
171        }
172        return results;
173    }
174
175    /**
176     * Serialize the FolderOperations
177     * Not implemented!!
178     * TODO(viki): Copy over from Gmail Labels#serialize(FolderOperations)
179     * @return Serialized representation of the folder operations
180     */
181    public static String serialize(FolderOperations operations) {
182        return "";
183    }
184
185    /**
186     * Deserialize a encoded string and instantiates a FolderOperations object
187     * Not implemented!!
188     * TODO(viki): Copy over from Gmail Labels#deSerialize(String)
189     * @param encodedFolderOperations Encode FolderOperations string
190     * @return FolderOperations object
191     */
192    public static FolderOperations deserialize(String encodedFolderOperations) {
193        return null;
194    }
195
196    /**
197     * An operation that can be performed on the folder.
198     *
199     */
200    private class Operation {
201        /**
202         * True if the action is to include in the folder, false if the action is to remove it
203         * from the folder.
204         */
205        public final boolean mAdd;
206
207        /**
208         * The  name of the folder for which the operation is performed.
209         */
210        public final Folder mFolder;
211
212        /**
213         * Create a new operation, which is to add the message to the given folder
214         * @param folder Name of the folder.
215         * @param add true if message has to be added to the folder. False if it has to be removed
216         * from the existing folder.
217         */
218        private Operation(Folder folder, boolean add) {
219            mFolder = folder;
220            mAdd = add;
221        }
222    }
223
224}
225