1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 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) 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * Create a new, empty calendar resources list.
 26  * @constructor
 27  * @class
 28  * This class represents a list of calendar resources. A calendar resource can be a
 29  * location or a piece of equipment. All calendar resource records are stored in the GAL.
 30  *
 31  * @author Conrad Damon
 32  *
 33  * @param {constant}	resType	the type of resources (location or equipment)
 34  * @param {ZmSearch}	search	the search that generated this list
 35  * 
 36  * @extends		ZmContactList
 37  * 
 38  * @see		ZmCalBaseItem
 39  */
 40 ZmResourceList = function(resType, search) {
 41 	ZmContactList.call(this, search, true, ZmItem.RESOURCE);
 42 
 43 	this.resType = resType;
 44 	
 45 	this._nameToResource = {};
 46 	this._emailToResource = {};
 47 	this._app = appCtxt.getApp(ZmApp.CALENDAR);
 48 };
 49 
 50 ZmResourceList.ATTRS =
 51 	[ZmResource.F_name, ZmResource.F_mail, ZmResource.F_type, ZmResource.F_locationName,
 52 	 ZmResource.F_capacity, ZmResource.F_contactMail, ZmResource.F_description];
 53 
 54 ZmResourceList.prototype = new ZmContactList;
 55 ZmResourceList.prototype.constructor = ZmResourceList;
 56 
 57 ZmResourceList.prototype.toString =
 58 function() {
 59 	return "ZmResourceList";
 60 };
 61 
 62 /**
 63  * Loads the list.
 64  * 
 65  * @param	{ZmBatchCommand}	batchCmd		the batch command
 66  */
 67 ZmResourceList.prototype.load =
 68 function(batchCmd) {
 69 	var conds = [];
 70 	var value = (this.resType == ZmCalBaseItem.LOCATION) ? ZmResource.ATTR_LOCATION : ZmResource.ATTR_EQUIPMENT;
 71 	conds.push({attr: ZmResource.F_type, op: "eq", value: value});
 72 	var params = {conds: conds, join: ZmSearch.JOIN_OR, attrs: ZmResourceList.ATTRS};
 73     if(batchCmd) {
 74         var search = new ZmSearch(params);        
 75 	    search.execute({callback: new AjxCallback(this, this._handleResponseLoad), batchCmd: batchCmd});
 76     }else{
 77         if (appCtxt.isOffline) {
 78             if (appCtxt.isZDOnline()) {
 79                 this.searchCalResources(params);
 80             }
 81         } else {
 82             this.searchCalResources(params);
 83         }
 84     }
 85 };
 86 
 87 /**
 88  * Searches the calendar resources.
 89  * 
 90  * @param	{Hash}	params		a hash of parameters
 91  */
 92 ZmResourceList.prototype.searchCalResources =
 93 function(params) {
 94     var soapDoc = AjxSoapDoc.create("SearchCalendarResourcesRequest", "urn:zimbraAccount");
 95     var method = soapDoc.getMethod();
 96     if (params.attrs) {
 97         AjxUtil.arrayRemove(params.attrs, "fullName");
 98         method.setAttribute("attrs", params.attrs.join(","));
 99     }
100     var searchFilterEl = soapDoc.set("searchFilter");
101     if (params.conds && params.conds.length) {
102         var condsEl = soapDoc.set("conds", null, searchFilterEl);
103         if (params.join == ZmSearch.JOIN_OR) {
104             condsEl.setAttribute("or", 1);
105         }
106         for (var i = 0; i < params.conds.length; i++) {
107             var cond = params.conds[i];
108             if (cond.attr=="fullName" && cond.op=="has") {
109                 var nameEl = soapDoc.set("name", cond.value);
110             } else {
111                 var condEl = soapDoc.set("cond", null, condsEl);
112                 condEl.setAttribute("attr", cond.attr);
113                 condEl.setAttribute("op", cond.op);
114                 condEl.setAttribute("value", cond.value);
115             }
116         }
117     }
118 
119     var response = appCtxt.getAppController().sendRequest({soapDoc:soapDoc, asyncMode:false,
120         timeout:params.timeout, noBusyOverlay:params.noBusyOverlay});
121     var result = new ZmCsfeResult(response, false);
122 
123     var search = new ZmSearch(params);
124     search.isCalResSearch = true;
125 
126     var searchResult = new ZmSearchResult(search);
127     searchResult.set(response.SearchCalendarResourcesResponse);
128     result.set(searchResult);
129     
130     this._handleResponseLoad(result);
131 };
132 
133 ZmResourceList.prototype._handleResponseLoad = 
134 function(result) {
135 	var resp = result.getResponse();
136 	this._vector = resp.getResults(ZmItem.RESOURCE).getVector();
137 	var a = this._vector.getArray();
138 	for (var i = 0; i < a.length; i++) {
139 		var resource = a[i];
140 		this._updateHashes(resource);
141 		this._idHash[resource.id] = resource;
142 	}
143 	//bug:16436 this._loaded changed to this.isLoaded 
144 	this.isLoaded = true;
145 	this._galAutocompleteEnabled = false;
146 };
147 
148 ZmResourceList.prototype._updateHashes =
149 function(resource) {
150 	this._app.updateResourceCache(resource);
151 	var name = resource.getFullName();
152 	if (name) {
153 		this._nameToResource[name.toLowerCase()] = resource;
154 	}
155 	var email = resource.getEmail();
156 	if (email) {
157 		this._emailToResource[email.toLowerCase()] = resource;
158 	}
159 };
160 
161 // Override so we don't invoke ZmContactList.addFromDom
162 ZmResourceList.prototype.addFromDom =
163 function(node, args) {
164 	ZmList.prototype.addFromDom.call(this, node, args);
165 };
166 
167 /**
168  * Gets the resource with the given name, if any. Canonical list only.
169  * Since names aren't guaranteed to be unique, this returns the last resource
170  * with the given name.
171  *
172  * @param {String}	name	the resource name
173  * @return	{ZmResource}	the resource or <code>null</code> if not found
174  */
175 ZmResourceList.prototype.getResourceByName = 
176 function(name) {
177 	if (!name || !this.isCanonical) return null;
178 
179 	return this._nameToResource[name.toLowerCase()];
180 };
181 
182 /**
183  *Gets the resource with the given address, if any. Canonical list only.
184  *
185  * @param {String}	address	an email address
186  * @return	{ZmResource}	the resource or <code>null</code> if not found
187  */
188 ZmResourceList.prototype.getResourceByEmail = 
189 function(address) {
190 	if (!address || !this.isCanonical) return null;
191 
192 	return this._emailToResource[address.toLowerCase()];
193 };
194