All Downloads are FREE. Search and download functionalities are using the official Maven repository.

microsoft.exchange.webservices.data.core.service.schema.ServiceObjectSchema Maven / Gradle / Ivy

There is a newer version: 2.15
Show newest version
/*
 * The MIT License
 * Copyright (c) 2012 Microsoft Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package microsoft.exchange.webservices.data.core.service.schema;

import microsoft.exchange.webservices.data.attribute.EditorBrowsable;
import microsoft.exchange.webservices.data.core.EwsUtilities;
import microsoft.exchange.webservices.data.core.ILazyMember;
import microsoft.exchange.webservices.data.core.LazyMember;
import microsoft.exchange.webservices.data.core.XmlElementNames;
import microsoft.exchange.webservices.data.core.enumeration.attribute.EditorBrowsableState;
import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
import microsoft.exchange.webservices.data.core.enumeration.property.PropertyDefinitionFlags;
import microsoft.exchange.webservices.data.misc.OutParam;
import microsoft.exchange.webservices.data.property.complex.ExtendedPropertyCollection;
import microsoft.exchange.webservices.data.property.complex.ICreateComplexPropertyDelegate;
import microsoft.exchange.webservices.data.property.definition.ComplexPropertyDefinition;
import microsoft.exchange.webservices.data.property.definition.IndexedPropertyDefinition;
import microsoft.exchange.webservices.data.property.definition.PropertyDefinition;
import microsoft.exchange.webservices.data.property.definition.PropertyDefinitionBase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Represents the base class for all item and folder schema.
 */
