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.notification;
025
026import microsoft.exchange.webservices.data.core.EwsServiceXmlReader;
027import microsoft.exchange.webservices.data.core.ILazyMember;
028import microsoft.exchange.webservices.data.core.LazyMember;
029import microsoft.exchange.webservices.data.core.XmlElementNames;
030import microsoft.exchange.webservices.data.core.enumeration.notification.EventType;
031import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace;
032
033import java.util.ArrayList;
034import java.util.Collection;
035import java.util.Date;
036import java.util.HashMap;
037import java.util.Map;
038
039/**
040 * Represents a collection of notification events.
041 */
042public final class GetEventsResults {
043  /**
044   * Watermark in event.
045   */
046  private String newWatermark;
047
048  /**
049   * Subscription id.
050   */
051  private String subscriptionId;
052
053  /**
054   * Previous watermark.
055   */
056  private String previousWatermark;
057
058  /**
059   * True if more events available for this subscription.
060   */
061  private boolean moreEventsAvailable;
062
063  /**
064   * Collection of notification events.
065   */
066  private Collection<NotificationEvent> events =
067      new ArrayList<NotificationEvent>();
068
069  /**
070   * Map XML element name to notification event type. If you add a new
071   * notification event type, you'll need to add a new entry to the Map here.
072   */
073  private static LazyMember<Map<String, EventType>>
074      xmlElementNameToEventTypeMap =
075      new LazyMember<Map<String, EventType>>(
076          new ILazyMember<Map<String, EventType>>() {
077            @Override
078            public Map<String, EventType> createInstance() {
079              Map<String, EventType> result =
080                  new HashMap<String, EventType>();
081              result.put(XmlElementNames.CopiedEvent, EventType.Copied);
082              result.put(XmlElementNames.CreatedEvent, EventType.Created);
083              result.put(XmlElementNames.DeletedEvent, EventType.Deleted);
084              result.put(XmlElementNames.ModifiedEvent,
085                  EventType.Modified);
086              result.put(XmlElementNames.MovedEvent, EventType.Moved);
087              result.put(XmlElementNames.NewMailEvent, EventType.NewMail);
088              result.put(XmlElementNames.StatusEvent, EventType.Status);
089              result.put(XmlElementNames.FreeBusyChangedEvent,
090                  EventType.FreeBusyChanged);
091              return result;
092            }
093          });
094
095  /**
096   * Gets the XML element name to event type mapping.
097   *
098   * @return The XML element name to event type mapping.
099   */
100  protected static Map<String, EventType> getXmlElementNameToEventTypeMap() {
101    return GetEventsResults.xmlElementNameToEventTypeMap.getMember();
102  }
103
104  /**
105   * Initializes a new instance.
106   */
107  public GetEventsResults() {
108  }
109
110  /**
111   * Loads from XML.
112   *
113   * @param reader the reader
114   * @throws Exception the exception
115   */
116  public void loadFromXml(EwsServiceXmlReader reader) throws Exception {
117    reader.readStartElement(XmlNamespace.Messages,
118        XmlElementNames.Notification);
119
120    this.subscriptionId = reader.readElementValue(XmlNamespace.Types,
121        XmlElementNames.SubscriptionId);
122    this.previousWatermark = reader.readElementValue(XmlNamespace.Types,
123        XmlElementNames.PreviousWatermark);
124    this.moreEventsAvailable = reader.readElementValue(Boolean.class,
125        XmlNamespace.Types, XmlElementNames.MoreEvents);
126
127    do {
128      reader.read();
129
130      if (reader.isStartElement()) {
131        String eventElementName = reader.getLocalName();
132        EventType eventType;
133
134        if (xmlElementNameToEventTypeMap.getMember().containsKey(
135            eventElementName)) {
136          eventType = xmlElementNameToEventTypeMap.getMember().get(
137              eventElementName);
138          this.newWatermark = reader.readElementValue(
139              XmlNamespace.Types, XmlElementNames.Watermark);
140          if (eventType == EventType.Status) {
141            // We don't need to return status events
142            reader.readEndElementIfNecessary(XmlNamespace.Types,
143                eventElementName);
144          } else {
145            this.loadNotificationEventFromXml(reader,
146                eventElementName, eventType);
147          }
148        } else {
149          reader.skipCurrentElement();
150        }
151
152      }
153
154    } while (!reader.isEndElement(XmlNamespace.Messages,
155        XmlElementNames.Notification));
156  }
157
158  /**
159   * Loads a notification event from XML.
160   *
161   * @param reader           the reader
162   * @param eventElementName the event element name
163   * @param eventType        the event type
164   * @throws Exception the exception
165   */
166  private void loadNotificationEventFromXml(EwsServiceXmlReader reader,
167      String eventElementName, EventType eventType) throws Exception {
168    Date date = reader.readElementValue(Date.class, XmlNamespace.Types,
169        XmlElementNames.TimeStamp);
170
171    NotificationEvent notificationEvent;
172
173    reader.read();
174
175    if (reader.getLocalName().equals(XmlElementNames.FolderId)) {
176      notificationEvent = new FolderEvent(eventType, date);
177    } else {
178      notificationEvent = new ItemEvent(eventType, date);
179    }
180
181    notificationEvent.loadFromXml(reader, eventElementName);
182    this.events.add(notificationEvent);
183  }
184
185  /**
186   * Gets the Id of the subscription the collection is associated with.
187   *
188   * @return the subscription id
189   */
190  protected String getSubscriptionId() {
191    return subscriptionId;
192  }
193
194  /**
195   * Gets the subscription's previous watermark.
196   *
197   * @return the previous watermark
198   */
199  protected String getPreviousWatermark() {
200    return previousWatermark;
201  }
202
203  /**
204   * Gets the subscription's new watermark.
205   *
206   * @return the new watermark
207   */
208  protected String getNewWatermark() {
209    return newWatermark;
210  }
211
212  /**
213   * Gets a value indicating whether more events are available on the Exchange
214   * server.
215   *
216   * @return true, if is more events available
217   */
218  protected boolean isMoreEventsAvailable() {
219    return moreEventsAvailable;
220  }
221
222  /**
223   * Gets the collection of folder events.
224   *
225   * @return the folder events
226   */
227  public Iterable<FolderEvent> getFolderEvents() {
228    Collection<FolderEvent> folderEvents = new ArrayList<FolderEvent>();
229    for (Object event : this.events) {
230      if (event instanceof FolderEvent) {
231        folderEvents.add((FolderEvent) event);
232      }
233    }
234    return folderEvents;
235  }
236
237  /**
238   * Gets the collection of item events.
239   *
240   * @return the item events
241   */
242  public Iterable<ItemEvent> getItemEvents() {
243    Collection<ItemEvent> itemEvents = new ArrayList<ItemEvent>();
244    for (Object event : this.events) {
245      if (event instanceof ItemEvent) {
246        itemEvents.add((ItemEvent) event);
247      }
248    }
249    return itemEvents;
250  }
251
252  /**
253   * Gets the collection of all events.
254   *
255   * @return the all events
256   */
257  public Collection<NotificationEvent> getAllEvents() {
258    return this.events;
259  }
260}