001/* 002 * The MIT License 003 * Copyright (c) 2012 Microsoft Corporation 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining a copy 006 * of this software and associated documentation files (the "Software"), to deal 007 * in the Software without restriction, including without limitation the rights 008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 009 * copies of the Software, and to permit persons to whom the Software is 010 * furnished to do so, subject to the following conditions: 011 * 012 * The above copyright notice and this permission notice shall be included in 013 * all copies or substantial portions of the Software. 014 * 015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 021 * THE SOFTWARE. 022 */ 023 024package microsoft.exchange.webservices.data.property.complex; 025 026import microsoft.exchange.webservices.data.core.EwsServiceXmlReader; 027import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter; 028import microsoft.exchange.webservices.data.core.XmlElementNames; 029import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace; 030import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlDeserializationException; 031import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlSerializationException; 032 033import javax.xml.stream.XMLStreamException; 034 035import java.util.ArrayList; 036import java.util.Iterator; 037import java.util.List; 038 039/** 040 * Represents a list of strings. 041 */ 042public class StringList extends ComplexProperty implements Iterable<String> { 043 044 /** 045 * The item. 046 */ 047 private List<String> items = new ArrayList<String>(); 048 049 /** 050 * The item xml element name. 051 */ 052 private String itemXmlElementName = XmlElementNames.String; 053 054 /** 055 * Initializes a new instance of the "StringList" class. 056 */ 057 public StringList() { 058 } 059 060 /** 061 * Initializes a new instance of the <see cref="StringList"/> class. 062 * 063 * @param strings The strings. 064 */ 065 public StringList(Iterable<String> strings) { 066 this.addRange(strings); 067 } 068 069 /** 070 * Initializes a new instance of the "StringList" class. 071 * 072 * @param itemXmlElementName Name of the item XML element. 073 */ 074 public StringList(String itemXmlElementName) { 075 this.itemXmlElementName = itemXmlElementName; 076 } 077 078 /** 079 * Tries to read element from XML. 080 * 081 * @param reader accepts EwsServiceXmlReader 082 * @return True if element was read 083 * @throws XMLStreamException the XML stream exception 084 * @throws ServiceXmlDeserializationException the service xml deserialization exception 085 */ 086 @Override 087 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 088 throws XMLStreamException, ServiceXmlDeserializationException { 089 boolean returnValue = false; 090 if (reader.getLocalName().equals(this.itemXmlElementName)) { 091 if (!reader.isEmptyElement()) { 092 this.add(reader.readValue()); 093 returnValue = true; 094 } else { 095 reader.read(); 096 097 returnValue = true; 098 } 099 100 } 101 return returnValue; 102 } 103 104 /** 105 * Writes elements to XML. 106 * 107 * @param writer accepts EwsServiceXmlWriter 108 * @throws ServiceXmlSerializationException the service xml serialization exception 109 * @throws XMLStreamException the XML stream exception 110 */ 111 @Override 112 public void writeElementsToXml(EwsServiceXmlWriter writer) 113 throws ServiceXmlSerializationException, XMLStreamException { 114 for (String item : this.items) { 115 writer.writeStartElement(XmlNamespace.Types, 116 this.itemXmlElementName); 117 writer.writeValue(item, this.itemXmlElementName); 118 writer.writeEndElement(); 119 } 120 } 121 122 /** 123 * Adds a string to the list. 124 * 125 * @param s The string to add. 126 */ 127 public void add(String s) { 128 this.items.add(s); 129 this.changed(); 130 } 131 132 /** 133 * Adds multiple strings to the list. 134 * 135 * @param strings The strings to add. 136 */ 137 public void addRange(Iterable<String> strings) { 138 boolean changed = false; 139 140 for (String s : strings) { 141 if (!this.contains(s)) { 142 this.items.add(s); 143 changed = true; 144 } 145 } 146 if (changed) { 147 this.changed(); 148 } 149 } 150 151 /** 152 * Determines whether the list contains a specific string. 153 * 154 * @param s The string to check the presence of. 155 * @return True if s is present in the list, false otherwise. 156 */ 157 public boolean contains(String s) { 158 return this.items.contains(s); 159 } 160 161 /** 162 * Removes a string from the list. 163 * 164 * @param s The string to remove. 165 * @return True is s was removed, false otherwise. 166 */ 167 public boolean remove(String s) { 168 boolean result = this.items.remove(s); 169 if (result) { 170 this.changed(); 171 } 172 return result; 173 } 174 175 /** 176 * Removes the string at the specified position from the list. 177 * 178 * @param index The index of the string to remove. 179 */ 180 public void removeAt(int index) { 181 if (index < 0 || index >= this.getSize()) { 182 throw new ArrayIndexOutOfBoundsException("index is out of range."); 183 } 184 this.items.remove(index); 185 this.changed(); 186 } 187 188 /** 189 * Clears the list. 190 */ 191 public void clearList() { 192 this.items.clear(); 193 this.changed(); 194 } 195 196 /** 197 * Returns a string representation of the object. In general, the 198 * <code>toString</code> method returns a string that "textually represents" 199 * this object. The result should be a concise but informative 200 * representation that is easy for a person to read. It is recommended that 201 * all subclasses override this method. 202 * <p/> 203 * The <code>toString</code> method for class <code>Object</code> returns a 204 * string consisting of the name of the class of which the object is an 205 * instance, the at-sign character `<code>@</code>', and the unsigned 206 * hexadecimal representation of the hash code of the object. In other 207 * words, this method returns a string equal to the value of: <blockquote> 208 * <p/> 209 * <pre> 210 * getClass().getName() + '@' + Integer.toHexString(hashCode()) 211 * </pre> 212 * <p/> 213 * </blockquote> 214 * 215 * @return a string representation of the object. 216 */ 217 @Override 218 public String toString() { 219 StringBuffer temp = new StringBuffer(); 220 for (String str : this.items) { 221 temp.append(str.concat(",")); 222 } 223 String tempString = temp.toString(); 224 return tempString; 225 } 226 227 /** 228 * Gets the number of strings in the list. 229 * 230 * @return the size 231 */ 232 public int getSize() { 233 return this.items.size(); 234 } 235 236 /** 237 * Gets the string at the specified index. 238 * 239 * @param index The index of the string to get or set. 240 * @return The string at the specified index. 241 */ 242 public String getString(int index) { 243 if (index < 0 || index >= this.getSize()) { 244 throw new ArrayIndexOutOfBoundsException("index is out of range."); 245 } 246 return this.items.get(index); 247 } 248 249 /** 250 * Sets the string at the specified index. 251 * 252 * @param index The index 253 * @param object The object. 254 */ 255 public void setString(int index, Object object) { 256 if (index < 0 || index >= this.getSize()) { 257 throw new ArrayIndexOutOfBoundsException("index is out of range."); 258 } 259 260 if (this.items.get(index) != object) { 261 this.items.set(index, (String) object); 262 this.changed(); 263 } 264 } 265 266 /** 267 * Gets an iterator that iterates through the elements of the collection. 268 * 269 * @return An Iterator for the collection. 270 */ 271 public Iterator<String> getIterator() { 272 return this.items.iterator(); 273 } 274 275 /** 276 * Indicates whether some other object is "equal to" this one. 277 * <p/> 278 * The <code>equals</code> method implements an equivalence relation on 279 * non-null object references: 280 * <ul> 281 * <li>It is <i>reflexive</i>: for any non-null reference value 282 * <code>x</code>, <code>x.equals(x)</code> should return <code>true</code>. 283 * <li>It is <i>symmetric</i>: for any non-null reference values 284 * <code>x</code> and <code>y</code>, <code>x.equals(y)</code> should return 285 * <code>true</code> if and only if <code>y.equals(x)</code> returns 286 * <code>true</code>. 287 * <li>It is <i>transitive</i>: for any non-null reference values 288 * <code>x</code>, <code>y</code>, and <code>z</code>, if 289 * <code>x.equals(y)</code> returns <code>true</code> and 290 * <code>y.equals(z)</code> returns <code>true</code>, then 291 * <code>x.equals(z)</code> should return <code>true</code>. 292 * <li>It is <i>consistent</i>: for any non-null reference values 293 * <code>x</code> and <code>y</code>, multiple invocations of 294 * <tt>x.equals(y)</tt> consistently return <code>true</code> or 295 * consistently return <code>false</code>, provided no information used in 296 * <code>equals</code> comparisons on the objects is modified. 297 * <li>For any non-null reference value <code>x</code>, 298 * <code>x.equals(null)</code> should return <code>false</code>. 299 * </ul> 300 * <p/> 301 * The <tt>equals</tt> method for class <code>Object</code> implements the 302 * most discriminating possible equivalence relation on objects; that is, 303 * for any non-null reference values <code>x</code> and <code>y</code>, this 304 * method returns <code>true</code> if and only if <code>x</code> and 305 * <code>y</code> refer to the same object (<code>x == y</code> has the 306 * value <code>true</code>). 307 * <p/> 308 * Note that it is generally necessary to override the <tt>hashCode</tt> 309 * method whenever this method is overridden, so as to maintain the general 310 * contract for the <tt>hashCode</tt> method, which states that equal 311 * objects must have equal hash codes. 312 * 313 * @param obj the reference object with which to compare. 314 * @return if this object is the same as the obj argument; otherwise. 315 * @see #hashCode() 316 * @see java.util.Hashtable 317 */ 318 @Override 319 public boolean equals(Object obj) { 320 if (obj instanceof StringList) { 321 StringList other = (StringList) obj; 322 return this.toString().equals(other.toString()); 323 } else { 324 return false; 325 } 326 } 327 328 /** 329 * Serves as a hash function for a particular type. 330 * 331 * @return A hash code for the current "T:System.Object". 332 */ 333 @Override 334 public int hashCode() { 335 return this.toString().hashCode(); 336 } 337 338 /** 339 * Returns an iterator over a set of elements of type T. 340 * 341 * @return an Iterator. 342 */ 343 @Override 344 public Iterator<String> iterator() { 345 return items.iterator(); 346 } 347}