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 2013/09/24 08:33:35 UTC

[2/2] git commit: Sample for Advanced Read Media Resource Tutorial

Sample for Advanced Read Media Resource Tutorial


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/08b99a4e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/tree/08b99a4e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/diff/08b99a4e

Branch: refs/heads/samples
Commit: 08b99a4e40d578e4b84ebb8bb9d79537b60291e1
Parents: 6fbfa98
Author: Michael Bolz <mi...@apache.org>
Authored: Mon Sep 23 16:14:54 2013 +0200
Committer: Michael Bolz <mi...@apache.org>
Committed: Mon Sep 23 16:14:54 2013 +0200

----------------------------------------------------------------------
 .../olingo/odata2/sample/service/DataStore.java | 105 +++++++++++++++++++
 .../odata2/sample/service/MyCallback.java       |  25 ++++-
 .../odata2/sample/service/MyEdmProvider.java    |  53 ++++++++++
 .../sample/service/MyODataSingleProcessor.java  |  65 +++++++++++-
 .../odata2/sample/service/MyServiceFactory.java |   3 +-
 .../src/main/resources/Driver_1.png             | Bin 0 -> 8429 bytes
 .../src/main/resources/Driver_2.png             | Bin 0 -> 12212 bytes
 .../src/main/resources/Driver_3.png             | Bin 0 -> 11655 bytes
 .../cars-web/src/main/webapp/index.html         |  17 ++-
 9 files changed, 262 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/DataStore.java
