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 2015/02/06 15:34:26 UTC

olingo-odata4 git commit: [OLINGO-545] support for entity creation in technical service

Repository: olingo-odata4
Updated Branches:
  refs/heads/master b7d2c5f44 -> 6c4b3ea40


[OLINGO-545] support for entity creation in technical service

Change-Id: I6112550db5ab73c5f189e8c3a91354c9e43284de

Signed-off-by: Christian Amend <ch...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/6c4b3ea4
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/6c4b3ea4
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/6c4b3ea4

Branch: refs/heads/master
Commit: 6c4b3ea40827845c67709e2c6bfa49df6e5eaba1
Parents: b7d2c5f
Author: Klaus Straubinger <kl...@sap.com>
Authored: Fri Feb 6 15:21:54 2015 +0100
Committer: Christian Amend <ch...@apache.org>
Committed: Fri Feb 6 15:26:23 2015 +0100

----------------------------------------------------------------------
 .../olingo/fit/tecsvc/client/BasicITCase.java   |  53 ++--
 .../olingo/server/tecsvc/data/DataCreator.java  | 242 +++++++++----------
 .../olingo/server/tecsvc/data/DataProvider.java |  77 ++++--
 .../processor/TechnicalEntityProcessor.java     |  32 +--
 .../server/tecsvc/data/DataProviderTest.java    |   2 +-
 5 files changed, 218 insertions(+), 188 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6c4b3ea4/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
index 9c3c9e2..c1abe15 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
@@ -27,14 +27,12 @@ import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.IOException;
 import java.net.URI;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
 import org.apache.olingo.client.api.communication.ODataClientErrorException;
-import org.apache.olingo.client.api.communication.ODataServerErrorException;
 import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
 import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
 import org.apache.olingo.client.api.communication.request.cud.v4.UpdateType;
@@ -306,7 +304,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
   }
 
   @Test
