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.EwsUtilities;
029 import microsoft.exchange.webservices.data.core.XmlAttributeNames;
030 import microsoft.exchange.webservices.data.core.XmlElementNames;
031 import microsoft.exchange.webservices.data.core.exception.service.local.ServiceValidationException;
032 import microsoft.exchange.webservices.data.core.service.item.Item;
033 import microsoft.exchange.webservices.data.core.enumeration.property.BodyType;
034 import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
035 import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace;
036 import microsoft.exchange.webservices.data.core.exception.service.local.ServiceVersionException;
037 import microsoft.exchange.webservices.data.property.definition.PropertyDefinitionBase;
038 import org.apache.commons.logging.Log;
039 import org.apache.commons.logging.LogFactory;
040
041 import java.util.Date;
042
043 /**
044 * Represents an attachment to an item.
045 */
046 public abstract class Attachment extends ComplexProperty {
047
048 private static final Log LOG = LogFactory.getLog(Attachment.class);
049
050 /**
051 * The owner.
052 */
053 private Item owner;
054
055 /**
056 * The id.
057 */
058 private String id;
059
060 /**
061 * The name.
062 */
063 private String name;
064
065 /**
066 * The content type.
067 */
068 private String contentType;
069
070 /**
071 * The content id.
072 */
073 private String contentId;
074
075 /**
076 * The content location.
077 */
078 private String contentLocation;
079
080 /**
081 * The size.
082 */
083 private int size;
084
085 /**
086 * The last modified time.
087 */
088 private Date lastModifiedTime;
089
090 /**
091 * The is inline.
092 */
093 private boolean isInline;
094
095 /**
096 * Initializes a new instance.
097 *
098 * @param owner The owner.
099 */
100 protected Attachment(Item owner) {
101 this.owner = owner;
102 }
103
104 /**
105 * Throws exception if this is not a new service object.
106 */
107 protected void throwIfThisIsNotNew() {
108 if (!this.isNew()) {
109 throw new UnsupportedOperationException("Attachments can't be updated.");
110 }
111 }
112
113 /**
114 * Sets value of field.
115 * <p/>
116 * We override the base implementation. Attachments cannot be modified so
117 * any attempts the change a property on an existing attachment is an error.
118 *
119 * @param <T> the generic type
120 * @param field The field
121 * @param value The value.
122 * @return true, if successful
123 */
124 public <T> boolean canSetFieldValue(T field, T value) {
125 this.throwIfThisIsNotNew();
126 return super.canSetFieldValue(field, value);
127 }
128
129 /**
130 * Gets the Id of the attachment.
131 *
132 * @return the id
133 */
134 public String getId() {
135 return this.id;
136 }
137
138 /**
139 * Gets the name of the attachment.
140 *
141 * @return the name
142 */
143 public String getName() {
144 return this.name;
145 }
146
147 /**
148 * Sets the name.
149 *
150 * @param value the new name
151 */
152 public void setName(String value) {
153 if (this.canSetFieldValue(this.name, value)) {
154 this.name = value;
155 this.changed();
156 }
157 }
158
159 /**
160 * Gets the content type of the attachment.
161 *
162 * @return the content type
163 */
164 public String getContentType() {
165 return this.contentType;
166 }
167
168 /**
169 * Sets the content type.
170 *
171 * @param value the new content type
172 */
173 public void setContentType(String value) {
174 if (this.canSetFieldValue(this.contentType, value)) {
175 this.contentType = value;
176 this.changed();
177 }
178 }
179
180 /**
181 * Gets the content Id of the attachment. ContentId can be used as a
182 * custom way to identify an attachment in order to reference it from within
183 * the body of the item the attachment belongs to.
184 *
185 * @return the content id
186 */
187 public String getContentId() {
188 return this.contentId;
189 }
190
191 /**
192 * Sets the content id.
193 *
194 * @param value the new content id
195 */
196 public void setContentId(String value) {
197 if (this.canSetFieldValue(this.contentId, value)) {
198 this.contentId = value;
199 this.changed();
200 }
201 }
202
203 /**
204 * Gets the content location of the attachment. ContentLocation can
205 * be used to associate an attachment with a Url defining its location on
206 * the Web.
207 *
208 * @return the content location
209 */
210 public String getContentLocation() {
211 return this.contentLocation;
212 }
213
214 /**
215 * Sets the content location.
216 *
217 * @param value the new content location
218 */
219 public void setContentLocation(String value) {
220 if (this.canSetFieldValue(this.contentLocation, value)) {
221 this.contentLocation = value;
222 this.changed();
223 }
224 }
225
226 /**
227 * Gets the size of the attachment.
228 *
229 * @return the size
230 * @throws ServiceVersionException throws ServiceVersionException
231 */
232 public int getSize() throws ServiceVersionException {
233 EwsUtilities.validatePropertyVersion(this.getOwner().getService(), ExchangeVersion.Exchange2010, "Size");
234 return this.size;
235 }
236
237 /**
238 * Gets the date and time when this attachment was last modified.
239 *
240 * @return the last modified time
241 * @throws ServiceVersionException the service version exception
242 */
243 public Date getLastModifiedTime() throws ServiceVersionException {
244
245 EwsUtilities.validatePropertyVersion(this.getOwner().getService(),
246 ExchangeVersion.Exchange2010, "LastModifiedTime");
247
248 return this.lastModifiedTime;
249
250 }
251
252 /**
253 * Gets a value indicating whether this is an inline attachment.
254 * Inline attachments are not visible to end users.
255 *
256 * @return the checks if is inline
257 * @throws ServiceVersionException the service version exception
258 */
259 public boolean getIsInline() throws ServiceVersionException {
260 EwsUtilities.validatePropertyVersion(this.getOwner().getService(),
261 ExchangeVersion.Exchange2010, "IsInline");
262 return this.isInline;
263
264 }
265
266 /**
267 * Sets the checks if is inline.
268 *
269 * @param value the new checks if is inline
270 * @throws ServiceVersionException the service version exception
271 */
272 public void setIsInline(boolean value) throws ServiceVersionException {
273 EwsUtilities.validatePropertyVersion(this.getOwner().getService(),
274 ExchangeVersion.Exchange2010, "IsInline");
275 if (this.canSetFieldValue(this.isInline, value)) {
276 this.isInline = value;
277 this.changed();
278 }
279 }
280
281 /**
282 * True if the attachment has not yet been saved, false otherwise.
283 *
284 * @return true, if is new
285 */
286 public boolean isNew() {
287 return (this.getId() == null || this.getId().isEmpty());
288 }
289
290 /**
291 * Gets the owner of the attachment.
292 *
293 * @return the owner
294 */
295 public Item getOwner() {
296 return this.owner;
297 }
298
299 /**
300 * Gets the name of the XML element.
301 *
302 * @return XML element name.
303 */
304 public abstract String getXmlElementName();
305
306 /**
307 * Tries to read element from XML.
308 *
309 * @param reader The reader.
310 * @return True if element was read.
311 * @throws Exception the exception
312 */
313 @Override
314 public boolean tryReadElementFromXml(EwsServiceXmlReader reader)
315 throws Exception {
316
317 try {
318 if (reader.getLocalName().equalsIgnoreCase(
319 XmlElementNames.AttachmentId)) {
320 try {
321 this.id = reader.readAttributeValue(XmlAttributeNames.Id);
322 } catch (Exception e) {
323 LOG.error(e);
324 return false;
325 }
326 if (this.getOwner() != null) {
327 String rootItemChangeKey = reader
328 .readAttributeValue(XmlAttributeNames.
329 RootItemChangeKey);
330 if (null != rootItemChangeKey &&
331 !rootItemChangeKey.isEmpty()) {
332 this.getOwner().getRootItemId().setChangeKey(
333 rootItemChangeKey);
334 }
335 }
336 reader.readEndElementIfNecessary(XmlNamespace.Types,
337 XmlElementNames.AttachmentId);
338 return true;
339 } else if (reader.getLocalName().equalsIgnoreCase(
340 XmlElementNames.Name)) {
341 this.name = reader.readElementValue();
342 return true;
343 } else if (reader.getLocalName().equalsIgnoreCase(
344 XmlElementNames.ContentType)) {
345 this.contentType = reader.readElementValue();
346 return true;
347 } else if (reader.getLocalName().equalsIgnoreCase(
348 XmlElementNames.ContentId)) {
349 this.contentId = reader.readElementValue();
350 return true;
351 } else if (reader.getLocalName().equalsIgnoreCase(
352 XmlElementNames.ContentLocation)) {
353 this.contentLocation = reader.readElementValue();
354 return true;
355 } else if (reader.getLocalName().equalsIgnoreCase(
356 XmlElementNames.Size)) {
357 this.size = reader.readElementValue(Integer.class);
358 return true;
359 } else if (reader.getLocalName().equalsIgnoreCase(
360 XmlElementNames.LastModifiedTime)) {
361 this.lastModifiedTime = reader.readElementValueAsDateTime();
362 return true;
363 } else if (reader.getLocalName().equalsIgnoreCase(
364 XmlElementNames.IsInline)) {
365 this.isInline = reader.readElementValue(Boolean.class);
366 return true;
367 } else {
368 return false;
369 }
370 } catch (Exception e) {
371 LOG.error(e);
372 return false;
373 }
374 }
375
376 /**
377 * Writes elements to XML.
378 *
379 * @param writer the writer
380 * @throws Exception the exception
381 */
382 @Override
383 public void writeElementsToXml(EwsServiceXmlWriter writer)
384 throws Exception {
385 writer.writeElementValue(XmlNamespace.Types, XmlElementNames.Name, this
386 .getName());
387 writer.writeElementValue(XmlNamespace.Types,
388 XmlElementNames.ContentType, this.getContentType());
389 writer.writeElementValue(XmlNamespace.Types, XmlElementNames.ContentId,
390 this.getContentId());
391 writer.writeElementValue(XmlNamespace.Types,
392 XmlElementNames.ContentLocation, this.getContentLocation());
393 if (writer.getService().getRequestedServerVersion().ordinal() >
394 ExchangeVersion.Exchange2007_SP1
395 .ordinal()) {
396 writer.writeElementValue(XmlNamespace.Types,
397 XmlElementNames.IsInline, this.getIsInline());
398 }
399 }
400
401 /**
402 * Load the attachment.
403 *
404 * @param bodyType Type of the body.
405 * @param additionalProperties The additional property.
406 * @throws Exception the exception
407 */
408 protected void internalLoad(BodyType bodyType,
409 Iterable<PropertyDefinitionBase> additionalProperties)
410 throws Exception {
411 this.getOwner().getService().getAttachment(this, bodyType,
412 additionalProperties);
413 }
414
415 /**
416 * Validates this instance.
417 *
418 * @param attachmentIndex Index of this attachment.
419 * @throws ServiceValidationException the service validation exception
420 * @throws Exception the exception
421 */
422 abstract void validate(int attachmentIndex) throws Exception;
423
424 /**
425 * Loads the attachment. Calling this method results in a call to EWS.
426 *
427 * @throws Exception the exception
428 */
429 public void load() throws Exception {
430 this.internalLoad(null, null);
431 }
432
433 }