You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2015/01/27 20:25:35 UTC

[37/37] olingo-odata2 git commit: [OLINGO-129] Merge with master branch

[OLINGO-129] Merge with master branch


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/13b99eab
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/13b99eab
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/13b99eab

Branch: refs/heads/Olingo-129_PocJpaDataStore
Commit: 13b99eab05d6ec637c9b6cf118abe25b82a3e610
Parents: 7224e85 5bb61bf
Author: mibo <mi...@mirb.de>
Authored: Tue Jan 27 20:01:50 2015 +0100
Committer: mibo <mi...@mirb.de>
Committed: Tue Jan 27 20:01:50 2015 +0100

----------------------------------------------------------------------
 .../core/datasource/AnnotationDataSource.java   |   7 +-
 .../core/edm/AnnotationEdmProvider.java         |  39 ++-
 .../processor/core/util/AnnotationHelper.java   | 170 ++++++++++---
 .../processor/core/util/ClassHelper.java        |  16 ++
 .../core/edm/AnnotationEdmProviderTest.java     |  36 +--
 .../annotation/processor/core/model/Team.java   |   6 +
 .../core/util/AnnotationHelperTest.java         |  22 +-
 .../ref/AnnotationRefServiceFactory.java        |   9 +-
 .../annotation/processor/ref/model/Team.java    |  10 +
 .../annotation/processor/ref/MetadataTest.java  |  70 ++++--
 .../processor/api/ODataJPAServiceFactory.java   |   4 +-
 .../api/exception/ODataJPAModelException.java   |   2 +
 .../processor/api/factory/JPAAccessFactory.java |   7 +
 .../core/ODataJPAProcessorDefault.java          |  58 ++---
 .../core/ODataJPAResponseBuilderDefault.java    |   9 +-
 .../processor/core/access/data/JPAEntity.java   |   3 +
 .../core/access/model/JPAEdmNameBuilder.java    |  87 +++++--
 .../core/access/model/JPATypeConvertor.java     |   3 +
 .../core/factory/ODataJPAFactoryImpl.java       |   7 +
 .../processor/core/model/JPAEdmAssociation.java |   7 +-
 .../processor/core/model/JPAEdmEntityType.java  |  12 +-
 .../processor/core/model/JPAEdmProperty.java    |  33 ++-
 .../model/JPAEdmReferentialConstraintRole.java  |   8 +-
 .../main/resources/jpaprocessor_msg.properties  |   2 +-
 .../core/access/data/JPAEntityTest.java         |   2 +
 .../core/access/model/JPATypeConvertorTest.java |   6 +
 .../processor/core/mock/data/EdmMockUtilV2.java |   8 +
 .../processor/core/mock/data/JPATypeMock.java   |  12 +
 .../core/mock/data/ODataEntryMockUtil.java      |   2 +
 .../core/model/JPAEdmPropertyTest.java          | 226 +++++++++++++----
 .../jpa/processor/ref/model/Customer.java       |  20 +-
 .../jpa/processor/ref/model/Importance.java     |  23 ++
 .../processor/ref/util/CustomerImageLoader.java |  49 ++++
 .../jpa-ref/src/main/resources/Customer_1.png   | Bin 0 -> 8429 bytes
 .../jpa-ref/src/main/resources/Customer_2.png   | Bin 0 -> 12212 bytes
 .../ref/extension/CustomerImageProcessor.java   |  35 +++
 .../SalesOrderProcessingExtension.java          |   1 +
 .../resources/SQL_Insert_Customer.properties    |  10 +-
 .../odata2/core/batch/BatchRequestWriter.java   |   3 +-
 .../odata2/core/batch/BatchResponseWriter.java  |  31 +--
 .../core/ep/consumer/XmlMetadataConsumer.java   |  25 +-
 .../odata2/core/rest/ODataRootLocator.java      |  30 ++-
 .../olingo/odata2/core/rest/RestUtil.java       |   8 +-
 .../core/servlet/ODataExceptionWrapper.java     |  29 ++-
 .../odata2/core/servlet/ODataServlet.java       | 110 +++++----
 .../olingo/odata2/core/servlet/RestUtil.java    |  27 ++-
 .../odata2/core/batch/BatchRequestTest.java     |   8 +-
 .../core/batch/BatchRequestWriterITTest.java    | 243 +++++++++++++++++++
 .../core/batch/BatchRequestWriterTest.java      | 214 ++++++++++------
 .../core/batch/BatchResponseParserTest.java     | 120 ++++++++-
 .../odata2/core/batch/BatchResponseTest.java    |   2 +-
 .../core/batch/BatchResponseWriterITTest.java   | 179 ++++++++++++++
 .../core/batch/BatchResponseWriterTest.java     | 128 +++++++---
 .../ep/consumer/XmlMetadataConsumerTest.java    | 116 ++++++++-
 .../odata2/core/servlet/ODataServletTest.java   |  83 ++++++-
 .../odata2/fit/basic/NullServiceTest.java       |   2 +-
 .../odata2/testutil/fit/FitErrorCallback.java   |   1 -
 odata2-spring/.springBeans                      |  26 ++
 odata2-spring/pom.xml                           |  86 +++++++
 .../odata2/spring/OlingoNamespaceHandler.java   |  29 +++
 .../olingo/odata2/spring/OlingoRootLocator.java |  62 +++++
 .../spring/OlingoServerDefinitionParser.java    |  96 ++++++++
 .../src/main/resources/META-INF/spring.handlers |   8 +
 .../src/main/resources/META-INF/spring.schemas  |   8 +
 .../src/main/resources/schema/olingo.xsd        |  32 +++
 .../spring/SpringNamespaceHandlerTest.java      |  71 ++++++
 .../olingo/odata2/spring/TestFactory.java       |  39 +++
 .../resources/spring/applicationContext.xml     |  33 +++
 pom.xml                                         |   4 +
 69 files changed, 2417 insertions(+), 457 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/13b99eab/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationDataSource.java
