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.core.response;
025
026 import microsoft.exchange.webservices.data.attribute.EditorBrowsable;
027 import microsoft.exchange.webservices.data.core.EwsServiceXmlReader;
028 import microsoft.exchange.webservices.data.core.EwsUtilities;
029 import microsoft.exchange.webservices.data.core.PropertySet;
030 import microsoft.exchange.webservices.data.core.XmlElementNames;
031 import microsoft.exchange.webservices.data.core.service.ServiceObject;
032 import microsoft.exchange.webservices.data.core.enumeration.sync.ChangeType;
033 import microsoft.exchange.webservices.data.core.enumeration.attribute.EditorBrowsableState;
034 import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace;
035 import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
036 import microsoft.exchange.webservices.data.sync.Change;
037 import microsoft.exchange.webservices.data.sync.ChangeCollection;
038 import microsoft.exchange.webservices.data.sync.ItemChange;
039
040 /**
041 * Represents the base response class for synchronuization operations.
042 *
043 * @param <TServiceObject> ServiceObject type.
044 * @param <TChange> Change type.
045 */
046 @EditorBrowsable(state = EditorBrowsableState.Never)
047 public abstract class SyncResponse<TServiceObject extends ServiceObject,
048 TChange extends Change> extends ServiceResponse {
049
050 /**
051 * The changes.
052 */
053 private ChangeCollection<TChange> changes = new ChangeCollection<TChange>();
054
055 /**
056 * The property set.
057 */
058 private PropertySet propertySet;
059
060 /**
061 * Initializes a new instance of the class.
062 *
063 * @param propertySet the property set
064 */
065 protected SyncResponse(PropertySet propertySet) {
066 super();
067 this.propertySet = propertySet;
068 EwsUtilities.ewsAssert(this.propertySet != null, "SyncResponse.ctor", "PropertySet should not be null");
069 }
070
071 /**
072 * Gets the name of the includes last in range XML element.
073 *
074 * @return XML element name.
075 */
076 protected abstract String getIncludesLastInRangeXmlElementName();
077
078 /**
079 * Creates the change instance.
080 *
081 * @return TChange instance
082 */
083 protected abstract TChange createChangeInstance();
084
085 /**
086 * Reads response elements from XML.
087 *
088 * @param reader the reader
089 * @throws ServiceLocalException the service local exception
090 * @throws Exception the exception
091 */
092 @Override
093 protected void readElementsFromXml(EwsServiceXmlReader reader)
094 throws ServiceLocalException, Exception {
095 this.changes.setSyncState(reader.readElementValue(
096 XmlNamespace.Messages, XmlElementNames.SyncState));
097 this.changes.setMoreChangesAvailable(!reader.readElementValue(
098 Boolean.class, XmlNamespace.Messages, this
099 .getIncludesLastInRangeXmlElementName()));
100
101 reader.readStartElement(XmlNamespace.Messages, XmlElementNames.Changes);
102 if (!reader.isEmptyElement()) {
103 do {
104 reader.read();
105
106 if (reader.isStartElement()) {
107 TChange change = this.createChangeInstance();
108
109 if (reader.getLocalName().equals(XmlElementNames.Create)) {
110 change.setChangeType(ChangeType.Create);
111 } else if (reader.getLocalName().equals(
112 XmlElementNames.Update)) {
113 change.setChangeType(ChangeType.Update);
114 } else if (reader.getLocalName().equals(
115 XmlElementNames.Delete)) {
116 change.setChangeType(ChangeType.Delete);
117 } else if (reader.getLocalName().equals(
118 XmlElementNames.ReadFlagChange)) {
119 change.setChangeType(ChangeType.ReadFlagChange);
120 } else {
121 reader.skipCurrentElement();
122 }
123
124 if (change != null) {
125 reader.read();
126 reader.ensureCurrentNodeIsStartElement();
127
128 if (change.getChangeType().equals(ChangeType.Delete)
129 || change.getChangeType().equals(
130 ChangeType.ReadFlagChange)) {
131 change.setId(change.createId());
132 change.getId().loadFromXml(reader,
133 change.getId().getXmlElementName());
134
135 if (change.getChangeType().equals(
136 ChangeType.ReadFlagChange)) {
137 reader.read();
138 reader.ensureCurrentNodeIsStartElement();
139 ItemChange itemChange = null;
140 if (change instanceof ItemChange) {
141 itemChange = (ItemChange) change;
142 }
143 EwsUtilities
144 .ewsAssert(itemChange != null, "SyncResponse." + "ReadElementsFromXml",
145 "ReadFlagChange is only " + "valid on ItemChange");
146
147 itemChange.setIsRead(reader.readElementValue(
148 Boolean.class, XmlNamespace.Types,
149 XmlElementNames.IsRead));
150 }
151 } else {
152
153 change.setServiceObject(EwsUtilities
154 .createEwsObjectFromXmlElementName(null,
155 reader.getService(), reader
156 .getLocalName()));
157
158 change.getServiceObject().loadFromXml(reader,
159 true, /* clearPropertyBag */
160 this.propertySet, this.getSummaryPropertiesOnly());
161 }
162
163 reader.readEndElementIfNecessary(XmlNamespace.Types,
164 change.getChangeType().toString());
165
166 this.changes.add(change);
167 }
168 }
169 } while (!reader.isEndElement(XmlNamespace.Messages,
170 XmlElementNames.Changes));
171 } else {
172 reader.read();
173 }
174 }
175
176 /**
177 * Gets a list of changes that occurred on the synchronized folder.
178 *
179 * @return the changes
180 */
181 public ChangeCollection<TChange> getChanges() {
182 return this.changes;
183 }
184
185 /**
186 * Gets a value indicating whether this request returns full or summary
187 * property.
188 *
189 * @return the summary property only
190 */
191 protected abstract boolean getSummaryPropertiesOnly();
192
193 }