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 2014/01/26 14:52:28 UTC

[1/2] [OLINGO-129] Introduced DataStoreFactory

Updated Branches:
  refs/heads/Olingo-129_PocJpaDataStore b0e0a32f2 -> 4941d8461


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationsInMemoryDsTest.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationsInMemoryDsTest.java b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationsInMemoryDsTest.java
deleted file mode 100644
index a7e7e13..0000000
--- a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationsInMemoryDsTest.java
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * Copyright 2013 The Apache Software Foundation.
- * 
- * Licensed 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.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.olingo.odata2.annotation.processor.core.datasource.DataSource.BinaryData;
-import org.apache.olingo.odata2.annotation.processor.core.edm.AnnotationEdmProvider;
-import org.apache.olingo.odata2.annotation.processor.core.model.Building;
-import org.apache.olingo.odata2.annotation.processor.core.model.City;
-import org.apache.olingo.odata2.annotation.processor.core.model.Employee;
-import org.apache.olingo.odata2.annotation.processor.core.model.Location;
-import org.apache.olingo.odata2.annotation.processor.core.model.Manager;
-import org.apache.olingo.odata2.annotation.processor.core.model.ModelSharedConstants;
-import org.apache.olingo.odata2.annotation.processor.core.model.Photo;
-import org.apache.olingo.odata2.annotation.processor.core.model.RefBase;
-import org.apache.olingo.odata2.annotation.processor.core.model.Room;
-import org.apache.olingo.odata2.annotation.processor.core.model.Team;
-import org.apache.olingo.odata2.annotation.processor.core.util.AnnotationHelper;
-import org.apache.olingo.odata2.api.annotation.edm.EdmKey;
-import org.apache.olingo.odata2.api.annotation.edm.EdmProperty;
-import org.apache.olingo.odata2.api.edm.EdmEntitySet;
-import org.apache.olingo.odata2.api.edm.EdmEntityType;
-import org.apache.olingo.odata2.api.edm.FullQualifiedName;
-import org.apache.olingo.odata2.api.edm.provider.EntitySet;
-import org.apache.olingo.odata2.api.exception.ODataException;
-import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
-import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-/**
- *
- */
-public class AnnotationsInMemoryDsTest {
-
-  final static Set<Class<?>> ANNOTATED_MODEL_CLASSES = new HashSet<Class<?>>();
-  final static Set<Class<?>> ANNOTATED_ENTITY_SET_CLASSES = new HashSet<Class<?>>();
-
-  static {
-    ANNOTATED_ENTITY_SET_CLASSES.add(Building.class);
-    ANNOTATED_ENTITY_SET_CLASSES.add(Employee.class);
-    ANNOTATED_ENTITY_SET_CLASSES.add(Manager.class);
-    ANNOTATED_ENTITY_SET_CLASSES.add(Photo.class);
-    ANNOTATED_ENTITY_SET_CLASSES.add(Room.class);
-    ANNOTATED_ENTITY_SET_CLASSES.add(Team.class);
-    
-    ANNOTATED_MODEL_CLASSES.addAll(ANNOTATED_ENTITY_SET_CLASSES);
-    ANNOTATED_MODEL_CLASSES.add(Location.class);
-    ANNOTATED_MODEL_CLASSES.add(City.class);
-    ANNOTATED_MODEL_CLASSES.add(RefBase.class);
-  }
-
-  private final AnnotationInMemoryDs datasource;
-  private final AnnotationEdmProvider edmProvider;
-  private static final String DEFAULT_CONTAINER = ModelSharedConstants.CONTAINER_1;
-
-  public AnnotationsInMemoryDsTest() throws ODataException {
-    datasource = new AnnotationInMemoryDs(Building.class.getPackage().getName(), false);
-    edmProvider = new AnnotationEdmProvider(Building.class.getPackage().getName());
-  }
-  
-  @Test
-  public void initFromPackage() throws Exception {
-    AnnotationInMemoryDs ds = new AnnotationInMemoryDs(Building.class.getPackage().getName(), false);
-    Assert.assertNotNull(ds);
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void initFromNotExistingPackage() throws Exception {
-    AnnotationInMemoryDs ds = new AnnotationInMemoryDs("does.not.exist", false);
-    Assert.assertNotNull(ds);
-  }
-
-  @Test
-  public void initFromPackageWithoutAnnotatedClasses() throws Exception {
-    AnnotationInMemoryDs ds = new AnnotationInMemoryDs(this.getClass().getPackage().getName(), false);
-    Assert.assertNotNull(ds);
-  }
-
-  @Test
-  public void initFromClassCollectionEntitySets() throws Exception {
-    AnnotationInMemoryDs ds = new AnnotationInMemoryDs(ANNOTATED_ENTITY_SET_CLASSES, false);
-    Assert.assertNotNull(ds);
-  }
-
-  @Test
-  public void initFromClassCollectionModel() throws Exception {
-    AnnotationInMemoryDs ds = new AnnotationInMemoryDs(ANNOTATED_MODEL_CLASSES, false);
-    Assert.assertNotNull(ds);
-  }
-
-  @Test(expected = ODataException.class)
-  public void initFromClassCollectionNotAnnotated() throws Exception {
-    Set<Class<?>> annotatedClassesAndMore = new HashSet<Class<?>>(ANNOTATED_ENTITY_SET_CLASSES);
-    annotatedClassesAndMore.add(String.class);
-    annotatedClassesAndMore.add(Object.class);
-    AnnotationInMemoryDs ds = new AnnotationInMemoryDs(annotatedClassesAndMore, false);
-    Assert.assertNotNull(ds);
-  }
-
-  @Test
-  @Ignore
-  public void multiThreadedSyncOnBuildingsTest() throws Exception {
-    final EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
-    CountDownLatch latch;
-
-    List<Thread> threads = new ArrayList<Thread>();
-    int max = 500;
-
-    latch = new CountDownLatch(max);
-    for (int i = 0; i < max; i++) {
-      threads.add(createBuildingThread(latch, datasource, edmEntitySet, String.valueOf("10")));
-    }
-
-    for (Thread thread : threads) {
-      thread.start();
-    }
-
-    latch.await(60, TimeUnit.SECONDS);
-
-    DataStore<Building> ds = datasource.getDataStore(Building.class);
-    Collection<Building> buildings = ds.read();
-    Assert.assertEquals(max, buildings.size());
-  }
-
-  @org.apache.olingo.odata2.api.annotation.edm.EdmEntitySet
-  @org.apache.olingo.odata2.api.annotation.edm.EdmEntityType
-  private static class SimpleEntity {
-
-    @EdmKey
-    @EdmProperty
-    public Integer id;
-    @EdmProperty
-    public String name;
-  }
-
-  @Test
-  @Ignore
-  public void multiThreadedSyncCreateReadTest() throws Exception {
-    Collection<Class<?>> ac = new ArrayList<Class<?>>();
-    ac.add(SimpleEntity.class);
-    final AnnotationInMemoryDs localDs = new AnnotationInMemoryDs(SimpleEntity.class.getPackage().getName(), true);
-    final AnnotationEdmProvider localProvider = new AnnotationEdmProvider(ac);
-    final EdmEntitySet edmEntitySet = createMockedEdmEntitySet(localProvider, "SimpleEntitySet");
-    final CountDownLatch latch;
-
-    List<Thread> threads = new ArrayList<Thread>();
-    int max = 500;
-    latch = new CountDownLatch(max);
-    for (int i = 0; i < max; i++) {
-      Runnable run = new Runnable() {
-        @Override
-        public void run() {
-          SimpleEntity se = new SimpleEntity();
-          se.id = Integer.valueOf(String.valueOf(System.currentTimeMillis()).substring(8));
-          se.name = "Name: " + System.currentTimeMillis();
-          try {
-            localDs.createData(edmEntitySet, se);
-          } catch (Exception ex) {
-            throw new RuntimeException(ex);
-          } finally {
-            latch.countDown();
-          }
-        }
-      };
-
-      threads.add(new Thread(run));
-    }
-
-    for (Thread thread : threads) {
-      thread.start();
-    }
-
-    latch.await(60, TimeUnit.SECONDS);
-
-    DataStore<SimpleEntity> ds = localDs.getDataStore(SimpleEntity.class);
-    Collection<SimpleEntity> buildings = ds.read();
-    Assert.assertEquals(max, buildings.size());
-  }
-
-  private Thread createBuildingThread(final CountDownLatch latch, final DataSource datasource,
-          final EdmEntitySet edmEntitySet, final String id) {
-    Runnable run = new Runnable() {
-      @Override
-      public void run() {
-        Building building = new Building();
-        building.setName("Common Building - " + System.currentTimeMillis());
-        building.setId(id);
-        try {
-          datasource.createData(edmEntitySet, building);
-        } catch (Exception ex) {
-          ex.printStackTrace();
-          throw new RuntimeException(ex);
-        } finally {
-          latch.countDown();
-        }
-      }
-    };
-
-    return new Thread(run);
-  }
-
-  @Test
-  public void readBinaryData() throws Exception {
-    EdmEntitySet entitySet = createMockedEdmEntitySet("Photos");
-
-    DataStore<Photo> photoDataStore = datasource.getDataStore(Photo.class);
-    Photo photo = new Photo();
-    photo.setName("SomePic");
-    photo.setType("PNG");
-    byte[] image = "binary".getBytes(Charset.defaultCharset());
-    photo.setImage(image);
-    photo.setImageType("image/png");
-    photoDataStore.create(photo);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Name", "SomePic");
-    keys.put("ImageFormat", "PNG");
-    Photo toReadPhoto = (Photo) datasource.readData(entitySet, keys);
-
-    // execute
-    BinaryData readBinaryData = datasource.readBinaryData(entitySet, toReadPhoto);
-
-    // validate
-    Assert.assertEquals("binary", new String(readBinaryData.getData(), Charset.defaultCharset()));
-    Assert.assertArrayEquals(image, readBinaryData.getData());
-    Assert.assertEquals("image/png", readBinaryData.getMimeType());
-  }
-
-  @Test
-  public void readBinaryDataDirect() throws Exception {
-    EdmEntitySet entitySet = createMockedEdmEntitySet("Photos");
-
-    DataStore<Photo> photoDataStore = datasource.getDataStore(Photo.class);
-    Photo photo = new Photo();
-    photo.setName("SomePic");
-    photo.setType("PNG");
-    byte[] image = "binary".getBytes(Charset.defaultCharset());
-    photo.setImage(image);
-    photo.setImageType("image/png");
-    photoDataStore.create(photo);
-
-    Photo toReadPhoto = new Photo();
-    toReadPhoto.setName("SomePic");
-    toReadPhoto.setType("PNG");
-    toReadPhoto.setImage(null);
-    toReadPhoto.setImageType(null);
-
-    BinaryData readBinaryData = datasource.readBinaryData(entitySet, toReadPhoto);
-
-    Assert.assertEquals("binary", new String(readBinaryData.getData(), Charset.defaultCharset()));
-    Assert.assertArrayEquals(image, readBinaryData.getData());
-    Assert.assertEquals("image/png", readBinaryData.getMimeType());
-  }
-
-  @Test
-  public void writeBinaryData() throws Exception {
-    EdmEntitySet entitySet = createMockedEdmEntitySet("Photos");
-
-    DataStore<Photo> photoDataStore = datasource.getDataStore(Photo.class);
-
-    Photo toWritePhoto = new Photo();
-    toWritePhoto.setName("SomePic");
-    toWritePhoto.setType("PNG");
-    photoDataStore.create(toWritePhoto);
-    byte[] image = "binary".getBytes(Charset.defaultCharset());
-    String mimeType = "image/png";
-    BinaryData writeBinaryData = new BinaryData(image, mimeType);
-    // execute
-    datasource.writeBinaryData(entitySet, toWritePhoto, writeBinaryData);
-
-    // validate
-    Photo photoKey = new Photo();
-    photoKey.setName("SomePic");
-    photoKey.setType("PNG");
-    Photo storedPhoto = photoDataStore.read(photoKey);
-    Assert.assertEquals("binary", new String(storedPhoto.getImage(), Charset.defaultCharset()));
-    Assert.assertArrayEquals(image, storedPhoto.getImage());
-    Assert.assertEquals("image/png", storedPhoto.getImageType());
-  }
-
-  @Test(expected = ODataNotFoundException.class)
-  public void writeBinaryDataNotFound() throws Exception {
-    EdmEntitySet entitySet = createMockedEdmEntitySet("Photos");
-
-    Photo toWritePhoto = new Photo();
-    toWritePhoto.setName("SomePic");
-    toWritePhoto.setType("PNG");
-    byte[] image = "binary".getBytes(Charset.defaultCharset());
-    String mimeType = "image/png";
-    BinaryData writeBinaryData = new BinaryData(image, mimeType);
-    // execute
-    datasource.writeBinaryData(entitySet, toWritePhoto, writeBinaryData);
-  }
-
-  @Test
-  public void newDataObject() throws Exception {
-    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
-    Room room = (Room) datasource.newDataObject(roomsEntitySet);
-
-    Assert.assertNotNull(room);
-  }
-
-  @Test
-  public void readEntity() throws Exception {
-    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
-    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
-
-    Building building = new Building();
-    building.setName("Common Building");
-
-    final int roomsCount = 3;
-    List<Room> rooms = new ArrayList<Room>();
-    for (int i = 0; i < roomsCount; i++) {
-      Room room = new Room(i, "Room " + i);
-      room.setBuilding(building);
-      datasource.createData(roomsEntitySet, room);
-      rooms.add(room);
-    }
-
-    building.getRooms().addAll(rooms);
-    datasource.createData(buildingsEntitySet, building);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "1");
-
-    // execute
-    Object relatedData = datasource.readData(buildingsEntitySet, keys);
-
-    // validate
-    Building readBuilding = (Building) relatedData;
-    Assert.assertEquals("Common Building", readBuilding.getName());
-    Assert.assertEquals("1", readBuilding.getId());
-
-    Collection<Room> relatedRooms = readBuilding.getRooms();
-    Assert.assertEquals(roomsCount, relatedRooms.size());
-    for (Room room : relatedRooms) {
-      Assert.assertNotNull(room.getId());
-      Assert.assertTrue(room.getName().matches("Room \\d*"));
-      Assert.assertEquals("Common Building", room.getBuilding().getName());
-    }
-  }
-
-  @Test(expected = ODataRuntimeException.class)
-  public void readUnknownEntity() throws Exception {
-    EdmEntitySet unknownEntitySet = Mockito.mock(EdmEntitySet.class);
-    Mockito.when(unknownEntitySet.getName()).thenReturn("UnknownEntity");
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "1");
-
-    // execute
-    datasource.readData(unknownEntitySet, keys);
-  }
-
-  @Test(expected = ODataRuntimeException.class)
-  public void readUnknownEntities() throws Exception {
-    EdmEntitySet unknownEntitySet = Mockito.mock(EdmEntitySet.class);
-    Mockito.when(unknownEntitySet.getName()).thenReturn("UnknownEntity");
-
-    // execute
-    datasource.readData(unknownEntitySet);
-  }
-
-  @Test
-  public void readEntities() throws Exception {
-    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
-
-    Building building = new Building();
-    building.setName("Common Building");
-
-    final int roomsCount = 11;
-    List<Room> rooms = new ArrayList<Room>();
-    for (int i = 0; i < roomsCount; i++) {
-      Room room = new Room(i, "Room " + i);
-      room.setBuilding(building);
-      datasource.createData(roomsEntitySet, room);
-      rooms.add(room);
-    }
-
-    // execute
-    Object relatedData = datasource.readData(roomsEntitySet);
-
-    // validate
-    @SuppressWarnings("unchecked")
-    Collection<Room> relatedRooms = (Collection<Room>) relatedData;
-    Assert.assertEquals(roomsCount, relatedRooms.size());
-    for (Room room : relatedRooms) {
-      Assert.assertNotNull(room.getId());
-      Assert.assertTrue(room.getName().matches("Room \\d*"));
-      Assert.assertEquals("Common Building", room.getBuilding().getName());
-    }
-  }
-
-  @Test
-  @SuppressWarnings("unchecked")
-  public void readRelatedEntities() throws Exception {
-    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
-    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
-
-    Building building = new Building();
-    building.setName("Common Building");
-
-    final int roomsCount = 10;
-    List<Room> rooms = new ArrayList<Room>();
-    for (int i = 0; i < roomsCount; i++) {
-      Room room = new Room(i, "Room " + i);
-      room.setBuilding(building);
-      datasource.createData(roomsEntitySet, room);
-      rooms.add(room);
-    }
-
-    building.getRooms().addAll(rooms);
-    datasource.createData(buildingsEntitySet, building);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "1");
-
-    Building read = (Building) datasource.readData(buildingsEntitySet, keys);
-    Assert.assertEquals("Common Building", read.getName());
-    Assert.assertEquals("1", read.getId());
-
-    // execute
-    Object relatedData = datasource.readRelatedData(
-            buildingsEntitySet, building, roomsEntitySet, Collections.EMPTY_MAP);
-
-    // validate
-    Assert.assertTrue("Result is no collection.", relatedData instanceof Collection);
-    Collection<Room> relatedRooms = (Collection<Room>) relatedData;
-    Assert.assertEquals(roomsCount, relatedRooms.size());
-    for (Room room : relatedRooms) {
-      Assert.assertNotNull(room.getId());
-      Assert.assertTrue(room.getName().matches("Room \\d*"));
-      Assert.assertEquals("Common Building", room.getBuilding().getName());
-    }
-  }
-
-  @Test
-  @SuppressWarnings("unchecked")
-  public void readRelatedEntity() throws Exception {
-    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
-    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
-
-    Building building = new Building();
-    building.setName("Common Building");
-
-    Room room = new Room(12, "Room 12");
-    room.setBuilding(building);
-    datasource.createData(roomsEntitySet, room);
-    datasource.createData(buildingsEntitySet, building);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", Integer.valueOf(12));
-    Room read = (Room) datasource.readData(roomsEntitySet, keys);
-    Assert.assertEquals("Room 12", read.getName());
-    Assert.assertEquals("12", read.getId());
-
-    // execute
-    Object relatedData = datasource.readRelatedData(
-            roomsEntitySet, room, buildingsEntitySet, Collections.EMPTY_MAP);
-
-    // validate
-    Assert.assertTrue("Result is no room.", relatedData instanceof Building);
-    Building b = (Building) relatedData;
-    Assert.assertEquals("Common Building", b.getName());
-  }
-
-  @Test
-  @SuppressWarnings("unchecked")
-  public void readRelatedEntityWithNull() throws Exception {
-    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
-    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
-
-    Building building = new Building();
-    building.setName("Common Building");
-    datasource.createData(buildingsEntitySet, building);
-
-    Room room = new Room(12, "Room 12");
-    room.setBuilding(null);
-    datasource.createData(roomsEntitySet, room);
-    //
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", Integer.valueOf(12));
-    Room read = (Room) datasource.readData(roomsEntitySet, keys);
-    Assert.assertEquals("Room 12", read.getName());
-    Assert.assertEquals("12", read.getId());
-
-    // execute
-    Object relatedData = datasource.readRelatedData(
-            roomsEntitySet, room, buildingsEntitySet, Collections.EMPTY_MAP);
-
-    // validate
-    Assert.assertNull("Related data must be null.", relatedData);
-  }
-
-  @Test
-  public void readRelatedTargetEntity() throws Exception {
-    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
-    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
-
-    Building building = new Building();
-    building.setName("Common Building");
-
-    final int roomsCount = 10;
-    List<Room> rooms = new ArrayList<Room>();
-    for (int i = 0; i < roomsCount; i++) {
-      Room room = new Room(i, "Room " + i);
-      room.setBuilding(building);
-      datasource.createData(roomsEntitySet, room);
-      rooms.add(room);
-    }
-
-    building.getRooms().addAll(rooms);
-    datasource.createData(buildingsEntitySet, building);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "1");
-
-    Building read = (Building) datasource.readData(buildingsEntitySet, keys);
-    Assert.assertEquals("Common Building", read.getName());
-    Assert.assertEquals("1", read.getId());
-
-    // execute
-    Map<String, Object> targetKeys = new HashMap<String, Object>();
-    targetKeys.put("Id", 3);
-    Object relatedData = datasource.readRelatedData(
-            buildingsEntitySet, building, roomsEntitySet, targetKeys);
-
-    // validate
-    Assert.assertTrue("Result is no Room.", relatedData instanceof Room);
-    Room relatedRoom = (Room) relatedData;
-    Assert.assertEquals("3", relatedRoom.getId());
-    Assert.assertEquals("Room 3", relatedRoom.getName());
-    Assert.assertEquals("Common Building", relatedRoom.getBuilding().getName());
-  }
-
-  @Test
-  public void createSimpleEntity() throws Exception {
-    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
-
-    Building building = new Building();
-    building.setName("Common Building");
-    datasource.createData(edmEntitySet, building);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "1");
-
-    Building read = (Building) datasource.readData(edmEntitySet, keys);
-    Assert.assertEquals("Common Building", read.getName());
-    Assert.assertEquals("1", read.getId());
-  }
-
-  @Test
-  public void createSimpleEntityWithOwnKey() throws Exception {
-    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
-
-    Building building = new Building();
-    building.setName("Common Building");
-    AnnotationHelper ah = new AnnotationHelper();
-    ah.setValueForProperty(building, "Id", "42");
-    datasource.createData(edmEntitySet, building);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "42");
-
-    Building read = (Building) datasource.readData(edmEntitySet, keys);
-    Assert.assertEquals("Common Building", read.getName());
-    Assert.assertEquals("42", read.getId());
-  }
-
-  @Test
-  public void createSimpleEntityWithDuplicateKey() throws Exception {
-    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
-    AnnotationHelper ah = new AnnotationHelper();
-
-    Building building = new Building();
-    building.setName("Common Building");
-    ah.setValueForProperty(building, "Id", "42");
-    datasource.createData(edmEntitySet, building);
-    //
-    Building buildingDuplicate = new Building();
-    buildingDuplicate.setName("Duplicate Building");
-    ah.setValueForProperty(buildingDuplicate, "Id", "42");
-    datasource.createData(edmEntitySet, buildingDuplicate);
-
-    Map<String, Object> keys42 = new HashMap<String, Object>();
-    keys42.put("Id", "42");
-    Building read42 = (Building) datasource.readData(edmEntitySet, keys42);
-    Assert.assertEquals("Common Building", read42.getName());
-    Assert.assertEquals("42", read42.getId());
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "1");
-    Building read = (Building) datasource.readData(edmEntitySet, keys);
-    Assert.assertEquals("Duplicate Building", read.getName());
-    Assert.assertEquals("1", read.getId());
-  }
-
-  @Test
-  public void createEntityTwoKeys() throws Exception {
-    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Photos");
-
-    Photo photo = new Photo();
-    photo.setName("BigPicture");
-    photo.setType("PNG");
-    photo.setImageUri("https://localhost/image.png");
-    photo.setImageType("image/png");
-    datasource.createData(edmEntitySet, photo);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("ImageFormat", "PNG");
-    keys.put("Name", "BigPicture");
-
-    Photo read = (Photo) datasource.readData(edmEntitySet, keys);
-    Assert.assertEquals("BigPicture", read.getName());
-    Assert.assertEquals("PNG", read.getType());
-    Assert.assertEquals("image/png", read.getImageType());
-    Assert.assertEquals("https://localhost/image.png", read.getImageUri());
-  }
-
-  @Test
-  public void createAndUpdateEntityTwoKeys() throws Exception {
-    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Photos");
-
-    Photo photo = new Photo();
-    final String nameKeyValue = "BigPicture";
-    final String typeKeyValue = "PNG";
-    photo.setName(nameKeyValue);
-    photo.setType(typeKeyValue);
-    photo.setImageUri("https://localhost/image.png");
-    photo.setImageType("image/png");
-    datasource.createData(edmEntitySet, photo);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Name", "BigPicture");
-    keys.put("ImageFormat", "PNG");
-
-    Photo read = (Photo) datasource.readData(edmEntitySet, keys);
-    Assert.assertEquals("BigPicture", read.getName());
-    Assert.assertEquals("PNG", read.getType());
-    Assert.assertEquals("image/png", read.getImageType());
-    Assert.assertEquals("https://localhost/image.png", read.getImageUri());
-
-    // update
-    Photo updatedPhoto = new Photo();
-    updatedPhoto.setName(nameKeyValue);
-    updatedPhoto.setType(typeKeyValue);
-    updatedPhoto.setImageUri("https://localhost/image.jpg");
-    updatedPhoto.setImageType("image/jpg");
-    datasource.updateData(edmEntitySet, updatedPhoto);
-
-    Map<String, Object> updatedKeys = new HashMap<String, Object>();
-    updatedKeys.put("Name", nameKeyValue);
-    updatedKeys.put("ImageFormat", typeKeyValue);
-
-    Photo readUpdated = (Photo) datasource.readData(edmEntitySet, updatedKeys);
-    Assert.assertEquals("BigPicture", readUpdated.getName());
-    Assert.assertEquals("PNG", readUpdated.getType());
-    Assert.assertEquals("image/jpg", readUpdated.getImageType());
-    Assert.assertEquals("https://localhost/image.jpg", readUpdated.getImageUri());
-  }
-
-  @Test
-  public void deleteSimpleEntity() throws Exception {
-    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
-    DataStore<Building> datastore = datasource.getDataStore(Building.class);
-
-    Building building = new Building();
-    building.setName("Common Building");
-    datastore.create(building);
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "1");
-
-    Building read = (Building) datasource.readData(edmEntitySet, keys);
-    Assert.assertEquals("Common Building", read.getName());
-    Assert.assertEquals("1", read.getId());
-
-    //
-    datasource.deleteData(edmEntitySet, keys);
-
-    // validate
-    try {
-      Building readAfterDelete = (Building) datasource.readData(edmEntitySet, keys);
-      Assert.fail("Expected " + ODataNotFoundException.class + "was not thrown for '" + readAfterDelete + "'.");
-    } catch (ODataNotFoundException e) {
-    }
-  }
-
-  @Test(expected = ODataRuntimeException.class)
-  public void unknownEntitySetForEntity() throws Exception {
-    String entitySetName = "Unknown";
-    FullQualifiedName entityType = new FullQualifiedName(DEFAULT_CONTAINER, entitySetName);
-
-    EdmEntitySet edmEntitySet = Mockito.mock(EdmEntitySet.class);
-    Mockito.when(edmEntitySet.getName()).thenReturn(entitySetName);
-    EdmEntityType edmEntityType = Mockito.mock(EdmEntityType.class);
-    Mockito.when(edmEntitySet.getEntityType()).thenReturn(edmEntityType);
-    Mockito.when(edmEntityType.getName()).thenReturn(entityType.getName());
-
-    Map<String, Object> keys = new HashMap<String, Object>();
-    keys.put("Id", "1");
-    //
-    datasource.readData(edmEntitySet, keys);
-  }
-
-  @Test(expected = ODataRuntimeException.class)
-  public void unknownEntitySetForEntities() throws Exception {
-    String entitySetName = "Unknown";
-    FullQualifiedName entityType = new FullQualifiedName(DEFAULT_CONTAINER, entitySetName);
-
-    EdmEntitySet edmEntitySet = Mockito.mock(EdmEntitySet.class);
-    Mockito.when(edmEntitySet.getName()).thenReturn(entitySetName);
-    EdmEntityType edmEntityType = Mockito.mock(EdmEntityType.class);
-    Mockito.when(edmEntitySet.getEntityType()).thenReturn(edmEntityType);
-    Mockito.when(edmEntityType.getName()).thenReturn(entityType.getName());
-
-    //
-    datasource.readData(edmEntitySet);
-  }
-
-  @Test
-  public void writeRelations() throws Exception {
-    DataStore<Building> buildingStore = InMemoryDataStore.createInMemory(Building.class, true);
-    DataStore<Room> roomStore = InMemoryDataStore.createInMemory(Room.class, true);
-
-    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
-    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
-
-    Building building = new Building();
-    building.setName("Common Building");
-    Building created = buildingStore.create(building);
-
-    Room room = new Room(42, "Room with Number");
-    room.setSeats(123);;
-    room.setVersion(4711);
-    roomStore.create(room);
-
-    Map<String, Object> targetEntityKeyValues = new HashMap<String, Object>();
-    targetEntityKeyValues.put("Id", 42);
-
-    // execute
-    datasource.writeRelation(buildingsEntitySet, building, roomsEntitySet, targetEntityKeyValues);
-
-    // validate
-    Building readBuilding = buildingStore.read(created);
-    Room readRoom = roomStore.read(new Room(42, ""));
-
-    List<Room> readRooms = readBuilding.getRooms();
-    Assert.assertEquals(1, readRooms.size());
-    Assert.assertEquals(readRoom, readRooms.get(0));
-
-    Assert.assertEquals("42", readRoom.getId());
-    Assert.assertEquals(123, readRoom.getSeats());
-    Assert.assertEquals(4711, readRoom.getVersion());
-    Assert.assertEquals(readBuilding, readRoom.getBuilding());
-  }
-
-  private EdmEntitySet createMockedEdmEntitySet(final String entitySetName) throws ODataException {
-    return createMockedEdmEntitySet(edmProvider, entitySetName);
-  }
-
-  private EdmEntitySet createMockedEdmEntitySet(AnnotationEdmProvider edmProvider, final String entitySetName)
-          throws ODataException {
-    EntitySet entitySet = edmProvider.getEntitySet(DEFAULT_CONTAINER, entitySetName);
-    FullQualifiedName entityType = entitySet.getEntityType();
-
-    EdmEntitySet edmEntitySet = Mockito.mock(EdmEntitySet.class);
-    Mockito.when(edmEntitySet.getName()).thenReturn(entitySetName);
-    EdmEntityType edmEntityType = Mockito.mock(EdmEntityType.class);
-    Mockito.when(edmEntitySet.getEntityType()).thenReturn(edmEntityType);
-    Mockito.when(edmEntityType.getName()).thenReturn(entityType.getName());
-
-    return edmEntitySet;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-ref/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-ref/src/main/resources/META-INF/persistence.xml b/odata2-annotation-processor/annotation-processor-ref/src/main/resources/META-INF/persistence.xml
index 61ecfed..c434fdf 100644
--- a/odata2-annotation-processor/annotation-processor-ref/src/main/resources/META-INF/persistence.xml
+++ b/odata2-annotation-processor/annotation-processor-ref/src/main/resources/META-INF/persistence.xml
@@ -18,7 +18,7 @@
          under the License.
 -->
 <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
-  <persistence-unit name="AnimalPersistence" transaction-type="RESOURCE_LOCAL">
+  <persistence-unit name="JpaAnnotationDataStorePersistence" transaction-type="RESOURCE_LOCAL">
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
     <class>org.apache.olingo.odata2.annotation.processor.ref.model.jpa.Animal</class>
     <properties>


[2/2] git commit: [OLINGO-129] Introduced DataStoreFactory

Posted by mi...@apache.org.
[OLINGO-129] Introduced DataStoreFactory


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

Branch: refs/heads/Olingo-129_PocJpaDataStore
Commit: 4941d846146e2107b5704655820d1d1de56c449d
Parents: b0e0a32
Author: Michael Bolz <mi...@apache.org>
Authored: Sun Jan 26 14:48:11 2014 +0100
Committer: Michael Bolz <mi...@apache.org>
Committed: Sun Jan 26 14:48:11 2014 +0100

----------------------------------------------------------------------
 .../core/AnnotationServiceFactoryImpl.java      |   6 +-
 .../core/datasource/AnnotationDataSource.java   | 433 ++++++++++
 .../core/datasource/AnnotationInMemoryDs.java   | 431 ----------
 .../processor/core/datasource/DataStore.java    |   6 +-
 .../core/datasource/DataStoreFactory.java       |  20 +-
 .../core/datasource/DualDataStoreFactory.java   |  56 ++
 .../core/datasource/InMemoryDataStore.java      |   3 +-
 .../core/datasource/JpaAnnotationDataStore.java |  40 +-
 .../processor/core/ListsProcessorTest.java      |   4 +-
 .../datasource/AnnotationsDataSourceTest.java   | 804 +++++++++++++++++++
 .../datasource/AnnotationsInMemoryDsTest.java   | 801 ------------------
 .../src/main/resources/META-INF/persistence.xml |   2 +-
 12 files changed, 1336 insertions(+), 1270 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/AnnotationServiceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/AnnotationServiceFactoryImpl.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/AnnotationServiceFactoryImpl.java
index 7947d6b..b5825e7 100644
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/AnnotationServiceFactoryImpl.java
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/AnnotationServiceFactoryImpl.java
@@ -21,7 +21,7 @@ package org.apache.olingo.odata2.annotation.processor.core;
 import java.util.Collection;
 
 import org.apache.olingo.odata2.annotation.processor.api.AnnotationServiceFactory.AnnotationServiceFactoryInstance;
-import org.apache.olingo.odata2.annotation.processor.core.datasource.AnnotationInMemoryDs;
+import org.apache.olingo.odata2.annotation.processor.core.datasource.AnnotationDataSource;
 import org.apache.olingo.odata2.annotation.processor.core.datasource.AnnotationValueAccess;
 import org.apache.olingo.odata2.annotation.processor.core.edm.AnnotationEdmProvider;
 import org.apache.olingo.odata2.api.ODataService;
@@ -39,7 +39,7 @@ public class AnnotationServiceFactoryImpl implements AnnotationServiceFactoryIns
   @Override
   public ODataService createAnnotationService(String modelPackage) throws ODataException {
     AnnotationEdmProvider edmProvider = new AnnotationEdmProvider(modelPackage);
-    AnnotationInMemoryDs dataSource = new AnnotationInMemoryDs(modelPackage);
+    AnnotationDataSource dataSource = new AnnotationDataSource(modelPackage);
     AnnotationValueAccess valueAccess = new AnnotationValueAccess();
 
     // Edm via Annotations and ListProcessor via AnnotationDS with AnnotationsValueAccess
@@ -53,7 +53,7 @@ public class AnnotationServiceFactoryImpl implements AnnotationServiceFactoryIns
   @Override
   public ODataService createAnnotationService(Collection<Class<?>> annotatedClasses) throws ODataException {
     AnnotationEdmProvider edmProvider = new AnnotationEdmProvider(annotatedClasses);
-    AnnotationInMemoryDs dataSource = new AnnotationInMemoryDs(annotatedClasses);
+    AnnotationDataSource dataSource = new AnnotationDataSource(annotatedClasses);
     AnnotationValueAccess valueAccess = new AnnotationValueAccess();
 
     // Edm via Annotations and ListProcessor via AnnotationDS with AnnotationsValueAccess

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationDataSource.java
----------------------------------------------------------------------
diff --git 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
new file mode 100644
index 0000000..c749e74
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationDataSource.java
@@ -0,0 +1,433 @@
+/**
+ * *****************************************************************************
+ * 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.ClassHelper;
+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;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+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();
+    if (sourceField == null) {
+      throw new ODataRuntimeException("Missing source field for related data (sourceStore='" + sourceStore
+          + "', targetStore='" + targetStore + "').");
+    }
+
+    List<Object> resultData = readResultData(targetStore, sourceData, sourceField);
+    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)
+      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) {
+        for (Object object : (Collection<?>) navigationInstance) {
+          if (targetStore.isKeyEqualChecked(targetInstance, object)) {
+            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 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/4941d846/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationInMemoryDs.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationInMemoryDs.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationInMemoryDs.java
deleted file mode 100644
index ee8c602..0000000
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationInMemoryDs.java
+++ /dev/null
@@ -1,431 +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.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.ClassHelper;
-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;
-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 DataStoreFactory dataStoreFactory;
-  private final boolean persistInMemory;
-
-  public AnnotationInMemoryDs(final Collection<Class<?>> annotatedClasses) throws ODataException {
-    this(annotatedClasses, true);
-  }
-
-  public AnnotationInMemoryDs(final Collection<Class<?>> annotatedClasses, final boolean persistInMemory) 
-      throws ODataException {
-    this.persistInMemory = persistInMemory;
-    this.dataStoreFactory = new DataStoreFactory();
-    
-    init(annotatedClasses);
-  }
-
-  public AnnotationInMemoryDs(final String packageToScan) throws ODataException {
-    this(packageToScan, true);
-  }
-
-  public AnnotationInMemoryDs(final String packageToScan, final boolean persistInMemory) throws ODataException {
-    this.persistInMemory = persistInMemory;
-    this.dataStoreFactory = new 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.createInstance(clz, persistInMemory);
-          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();
-    if (sourceField == null) {
-      throw new ODataRuntimeException("Missing source field for related data (sourceStore='" + sourceStore
-          + "', targetStore='" + targetStore + "').");
-    }
-
-    List<Object> resultData = readResultData(targetStore, sourceData, sourceField);
-    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)
-      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) {
-        for (Object object : (Collection<?>) navigationInstance) {
-          if (targetStore.isKeyEqualChecked(targetInstance, object)) {
-            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 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/4941d846/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStore.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStore.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStore.java
index 2db386b..ff47232 100644
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStore.java
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStore.java
@@ -42,14 +42,14 @@ public interface DataStore<T> {
    * @param second second instance to check for key equal
    * @return <code>true</code> if object instance have equal keys set.
    */
-  boolean isKeyEqual(final T first, final T second);
+//  boolean isKeyEqual(final T first, final T second);
 
   /**
    * 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
+   * and that both are from the same class as this {@link DataStore} (see {@link #getDataTypeClass()}).
+   * For the equal check on {@link #getDataTypeClass()} instances without validation see
    * {@link #isKeyEqual(Object, Object)}.
    *
    * @param first first instance to check for key equal

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStoreFactory.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStoreFactory.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStoreFactory.java
index 739ec94..9d0b97b 100644
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStoreFactory.java
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DataStoreFactory.java
@@ -16,21 +16,15 @@
 
 package org.apache.olingo.odata2.annotation.processor.core.datasource;
 
-import javax.persistence.Entity;
+import java.util.Map;
 
 /**
  *
  */
-public class DataStoreFactory {
- 
-  public DataStore<?> createInstance(Class<?> clz, boolean keepPersistent) throws DataStoreException {
-    if(isJpaAnnotated(clz)) {
-      return JpaAnnotationDataStore.createInstance(clz);
-    }
-    return InMemoryDataStore.createInMemory(clz, keepPersistent);
-  }
-
-  private boolean isJpaAnnotated(Class<?> clz) {
-    return clz.getAnnotation(Entity.class) != null;
-  }
+public interface DataStoreFactory {
+  static final String KEEP_PERSISTENT = "KEEP_PERSISTENT";
+  
+  void setDefaultProperty(String name, String value);
+  DataStore<?> createDataStore(Class<?> clz) throws DataStoreException;
+  DataStore<?> createDataStore(Class<?> clz, Map<String, String> properties) throws DataStoreException;
 }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DualDataStoreFactory.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DualDataStoreFactory.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DualDataStoreFactory.java
new file mode 100644
index 0000000..0140118
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/DualDataStoreFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2014 The Apache Software Foundation.
+ *
+ * Licensed 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.util.HashMap;
+import java.util.Map;
+import javax.persistence.Entity;
+
+/**
+ *
+ */
+public class DualDataStoreFactory implements DataStoreFactory {
+
+  private final Map<String, String> properties = new HashMap<String, String>();
+  
+  @Override
+  public DataStore<?> createDataStore(Class<?> clz) throws DataStoreException {
+    return createDataStore(clz, properties);
+  }
+
+  @Override
+  public DataStore<?> createDataStore(Class<?> clz, Map<String, String> properties) throws DataStoreException {
+    boolean keepPersistent = Boolean.parseBoolean(properties.get(KEEP_PERSISTENT));
+    return createInstance(clz, keepPersistent);
+  }
+
+  @Override
+  public void setDefaultProperty(String name, String value) {
+    properties.put(name, value);
+  }
+  
+  public DataStore<?> createInstance(Class<?> clz, boolean keepPersistent) throws DataStoreException {
+    if(isJpaAnnotated(clz)) {
+      return JpaAnnotationDataStore.createInstance(clz);
+    }
+    return InMemoryDataStore.createInMemory(clz, keepPersistent);
+  }
+
+  private boolean isJpaAnnotated(Class<?> clz) {
+    return clz.getAnnotation(Entity.class) != null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/InMemoryDataStore.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/InMemoryDataStore.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/InMemoryDataStore.java
index b50ada1..af66016 100644
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/InMemoryDataStore.java
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/InMemoryDataStore.java
@@ -153,8 +153,7 @@ public class InMemoryDataStore<T> implements DataStore<T> {
    * @param second second instance to check for key equal
    * @return <code>true</code> if object instance have equal keys set.
    */
-  @Override
-  public boolean isKeyEqual(final T first, final T second) {
+  private boolean isKeyEqual(final T first, final T second) {
     KeyElement firstKeys = getKeys(first);
     KeyElement secondKeys = getKeys(second);
     

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/JpaAnnotationDataStore.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/JpaAnnotationDataStore.java b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/JpaAnnotationDataStore.java
index fe32483..65f9344 100644
--- a/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/JpaAnnotationDataStore.java
+++ b/odata2-annotation-processor/annotation-processor-core/src/main/java/org/apache/olingo/odata2/annotation/processor/core/datasource/JpaAnnotationDataStore.java
@@ -30,17 +30,23 @@ import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
  */
 public class JpaAnnotationDataStore<T> implements DataStore<T> {
 
-  public static DataStore<?> createInstance(Class<?> clz) {
-    return new JpaAnnotationDataStore<Object>((Class<Object>) clz);
-  }
+  public static final String DEFAULT_PERSISTENCE_NAME = "JpaAnnotationDataStorePersistence";
 
-  protected Class<T> dataTypeClass;
   private static final AnnotationHelper ANNOTATION_HELPER = new AnnotationHelper();
 
+  protected Class<T> dataTypeClass;
   protected EntityManager entityManager;
 
-  public JpaAnnotationDataStore(final Class<T> clz) {
-    EntityManagerFactory emf = Persistence.createEntityManagerFactory("AnimalPersistence");
+  public static DataStore<?> createInstance(Class<?> clz) {
+    return createInstance(clz, DEFAULT_PERSISTENCE_NAME);
+  }
+
+  public static DataStore<?> createInstance(Class<?> clz, String persistenceName) {
+    return new JpaAnnotationDataStore<Object>((Class<Object>) clz, persistenceName);
+  }
+
+  private JpaAnnotationDataStore(final Class<T> clz, String persistenceName) {
+    EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceName);
     entityManager = emf.createEntityManager();
     this.dataTypeClass = clz;
   }
@@ -103,11 +109,6 @@ public class JpaAnnotationDataStore<T> implements DataStore<T> {
   }
 
   @Override
-  public boolean isKeyEqual(T first, T second) {
-    return ANNOTATION_HELPER.keyMatch(first, second);
-  }
-
-  @Override
   public boolean isKeyEqualChecked(Object first, Object second) throws DataStoreException {
     return ANNOTATION_HELPER.keyMatch(first, second);
   }
@@ -122,13 +123,24 @@ public class JpaAnnotationDataStore<T> implements DataStore<T> {
   public Collection<T> read() {
     TypedQuery<T> query = entityManager.createQuery(
             "select t from " + dataTypeClass.getSimpleName() + " t", dataTypeClass);
-//    Query query = entityManager.createQuery(
-//            "select t from " + dataTypeClass.getSimpleName() + " t");
     return query.getResultList();
   }
 
   @Override
   public T update(T object) {
-    return this.entityManager.merge(object);
+    EntityTransaction t = this.entityManager.getTransaction();
+    try {
+      t.begin();
+      object = this.entityManager.merge(object);
+      this.entityManager.flush();
+      t.commit();
+
+      return object;
+    } catch(Exception e) {
+      if(t != null && t.isActive()) {
+        t.rollback();
+      }
+    }
+    return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessorTest.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessorTest.java b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessorTest.java
index 82b857c..f5772f5 100644
--- a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessorTest.java
+++ b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/ListsProcessorTest.java
@@ -15,7 +15,7 @@
  */
 package org.apache.olingo.odata2.annotation.processor.core;
 
-import org.apache.olingo.odata2.annotation.processor.core.datasource.AnnotationInMemoryDs;
+import org.apache.olingo.odata2.annotation.processor.core.datasource.AnnotationDataSource;
 import org.apache.olingo.odata2.annotation.processor.core.datasource.AnnotationValueAccess;
 import org.apache.olingo.odata2.annotation.processor.core.datasource.DataSource;
 import org.apache.olingo.odata2.annotation.processor.core.datasource.ValueAccess;
@@ -36,7 +36,7 @@ public class ListsProcessorTest {
   
   @Test
   public void init() throws ODataException {
-    DataSource dataSource = new AnnotationInMemoryDs(Building.class.getPackage().getName());
+    DataSource dataSource = new AnnotationDataSource(Building.class.getPackage().getName());
     ValueAccess valueAccess = new AnnotationValueAccess();
     ListsProcessor lp = new ListsProcessor(dataSource, valueAccess);
     

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/4941d846/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationsDataSourceTest.java
----------------------------------------------------------------------
diff --git a/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationsDataSourceTest.java b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationsDataSourceTest.java
new file mode 100644
index 0000000..f2c1fe2
--- /dev/null
+++ b/odata2-annotation-processor/annotation-processor-core/src/test/java/org/apache/olingo/odata2/annotation/processor/core/datasource/AnnotationsDataSourceTest.java
@@ -0,0 +1,804 @@
+/*
+ * Copyright 2013 The Apache Software Foundation.
+ * 
+ * Licensed 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.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.olingo.odata2.annotation.processor.core.datasource.DataSource.BinaryData;
+import org.apache.olingo.odata2.annotation.processor.core.edm.AnnotationEdmProvider;
+import org.apache.olingo.odata2.annotation.processor.core.model.Building;
+import org.apache.olingo.odata2.annotation.processor.core.model.City;
+import org.apache.olingo.odata2.annotation.processor.core.model.Employee;
+import org.apache.olingo.odata2.annotation.processor.core.model.Location;
+import org.apache.olingo.odata2.annotation.processor.core.model.Manager;
+import org.apache.olingo.odata2.annotation.processor.core.model.ModelSharedConstants;
+import org.apache.olingo.odata2.annotation.processor.core.model.Photo;
+import org.apache.olingo.odata2.annotation.processor.core.model.RefBase;
+import org.apache.olingo.odata2.annotation.processor.core.model.Room;
+import org.apache.olingo.odata2.annotation.processor.core.model.Team;
+import org.apache.olingo.odata2.annotation.processor.core.util.AnnotationHelper;
+import org.apache.olingo.odata2.api.annotation.edm.EdmKey;
+import org.apache.olingo.odata2.api.annotation.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ *
+ */
+public class AnnotationsDataSourceTest {
+
+  final static Set<Class<?>> ANNOTATED_MODEL_CLASSES = new HashSet<Class<?>>();
+  final static Set<Class<?>> ANNOTATED_ENTITY_SET_CLASSES = new HashSet<Class<?>>();
+
+  static {
+    ANNOTATED_ENTITY_SET_CLASSES.add(Building.class);
+    ANNOTATED_ENTITY_SET_CLASSES.add(Employee.class);
+    ANNOTATED_ENTITY_SET_CLASSES.add(Manager.class);
+    ANNOTATED_ENTITY_SET_CLASSES.add(Photo.class);
+    ANNOTATED_ENTITY_SET_CLASSES.add(Room.class);
+    ANNOTATED_ENTITY_SET_CLASSES.add(Team.class);
+    
+    ANNOTATED_MODEL_CLASSES.addAll(ANNOTATED_ENTITY_SET_CLASSES);
+    ANNOTATED_MODEL_CLASSES.add(Location.class);
+    ANNOTATED_MODEL_CLASSES.add(City.class);
+    ANNOTATED_MODEL_CLASSES.add(RefBase.class);
+  }
+
+  private final AnnotationDataSource datasource;
+  private final AnnotationEdmProvider edmProvider;
+  private static final String DEFAULT_CONTAINER = ModelSharedConstants.CONTAINER_1;
+  private final DualDataStoreFactory dataStoreFactory;
+
+  public AnnotationsDataSourceTest() throws ODataException {
+    dataStoreFactory = new DualDataStoreFactory();
+    dataStoreFactory.setDefaultProperty(DataStoreFactory.KEEP_PERSISTENT, Boolean.FALSE.toString());
+    datasource = new AnnotationDataSource(Building.class.getPackage().getName(), dataStoreFactory);
+    edmProvider = new AnnotationEdmProvider(Building.class.getPackage().getName());
+  }
+  
+  @Test
+  public void initFromPackage() throws Exception {
+    AnnotationDataSource ds = new AnnotationDataSource(Building.class.getPackage().getName());
+    Assert.assertNotNull(ds);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void initFromNotExistingPackage() throws Exception {
+    AnnotationDataSource ds = new AnnotationDataSource("does.not.exist");
+    Assert.assertNotNull(ds);
+  }
+
+  @Test
+  public void initFromPackageWithoutAnnotatedClasses() throws Exception {
+    AnnotationDataSource ds = new AnnotationDataSource(this.getClass().getPackage().getName());
+    Assert.assertNotNull(ds);
+  }
+
+  @Test
+  public void initFromClassCollectionEntitySets() throws Exception {
+    AnnotationDataSource ds = new AnnotationDataSource(ANNOTATED_ENTITY_SET_CLASSES);
+    Assert.assertNotNull(ds);
+  }
+
+  @Test
+  public void initFromClassCollectionModel() throws Exception {
+    AnnotationDataSource ds = new AnnotationDataSource(ANNOTATED_MODEL_CLASSES);
+    Assert.assertNotNull(ds);
+  }
+
+  @Test(expected = ODataException.class)
+  public void initFromClassCollectionNotAnnotated() throws Exception {
+    Set<Class<?>> annotatedClassesAndMore = new HashSet<Class<?>>(ANNOTATED_ENTITY_SET_CLASSES);
+    annotatedClassesAndMore.add(String.class);
+    annotatedClassesAndMore.add(Object.class);
+    AnnotationDataSource ds = new AnnotationDataSource(annotatedClassesAndMore);
+    Assert.assertNotNull(ds);
+  }
+
+  @Test
+  @Ignore
+  public void multiThreadedSyncOnBuildingsTest() throws Exception {
+    final EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
+    CountDownLatch latch;
+
+    List<Thread> threads = new ArrayList<Thread>();
+    int max = 500;
+
+    latch = new CountDownLatch(max);
+    for (int i = 0; i < max; i++) {
+      threads.add(createBuildingThread(latch, datasource, edmEntitySet, String.valueOf("10")));
+    }
+
+    for (Thread thread : threads) {
+      thread.start();
+    }
+
+    latch.await(60, TimeUnit.SECONDS);
+
+    DataStore<Building> ds = datasource.getDataStore(Building.class);
+    Collection<Building> buildings = ds.read();
+    Assert.assertEquals(max, buildings.size());
+  }
+
+  @org.apache.olingo.odata2.api.annotation.edm.EdmEntitySet
+  @org.apache.olingo.odata2.api.annotation.edm.EdmEntityType
+  private static class SimpleEntity {
+
+    @EdmKey
+    @EdmProperty
+    public Integer id;
+    @EdmProperty
+    public String name;
+  }
+
+  @Test
+  @Ignore
+  public void multiThreadedSyncCreateReadTest() throws Exception {
+    Collection<Class<?>> ac = new ArrayList<Class<?>>();
+    ac.add(SimpleEntity.class);
+    final AnnotationDataSource localDs = new AnnotationDataSource(SimpleEntity.class.getPackage().getName());
+    final AnnotationEdmProvider localProvider = new AnnotationEdmProvider(ac);
+    final EdmEntitySet edmEntitySet = createMockedEdmEntitySet(localProvider, "SimpleEntitySet");
+    final CountDownLatch latch;
+
+    List<Thread> threads = new ArrayList<Thread>();
+    int max = 500;
+    latch = new CountDownLatch(max);
+    for (int i = 0; i < max; i++) {
+      Runnable run = new Runnable() {
+        @Override
+        public void run() {
+          SimpleEntity se = new SimpleEntity();
+          se.id = Integer.valueOf(String.valueOf(System.currentTimeMillis()).substring(8));
+          se.name = "Name: " + System.currentTimeMillis();
+          try {
+            localDs.createData(edmEntitySet, se);
+          } catch (Exception ex) {
+            throw new RuntimeException(ex);
+          } finally {
+            latch.countDown();
+          }
+        }
+      };
+
+      threads.add(new Thread(run));
+    }
+
+    for (Thread thread : threads) {
+      thread.start();
+    }
+
+    latch.await(60, TimeUnit.SECONDS);
+
+    DataStore<SimpleEntity> ds = localDs.getDataStore(SimpleEntity.class);
+    Collection<SimpleEntity> buildings = ds.read();
+    Assert.assertEquals(max, buildings.size());
+  }
+
+  private Thread createBuildingThread(final CountDownLatch latch, final DataSource datasource,
+          final EdmEntitySet edmEntitySet, final String id) {
+    Runnable run = new Runnable() {
+      @Override
+      public void run() {
+        Building building = new Building();
+        building.setName("Common Building - " + System.currentTimeMillis());
+        building.setId(id);
+        try {
+          datasource.createData(edmEntitySet, building);
+        } catch (Exception ex) {
+          ex.printStackTrace();
+          throw new RuntimeException(ex);
+        } finally {
+          latch.countDown();
+        }
+      }
+    };
+
+    return new Thread(run);
+  }
+
+  @Test
+  public void readBinaryData() throws Exception {
+    EdmEntitySet entitySet = createMockedEdmEntitySet("Photos");
+
+    DataStore<Photo> photoDataStore = datasource.getDataStore(Photo.class);
+    Photo photo = new Photo();
+    photo.setName("SomePic");
+    photo.setType("PNG");
+    byte[] image = "binary".getBytes(Charset.defaultCharset());
+    photo.setImage(image);
+    photo.setImageType("image/png");
+    photoDataStore.create(photo);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Name", "SomePic");
+    keys.put("ImageFormat", "PNG");
+    Photo toReadPhoto = (Photo) datasource.readData(entitySet, keys);
+
+    // execute
+    BinaryData readBinaryData = datasource.readBinaryData(entitySet, toReadPhoto);
+
+    // validate
+    Assert.assertEquals("binary", new String(readBinaryData.getData(), Charset.defaultCharset()));
+    Assert.assertArrayEquals(image, readBinaryData.getData());
+    Assert.assertEquals("image/png", readBinaryData.getMimeType());
+  }
+
+  @Test
+  public void readBinaryDataDirect() throws Exception {
+    EdmEntitySet entitySet = createMockedEdmEntitySet("Photos");
+
+    DataStore<Photo> photoDataStore = datasource.getDataStore(Photo.class);
+    Photo photo = new Photo();
+    photo.setName("SomePic");
+    photo.setType("PNG");
+    byte[] image = "binary".getBytes(Charset.defaultCharset());
+    photo.setImage(image);
+    photo.setImageType("image/png");
+    photoDataStore.create(photo);
+
+    Photo toReadPhoto = new Photo();
+    toReadPhoto.setName("SomePic");
+    toReadPhoto.setType("PNG");
+    toReadPhoto.setImage(null);
+    toReadPhoto.setImageType(null);
+
+    BinaryData readBinaryData = datasource.readBinaryData(entitySet, toReadPhoto);
+
+    Assert.assertEquals("binary", new String(readBinaryData.getData(), Charset.defaultCharset()));
+    Assert.assertArrayEquals(image, readBinaryData.getData());
+    Assert.assertEquals("image/png", readBinaryData.getMimeType());
+  }
+
+  @Test
+  public void writeBinaryData() throws Exception {
+    EdmEntitySet entitySet = createMockedEdmEntitySet("Photos");
+
+    DataStore<Photo> photoDataStore = datasource.getDataStore(Photo.class);
+
+    Photo toWritePhoto = new Photo();
+    toWritePhoto.setName("SomePic");
+    toWritePhoto.setType("PNG");
+    photoDataStore.create(toWritePhoto);
+    byte[] image = "binary".getBytes(Charset.defaultCharset());
+    String mimeType = "image/png";
+    BinaryData writeBinaryData = new BinaryData(image, mimeType);
+    // execute
+    datasource.writeBinaryData(entitySet, toWritePhoto, writeBinaryData);
+
+    // validate
+    Photo photoKey = new Photo();
+    photoKey.setName("SomePic");
+    photoKey.setType("PNG");
+    Photo storedPhoto = photoDataStore.read(photoKey);
+    Assert.assertEquals("binary", new String(storedPhoto.getImage(), Charset.defaultCharset()));
+    Assert.assertArrayEquals(image, storedPhoto.getImage());
+    Assert.assertEquals("image/png", storedPhoto.getImageType());
+  }
+
+  @Test(expected = ODataNotFoundException.class)
+  public void writeBinaryDataNotFound() throws Exception {
+    EdmEntitySet entitySet = createMockedEdmEntitySet("Photos");
+
+    Photo toWritePhoto = new Photo();
+    toWritePhoto.setName("SomePic");
+    toWritePhoto.setType("PNG");
+    byte[] image = "binary".getBytes(Charset.defaultCharset());
+    String mimeType = "image/png";
+    BinaryData writeBinaryData = new BinaryData(image, mimeType);
+    // execute
+    datasource.writeBinaryData(entitySet, toWritePhoto, writeBinaryData);
+  }
+
+  @Test
+  public void newDataObject() throws Exception {
+    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
+    Room room = (Room) datasource.newDataObject(roomsEntitySet);
+
+    Assert.assertNotNull(room);
+  }
+
+  @Test
+  public void readEntity() throws Exception {
+    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
+    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
+
+    Building building = new Building();
+    building.setName("Common Building");
+
+    final int roomsCount = 3;
+    List<Room> rooms = new ArrayList<Room>();
+    for (int i = 0; i < roomsCount; i++) {
+      Room room = new Room(i, "Room " + i);
+      room.setBuilding(building);
+      datasource.createData(roomsEntitySet, room);
+      rooms.add(room);
+    }
+
+    building.getRooms().addAll(rooms);
+    datasource.createData(buildingsEntitySet, building);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "1");
+
+    // execute
+    Object relatedData = datasource.readData(buildingsEntitySet, keys);
+
+    // validate
+    Building readBuilding = (Building) relatedData;
+    Assert.assertEquals("Common Building", readBuilding.getName());
+    Assert.assertEquals("1", readBuilding.getId());
+
+    Collection<Room> relatedRooms = readBuilding.getRooms();
+    Assert.assertEquals(roomsCount, relatedRooms.size());
+    for (Room room : relatedRooms) {
+      Assert.assertNotNull(room.getId());
+      Assert.assertTrue(room.getName().matches("Room \\d*"));
+      Assert.assertEquals("Common Building", room.getBuilding().getName());
+    }
+  }
+
+  @Test(expected = ODataRuntimeException.class)
+  public void readUnknownEntity() throws Exception {
+    EdmEntitySet unknownEntitySet = Mockito.mock(EdmEntitySet.class);
+    Mockito.when(unknownEntitySet.getName()).thenReturn("UnknownEntity");
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "1");
+
+    // execute
+    datasource.readData(unknownEntitySet, keys);
+  }
+
+  @Test(expected = ODataRuntimeException.class)
+  public void readUnknownEntities() throws Exception {
+    EdmEntitySet unknownEntitySet = Mockito.mock(EdmEntitySet.class);
+    Mockito.when(unknownEntitySet.getName()).thenReturn("UnknownEntity");
+
+    // execute
+    datasource.readData(unknownEntitySet);
+  }
+
+  @Test
+  public void readEntities() throws Exception {
+    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
+
+    Building building = new Building();
+    building.setName("Common Building");
+
+    final int roomsCount = 11;
+    List<Room> rooms = new ArrayList<Room>();
+    for (int i = 0; i < roomsCount; i++) {
+      Room room = new Room(i, "Room " + i);
+      room.setBuilding(building);
+      datasource.createData(roomsEntitySet, room);
+      rooms.add(room);
+    }
+
+    // execute
+    Object relatedData = datasource.readData(roomsEntitySet);
+
+    // validate
+    @SuppressWarnings("unchecked")
+    Collection<Room> relatedRooms = (Collection<Room>) relatedData;
+    Assert.assertEquals(roomsCount, relatedRooms.size());
+    for (Room room : relatedRooms) {
+      Assert.assertNotNull(room.getId());
+      Assert.assertTrue(room.getName().matches("Room \\d*"));
+      Assert.assertEquals("Common Building", room.getBuilding().getName());
+    }
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void readRelatedEntities() throws Exception {
+    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
+    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
+
+    Building building = new Building();
+    building.setName("Common Building");
+
+    final int roomsCount = 10;
+    List<Room> rooms = new ArrayList<Room>();
+    for (int i = 0; i < roomsCount; i++) {
+      Room room = new Room(i, "Room " + i);
+      room.setBuilding(building);
+      datasource.createData(roomsEntitySet, room);
+      rooms.add(room);
+    }
+
+    building.getRooms().addAll(rooms);
+    datasource.createData(buildingsEntitySet, building);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "1");
+
+    Building read = (Building) datasource.readData(buildingsEntitySet, keys);
+    Assert.assertEquals("Common Building", read.getName());
+    Assert.assertEquals("1", read.getId());
+
+    // execute
+    Object relatedData = datasource.readRelatedData(
+            buildingsEntitySet, building, roomsEntitySet, Collections.EMPTY_MAP);
+
+    // validate
+    Assert.assertTrue("Result is no collection.", relatedData instanceof Collection);
+    Collection<Room> relatedRooms = (Collection<Room>) relatedData;
+    Assert.assertEquals(roomsCount, relatedRooms.size());
+    for (Room room : relatedRooms) {
+      Assert.assertNotNull(room.getId());
+      Assert.assertTrue(room.getName().matches("Room \\d*"));
+      Assert.assertEquals("Common Building", room.getBuilding().getName());
+    }
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void readRelatedEntity() throws Exception {
+    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
+    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
+
+    Building building = new Building();
+    building.setName("Common Building");
+
+    Room room = new Room(12, "Room 12");
+    room.setBuilding(building);
+    datasource.createData(roomsEntitySet, room);
+    datasource.createData(buildingsEntitySet, building);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", Integer.valueOf(12));
+    Room read = (Room) datasource.readData(roomsEntitySet, keys);
+    Assert.assertEquals("Room 12", read.getName());
+    Assert.assertEquals("12", read.getId());
+
+    // execute
+    Object relatedData = datasource.readRelatedData(
+            roomsEntitySet, room, buildingsEntitySet, Collections.EMPTY_MAP);
+
+    // validate
+    Assert.assertTrue("Result is no room.", relatedData instanceof Building);
+    Building b = (Building) relatedData;
+    Assert.assertEquals("Common Building", b.getName());
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void readRelatedEntityWithNull() throws Exception {
+    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
+    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
+
+    Building building = new Building();
+    building.setName("Common Building");
+    datasource.createData(buildingsEntitySet, building);
+
+    Room room = new Room(12, "Room 12");
+    room.setBuilding(null);
+    datasource.createData(roomsEntitySet, room);
+    //
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", Integer.valueOf(12));
+    Room read = (Room) datasource.readData(roomsEntitySet, keys);
+    Assert.assertEquals("Room 12", read.getName());
+    Assert.assertEquals("12", read.getId());
+
+    // execute
+    Object relatedData = datasource.readRelatedData(
+            roomsEntitySet, room, buildingsEntitySet, Collections.EMPTY_MAP);
+
+    // validate
+    Assert.assertNull("Related data must be null.", relatedData);
+  }
+
+  @Test
+  public void readRelatedTargetEntity() throws Exception {
+    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
+    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
+
+    Building building = new Building();
+    building.setName("Common Building");
+
+    final int roomsCount = 10;
+    List<Room> rooms = new ArrayList<Room>();
+    for (int i = 0; i < roomsCount; i++) {
+      Room room = new Room(i, "Room " + i);
+      room.setBuilding(building);
+      datasource.createData(roomsEntitySet, room);
+      rooms.add(room);
+    }
+
+    building.getRooms().addAll(rooms);
+    datasource.createData(buildingsEntitySet, building);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "1");
+
+    Building read = (Building) datasource.readData(buildingsEntitySet, keys);
+    Assert.assertEquals("Common Building", read.getName());
+    Assert.assertEquals("1", read.getId());
+
+    // execute
+    Map<String, Object> targetKeys = new HashMap<String, Object>();
+    targetKeys.put("Id", 3);
+    Object relatedData = datasource.readRelatedData(
+            buildingsEntitySet, building, roomsEntitySet, targetKeys);
+
+    // validate
+    Assert.assertTrue("Result is no Room.", relatedData instanceof Room);
+    Room relatedRoom = (Room) relatedData;
+    Assert.assertEquals("3", relatedRoom.getId());
+    Assert.assertEquals("Room 3", relatedRoom.getName());
+    Assert.assertEquals("Common Building", relatedRoom.getBuilding().getName());
+  }
+
+  @Test
+  public void createSimpleEntity() throws Exception {
+    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
+
+    Building building = new Building();
+    building.setName("Common Building");
+    datasource.createData(edmEntitySet, building);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "1");
+
+    Building read = (Building) datasource.readData(edmEntitySet, keys);
+    Assert.assertEquals("Common Building", read.getName());
+    Assert.assertEquals("1", read.getId());
+  }
+
+  @Test
+  public void createSimpleEntityWithOwnKey() throws Exception {
+    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
+
+    Building building = new Building();
+    building.setName("Common Building");
+    AnnotationHelper ah = new AnnotationHelper();
+    ah.setValueForProperty(building, "Id", "42");
+    datasource.createData(edmEntitySet, building);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "42");
+
+    Building read = (Building) datasource.readData(edmEntitySet, keys);
+    Assert.assertEquals("Common Building", read.getName());
+    Assert.assertEquals("42", read.getId());
+  }
+
+  @Test
+  public void createSimpleEntityWithDuplicateKey() throws Exception {
+    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
+    AnnotationHelper ah = new AnnotationHelper();
+
+    Building building = new Building();
+    building.setName("Common Building");
+    ah.setValueForProperty(building, "Id", "42");
+    datasource.createData(edmEntitySet, building);
+    //
+    Building buildingDuplicate = new Building();
+    buildingDuplicate.setName("Duplicate Building");
+    ah.setValueForProperty(buildingDuplicate, "Id", "42");
+    datasource.createData(edmEntitySet, buildingDuplicate);
+
+    Map<String, Object> keys42 = new HashMap<String, Object>();
+    keys42.put("Id", "42");
+    Building read42 = (Building) datasource.readData(edmEntitySet, keys42);
+    Assert.assertEquals("Common Building", read42.getName());
+    Assert.assertEquals("42", read42.getId());
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "1");
+    Building read = (Building) datasource.readData(edmEntitySet, keys);
+    Assert.assertEquals("Duplicate Building", read.getName());
+    Assert.assertEquals("1", read.getId());
+  }
+
+  @Test
+  public void createEntityTwoKeys() throws Exception {
+    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Photos");
+
+    Photo photo = new Photo();
+    photo.setName("BigPicture");
+    photo.setType("PNG");
+    photo.setImageUri("https://localhost/image.png");
+    photo.setImageType("image/png");
+    datasource.createData(edmEntitySet, photo);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("ImageFormat", "PNG");
+    keys.put("Name", "BigPicture");
+
+    Photo read = (Photo) datasource.readData(edmEntitySet, keys);
+    Assert.assertEquals("BigPicture", read.getName());
+    Assert.assertEquals("PNG", read.getType());
+    Assert.assertEquals("image/png", read.getImageType());
+    Assert.assertEquals("https://localhost/image.png", read.getImageUri());
+  }
+
+  @Test
+  public void createAndUpdateEntityTwoKeys() throws Exception {
+    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Photos");
+
+    Photo photo = new Photo();
+    final String nameKeyValue = "BigPicture";
+    final String typeKeyValue = "PNG";
+    photo.setName(nameKeyValue);
+    photo.setType(typeKeyValue);
+    photo.setImageUri("https://localhost/image.png");
+    photo.setImageType("image/png");
+    datasource.createData(edmEntitySet, photo);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Name", "BigPicture");
+    keys.put("ImageFormat", "PNG");
+
+    Photo read = (Photo) datasource.readData(edmEntitySet, keys);
+    Assert.assertEquals("BigPicture", read.getName());
+    Assert.assertEquals("PNG", read.getType());
+    Assert.assertEquals("image/png", read.getImageType());
+    Assert.assertEquals("https://localhost/image.png", read.getImageUri());
+
+    // update
+    Photo updatedPhoto = new Photo();
+    updatedPhoto.setName(nameKeyValue);
+    updatedPhoto.setType(typeKeyValue);
+    updatedPhoto.setImageUri("https://localhost/image.jpg");
+    updatedPhoto.setImageType("image/jpg");
+    datasource.updateData(edmEntitySet, updatedPhoto);
+
+    Map<String, Object> updatedKeys = new HashMap<String, Object>();
+    updatedKeys.put("Name", nameKeyValue);
+    updatedKeys.put("ImageFormat", typeKeyValue);
+
+    Photo readUpdated = (Photo) datasource.readData(edmEntitySet, updatedKeys);
+    Assert.assertEquals("BigPicture", readUpdated.getName());
+    Assert.assertEquals("PNG", readUpdated.getType());
+    Assert.assertEquals("image/jpg", readUpdated.getImageType());
+    Assert.assertEquals("https://localhost/image.jpg", readUpdated.getImageUri());
+  }
+
+  @Test
+  public void deleteSimpleEntity() throws Exception {
+    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
+    DataStore<Building> datastore = datasource.getDataStore(Building.class);
+
+    Building building = new Building();
+    building.setName("Common Building");
+    datastore.create(building);
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "1");
+
+    Building read = (Building) datasource.readData(edmEntitySet, keys);
+    Assert.assertEquals("Common Building", read.getName());
+    Assert.assertEquals("1", read.getId());
+
+    //
+    datasource.deleteData(edmEntitySet, keys);
+
+    // validate
+    try {
+      Building readAfterDelete = (Building) datasource.readData(edmEntitySet, keys);
+      Assert.fail("Expected " + ODataNotFoundException.class + "was not thrown for '" + readAfterDelete + "'.");
+    } catch (ODataNotFoundException e) {
+    }
+  }
+
+  @Test(expected = ODataRuntimeException.class)
+  public void unknownEntitySetForEntity() throws Exception {
+    String entitySetName = "Unknown";
+    FullQualifiedName entityType = new FullQualifiedName(DEFAULT_CONTAINER, entitySetName);
+
+    EdmEntitySet edmEntitySet = Mockito.mock(EdmEntitySet.class);
+    Mockito.when(edmEntitySet.getName()).thenReturn(entitySetName);
+    EdmEntityType edmEntityType = Mockito.mock(EdmEntityType.class);
+    Mockito.when(edmEntitySet.getEntityType()).thenReturn(edmEntityType);
+    Mockito.when(edmEntityType.getName()).thenReturn(entityType.getName());
+
+    Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("Id", "1");
+    //
+    datasource.readData(edmEntitySet, keys);
+  }
+
+  @Test(expected = ODataRuntimeException.class)
+  public void unknownEntitySetForEntities() throws Exception {
+    String entitySetName = "Unknown";
+    FullQualifiedName entityType = new FullQualifiedName(DEFAULT_CONTAINER, entitySetName);
+
+    EdmEntitySet edmEntitySet = Mockito.mock(EdmEntitySet.class);
+    Mockito.when(edmEntitySet.getName()).thenReturn(entitySetName);
+    EdmEntityType edmEntityType = Mockito.mock(EdmEntityType.class);
+    Mockito.when(edmEntitySet.getEntityType()).thenReturn(edmEntityType);
+    Mockito.when(edmEntityType.getName()).thenReturn(entityType.getName());
+
+    //
+    datasource.readData(edmEntitySet);
+  }
+
+  @Test
+  public void writeRelations() throws Exception {
+    DataStore<Building> buildingStore = InMemoryDataStore.createInMemory(Building.class, true);
+    DataStore<Room> roomStore = InMemoryDataStore.createInMemory(Room.class, true);
+
+    EdmEntitySet buildingsEntitySet = createMockedEdmEntitySet("Buildings");
+    EdmEntitySet roomsEntitySet = createMockedEdmEntitySet("Rooms");
+
+    Building building = new Building();
+    building.setName("Common Building");
+    Building created = buildingStore.create(building);
+
+    Room room = new Room(42, "Room with Number");
+    room.setSeats(123);;
+    room.setVersion(4711);
+    roomStore.create(room);
+
+    Map<String, Object> targetEntityKeyValues = new HashMap<String, Object>();
+    targetEntityKeyValues.put("Id", 42);
+
+    // execute
+    datasource.writeRelation(buildingsEntitySet, building, roomsEntitySet, targetEntityKeyValues);
+
+    // validate
+    Building readBuilding = buildingStore.read(created);
+    Room readRoom = roomStore.read(new Room(42, ""));
+
+    List<Room> readRooms = readBuilding.getRooms();
+    Assert.assertEquals(1, readRooms.size());
+    Assert.assertEquals(readRoom, readRooms.get(0));
+
+    Assert.assertEquals("42", readRoom.getId());
+    Assert.assertEquals(123, readRoom.getSeats());
+    Assert.assertEquals(4711, readRoom.getVersion());
+    Assert.assertEquals(readBuilding, readRoom.getBuilding());
+  }
+
+  private EdmEntitySet createMockedEdmEntitySet(final String entitySetName) throws ODataException {
+    return createMockedEdmEntitySet(edmProvider, entitySetName);
+  }
+
+  private EdmEntitySet createMockedEdmEntitySet(AnnotationEdmProvider edmProvider, final String entitySetName)
+          throws ODataException {
+    EntitySet entitySet = edmProvider.getEntitySet(DEFAULT_CONTAINER, entitySetName);
+    FullQualifiedName entityType = entitySet.getEntityType();
+
+    EdmEntitySet edmEntitySet = Mockito.mock(EdmEntitySet.class);
+    Mockito.when(edmEntitySet.getName()).thenReturn(entitySetName);
+    EdmEntityType edmEntityType = Mockito.mock(EdmEntityType.class);
+    Mockito.when(edmEntitySet.getEntityType()).thenReturn(edmEntityType);
+    Mockito.when(edmEntityType.getName()).thenReturn(entityType.getName());
+
+    return edmEntitySet;
+  }
+}