-  @Ignore("Actual leads to an unexpected exception")
+  @Ignore("Currently this test is not possible due to nullable=false in all available complex types")
   public void updateEntityWithComplex() throws Exception {
     final ODataClient client = getClient();
     final ODataObjectFactory factory = client.getObjectFactory();
@@ -334,40 +332,29 @@ public class BasicITCase extends AbstractBaseTestITCase {
     assertNull(property.getPrimitiveValue());
   }
 
-  /**
-   * Currently a create request for an entity will lead to a "501 - Not Implemented" response
-   * and hence to an ODataServerErrorException.
-   */
-  @Test(expected = ODataServerErrorException.class)
-  public void createEntity() throws IOException {
-    final ODataEntityRequest<ODataEntity> request = getClient().getRetrieveRequestFactory()
-        .getEntityRequest(getClient().newURIBuilder(SERVICE_URI)
-            .appendEntitySetSegment("ESCollAllPrim").appendKeySegment(1).build());
-    assertNotNull(request);
-
-    final ODataRetrieveResponse<ODataEntity> response = request.execute();
-    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
-    assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
-
-    final ODataEntity entity = response.getBody();
-    assertNotNull(entity);
-
-    final ODataEntityCreateRequest<ODataEntity> createRequest = getClient().getCUDRequestFactory()
-        .getEntityCreateRequest(getClient().newURIBuilder(SERVICE_URI)
-            .appendEntitySetSegment("ESCollAllPrim").build(), entity);
+  @Test
+  public void createEntity() throws Exception {
+    final ODataClient client = getClient();
+    final ODataObjectFactory factory = client.getObjectFactory();
+    ODataEntity newEntity = factory.newEntity(new FullQualifiedName("olingo.odata.test1", "ETAllPrim"));
+    newEntity.getProperties().add(factory.newPrimitiveProperty("PropertyInt64",
+        factory.newPrimitiveValueBuilder().buildInt32(42)));
+    final ODataEntityCreateRequest<ODataEntity> createRequest = client.getCUDRequestFactory().getEntityCreateRequest(
+        client.newURIBuilder(SERVICE_URI).appendEntitySetSegment("ESAllPrim").build(),
+        newEntity);
     assertNotNull(createRequest);
-    ODataEntityCreateResponse<ODataEntity> createResponse = createRequest.execute();
+    final ODataEntityCreateResponse<ODataEntity> createResponse = createRequest.execute();
 
+    assertEquals(HttpStatusCode.CREATED.getStatusCode(), createResponse.getStatusCode());
+    assertEquals(SERVICE_URI + "/ESAllPrim(1)", createResponse.getHeader(HttpHeader.LOCATION).iterator().next());
     final ODataEntity createdEntity = createResponse.getBody();
     assertNotNull(createdEntity);
-    final ODataProperty property = createdEntity.getProperty("CollPropertyInt16");
-    assertNotNull(property);
-    assertNotNull(property.getCollectionValue());
-    assertEquals(3, property.getCollectionValue().size());
-    Iterator<ODataValue> iterator = property.getCollectionValue().iterator();
-    assertEquals(1000, iterator.next().asPrimitive().toValue());
-    assertEquals(2000, iterator.next().asPrimitive().toValue());
-    assertEquals(30112, iterator.next().asPrimitive().toValue());
+    final ODataProperty property1 = createdEntity.getProperty("PropertyInt64");
+    assertNotNull(property1);
+    assertEquals(42, property1.getPrimitiveValue().toValue());
+    final ODataProperty property2 = createdEntity.getProperty("PropertyDecimal");
+    assertNotNull(property2);
+    assertNull(property2.getPrimitiveValue());
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6c4b3ea4/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
index 3e964ee..b692257 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java
@@ -155,74 +155,68 @@ public class DataCreator {
 
     Entity entity = new EntityImpl();
     entity.addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE));
-    LinkedComplexValue complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyString", "First Resource - first"));
-    complexValue.getValue().add(createPrimitive("PropertyBinary",
-        new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }));
-    complexValue.getValue().add(createPrimitive("PropertyBoolean", true));
-    complexValue.getValue().add(createPrimitive("PropertyByte", 255));
-    complexValue.getValue().add(createPrimitive("PropertyDate", getDateTime(2012, 10, 3, 0, 0, 0)));
-    complexValue.getValue().add(createPrimitive("PropertyDateTimeOffset",
-        getTimestamp(2012, 10, 3, 7, 16, 23, 123456700)));
-    complexValue.getValue().add(createPrimitive("PropertyDecimal", 34.27));
-    complexValue.getValue().add(createPrimitive("PropertySingle", 1.79000000E+20));
-    complexValue.getValue().add(createPrimitive("PropertyDouble", -1.7900000000000000E+19));
-    complexValue.getValue().add(createPrimitive("PropertyDuration", 6));
-    complexValue.getValue().add(createPrimitive("PropertyGuid", GUID));
-    complexValue.getValue().add(createPrimitive("PropertyInt16", Short.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertyInt32", Integer.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertyInt64", Long.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertySByte", Byte.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertyTimeOfDay", getTime(1, 0, 1)));
-    entity.addProperty(new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue));
+    entity.addProperty(createComplex("PropertyComp",
+        createPrimitive("PropertyString", "First Resource - first"),
+        createPrimitive("PropertyBinary",
+            new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }),
+        createPrimitive("PropertyBoolean", true),
+        createPrimitive("PropertyByte", 255),
+        createPrimitive("PropertyDate", getDateTime(2012, 10, 3, 0, 0, 0)),
+        createPrimitive("PropertyDateTimeOffset", getTimestamp(2012, 10, 3, 7, 16, 23, 123456700)),
+        createPrimitive("PropertyDecimal", 34.27),
+        createPrimitive("PropertySingle", 1.79000000E+20),
+        createPrimitive("PropertyDouble", -1.7900000000000000E+19),
+        createPrimitive("PropertyDuration", 6),
+        createPrimitive("PropertyGuid", GUID),
+        createPrimitive("PropertyInt16", Short.MAX_VALUE),
+        createPrimitive("PropertyInt32", Integer.MAX_VALUE),
+        createPrimitive("PropertyInt64", Long.MAX_VALUE),
+        createPrimitive("PropertySByte", Byte.MAX_VALUE),
+        createPrimitive("PropertyTimeOfDay", getTime(1, 0, 1))));
     entitySet.getEntities().add(entity);
 
     entity = new EntityImpl();
     entity.addProperty(createPrimitive("PropertyInt16", 7));