----------------------------------------------------------------------
diff --git a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/DataStore.java b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/DataStore.java
index d302099..b2805bd 100644
--- a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/DataStore.java
+++ b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/DataStore.java
@@ -1,11 +1,17 @@
 package org.apache.olingo.odata2.sample.service;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.TimeZone;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
 
 public class DataStore {
 
@@ -106,6 +112,51 @@ public class DataStore {
     return address;
   }
 
+  public Map<String, Object> getDriver(int id) {
+    Map<String, Object> data = null;
+    Calendar updated = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    
+    switch (id) {
+    case 1:
+      updated.set(2012, 12, 19);
+      data = createDriver(id, "Michael", "Shoemaker", "The One", null, updated);
+      break;
+      
+    case 2:
+      updated.set(2012, 12, 18);
+      data = createDriver(id, "Nico", "Horsehill", null, 2, updated);
+      break;
+
+    case 3:
+      updated.set(2011, 11, 11);
+      data = createDriver(id, "Kimi", "Heikkinen", "Iceman", 3, updated);
+      break;
+
+    default:
+      break;
+    }
+    
+    return data;
+  }
+
+  private Map<String, Object> createDriver(int id, String name, String surname, String nickname, Integer carId, Calendar updated) {
+    Map<String, Object> data = new HashMap<String, Object>();
+    data.put("Id", id);
+    data.put("Name", name);
+    data.put("Surname", surname);
+    data.put("Nickname", nickname);
+    data.put("CarId", carId);
+    data.put("Updated", updated);
+    return data;
+  }
+
+  public List<Map<String, Object>> getDrivers() {
+    List<Map<String, Object>> drivers = new ArrayList<Map<String, Object>>();
+    drivers.add(getDriver(1));
+    drivers.add(getDriver(2));
+    drivers.add(getDriver(3));
+    return drivers;
+  }
 
   public List<Map<String, Object>> getCars() {
     List<Map<String, Object>> cars = new ArrayList<Map<String, Object>>();
@@ -148,4 +199,58 @@ public class DataStore {
     }
     return null;
   }
+
+  public Map<String, Object> getDriverFor(int carId) {
+    List<Map<String, Object>> drivers = getDrivers();
+    
+    for (Map<String,Object> driver: drivers) {
+      if(Integer.valueOf(carId).equals(driver.get("CarId"))) {
+        return driver;
+      }
+    }
+    return null;
+  }
+
+  public Map<String, Object> getCarFor(int driverKey) {
+    Map<String, Object> driver = getDriver(driverKey);
+    if(driver != null) {
+      Object carId = driver.get("CarId");
+      if(carId != null) {
+        return getCar((Integer) carId);
+      }
+    }
+    return null;
+  }
+
+  public byte[] readDriverImage(EdmEntitySet entitySet, int id) {
+    try {
+      if(MyEdmProvider.ENTITY_SET_NAME_DRIVERS.equals(entitySet.getName())) {
+        int capacity = 1024 * 1000;
+        byte[] temp = new byte[capacity];
+        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("Driver_" + id + ".png");
+        if(is == null) {
+          return null;
+        }
+
+        ByteBuffer result = ByteBuffer.allocate(capacity);
+        int read = is.read(temp);
+        while (read >= 0) {
+          if(result.remaining() < read) {
+            ByteBuffer tmpResult = ByteBuffer.allocate(result.capacity() + capacity);
+            tmpResult.put(result);
+            result = tmpResult;
+          }
+          result.put(temp, 0, read);
+          read = is.read(temp);
+        }
+        
+        return Arrays.copyOf(result.array(), result.position());
+      }
+    } catch (EdmException e) {
+      e.printStackTrace();
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyCallback.java
----------------------------------------------------------------------
diff --git a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyCallback.java b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyCallback.java
index a132516..d768d73 100644
--- a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyCallback.java
+++ b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyCallback.java
@@ -1,7 +1,10 @@
 package org.apache.olingo.odata2.sample.service;
 
+import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_NAME_CAR;
+import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_NAME_DRIVER;
 import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_NAME_MANUFACTURER;
 import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_SET_NAME_CARS;
+import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_SET_NAME_DRIVERS;
 import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_SET_NAME_MANUFACTURERS;
 
 import java.net.URI;
@@ -43,7 +46,27 @@ public class MyCallback implements OnWriteEntryContent, OnWriteFeedContent {
     WriteEntryCallbackResult result = new WriteEntryCallbackResult();
     
     try {
-      if (isNavigationFromTo(context, ENTITY_SET_NAME_CARS, ENTITY_NAME_MANUFACTURER)) {
+      if(isNavigationFromTo(context, ENTITY_SET_NAME_CARS, ENTITY_NAME_DRIVER)) {
+        EntityProviderWriteProperties inlineProperties = EntityProviderWriteProperties.serviceRoot(serviceRoot)
+            .expandSelectTree(context.getCurrentExpandSelectTreeNode())
+            .build();
+
+        Map<String, Object> keys = context.extractKeyFromEntryData();
+        Integer carId = (Integer) keys.get("Id");
+        result.setEntryData(dataStore.getDriverFor(carId));
+        result.setInlineProperties(inlineProperties);
+        
+      } else if(isNavigationFromTo(context, ENTITY_SET_NAME_DRIVERS, ENTITY_NAME_CAR)) {
+        EntityProviderWriteProperties inlineProperties = EntityProviderWriteProperties.serviceRoot(serviceRoot)
+            .expandSelectTree(context.getCurrentExpandSelectTreeNode())
+            .build();
+
+        Map<String, Object> keys = context.extractKeyFromEntryData();
+        Integer driverId = (Integer) keys.get("Id");
+        result.setEntryData(dataStore.getCarFor(driverId));
+        result.setInlineProperties(inlineProperties);
+        
+      } else if (isNavigationFromTo(context, ENTITY_SET_NAME_CARS, ENTITY_NAME_MANUFACTURER)) {
         EntityProviderWriteProperties inlineProperties = EntityProviderWriteProperties.serviceRoot(serviceRoot)
             .expandSelectTree(context.getCurrentExpandSelectTreeNode())
             .build();

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyEdmProvider.java
----------------------------------------------------------------------
diff --git a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyEdmProvider.java b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyEdmProvider.java
index 0d53d25..2d2850b 100755
--- a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyEdmProvider.java
+++ b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyEdmProvider.java
@@ -23,6 +23,7 @@ import org.apache.olingo.odata2.api.edm.provider.EntityType;
 import org.apache.olingo.odata2.api.edm.provider.Facets;
 import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
 import org.apache.olingo.odata2.api.edm.provider.Key;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
 import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
 import org.apache.olingo.odata2.api.edm.provider.Property;
 import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
@@ -35,24 +36,31 @@ public class MyEdmProvider extends EdmProvider {
 
   static final String ENTITY_SET_NAME_MANUFACTURERS = "Manufacturers";
   static final String ENTITY_SET_NAME_CARS = "Cars";
+  static final String ENTITY_SET_NAME_DRIVERS = "Drivers";
   static final String ENTITY_NAME_MANUFACTURER = "Manufacturer";
   static final String ENTITY_NAME_CAR = "Car";
+  static final String ENTITY_NAME_DRIVER = "Driver";
 
   private static final String NAMESPACE = "org.apache.olingo.odata2.ODataCars";
 
   private static final FullQualifiedName ENTITY_TYPE_1_1 = new FullQualifiedName(NAMESPACE, ENTITY_NAME_CAR);
   private static final FullQualifiedName ENTITY_TYPE_1_2 = new FullQualifiedName(NAMESPACE, ENTITY_NAME_MANUFACTURER);
+  private static final FullQualifiedName ENTITY_TYPE_1_3 = new FullQualifiedName(NAMESPACE, ENTITY_NAME_DRIVER);
 
   private static final FullQualifiedName COMPLEX_TYPE = new FullQualifiedName(NAMESPACE, "Address");
 
   private static final FullQualifiedName ASSOCIATION_CAR_MANUFACTURER = new FullQualifiedName(NAMESPACE, "Car_Manufacturer_Manufacturer_Cars");
+  private static final FullQualifiedName ASSOCIATION_DRIVER_CAR = new FullQualifiedName(NAMESPACE, "Driver_Car-Car_Driver");
 
   private static final String ROLE_1_1 = "Car_Manufacturer";
   private static final String ROLE_1_2 = "Manufacturer_Cars";
+  private static final String ROLE_1_3 = "Car_Driver";
+  private static final String ROLE_3_1 = "Driver_Car";
 
   private static final String ENTITY_CONTAINER = "ODataCarsEntityContainer";
 
   private static final String ASSOCIATION_SET = "Cars_Manufacturers";
+  private static final String ASSOCIATION_SET_CARS_DRIVERS = "Cars_Drivers";
 
   private static final String FUNCTION_IMPORT = "NumberOfCars";
 
@@ -66,6 +74,7 @@ public class MyEdmProvider extends EdmProvider {
     List<EntityType> entityTypes = new ArrayList<EntityType>();
     entityTypes.add(getEntityType(ENTITY_TYPE_1_1));
     entityTypes.add(getEntityType(ENTITY_TYPE_1_2));
+    entityTypes.add(getEntityType(ENTITY_TYPE_1_3));
     schema.setEntityTypes(entityTypes);
 
     List<ComplexType> complexTypes = new ArrayList<ComplexType>();
@@ -74,6 +83,7 @@ public class MyEdmProvider extends EdmProvider {
 
     List<Association> associations = new ArrayList<Association>();
     associations.add(getAssociation(ASSOCIATION_CAR_MANUFACTURER));
+    associations.add(getAssociation(ASSOCIATION_DRIVER_CAR));
     schema.setAssociations(associations);
 
     List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
@@ -83,10 +93,12 @@ public class MyEdmProvider extends EdmProvider {
     List<EntitySet> entitySets = new ArrayList<EntitySet>();
     entitySets.add(getEntitySet(ENTITY_CONTAINER, ENTITY_SET_NAME_CARS));
     entitySets.add(getEntitySet(ENTITY_CONTAINER, ENTITY_SET_NAME_MANUFACTURERS));
+    entitySets.add(getEntitySet(ENTITY_CONTAINER, ENTITY_SET_NAME_DRIVERS));
     entityContainer.setEntitySets(entitySets);
 
     List<AssociationSet> associationSets = new ArrayList<AssociationSet>();
     associationSets.add(getAssociationSet(ENTITY_CONTAINER, ASSOCIATION_CAR_MANUFACTURER, ENTITY_SET_NAME_MANUFACTURERS, ROLE_1_2));
+    associationSets.add(getAssociationSet(ENTITY_CONTAINER, ASSOCIATION_DRIVER_CAR, ENTITY_SET_NAME_DRIVERS, ROLE_3_1));
     entityContainer.setAssociationSets(associationSets);
 
     List<FunctionImport> functionImports = new ArrayList<FunctionImport>();
@@ -125,6 +137,8 @@ public class MyEdmProvider extends EdmProvider {
         List<NavigationProperty> navigationProperties = new ArrayList<NavigationProperty>();
         navigationProperties.add(new NavigationProperty().setName("Manufacturer")
             .setRelationship(ASSOCIATION_CAR_MANUFACTURER).setFromRole(ROLE_1_1).setToRole(ROLE_1_2));
+        navigationProperties.add(new NavigationProperty().setName("Driver")
+            .setRelationship(ASSOCIATION_DRIVER_CAR).setFromRole(ROLE_1_3).setToRole(ROLE_3_1));
 
         //Key
         List<PropertyRef> keyProperties = new ArrayList<PropertyRef>();
@@ -163,6 +177,34 @@ public class MyEdmProvider extends EdmProvider {
             .setKey(key)
             .setNavigationProperties(navigationProperties);
 
+      } else if (ENTITY_TYPE_1_3.getName().equals(edmFQName.getName())) {
+        List<Property> properties = new ArrayList<Property>();
+        properties.add(new SimpleProperty().setName("Id").setType(EdmSimpleTypeKind.Int32).setFacets(new Facets().setNullable(false)));
+        properties.add(new SimpleProperty().setName("CarId").setType(EdmSimpleTypeKind.Int32));
+        properties.add(new SimpleProperty().setName("Name").setType(EdmSimpleTypeKind.String).setFacets(new Facets().setNullable(false).setMaxLength(50)));
+        properties.add(new SimpleProperty().setName("Surname").setType(EdmSimpleTypeKind.String).setFacets(new Facets().setNullable(false).setMaxLength(80))
+                        .setCustomizableFeedMappings(new CustomizableFeedMappings().setFcTargetPath(EdmTargetPath.SYNDICATION_TITLE)));
+        properties.add(new SimpleProperty().setName("Nickname").setType(EdmSimpleTypeKind.String).setFacets(new Facets().setNullable(true).setMaxLength(50)));
+        properties.add(new SimpleProperty().setName("Updated").setType(EdmSimpleTypeKind.DateTime)
+            .setFacets(new Facets().setNullable(false).setConcurrencyMode(EdmConcurrencyMode.Fixed))
+            .setCustomizableFeedMappings(new CustomizableFeedMappings().setFcTargetPath(EdmTargetPath.SYNDICATION_UPDATED)));
+
+        // Navigation properties
+        List<NavigationProperty> navigationProperties = new ArrayList<NavigationProperty>();
+        navigationProperties.add(new NavigationProperty().setName("Car").setRelationship(ASSOCIATION_DRIVER_CAR).setFromRole(ROLE_3_1).setToRole(ROLE_1_3));
+        
+        // Key
+        List<PropertyRef> keyProperties = new ArrayList<PropertyRef>();
+        keyProperties.add(new PropertyRef().setName("Id"));
+        Key key = new Key().setKeys(keyProperties);
+
+        // finish
+        return new EntityType().setName(ENTITY_TYPE_1_3.getName())
+            .setProperties(properties)
+            .setHasStream(true)
+            .setKey(key)
+            .setNavigationProperties(navigationProperties)
+            .setMapping(new Mapping().setMimeType("image/png"));
       }
     }
 
@@ -192,6 +234,10 @@ public class MyEdmProvider extends EdmProvider {
         return new Association().setName(ASSOCIATION_CAR_MANUFACTURER.getName())
             .setEnd1(new AssociationEnd().setType(ENTITY_TYPE_1_1).setRole(ROLE_1_1).setMultiplicity(EdmMultiplicity.MANY))
             .setEnd2(new AssociationEnd().setType(ENTITY_TYPE_1_2).setRole(ROLE_1_2).setMultiplicity(EdmMultiplicity.ONE));
+      } else if (ASSOCIATION_DRIVER_CAR.getName().equals(edmFQName.getName())) {
+        return new Association().setName(ASSOCIATION_DRIVER_CAR.getName())
+            .setEnd1(new AssociationEnd().setType(ENTITY_TYPE_1_1).setRole(ROLE_1_3).setMultiplicity(EdmMultiplicity.ONE))
+            .setEnd2(new AssociationEnd().setType(ENTITY_TYPE_1_3).setRole(ROLE_3_1).setMultiplicity(EdmMultiplicity.ONE));
       }
     }
     return null;
@@ -204,6 +250,8 @@ public class MyEdmProvider extends EdmProvider {
         return new EntitySet().setName(name).setEntityType(ENTITY_TYPE_1_1);
       } else if (ENTITY_SET_NAME_MANUFACTURERS.equals(name)) {
         return new EntitySet().setName(name).setEntityType(ENTITY_TYPE_1_2);
+      } else if(ENTITY_SET_NAME_DRIVERS.equals(name)) {
+        return new EntitySet().setName(name).setEntityType(ENTITY_TYPE_1_3);
       }
     }
     return null;
@@ -217,6 +265,11 @@ public class MyEdmProvider extends EdmProvider {
             .setAssociation(ASSOCIATION_CAR_MANUFACTURER)
             .setEnd1(new AssociationSetEnd().setRole(ROLE_1_2).setEntitySet(ENTITY_SET_NAME_MANUFACTURERS))
             .setEnd2(new AssociationSetEnd().setRole(ROLE_1_1).setEntitySet(ENTITY_SET_NAME_CARS));
+      } else if (ASSOCIATION_DRIVER_CAR.equals(association)) {
+        return new AssociationSet().setName(ASSOCIATION_SET_CARS_DRIVERS)
+            .setAssociation(ASSOCIATION_DRIVER_CAR)
+            .setEnd1(new AssociationSetEnd().setRole(ROLE_3_1).setEntitySet(ENTITY_SET_NAME_DRIVERS))
+            .setEnd2(new AssociationSetEnd().setRole(ROLE_1_3).setEntitySet(ENTITY_SET_NAME_CARS));
       }
     }
     return null;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyODataSingleProcessor.java
----------------------------------------------------------------------
diff --git a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyODataSingleProcessor.java b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyODataSingleProcessor.java
index 4c630db..6f487ca 100755
--- a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyODataSingleProcessor.java
+++ b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyODataSingleProcessor.java
@@ -1,7 +1,10 @@
 package org.apache.olingo.odata2.sample.service;
 
+import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_NAME_CAR;
+import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_NAME_DRIVER;
 import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_NAME_MANUFACTURER;
 import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_SET_NAME_CARS;
+import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_SET_NAME_DRIVERS;
 import static org.apache.olingo.odata2.sample.service.MyEdmProvider.ENTITY_SET_NAME_MANUFACTURERS;
 
 import java.net.URI;
@@ -9,9 +12,9 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import org.apache.olingo.odata2.api.ODataCallback;
 import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
 import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
 import org.apache.olingo.odata2.api.edm.EdmProperty;
 import org.apache.olingo.odata2.api.edm.EdmSimpleType;
@@ -28,6 +31,8 @@ import org.apache.olingo.odata2.api.uri.KeyPredicate;
 import org.apache.olingo.odata2.api.uri.UriParser;
 import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
 import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetMediaResourceUriInfo;
+
 
 public class MyODataSingleProcessor extends ODataSingleProcessor {
   
@@ -49,6 +54,8 @@ public class MyODataSingleProcessor extends ODataSingleProcessor {
         return EntityProvider.writeFeed(contentType, entitySet, dataStore.getCars(), EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).build());
       } else if (ENTITY_SET_NAME_MANUFACTURERS.equals(entitySet.getName())) {
         return EntityProvider.writeFeed(contentType, entitySet, dataStore.getManufacturers(), EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).build());
+      } else if (ENTITY_SET_NAME_DRIVERS.equals(entitySet.getName())) {
+        return EntityProvider.writeFeed(contentType, entitySet, dataStore.getDrivers(), EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).build());
       }
 
       throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
@@ -89,6 +96,7 @@ public class MyODataSingleProcessor extends ODataSingleProcessor {
           // create and register callback
           Map<String, ODataCallback> callbacks = new HashMap<String, ODataCallback>();
           callbacks.put(ENTITY_NAME_MANUFACTURER, new MyCallback(dataStore, serviceRoot));
+          callbacks.put(ENTITY_NAME_DRIVER, new MyCallback(dataStore, serviceRoot));
           ExpandSelectTreeNode expandSelectTreeNode = UriParser.createExpandSelectTree(uriInfo.getSelect(), uriInfo.getExpand());
           //
           propertiesBuilder.expandSelectTree(expandSelectTreeNode).callbacks(callbacks);
@@ -112,6 +120,23 @@ public class MyODataSingleProcessor extends ODataSingleProcessor {
 
           return EntityProvider.writeEntry(contentType, entitySet, data, propertiesBuilder.build());
         }
+      } else if (ENTITY_SET_NAME_DRIVERS.equals(entitySet.getName())) {
+        int id = getKeyValue(uriInfo.getKeyPredicates().get(0));
+        Map<String, Object> data = dataStore.getDriver(id);
+
+        if (data != null) {
+          URI serviceRoot = getContext().getPathInfo().getServiceRoot();
+          ODataEntityProviderPropertiesBuilder propertiesBuilder = EntityProviderWriteProperties.serviceRoot(serviceRoot);
+
+          // create and register callback
+          Map<String, ODataCallback> callbacks = new HashMap<String, ODataCallback>();
+          callbacks.put(ENTITY_NAME_CAR, new MyCallback(dataStore, serviceRoot));
+          ExpandSelectTreeNode expandSelectTreeNode = UriParser.createExpandSelectTree(uriInfo.getSelect(), uriInfo.getExpand());
+          //
+          propertiesBuilder.expandSelectTree(expandSelectTreeNode).callbacks(callbacks);
+
+          return EntityProvider.writeEntry(contentType, entitySet, data, propertiesBuilder.build());
+        }
       }
 
       throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
@@ -125,6 +150,12 @@ public class MyODataSingleProcessor extends ODataSingleProcessor {
       if (ENTITY_SET_NAME_MANUFACTURERS.equals(entitySet.getName())) {
         int carKey = getKeyValue(uriInfo.getKeyPredicates().get(0));
         data = dataStore.getManufacturerFor(carKey);
+      } else if(isAssociation(uriInfo, ENTITY_SET_NAME_CARS, ENTITY_SET_NAME_DRIVERS)) {
+        int carKey = getKeyValue(uriInfo.getKeyPredicates().get(0));
+        data = dataStore.getDriverFor(carKey);
+      } else if(isAssociation(uriInfo, ENTITY_SET_NAME_DRIVERS, ENTITY_SET_NAME_CARS)) {
+        int driverKey = getKeyValue(uriInfo.getKeyPredicates().get(0));
+        data = dataStore.getCarFor(driverKey);
       }
       
       if(data != null) {
@@ -138,9 +169,39 @@ public class MyODataSingleProcessor extends ODataSingleProcessor {
     throw new ODataNotImplementedException();
   }
   
+  private boolean isAssociation(GetEntityUriInfo uriInfo, String startName, String targetName) throws EdmException {
+    if(startName == null || targetName == null) {
+      return false;
+    }
+    EdmEntitySet startEntitySet = uriInfo.getStartEntitySet();
+    EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
+    
+    return startName.equals(startEntitySet.getName()) && targetName.equals(targetEntitySet.getName());
+    
+  }
+  
+  @Override
+  public ODataResponse readEntityMedia(final GetMediaResourceUriInfo uriInfo, final String contentType) throws ODataException {
+
+    final EdmEntitySet entitySet = uriInfo.getTargetEntitySet();
+    if(ENTITY_SET_NAME_DRIVERS.equals(entitySet.getName())) {
+      int id = getKeyValue(uriInfo.getKeyPredicates().get(0));
+      byte[] image = dataStore.readDriverImage(entitySet, id);
+      if (image == null) {
+        throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+      }
+      
+      String mimeType = "image/png";
+      return ODataResponse.fromResponse(EntityProvider.writeBinary(mimeType, image)).build();
+    }
+    
+    throw new ODataNotImplementedException();
+  }
+
+
   private int getKeyValue(KeyPredicate key) throws ODataException {
     EdmProperty property = key.getProperty();
     EdmSimpleType type = (EdmSimpleType) property.getType();
     return type.valueOfString(key.getLiteral(), EdmLiteralKind.DEFAULT, property.getFacets(), Integer.class);
   }
-}
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyServiceFactory.java b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyServiceFactory.java
index c15cb18..d7d3c71 100755
--- a/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyServiceFactory.java
+++ b/odata-sample/cars-service/src/main/java/org/apache/olingo/odata2/sample/service/MyServiceFactory.java
@@ -7,6 +7,7 @@ import org.apache.olingo.odata2.api.exception.ODataException;
 import org.apache.olingo.odata2.api.processor.ODataContext;
 import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
 
+
 public class MyServiceFactory extends ODataServiceFactory {
 
   @Override
@@ -18,4 +19,4 @@ public class MyServiceFactory extends ODataServiceFactory {
 
     return createODataSingleProcessorService(edmProvider, singleProcessor);
   }
-}
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-service/src/main/resources/Driver_1.png
----------------------------------------------------------------------
diff --git a/odata-sample/cars-service/src/main/resources/Driver_1.png b/odata-sample/cars-service/src/main/resources/Driver_1.png
new file mode 100644
index 0000000..f817682
Binary files /dev/null and b/odata-sample/cars-service/src/main/resources/Driver_1.png differ

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-service/src/main/resources/Driver_2.png
----------------------------------------------------------------------
diff --git a/odata-sample/cars-service/src/main/resources/Driver_2.png b/odata-sample/cars-service/src/main/resources/Driver_2.png
new file mode 100644
index 0000000..144ed93
Binary files /dev/null and b/odata-sample/cars-service/src/main/resources/Driver_2.png differ

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-service/src/main/resources/Driver_3.png
----------------------------------------------------------------------
diff --git a/odata-sample/cars-service/src/main/resources/Driver_3.png b/odata-sample/cars-service/src/main/resources/Driver_3.png
new file mode 100644
index 0000000..adc7d7d
Binary files /dev/null and b/odata-sample/cars-service/src/main/resources/Driver_3.png differ

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/08b99a4e/odata-sample/cars-web/src/main/webapp/index.html
----------------------------------------------------------------------
diff --git a/odata-sample/cars-web/src/main/webapp/index.html b/odata-sample/cars-web/src/main/webapp/index.html
index 96dc0ea..4113782 100644
--- a/odata-sample/cars-web/src/main/webapp/index.html
+++ b/odata-sample/cars-web/src/main/webapp/index.html
@@ -18,20 +18,33 @@
           <ul>
             <li><a href="MyODataSample.svc/Cars">/Cars</a></li>        
             <li><a href="MyODataSample.svc/Manufacturers">/Manufacturers</a></li>        
+            <li><a href="MyODataSample.svc/Drivers">/Drivers</a></li>        
           </ul>
         </li>
         <li>Sample Entities
           <ul>
             <li><a href="MyODataSample.svc/Cars(1)">/Cars(1)</a></li>        
             <li><a href="MyODataSample.svc/Cars(3)">/Cars(3)</a></li>        
-            <li><a href="MyODataSample.svc/Cars(3)/Manufacturer">/Cars(3)/Manufacturer</a></li>        
             <li><a href="MyODataSample.svc/Manufacturers(1)">/Manufacturers(1)</a></li>        
+            <li><a href="MyODataSample.svc/Drivers(1)">/Drivers(1)</a></li>        
+            <li><a href="MyODataSample.svc/Drivers(3)">/Drivers(3)</a></li>        
           </ul>
         </li>
         <li>Sample Entities with <i>$expand</i>
           <ul>
-            <li><a href="MyODataSample.svc/Cars(3)/?$expand=Manufacturer">/Cars(3)/?$expand=Manufacturer</a></li>        
+            <li><a href="MyODataSample.svc/Cars(2)/?$expand=Driver">/Cars(2)/?$expand=Driver</a></li>        
+            <li><a href="MyODataSample.svc/Cars(3)/?$expand=Driver,Manufacturer">/Cars(3)/?$expand=Driver,Manufacturer</a></li>        
             <li><a href="MyODataSample.svc/Manufacturers(1)/?$expand=Cars">/Manufacturers(1)/?$expand=Cars</a></li>        
+            <li><a href="MyODataSample.svc/Drivers(1)/?$expand=Car">/Drivers(1)/?$expand=Car</a></li>        
+            <li><a href="MyODataSample.svc/Drivers(3)/?$expand=Car">/Drivers(3)/?$expand=Car</a></li>        
+          </ul>
+        </li>
+
+        <li>Sample Entities with <i>Media Resource ($value)</i>
+          <ul>
+            <li><a href="MyODataSample.svc/Drivers(1)/$value">/Drivers(1)/$value</a></li>        
+            <li><a href="MyODataSample.svc/Drivers(2)/$value">/Drivers(2)/$value</a></li>        
+            <li><a href="MyODataSample.svc/Cars(3)/Driver/$value">/Cars(3)/Driver/$value</a></li>        
           </ul>
         </li>
       </ul>