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
024 package microsoft.exchange.webservices.data.property.complex;
025
026 import microsoft.exchange.webservices.data.core.EwsServiceXmlReader;
027 import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter;
028 import microsoft.exchange.webservices.data.core.XmlElementNames;
029 import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace;
030 import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlDeserializationException;
031 import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlSerializationException;
032
033 import javax.xml.stream.XMLStreamException;
034
035 import java.util.ArrayList;
036 import java.util.Iterator;
037 import java.util.List;
038
039 /**
040 * Represents a list of strings.
041 */
042 public 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 }