-    complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyString", "Second Resource - second"));
-    complexValue.getValue().add(createPrimitive("PropertyBinary",
-        new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }));
-    complexValue.getValue().add(createPrimitive("PropertyBoolean", true));
-    complexValue.getValue().add(createPrimitive("PropertyByte", 255));
-    complexValue.getValue().add(createPrimitive("PropertyDate", getDateTime(2013, 11, 4, 0, 0, 0)));
-    complexValue.getValue().add(createPrimitive("PropertyDateTimeOffset",
-        getDateTime(2013, 11, 4, 7, 16, 23)));
-    complexValue.getValue().add(createPrimitive("PropertyDecimal", 34.27));
-    complexValue.getValue().add(createPrimitive("PropertySingle", 1.79000000E+20));
-    complexValue.getValue().add(createPrimitive("PropertyDouble", -1.7900000000000000E+02));
-    complexValue.getValue().add(createPrimitive("PropertyDuration", 6));
-    complexValue.getValue().add(createPrimitive("PropertyGuid", GUID));
-    complexValue.getValue().add(createPrimitive("PropertyInt16", 25));
-    complexValue.getValue().add(createPrimitive("PropertyInt32", Integer.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertyInt64", Long.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertySByte", Byte.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertyTimeOfDay", getTimestamp(1, 1, 1, 7, 45, 12, 765432100)));
-    entity.addProperty(new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue));
+    entity.addProperty(createComplex("PropertyComp",
+        createPrimitive("PropertyString", "Second Resource - second"),
+        createPrimitive("PropertyBinary",
+            new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }),
+        createPrimitive("PropertyBoolean", true),
+        createPrimitive("PropertyByte", 255),
+        createPrimitive("PropertyDate", getDateTime(2013, 11, 4, 0, 0, 0)),
+        createPrimitive("PropertyDateTimeOffset", getDateTime(2013, 11, 4, 7, 16, 23)),
+        createPrimitive("PropertyDecimal", 34.27),
+        createPrimitive("PropertySingle", 1.79000000E+20),
+        createPrimitive("PropertyDouble", -1.7900000000000000E+02),
+        createPrimitive("PropertyDuration", 6),
+        createPrimitive("PropertyGuid", GUID),
+        createPrimitive("PropertyInt16", 25),
+        createPrimitive("PropertyInt32", Integer.MAX_VALUE),
+        createPrimitive("PropertyInt64", Long.MAX_VALUE),
+        createPrimitive("PropertySByte", Byte.MAX_VALUE),
+        createPrimitive("PropertyTimeOfDay", getTimestamp(1, 1, 1, 7, 45, 12, 765432100))));
     entitySet.getEntities().add(entity);
 
     entity = new EntityImpl();
     entity.addProperty(createPrimitive("PropertyInt16", 0));
-    complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyString", "Third Resource - third"));
-    complexValue.getValue().add(createPrimitive("PropertyBinary",
-        new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }));
-    complexValue.getValue().add(createPrimitive("PropertyBoolean", true));
-    complexValue.getValue().add(createPrimitive("PropertyByte", 255));
-    complexValue.getValue().add(createPrimitive("PropertyDate", getDateTime(2014, 12, 5, 0, 0, 0)));
-    complexValue.getValue().add(createPrimitive("PropertyDateTimeOffset",
-        getTimestamp(2014, 12, 5, 8, 17, 45, 123456700)));
-    complexValue.getValue().add(createPrimitive("PropertyDecimal", 17.98));
-    complexValue.getValue().add(createPrimitive("PropertySingle", 1.79000000E+20));
-    complexValue.getValue().add(createPrimitive("PropertyDouble", -1.7900000000000000E+02));
-    complexValue.getValue().add(createPrimitive("PropertyDuration", 6));
-    complexValue.getValue().add(createPrimitive("PropertyGuid", GUID));
-    complexValue.getValue().add(createPrimitive("PropertyInt16", -25));
-    complexValue.getValue().add(createPrimitive("PropertyInt32", Integer.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertyInt64", Long.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertySByte", Byte.MAX_VALUE));
-    complexValue.getValue().add(createPrimitive("PropertyTimeOfDay", getTime(13, 27, 45)));
-    entity.addProperty(new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue));
+    entity.addProperty(createComplex("PropertyComp",
+        createPrimitive("PropertyString", "Third Resource - third"),
+        createPrimitive("PropertyBinary",
+            new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF }),
+        createPrimitive("PropertyBoolean", true),
+        createPrimitive("PropertyByte", 255),
+        createPrimitive("PropertyDate", getDateTime(2014, 12, 5, 0, 0, 0)),
+        createPrimitive("PropertyDateTimeOffset", getTimestamp(2014, 12, 5, 8, 17, 45, 123456700)),
+        createPrimitive("PropertyDecimal", 17.98),
+        createPrimitive("PropertySingle", 1.79000000E+20),
+        createPrimitive("PropertyDouble", -1.7900000000000000E+02),
+        createPrimitive("PropertyDuration", 6),
+        createPrimitive("PropertyGuid", GUID),
+        createPrimitive("PropertyInt16", -25),
+        createPrimitive("PropertyInt32", Integer.MAX_VALUE),
+        createPrimitive("PropertyInt64", Long.MAX_VALUE),
+        createPrimitive("PropertySByte", Byte.MAX_VALUE),
+        createPrimitive("PropertyTimeOfDay", getTime(13, 27, 45))));
     entitySet.getEntities().add(entity);
 
     return entitySet;
