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.definition;
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.enumeration.property.DefaultExtendedPropertySet;
032    import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
033    import microsoft.exchange.webservices.data.core.enumeration.property.MapiPropertyType;
034    import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlSerializationException;
035    import microsoft.exchange.webservices.data.misc.MapiTypeConverter;
036    
037    import java.util.UUID;
038    
039    /**
040     * Represents the definition of an extended property.
041     */
042    public final class ExtendedPropertyDefinition extends PropertyDefinitionBase {
043    
044      /**
045       * The property set.
046       */
047      private DefaultExtendedPropertySet propertySet;
048    
049      /**
050       * The property set id.
051       */
052      private UUID propertySetId;
053    
054      /**
055       * The tag.
056       */
057      private Integer tag;
058    
059      /**
060       * The name.
061       */
062      private String name;
063    
064      /**
065       * The id.
066       */
067      private Integer id;
068    
069      /**
070       * The mapi type.
071       */
072      private MapiPropertyType mapiType;
073    
074      /**
075       * The Constant FieldFormat.
076       */
077      private final static String FieldFormat = "%s: %s ";
078    
079      /**
080       * The Property set field name.
081       */
082      private static final String PropertySetFieldName = "PropertySet";
083    
084      /**
085       * The Property set id field name.
086       */
087      private static final String PropertySetIdFieldName = "PropertySetId";
088    
089      /**
090       * The Tag field name.
091       */
092      private static final String TagFieldName = "Tag";
093    
094      /**
095       * The Name field name.
096       */
097      private static final String NameFieldName = "Name";
098    
099      /**
100       * The Id field name.
101       */
102      private static final String IdFieldName = "Id";
103    
104      /**
105       * The Mapi type field name.
106       */
107      private static final String MapiTypeFieldName = "MapiType";
108    
109      /**
110       * Initializes a new instance.
111       */
112      public ExtendedPropertyDefinition() {
113        super();
114        this.mapiType = MapiPropertyType.String;
115      }
116    
117      /**
118       * Initializes a new instance.
119       *
120       * @param mapiType The MAPI type of the extended property.
121       */
122      protected ExtendedPropertyDefinition(MapiPropertyType mapiType) {
123        this();
124        this.mapiType = mapiType;
125      }
126    
127      /**
128       * Initializes a new instance.
129       *
130       * @param tag      The tag of the extended property.
131       * @param mapiType The MAPI type of the extended property.
132       */
133      public ExtendedPropertyDefinition(int tag, MapiPropertyType mapiType) {
134        this(mapiType);
135        if (tag < 0) {
136          throw new IllegalArgumentException("Argument out of range : tag " + "The extended property tag value must be in the range of 0 to 65,535.");
137        }
138        this.tag = tag;
139      }
140    
141      /**
142       * Initializes a new instance.
143       *
144       * @param propertySet The extended property set of the extended property.
145       * @param name        The name of the extended property.
146       * @param mapiType    The MAPI type of the extended property.
147       * @throws Exception the exception
148       */
149      public ExtendedPropertyDefinition(DefaultExtendedPropertySet propertySet,
150          String name, MapiPropertyType mapiType) throws Exception {
151        this(mapiType);
152        EwsUtilities.validateParam(name, "name");
153    
154        this.propertySet = propertySet;
155        this.name = name;
156      }
157    
158      /**
159       * Initializes a new instance.
160       *
161       * @param propertySet The property set of the extended property.
162       * @param id          The Id of the extended property.
163       * @param mapiType    The MAPI type of the extended property.
164       */
165      public ExtendedPropertyDefinition(DefaultExtendedPropertySet propertySet,
166          int id, MapiPropertyType mapiType) {
167        this(mapiType);
168        this.propertySet = propertySet;
169        this.id = id;
170      }
171    
172      /**
173       * Initializes a new instance.
174       *
175       * @param propertySetId The property set Id of the extended property.
176       * @param name          The name of the extended property.
177       * @param mapiType      The MAPI type of the extended property.
178       * @throws Exception the exception
179       */
180      public ExtendedPropertyDefinition(UUID propertySetId, String name,
181          MapiPropertyType mapiType) throws Exception {
182        this(mapiType);
183        EwsUtilities.validateParam(name, "name");
184    
185        this.propertySetId = propertySetId;
186        this.name = name;
187      }
188    
189      /**
190       * Initializes a new instance.
191       *
192       * @param propertySetId The property set Id of the extended property.
193       * @param id            The Id of the extended property.
194       * @param mapiType      The MAPI type of the extended property.
195       */
196      public ExtendedPropertyDefinition(UUID propertySetId, int id,
197          MapiPropertyType mapiType) {
198        this(mapiType);
199        this.propertySetId = propertySetId;
200        this.id = id;
201      }
202    
203      /**
204       * Determines whether two specified instances of ExtendedPropertyDefinition are equal.
205       *
206       * @param extPropDef1 First extended property definition.
207       * @param extPropDef2 Second extended property definition.
208       * @return True if extended property definitions are equal.
209       */
210      protected static boolean isEqualTo(ExtendedPropertyDefinition extPropDef1,
211          ExtendedPropertyDefinition extPropDef2) {
212        if (extPropDef1 == extPropDef2) {
213          return true;
214        }
215    
216        if (extPropDef1 == null || extPropDef2 == null) {
217          return false;
218        }
219    
220        if (extPropDef1.getId() != null) {
221          if (!extPropDef1.getId().equals(extPropDef2.getId())) {
222            return false;
223          }
224        } else if (extPropDef2.getId() != null) {
225          return false;
226        }
227    
228        if (extPropDef1.getMapiType() != extPropDef2.getMapiType()) {
229          return false;
230        }
231    
232        if (extPropDef1.getTag() != null) {
233          if (!extPropDef1.getTag().equals(extPropDef2.getTag())) {
234            return false;
235          }
236        } else if (extPropDef2.getTag() != null) {
237          return false;
238        }
239    
240        if (extPropDef1.getName() != null) {
241          if (!extPropDef1.getName().equals(extPropDef2.getName())) {
242            return false;
243          }
244        } else if (extPropDef2.getName() != null) {
245          return false;
246        }
247    
248        if (extPropDef1.getPropertySet() != extPropDef2.getPropertySet()) {
249          return false;
250        }
251    
252        if (extPropDef1.propertySetId != null) {
253          if (!extPropDef1.propertySetId.equals(extPropDef2.propertySetId)) {
254            return false;
255          }
256        } else if (extPropDef2.propertySetId != null) {
257          return false;
258        }
259    
260        return true;
261      }
262    
263      /**
264       * Gets the name of the XML element.
265       *
266       * @return XML element name.
267       */
268      @Override
269      protected String getXmlElementName() {
270        return XmlElementNames.ExtendedFieldURI;
271      }
272    
273      /**
274       * Gets the minimum Exchange version that supports this extended property.
275       *
276       * @return The version.
277       */
278      @Override
279      public ExchangeVersion getVersion() {
280        return ExchangeVersion.Exchange2007_SP1;
281      }
282    
283      /**
284       * Writes the attribute to XML.
285       *
286       * @param writer The writer.
287       * @throws ServiceXmlSerializationException the service xml serialization exception
288       */
289      @Override
290      protected void writeAttributesToXml(EwsServiceXmlWriter writer)
291          throws ServiceXmlSerializationException {
292        if (this.propertySet != null) {
293          writer.writeAttributeValue(
294              XmlAttributeNames.DistinguishedPropertySetId,
295              this.propertySet);
296        }
297        if (this.propertySetId != null) {
298          writer.writeAttributeValue(XmlAttributeNames.PropertySetId,
299              this.propertySetId.toString());
300        }
301        if (this.tag != null) {
302          writer.writeAttributeValue(XmlAttributeNames.PropertyTag, this.tag);
303        }
304        if (null != this.name && !this.name.isEmpty()) {
305          writer.writeAttributeValue(XmlAttributeNames.PropertyName,
306              this.name);
307        }
308        if (this.id != null) {
309          writer.writeAttributeValue(XmlAttributeNames.PropertyId, this.id);
310        }
311        writer.writeAttributeValue(XmlAttributeNames.PropertyType,
312            this.mapiType);
313      }
314    
315      /**
316       * Loads from XML.
317       *
318       * @param reader The reader.
319       * @throws Exception the exception
320       */
321      public void loadFromXml(EwsServiceXmlReader reader) throws Exception {
322        String attributeValue;
323    
324        attributeValue = reader
325            .readAttributeValue(XmlAttributeNames.
326                DistinguishedPropertySetId);
327        if (null != attributeValue && !attributeValue.isEmpty()) {
328          this.propertySet = DefaultExtendedPropertySet
329              .valueOf(attributeValue);
330        }
331    
332        attributeValue = reader
333            .readAttributeValue(XmlAttributeNames.PropertySetId);
334        if (null != attributeValue && !attributeValue.isEmpty()) {
335          this.propertySetId = UUID.fromString(attributeValue);
336        }
337    
338        attributeValue = reader
339            .readAttributeValue(XmlAttributeNames.PropertyTag);
340        if (null != attributeValue && !attributeValue.isEmpty()) {
341    
342          this.tag = Integer.decode(attributeValue);
343        }
344    
345        this.name = reader.readAttributeValue(XmlAttributeNames.PropertyName);
346        attributeValue = reader
347            .readAttributeValue(XmlAttributeNames.PropertyId);
348        if (null != attributeValue && !attributeValue.isEmpty()) {
349          this.id = Integer.parseInt(attributeValue);
350        }
351    
352        this.mapiType = reader.readAttributeValue(MapiPropertyType.class,
353            XmlAttributeNames.PropertyType);
354      }
355    
356    
357      /**
358       * Determines whether two specified instances of ExtendedPropertyDefinition
359       * are equal.
360       *
361       * @param obj the obj
362       * @return True if extended property definitions are equal.
363       */
364      @Override
365      public boolean equals(Object obj) {
366        if (this == obj) {
367          return true;
368        }
369        if (obj instanceof ExtendedPropertyDefinition) {
370          return ExtendedPropertyDefinition.isEqualTo(this,
371              (ExtendedPropertyDefinition) obj);
372        } else {
373          return false;
374        }
375      }
376    
377      /*
378       * (non-Javadoc)
379       *
380       * @see java.lang.Object#hashCode()
381       */
382      @Override
383      public int hashCode() {
384        return this.getPrintableName().hashCode();
385      }
386    
387      /**
388       * Gets the property definition's printable name.
389       *
390       * @return The property definition's printable name.
391       */
392      @Override public String getPrintableName() {
393        StringBuilder sb = new StringBuilder();
394        sb.append("{");
395        sb.append(formatField(NameFieldName, this.getName()));
396        sb.append(formatField(MapiTypeFieldName, this.getMapiType()));
397        sb.append(formatField(IdFieldName, this.getId()));
398        sb.append(formatField(PropertySetFieldName, this.getPropertySet()));
399        sb.append(formatField(PropertySetIdFieldName, this.getPropertySetId()));
400        sb.append(formatField(TagFieldName, this.getTag()));
401        sb.append("}");
402        return sb.toString();
403      }
404    
405      /**
406       * Formats the field.
407       *
408       * @param <T>        Type of the field.
409       * @param name       The name.
410       * @param fieldValue The field value.
411       * @return the string
412       */
413      protected <T> String formatField(String name, T fieldValue) {
414        return (fieldValue != null) ? String.format(FieldFormat, name,
415            fieldValue.toString()) : "";
416      }
417    
418      /**
419       * Gets the property set of the extended property.
420       *
421       * @return property set of the extended property.
422       */
423      public DefaultExtendedPropertySet getPropertySet() {
424        return this.propertySet;
425      }
426    
427      /**
428       * Gets the property set Id or the extended property.
429       *
430       * @return property set Id or the extended property.
431       */
432      public UUID getPropertySetId() {
433        return this.propertySetId;
434      }
435    
436      /**
437       * Gets the extended property's tag.
438       *
439       * @return The extended property's tag.
440       */
441      public Integer getTag() {
442        return this.tag;
443      }
444    
445      /**
446       * Gets the name of the extended property.
447       *
448       * @return The name of the extended property.
449       */
450      public String getName() {
451        return this.name;
452      }
453    
454      /**
455       * Gets the Id of the extended property.
456       *
457       * @return The Id of the extended property.
458       */
459      public Integer getId() {
460        return this.id;
461      }
462    
463      /**
464       * Gets the MAPI type of the extended property.
465       *
466       * @return The MAPI type of the extended property.
467       */
468      public MapiPropertyType getMapiType() {
469        return this.mapiType;
470      }
471    
472      /**
473       * Gets the property type.
474       */
475      @Override
476      public Class<?> getType() {
477        return MapiTypeConverter.getMapiTypeConverterMap().
478            get(getMapiType()).getType();
479      }
480    }