You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2014/01/17 19:59:43 UTC

git commit: [OLINGO-51] - Full support for Inserting an Entity and creating a link using the tags part of OData entry. [OLINGO-49] - Handle Links [OLINGO-45] - Ignore inline entries in case of HTTP PUT. However only update the links.

Updated Branches:
  refs/heads/master 8ed6306f6 -> 1fc260e61


[OLINGO-51] - Full support for Inserting an Entity and creating a link
using the <link> tags part of OData entry.
[OLINGO-49] - Handle Links
[OLINGO-45] - Ignore inline entries in case of HTTP PUT. However only
update the links.



Signed-off-by: Chandan V A <ch...@sap.com>

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

Branch: refs/heads/master
Commit: 1fc260e61aee0dba8d95d1e9a50957bf01218138
Parents: 8ed6306
Author: Chandan V A <ch...@sap.com>
Authored: Sat Jan 18 00:29:13 2014 +0530
Committer: Chandan V A <ch...@sap.com>
Committed: Sat Jan 18 00:29:13 2014 +0530

----------------------------------------------------------------------
 .../processor/core/access/data/JPAEntity.java   | 163 +++++++++------
 .../core/access/data/JPAEntityParser.java       |   5 +-
 .../jpa/processor/core/access/data/JPALink.java |  64 +++---
 .../core/access/data/JPAProcessorImpl.java      |   3 -
 .../core/access/data/JPAEntityTest.java         |   3 +-
 .../processor/core/mock/data/EdmMockUtilV2.java |   3 +-
 .../core/mock/data/ODataEntryMockUtil.java      |  34 ++-
 .../processor/ref/model/SalesOrderHeader.java   |  16 +-
 .../jpa/processor/ref/model/SalesOrderItem.java | 208 +++++++++----------
 9 files changed, 271 insertions(+), 228 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
