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.core.response; 025 026import microsoft.exchange.webservices.data.attribute.EditorBrowsable; 027import microsoft.exchange.webservices.data.core.EwsServiceXmlReader; 028import microsoft.exchange.webservices.data.core.EwsUtilities; 029import microsoft.exchange.webservices.data.core.PropertySet; 030import microsoft.exchange.webservices.data.core.XmlElementNames; 031import microsoft.exchange.webservices.data.core.service.ServiceObject; 032import microsoft.exchange.webservices.data.core.enumeration.sync.ChangeType; 033import microsoft.exchange.webservices.data.core.enumeration.attribute.EditorBrowsableState; 034import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace; 035import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException; 036import microsoft.exchange.webservices.data.sync.Change; 037import microsoft.exchange.webservices.data.sync.ChangeCollection; 038import 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) 047public 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}