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.notification;
025    
026    import microsoft.exchange.webservices.data.core.EwsServiceXmlReader;
027    import microsoft.exchange.webservices.data.core.ILazyMember;
028    import microsoft.exchange.webservices.data.core.LazyMember;
029    import microsoft.exchange.webservices.data.core.XmlElementNames;
030    import microsoft.exchange.webservices.data.core.enumeration.notification.EventType;
031    import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace;
032    
033    import java.util.ArrayList;
034    import java.util.Collection;
035    import java.util.Date;
036    import java.util.HashMap;
037    import java.util.Map;
038    
039    /**
040     * Represents a collection of notification events.
041     */
042    public 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    }