----------------------------------------------------------------------
diff --cc odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationDataSource.java
index b2b44ba,0000000..eb22f81
mode 100644,000000..100644
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationDataSource.java
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationDataSource.java
@@@ -1,438 -1,0 +1,443 @@@
 +/**
 + * *****************************************************************************
 + * 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.datasource;
 +
 +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.Map;
 +
 +import org.apache.olingo.odata2.annotation.processor.core.util.AnnotationHelper;
 +import org.apache.olingo.odata2.annotation.processor.core.util.AnnotationHelper.AnnotatedNavInfo;
 +import org.apache.olingo.odata2.annotation.processor.core.util.AnnotationHelper.ODataAnnotationException;
 +import org.apache.olingo.odata2.annotation.processor.core.util.AnnotationRuntimeException;
 +import org.apache.olingo.odata2.annotation.processor.core.util.ClassHelper;
 +import org.apache.olingo.odata2.api.annotation.edm.EdmKey;
 +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.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;
 +
 +public class AnnotationDataSource implements DataSource {
 +
 +  private static final AnnotationHelper ANNOTATION_HELPER = new AnnotationHelper();
 +  private static final String DEFAULT_PERSISTENCE = Boolean.TRUE.toString();
 +
 +  private final Map<String, DataStore<Object>> dataStores = new HashMap<String, DataStore<Object>>();
 +  private final DataStoreFactory dataStoreFactory;
 +
 +  public AnnotationDataSource(final Collection<Class<?>> annotatedClasses) throws ODataException {
 +    this(annotatedClasses, new DualDataStoreFactory());
 +    dataStoreFactory.setDefaultProperty(DataStoreFactory.KEEP_PERSISTENT, DEFAULT_PERSISTENCE);
 +  }
 +
 +  public AnnotationDataSource(final Collection<Class<?>> annotatedClasses, final DataStoreFactory dataStoreFactory)
 +      throws ODataException {
 +    this.dataStoreFactory = dataStoreFactory;
 +    
 +    init(annotatedClasses);
 +  }
 +
 +  public AnnotationDataSource(final String packageToScan) throws ODataException {
 +    this(packageToScan, new DualDataStoreFactory());
 +    dataStoreFactory.setDefaultProperty(DataStoreFactory.KEEP_PERSISTENT, DEFAULT_PERSISTENCE);
 +  }
 +
 +  public AnnotationDataSource(final String packageToScan, final DataStoreFactory dataStoreFactory) 
 +          throws ODataException {
 +    this.dataStoreFactory = dataStoreFactory;
 +
 +    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 Collection<Class<?>> annotatedClasses) throws ODataException {
 +    try {
 +      for (Class<?> clz : annotatedClasses) {
 +        String entitySetName = ANNOTATION_HELPER.extractEntitySetName(clz);
 +        if(entitySetName != null) {
 +          DataStore<Object> dhs = (DataStore<Object>) dataStoreFactory.createDataStore(clz);
 +          dataStores.put(entitySetName, dhs);
 +        } else if (!ANNOTATION_HELPER.isEdmAnnotated(clz)) {
 +          throw new ODataException("Found not annotated class during DataStore initilization of type: "
 +              + clz.getName());
 +        }
 +      }
 +    } catch (DataStoreException e) {
 +      throw new ODataException("Error in DataStore initilization with message: " + e.getMessage(), e);
 +    }
 +  }
 +
 +  @SuppressWarnings("unchecked")
 +  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();
++    final Field sourceField;
++    if(navInfo.isBiDirectional()) {
++      sourceField = navInfo.getToField();
++    } else {
++      sourceField = navInfo.getFromField();
++    }
 +    if (sourceField == null) {
 +      throw new AnnotationRuntimeException("Missing source field for related data (sourceStore='" + sourceStore
 +          + "', targetStore='" + targetStore + "').");
 +    }
 +
 +    List<Object> resultData = readResultData(targetStore, sourceData, sourceField, navInfo);
 +    return extractResultData(targetStore, targetKeys, navInfo, resultData);
 +  }
 +
 +  /**
 +   * Read the result data from the target store based on <code>sourceData</code> and <code>sourceField</code>
 +   * 
 +   * @param targetStore
 +   * @param sourceData
 +   * @param sourceField
 +   * @return
 +   * @throws DataStoreException
 +   */
 +  private List<Object> readResultData(final DataStore<?> targetStore, final Object sourceData, 
 +          final Field sourceField, final AnnotatedNavInfo navInfo)
 +      throws DataStoreException {
 +    Object navigationInstance = getValue(sourceField, sourceData);
 +    if (navigationInstance == null) {
 +      return Collections.emptyList();
 +    }
 +    
 +    List<Object> resultData = new ArrayList<Object>();
 +    for (Object targetInstance : targetStore.read()) {
 +      if (navigationInstance instanceof Collection) {
 +        Map<String, Object> keyName2Value = 
 +                ANNOTATION_HELPER.getValueForAnnotatedFields(sourceData, EdmKey.class);
 +        Field toField = navInfo.getToField();
 +        Object backInstance = ClassHelper.getFieldValue(targetInstance, toField);
 +        boolean keyMatch = ANNOTATION_HELPER.keyMatch(backInstance, keyName2Value);
 +        if(keyMatch) {
 +          resultData.add(targetInstance);
 +        }
 +      } else if (targetStore.isKeyEqualChecked(targetInstance, navigationInstance)) {
 +        resultData.add(targetInstance);
 +      }
 +    }
 +    return resultData;
 +  }
 +
 +  /**
 +   * Extract the <code>result data</code> from the <code>resultData</code> list based on
 +   * <code>navigation information</code> and <code>targetKeys</code>.
 +   * 
 +   * @param targetStore
 +   * @param targetKeys
 +   * @param navInfo
 +   * @param resultData
 +   * @return
 +   * @throws DataStoreException
 +   */
 +  private Object extractResultData(final DataStore<?> targetStore, final Map<String, Object> targetKeys,
 +      final AnnotatedNavInfo navInfo, final List<Object> resultData) throws DataStoreException {
 +    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 AnnotationRuntimeException("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 AnnotationRuntimeException("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 AnnotationRuntimeException("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 AnnotationRuntimeException("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
 +   * AnnotationRuntimeException is thrown.
 +   * Never returns NULL.
 +   * 
 +   * @param entitySet for which the corresponding DataStore is returned
 +   * @return a DataStore object
 +   * @throws EdmException
 +   * @throws AnnotationRuntimeException 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 AnnotationRuntimeException("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 AnnotationRuntimeException("Error for getting value of field '"
 +          + field + "' at instance '" + instance + "'.", e);
 +    } catch (IllegalAccessException e) {
 +      throw new AnnotationRuntimeException("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 AnnotationRuntimeException("Error for setting value of field: '"
 +          + field + "' at instance: '" + instance + "'.", e);
 +    } catch (IllegalAccessException e) {
 +      throw new AnnotationRuntimeException("Error for setting value of field: '"
 +          + field + "' at instance: '" + instance + "'.", e);
 +    }
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/13b99eab/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/edm/AnnotationEdmProvider.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/13b99eab/odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java
----------------------------------------------------------------------
diff --cc odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java
index 0977a83,9130a19..65f5585
--- a/odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java
+++ b/odata2-annotation-processor/annotation-processor-ref/src/main/java/org/apache/olingo/odata2/annotation/processor/ref/AnnotationRefServiceFactory.java
@@@ -145,9 -126,11 +145,11 @@@ public class AnnotationRefServiceFactor
      teamDs.create(createTeam("Team Beta", false));
      teamDs.create(createTeam("Team Gamma", false));
      teamDs.create(createTeam("Team Omega", true));
-     teamDs.create(createTeam("Team Zeta", true));
+     Team subTeam = createTeam("SubTeamOne", false);
+     teamDs.create(subTeam);
+     teamDs.create(createTeam("Team Zeta", true, subTeam));
  
 -    DataStore<Building> buildingsDs = getDataStore(Building.class);
 +    InMemoryDataStore<Building> buildingsDs = getDataStore(Building.class);
      Building redBuilding = createBuilding("Red Building");
      buildingsDs.create(redBuilding);
      Building greenBuilding = createBuilding("Green Building");