1 /* ***** BEGIN LICENSE BLOCK ***** 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 * 4 * The contents of this file are subject to the Mozilla Public License Version 5 * 1.1 (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * http://www.mozilla.org/MPL/ 8 * 9 * Software distributed under the License is distributed on an "AS IS" basis, 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 * for the specific language governing rights and limitations under the 12 * License. 13 * 14 * The Original Code is gContactSync. 15 * 16 * The Initial Developer of the Original Code is 17 * Josh Geenen <gcontactsync@pirules.org>. 18 * Portions created by the Initial Developer are Copyright (C) 2008-2009 19 * the Initial Developer. All Rights Reserved. 20 * 21 * Contributor(s): 22 * 23 * Alternatively, the contents of this file may be used under the terms of 24 * either the GNU General Public License Version 2 or later (the "GPL"), or 25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 26 * in which case the provisions of the GPL or the LGPL are applicable instead 27 * of those above. If you wish to allow use of your version of this file only 28 * under the terms of either the GPL or the LGPL, and not to allow others to 29 * use your version of this file under the terms of the MPL, indicate your 30 * decision by deleting the provisions above and replace them with the notice 31 * and other provisions required by the GPL or the LGPL. If you do not delete 32 * the provisions above, a recipient may use your version of this file under 33 * the terms of any one of the MPL, the GPL or the LGPL. 34 * 35 * ***** END LICENSE BLOCK ***** */ 36 37 if (!com) var com = {}; // A generic wrapper variable 38 // A wrapper for all GCS functions and variables 39 if (!com.gContactSync) com.gContactSync = {}; 40 41 /** 42 * A class for storing and editing the XML feed for a Group in Google Contacts. 43 * @param aXml {XML Element} The XML representation of the group. 44 * If not supplied then a new group is created. 45 * @param aTitle {string} The title for the group, if new. 46 * @class 47 * @constructor 48 */ 49 com.gContactSync.Group = function gCS_Group(aXml, aTitle) { 50 if (!aXml) { 51 if (!aTitle) { 52 throw "Error - No title or XML passed to the Group constructor"; 53 } 54 var atom = com.gContactSync.gdata.namespaces.ATOM, 55 gd = com.gContactSync.gdata.namespaces.GD, 56 gcontact = com.gContactSync.gdata.namespaces.GCONTACT, 57 xml = document.createElementNS(atom.url, atom.prefix + "entry"), 58 category = document.createElementNS(atom.url, atom.prefix + "category"), 59 title = document.createElementNS(atom.url, atom.prefix + "title"), 60 text = document.createTextNode(aTitle); 61 category.setAttribute("scheme", gd.url + "/#kind"); 62 category.setAttribute("term", gcontact.url + "/#group"); 63 xml.appendChild(category); 64 title.appendChild(text); 65 xml.appendChild(title); 66 this.xml = xml; 67 this.mTitle = aTitle; 68 } 69 else { 70 this.xml = aXml; 71 this.mTitle = this.getTitle(); 72 } 73 }; 74 75 com.gContactSync.Group.prototype = { 76 /** 77 * Sets the title of this Group. 78 * @param aTitle The new title for this Group. 79 */ 80 setTitle: function Group_setTitle(aTitle) { 81 if (!aTitle) { 82 throw "Error - invalid title passed to Group.setTitle"; 83 } 84 85 var atom = com.gContactSync.gdata.namespaces.ATOM, 86 title = this.xml.getElementsByTagNameNS(atom.url, "title")[0], 87 text; 88 if (title && title.value && title.value.indexOf("System Group") !== -1) { 89 return; // cannot rename system groups 90 } 91 this.mTitle = aTitle; 92 if (title) { 93 if (title.childNodes[0]) { 94 title.childNodes[0].nodeValue = aTitle; 95 } 96 else { 97 text = document.createTextNode(aTitle); 98 title.appendChild(text); 99 } 100 } 101 else { 102 title = document.createElementNS(atom.url, atom.prefix + "title"); 103 text = document.createTextNode(aTitle); 104 title.appendChild(text); 105 this.xml.appendChild(title); 106 } 107 }, 108 /** 109 * Returns the title of this Group. If this is a system group, which is NOT 110 * translated through the API, then this method will return a localized name 111 * for this group. 112 * @returns {string} The title of this Group. 113 */ 114 getTitle: function Group_getTitle() { 115 if (this.mTitle) { 116 return this.mTitle; 117 } 118 // System Groups aren't localized through the API, so this will find the 119 // system group's ID (Contact, Coworker, Family, or Friend) and return the 120 // localized version of that group 121 if (this.isSystemGroup()) { 122 var elem = this.xml.getElementsByTagNameNS(com.gContactSync.gdata.namespaces.GCONTACT.url, 123 "systemGroup")[0], 124 id = elem ? elem.getAttribute("id") : null; 125 if (id) { 126 this.mTitle = com.gContactSync.StringBundle.getStr(id); 127 if (this.mTitle) { 128 return this.mTitle; 129 } 130 } 131 } 132 var atom = com.gContactSync.gdata.namespaces.ATOM, 133 title = this.xml.getElementsByTagNameNS(atom.url, "title")[0]; 134 if (title && title.childNodes[0]) { 135 this.mTitle = title.childNodes[0].nodeValue ? 136 title.childNodes[0].nodeValue.replace("System Group: ", "") : null; 137 return this.mTitle; 138 } 139 return null; 140 }, 141 /** 142 * Returns the URL used to edit this Group. 143 * @returns {string} the URL used to edit this Group. 144 */ 145 getEditURL: function Group_getEditURL() { 146 var atom = com.gContactSync.gdata.namespaces.ATOM; 147 var arr = this.xml.getElementsByTagNameNS(atom.url, "link"), 148 i = 0, 149 length = arr.length; 150 for (; i < length; i++) { 151 if (arr[i].getAttribute("rel") === com.gContactSync.gdata.contacts.links.EditURL) { 152 return arr[i].getAttribute("href"); 153 } 154 } 155 return null; 156 }, 157 /** 158 * Retrieves and returns the ID of this Group. 159 * @returns {string} The ID of this Group. 160 */ 161 getID: function Group_getID() { 162 var atom = com.gContactSync.gdata.namespaces.ATOM, 163 id = this.xml.getElementsByTagNameNS(atom.url, "id")[0]; 164 if (id && id.childNodes[0]) { 165 return com.gContactSync.fixURL(id.childNodes[0].nodeValue); 166 } 167 return null; 168 }, 169 /** 170 * Removes all of the extended properties from this Group. 171 */ 172 removeExtendedProperties: function Group_removeExtendedProperties() { 173 var arr = this.xml.getElementsByTagNameNS(com.gContactSync.gdata.namespaces.GD.url, "extendedProperty"), 174 i = arr.length - 1; 175 for (; i > -1 ; i--) { 176 this.xml.removeChild(arr[i]); 177 } 178 }, 179 /** 180 * Returns the extended property of this group's XML whose value for the 181 * name attribute matches aName, if any. 182 * @param aName {string} The value of the name attribute to find. 183 * @returns {string} The value of an extended property whose name is the value of aName. 184 */ 185 getExtendedProperty: function Group_getExtendedProperty(aName) { 186 var arr = this.xml.getElementsByTagNameNS(com.gContactSync.gdata.namespaces.GD.url, "extendedProperty"), 187 i = 0, 188 length = arr.length; 189 for (; i < length; i++) { 190 if (arr[i].getAttribute("name") === aName) { 191 return arr[i].getAttribute("value"); 192 } 193 } 194 return null; 195 }, 196 /** 197 * Gets the last modified date from the group's XML feed in milliseconds since 198 * 1970 199 * @returns {int} The last modified date of the group in milliseconds since 200 * 1970. 201 */ 202 getLastModifiedDate: function Group_getLastModifiedDate() { 203 try { 204 var sModified = this.xml.getElementsByTagName('updated')[0].childNodes[0].nodeValue, 205 year = sModified.substring(0, 4), 206 month = sModified.substring(5, 7), 207 day = sModified.substring(8, 10), 208 hrs = sModified.substring(11, 13), 209 mins = sModified.substring(14, 16), 210 sec = sModified.substring(17, 19), 211 ms = sModified.substring(20, 23); 212 return parseInt(Date.UTC(year, parseInt(month, 10) - 1, day, hrs, mins, sec, ms), 10); 213 } 214 catch (e) { 215 com.gContactSync.LOGGER.LOG_WARNING("Unable to get last modified date from a group:\n" + e); 216 } 217 return 0; 218 }, 219 /** 220 * Sets an extended property with the given name and value if there are less 221 * than 10 existing. Logs a warning if there are already 10 or more and does 222 * not add the property. 223 * @param aName {string} The name of the property. 224 * @param aValue {string} The value of the property. 225 */ 226 setExtendedProperty: function Group_setExtendedProperty(aName, aValue) { 227 if (this.xml.getElementsByTagNameNS(com.gContactSync.gdata.namespaces.GD.url, 228 "extendedProperty").length >= 10) { 229 com.gContactSync.LOGGER.LOG_WARNING("Attempt to add too many properties aborted"); 230 return; 231 } 232 if (aValue && aValue !== "") { 233 var property = document.createElementNS(com.gContactSync.gdata.namespaces.GD.url, 234 "extendedProperty"); 235 property.setAttribute("name", aName); 236 property.setAttribute("value", aValue); 237 this.xml.appendChild(property); 238 } 239 }, 240 /** 241 * Returns true if this group is one of Google's system groups. 242 * These currently are: 243 * - My Contacts 244 * - Coworkers 245 * - Family 246 * - Friends 247 * @returns {boolean} True if this group is a system group. 248 */ 249 isSystemGroup: function Group_isSystemGroup() { 250 var nodes = this.xml.getElementsByTagNameNS(com.gContactSync.gdata.namespaces.GCONTACT.url, 251 "systemGroup"); 252 return nodes && nodes.length > 0; 253 }, 254 /** 255 * Returns the ID of the gContact:systemGroup tag, if any. 256 * @returns {string} The ID of the system group, if any. 257 */ 258 getSystemId: function Group_getSystemId() { 259 var nodes = this.xml.getElementsByTagNameNS(com.gContactSync.gdata.namespaces.GCONTACT.url, 260 "systemGroup"); 261 if (!nodes || !nodes.length || !nodes[0]) return null; 262 return nodes[0].getAttribute("id"); 263 } 264 }; 265