You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by tb...@apache.org on 2013/12/20 16:18:08 UTC

[06/12] [OLINGO-83] Refactoring of 'annotation-processor-*' modules

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/3bd59050/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/util/AnnotationHelper.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/util/AnnotationHelper.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/util/AnnotationHelper.java
new file mode 100644
index 0000000..807b6fe
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/util/AnnotationHelper.java
@@ -0,0 +1,777 @@
+/**
+ * *****************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
+ * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ * ****************************************************************************
+ */
+package org.apache.olingo.odata2.annotation.processor.core.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.annotation.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.annotation.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.annotation.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.annotation.edm.EdmKey;
+import org.apache.olingo.odata2.api.annotation.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.annotation.edm.EdmNavigationProperty.Multiplicity;
+import org.apache.olingo.odata2.api.annotation.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ *
+ */
+public class AnnotationHelper {
+
+  public static final String DEFAULT_CONTAINER_NAME = "DefaultContainer";
+
+  /**
+   * Compare keys of both instances.
+   * 
+   * @param firstInstance
+   * @param secondInstance
+   * @return
+   */
+  public boolean keyMatch(final Object firstInstance, final Object secondInstance) {
+    if (firstInstance == null || secondInstance == null) {
+      return false;
+    } else if (firstInstance.getClass() != secondInstance.getClass()) {
+      return false;
+    }
+
+    Map<String, Object> firstKeyFields = getValueForAnnotatedFields(firstInstance, EdmKey.class);
+    Map<String, Object> secondKeyFields = getValueForAnnotatedFields(secondInstance, EdmKey.class);
+
+    return keyValuesMatch(firstKeyFields, secondKeyFields);
+  }
+
+  /**
+   * Compare keys of instance with key values in map.
+   * 
+   * @param instance
+   * @param keyName2Value
+   * @return
+   */
+  public boolean keyMatch(final Object instance, final Map<String, Object> keyName2Value) {
+    Map<String, Object> instanceKeyFields = getValueForAnnotatedFields(instance, EdmKey.class);
+    return keyValuesMatch(instanceKeyFields, keyName2Value);
+  }
+
+  private boolean keyValuesMatch(final Map<String, Object> firstKeyValues, final Map<String, Object> secondKeyValues) {
+    if (firstKeyValues.size() != secondKeyValues.size()) {
+      return false;
+    } else {
+      Set<Map.Entry<String, Object>> entries = firstKeyValues.entrySet();
+      for (Map.Entry<String, Object> entry : entries) {
+        Object firstKey = entry.getValue();
+        Object secondKey = secondKeyValues.get(entry.getKey());
+        if (!isEqual(firstKey, secondKey)) {
+          return false;
+        }
+      }
+      return true;
+    }
+  }
+
+  private boolean isEqual(final Object firstKey, final Object secondKey) {
+    if (firstKey == null) {
+      if (secondKey == null) {
+        return true;
+      } else {
+        return secondKey.equals(firstKey);
+      }
+    } else {
+      return firstKey.equals(secondKey);
+    }
+  }
+
+  public String extractEntitTypeName(final EdmNavigationProperty enp, final Class<?> fallbackClass) {
+    Class<?> entityTypeClass = enp.toType();
+    return extractEntityTypeName(entityTypeClass == Object.class ? fallbackClass : entityTypeClass);
+  }
+
+  public String extractEntitTypeName(final EdmNavigationProperty enp, final Field field) {
+    Class<?> entityTypeClass = enp.toType();
+    if (entityTypeClass == Object.class) {
+      Class<?> toClass = field.getType();
+      return extractEntityTypeName((toClass.isArray() || Collection.class.isAssignableFrom(toClass) ?
+          (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0] : toClass));
+    } else {
+      return extractEntityTypeName(entityTypeClass);
+    }
+  }
+
+  /**
+   * Returns <code>NULL</code> if given class is not annotated. If annotated the set entity type name is returned and if
+   * no name is set the default name is generated from the simple class name.
+   * 
+   * @param annotatedClass
+   * @return
+   */
+  public String extractEntityTypeName(final Class<?> annotatedClass) {
+    return extractTypeName(annotatedClass, EdmEntityType.class);
+  }
+
+  /**
+   * Returns <code>NULL</code> if given class is not annotated.
+   * If annotated the entity set name is returned and if
+   * no name is set a default name is generated based on the simple class name.
+   * 
+   * @param annotatedClass
+   * @return
+   */
+  public String extractEntitySetName(final Class<?> annotatedClass) {
+    if (annotatedClass == Object.class) {
+      return null;
+    }
+    EdmEntitySet entitySet = annotatedClass.getAnnotation(EdmEntitySet.class);
+    if (entitySet == null) {
+      return null;
+    }
+
+    String name = entitySet.name();
+    if (name.isEmpty()) {
+      return getCanonicalName(annotatedClass) + "Set";
+    }
+    return name;
+  }
+
+  public FullQualifiedName extractEntityTypeFqn(final EdmEntityType type, final Class<?> annotatedClass) {
+    if (type.namespace().isEmpty()) {
+      return new FullQualifiedName(generateNamespace(annotatedClass), extractEntityTypeName(annotatedClass));
+    }
+    return new FullQualifiedName(type.namespace(), extractEntityTypeName(annotatedClass));
+  }
+
+  public FullQualifiedName extractEntityTypeFqn(final Class<?> annotatedClass) {
+    EdmEntityType type = annotatedClass.getAnnotation(EdmEntityType.class);
+    if (type == null) {
+      return null;
+    }
+    return extractEntityTypeFqn(type, annotatedClass);
+  }
+
+  public FullQualifiedName extractComplexTypeFqn(final Class<?> annotatedClass) {
+    EdmComplexType type = annotatedClass.getAnnotation(EdmComplexType.class);
+    if (type == null) {
+      return null;
+    }
+    return extractComplexTypeFqn(type, annotatedClass);
+  }
+
+  public FullQualifiedName extractComplexTypeFqn(final EdmComplexType type, final Class<?> annotatedClass) {
+    if (type.namespace().isEmpty()) {
+      return new FullQualifiedName(generateNamespace(annotatedClass), extractComplexTypeName(annotatedClass));
+    }
+    return new FullQualifiedName(type.namespace(), extractComplexTypeName(annotatedClass));
+  }
+
+  public String extractComplexTypeName(final Class<?> annotatedClass) {
+    return extractTypeName(annotatedClass, EdmComplexType.class);
+  }
+
+  public String generateNamespace(final Class<?> annotatedClass) {
+    String packageName = annotatedClass.getPackage().getName();
+    return packageName;
+  }
+
+  /**
+   * 
+   * 
+   * @param <T> must be EdmEntityType or EdmComplexType annotation
+   * @param annotatedClass
+   * @param typeAnnotation
+   * @return null if annotatedClass is not annotated or name set via annotation or generated via
+   * {@link #getCanonicalName(java.lang.Class)}
+   */
+  private <T extends Annotation> String extractTypeName(final Class<?> annotatedClass, final Class<T> typeAnnotation) {
+    if (annotatedClass == Object.class) {
+      return null;
+    }
+    T type = annotatedClass.getAnnotation(typeAnnotation);
+    if (type == null) {
+      return null;
+    }
+
+    String name;
+    if (typeAnnotation == EdmEntityType.class) {
+      name = ((EdmEntityType) type).name();
+    } else if (typeAnnotation == EdmComplexType.class) {
+      name = ((EdmComplexType) type).name();
+    } else {
+      return null;
+    }
+
+    if (name.isEmpty()) {
+      return getCanonicalName(annotatedClass);
+    }
+    return name;
+  }
+
+  /**
+   * Get the set property name from an EdmProperty or EdmNavigationProperty annotation.
+   * 
+   * @param field
+   * @return
+   */
+  public String getPropertyNameFromAnnotation(final Field field) {
+    EdmProperty property = field.getAnnotation(EdmProperty.class);
+    if (property == null) {
+      EdmNavigationProperty navProperty = field.getAnnotation(EdmNavigationProperty.class);
+      if (navProperty == null) {
+        throw new EdmAnnotationException("Given field '" + field
+            + "' has no EdmProperty or EdmNavigationProperty annotation.");
+      }
+      return navProperty.name();
+    }
+    return property.name();
+  }
+
+  public String getPropertyName(final Field field) {
+    String propertyName = getPropertyNameFromAnnotation(field);
+    if (propertyName.isEmpty()) {
+      propertyName = getCanonicalName(field);
+    }
+    return propertyName;
+  }
+
+  public String extractFromRoleName(final EdmNavigationProperty enp, final Field field) {
+    return getCanonicalRole(field.getDeclaringClass());
+  }
+
+  public String extractToRoleName(final EdmNavigationProperty enp, final Field field) {
+    String role = enp.toRole();
+    if (role.isEmpty()) {
+      role = getCanonicalRole(
+          field.getType().isArray() || Collection.class.isAssignableFrom(field.getType()) ?
+              (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0] : field.getType());
+    }
+    return role;
+  }
+
+  public String getCanonicalRole(final Class<?> fallbackClass) {
+    String toRole = extractEntityTypeName(fallbackClass);
+    return "r_" + toRole;
+  }
+
+  public String extractRelationshipName(final EdmNavigationProperty enp, final Field field) {
+    String relationshipName = enp.association();
+    if (relationshipName.isEmpty()) {
+      final String fromRole = extractFromRoleName(enp, field);
+      final String toRole = extractToRoleName(enp, field);
+      if (fromRole.compareTo(toRole) > 0) {
+        relationshipName = toRole + "-" + fromRole;
+      } else {
+        relationshipName = fromRole + "-" + toRole;
+      }
+    }
+    return relationshipName;
+  }
+
+  public EdmMultiplicity getMultiplicity(final EdmNavigationProperty enp, final Field field) {
+    EdmMultiplicity multiplicity = mapMultiplicity(enp.toMultiplicity());
+    final boolean isCollectionType = field.getType().isArray() || Collection.class.isAssignableFrom(field.getType());
+
+    if (multiplicity == EdmMultiplicity.ONE && isCollectionType) {
+      return EdmMultiplicity.MANY;
+    }
+    return multiplicity;
+  }
+
+  /**
+   * Set key fields based on values in map.
+   * If an key field is not available or <code>NULL</code> in the map
+   * it will be not set as <code>NULL</code> at the instance object.
+   * 
+   * @param instance
+   * @param keys
+   * @return
+   */
+  public <T> T setKeyFields(final T instance, final Map<String, Object> keys) {
+    List<Field> fields = getAnnotatedFields(instance, EdmKey.class);
+
+    for (Field field : fields) {
+      String propertyName = getPropertyName(field);
+      Object keyValue = keys.get(propertyName);
+      setValueForProperty(instance, propertyName, keyValue);
+    }
+
+    return instance;
+  }
+
+  public static final class ODataAnnotationException extends ODataException {
+    private static final long serialVersionUID = 42L;
+
+    public ODataAnnotationException(final String message) {
+      super(message);
+    }
+
+    public ODataAnnotationException(final String message, final Exception cause) {
+      super(message, cause);
+    }
+  }
+
+  public class AnnotatedNavInfo {
+    private final Field fromField;
+    private final Field toField;
+    private final EdmNavigationProperty fromNavigation;
+    private final EdmNavigationProperty toNavigation;
+
+    public AnnotatedNavInfo(final Field fromField, final Field toField, final EdmNavigationProperty fromNavigation,
+        final EdmNavigationProperty toNavigation) {
+      this.fromField = fromField;
+      this.toField = toField;
+      this.fromNavigation = fromNavigation;
+      this.toNavigation = toNavigation;
+    }
+
+    public Field getFromField() {
+      return fromField;
+    }
+
+    public Field getToField() {
+      return toField;
+    }
+
+    public EdmMultiplicity getFromMultiplicity() {
+      return getMultiplicity(toNavigation, toField);
+    }
+
+    public EdmMultiplicity getToMultiplicity() {
+      return getMultiplicity(fromNavigation, fromField);
+    }
+
+    public boolean isBiDirectional() {
+      return toNavigation != null;
+    }
+  }
+
+  public AnnotatedNavInfo getCommonNavigationInfo(final Class<?> sourceClass, final Class<?> targetClass) {
+    List<Field> sourceFields = getAnnotatedFields(sourceClass, EdmNavigationProperty.class);
+    List<Field> targetFields = getAnnotatedFields(targetClass, EdmNavigationProperty.class);
+
+    // first try via association name to get full navigation information
+    for (Field sourceField : sourceFields) {
+      final EdmNavigationProperty sourceNav = sourceField.getAnnotation(EdmNavigationProperty.class);
+      final String sourceAssociation = extractRelationshipName(sourceNav, sourceField);
+      for (Field targetField : targetFields) {
+        final EdmNavigationProperty targetNav = targetField.getAnnotation(EdmNavigationProperty.class);
+        final String targetAssociation = extractRelationshipName(targetNav, targetField);
+        if (sourceAssociation.equals(targetAssociation)) {
+          return new AnnotatedNavInfo(sourceField, targetField, sourceNav, targetNav);
+        }
+      }
+    }
+
+    // if nothing was found assume none bi-directinal navigation
+    String targetEntityTypeName = extractEntityTypeName(targetClass);
+    for (Field sourceField : sourceFields) {
+      final EdmNavigationProperty sourceNav = sourceField.getAnnotation(EdmNavigationProperty.class);
+      final String navTargetEntityName = extractEntitTypeName(sourceNav, sourceField);
+
+      if (navTargetEntityName.equals(targetEntityTypeName)) {
+        return new AnnotatedNavInfo(sourceField, null, sourceNav, null);
+      }
+    }
+
+    return null;
+  }
+
+  public Class<?> getFieldTypeForProperty(final Object instance, final String propertyName)
+      throws ODataAnnotationException {
+    if (instance == null) {
+      return null;
+    }
+
+    Field field = getFieldForPropertyName(instance, propertyName, instance.getClass(), true);
+    if (field == null) {
+      throw new ODataAnnotationException("No field for property '" + propertyName
+          + "' found at class '" + instance.getClass() + "'.");
+    }
+    return field.getType();
+  }
+
+  public Object getValueForProperty(final Object instance, final String propertyName) throws ODataAnnotationException {
+    if (instance == null) {
+      return null;
+    }
+
+    Field field = getFieldForPropertyName(instance, propertyName, instance.getClass(), true);
+    if (field == null) {
+      throw new ODataAnnotationException("No field for property '" + propertyName
+          + "' found at class '" + instance.getClass() + "'.");
+    }
+    return getFieldValue(instance, field);
+  }
+
+  public void setValueForProperty(final Object instance, final String propertyName, final Object propertyValue) {
+    if (instance != null) {
+      Field field = getFieldForPropertyName(instance, propertyName, instance.getClass(), true);
+      if (field != null) {
+        setFieldValue(instance, field, propertyValue);
+      }
+    }
+  }
+
+  private Field getFieldForPropertyName(final Object instance, final String propertyName,
+      final Class<?> resultClass, final boolean inherited) {
+    if (instance == null) {
+      return null;
+    }
+
+    Field[] fields = resultClass.getDeclaredFields();
+    for (Field field : fields) {
+      EdmProperty property = field.getAnnotation(EdmProperty.class);
+      if (property != null) {
+        if (property.name().isEmpty() && getCanonicalName(field).equals(propertyName)) {
+          return field;
+        } else if (property.name().equals(propertyName)) {
+          return field;
+        }
+      }
+    }
+
+    Class<?> superClass = resultClass.getSuperclass();
+    if (inherited && superClass != Object.class) {
+      return getFieldForPropertyName(instance, propertyName, superClass, true);
+    }
+
+    return null;
+  }
+
+  public Object getValueForField(final Object instance, final String fieldName,
+      final Class<? extends Annotation> annotation) {
+    if (instance == null) {
+      return null;
+    }
+    return getValueForField(instance, fieldName, instance.getClass(), annotation, true);
+  }
+
+  public Object getValueForField(final Object instance, final Class<? extends Annotation> annotation) {
+    if (instance == null) {
+      return null;
+    }
+    return getValueForField(instance, instance.getClass(), annotation, true);
+  }
+
+  private Object getValueForField(final Object instance, final Class<?> resultClass,
+      final Class<? extends Annotation> annotation, final boolean inherited) {
+    return getValueForField(instance, null, resultClass, annotation, inherited);
+  }
+
+  public Map<String, Object> getValueForAnnotatedFields(final Object instance,
+      final Class<? extends Annotation> annotation) {
+    return getValueForAnnotatedFields(instance, instance.getClass(), annotation, true);
+  }
+
+  private Map<String, Object> getValueForAnnotatedFields(final Object instance, final Class<?> resultClass,
+      final Class<? extends Annotation> annotation, final boolean inherited) {
+    if (instance == null) {
+      return null;
+    }
+
+    Field[] fields = resultClass.getDeclaredFields();
+    Map<String, Object> fieldName2Value = new HashMap<String, Object>();
+
+    for (Field field : fields) {
+      if (field.getAnnotation(annotation) != null) {
+        Object value = getFieldValue(instance, field);
+        final EdmProperty property = field.getAnnotation(EdmProperty.class);
+        final String name = property == null || property.name().isEmpty() ? field.getName() : property.name();
+        fieldName2Value.put(name, value);
+      }
+    }
+
+    Class<?> superClass = resultClass.getSuperclass();
+    if (inherited && superClass != Object.class) {
+      Map<String, Object> tmp = getValueForAnnotatedFields(instance, superClass, annotation, true);
+      fieldName2Value.putAll(tmp);
+    }
+
+    return fieldName2Value;
+  }
+
+  public void setValueForAnnotatedField(final Object instance, final Class<? extends Annotation> annotation,
+      final Object value)
+      throws ODataAnnotationException {
+    List<Field> fields = getAnnotatedFields(instance, annotation);
+
+    if (fields.isEmpty()) {
+      throw new ODataAnnotationException("No field found for annotation '" + annotation
+          + "' on instance '" + instance + "'.");
+    } else if (fields.size() > 1) {
+      throw new ODataAnnotationException("More then one field found for annotation '" + annotation
+          + "' on instance '" + instance + "'.");
+    }
+
+    setFieldValue(instance, fields.get(0), value);
+  }
+
+  public void setValuesToAnnotatedFields(final Object instance,
+      final Class<? extends Annotation> annotation, final Map<String, Object> fieldName2Value) {
+    List<Field> fields = getAnnotatedFields(instance, annotation);
+
+    // XXX: refactore
+    for (Field field : fields) {
+      final String canonicalName = getCanonicalName(field);
+      if (fieldName2Value.containsKey(canonicalName)) {
+        Object value = fieldName2Value.get(canonicalName);
+        setFieldValue(instance, field, value);
+      }
+    }
+  }
+
+  public List<Field> getAnnotatedFields(final Object instance, final Class<? extends Annotation> annotation) {
+    if (instance == null) {
+      return null;
+    }
+    return getAnnotatedFields(instance.getClass(), annotation, true);
+  }
+
+  public List<Field> getAnnotatedFields(final Class<?> fieldClass, final Class<? extends Annotation> annotation) {
+    return getAnnotatedFields(fieldClass, annotation, true);
+  }
+
+  /**
+   * 
+   * @param instance
+   * @param resultClass
+   * @param annotation
+   * @param inherited
+   * @return
+   */
+  private List<Field> getAnnotatedFields(final Class<?> resultClass,
+      final Class<? extends Annotation> annotation, final boolean inherited) {
+    if (resultClass == null) {
+      return null;
+    }
+
+    Field[] fields = resultClass.getDeclaredFields();
+    List<Field> annotatedFields = new ArrayList<Field>();
+
+    for (Field field : fields) {
+      if (field.getAnnotation(annotation) != null) {
+        annotatedFields.add(field);
+      }
+    }
+
+    Class<?> superClass = resultClass.getSuperclass();
+    if (inherited && superClass != Object.class) {
+      List<Field> tmp = getAnnotatedFields(superClass, annotation, true);
+      annotatedFields.addAll(tmp);
+    }
+
+    return annotatedFields;
+  }
+
+  private Object getValueForField(final Object instance, final String fieldName, final Class<?> resultClass,
+      final Class<? extends Annotation> annotation, final boolean inherited) {
+    if (instance == null) {
+      return null;
+    }
+
+    Field[] fields = resultClass.getDeclaredFields();
+    for (Field field : fields) {
+      if (field.getAnnotation(annotation) != null
+          && (fieldName == null || field.getName().equals(fieldName))) {
+        return getFieldValue(instance, field);
+      }
+    }
+
+    Class<?> superClass = resultClass.getSuperclass();
+    if (inherited && superClass != Object.class) {
+      return getValueForField(instance, fieldName, superClass, annotation, true);
+    }
+
+    return null;
+  }
+
+  private Object getFieldValue(final Object instance, final Field field) {
+    try {
+      boolean access = field.isAccessible();
+      field.setAccessible(true);
+      Object value = field.get(instance);
+      field.setAccessible(access);
+      return value;
+    } catch (IllegalArgumentException ex) { // should never happen
+      throw new ODataRuntimeException(ex);
+    } catch (IllegalAccessException ex) { // should never happen
+      throw new ODataRuntimeException(ex);
+    }
+  }
+
+  private void setFieldValue(final Object instance, final Field field, final Object value) {
+    try {
+      Object usedValue = value;
+      if (value != null
+          && field.getType() != value.getClass()
+          && value.getClass() == String.class) {
+        usedValue = convert(field, (String) value);
+      }
+      boolean access = field.isAccessible();
+      field.setAccessible(true);
+      field.set(instance, usedValue);
+      field.setAccessible(access);
+    } catch (IllegalArgumentException ex) { // should never happen
+      throw new ODataRuntimeException(ex);
+    } catch (IllegalAccessException ex) { // should never happen
+      throw new ODataRuntimeException(ex);
+    }
+  }
+
+  public Object convert(final Field field, final String propertyValue) {
+    Class<?> fieldClass = field.getType();
+    try {
+      EdmProperty property = field.getAnnotation(EdmProperty.class);
+      EdmSimpleTypeKind type = mapTypeKind(property.type());
+      return type.getEdmSimpleTypeInstance().valueOfString(propertyValue,
+          EdmLiteralKind.DEFAULT, null, fieldClass);
+    } catch (EdmSimpleTypeException ex) {
+      throw new ODataRuntimeException("Conversion failed for string property with error: "
+          + ex.getMessage(), ex);
+    }
+  }
+
+  public boolean isEdmAnnotated(final Object object) {
+    if (object == null) {
+      return false;
+    }
+    return isEdmAnnotated(object.getClass());
+  }
+
+  public boolean isEdmTypeAnnotated(final Class<?> clazz) {
+    boolean isComplexEntity = clazz.getAnnotation(EdmComplexType.class) != null;
+    boolean isEntity = clazz.getAnnotation(EdmEntityType.class) != null;
+    return isComplexEntity || isEntity;
+  }
+
+  public boolean isEdmAnnotated(final Class<?> clazz) {
+    if (clazz == null) {
+      return false;
+    } else {
+      final boolean isEntity = null != clazz.getAnnotation(EdmEntityType.class);
+      final boolean isEntitySet = null != clazz.getAnnotation(EdmEntitySet.class);
+      final boolean isComplexEntity = null != clazz.getAnnotation(EdmComplexType.class);
+      return isEntity || isComplexEntity || isEntitySet;
+    }
+  }
+
+  public String getCanonicalName(final Field field) {
+    return firstCharToUpperCase(field.getName());
+  }
+
+  public String getCanonicalName(final Class<?> clazz) {
+    return firstCharToUpperCase(clazz.getSimpleName());
+  }
+
+  private String firstCharToUpperCase(final String content) {
+    if (content == null || content.isEmpty()) {
+      return content;
+    }
+    return content.substring(0, 1).toUpperCase(Locale.ENGLISH) + content.substring(1);
+  }
+
+  public EdmSimpleTypeKind mapTypeKind(final org.apache.olingo.odata2.api.annotation.edm.EdmType type) {
+    switch (type) {
+    case BINARY:
+      return EdmSimpleTypeKind.Binary;
+    case BOOLEAN:
+      return EdmSimpleTypeKind.Boolean;
+    case BYTE:
+      return EdmSimpleTypeKind.Byte;
+    case COMPLEX:
+      return EdmSimpleTypeKind.Null;
+    case DATE_TIME:
+      return EdmSimpleTypeKind.DateTime;
+    case DATE_TIME_OFFSET:
+      return EdmSimpleTypeKind.DateTimeOffset;
+    case DECIMAL:
+      return EdmSimpleTypeKind.Decimal;
+    case DOUBLE:
+      return EdmSimpleTypeKind.Double;
+    case GUID:
+      return EdmSimpleTypeKind.Guid;
+    case INT16:
+      return EdmSimpleTypeKind.Int16;
+    case INT32:
+      return EdmSimpleTypeKind.Int32;
+    case INT64:
+      return EdmSimpleTypeKind.Int64;
+    case NULL:
+      return EdmSimpleTypeKind.Null;
+    case SBYTE:
+      return EdmSimpleTypeKind.SByte;
+    case SINGLE:
+      return EdmSimpleTypeKind.Single;
+    case STRING:
+      return EdmSimpleTypeKind.String;
+    case TIME:
+      return EdmSimpleTypeKind.Time;
+    default:
+      throw new ODataRuntimeException("Unknown type '" + type
+          + "' for mapping to EdmSimpleTypeKind.");
+    }
+  }
+
+  public EdmMultiplicity mapMultiplicity(final Multiplicity multiplicity) {
+    switch (multiplicity) {
+    case ZERO_OR_ONE:
+      return EdmMultiplicity.ZERO_TO_ONE;
+    case ONE:
+      return EdmMultiplicity.ONE;
+    case MANY:
+      return EdmMultiplicity.MANY;
+    default:
+      throw new ODataRuntimeException("Unknown type '" + multiplicity + "' for mapping to EdmMultiplicity.");
+    }
+  }
+
+  /**
+   * 
+   */
+  private static class EdmAnnotationException extends RuntimeException {
+
+    private static final long serialVersionUID = 42L;
+
+    public EdmAnnotationException(final String message) {
+      super(message);
+    }
+  }
+
+  public String getCanonicalNamespace(final Class<?> aClass) {
+    return generateNamespace(aClass);
+  }
+
+  public String extractContainerName(final Class<?> aClass) {
+    EdmEntitySet entitySet = aClass.getAnnotation(EdmEntitySet.class);
+    if (entitySet != null) {
+      String containerName = entitySet.container();
+      if (!containerName.isEmpty()) {
+        return containerName;
+      }
+    }
+    return DEFAULT_CONTAINER_NAME;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/3bd59050/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelper.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelper.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelper.java
new file mode 100644
index 0000000..fa575ae
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/util/ClassHelper.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.annotation.processor.core.util;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FilenameFilter;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ *
+ */
+public class ClassHelper {
+
+  private static final File[] EMPTY_FILE_ARRAY = new File[0];
+
+  private static final FilenameFilter CLASSFILE_FILTER = new FilenameFilter() {
+    @Override
+    public boolean accept(final File dir, final String name) {
+      return name.endsWith(CLASSFILE_ENDING);
+    }
+
+    public static final String CLASSFILE_ENDING = ".class";
+  };
+
+  private static final FileFilter FOLDER_FILTER = new FileFilter() {
+    @Override
+    public boolean accept(final File pathname) {
+      return pathname.isDirectory();
+    }
+  };
+
+  public static final List<Class<?>> loadClasses(final String packageToScan, final ClassValidator cv) {
+    return loadClasses(packageToScan, CLASSFILE_FILTER, cv);
+  }
+
+  public static final List<Class<?>> loadClasses(final String packageToScan, final FilenameFilter ff,
+      final ClassValidator cv) {
+    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+    String folderToScan = packageToScan.replace(".", "/");
+    URL url = classLoader.getResource(folderToScan);
+    if (url == null) {
+      throw new IllegalArgumentException("No folder to scan found for package '" + packageToScan + "'.");
+    }
+    File folder = new File(url.getFile());
+    File[] classFiles = folder.listFiles(ff);
+    if (classFiles == null) {
+      classFiles = EMPTY_FILE_ARRAY;
+    }
+
+    List<Class<?>> annotatedClasses = new ArrayList<Class<?>>(classFiles.length);
+    for (File file : classFiles) {
+      String name = file.getName();
+      String fqn = packageToScan + "." + name.substring(0, name.length() - 6);
+      try {
+        Class<?> c = classLoader.loadClass(fqn);
+        if (cv.isClassValid(c)) {
+          annotatedClasses.add(c);
+        }
+      } catch (ClassNotFoundException ex) {
+        throw new IllegalArgumentException("Exception during class loading of class '" + fqn +
+            "' with message '" + ex.getMessage() + "'.");
+      }
+    }
+
+    // recursive search
+    File[] subfolders = listSubFolder(folder);
+    for (File file : subfolders) {
+      List<Class<?>> subFolderClazzes = loadClasses(packageToScan + "." + file.getName(), ff, cv);
+      annotatedClasses.addAll(subFolderClazzes);
+    }
+    //
+
+    return annotatedClasses;
+  }
+
+  public static Object getFieldValue(final Object instance, final Field field) {
+    try {
+      synchronized (field) {
+        boolean access = field.isAccessible();
+        field.setAccessible(true);
+        Object value = field.get(instance);
+        field.setAccessible(access);
+        return value;
+      }
+    } catch (IllegalArgumentException ex) { // should never happen
+      throw new ODataRuntimeException(ex);
+    } catch (IllegalAccessException ex) { // should never happen
+      throw new ODataRuntimeException(ex);
+    }
+  }
+
+  public static void setFieldValue(final Object instance, final Field field, final Object value) {
+    try {
+      synchronized (field) {
+        boolean access = field.isAccessible();
+        field.setAccessible(true);
+        field.set(instance, value);
+        field.setAccessible(access);
+      }
+    } catch (IllegalArgumentException ex) { // should never happen
+      throw new ODataRuntimeException(ex);
+    } catch (IllegalAccessException ex) { // should never happen
+      throw new ODataRuntimeException(ex);
+    }
+  }
+
+  private static File[] listSubFolder(final File folder) {
+    File[] subfolders = folder.listFiles(FOLDER_FILTER);
+    if (subfolders == null) {
+      return EMPTY_FILE_ARRAY;
+    }
+    return subfolders;
+  }
+
+  public interface ClassValidator {
+    boolean isClassValid(Class<?> c);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/3bd59050/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
deleted file mode 100644
index a53ee8f..0000000
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
+++ /dev/null
@@ -1,376 +0,0 @@
-/**
- * *****************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
- * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
- * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- ***************************************************************************** 
- */
-package org.apache.olingo.odata2.core.annotation.data;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.olingo.odata2.api.annotation.edm.EdmMediaResourceContent;
-import org.apache.olingo.odata2.api.annotation.edm.EdmMediaResourceMimeType;
-import org.apache.olingo.odata2.api.annotation.edm.EdmNavigationProperty;
-import org.apache.olingo.odata2.api.data.DataSource;
-import org.apache.olingo.odata2.api.edm.EdmEntitySet;
-import org.apache.olingo.odata2.api.edm.EdmException;
-import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
-import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
-import org.apache.olingo.odata2.api.exception.ODataApplicationException;
-import org.apache.olingo.odata2.api.exception.ODataException;
-import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
-import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
-import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper;
-import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper.AnnotatedNavInfo;
-import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper.ODataAnnotationException;
-import org.apache.olingo.odata2.core.annotation.util.ClassHelper;
-import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
-
-public class AnnotationInMemoryDs implements DataSource {
-
-  private static final AnnotationHelper ANNOTATION_HELPER = new AnnotationHelper();
-  private final Map<String, DataStore<Object>> dataStores = new HashMap<String, DataStore<Object>>();
-  private final boolean persistInMemory;
-
-  public AnnotationInMemoryDs(final String packageToScan) throws ODataException {
-    this(packageToScan, true);
-  }
-
-  public AnnotationInMemoryDs(final String packageToScan, final boolean persistInMemory) throws ODataException {
-    this.persistInMemory = persistInMemory;
-    List<Class<?>> foundClasses = ClassHelper.loadClasses(packageToScan, new ClassHelper.ClassValidator() {
-      @Override
-      public boolean isClassValid(final Class<?> c) {
-        return null != c.getAnnotation(org.apache.olingo.odata2.api.annotation.edm.EdmEntitySet.class);
-      }
-    });
-
-    init(foundClasses);
-  }
-
-  @SuppressWarnings("unchecked")
-  private void init(final List<Class<?>> foundClasses) throws ODataException {
-    try {
-      for (Class<?> clz : foundClasses) {
-        DataStore<Object> dhs = (DataStore<Object>) DataStore.createInMemory(clz, persistInMemory);
-        String entitySetName = ANNOTATION_HELPER.extractEntitySetName(clz);
-        dataStores.put(entitySetName, dhs);
-      }
-    } catch (DataStore.DataStoreException e) {
-      throw new ODataException("Error in DataStore initilization with message: " + e.getMessage(), e);
-    }
-  }
-
-  public <T> DataStore<T> getDataStore(final Class<T> clazz) {
-    String entitySetName = ANNOTATION_HELPER.extractEntitySetName(clazz);
-    return (DataStore<T>) dataStores.get(entitySetName);
-  }
-
-  @Override
-  public List<?> readData(final EdmEntitySet entitySet) throws ODataNotImplementedException,
-      ODataNotFoundException, EdmException, ODataApplicationException {
-
-    DataStore<Object> holder = getDataStore(entitySet);
-    if (holder != null) {
-      return new ArrayList<Object>(holder.read());
-    }
-
-    throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
-  }
-
-  @Override
-  public Object readData(final EdmEntitySet entitySet, final Map<String, Object> keys)
-      throws ODataNotFoundException, EdmException, ODataApplicationException {
-
-    DataStore<Object> store = getDataStore(entitySet);
-    if (store != null) {
-      Object keyInstance = store.createInstance();
-      ANNOTATION_HELPER.setKeyFields(keyInstance, keys);
-
-      Object result = store.read(keyInstance);
-      if (result != null) {
-        return result;
-      }
-    }
-
-    throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
-  }
-
-  @Override
-  public Object readData(final EdmFunctionImport function, final Map<String, Object> parameters,
-      final Map<String, Object> keys)
-      throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
-    throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
-  }
-
-  @Override
-  public Object readRelatedData(final EdmEntitySet sourceEntitySet, final Object sourceData,
-      final EdmEntitySet targetEntitySet,
-      final Map<String, Object> targetKeys)
-      throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
-
-    DataStore<?> sourceStore = dataStores.get(sourceEntitySet.getName());
-    DataStore<?> targetStore = dataStores.get(targetEntitySet.getName());
-
-    AnnotatedNavInfo navInfo = ANNOTATION_HELPER.getCommonNavigationInfo(
-        sourceStore.getDataTypeClass(), targetStore.getDataTypeClass());
-    Field sourceField = navInfo.getFromField();
-    if (sourceField == null) {
-      throw new ODataRuntimeException("Missing source field for related data (sourceStore='" + sourceStore
-          + "', targetStore='" + targetStore + "').");
-    }
-
-    Object navigationInstance = getValue(sourceField, sourceData);
-    List<Object> resultData = new ArrayList<Object>();
-    for (Object targetInstance : targetStore.read()) {
-      if (navigationInstance instanceof Collection) {
-        for (Object object : (Collection<?>) navigationInstance) {
-          if (targetStore.isKeyEqualChecked(targetInstance, object)) {
-            resultData.add(targetInstance);
-          }
-        }
-      } else if (targetStore.isKeyEqualChecked(targetInstance, navigationInstance)) {
-        resultData.add(targetInstance);
-      }
-    }
-
-    if (navInfo.getToMultiplicity() == EdmMultiplicity.MANY) {
-      if (targetKeys.isEmpty()) {
-        return resultData;
-      } else {
-        Object keyInstance = targetStore.createInstance();
-        ANNOTATION_HELPER.setKeyFields(keyInstance, targetKeys);
-        for (Object result : resultData) {
-          if (targetStore.isKeyEqualChecked(result, keyInstance)) {
-            return result;
-          }
-        }
-        return null;
-      }
-    } else {
-      if (resultData.isEmpty()) {
-        return null;
-      }
-      return resultData.get(0);
-    }
-  }
-
-  @Override
-  public BinaryData readBinaryData(final EdmEntitySet entitySet, final Object mediaLinkEntryData)
-      throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
-
-    Object data = ANNOTATION_HELPER.getValueForField(mediaLinkEntryData, EdmMediaResourceContent.class);
-    Object mimeType = ANNOTATION_HELPER.getValueForField(mediaLinkEntryData, EdmMediaResourceMimeType.class);
-
-    if(data == null && mimeType == null) {
-      DataStore<Object> dataStore = getDataStore(entitySet);
-      Object readEntry = dataStore.read(mediaLinkEntryData);
-      if(readEntry != null) {
-        data = ANNOTATION_HELPER.getValueForField(readEntry, EdmMediaResourceContent.class);
-        mimeType = ANNOTATION_HELPER.getValueForField(readEntry, EdmMediaResourceMimeType.class);
-      }
-    }
-    
-    return new BinaryData((byte[]) data, String.valueOf(mimeType));
-  }
-
-  @Override
-  public Object newDataObject(final EdmEntitySet entitySet)
-      throws ODataNotImplementedException, EdmException, ODataApplicationException {
-
-    DataStore<Object> dataStore = getDataStore(entitySet);
-    if (dataStore != null) {
-      return dataStore.createInstance();
-    }
-
-    throw new ODataRuntimeException("No DataStore found for entitySet with name: " + entitySet.getName());
-  }
-
-  @Override
-  public void writeBinaryData(final EdmEntitySet entitySet, final Object mediaEntityInstance,
-      final BinaryData binaryData)
-      throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
-
-    try {
-      DataStore<Object> dataStore = getDataStore(entitySet);
-      Object readEntry = dataStore.read(mediaEntityInstance);
-      if(readEntry == null) {
-        throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
-      } else {
-        ANNOTATION_HELPER.setValueForAnnotatedField(
-            mediaEntityInstance, EdmMediaResourceContent.class, binaryData.getData());
-        ANNOTATION_HELPER.setValueForAnnotatedField(
-            mediaEntityInstance, EdmMediaResourceMimeType.class, binaryData.getMimeType());
-      }
-    } catch (ODataAnnotationException e) {
-      throw new ODataRuntimeException("Invalid media resource annotation at entity set '" + entitySet.getName()
-          + "' with message '" + e.getMessage() + "'.", e);
-    }
-  }
-
-  /**
-   * <p>Updates a single data object identified by the specified entity set and key fields of
-   * the data object.</p>
-   * @param entitySet the {@link EdmEntitySet} the object must correspond to
-   * @param data the data object of the new entity
-   * @return updated data object instance
-   * @throws org.apache.olingo.odata2.api.exception.ODataNotImplementedException
-   * @throws org.apache.olingo.odata2.api.edm.EdmException
-   * @throws org.apache.olingo.odata2.api.exception.ODataApplicationException
-   */
-  public Object updateData(final EdmEntitySet entitySet, final Object data)
-      throws ODataNotImplementedException, EdmException, ODataApplicationException {
-
-    DataStore<Object> dataStore = getDataStore(entitySet);
-    return dataStore.update(data);
-  }
-
-  @Override
-  public void deleteData(final EdmEntitySet entitySet, final Map<String, Object> keys)
-      throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
-    DataStore<Object> dataStore = getDataStore(entitySet);
-    Object keyInstance = dataStore.createInstance();
-    ANNOTATION_HELPER.setKeyFields(keyInstance, keys);
-    dataStore.delete(keyInstance);
-  }
-
-  @Override
-  public void createData(final EdmEntitySet entitySet, final Object data)
-      throws ODataNotImplementedException, EdmException, ODataApplicationException {
-
-    DataStore<Object> dataStore = getDataStore(entitySet);
-    dataStore.create(data);
-  }
-
-  @Override
-  public void deleteRelation(final EdmEntitySet sourceEntitySet, final Object sourceData,
-      final EdmEntitySet targetEntitySet,
-      final Map<String, Object> targetKeys)
-      throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
-    throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
-  }
-
-  @Override
-  public void writeRelation(final EdmEntitySet sourceEntitySet, final Object sourceEntity,
-      final EdmEntitySet targetEntitySet,
-      final Map<String, Object> targetEntityValues)
-      throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
-    // get common data
-    DataStore<Object> sourceStore = dataStores.get(sourceEntitySet.getName());
-    DataStore<Object> targetStore = dataStores.get(targetEntitySet.getName());
-
-    AnnotatedNavInfo commonNavInfo = ANNOTATION_HELPER.getCommonNavigationInfo(
-        sourceStore.getDataTypeClass(), targetStore.getDataTypeClass());
-
-    // get and validate source fields
-    Field sourceField = commonNavInfo.getFromField();
-    if (sourceField == null) {
-      throw new ODataRuntimeException("Missing source field for related data (sourceStore='" + sourceStore
-          + "', targetStore='" + targetStore + "').");
-    }
-
-    // get related target entity
-    Object targetEntity = targetStore.createInstance();
-    ANNOTATION_HELPER.setKeyFields(targetEntity, targetEntityValues);
-    targetEntity = targetStore.read(targetEntity);
-
-    // set at source
-    setValueAtNavigationField(sourceEntity, sourceField, targetEntity);
-    // set at target
-    Field targetField = commonNavInfo.getToField();
-    if (targetField != null) {
-      setValueAtNavigationField(targetEntity, targetField, sourceEntity);
-    }
-  }
-
-  /**
-   * Set (Multiplicity != *) or add (Multiplicity == *) <code>value</code> at <code>field</code>
-   * of <code>instance</code>.
-   * 
-   * @param instance
-   * @param field
-   * @param value
-   * @throws EdmException
-   */
-  private void setValueAtNavigationField(final Object instance, final Field field, final Object value)
-      throws EdmException {
-    Class<?> fieldTypeClass = field.getType();
-    if (Collection.class.isAssignableFrom(fieldTypeClass)) {
-      @SuppressWarnings("unchecked")
-      Collection<Object> collection = (Collection<Object>) ANNOTATION_HELPER.getValueForField(
-          instance, field.getName(), EdmNavigationProperty.class);
-      if (collection == null) {
-        collection = new ArrayList<Object>();
-        setValue(instance, field, collection);
-      }
-      collection.add(value);
-    } else if (fieldTypeClass.isArray()) {
-      throw new ODataRuntimeException("Write relations for internal used arrays is not supported.");
-    } else {
-      setValue(instance, field, value);
-    }
-  }
-
-  /**
-   * Returns corresponding DataStore for EdmEntitySet or if no data store is registered an
-   * ODataRuntimeException is thrown.
-   * Never returns NULL.
-   * 
-   * @param entitySet for which the corresponding DataStore is returned
-   * @return a DataStore object
-   * @throws EdmException
-   * @throws ODataRuntimeException if no DataStore is found
-   */
-  private DataStore<Object> getDataStore(final EdmEntitySet entitySet) throws EdmException {
-    final String name = entitySet.getName();
-    DataStore<Object> dataStore = dataStores.get(name);
-    if (dataStore == null) {
-      throw new ODataRuntimeException("No DataStore found for entity set '" + entitySet + "'.");
-    }
-    return dataStore;
-  }
-
-  private Object getValue(final Field field, final Object instance) {
-    try {
-      boolean access = field.isAccessible();
-      field.setAccessible(true);
-      Object value = field.get(instance);
-      field.setAccessible(access);
-      return value;
-    } catch (IllegalArgumentException e) {
-      throw new ODataRuntimeException("Error for getting value of field '"
-          + field + "' at instance '" + instance + "'.", e);
-    } catch (IllegalAccessException e) {
-      throw new ODataRuntimeException("Error for getting value of field '"
-          + field + "' at instance '" + instance + "'.", e);
-    }
-  }
-
-  private void setValue(final Object instance, final Field field, final Object value) {
-    try {
-      boolean access = field.isAccessible();
-      field.setAccessible(true);
-      field.set(instance, value);
-      field.setAccessible(access);
-    } catch (IllegalArgumentException e) {
-      throw new ODataRuntimeException("Error for setting value of field: '"
-          + field + "' at instance: '" + instance + "'.", e);
-    } catch (IllegalAccessException e) {
-      throw new ODataRuntimeException("Error for setting value of field: '"
-          + field + "' at instance: '" + instance + "'.", e);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/3bd59050/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationValueAccess.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationValueAccess.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationValueAccess.java
deleted file mode 100644
index 5703295..0000000
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationValueAccess.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.annotation.data;
-
-import org.apache.olingo.odata2.api.data.ValueAccess;
-import org.apache.olingo.odata2.api.edm.EdmMapping;
-import org.apache.olingo.odata2.api.edm.EdmProperty;
-import org.apache.olingo.odata2.api.exception.ODataException;
-import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
-import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper;
-
-/**
- *
- */
-public class AnnotationValueAccess implements ValueAccess {
-  private final AnnotationHelper annotationHelper = new AnnotationHelper();
-
-  /**
-   * Retrieves the value of an EDM property for the given data object.
-   * @param data the Java data object
-   * @param property the requested {@link EdmProperty}
-   * @return the requested property value
-   */
-  @Override
-  public <T> Object getPropertyValue(final T data, final EdmProperty property) throws ODataException {
-    if (data == null) {
-      return null;
-    } else if (annotationHelper.isEdmAnnotated(data)) {
-      return annotationHelper.getValueForProperty(data, property.getName());
-    }
-    throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
-  }
-
-  /**
-   * Sets the value of an EDM property for the given data object.
-   * @param data the Java data object
-   * @param property the {@link EdmProperty}
-   * @param value the new value of the property
-   */
-  @Override
-  public <T, V> void setPropertyValue(final T data, final EdmProperty property, final V value) throws ODataException {
-    if (annotationHelper.isEdmAnnotated(data)) {
-      annotationHelper.setValueForProperty(data, property.getName(), value);
-    } else {
-      throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
-    }
-  }
-
-  /**
-   * Retrieves the Java type of an EDM property for the given data object.
-   * @param data the Java data object
-   * @param property the requested {@link EdmProperty}
-   * @return the requested Java type
-   */
-  @Override
-  public <T> Class<?> getPropertyType(final T data, final EdmProperty property) throws ODataException {
-    if (annotationHelper.isEdmAnnotated(data)) {
-      Class<?> fieldType = annotationHelper.getFieldTypeForProperty(data, property.getName());
-      if (fieldType == null) {
-        throw new ODataException("No field type found for property " + property);
-      }
-      return fieldType;
-    }
-    throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
-  }
-
-  /**
-   * Retrieves the value defined by a mapping object for the given data object.
-   * @param data the Java data object
-   * @param mapping the requested {@link EdmMapping}
-   * @return the requested value
-   */
-  @Override
-  public <T> Object getMappingValue(final T data, final EdmMapping mapping) throws ODataException {
-    if (mapping != null && mapping.getMediaResourceMimeTypeKey() != null) {
-      return annotationHelper.getValueForProperty(data, mapping.getMediaResourceMimeTypeKey());
-    }
-    return null;
-  }
-
-  /**
-   * Sets the value defined by a mapping object for the given data object.
-   * @param data the Java data object
-   * @param mapping the {@link EdmMapping}
-   * @param value the new value
-   */
-  @Override
-  public <T, V> void setMappingValue(final T data, final EdmMapping mapping, final V value) throws ODataException {
-    if (mapping != null && mapping.getMediaResourceMimeTypeKey() != null) {
-      annotationHelper.setValueForProperty(data, mapping.getMediaResourceMimeTypeKey(), value);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/3bd59050/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/BeanPropertyAccess.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/BeanPropertyAccess.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/BeanPropertyAccess.java
deleted file mode 100644
index 49794be..0000000
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/BeanPropertyAccess.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.annotation.data;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
-import org.apache.olingo.odata2.api.data.ValueAccess;
-import org.apache.olingo.odata2.api.edm.EdmException;
-import org.apache.olingo.odata2.api.edm.EdmMapping;
-import org.apache.olingo.odata2.api.edm.EdmProperty;
-import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
-import org.apache.olingo.odata2.api.exception.ODataException;
-import org.apache.olingo.odata2.api.exception.ODataHttpException;
-import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
-
-/**
- * Data access.
- */
-public class BeanPropertyAccess implements ValueAccess {
-
-  @Override
-  public <T> Object getPropertyValue(final T data, final EdmProperty property) throws ODataException {
-    return getValue(data, getGetterMethodName(property));
-  }
-
-  @Override
-  public <T, V> void setPropertyValue(final T data, final EdmProperty property, final V value) throws ODataException {
-    final String methodName = getSetterMethodName(getGetterMethodName(property));
-    if (methodName != null) {
-      setValue(data, methodName, value);
-    }
-  }
-
-  @Override
-  public <T> Class<?> getPropertyType(final T data, final EdmProperty property) throws ODataException {
-    return getType(data, getGetterMethodName(property));
-  }
-
-  @Override
-  public <T> Object getMappingValue(final T data, final EdmMapping mapping) throws ODataException {
-    if (mapping != null && mapping.getMimeType() != null) {
-      return getValue(data, mapping.getMimeType());
-    }
-    return null;
-  }
-
-  @Override
-  public <T, V> void setMappingValue(final T data, final EdmMapping mapping, final V value) throws ODataException {
-    if (mapping != null && mapping.getMimeType() != null) {
-      setValue(data, getSetterMethodName(mapping.getMimeType()), value);
-    }
-  }
-
-  private String getGetterMethodName(final EdmProperty property) throws EdmException {
-    final String prefix = isBooleanProperty(property) ? "is" : "get";
-    final String defaultMethodName = prefix + property.getName();
-    return property.getMapping() == null || property.getMapping().getInternalName() == null ?
-        defaultMethodName : property.getMapping().getInternalName();
-  }
-
-  private boolean isBooleanProperty(final EdmProperty property) throws EdmException {
-    return property.isSimple()
-        && property.getType() == EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance();
-  }
-
-  private String getSetterMethodName(final String getterMethodName) {
-    return getterMethodName.contains(".") ?
-        null : getterMethodName.replaceFirst("^is", "set").replaceFirst("^get", "set");
-  }
-
-  private <T> Object getValue(final T data, final String methodName) throws ODataNotFoundException {
-    Object dataObject = data;
-
-    for (final String method : methodName.split("\\.", -1)) {
-      if (dataObject != null) {
-        try {
-          dataObject = dataObject.getClass().getMethod(method).invoke(dataObject);
-        } catch (SecurityException e) {
-          throw new ODataNotFoundException(ODataHttpException.COMMON, e);
-        } catch (NoSuchMethodException e) {
-          throw new ODataNotFoundException(ODataHttpException.COMMON, e);
-        } catch (IllegalArgumentException e) {
-          throw new ODataNotFoundException(ODataHttpException.COMMON, e);
-        } catch (IllegalAccessException e) {
-          throw new ODataNotFoundException(ODataHttpException.COMMON, e);
-        } catch (InvocationTargetException e) {
-          throw new ODataNotFoundException(ODataHttpException.COMMON, e);
-        }
-      }
-    }
-
-    return dataObject;
-  }
-
-  private <T, V> void setValue(final T data, final String methodName, final V value)
-      throws ODataNotFoundException {
-    try {
-      boolean found = false;
-      for (final Method method : Arrays.asList(data.getClass().getMethods())) {
-        if (method.getName().equals(methodName)) {
-          found = true;
-          final Class<?> type = method.getParameterTypes()[0];
-          if (value == null) {
-            if (type.equals(byte.class) || type.equals(short.class) || type.equals(int.class)
-                || type.equals(long.class) || type.equals(char.class)) {
-              method.invoke(data, 0);
-            } else if (type.equals(float.class) || type.equals(double.class)) {
-              method.invoke(data, 0.0);
-            } else if (type.equals(boolean.class)) {
-              method.invoke(data, false);
-            } else {
-              method.invoke(data, value);
-            }
-          } else {
-            method.invoke(data, value);
-          }
-          break;
-        }
-      }
-      if (!found) {
-        throw new ODataNotFoundException(null);
-      }
-    } catch (SecurityException e) {
-      throw new ODataNotFoundException(null, e);
-    } catch (IllegalArgumentException e) {
-      throw new ODataNotFoundException(null, e);
-    } catch (IllegalAccessException e) {
-      throw new ODataNotFoundException(null, e);
-    } catch (InvocationTargetException e) {
-      throw new ODataNotFoundException(null, e);
-    }
-  }
-
-  private <T> Class<?> getType(final T data, final String methodName) throws ODataNotFoundException {
-    if (data == null) {
-      throw new ODataNotFoundException(ODataHttpException.COMMON);
-    }
-
-    Class<?> type = data.getClass();
-    for (final String method : methodName.split("\\.", -1)) {
-      try {
-        type = type.getMethod(method).getReturnType();
-        if (type.isPrimitive()) {
-          if (type == boolean.class) {
-            type = Boolean.class;
-          } else if (type == byte.class) {
-            type = Byte.class;
-          } else if (type == short.class) {
-            type = Short.class;
-          } else if (type == int.class) {
-            type = Integer.class;
-          } else if (type == long.class) {
-            type = Long.class;
-          } else if (type == float.class) {
-            type = Float.class;
-          } else if (type == double.class) {
-            type = Double.class;
-          }
-        }
-      } catch (final SecurityException e) {
-        throw new ODataNotFoundException(ODataHttpException.COMMON, e);
-      } catch (final NoSuchMethodException e) {
-        throw new ODataNotFoundException(ODataHttpException.COMMON, e);
-      }
-    }
-    return type;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/3bd59050/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/DataStore.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/DataStore.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/DataStore.java
deleted file mode 100644
index ab52c0b..0000000
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/DataStore.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.core.annotation.data;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.olingo.odata2.api.annotation.edm.EdmKey;
-import org.apache.olingo.odata2.api.exception.ODataApplicationException;
-import org.apache.olingo.odata2.core.annotation.util.AnnotationHelper;
-import org.apache.olingo.odata2.core.annotation.util.ClassHelper;
-import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
-
-/**
- *
- */
-public class DataStore<T> {
-
-  private static final AnnotationHelper ANNOTATION_HELPER = new AnnotationHelper();
-  private final Map<KeyElement, T> dataStore;
-  private final Class<T> dataTypeClass;
-  private final KeyAccess keyAccess;
-
-  private static class InMemoryDataStore {
-    private static final Map<Class<?>, DataStore<?>> c2ds = new HashMap<Class<?>, DataStore<?>>();
-
-    @SuppressWarnings("unchecked")
-    static synchronized DataStore<?> getInstance(final Class<?> clz, final boolean createNewInstance)
-        throws DataStoreException {
-      DataStore<?> ds = c2ds.get(clz);
-      if (createNewInstance || ds == null) {
-        ds = new DataStore<Object>((Class<Object>) clz);
-        c2ds.put(clz, ds);
-      }
-      return ds;
-    }
-  }
-
-  @SuppressWarnings("unchecked")
-  public static <T> DataStore<T> createInMemory(final Class<T> clazz) throws DataStoreException {
-    return (DataStore<T>) InMemoryDataStore.getInstance(clazz, true);
-  }
-
-  @SuppressWarnings("unchecked")
-  public static <T> DataStore<T> createInMemory(final Class<T> clazz, final boolean keepExisting)
-      throws DataStoreException {
-    return (DataStore<T>) InMemoryDataStore.getInstance(clazz, !keepExisting);
-  }
-
-  private DataStore(final Map<KeyElement, T> wrapStore, final Class<T> clz) throws DataStoreException {
-    dataStore = Collections.synchronizedMap(wrapStore);
-    dataTypeClass = clz;
-    keyAccess = new KeyAccess(clz);
-  }
-
-  private DataStore(final Class<T> clz) throws DataStoreException {
-    this(new HashMap<KeyElement, T>(), clz);
-  }
-
-  public Class<T> getDataTypeClass() {
-    return dataTypeClass;
-  }
-
-  public String getEntityTypeName() {
-    return ANNOTATION_HELPER.extractEntityTypeName(dataTypeClass);
-  }
-
-  public T createInstance() {
-    try {
-      return dataTypeClass.newInstance();
-    } catch (InstantiationException e) {
-      throw new ODataRuntimeException("Unable to create instance of class '" + dataTypeClass + "'.", e);
-    } catch (IllegalAccessException e) {
-      throw new ODataRuntimeException("Unable to create instance of class '" + dataTypeClass + "'.", e);
-    }
-  }
-
-  public T read(final T obj) {
-    KeyElement objKeys = getKeys(obj);
-    return dataStore.get(objKeys);
-  }
-
-  public Collection<T> read() {
-    return Collections.unmodifiableCollection(dataStore.values());
-  }
-
-  public T create(final T object) throws DataStoreException {
-    KeyElement keyElement = getKeys(object);
-    return create(object, keyElement);
-  }
-
-  private T create(final T object, final KeyElement keyElement) throws DataStoreException {
-    synchronized (dataStore) {
-      if (keyElement.keyValuesMissing() || dataStore.containsKey(keyElement)) {
-        KeyElement newKey = createSetAndGetKeys(object);
-        return this.create(object, newKey);
-      }
-      dataStore.put(keyElement, object);
-    }
-    return object;
-  }
-
-  public T update(final T object) {
-    KeyElement keyElement = getKeys(object);
-    synchronized (dataStore) {
-      dataStore.remove(keyElement);
-      dataStore.put(keyElement, object);
-    }
-    return object;
-  }
-
-  public T delete(final T object) {
-    KeyElement keyElement = getKeys(object);
-    synchronized (dataStore) {
-      return dataStore.remove(keyElement);
-    }
-  }
-  
-  /**
-   * Are the key values equal for both instances.
-   * If all compared key values are <code>null</code> this also means equal.
-   * 
-   * @param first first instance to check for key equal
-   * @param second second instance to check for key equal
-   * @return <code>true</code> if object instance have equal keys set.
-   */
-  public boolean isKeyEqual(final T first, final T second) {
-    KeyElement firstKeys = getKeys(first);
-    KeyElement secondKeys = getKeys(second);
-    
-    return firstKeys.equals(secondKeys);
-  }
-  
-  /**
-   * Are the key values equal for both instances.
-   * If all compared key values are <code>null</code> this also means equal.
-   * Before object (keys) are compared it is validated that both object instance are NOT null
-   * and that both are from the same class as this {@link DataStore} (see {@link #dataTypeClass}).
-   * For the equal check on {@link #dataTypeClass} instances without validation see
-   * {@link #isKeyEqual(Object, Object)}.
-   * 
-   * @param first first instance to check for key equal
-   * @param second second instance to check for key equal
-   * @return <code>true</code> if object instance have equal keys set.
-   */
-  @SuppressWarnings("unchecked")
-  public boolean isKeyEqualChecked(Object first, Object second) throws DataStoreException {
-    if(first == null || second == null) {
-      throw new DataStoreException("Tried to compare null values which is not allowed.");
-    } else if(first.getClass() != dataTypeClass) {
-      throw new DataStoreException("First value is no instance from required class '" + dataTypeClass + "'.");
-    } else if(second.getClass() != dataTypeClass) {
-      throw new DataStoreException("Second value is no instance from required class '" + dataTypeClass + "'.");
-    }
-    
-    return isKeyEqual((T) first, (T) second);
-  }
-
-
-  private class KeyElement {
-    private int cachedHashCode = 42;
-    private final List<Object> keyValues;
-
-    public KeyElement(final int size) {
-      keyValues = new ArrayList<Object>(size);
-    }
-
-    private void addValue(final Object keyValue) {
-      keyValues.add(keyValue);
-      cachedHashCode = 89 * cachedHashCode + (keyValue != null ? keyValue.hashCode() : 0);
-    }
-
-    boolean keyValuesMissing() {
-      return keyValues.contains(null);
-    }
-
-    @Override
-    public int hashCode() {
-      return cachedHashCode;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-      if (obj == null) {
-        return false;
-      }
-      if (getClass() != obj.getClass()) {
-        return false;
-      }
-      @SuppressWarnings("unchecked")
-      final KeyElement other = (KeyElement) obj;
-      if (this.keyValues != other.keyValues && (this.keyValues == null || !this.keyValues.equals(other.keyValues))) {
-        return false;
-      }
-      return true;
-    }
-
-    @Override
-    public String toString() {
-      return "KeyElement{" + "cachedHashCode=" + cachedHashCode + ", keyValues=" + keyValues + '}';
-    }
-  }
-
-  private class KeyAccess {
-    final List<Field> keyFields;
-    final AtomicInteger idCounter = new AtomicInteger(1);
-
-    KeyAccess(final Class<?> clazz) throws DataStoreException {
-      keyFields = ANNOTATION_HELPER.getAnnotatedFields(clazz, EdmKey.class);
-      if (keyFields.isEmpty()) {
-        throw new DataStoreException("No EdmKey annotated fields found for class " + clazz);
-      }
-    }
-
-    KeyElement getKeyValues(final T object) {
-      KeyElement keyElement = new KeyElement(keyFields.size());
-      for (Field field : keyFields) {
-        Object keyValue = ClassHelper.getFieldValue(object, field);
-        keyElement.addValue(keyValue);
-      }
-
-      return keyElement;
-    }
-
-    KeyElement createSetAndGetKeys(final T object) throws DataStoreException {
-      KeyElement keyElement = new KeyElement(keyFields.size());
-      for (Field field : keyFields) {
-        Object key = createKey(field);
-        ClassHelper.setFieldValue(object, field, key);
-        keyElement.addValue(key);
-      }
-
-      return keyElement;
-    }
-
-    private Object createKey(final Field field) {
-      Class<?> type = field.getType();
-
-      if (type == String.class) {
-        return String.valueOf(idCounter.getAndIncrement());
-      } else if (type == Integer.class || type == int.class) {
-        return Integer.valueOf(idCounter.getAndIncrement());
-      } else if (type == Long.class || type == long.class) {
-        return Long.valueOf(idCounter.getAndIncrement());
-      }
-
-      throw new UnsupportedOperationException("Automated key generation for type '" + type
-          + "' is not supported (caused on field '" + field + "').");
-    }
-  }
-
-  private KeyElement getKeys(final T object) {
-    return keyAccess.getKeyValues(object);
-  }
-
-  private KeyElement createSetAndGetKeys(final T object) throws DataStoreException {
-    return keyAccess.createSetAndGetKeys(object);
-  }
-
-  public static class DataStoreException extends ODataApplicationException {
-    private static final long serialVersionUID = 42L;
-
-    public DataStoreException(final String message) {
-      this(message, null);
-    }
-
-    public DataStoreException(final String message, final Throwable cause) {
-      super(message, Locale.ENGLISH, cause);
-    }
-  }
-}