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.attribute.EditorBrowsable;
027    import microsoft.exchange.webservices.data.core.EwsServiceXmlReader;
028    import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter;
029    import microsoft.exchange.webservices.data.core.EwsUtilities;
030    import microsoft.exchange.webservices.data.core.ICustomXmlUpdateSerializer;
031    import microsoft.exchange.webservices.data.core.XmlElementNames;
032    import microsoft.exchange.webservices.data.core.service.ServiceObject;
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.misc.ArgumentException;
036    import microsoft.exchange.webservices.data.core.exception.service.local.ServiceXmlSerializationException;
037    import microsoft.exchange.webservices.data.misc.OutParam;
038    import microsoft.exchange.webservices.data.property.definition.ExtendedPropertyDefinition;
039    import microsoft.exchange.webservices.data.property.definition.PropertyDefinition;
040    
041    import javax.xml.stream.XMLStreamException;
042    
043    import java.util.ArrayList;
044    import java.util.List;
045    
046    /**
047     * Represents a collection of extended property.
048     */
049    @EditorBrowsable(state = EditorBrowsableState.Never)
050    public final class ExtendedPropertyCollection extends ComplexPropertyCollection<ExtendedProperty> implements
051                                                                                                      ICustomXmlUpdateSerializer {
052    
053      /**
054       * Creates the complex property.
055       *
056       * @param xmlElementName Name of the XML element.
057       * @return Complex property instance.
058       */
059      @Override
060      protected ExtendedProperty createComplexProperty(String xmlElementName) {
061        // This method is unused in this class, so just return null.
062        return null;
063      }
064    
065      /**
066       * Gets the name of the collection item XML element.
067       *
068       * @param complexProperty The complex property.
069       * @return XML element name.
070       */
071      @Override
072      protected String getCollectionItemXmlElementName(
073          ExtendedProperty complexProperty) {
074        // This method is unused in this class, so just return null.
075        return null;
076      }
077    
078      /**
079       * Loads from XML.
080       *
081       * @param reader           The reader.
082       * @param localElementName Name of the local element.
083       * @throws Exception the exception
084       */
085      @Override public void loadFromXml(EwsServiceXmlReader reader, String localElementName) throws Exception {
086        ExtendedProperty extendedProperty = new ExtendedProperty();
087        extendedProperty.loadFromXml(reader, reader.getLocalName());
088        this.internalAdd(extendedProperty);
089      }
090    
091      /**
092       * Writes to XML.
093       *
094       * @param writer         The writer.
095       * @param xmlElementName Name of the XML element.
096       * @throws Exception the exception
097       */
098      @Override public void writeToXml(EwsServiceXmlWriter writer, String xmlElementName)
099          throws Exception {
100        for (ExtendedProperty extendedProperty : this) {
101          extendedProperty.writeToXml(writer,
102              XmlElementNames.ExtendedProperty);
103        }
104      }
105    
106      /**
107       * Gets existing or adds new extended property.
108       *
109       * @param propertyDefinition The property definition.
110       * @return ExtendedProperty.
111       * @throws Exception the exception
112       */
113      private ExtendedProperty getOrAddExtendedProperty(
114          ExtendedPropertyDefinition propertyDefinition) throws Exception {
115        ExtendedProperty extendedProperty = null;
116        OutParam<ExtendedProperty> extendedPropertyOut =
117            new OutParam<ExtendedProperty>();
118        if (!this.tryGetProperty(propertyDefinition, extendedPropertyOut)) {
119          extendedProperty = new ExtendedProperty(propertyDefinition);
120          this.internalAdd(extendedProperty);
121        } else {
122          extendedProperty = extendedPropertyOut.getParam();
123        }
124        return extendedProperty;
125      }
126    
127      /**
128       * Sets an extended property.
129       *
130       * @param propertyDefinition The property definition.
131       * @param value              The value.
132       * @throws Exception the exception
133       */
134      public void setExtendedProperty(ExtendedPropertyDefinition propertyDefinition, Object value)
135          throws Exception {
136        ExtendedProperty extendedProperty = this
137            .getOrAddExtendedProperty(propertyDefinition);
138        extendedProperty.setValue(value);
139      }
140    
141      /**
142       * Removes a specific extended property definition from the collection.
143       *
144       * @param propertyDefinition The definition of the extended property to remove.
145       * @return True if the property matching the extended property definition
146       * was successfully removed from the collection, false otherwise.
147       * @throws Exception the exception
148       */
149      public boolean removeExtendedProperty(ExtendedPropertyDefinition propertyDefinition) throws Exception {
150        EwsUtilities.validateParam(propertyDefinition, "propertyDefinition");
151    
152        ExtendedProperty extendedProperty = null;
153        OutParam<ExtendedProperty> extendedPropertyOut =
154            new OutParam<ExtendedProperty>();
155        if (this.tryGetProperty(propertyDefinition, extendedPropertyOut)) {
156          extendedProperty = extendedPropertyOut.getParam();
157          return this.internalRemove(extendedProperty);
158        } else {
159          return false;
160        }
161      }
162    
163      /**
164       * Tries to get property.
165       *
166       * @param propertyDefinition  The property definition.
167       * @param extendedPropertyOut The extended property.
168       * @return True of property exists in collection.
169       */
170      private boolean tryGetProperty(
171          ExtendedPropertyDefinition propertyDefinition,
172          OutParam<ExtendedProperty> extendedPropertyOut) {
173        boolean found = false;
174        extendedPropertyOut.setParam(null);
175        for (ExtendedProperty prop : this.getItems()) {
176          if (prop.getPropertyDefinition().equals(propertyDefinition)) {
177            found = true;
178            extendedPropertyOut.setParam(prop);
179            break;
180          }
181        }
182        return found;
183      }
184    
185      /**
186       * Tries to get property value.
187       *
188       * @param propertyDefinition The property definition.
189       * @param propertyValueOut   The property value.
190       * @return True if property exists in collection.
191       * @throws ArgumentException
192       */
193      public <T> boolean tryGetValue(Class<T> cls, ExtendedPropertyDefinition propertyDefinition,
194          OutParam<T> propertyValueOut) throws ArgumentException {
195        ExtendedProperty extendedProperty = null;
196        OutParam<ExtendedProperty> extendedPropertyOut =
197            new OutParam<ExtendedProperty>();
198        if (this.tryGetProperty(propertyDefinition, extendedPropertyOut)) {
199          extendedProperty = extendedPropertyOut.getParam();
200          if (!cls.isAssignableFrom(propertyDefinition.getType())) {
201            String errorMessage = String.format(
202                "Property definition type '%s' and type parameter '%s' aren't compatible.",
203                propertyDefinition.getType().getSimpleName(),
204                cls.getSimpleName());
205            throw new ArgumentException(errorMessage, "propertyDefinition");
206          }
207          propertyValueOut.setParam((T) extendedProperty.getValue());
208          return true;
209        } else {
210          propertyValueOut.setParam(null);
211          return false;
212        }
213      }
214    
215    
216      /**
217       * Writes the update to XML.
218       *
219       * @param writer             The writer.
220       * @param ewsObject          The ews object.
221       * @param propertyDefinition Property definition.
222       * @return True if property generated serialization.
223       * @throws Exception the exception
224       */
225      @Override
226      public boolean writeSetUpdateToXml(EwsServiceXmlWriter writer,
227          ServiceObject ewsObject, PropertyDefinition propertyDefinition)
228          throws Exception {
229        List<ExtendedProperty> propertiesToSet =
230            new ArrayList<ExtendedProperty>();
231    
232        propertiesToSet.addAll(this.getAddedItems());
233        propertiesToSet.addAll(this.getModifiedItems());
234    
235        for (ExtendedProperty extendedProperty : propertiesToSet) {
236          writer.writeStartElement(XmlNamespace.Types, ewsObject
237              .getSetFieldXmlElementName());
238          extendedProperty.getPropertyDefinition().writeToXml(writer);
239    
240          writer.writeStartElement(XmlNamespace.Types, ewsObject
241              .getXmlElementName());
242          extendedProperty.writeToXml(writer,
243              XmlElementNames.ExtendedProperty);
244          writer.writeEndElement();
245    
246          writer.writeEndElement();
247        }
248    
249        for (ExtendedProperty extendedProperty : this.getRemovedItems()) {
250          writer.writeStartElement(XmlNamespace.Types, ewsObject
251              .getDeleteFieldXmlElementName());
252          extendedProperty.getPropertyDefinition().writeToXml(writer);
253          writer.writeEndElement();
254        }
255    
256        return true;
257      }
258    
259      /**
260       * Writes the deletion update to XML.
261       *
262       * @param writer    the writer
263       * @param ewsObject the ews object
264       * @return true if property generated serialization
265       * @throws XMLStreamException the XML stream exception
266       * @throws ServiceXmlSerializationException the service xml serialization exception
267       */
268      @Override
269      public boolean writeDeleteUpdateToXml(EwsServiceXmlWriter writer,
270          ServiceObject ewsObject) throws XMLStreamException, ServiceXmlSerializationException {
271        for (ExtendedProperty extendedProperty : this.getItems()) {
272          writer.writeStartElement(XmlNamespace.Types, ewsObject
273              .getDeleteFieldXmlElementName());
274          extendedProperty.getPropertyDefinition().writeToXml(writer);
275          writer.writeEndElement();
276        }
277    
278        return true;
279      }
280    }