1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2012, 2013, 2014, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * @overview
 26  * This file contains the tree class
 27  */
 28 
 29 /**
 30  * Creates the tree
 31  * @class
 32  * This class represents a tree.
 33  * 
 34  * @param	{constant}	type		the type
 35  * @extends	ZmModel
 36  */
 37 ZmTree = function(type) {
 38 
 39 	if (arguments.length == 0) { return; }
 40 	ZmModel.call(this, type);
 41 
 42 	this.type = type;
 43 	this.root = null;
 44 };
 45 
 46 ZmTree.prototype = new ZmModel;
 47 ZmTree.prototype.constructor = ZmTree;
 48 
 49 /**
 50  * Returns a string representation of the object.
 51  * 
 52  * @return		{String}		a string representation of the object
 53  */
 54 ZmTree.prototype.toString = 
 55 function() {
 56 	return "ZmTree";
 57 };
 58 
 59 /**
 60  * Gets this tree as a string.
 61  * 
 62  * @return	{String}	the tree
 63  */
 64 ZmTree.prototype.asString = 
 65 function() {
 66 	return this.root ? this._asString(this.root, "") : "";
 67 };
 68 
 69 /**
 70  * Gets the item by id.
 71  * 
 72  * @param	{String}	id		the id
 73  * @return	{Object}	the item
 74  */
 75 ZmTree.prototype.getById =
 76 function(id) {
 77 	return this.root ? this.root.getById(id) : null;
 78 };
 79 
 80 /**
 81  * Gets the item by name.
 82  * 
 83  * @param	{String}	name		the name
 84  * @return	{Object}	the item
 85  */
 86 ZmTree.prototype.getByName =
 87 function(name) {
 88 	return this.root ? this.root.getByName(name) : null;
 89 };
 90 
 91 /**
 92  * Gets the item type by name.
 93  *
 94  * @param	{String}	name		the name
 95  * @return	{String}    type of folder
 96  */
 97 //Bug:47848: new method that returns type of the item given its name
 98 ZmTree.prototype.getFolderTypeByName =
 99 function(name){
100 
101     //As folder names are case-insensitive
102     var formattedName = name.toLowerCase();
103 
104     //Iterate through folders of loaded apps
105     var folderList = appCtxt.getTree(ZmOrganizer.FOLDER).asList();
106     var type;
107     var i;
108     for(i=0 ; i < folderList.length ; i ++){
109         var currentName = folderList[i].name;
110         if(formattedName == currentName.toLowerCase()){
111             return folderList[i].type;
112         }
113     }
114 
115     // check for _deferredFolders in the apps that have not been loaded
116     var apps = ZmApp.APPS;
117 
118     for(i=0 ; i<apps.length; i++){
119        var currentApp = appCtxt.getApp(apps[i]);
120        var deferredFolders = currentApp && currentApp._deferredFolders;
121        if(!deferredFolders){
122            continue;
123        }
124        var j;
125        for(j=0 ; j < deferredFolders.length ; j++){
126            var currentFolder = deferredFolders[j];
127            var currentName = currentFolder.obj && currentFolder.obj.name;
128             if(formattedName == currentName.toLowerCase()){
129                 return currentFolder.type;
130             }
131        }
132 
133     }
134     // if still not found return type as "Folder"
135     type = ZmOrganizer.FOLDER;
136     return type;
137 }
138 
139 /**
140  * Gets the item by type.
141  * 
142  * @param	{String}	name		the type name
143  * @return	{Object}	the item
144  */
145 ZmTree.prototype.getByType =
146 function(name) {
147 	return this.root ? this.root.getByType(name) : null;
148 };
149 
150 /**
151  * Gets the size of the tree.
152  * 
153  * @return	{int}	the size
154  */
155 ZmTree.prototype.size =
156 function() {
157 	return this.root ? this.root.size() : 0;
158 };
159 
160 /**
161  * Resets the tree.
162  */
163 ZmTree.prototype.reset =
164 function() {
165 	this.root = null;
166 };
167 
168 /**
169  * Gets the tree as a list.
170  * 
171  * @return	{Array}	an array
172  */
173 ZmTree.prototype.asList =
174 function(options) {
175 	var list = [];
176 	return this.root ? this._addToList(this.root, list, options) : list;
177 };
178 
179 /**
180  * Gets the unread hash.
181  * 
182  * @param	{Hash}	unread		the unread hash
183  * @return	{Hash} the unread tree as a hash
184  */
185 ZmTree.prototype.getUnreadHash =
186 function(unread) {
187 	if (!unread) {
188 		unread = {};
189 	}
190 	return this.root ? this._getUnreadHash(this.root, unread) : unread;
191 };
192 
193 /**
194  * @private
195  */
196 ZmTree.prototype._addToList =
197 function(organizer, list, options) {
198 	var incRemote = options && options.includeRemote;
199 	var remoteOnly = options && options.remoteOnly;
200 	var isRemote = organizer.isRemote();
201 	if ((!isRemote && !remoteOnly) || (isRemote && (remoteOnly || incRemote))) {
202 		list.push(organizer);
203 	}
204 	var children = organizer.children.getArray();
205     for (var i = 0; i < children.length; i++) {
206         this._addToList(children[i], list, options);
207     }
208 	return list;
209 };
210 
211 /**
212  * @private
213  */
214 ZmTree.prototype._asString =
215 function(organizer, str) {
216 	if (organizer.id) {
217 		str = str + organizer.id;
218 	}
219 	var children = organizer.children.clone().getArray();
220 	if (children.length) {
221 		children.sort(function(a,b){return a.id - b.id;});
222 		str = str + "[";
223 		for (var i = 0; i < children.length; i++) {
224 			if (children[i].id == ZmFolder.ID_TAGS) { // Tags "folder" added when view is set
225 				continue;
226 			}
227 			if (i > 0) {
228 				str = str + ",";
229 			}
230 			str = this._asString(children[i], str);
231 		}
232 		str = str + "]";
233 	}
234 	return str;
235 };
236 
237 /**
238  * @private
239  */
240 ZmTree.prototype._getUnreadHash =
241 function(organizer, unread) {
242 	unread[organizer.id] = organizer.numUnread;
243 	var children = organizer.children.getArray();
244 	for (var i = 0; i < children.length; i++) {
245 		this._getUnreadHash(children[i], unread);
246 	}
247 
248 	return unread;
249 };
250