index f6cf6c1..d7d4446 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntity.java
@@ -21,7 +21,6 @@ package org.apache.olingo.odata2.jpa.processor.core.access.data;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -36,15 +35,18 @@ import org.apache.olingo.odata2.api.edm.EdmProperty;
 import org.apache.olingo.odata2.api.edm.EdmStructuralType;
 import org.apache.olingo.odata2.api.edm.EdmTypeKind;
 import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.ep.entry.EntryMetadata;
 import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
 import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
 import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
 import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
 import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
 
 public class JPAEntity {
 
   private Object jpaEntity = null;
+  private JPAEntity parentJPAEntity = null;
   private EdmEntityType oDataEntityType = null;
   private EdmEntitySet oDataEntitySet = null;
   private Class<?> jpaType = null;
@@ -52,8 +54,9 @@ public class JPAEntity {
   private JPAEntityParser jpaEntityParser = null;
   private ODataJPAContext oDataJPAContext;
   public HashMap<EdmNavigationProperty, EdmEntitySet> inlinedEntities = null;
+  public HashMap<String, List<Object>> relatedJPAEntityMap = null;
 
-  public JPAEntity(final EdmEntityType oDataEntityType, final EdmEntitySet oDataEntitySet, 
+  public JPAEntity(final EdmEntityType oDataEntityType, final EdmEntitySet oDataEntitySet,
       final ODataJPAContext context) {
     this.oDataEntityType = oDataEntityType;
     this.oDataEntitySet = oDataEntitySet;
@@ -71,12 +74,21 @@ public class JPAEntity {
     this.accessModifiersWrite = accessModifiersWrite;
   }
 
+  public void setParentJPAEntity(JPAEntity jpaEntity) {
+    this.parentJPAEntity = jpaEntity;
+  }
+
+  public JPAEntity getParentJPAEntity() {
+    return this.parentJPAEntity;
+  }
+
   public Object getJPAEntity() {
     return jpaEntity;
   }
 
   @SuppressWarnings("unchecked")
-  private void write(final Map<String, Object> oDataEntryProperties, final boolean isCreate)
+  private void write(final Map<String, Object> oDataEntryProperties,
+      final boolean isCreate)
       throws ODataJPARuntimeException {
     try {
 
@@ -104,20 +116,13 @@ public class JPAEntity {
           jpaEntityParser.getJPAEmbeddableKeyMap(jpaEntity.getClass().getName());
       Set<String> propertyNames = null;
       if (embeddableKeys != null) {
-        List<String> processedKeys =
-            setEmbeddableKeyProperty(embeddableKeys, oDataEntityType.getKeyProperties(), oDataEntryProperties,
-                jpaEntity);
+        setEmbeddableKeyProperty(embeddableKeys, oDataEntityType.getKeyProperties(), oDataEntryProperties,
+            jpaEntity);
 
         propertyNames = new HashSet<String>();
         propertyNames.addAll(oDataEntryProperties.keySet());
-        if (processedKeys.isEmpty()) {
-          for (String key : embeddableKeys.keySet()) {
-            propertyNames.remove(key);
-          }
-        } else {
-          for (String propertyName : processedKeys) {
-            propertyNames.remove(propertyName);
-          }
+        for (String key : embeddableKeys.keySet()) {
+          propertyNames.remove(key);
         }
       } else {
         propertyNames = oDataEntryProperties.keySet();
@@ -147,37 +152,29 @@ public class JPAEntity {
           break;
         case NAVIGATION:
         case ENTITY:
-          structuralType = (EdmStructuralType) edmTyped.getType();
-          EdmNavigationProperty navProperty = (EdmNavigationProperty) edmTyped;
-          accessModifier =
-              jpaEntityParser.getAccessModifier(jpaEntity, navProperty,
-                  JPAEntityParser.ACCESS_MODIFIER_SET);
-          EdmEntitySet edmRelatedEntitySet = oDataEntitySet.getRelatedEntitySet(navProperty);
-          List<ODataEntry> relatedEntries = (List<ODataEntry>) oDataEntryProperties.get(propertyName);
-          Collection<Object> relatedJPAEntites = instantiateRelatedJPAEntities(jpaEntity, navProperty);
-          JPAEntity relatedEntity = new JPAEntity((EdmEntityType) structuralType, edmRelatedEntitySet, oDataJPAContext);
-          for (ODataEntry oDataEntry : relatedEntries) {
-            relatedEntity.create(oDataEntry);
-            relatedJPAEntites.add(relatedEntity.getJPAEntity());
-            JPALink link = new JPALink(oDataJPAContext);
-            link.create(edmRelatedEntitySet, oDataEntry);
-          }
-
-          switch (navProperty.getMultiplicity()) {
-          case MANY:
-            accessModifier.invoke(jpaEntity, relatedJPAEntites);
-            break;
-          case ONE:
-          case ZERO_TO_ONE:
-            accessModifier.invoke(jpaEntity, relatedJPAEntites.iterator().next());
-            break;
-          }
+          if (isCreate) {
+            structuralType = (EdmStructuralType) edmTyped.getType();
+            EdmNavigationProperty navProperty = (EdmNavigationProperty) edmTyped;
+            EdmEntitySet edmRelatedEntitySet = oDataEntitySet.getRelatedEntitySet(navProperty);
+            List<ODataEntry> relatedEntries = (List<ODataEntry>) oDataEntryProperties.get(propertyName);
+            if (inlinedEntities == null) {
+              inlinedEntities = new HashMap<EdmNavigationProperty, EdmEntitySet>();
+            }
 
-          if (inlinedEntities == null) {
-            inlinedEntities = new HashMap<EdmNavigationProperty, EdmEntitySet>();
+            if (relatedJPAEntityMap == null) {
+              relatedJPAEntityMap = new HashMap<String, List<Object>>();
+            }
+            List<Object> relatedJPAEntities = new ArrayList<Object>();
+            JPAEntity relatedEntity =
+                new JPAEntity((EdmEntityType) structuralType, edmRelatedEntitySet, oDataJPAContext);
+            for (ODataEntry oDataEntry : relatedEntries) {
+              relatedEntity.setParentJPAEntity(this);
+              relatedEntity.create(oDataEntry);
+              relatedJPAEntities.add(relatedEntity.getJPAEntity());
+            }
+            relatedJPAEntityMap.put(navProperty.getName(), relatedJPAEntities);
+            inlinedEntities.put((EdmNavigationProperty) edmTyped, edmRelatedEntitySet);
           }
-
-          inlinedEntities.put((EdmNavigationProperty) edmTyped, edmRelatedEntitySet);
         default:
           continue;
         }
@@ -189,21 +186,6 @@ public class JPAEntity {
     }
   }
 
-  @SuppressWarnings("unchecked")
-  private Collection<Object> instantiateRelatedJPAEntities(final Object jpaEntity,
-      final EdmNavigationProperty navProperty)
-      throws InstantiationException,
-      IllegalAccessException, EdmException, ODataJPARuntimeException, IllegalArgumentException,
-      InvocationTargetException {
-    Method accessModifier =
-        jpaEntityParser.getAccessModifier(jpaEntity, navProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
-    Collection<Object> relatedJPAEntities = (Collection<Object>) accessModifier.invoke(jpaEntity);
-    if (relatedJPAEntities == null) {
-      relatedJPAEntities = new ArrayList<Object>();
-    }
-    return relatedJPAEntities;
-  }
-
   public void create(final ODataEntry oDataEntry) throws ODataJPARuntimeException {
     if (oDataEntry == null) {
       throw ODataJPARuntimeException
@@ -214,6 +196,50 @@ public class JPAEntity {
       normalizeInlineEntries(oDataEntryProperties);
     }
     write(oDataEntryProperties, true);
+
+    EntryMetadata entryMetadata = oDataEntry.getMetadata();
+    List<String> leftNavPrpNames = new ArrayList<String>();
+    try {
+      for (String navigationPropertyName : oDataEntityType.getNavigationPropertyNames()) {
+        List<String> links = entryMetadata.getAssociationUris(navigationPropertyName);
+        if (links.isEmpty()) {
+          continue;
+        } else {
+          EdmNavigationProperty navProperty =
+              (EdmNavigationProperty) oDataEntityType.getProperty(navigationPropertyName);
+          if (relatedJPAEntityMap != null && relatedJPAEntityMap.containsKey(navigationPropertyName)) {
+            JPALink.linkJPAEntities(relatedJPAEntityMap.get(navigationPropertyName), this.jpaEntity,
+                navProperty);
+          } else if (parentJPAEntity != null
+              &&
+              parentJPAEntity.getEdmEntitySet().getName().equals(
+                  oDataEntitySet.getRelatedEntitySet(navProperty).getName())) {
+            List<Object> targetJPAEntities = new ArrayList<Object>();
+            targetJPAEntities.add(parentJPAEntity.getJPAEntity());
+            JPALink.linkJPAEntities(targetJPAEntities, this.jpaEntity, navProperty);
+          } else {
+            leftNavPrpNames.add(navigationPropertyName);
+          }
+        }
+      }
+      if (!leftNavPrpNames.isEmpty()) {
+        JPALink link = new JPALink(oDataJPAContext);
+        link.setSourceJPAEntity(this.jpaEntity);
+        link.create(oDataEntitySet, oDataEntry, leftNavPrpNames);
+      }
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (ODataJPAModelException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+  }
+
+  public EdmEntitySet getEdmEntitySet() {
+    return oDataEntitySet;
   }
 
   public void create(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException {
@@ -231,6 +257,19 @@ public class JPAEntity {
       normalizeInlineEntries(oDataEntryProperties);
     }
     write(oDataEntryProperties, false);
+    JPALink link = new JPALink(oDataJPAContext);
+    link.setSourceJPAEntity(this.jpaEntity);
+    try {
+      link.create(oDataEntitySet, oDataEntry, oDataEntityType.getNavigationPropertyNames());
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (ODataJPAModelException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
   }
 
   public void update(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException {
@@ -294,7 +333,7 @@ public class JPAEntity {
     }
   }
 
-  protected List<String> setEmbeddableKeyProperty(final HashMap<String, String> embeddableKeys,
+  protected void setEmbeddableKeyProperty(final HashMap<String, String> embeddableKeys,
       final List<EdmProperty> oDataEntryKeyProperties,
       final Map<String, Object> oDataEntryProperties, final Object entity)
       throws ODataJPARuntimeException, EdmException, IllegalAccessException, IllegalArgumentException,
@@ -303,7 +342,6 @@ public class JPAEntity {
     HashMap<String, Object> embeddableObjMap = new HashMap<String, Object>();
     List<EdmProperty> leftODataEntryKeyProperties = new ArrayList<EdmProperty>();
     HashMap<String, String> leftEmbeddableKeys = new HashMap<String, String>();
-    List<String> processedKeys = new ArrayList<String>();
 
     for (EdmProperty edmProperty : oDataEntryKeyProperties) {
       if (oDataEntryProperties.containsKey(edmProperty.getName()) == false) {
@@ -339,13 +377,8 @@ public class JPAEntity {
         leftODataEntryKeyProperties.add(edmProperty);
         leftEmbeddableKeys
             .put(edmPropertyName, embeddableKeyNameComposite.split(embeddableKeyNameSplit[0] + ".", 2)[1]);
-        processedKeys.addAll(setEmbeddableKeyProperty(leftEmbeddableKeys, leftODataEntryKeyProperties,
-            oDataEntryProperties, embeddableObj));
       }
-      processedKeys.add(edmPropertyName);
-
     }
-    return processedKeys;
   }
 
   protected Object instantiateJPAEntity() throws InstantiationException, IllegalAccessException {

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
index 45e517d..dd030ce 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityParser.java
@@ -192,6 +192,9 @@ public final class JPAEntityParser {
           Object propertyValue = jpaEntity;
           Method method = null;
           for (String namePart : nameParts) {
+            if (propertyValue == null) {
+              break;
+            }
             method = propertyValue.getClass().getMethod(
                 namePart, (Class<?>[]) null);
             method.setAccessible(true);
@@ -314,7 +317,7 @@ public final class JPAEntityParser {
         } catch (SecurityException e1) {
           throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e1);
         }
-        if (acceserMethod != null){
+        if (acceserMethod != null) {
           accessModifierMap.put(
               propertyName,
               acceserMethod);

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPALink.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPALink.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPALink.java
index 18b5664..91ac44e 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPALink.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPALink.java
@@ -192,20 +192,25 @@ public class JPALink {
 
   }
 
-  public void create(final EdmEntitySet entitySet, final ODataEntry oDataEntry) throws ODataJPARuntimeException,
+  public void create(final EdmEntitySet entitySet, final ODataEntry oDataEntry,
+      List<String> navigationPropertyNames)
+      throws ODataJPARuntimeException,
       ODataJPAModelException {
-    List<String> navPropertyNames;
+
     try {
-      navPropertyNames = entitySet.getEntityType().getNavigationPropertyNames();
-      for (String navPropertyName : navPropertyNames) {
+      for (String navPropertyName : navigationPropertyNames) {
         List<String> links = oDataEntry.getMetadata().getAssociationUris(navPropertyName);
         if (links != null && links.isEmpty() == false) {
+          EdmNavigationProperty navProperty = (EdmNavigationProperty) entitySet.getEntityType()
+              .getProperty(
+                  navPropertyName);
+
           for (String link : links) {
             UriInfo bindingUriInfo = parser.parseBindingLink(link, new HashMap<String, String>());
             targetJPAEntity = jpaProcessor.process((GetEntityUriInfo) bindingUriInfo);
-            linkJPAEntities(targetJPAEntity, sourceJPAEntity, (EdmNavigationProperty) entitySet.getEntityType()
-                .getProperty(
-                    navPropertyName));
+            List<Object> targetJPAEntities = new ArrayList<Object>();
+            targetJPAEntities.add(targetJPAEntity);
+            linkJPAEntities(targetJPAEntities, sourceJPAEntity, navProperty);
           }
         }
       }
@@ -215,7 +220,7 @@ public class JPALink {
 
   }
 
-  public void create(final PostUriInfo uriInfo, final ODataEntry oDataEntry) throws ODataJPARuntimeException,
+  public void create(final PostUriInfo uriInfo) throws ODataJPARuntimeException,
       ODataJPAModelException {
     try {
       int index = context.getODataContext().getPathInfo().getODataSegments().size() - 2;
@@ -228,12 +233,12 @@ public class JPALink {
           throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.RESOURCE_X_NOT_FOUND
               .addContent(parsedUriInfo.getTargetEntitySet().getName()), null);
         }
-        linkJPAEntities(sourceJPAEntity, targetJPAEntity, uriInfo.getNavigationSegments().get(0)
+        List<Object> targetJPAEntities = new ArrayList<Object>();
+        targetJPAEntities.add(sourceJPAEntity);
+        linkJPAEntities(targetJPAEntities, targetJPAEntity, uriInfo.getNavigationSegments().get(0)
             .getNavigationProperty());
       }
 
-      create(uriInfo.getTargetEntitySet(), oDataEntry);
-
     } catch (EdmException e) {
       throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
     } catch (ODataException e) {
@@ -273,7 +278,9 @@ public class JPALink {
         }
       }
       if (targetJPAEntity != null && sourceJPAEntity != null) {
-        linkJPAEntities(targetJPAEntity, sourceJPAEntity, navigationProperty);
+        List<Object> targetJPAEntities = new ArrayList<Object>();
+        targetJPAEntities.add(targetJPAEntity);
+        linkJPAEntities(targetJPAEntities, sourceJPAEntity, navigationProperty);
       }
 
     } catch (IllegalArgumentException e) {
@@ -285,27 +292,34 @@ public class JPALink {
     }
   }
 
-  private void
-      linkJPAEntities(final Object targetJPAEntity, final Object sourceJPAEntity,
-          final EdmNavigationProperty navigationProperty)
-          throws ODataJPARuntimeException {
+  @SuppressWarnings("unchecked")
+  public static void linkJPAEntities(final Collection<Object> targetJPAEntities, final Object sourceJPAEntity,
+      final EdmNavigationProperty navigationProperty) throws ODataJPARuntimeException {
+    if (targetJPAEntities == null || sourceJPAEntity == null || navigationProperty == null) {
+      return;
+    }
     try {
       JPAEntityParser entityParser = new JPAEntityParser();
       Method setMethod = entityParser.getAccessModifier(sourceJPAEntity,
           navigationProperty, JPAEntityParser.ACCESS_MODIFIER_SET);
 
-      Method getMethod = entityParser.getAccessModifier(sourceJPAEntity,
-          navigationProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
-
-      if (getMethod.getReturnType().getTypeParameters() != null
-          && getMethod.getReturnType().getTypeParameters().length != 0) {
-        @SuppressWarnings("unchecked")
+      switch (navigationProperty.getMultiplicity()) {
+      case MANY:
+        Method getMethod = entityParser.getAccessModifier(sourceJPAEntity,
+            navigationProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
         Collection<Object> relatedEntities = (Collection<Object>) getMethod.invoke(sourceJPAEntity);
-        relatedEntities.add(targetJPAEntity);
+        relatedEntities.addAll(targetJPAEntities);
         setMethod.invoke(sourceJPAEntity, relatedEntities);
-      } else {
-        setMethod.invoke(sourceJPAEntity, targetJPAEntity);
+        break;
+      case ONE:
+      case ZERO_TO_ONE:
+        setMethod.invoke(sourceJPAEntity, targetJPAEntities.iterator().next());
+        break;
       }
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
     } catch (IllegalAccessException e) {
       throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
     } catch (InvocationTargetException e) {

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
index 1a8a0f0..0b46fd9 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAProcessorImpl.java
@@ -314,9 +314,6 @@ public class JPAProcessorImpl implements JPAProcessor {
         final ODataEntry oDataEntry =
             oDataEntityParser.parseEntry(oDataEntitySet, content, requestedContentType, false);
         virtualJPAEntity.create(oDataEntry);
-        JPALink link = new JPALink(oDataJPAContext);
-        link.setSourceJPAEntity(virtualJPAEntity.getJPAEntity());
-        link.create(createView, oDataEntry);
       } else if (properties != null) {
         virtualJPAEntity.create(properties);
       } else {

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityTest.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityTest.java
index caf3167..71e2204 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/access/data/JPAEntityTest.java
@@ -112,7 +112,6 @@ public class JPAEntityTest {
     assertTrue(jpaTypeMock.getMDateTime().equals(ODataEntryMockUtil.VALUE_DATE_TIME));
 
     JPARelatedTypeMock relatedType = jpaTypeMock.getMRelatedEntity();
-    assertNotNull(jpaTypeMock.getMRelatedEntity());
     assertEquals(relatedType.getMByte(), ODataEntryMockUtil.VALUE_MBYTE);
     assertEquals(relatedType.getMByteArray(), ODataEntryMockUtil.VALUE_MBYTEARRAY);
     assertEquals(relatedType.getMDouble(), ODataEntryMockUtil.VALUE_MDOUBLE, 0.0);
@@ -146,7 +145,7 @@ public class JPAEntityTest {
       EdmEntitySet edmEntitySet = EdmMockUtilV2.mockEdmEntitySet(JPATypeMock.ENTITY_NAME, false);
       EdmEntityType edmEntityType = edmEntitySet.getEntityType();
 
-      jpaEntity = new JPAEntity(edmEntityType, edmEntitySet, null);
+      jpaEntity = new JPAEntity(edmEntityType, edmEntitySet, ODataJPAContextMock.mockODataJPAContext());
       JPATypeMock jpaTypeMock = new JPATypeMock();
       jpaEntity.setJPAEntity(jpaTypeMock);
       jpaEntity.update(ODataEntryMockUtil.mockODataEntry(JPATypeMock.ENTITY_NAME));

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/EdmMockUtilV2.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/EdmMockUtilV2.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/EdmMockUtilV2.java
index 2ecf5dd..a15fbc1 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/EdmMockUtilV2.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/EdmMockUtilV2.java
@@ -75,7 +75,8 @@ public class EdmMockUtilV2 {
       EasyMock.expect(entityType.getPropertyNames()).andReturn(mockPropertyNamesWithComplexType(entityName)).anyTimes();
     }
 
-    EasyMock.expect(entityType.getNavigationPropertyNames()).andReturn(mockNavigationPropertyNames(entityName));
+    EasyMock.expect(entityType.getNavigationPropertyNames()).andReturn(mockNavigationPropertyNames(entityName))
+        .anyTimes();
     EasyMock.expect(entityType.getKind()).andReturn(EdmTypeKind.ENTITY);
     EasyMock.expect(entityType.getMapping()).andReturn((EdmMapping) mockEdmMapping(entityName, null, null));
     EasyMock.expect(entityType.getKeyProperties()).andReturn(mockKeyProperties(entityName)).anyTimes();

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/ODataEntryMockUtil.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/ODataEntryMockUtil.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/ODataEntryMockUtil.java
index 019bfb6..125f160 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/ODataEntryMockUtil.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/mock/data/ODataEntryMockUtil.java
@@ -51,11 +51,7 @@ public class ODataEntryMockUtil {
     ODataEntry oDataEntry = EasyMock.createMock(ODataEntry.class);
     EasyMock.expect(oDataEntry.getProperties()).andReturn(mockODataEntryProperties(entityName)).anyTimes();
 
-    EasyMock.expect(oDataEntry.containsInlineEntry()).andReturn(false).anyTimes();
-    EntryMetadata entryMetadata = EasyMock.createMock(EntryMetadata.class);
-    EasyMock.expect(entryMetadata.getAssociationUris(EasyMock.isA(String.class))).andReturn(null).anyTimes();
-    EasyMock.replay(entryMetadata);
-    EasyMock.expect(oDataEntry.getMetadata()).andReturn(entryMetadata).anyTimes();
+    enhanceMockODataEntry(oDataEntry, false, new ArrayList<String>());
     EasyMock.replay(oDataEntry);
     return oDataEntry;
   }
@@ -65,7 +61,7 @@ public class ODataEntryMockUtil {
     EasyMock.expect(oDataEntry.getProperties()).andReturn(mockODataEntryPropertiesWithComplexType(entityName))
         .anyTimes();
 
-    EasyMock.expect(oDataEntry.containsInlineEntry()).andReturn(false).anyTimes();
+    enhanceMockODataEntry(oDataEntry, false, new ArrayList<String>());
     EasyMock.replay(oDataEntry);
     return oDataEntry;
   }
@@ -122,11 +118,33 @@ public class ODataEntryMockUtil {
     ODataEntry oDataEntry = EasyMock.createMock(ODataEntry.class);
     EasyMock.expect(oDataEntry.getProperties()).andReturn(mockODataEntryPropertiesWithInline(entityName)).anyTimes();
     if (entityName.equals(JPATypeMock.ENTITY_NAME)) {
-      EasyMock.expect(oDataEntry.containsInlineEntry()).andReturn(true).anyTimes();
+      List<String> links = new ArrayList<String>();
+      links.add(JPATypeMock.ENTITY_NAME + "(" + ODataEntryMockUtil.VALUE_MINT + ")/"
+          + JPATypeMock.NAVIGATION_PROPERTY_X);
+      enhanceMockODataEntry(oDataEntry, true, links);
     } else {
-      EasyMock.expect(oDataEntry.containsInlineEntry()).andReturn(false).anyTimes();
+      enhanceMockODataEntry(oDataEntry, false, new ArrayList<String>());
     }
     EasyMock.replay(oDataEntry);
     return oDataEntry;
   }
+
+  private static void
+      enhanceMockODataEntry(final ODataEntry oDataEntry, boolean hasInline, List<String> associationURIs) {
+    EasyMock.expect(oDataEntry.containsInlineEntry()).andReturn(hasInline).anyTimes();
+    EntryMetadata entryMetadata = EasyMock.createMock(EntryMetadata.class);
+    if (hasInline) {
+      EasyMock.expect(entryMetadata.getAssociationUris(JPATypeMock.NAVIGATION_PROPERTY_X)).andReturn(associationURIs)
+          .anyTimes();
+      EasyMock.expect(entryMetadata.getAssociationUris(JPATypeMock.NAVIGATION_PROPERTY_XS)).andReturn(
+          new ArrayList<String>())
+          .anyTimes();
+    } else {
+      EasyMock.expect(entryMetadata.getAssociationUris(EasyMock.isA(String.class))).andReturn(associationURIs)
+          .anyTimes();
+    }
+
+    EasyMock.replay(entryMetadata);
+    EasyMock.expect(oDataEntry.getMetadata()).andReturn(entryMetadata).anyTimes();
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderHeader.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderHeader.java b/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderHeader.java
index c6a28c5..74a39c8 100644
--- a/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderHeader.java
+++ b/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderHeader.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.TimeZone;
 
+import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.Id;
@@ -81,27 +82,16 @@ public class SalesOrderHeader {
   @Column(precision = 8)
   private double netAmount;
 
-  @Column(name = "CUST_ID")
-  private Long customerId;
-
-  @OneToMany(mappedBy = "salesOrderHeader")
+  @OneToMany(mappedBy = "salesOrderHeader", cascade = CascadeType.ALL)
   private Set<SalesOrderItem> salesOrderItem = new HashSet<SalesOrderItem>();
 
   @OneToMany(mappedBy = "salesOrderHeader")
   private List<Note> notes = new ArrayList<Note>();
 
   @ManyToOne
-  @JoinColumn(name = "CUST_ID", referencedColumnName = "ID", insertable = false, updatable = false)
+  @JoinColumn(name = "CUST_ID", referencedColumnName = "ID")
   private Customer customer;
 
-  public Long getCustomerId() {
-    return customerId;
-  }
-
-  public void setCustomerId(final Long customerId) {
-    this.customerId = customerId;
-  }
-
   public Customer getCustomer() {
     return customer;
   }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1fc260e6/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderItem.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderItem.java b/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderItem.java
index 9ee0f19..a8671d1 100644
--- a/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderItem.java
+++ b/odata2-jpa-processor/jpa-ref/src/main/java/org/apache/olingo/odata2/jpa/processor/ref/model/SalesOrderItem.java
@@ -30,116 +30,104 @@ import javax.persistence.Transient;
 @Table(name = "T_SALESORDERITEM")
 public class SalesOrderItem {
 
-	public SalesOrderItem() {
-	}
+  public SalesOrderItem() {}
 
-	public SalesOrderItem(final int quantity, final double amount,
-			final double discount, final Material material) {
-		super();
-		this.quantity = quantity;
-		this.amount = amount;
-		this.discount = discount;
-		this.material = material;
-	}
-
-	@EmbeddedId
-	private SalesOrderItemKey salesOrderItemKey;
-
-	@Column(name = "Material_Id", nullable = false)
-	private long matId;
-
-	@Column
-	private int quantity;
-
-	@Column
-	private double amount;
-
-	@Column
-	private double discount;
-
-	@Transient
-	private double netAmount;
-	
-	@Column
-	private boolean delivered;
-
-	public Boolean isDelivered() {
-		return delivered;
-	}
-
-	public void setDelivered(final Boolean deliveryStatus) {
-		this.delivered = deliveryStatus;
-	}
-
-	@JoinColumn(name = "Material_Id", referencedColumnName = "MATERIAL_ID", insertable = false, updatable = false)
-	@ManyToOne
-	private Material material;
-
-	@JoinColumn(name = "Sales_Order_Id", referencedColumnName = "SO_ID", insertable = false, updatable = false)
-	@ManyToOne
-	private SalesOrderHeader salesOrderHeader;
-
-	public SalesOrderItemKey getSalesOrderItemKey() {
-		return salesOrderItemKey;
-	}
-
-	public void setSalesOrderItemKey(final SalesOrderItemKey salesOrderItemKey) {
-		this.salesOrderItemKey = salesOrderItemKey;
-	}
-
-	public long getMatId() {
-		return matId;
-	}
-
-	public void setMatId(final long matId) {
-		this.matId = matId;
-	}
-
-	public int getQuantity() {
-		return quantity;
-	}
-
-	public void setQuantity(final int quantity) {
-		this.quantity = quantity;
-	}
-
-	public double getAmount() {
-		return amount;
-	}
-
-	public void setAmount(final double amount) {
-		this.amount = amount;
-	}
-
-	public double getDiscount() {
-		return discount;
-	}
-
-	public void setDiscount(final double discount) {
-		this.discount = discount;
-	}
-
-	public double getNetAmount() {
-		return netAmount;
-	}
-
-	public void setNetAmount(final double netAmount) {
-		this.netAmount = netAmount;
-	}
-
-	public Material getMaterial() {
-		return material;
-	}
-
-	public void setMaterial(final Material material) {
-		this.material = material;
-	}
-
-	public SalesOrderHeader getSalesOrderHeader() {
-		return salesOrderHeader;
-	}
+  public SalesOrderItem(final int quantity, final double amount,
+      final double discount, final Material material) {
+    super();
+    this.quantity = quantity;
+    this.amount = amount;
+    this.discount = discount;
+    this.material = material;
+  }
 
-	public void setSalesOrderHeader(final SalesOrderHeader salesOrderHeader) {
-		this.salesOrderHeader = salesOrderHeader;
-	}
+  @EmbeddedId
+  private SalesOrderItemKey salesOrderItemKey;
+
+  @Column
+  private int quantity;
+
+  @Column
+  private double amount;
+
+  @Column
+  private double discount;
+
+  @Transient
+  private double netAmount;
+
+  @Column
+  private boolean delivered;
+
+  public Boolean isDelivered() {
+    return delivered;
+  }
+
+  public void setDelivered(final Boolean deliveryStatus) {
+    this.delivered = deliveryStatus;
+  }
+
+  @JoinColumn(name = "Material_Id", referencedColumnName = "MATERIAL_ID")
+  @ManyToOne
+  private Material material;
+
+  @JoinColumn(name = "Sales_Order_Id", referencedColumnName = "SO_ID", insertable = false, updatable = false)
+  @ManyToOne
+  private SalesOrderHeader salesOrderHeader;
+
+  public SalesOrderItemKey getSalesOrderItemKey() {
+    return salesOrderItemKey;
+  }
+
+  public void setSalesOrderItemKey(final SalesOrderItemKey salesOrderItemKey) {
+    this.salesOrderItemKey = salesOrderItemKey;
+  }
+
+  public int getQuantity() {
+    return quantity;
+  }
+
+  public void setQuantity(final int quantity) {
+    this.quantity = quantity;
+  }
+
+  public double getAmount() {
+    return amount;
+  }
+
+  public void setAmount(final double amount) {
+    this.amount = amount;
+  }
+
+  public double getDiscount() {
+    return discount;
+  }
+
+  public void setDiscount(final double discount) {
+    this.discount = discount;
+  }
+
+  public double getNetAmount() {
+    return netAmount;
+  }
+
+  public void setNetAmount(final double netAmount) {
+    this.netAmount = netAmount;
+  }
+
+  public Material getMaterial() {
+    return material;
+  }
+
+  public void setMaterial(final Material material) {
+    this.material = material;
+  }
+
+  public SalesOrderHeader getSalesOrderHeader() {
+    return salesOrderHeader;
+  }
+
+  public void setSalesOrderHeader(final SalesOrderHeader salesOrderHeader) {
+    this.salesOrderHeader = salesOrderHeader;
+  }
 }