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/12/05 13:31:27 UTC

[34/52] git commit: Added support for write relations

Added support for write relations


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

Branch: refs/heads/master
Commit: e39b0b9586aa1c64034fc23d245bbce55d84a63b
Parents: 49786b4
Author: Michael Bolz <mi...@apache.org>
Authored: Tue Dec 3 05:28:05 2013 +0100
Committer: Michael Bolz <mi...@apache.org>
Committed: Tue Dec 3 08:14:21 2013 +0100

----------------------------------------------------------------------
 .../annotation/data/AnnotationInMemoryDs.java   | 85 +++++++++++++++++---
 .../core/annotation/edm/AnnotationHelper.java   | 31 ++++++-
 .../data/AnnotationsInMemoryDsTest.java         |  8 --
 3 files changed, 101 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/e39b0b95/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
index d7c7f59..938a0d2 100644
--- a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
+++ b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/data/AnnotationInMemoryDs.java
@@ -33,6 +33,7 @@ import org.apache.olingo.odata2.api.exception.ODataApplicationException;
 import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
 import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
 import org.apache.olingo.odata2.core.annotation.edm.AnnotationHelper;
+import org.apache.olingo.odata2.core.annotation.edm.AnnotationHelper.AnnotatedNavInfo;
 import org.apache.olingo.odata2.core.annotation.edm.ClassHelper;
 import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
 
@@ -111,7 +112,9 @@ public class AnnotationInMemoryDs implements ListsDataSource {
     DataStore<?> sourceStore = dataStores.get(sourceEntitySet.getName());
     DataStore<?> targetStore = dataStores.get(targetEntitySet.getName());
 
-    Field sourceField = extractSourceField(sourceStore, targetStore);
+    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 + "').");
@@ -131,8 +134,7 @@ public class AnnotationInMemoryDs implements ListsDataSource {
       }
     }
 
-    EdmNavigationProperty navProperty = sourceField.getAnnotation(EdmNavigationProperty.class);
-    if (navProperty.toMultiplicity() == EdmMultiplicity.MANY) {
+    if (navInfo.getToMultiplicity() == EdmMultiplicity.MANY) {
       if (targetKeys.isEmpty()) {
         return resultData;
       } else {
@@ -223,10 +225,63 @@ public class AnnotationInMemoryDs implements ListsDataSource {
   }
 
   @Override
-  public void writeRelation(EdmEntitySet sourceEntitySet, Object sourceData, EdmEntitySet targetEntitySet,
-      Map<String, Object> targetKeys)
+  public void writeRelation(EdmEntitySet sourceEntitySet, Object sourceEntity, EdmEntitySet targetEntitySet,
+      Map<String, Object> targetEntityValues)
       throws ODataNotImplementedException, ODataNotFoundException, EdmException, ODataApplicationException {
-    throw new ODataNotImplementedException(ODataNotImplementedException.COMMON);
+    // 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(Object instance, Field field, 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);
+    }
   }
 
   /**
@@ -264,10 +319,18 @@ public class AnnotationInMemoryDs implements ListsDataSource {
     }
   }
 
-  private Field extractSourceField(DataStore<?> sourceStore, DataStore<?> targetStore) {
-    Class<?> sourceDataTypeClass = sourceStore.getDataTypeClass();
-    Class<?> targetDataTypeClass = targetStore.getDataTypeClass();
-
-    return ANNOTATION_HELPER.getCommonNavigationInfo(sourceDataTypeClass, targetDataTypeClass).getFromField();
+  private void setValue(Object instance, Field field, 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/e39b0b95/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/edm/AnnotationHelper.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/edm/AnnotationHelper.java b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/edm/AnnotationHelper.java
index 462a0bc..08699fa 100644
--- a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/edm/AnnotationHelper.java
+++ b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/edm/AnnotationHelper.java
@@ -275,12 +275,18 @@ public class AnnotationHelper {
     return multiplicity;
   }
 
+
+  /**
+   * Set key fields based on values in map.
+   * If an key field is not available or <code>NULL</code> in the map 
+   * it will be not set as <code>NULL</code> at the instance object.
+   * 
+   * @param instance
+   * @param keys
+   * @return
+   */
   public <T> T setKeyFields(T instance, Map<String, Object> keys) {
     List<Field> fields = getAnnotatedFields(instance, EdmKey.class);
-    if (fields.size() != keys.size()) {
-      throw new IllegalStateException("Wrong amount of key properties. Expected read keys = "
-          + fields + " given key predicates = " + keys);
-    }
 
     for (Field field : fields) {
       String propertyName = getPropertyName(field);
@@ -327,12 +333,17 @@ public class AnnotationHelper {
     public EdmMultiplicity getToMultiplicity() {
       return getMultiplicity(fromNavigation, fromField);
     }
+    
+    public boolean isBiDirectional() {
+      return toNavigation != null;
+    }
   }
 
   public AnnotatedNavInfo getCommonNavigationInfo(Class<?> sourceClass, Class<?> targetClass) {
     List<Field> sourceFields = getAnnotatedFields(sourceClass, EdmNavigationProperty.class);
     List<Field> targetFields = getAnnotatedFields(targetClass, EdmNavigationProperty.class);
 
+    // first try via association name to get full navigation information
     for (Field sourceField : sourceFields) {
       final EdmNavigationProperty sourceNav = sourceField.getAnnotation(EdmNavigationProperty.class);
       final String sourceAssociation = extractRelationshipName(sourceNav, sourceField);
@@ -344,6 +355,18 @@ public class AnnotationHelper {
         }
       }
     }
+    
+    // if nothing was found assume none bi-directinal navigation
+    String targetEntityTypeName = extractEntityTypeName(targetClass);
+    for (Field sourceField : sourceFields) {
+      final EdmNavigationProperty sourceNav = sourceField.getAnnotation(EdmNavigationProperty.class);
+      final String navTargetEntityName = extractEntitTypeName(sourceNav, sourceField);
+      
+      if (navTargetEntityName.equals(targetEntityTypeName)) {
+        return new AnnotatedNavInfo(sourceField, null, sourceNav, null);
+      }
+    }
+    
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/e39b0b95/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java b/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java
index 3063004..02881f0 100644
--- a/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java
+++ b/odata2-edm-annotation/edm-annotation-core/src/test/java/org/apache/olingo/odata2/core/annotation/data/AnnotationsInMemoryDsTest.java
@@ -39,20 +39,12 @@ public class AnnotationsInMemoryDsTest {
   private final AnnotationInMemoryDs datasource;
   private AnnotationEdmProvider edmProvider;
   private static final String DEFAULT_CONTAINER = ModelSharedConstants.CONTAINER_1;
-  private static final String DEFAULT_NAMESPACE = ModelSharedConstants.NAMESPACE_1;
 
   public AnnotationsInMemoryDsTest() {
     datasource = new AnnotationInMemoryDs(Building.class.getPackage().getName());
     edmProvider = new AnnotationEdmProvider(Building.class.getPackage().getName());
   }
 
-  //  @Test(expected = ODataApplicationException.class)
-  //  public void invalidEntity() throws Exception {
-  //    EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");
-  //
-  //    datasource.createData(edmEntitySet, this);
-  //  }
-
   @Test
   public void createSimpleEntity() throws Exception {
     EdmEntitySet edmEntitySet = createMockedEdmEntitySet("Buildings");