@@ -233,36 +227,36 @@ public class DataCreator {
 
     entitySet.getEntities().add(new EntityImpl()
         .addProperty(createPrimitive("PropertyInt16", 1))
-        .addProperty(createCollection("CollPropertyString",
+        .addProperty(createPrimitiveCollection("CollPropertyString",
             "Employee1@company.example", "Employee2@company.example", "Employee3@company.example"))
-        .addProperty(createCollection("CollPropertyBoolean", true, false, true))
-        .addProperty(createCollection("CollPropertyByte", 50, 200, 249))
-        .addProperty(createCollection("CollPropertySByte", -120, 120, 126))
-        .addProperty(createCollection("CollPropertyInt16", 1000, 2000, 30112))
-        .addProperty(createCollection("CollPropertyInt32", 23232323, 11223355, 10000001))
-        .addProperty(createCollection("CollPropertyInt64", 929292929292L, 333333333333L, 444444444444L))
-        .addProperty(createCollection("CollPropertySingle", 1.79000000E+03, 2.66000000E+04, 3.21000000E+03))
-        .addProperty(createCollection("CollPropertyDouble",
+        .addProperty(createPrimitiveCollection("CollPropertyBoolean", true, false, true))
+        .addProperty(createPrimitiveCollection("CollPropertyByte", 50, 200, 249))
+        .addProperty(createPrimitiveCollection("CollPropertySByte", -120, 120, 126))
+        .addProperty(createPrimitiveCollection("CollPropertyInt16", 1000, 2000, 30112))
+        .addProperty(createPrimitiveCollection("CollPropertyInt32", 23232323, 11223355, 10000001))
+        .addProperty(createPrimitiveCollection("CollPropertyInt64", 929292929292L, 333333333333L, 444444444444L))
+        .addProperty(createPrimitiveCollection("CollPropertySingle", 1.79000000E+03, 2.66000000E+04, 3.21000000E+03))
+        .addProperty(createPrimitiveCollection("CollPropertyDouble",
             -1.7900000000000000E+04, -2.7800000000000000E+07, 3.2100000000000000E+03))
-        .addProperty(createCollection("CollPropertyDecimal", 12, -2, 1234))
-        .addProperty(createCollection("CollPropertyBinary",
+        .addProperty(createPrimitiveCollection("CollPropertyDecimal", 12, -2, 1234))
+        .addProperty(createPrimitiveCollection("CollPropertyBinary",
             new byte[] { (byte) 0xAB, (byte) 0xCD, (byte) 0xEF },
             new byte[] { 0x01, 0x23, 0x45 },
             new byte[] { 0x54, 0x67, (byte) 0x89 }))
-        .addProperty(createCollection("CollPropertyDate",
+        .addProperty(createPrimitiveCollection("CollPropertyDate",
             getDateTime(1958, 12, 3, 0, 0, 0),
             getDateTime(1999, 8, 5, 0, 0, 0),
             getDateTime(2013, 6, 25, 0, 0, 0)))
-        .addProperty(createCollection("CollPropertyDateTimeOffset",
+        .addProperty(createPrimitiveCollection("CollPropertyDateTimeOffset",
             getDateTime(2015, 8, 12, 3, 8, 34),
             getDateTime(1970, 3, 28, 12, 11, 10),
             getDateTime(1948, 2, 17, 9, 9, 9)))
-        .addProperty(createCollection("CollPropertyDuration", 13, 19680, 3600))
-        .addProperty(createCollection("CollPropertyGuid",
+        .addProperty(createPrimitiveCollection("CollPropertyDuration", 13, 19680, 3600))
+        .addProperty(createPrimitiveCollection("CollPropertyGuid",
             UUID.fromString("ffffff67-89ab-cdef-0123-456789aaaaaa"),
             UUID.fromString("eeeeee67-89ab-cdef-0123-456789bbbbbb"),
             UUID.fromString("cccccc67-89ab-cdef-0123-456789cccccc")))
-        .addProperty(createCollection("CollPropertyTimeOfDay",
+        .addProperty(createPrimitiveCollection("CollPropertyTimeOfDay",
             getTime(4, 14, 13), getTime(23, 59, 59), getTime(1, 12, 33))));
 
     Entity entity = new EntityImpl();
@@ -283,51 +277,37 @@ public class DataCreator {
 
     Entity entity = new EntityImpl();
     entity.addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE));
-    entity.addProperty(createCollection("CollPropertyString",
+    entity.addProperty(createPrimitiveCollection("CollPropertyString",
         "Employee1@company.example", "Employee2@company.example", "Employee3@company.example"));
-    LinkedComplexValue complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyInt16", 111));
-    complexValue.getValue().add(createPrimitive("PropertyString", "TEST A"));
-    entity.addProperty(new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue));
-    List<LinkedComplexValue> complexCollection = new ArrayList<LinkedComplexValue>();
-    complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyInt16", 123));
-    complexValue.getValue().add(createPrimitive("PropertyString", "TEST 1"));
-    complexCollection.add(complexValue);
-    complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyInt16", 456));
-    complexValue.getValue().add(createPrimitive("PropertyString", "TEST 2"));
-    complexCollection.add(complexValue);
-    complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyInt16", 789));
-    complexValue.getValue().add(createPrimitive("PropertyString", "TEST 3"));
-    complexCollection.add(complexValue);
-    entity.addProperty(new PropertyImpl(null, "CollPropertyComp", ValueType.COLLECTION_LINKED_COMPLEX,
-        complexCollection));
+    entity.addProperty(createComplex("PropertyComp",
+        createPrimitive("PropertyInt16", 111),
+        createPrimitive("PropertyString", "TEST A")));
+    @SuppressWarnings("unchecked")
+    final Property complexCollection = createComplexCollection("CollPropertyComp",
+        Arrays.asList(createPrimitive("PropertyInt16", 123), createPrimitive("PropertyString", "TEST 1")),
+        Arrays.asList(createPrimitive("PropertyInt16", 456), createPrimitive("PropertyString", "TEST 2")),
+        Arrays.asList(createPrimitive("PropertyInt16", 789), createPrimitive("PropertyString", "TEST 3")));
+    entity.addProperty(complexCollection);
     entitySet.getEntities().add(entity);
 
     entity = new EntityImpl();
     entity.addProperty(createPrimitive("PropertyInt16", 7));
-    entity.addProperty(createCollection("CollPropertyString",
+    entity.addProperty(createPrimitiveCollection("CollPropertyString",
         "Employee1@company.example", "Employee2@company.example", "Employee3@company.example"));
-    complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyInt16", 222));
-    complexValue.getValue().add(createPrimitive("PropertyString", "TEST B"));
-    entity.addProperty(new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue));
-    entity.addProperty(new PropertyImpl(null, "CollPropertyComp", ValueType.COLLECTION_LINKED_COMPLEX,
-        complexCollection));
+    entity.addProperty(createComplex("PropertyComp",
+        createPrimitive("PropertyInt16", 222),
+        createPrimitive("PropertyString", "TEST B")));
+    entity.addProperty(complexCollection);
     entitySet.getEntities().add(entity);
 
     entity = new EntityImpl();
     entity.addProperty(createPrimitive("PropertyInt16", 0));
-    entity.addProperty(createCollection("CollPropertyString",
+    entity.addProperty(createPrimitiveCollection("CollPropertyString",
         "Employee1@company.example", "Employee2@company.example", "Employee3@company.example"));
-    complexValue = new LinkedComplexValueImpl();
-    complexValue.getValue().add(createPrimitive("PropertyInt16", 333));
-    complexValue.getValue().add(createPrimitive("PropertyString", "TEST C"));
-    entity.addProperty(new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue));
-    entity.addProperty(new PropertyImpl(null, "CollPropertyComp", ValueType.COLLECTION_LINKED_COMPLEX,
-        complexCollection));
+    entity.addProperty(createComplex("PropertyComp",
+        createPrimitive("PropertyInt16", 333),
+        createPrimitive("PropertyString", "TEST C")));
+    entity.addProperty(complexCollection);
     entitySet.getEntities().add(entity);
 
     return entitySet;
@@ -374,24 +354,18 @@ public class DataCreator {
 
     Entity entity = new EntityImpl();
     entity.addProperty(createPrimitive("PropertyInt16", 1));
-    LinkedComplexValue complexValueInner = new LinkedComplexValueImpl();
-    complexValueInner.getValue().add(createPrimitive("PropertyInt16", 123));
-    complexValueInner.getValue().add(createPrimitive("PropertyString", "String 1"));
-    LinkedComplexValue complexValueOuter = new LinkedComplexValueImpl();
-    complexValueOuter.getValue().add(
-        new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValueInner));
-    entity.addProperty(new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValueOuter));
+    entity.addProperty(createComplex("PropertyComp",
+        createComplex("PropertyComp",
+            createPrimitive("PropertyInt16", 123),
+            createPrimitive("PropertyString", "String 1"))));
     entitySet.getEntities().add(entity);
 
     entity = new EntityImpl();
     entity.addProperty(createPrimitive("PropertyInt16", 2));
-    complexValueInner = new LinkedComplexValueImpl();
-    complexValueInner.getValue().add(createPrimitive("PropertyInt16", 987));
-    complexValueInner.getValue().add(createPrimitive("PropertyString", "String 2"));
-    complexValueOuter = new LinkedComplexValueImpl();
-    complexValueOuter.getValue().add(
-        new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValueInner));
-    entity.addProperty(new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValueOuter));
+    entity.addProperty(createComplex("PropertyComp",
+        createComplex("PropertyComp",
+            createPrimitive("PropertyInt16", 987),
+            createPrimitive("PropertyString", "String 2"))));
     entitySet.getEntities().add(entity);
 
     return entitySet;
@@ -460,10 +434,28 @@ public class DataCreator {
     return new PropertyImpl(null, name, ValueType.PRIMITIVE, value);
   }
 
-  protected static Property createCollection(final String name, final Object... values) {
+  protected static Property createPrimitiveCollection(final String name, final Object... values) {
     return new PropertyImpl(null, name, ValueType.COLLECTION_PRIMITIVE, Arrays.asList(values));
   }
 
+  protected static Property createComplex(final String name, final Property... properties) {
+    LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+    for (final Property property : properties) {
+      complexValue.getValue().add(property);
+    }
+    return new PropertyImpl(null, name, ValueType.LINKED_COMPLEX, complexValue);
+  }
+
+  protected static Property createComplexCollection(final String name, final List<Property>... propertiesList) {
+    List<LinkedComplexValue> complexCollection = new ArrayList<LinkedComplexValue>();
+    for (final List<Property> properties : propertiesList) {
+      LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+      complexValue.getValue().addAll(properties);
+      complexCollection.add(complexValue);
+    }
+    return new PropertyImpl(null, name, ValueType.COLLECTION_LINKED_COMPLEX, complexCollection);
+  }
+
   private Calendar getDateTime(final int year, final int month, final int day,
       final int hour, final int minute, final int second) {
     Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6c4b3ea4/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index 925dbf8..7a4384b 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@ -19,6 +19,7 @@
 package org.apache.olingo.server.tecsvc.data;
 
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
@@ -34,6 +35,7 @@ import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.commons.core.data.EntityImpl;
 import org.apache.olingo.server.api.ODataApplicationException;
@@ -42,6 +44,7 @@ import org.apache.olingo.server.api.uri.UriParameter;
 public class DataProvider {
 
   protected static final String MEDIA_PROPERTY_NAME = "$value";
+  private static final String KEY_NAME = "PropertyInt16";
 
   private Map<String, EntitySet> data;
 
@@ -54,16 +57,16 @@ public class DataProvider {
   }
 
   public Entity read(final EdmEntitySet edmEntitySet, final List<UriParameter> keys) throws DataProviderException {
-    final EdmEntityType entityType = edmEntitySet.getEntityType();
-    final EntitySet entitySet = data.get(edmEntitySet.getName());
+    final EntitySet entitySet = readAll(edmEntitySet);
     if (entitySet == null) {
       return null;
     } else {
+      final EdmEntityType edmEntityType = edmEntitySet.getEntityType();
       try {
         for (final Entity entity : entitySet.getEntities()) {
           boolean found = true;
           for (final UriParameter key : keys) {
-            final EdmProperty property = (EdmProperty) entityType.getProperty(key.getName());
+            final EdmProperty property = (EdmProperty) edmEntityType.getProperty(key.getName());
             final EdmPrimitiveType type = (EdmPrimitiveType) property.getType();
             final Object value = entity.getProperty(key.getName()).getValue();
             final Object keyValue = type.valueOfString(type.fromUriLiteral(key.getText()),
@@ -88,12 +91,12 @@ public class DataProvider {
 
   public void delete(final EdmEntitySet edmEntitySet, final Entity entity) throws DataProviderException {
     deleteLinksTo(entity);
-    data.get(edmEntitySet.getName()).getEntities().remove(entity);
+    readAll(edmEntitySet).getEntities().remove(entity);
   }
 
   public void deleteLinksTo(final Entity to) throws DataProviderException {
-    for (final String entitySet : data.keySet()) {
-      for (final Entity entity : data.get(entitySet).getEntities()) {
+    for (final String entitySetName : data.keySet()) {
+      for (final Entity entity : data.get(entitySetName).getEntities()) {
         for (Iterator<Link> linkIterator = entity.getNavigationLinks().iterator(); linkIterator.hasNext();) {
           final Link link = linkIterator.next();
           if (to.equals(link.getInlineEntity())) {
@@ -114,20 +117,62 @@ public class DataProvider {
   }
 
   public Entity create(final EdmEntitySet edmEntitySet) throws DataProviderException {
+    final EdmEntityType edmEntityType = edmEntitySet.getEntityType();
     List<Entity> entities = readAll(edmEntitySet).getEntities();
     Entity entity = new EntityImpl();
-    final List<String> keyNames = edmEntitySet.getEntityType().getKeyPredicateNames();
-    if (keyNames.size() == 1 && keyNames.get(0).equals("PropertyInt16")) {
-      entity.addProperty(DataCreator.createPrimitive("PropertyInt16",
-          entities.isEmpty() ? 1 :
-              (Integer) entities.get(entities.size() - 1).getProperty("PropertyInt16").getValue() + 1));
+    final List<String> keyNames = edmEntityType.getKeyPredicateNames();
+    if (keyNames.size() == 1 && keyNames.get(0).equals(KEY_NAME)) {
+      entity.addProperty(DataCreator.createPrimitive(KEY_NAME, findFreeKeyValue(entities)));
     } else {
       throw new DataProviderException("Key construction not supported!");
     }
+    createProperties(edmEntityType, entity.getProperties());
     entities.add(entity);
     return entity;
   }
 
+  private Integer findFreeKeyValue(final List<Entity> entities) {
+    Integer result = 0;
+    boolean free;
+    do {
+      ++result;
+      free = true;
+      for (final Entity entity : entities) {
+        if (result.equals(entity.getProperty(KEY_NAME).getValue())) {
+          free = false;
+          break;
+        }
+      }
+    } while (!free);
+    return result;
+  }
+
+  private void createProperties(final EdmStructuredType type, List<Property> properties) throws DataProviderException {
+    final List<String> keyNames = type instanceof EdmEntityType ?
+        ((EdmEntityType) type).getKeyPredicateNames() : Collections.<String> emptyList();
+    for (final String propertyName : type.getPropertyNames()) {
+      if (!keyNames.contains(propertyName)) {
+        final EdmProperty edmProperty = type.getStructuralProperty(propertyName);
+        Property newProperty;
+        if (edmProperty.isPrimitive()) {
+          newProperty = edmProperty.isCollection() ?
+              DataCreator.createPrimitiveCollection(propertyName) :
+              DataCreator.createPrimitive(propertyName, null);
+        } else {
+          if (edmProperty.isCollection()) {
+            @SuppressWarnings("unchecked")
+            Property newProperty2 = DataCreator.createComplexCollection(propertyName);
+            newProperty = newProperty2;
+          } else {
+            newProperty = DataCreator.createComplex(propertyName);
+            createProperties((EdmComplexType) edmProperty.getType(), newProperty.asLinkedComplex().getValue());
+          }
+        }
+        properties.add(newProperty);
+      }
+    }
+  }
+
   public void update(final EdmEntitySet edmEntitySet, Entity entity, final Entity changedEntity, final boolean patch)
       throws DataProviderException {
     final EdmEntityType entityType = edmEntitySet.getEntityType();
@@ -147,9 +192,7 @@ public class DataProvider {
 
   public void updateProperty(final EdmProperty edmProperty, Property property, final Property newProperty,
       final boolean patch) throws DataProviderException {
-    if (edmProperty.isCollection() && !edmProperty.isPrimitive()) {
-      throw new DataProviderException("Complex-collection properties are not yet supported.");
-    } else if (property.isPrimitive()) {
+    if (edmProperty.isPrimitive()) {
       if (newProperty != null || !patch) {
         final Object value = newProperty == null ? null : newProperty.getValue();
         if (value == null && edmProperty.isNullable() != null && !edmProperty.isNullable()) {
@@ -157,6 +200,12 @@ public class DataProvider {
         }
         property.setValue(property.getValueType(), value);
       }
+    } else if (edmProperty.isCollection()) {
+      if (newProperty != null && !newProperty.asLinkedComplex().getValue().isEmpty()) {
+        throw new DataProviderException("Update of a complex-collection property not supported!");
+      } else {
+        property.asLinkedComplex().getValue().clear();
+      }
     } else {
       final EdmComplexType type = (EdmComplexType) edmProperty.getType();
       for (final String propertyName : type.getPropertyNames()) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6c4b3ea4/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
index 3400b0d..6cd3195 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java
@@ -26,6 +26,7 @@ import org.apache.olingo.commons.api.data.ContextURL.Suffix;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntitySet;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.format.ODataFormat;
 import org.apache.olingo.commons.api.http.HttpContentType;
@@ -162,24 +163,33 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
   public void createMediaEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
       final ContentType requestFormat, final ContentType responseFormat)
           throws ODataApplicationException, DeserializerException, SerializerException {
+    createEntity(request, response, uriInfo, requestFormat, responseFormat);
+  }
 
+  @Override
+  public void createEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
+      final ContentType requestFormat, final ContentType responseFormat)
+          throws ODataApplicationException, DeserializerException, SerializerException {
     blockNavigation(uriInfo);
+    checkRequestFormat(requestFormat);
     final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) uriInfo.getUriResourceParts().get(0);
     final EdmEntitySet edmEntitySet = resourceEntitySet.getEntitySet();
-    Entity entity = null;
-    if (edmEntitySet.getEntityType().hasStream()) {
-      checkRequestFormat(requestFormat);
-      entity = dataProvider.create(edmEntitySet);
+    final EdmEntityType edmEntityType = edmEntitySet.getEntityType();
+
+    Entity entity = dataProvider.create(edmEntitySet);
+    if (edmEntityType.hasStream()) {  // called from createMediaEntity(...), not directly
       dataProvider.setMedia(entity, odata.createFixedFormatDeserializer().binary(request.getBody()),
               requestFormat.toContentTypeString());
     } else {
-      throw new ODataApplicationException("Requested Entity is not a media resource.",
-          HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT);
+      dataProvider.update(edmEntitySet, entity,
+          odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
+              .entity(request.getBody(), edmEntityType),
+          false);
     }
 
     final ODataFormat format = ODataFormat.fromContentType(responseFormat);
     ODataSerializer serializer = odata.createSerializer(format);
-    response.setContent(serializer.entity(edmEntitySet.getEntityType(), entity,
+    response.setContent(serializer.entity(edmEntityType, entity,
         EntitySerializerOptions.with()
             .contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
                 getContextUrl(edmEntitySet, true, null, null))
@@ -191,14 +201,6 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
   }
 
   @Override
-  public void createEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo,
-      final ContentType requestFormat, final ContentType responseFormat)
-          throws ODataApplicationException, DeserializerException, SerializerException {
-    throw new ODataApplicationException("Entity creation is not supported yet.",
-        HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
-  }
-
-  @Override
   public void updateEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo,
       final ContentType requestFormat, final ContentType responseFormat)
           throws ODataApplicationException, DeserializerException, SerializerException {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6c4b3ea4/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
index 264febd..63d8550 100644
--- a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
+++ b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java
@@ -162,7 +162,7 @@ public class DataProviderTest {
     dataProvider.delete(esMedia, entity);
     Assert.assertEquals(3, dataProvider.readAll(esMedia).getEntities().size());
     entity = dataProvider.create(esMedia);
-    Assert.assertEquals(5, entity.getProperty("PropertyInt16").getValue());
+    Assert.assertEquals(3, entity.getProperty("PropertyInt16").getValue());
     dataProvider.setMedia(entity, new byte[] { 1, 2, 3, 4 }, "x/y");
     Assert.assertArrayEquals(new byte[] { 1, 2, 3, 4 }, dataProvider.readMedia(entity));
     Assert.assertEquals("x/y", entity.getMediaContentType());