@EditorBrowsable(state = EditorBrowsableState.Never)
public abstract class ServiceObjectSchema implements
    Iterable {

  private static final Log LOG = LogFactory.getLog(ServiceObjectSchema.class);

  /**
   * The lock object.
   */
  private static final Object lockObject = new Object();

  /**
   * List of all schema types. If you add a new ServiceObject subclass that
   * has an associated schema, add the schema type to the list below.
   */
  private static LazyMember>> allSchemaTypes = new
      LazyMember>>(new
                                     ILazyMember>>() {
                                       public List> createInstance() {
                                         List> typeList = new ArrayList>();
                                         // typeList.add()
                                        /*
					 * typeList.add(AppointmentSchema.class);
					 * typeList.add(CalendarResponseObjectSchema.class);
					 * typeList.add(CancelMeetingMessageSchema.class);
					 * typeList.add(ContactGroupSchema.class);
					 * typeList.add(ContactSchema.class);
					 * typeList.add(EmailMessageSchema.class);
					 * typeList.add(FolderSchema.class);
					 * typeList.add(ItemSchema.class);
					 * typeList.add(MeetingMessageSchema.class);
					 * typeList.add(MeetingRequestSchema.class);
					 * typeList.add(PostItemSchema.class);
					 * typeList.add(PostReplySchema.class);
					 * typeList.add(ResponseMessageSchema.class);
					 * typeList.add(ResponseObjectSchema.class);
					 * typeList.add(ServiceObjectSchema.class);
					 * typeList.add(SearchFolderSchema.class);
					 * typeList.add(TaskSchema.class);
					 */
                                         // Verify that all Schema types in the Managed API assembly
                                         // have been included.
					/*
					 * var missingTypes = from type in
					 * Assembly.GetExecutingAssembly().GetTypes() where
					 * type.IsSubclassOf(typeof(ServiceObjectSchema)) &&
					 * !typeList.Contains(type) select type; if
					 * (missingTypes.Count() > 0) { throw new
					 * ServiceLocalException
					 * ("SchemaTypeList does not include all 
					 * defined schema types."
					 * ); }
					 */
                                         return typeList;
                                       }
                                     });

  /**
   * Dictionary of all property definitions.
   */
  private static LazyMember>
      allSchemaProperties = new
      LazyMember>(
      new ILazyMember>() {
        public Map createInstance() {
          Map propDefDictionary =
              new HashMap();
          for (Class c : ServiceObjectSchema.allSchemaTypes
              .getMember()) {
            ServiceObjectSchema.addSchemaPropertiesToDictionary(c,
                propDefDictionary);
          }
          return propDefDictionary;
        }
      });

  /**
   * Adds schema property to dictionary.
   *
   * @param type              Schema type.
   * @param propDefDictionary The property definition dictionary.
   */
  protected static void addSchemaPropertiesToDictionary(Class type,
      Map propDefDictionary) {
    Field[] fields = type.getDeclaredFields();
    for (Field field : fields) {
      int modifier = field.getModifiers();
      if (Modifier.isPublic(modifier) && Modifier.isStatic(modifier)) {
        Object o;
        try {
          o = field.get(null);
          if (o instanceof PropertyDefinition) {
            PropertyDefinition propertyDefinition =
                (PropertyDefinition) o;
            // Some property definitions descend from
            // ServiceObjectPropertyDefinition but don't have
            // a Uri, like ExtendedProperties. Ignore them.
            if (null != propertyDefinition.getUri() &&
                !propertyDefinition.getUri().isEmpty()) {
              PropertyDefinitionBase existingPropertyDefinition;
              if (propDefDictionary
                  .containsKey(propertyDefinition.getUri())) {
                existingPropertyDefinition = propDefDictionary
                    .get(propertyDefinition.getUri());
                EwsUtilities
                    .ewsAssert(existingPropertyDefinition == propertyDefinition,
                               "Schema.allSchemaProperties." + "delegate",
                               String.format("There are at least " +
                                             "two distinct property " +
                                             "definitions with the" +
                                             " following URI: %s", propertyDefinition.getUri()));
              } else {
                propDefDictionary.put(propertyDefinition
                    .getUri(), propertyDefinition);
                // The following is a "generic hack" to register
                // property that are not public and
                // thus not returned by the above GetFields
                // call. It is currently solely used to register
                // the MeetingTimeZone property.
                List associatedInternalProperties =
                    propertyDefinition.getAssociatedInternalProperties();
                for (PropertyDefinition associatedInternalProperty : associatedInternalProperties) {
                  propDefDictionary
                      .put(associatedInternalProperty
                              .getUri(),
                          associatedInternalProperty);
                }

              }
            }
          }
        } catch (IllegalArgumentException e) {
          LOG.error(e);

          // Skip the field
        } catch (IllegalAccessException e) {
          LOG.error(e);

          // Skip the field
        }

      }
    }
  }

  /**
   * Adds the schema property names to dictionary.
   *
   * @param type                   The type.
   * @param propertyNameDictionary The property name dictionary.
   */
  protected static void addSchemaPropertyNamesToDictionary(Class type,
      Map propertyNameDictionary) {

    Field[] fields = type.getDeclaredFields();
    for (Field field : fields) {
      int modifier = field.getModifiers();
      if (Modifier.isPublic(modifier) && Modifier.isStatic(modifier)) {
        Object o;
        try {
          o = field.get(null);
          if (o instanceof PropertyDefinition) {
            PropertyDefinition propertyDefinition =
                (PropertyDefinition) o;
            propertyNameDictionary.put(propertyDefinition, field
                .getName());
          }
        } catch (IllegalArgumentException e) {
          LOG.error(e);

          // Skip the field
        } catch (IllegalAccessException e) {
          LOG.error(e);

          // Skip the field
        }
      }
    }
  }

  /**
   * Initializes a new instance.
   */
  protected ServiceObjectSchema() {
    this.registerProperties();
  }

  /**
   * Finds the property definition.
   *
   * @param uri The URI.
   * @return Property definition.
   */
  public static PropertyDefinitionBase findPropertyDefinition(String uri) {
    return ServiceObjectSchema.allSchemaProperties.getMember().get(uri);
  }

  /**
   * Initialize schema property names.
   */
  public static void initializeSchemaPropertyNames() {
    synchronized (lockObject) {
      for (Class type : ServiceObjectSchema.allSchemaTypes.getMember()) {
        Field[] fields = type.getDeclaredFields();
        for (Field field : fields) {
          int modifier = field.getModifiers();
          if (Modifier.isPublic(modifier) &&
              Modifier.isStatic(modifier)) {
            Object o;
            try {
              o = field.get(null);
              if (o instanceof PropertyDefinition) {
                PropertyDefinition propertyDefinition =
                    (PropertyDefinition) o;
                propertyDefinition.setName(field.getName());
              }
            } catch (IllegalArgumentException e) {
              LOG.error(e);

              // Skip the field
            } catch (IllegalAccessException e) {
              LOG.error(e);

              // Skip the field
            }
          }
        }
      }
    }
  }

  /**
   * Defines the ExtendedProperties property.
   */
  public static final PropertyDefinition extendedProperties =
      new ComplexPropertyDefinition(
          ExtendedPropertyCollection.class,
          XmlElementNames.ExtendedProperty,
          EnumSet.of(PropertyDefinitionFlags.AutoInstantiateOnRead,
              PropertyDefinitionFlags.ReuseInstance,
              PropertyDefinitionFlags.CanSet,
              PropertyDefinitionFlags.CanUpdate),
          ExchangeVersion.Exchange2007_SP1,
          new ICreateComplexPropertyDelegate() {
            public ExtendedPropertyCollection createComplexProperty() {
              return new ExtendedPropertyCollection();
            }
          });

  /**
   * The property.
   */
  private Map properties =
      new HashMap();

  /**
   * The visible property.
   */
  private List visibleProperties =
      new ArrayList();

  /**
   * The first class property.
   */
  private List firstClassProperties =
      new ArrayList();

  /**
   * The first class summary property.
   */
  private List firstClassSummaryProperties =
      new ArrayList();

  private List indexedProperties =
      new ArrayList();

  /**
   * Registers a schema property.
   *
   * @param property   The property to register.
   * @param isInternal Indicates whether the property is internal or should be
   *                   visible to developers.
   */
  private void registerProperty(PropertyDefinition property,
      boolean isInternal) {
    this.properties.put(property.getXmlElement(), property);

    if (!isInternal) {
      this.visibleProperties.add(property);
    }

    // If this property does not have to be requested explicitly, add
    // it to the list of firstClassProperties.
    if (!property.hasFlag(PropertyDefinitionFlags.MustBeExplicitlyLoaded)) {
      this.firstClassProperties.add(property);
    }

    // If this property can be found, add it to the list of
    // firstClassSummaryProperties
    if (property.hasFlag(PropertyDefinitionFlags.CanFind)) {
      this.firstClassSummaryProperties.add(property);
    }
  }

  /**
   * Registers a schema property that will be visible to developers.
   *
   * @param property The property to register.
   */
  protected void registerProperty(PropertyDefinition property) {
    this.registerProperty(property, false);
  }

  /**
   * Registers an internal schema property.
   *
   * @param property The property to register.
   */
  protected void registerInternalProperty(PropertyDefinition property) {
    this.registerProperty(property, true);
  }

  /**
   * Registers an indexed property.
   *
   * @param indexedProperty The indexed property to register.
   */
  protected void registerIndexedProperty(IndexedPropertyDefinition
      indexedProperty) {
    this.indexedProperties.add(indexedProperty);
  }


  /**
   * Registers property.
   */
  protected void registerProperties() {
  }

  /**
   * Gets the list of first class property for this service object type.
   *
   * @return the first class property
   */
  public List getFirstClassProperties() {
    return this.firstClassProperties;
  }

  /**
   * Gets the list of first class summary property for this service object
   * type.
   *
   * @return the first class summary property
   */
  public List getFirstClassSummaryProperties() {
    return this.firstClassSummaryProperties;
  }

  /**
   * Tries to get property definition.
   *
   * @param xmlElementName             Name of the XML element.
   * @param propertyDefinitionOutParam The property definition.
   * @return True if property definition exists.
   */
  public boolean tryGetPropertyDefinition(String xmlElementName,
      OutParam propertyDefinitionOutParam) {
    if (this.properties.containsKey(xmlElementName)) {
      propertyDefinitionOutParam.setParam(this.properties
          .get(xmlElementName));
      return true;
    } else {
      return false;
    }
  }

  /**
   * Returns an iterator over a set of elements of type T.
   *
   * @return an Iterator.
   */
  @Override
  public Iterator iterator() {
    return this.visibleProperties.iterator();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy