Repository: olingo-odata4
Updated Branches:
  refs/heads/master 34e518a6e -> cd23eb96f


[OLINGO-604] Implement Action imports in TechSvc part 1


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

Branch: refs/heads/master
Commit: cd23eb96f8f5c6e0fdb8c91ceef8187a2642ad9b
Parents: 34e518a
Author: Christian Amend <[email protected]>
Authored: Tue Apr 14 14:52:36 2015 +0200
Committer: Christian Amend <[email protected]>
Committed: Tue Apr 21 16:37:31 2015 +0200

----------------------------------------------------------------------
 .../api/deserializer/DeserializerResult.java    |   9 +-
 .../api/deserializer/ODataDeserializer.java     |   2 +-
 .../server/api/serializer/ODataSerializer.java  |   2 -
 .../server/api/uri/UriResourceAction.java       |   3 +-
 .../server/api/uri/UriResourceFunction.java     |   4 +-
 .../olingo/server/core/ContentNegotiator.java   |  25 +-
 .../apache/olingo/server/core/ODataHandler.java |   8 +-
 .../deserializer/DeserializerResultImpl.java    |  12 +-
 .../json/ODataJsonDeserializer.java             |  32 +--
 .../olingo/server/tecsvc/data/ActionData.java   | 242 +++++++++++++++++++
 .../olingo/server/tecsvc/data/DataCreator.java  |  39 ++-
 .../olingo/server/tecsvc/data/DataProvider.java |  17 +-
 .../TechnicalPrimitiveComplexProcessor.java     |  70 +++++-
 ...ataJsonDeserializerActionParametersTest.java |  20 +-
 14 files changed, 413 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerResult.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerResult.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerResult.java
index 9fcc3fc..c58612a 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerResult.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerResult.java
@@ -20,12 +20,13 @@ package org.apache.olingo.server.api.deserializer;
 
 import java.net.URI;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Parameter;
-import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
 import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
 
 /**
  * Result type for {@link ODataDeserializer} methods
@@ -53,7 +54,11 @@ public interface DeserializerResult {
    * Returns the deserialized action-parameters of an {@link Entity} object.
    * @return a collection {@link Parameter}
    */
-  List<Parameter> getActionParameter();
+  /**
+   * Returns the deserialized action-parameters as key value pairs.
+   * @return the action parameters
+   */
+  Map<String, Parameter> getActionParameters();
 
   /**
    * Returns a Property or collections of properties (primitive & complex)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/ODataDeserializer.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/ODataDeserializer.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/ODataDeserializer.java
index 5a927ed..c6ba000 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/ODataDeserializer.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/ODataDeserializer.java
@@ -56,7 +56,7 @@ public interface ODataDeserializer {
    * Validates: parameter types, no double parameters, correct json types.
    * @param stream
    * @param edmAction
-   * @return {@link DeserializerResult#getActionParameter()}
+   * @return {@link DeserializerResult#getActionParameters()}
    * @throws DeserializerException
    */
   DeserializerResult actionParameters(InputStream stream, EdmAction edmAction) 
throws DeserializerException;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
index 3a2fbe0..c7f7bba 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
@@ -18,8 +18,6 @@
  */
 package org.apache.olingo.server.api.serializer;
 
-import java.io.InputStream;
-
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Property;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
index 3ba7ce7..e916ce5 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
@@ -28,7 +28,8 @@ import org.apache.olingo.commons.api.edm.EdmActionImport;
 public interface UriResourceAction extends UriResourcePartTyped {
 
   /**
-   * @return Action used in the resource path
+   * If the resource path specifies an action import this method will deliver 
the unbound action for the action import.
+   * @return Action used in the resource path or action import
    */
   EdmAction getAction();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceFunction.java
----------------------------------------------------------------------
diff --git 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceFunction.java
 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceFunction.java
index 00db971..1caf000 100644
--- 
a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceFunction.java
+++ 
b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceFunction.java
@@ -31,7 +31,9 @@ import java.util.List;
 public interface UriResourceFunction extends UriResourcePartTyped {
 
   /**
-   * @return Function used in the resource path
+   * If the resource path specifies a function import this method will deliver 
the unbound function for the function
+   * import.
+   * @return Function used in the resource path or function import
    */
   EdmFunction getFunction();
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
index 6a9d770..351b769 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java
@@ -49,13 +49,14 @@ public class ContentNegotiator {
     default:
       return Arrays.asList(
           ODataFormat.JSON.getContentType(),
-          ODataFormat.JSON_NO_METADATA.getContentType());
+          ODataFormat.JSON_NO_METADATA.getContentType(),
+          ODataFormat.APPLICATION_JSON.getContentType());
     }
   }
 
   private static List<ContentType> getSupportedContentTypes(
       final CustomContentTypeSupport customContentTypeSupport, final 
RepresentationType representationType)
-          throws ContentNegotiatorException {
+      throws ContentNegotiatorException {
     final List<ContentType> defaultSupportedContentTypes = 
getDefaultSupportedContentTypes(representationType);
     final List<ContentType> result = customContentTypeSupport == null ? 
defaultSupportedContentTypes :
         
customContentTypeSupport.modifySupportedContentTypes(defaultSupportedContentTypes,
 representationType);
@@ -69,7 +70,7 @@ public class ContentNegotiator {
 
   public static ContentType doContentNegotiation(final FormatOption 
formatOption, final ODataRequest request,
       final CustomContentTypeSupport customContentTypeSupport, final 
RepresentationType representationType)
-          throws ContentNegotiatorException {
+      throws ContentNegotiatorException {
     final List<ContentType> supportedContentTypes =
         getSupportedContentTypes(customContentTypeSupport, representationType);
     final String acceptHeaderValue = request.getHeader(HttpHeader.ACCEPT);
@@ -79,15 +80,15 @@ public class ContentNegotiator {
       final String formatString = formatOption.getFormat().trim();
       final ODataFormat format =
           ODataFormat.JSON.name().equalsIgnoreCase(formatString) ? 
ODataFormat.JSON :
-          ODataFormat.XML.name().equalsIgnoreCase(formatString) ? 
ODataFormat.XML :
-          ODataFormat.ATOM.name().equalsIgnoreCase(formatString) ? 
ODataFormat.ATOM : null;
+              ODataFormat.XML.name().equalsIgnoreCase(formatString) ? 
ODataFormat.XML :
+                  ODataFormat.ATOM.name().equalsIgnoreCase(formatString) ? 
ODataFormat.ATOM : null;
       try {
         result = getAcceptedType(
             AcceptType.fromContentType(format == null ?
                 ContentType.create(formatOption.getFormat()) : 
format.getContentType()),
             supportedContentTypes);
       } catch (final IllegalArgumentException e) {
-        //Exception results in result = null for next check.
+        // Exception results in result = null for next check.
       }
       if (result == null) {
         throw new ContentNegotiatorException("Unsupported $format = " + 
formatString,
@@ -142,9 +143,8 @@ public class ContentNegotiator {
 
   public static void checkSupport(final ContentType contentType,
       final CustomContentTypeSupport customContentTypeSupport, final 
RepresentationType representationType)
-          throws ContentNegotiatorException {
-    for (final ContentType supportedContentType :
-      getSupportedContentTypes(customContentTypeSupport, representationType)) {
+      throws ContentNegotiatorException {
+    for (ContentType supportedContentType : 
getSupportedContentTypes(customContentTypeSupport, representationType)) {
       if 
(AcceptType.fromContentType(supportedContentType).get(0).matches(contentType)) {
         return;
       }
@@ -154,11 +154,10 @@ public class ContentNegotiator {
   }
 
   public static boolean isSupported(final ContentType contentType,
-                                  final CustomContentTypeSupport 
customContentTypeSupport,
-                                  final RepresentationType representationType) 
throws ContentNegotiatorException {
+      final CustomContentTypeSupport customContentTypeSupport,
+      final RepresentationType representationType) throws 
ContentNegotiatorException {
 
-    for (final ContentType supportedContentType :
-            getSupportedContentTypes(customContentTypeSupport, 
representationType)) {
+    for (ContentType supportedContentType : 
getSupportedContentTypes(customContentTypeSupport, representationType)) {
       if 
(AcceptType.fromContentType(supportedContentType).get(0).matches(contentType)) {
         return true;
       }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
index b01970d..ad0bba0 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
@@ -322,7 +322,7 @@ public class ODataHandler {
               .processActionEntity(request, response, uriInfo, requestFormat, 
responseFormat);
         }
         break;
-          
+
       case PRIMITIVE:
         responseFormat = 
ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
             request, customContentTypeSupport,
@@ -623,11 +623,7 @@ public class ODataHandler {
 
   private void checkContentTypeSupport(ContentType requestFormat, 
RepresentationType representationType)
       throws ODataHandlerException, ContentNegotiatorException {
-    if (!ContentNegotiator.isSupported(requestFormat, 
customContentTypeSupport, representationType)) {
-      final String contentTypeString = requestFormat.toContentTypeString();
-      throw new ODataHandlerException("ContentType " + contentTypeString + " 
is not supported.",
-          ODataHandlerException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, 
contentTypeString);
-    }
+    ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, 
representationType);
   }
 
   private void validateODataVersion(final ODataRequest request, final 
ODataResponse response)

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/DeserializerResultImpl.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/DeserializerResultImpl.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/DeserializerResultImpl.java
index 1c85f3e..acfbe69 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/DeserializerResultImpl.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/DeserializerResultImpl.java
@@ -20,7 +20,9 @@ package org.apache.olingo.server.core.deserializer;
 
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
@@ -34,7 +36,7 @@ public class DeserializerResultImpl implements 
DeserializerResult {
   private EntityCollection entitySet;
   private ExpandOption expandOption;
   private Property property;
-  private List<Parameter> actionParametes;
+  private Map<String, Parameter> actionParametes;
   private List<URI> entityReferences;
   
   private DeserializerResultImpl() {}
@@ -55,7 +57,7 @@ public class DeserializerResultImpl implements 
DeserializerResult {
   }
   
   @Override
-  public List<Parameter> getActionParameter() {
+  public Map<String, Parameter> getActionParameters() {
     return actionParametes;
   }
 
@@ -78,7 +80,7 @@ public class DeserializerResultImpl implements 
DeserializerResult {
     private EntityCollection entitySet;
     private ExpandOption expandOption;
     private Property property;
-    private List<Parameter> actionParametes;
+    private Map<String, Parameter> actionParametes;
     private List<URI> entityReferences;
     
     public DeserializerResult build() {
@@ -88,7 +90,7 @@ public class DeserializerResultImpl implements 
DeserializerResult {
       result.expandOption = expandOption;
       result.property = property;
       result.entityReferences = (entityReferences == null) ? new 
ArrayList<URI>() : entityReferences;
-      result.actionParametes = (actionParametes == null) ? new 
ArrayList<Parameter>() : actionParametes;
+      result.actionParametes = (actionParametes == null) ? new 
LinkedHashMap<String, Parameter>() : actionParametes;
       
       return result;
     }
@@ -118,7 +120,7 @@ public class DeserializerResultImpl implements 
DeserializerResult {
       return this;
     }
     
-    public DeserializerResultBuilder actionParameters(final List<Parameter> 
actionParameters) {
+    public DeserializerResultBuilder actionParameters(final Map<String, 
Parameter> actionParameters) {
       this.actionParametes = actionParameters;
       return this;
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
----------------------------------------------------------------------
diff --git 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
index d92ac0c..66da3fc 100644
--- 
a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
+++ 
b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
@@ -24,6 +24,7 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -191,9 +192,11 @@ public class ODataJsonDeserializer implements 
ODataDeserializer {
       throws DeserializerException {
     try {
       ObjectNode tree = parseJsonTree(stream);
-      List<Parameter> parameters = new ArrayList<Parameter>();
-      consumeParameters(edmAction, tree, parameters);
-      assertJsonNodeIsEmpty(tree);
+      Map<String, Parameter> parameters = new LinkedHashMap<String, 
Parameter>();
+      if (tree != null) {
+        consumeParameters(edmAction, tree, parameters);
+        assertJsonNodeIsEmpty(tree);
+      }
       return 
DeserializerResultImpl.with().actionParameters(parameters).build();
 
     } catch (final JsonParseException e) {
@@ -217,18 +220,18 @@ public class ODataJsonDeserializer implements 
ODataDeserializer {
     return tree;
   }
 
-  private void consumeParameters(final EdmAction edmAction, ObjectNode node, 
List<Parameter> parameters)
+  private void consumeParameters(final EdmAction edmAction, ObjectNode node, 
Map<String, Parameter> parameters)
       throws DeserializerException {
     List<String> parameterNames = edmAction.getParameterNames();
     if (edmAction.isBound()) {
       // The binding parameter must not occur in the payload.
       parameterNames = parameterNames.subList(1, parameterNames.size());
     }
-    for (final String name : parameterNames) {
-      final EdmParameter edmParameter = edmAction.getParameter(name);
+    for (final String paramName : parameterNames) {
+      final EdmParameter edmParameter = edmAction.getParameter(paramName);
       Parameter parameter = new Parameter();
-      parameter.setName(name);
-      JsonNode jsonNode = node.get(name);
+      parameter.setName(paramName);
+      JsonNode jsonNode = node.get(paramName);
 
       switch (edmParameter.getType().getKind()) {
       case PRIMITIVE:
@@ -237,11 +240,11 @@ public class ODataJsonDeserializer implements 
ODataDeserializer {
         if (jsonNode == null || jsonNode.isNull()) {
           if (!edmParameter.isNullable()) {
             throw new DeserializerException("Non-nullable parameter not 
present or null",
-                DeserializerException.MessageKeys.INVALID_NULL_PARAMETER, 
name);
+                DeserializerException.MessageKeys.INVALID_NULL_PARAMETER, 
paramName);
           }
           if (edmParameter.isCollection()) {
-            throw new DeserializerException("Collection must not be null for 
parameter: " + name,
-                DeserializerException.MessageKeys.INVALID_NULL_PARAMETER, 
name);
+            throw new DeserializerException("Collection must not be null for 
parameter: " + paramName,
+                DeserializerException.MessageKeys.INVALID_NULL_PARAMETER, 
paramName);
           }
           parameter.setValue(ValueType.PRIMITIVE, null);
         } else {
@@ -250,8 +253,8 @@ public class ODataJsonDeserializer implements 
ODataDeserializer {
                   edmParameter.isNullable(), edmParameter.getMaxLength(), 
edmParameter.getPrecision(), edmParameter
                       .getScale(), true, edmParameter.getMapping(), jsonNode);
           parameter.setValue(consumePropertyNode.getValueType(), 
consumePropertyNode.getValue());
-          parameters.add(parameter);
-          node.remove(name);
+          parameters.put(paramName, parameter);
+          node.remove(paramName);
         }
         break;
       case COMPLEX:
@@ -260,7 +263,8 @@ public class ODataJsonDeserializer implements 
ODataDeserializer {
             DeserializerException.MessageKeys.NOT_IMPLEMENTED);
       default:
         throw new DeserializerException("Invalid type kind " + 
edmParameter.getType().getKind().toString()
-            + " for action parameter: " + name, 
DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE, name);
+            + " for action parameter: " + paramName, 
DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE,
+            paramName);
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
new file mode 100644
index 0000000..d2a8525
--- /dev/null
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.tecsvc.data;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.data.EntityCollection;
+import org.apache.olingo.commons.api.data.Parameter;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.data.ValueType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.tecsvc.data.DataProvider.DataProviderException;
+
+public class ActionData {
+
+  protected static Property primitiveAction(String name, Map<String, 
Parameter> parameters)
+      throws DataProviderException {
+    if ("UARTString".equals(name)) {
+      return DataCreator.createPrimitive(null, "UARTString string value");
+    }
+    throw new DataProviderException("Action " + name + " is not yet 
implemented.");
+  }
+
+  protected static Property primitiveCollectionAction(String name, Map<String, 
Parameter> parameters)
+      throws DataProviderException {
+    if ("UARTCollStringTwoParam".equals(name)) {
+      List<Object> collectionValues = new ArrayList<Object>();
+      int loopCount = (Integer) parameters.get("ParameterInt16").asPrimitive();
+      EdmPrimitiveType primDuration = 
OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Duration);
+      BigDecimal duration = (BigDecimal) 
parameters.get("ParameterDuration").asPrimitive();
+      BigDecimal addValue = new BigDecimal(1);
+      for (int i = 0; i < loopCount; i++) {
+        try {
+          String value = primDuration.valueToString(duration, false, null, 
null, null, null);
+          collectionValues.add(value);
+        } catch (EdmPrimitiveTypeException e) {
+          throw new DataProviderException("EdmPrimitiveTypeException", e);
+        }
+        duration = duration.add(addValue);
+      }
+      return DataCreator.createPrimitiveCollection(null, collectionValues);
+    }
+    throw new DataProviderException("Action " + name + " is not yet 
implemented.");
+  }
+
+  protected static Property complexAction(String name, Map<String, Parameter> 
parameters) throws DataProviderException {
+    if ("UARTCTTwoPrimParam".equals(name)) {
+      Integer number = (Integer) 
parameters.get("ParameterInt16").asPrimitive();
+      if (number == null) {
+        number = new Integer(32767);
+      }
+      Property complexProp = createCTTwoPrimComplexProperty(number, 
"UARTCTTwoPrimParam string value");
+
+      return complexProp;
+    }
+    throw new DataProviderException("Action " + name + " is not yet 
implemented.");
+  }
+
+  private static Property createCTTwoPrimComplexProperty(Integer number, 
String text) {
+    List<Property> props = new ArrayList<Property>();
+    Property propInt = new Property();
+    propInt.setName("PropertyInt16");
+    propInt.setValue(ValueType.PRIMITIVE, number);
+    props.add(propInt);
+    Property propString = new Property();
+    propString.setName("PropertyString");
+    propString.setValue(ValueType.PRIMITIVE, text);
+    props.add(propString);
+
+    Property complexProp = new Property();
+    complexProp.setValue(ValueType.COMPLEX, props);
+    return complexProp;
+  }
+
+  protected static Property complexCollectionAction(String name, Map<String, 
Parameter> parameters)
+      throws DataProviderException {
+    if ("UARTCollCTTwoPrimParam".equals(name)) {
+      ArrayList<Property> complexCollection = new ArrayList<Property>();
+      complexCollection.add(createCTTwoPrimComplexProperty(16, "Test123"));
+      complexCollection.add(createCTTwoPrimComplexProperty(17, "Test456"));
+      complexCollection.add(createCTTwoPrimComplexProperty(18, "Test678"));
+
+      Integer number = (Integer) 
parameters.get("ParameterInt16").asPrimitive();
+      if (number != null && number >= 0 && number < complexCollection.size()) {
+        complexCollection.subList(number, complexCollection.size() - 
1).clear();
+      }
+
+      Property complexCollProperty = new Property();
+      complexCollProperty.setValue(ValueType.COLLECTION_COMPLEX, 
complexCollection);
+      return complexCollProperty;
+    }
+    throw new DataProviderException("Action " + name + " is not yet 
implemented.");
+  }
+
+  protected static Entity entityAction(String name, Map<String, Parameter> 
parameters) throws DataProviderException {
+    if ("UARTETTwoKeyTwoPrimParam".equals(name)) {
+      Integer number = (Integer) 
parameters.get("ParameterInt16").asPrimitive();
+      if (number == null) {
+        number = 0;
+      }
+      EntityCollection entityCollection = new 
DataCreator().getData().get("ESTwoKeyTwoPrim");
+      for (Entity entity : entityCollection.getEntities()) {
+        if (number.equals(entity.getProperty("PropertyInt16").asPrimitive())) {
+          return entity;
+        }
+      }
+      // Entity Not found
+      throw new DataProviderException("Entity not found with key: " + number, 
HttpStatusCode.NOT_FOUND);
+    } else if ("UARTETAllPrimParam".equals(name)) {
+      Calendar date = (Calendar) parameters.get("ParameterDate").asPrimitive();
+      EntityCollection entityCollection = new 
DataCreator().getData().get("ESAllPrim");
+      if (date != null) {
+        boolean freeKey;
+        Short key = 0;
+        do {
+          freeKey = true;
+          for (Entity entity : entityCollection.getEntities()) {
+            if (key.equals(entity.getProperty("PropertyInt16"))) {
+              freeKey = false;
+              break;
+            }
+          }
+          key++;
+        } while (!freeKey);
+        // TODO: Set create response code
+        return createAllPrimEntity(key, "UARTETAllPrimParam string value", 
date);
+      } else {
+        return entityCollection.getEntities().get(0);
+      }
+    }
+    throw new DataProviderException("Action " + name + " is not yet 
implemented.");
+  }
+
+  private static Entity createAllPrimEntity(Short key, String val, Calendar 
date) {
+    return new 
Entity().addProperty(DataCreator.createPrimitive("PropertyInt16", key))
+        .addProperty(DataCreator.createPrimitive("PropertyString", val))
+        .addProperty(DataCreator.createPrimitive("PropertyBoolean", false))
+        .addProperty(DataCreator.createPrimitive("PropertyByte", null))
+        .addProperty(DataCreator.createPrimitive("PropertySByte", null))
+        .addProperty(DataCreator.createPrimitive("PropertyInt32", null))
+        .addProperty(DataCreator.createPrimitive("PropertyInt64", null))
+        .addProperty(DataCreator.createPrimitive("PropertySingle", null))
+        .addProperty(DataCreator.createPrimitive("PropertyDouble", null))
+        .addProperty(DataCreator.createPrimitive("PropertyDecimal", null))
+        .addProperty(DataCreator.createPrimitive("PropertyBinary", null))
+        .addProperty(DataCreator.createPrimitive("PropertyDate", date))
+        .addProperty(DataCreator.createPrimitive("PropertyDateTimeOffset", 
null))
+        .addProperty(DataCreator.createPrimitive("PropertyDuration", null))
+        .addProperty(DataCreator.createPrimitive("PropertyGuid", null))
+        .addProperty(DataCreator.createPrimitive("PropertyTimeOfDay", null));
+  }
+
+  protected static EntityCollection entityCollectionAction(String name, 
Map<String, Parameter> parameters)
+      throws DataProviderException {
+    if ("UARTCollETKeyNavParam".equals(name)) {
+      Short number = (Short) parameters.get("ParameterInt16").asPrimitive();
+      EntityCollection collection = new EntityCollection();
+      if (number != null && number > 0) {
+        for (int i = 1; i <= number; i++) {
+          collection.getEntities().add(createETKeyNavEntity(number));
+        }
+      } else {
+        return collection;
+      }
+    } else if ("UARTCollETAllPrimParam".equals(name)) {
+      Calendar timeOfDay = (Calendar) 
parameters.get("ParameterTimeOfDay").asPrimitive();
+      EntityCollection collection = new EntityCollection();
+      if (timeOfDay != null) {
+        int count = timeOfDay.get(Calendar.HOUR_OF_DAY);
+        for (short i = 1; i <= count; i++) {
+          collection.getEntities().add(createAllPrimEntity(i, 
"UARTCollETAllPrimParam int16 value: " + i, null));
+        }
+      } else {
+        return collection;
+      }  
+    }
+    throw new DataProviderException("Action " + name + " is not yet 
implemented.");
+  }
+
+  @SuppressWarnings("unchecked")
+  private static Entity createETKeyNavEntity(Short number) {
+    return new Entity()
+        .addProperty(DataCreator.createPrimitive("PropertyInt16", number))
+        .addProperty(DataCreator.createPrimitive("PropertyString", 
"UARTCollETKeyNavParam int16 value: " + number))
+        .addProperty(
+            DataCreator.createComplex("PropertyCompNav", 
DataCreator.createPrimitive("PropertyInt16", 0)))
+        
.addProperty(createKeyNavAllPrimComplexValue("PropertyCompAllPrim")).addProperty(
+            DataCreator.createComplex("PropertyCompTwoPrim", 
DataCreator.createPrimitive("PropertyInt16", 0),
+                DataCreator.createPrimitive("PropertyString", 
""))).addProperty(
+            DataCreator.createPrimitiveCollection("CollPropertyString"))
+        
.addProperty(DataCreator.createPrimitiveCollection("CollPropertyInt16")).addProperty(
+            DataCreator.createComplexCollection("CollPropertyComp"))
+        .addProperty(
+            DataCreator.createComplex("PropertyCompCompNav", 
DataCreator.createPrimitive("PropertyString", ""),
+                DataCreator.createComplex("PropertyCompNav", 
DataCreator.createPrimitive("PropertyInt16", 0))));
+  }
+
+  protected static Property createKeyNavAllPrimComplexValue(final String name) 
{
+    return DataCreator.createComplex(name,
+        DataCreator.createPrimitive("PropertyString", ""),
+        DataCreator.createPrimitive("PropertyBinary", new byte[] {}),
+        DataCreator.createPrimitive("PropertyBoolean", false),
+        DataCreator.createPrimitive("PropertyByte", 0),
+        DataCreator.createPrimitive("PropertyDate", null),
+        DataCreator.createPrimitive("PropertyDateTimeOffset", null),
+        DataCreator.createPrimitive("PropertyDecimal", 0),
+        DataCreator.createPrimitive("PropertySingle", 0),
+        DataCreator.createPrimitive("PropertyDouble", 0),
+        DataCreator.createPrimitive("PropertyDuration", 0),
+        DataCreator.createPrimitive("PropertyGuid", null),
+        DataCreator.createPrimitive("PropertyInt16", null),
+        DataCreator.createPrimitive("PropertyInt32", null),
+        DataCreator.createPrimitive("PropertyInt64", null),
+        DataCreator.createPrimitive("PropertySByte", null),
+        DataCreator.createPrimitive("PropertyTimeOfDay", null));
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/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 3cef7e6..37b7752 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
@@ -57,6 +57,7 @@ public class DataCreator {
     data.put("ESTwoKeyNav", createESTwoKeyNav());
     data.put("ESCompCollComp", createESCompCollComp());
     data.put("ESServerSidePaging", createESServerSidePaging());
+    data.put("ESTwoKeyTwoPrim", createESTwoKeyTwoPrim());
 
     // No data available but to allow an insert operation create empty 
EntitySets
     data.put("ESAllNullable", new EntityCollection());
@@ -64,7 +65,6 @@ public class DataCreator {
     data.put("ESTwoBase", new EntityCollection());
     data.put("ESBaseTwoKeyNav", new EntityCollection());
     data.put("ESBaseTwoKeyTwoPrim", new EntityCollection());
-    data.put("ESTwoKeyTwoPrim", new EntityCollection());
     data.put("ESCompCollAllPrim", new EntityCollection());
     data.put("ESKeyTwoKeyComp", new EntityCollection());
     data.put("ESFourKeyAlias", new EntityCollection());
@@ -83,6 +83,19 @@ public class DataCreator {
     return data;
   }
 
+  private EntityCollection createESTwoKeyTwoPrim() {
+    EntityCollection entitySet = new EntityCollection();
+    entitySet.getEntities().add(createETTwoKeyTwoPrimEntity(32767, "Test 
String1"));
+    entitySet.getEntities().add(createETKeyNavEntity(-365, "Test String2"));
+    entitySet.getEntities().add(createETKeyNavEntity(-32766, "Test String3"));
+    return entitySet;
+  }
+
+  private Entity createETTwoKeyTwoPrimEntity(int propertyInt16, String 
propertyString) {
+    return new Entity().addProperty(createPrimitive("PropertyInt16", 
propertyInt16))
+        .addProperty(createPrimitive("PropertyString", propertyString));
+  }
+
   private EntityCollection createESServerSidePaging() {
     EntityCollection entitySet = new EntityCollection();
 
@@ -136,8 +149,10 @@ public class DataCreator {
 
   @SuppressWarnings("unchecked")
   private Entity createESTwoKeyNavEntity(int propertyInt16, String 
propertyString) {
-    return new Entity().addProperty(createPrimitive("PropertyInt16", 
propertyInt16))
-        .addProperty(createPrimitive("PropertyString", 
propertyString)).addProperty(
+    return new Entity()
+        .addProperty(createPrimitive("PropertyInt16", propertyInt16))
+        .addProperty(createPrimitive("PropertyString", propertyString))
+        .addProperty(
             createComplex("PropertyComp", createPrimitive("PropertyInt16", 11),
                 createComplex("PropertyComp", 
createPrimitive("PropertyString", "StringValue"),
                     createPrimitive("PropertyBinary", new byte[] { 1, 35, 69, 
103, -119, -85, -51, -17 }),
@@ -149,7 +164,8 @@ public class DataCreator {
                     createPrimitive("PropertyInt16", Short.MAX_VALUE),
                     createPrimitive("PropertyInt32", Integer.MAX_VALUE),
                     createPrimitive("PropertyInt64", Long.MAX_VALUE), 
createPrimitive("PropertySByte", Byte.MAX_VALUE),
-                    createPrimitive("PropertyTimeOfDay", getTime(21, 5, 
59))))).addProperty(
+                    createPrimitive("PropertyTimeOfDay", getTime(21, 5, 59)))))
+        .addProperty(
             createComplex("PropertyCompNav", createPrimitive("PropertyInt16", 
1),
                 createKeyNavAllPrimComplexValue("PropertyComp")))
         .addProperty(createComplexCollection("CollPropertyComp"))
@@ -159,7 +175,7 @@ public class DataCreator {
                 createPrimitive("PropertyString", "11")));
   }
 
-  private Property createKeyNavAllPrimComplexValue(final String name) {
+  protected Property createKeyNavAllPrimComplexValue(final String name) {
     return createComplex(name, createPrimitive("PropertyString", "First 
Resource - positive values"),
         createPrimitive("PropertyBinary", new byte[] { 1, 35, 69, 103, -119, 
-85, -51, -17 }),
         createPrimitive("PropertyBoolean", true), 
createPrimitive("PropertyByte", 255),
@@ -335,7 +351,7 @@ public class DataCreator {
             
3.2100000000000000E+03)).addProperty(createPrimitiveCollection("CollPropertyDecimal",
 12, -2, 1234))
         .addProperty(
             createPrimitiveCollection("CollPropertyBinary", new byte[] { 
(byte) 0xAB, (byte) 0xCD, (byte) 0xEF }, new
-                    byte[] { 0x01, 0x23, 0x45 },
+                byte[] { 0x01, 0x23, 0x45 },
                 new byte[] { 0x54, 0x67, (byte) 0x89 })).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(
@@ -362,7 +378,8 @@ public class DataCreator {
   }
 
   private EntityCollection createESMixPrimCollComp() {
-    @SuppressWarnings("unchecked") final Property complexCollection = 
createComplexCollection("CollPropertyComp",
+    @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")));
@@ -522,7 +539,7 @@ public class DataCreator {
     setLink(entitySet.getEntities().get(0), "NavPropertyETMediaOne", 
esMediaTargets.get(0));
     setLink(entitySet.getEntities().get(1), "NavPropertyETMediaOne", 
esMediaTargets.get(1));
     setLink(entitySet.getEntities().get(2), "NavPropertyETMediaOne", 
esMediaTargets.get(2));
-    
+
     // NavPropertyETMediaMany
     setLinks(entitySet.getEntities().get(0), "NavPropertyETMediaMany", 
esMediaTargets.get(0), esMediaTargets.get(2));
     setLinks(entitySet.getEntities().get(1), "NavPropertyETMediaMany", 
esMediaTargets.get(2));
@@ -583,7 +600,7 @@ public class DataCreator {
     return new Property(null, name, ValueType.COLLECTION_COMPLEX, 
complexCollection);
   }
 
-  private Calendar getDateTime(final int year, final int month, final int day,
+  private static 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"));
     dateTime.clear();
@@ -591,7 +608,7 @@ public class DataCreator {
     return dateTime;
   }
 
-  private Calendar getTime(final int hour, final int minute, final int second) 
{
+  private static Calendar getTime(final int hour, final int minute, final int 
second) {
     Calendar time = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
     time.clear();
     time.set(Calendar.HOUR_OF_DAY, hour);
@@ -600,7 +617,7 @@ public class DataCreator {
     return time;
   }
 
-  private Timestamp getTimestamp(final int year, final int month, final int 
day,
+  private static Timestamp getTimestamp(final int year, final int month, final 
int day,
       final int hour, final int minute, final int second, final int 
nanosecond) {
     Timestamp timestamp = new Timestamp(getDateTime(year, month, day, hour, 
minute, second).getTimeInMillis());
     timestamp.setNanos(nanosecond);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/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 6bf79fa..878efce 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
@@ -31,6 +31,7 @@ import org.apache.olingo.commons.api.data.ComplexValue;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Link;
+import org.apache.olingo.commons.api.data.Parameter;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
@@ -72,8 +73,9 @@ public class DataProvider {
     return entitySet == null ? null : read(edmEntitySet.getEntityType(), 
entitySet, keys);
   }
 
-  public Entity read(final EdmEntityType edmEntityType, final EntityCollection 
entitySet, final List<UriParameter> keys)
-      throws DataProviderException {
+  public Entity
+      read(final EdmEntityType edmEntityType, final EntityCollection 
entitySet, final List<UriParameter> keys)
+          throws DataProviderException {
     try {
       for (final Entity entity : entitySet.getEntities()) {
         boolean found = true;
@@ -488,6 +490,16 @@ public class DataProvider {
     return FunctionData.primitiveComplexFunction(function.getName(), 
parameters, data);
   }
 
+  public Property processActionPrimitive(String name, Map<String, Parameter> 
actionParameters)
+      throws DataProviderException {
+    return ActionData.primitiveAction(name, actionParameters);
+  }
+
+  public Property processActionPrimitiveCollection(String name, Map<String, 
Parameter> actionParameters)
+      throws DataProviderException {
+    return ActionData.primitiveCollectionAction(name, actionParameters);
+  }
+
   public void setEdm(final Edm edm) {
     this.edm = edm;
   }
@@ -511,4 +523,5 @@ public class DataProvider {
       super(message, statusCode.getStatusCode(), Locale.ROOT);
     }
   }
+
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
----------------------------------------------------------------------
diff --git 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
index 303800f..d811670 100644
--- 
a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
+++ 
b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java
@@ -27,6 +27,7 @@ import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.data.ContextURL.Builder;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.edm.EdmAction;
 import org.apache.olingo.commons.api.edm.EdmComplexType;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
@@ -45,6 +46,7 @@ import org.apache.olingo.server.api.ODataRequest;
 import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
+import org.apache.olingo.server.api.deserializer.DeserializerResult;
 import org.apache.olingo.server.api.processor.ActionComplexCollectionProcessor;
 import org.apache.olingo.server.api.processor.ActionComplexProcessor;
 import 
org.apache.olingo.server.api.processor.ActionPrimitiveCollectionProcessor;
@@ -61,10 +63,12 @@ import 
org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
 import org.apache.olingo.server.api.serializer.PrimitiveValueSerializerOptions;
 import org.apache.olingo.server.api.serializer.RepresentationType;
 import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.api.serializer.SerializerResult;
 import org.apache.olingo.server.api.uri.UriHelper;
 import org.apache.olingo.server.api.uri.UriInfo;
 import org.apache.olingo.server.api.uri.UriInfoResource;
 import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.UriResourceAction;
 import org.apache.olingo.server.api.uri.UriResourceFunction;
 import org.apache.olingo.server.api.uri.UriResourceKind;
 import org.apache.olingo.server.api.uri.UriResourceProperty;
@@ -110,8 +114,43 @@ public class TechnicalPrimitiveComplexProcessor extends 
TechnicalProcessor
   public void processActionPrimitive(final ODataRequest request, final 
ODataResponse response,
       final UriInfo uriInfo, final ContentType requestFormat, final 
ContentType responseFormat)
       throws ODataApplicationException, DeserializerException, 
SerializerException {
-    throw new ODataApplicationException("Not supported yet.",
-        HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
+    EdmAction action = checkBoundAndExtractAction(uriInfo);
+    DeserializerResult deserializerResult =
+        odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
+            .actionParameters(request.getBody(), action);
+
+    Property property = dataProvider.processActionPrimitive(action.getName(), 
deserializerResult.getActionParameters());
+    EdmPrimitiveType type = (EdmPrimitiveType) 
action.getReturnType().getType();
+    if (property.isNull()) {
+      if (action.getReturnType().isNullable()) {
+        response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
+      } else {
+        // Not nullable return type so we have to give back a 500
+        throw new ODataApplicationException("The action could no be executed", 
500, Locale.ROOT);
+      }
+    } else {
+      ContextURL contextURL = ContextURL.with().type(type).build();
+      PrimitiveSerializerOptions options = 
PrimitiveSerializerOptions.with().contextURL(contextURL).build();
+
+      SerializerResult result = 
odata.createSerializer(ODataFormat.fromContentType(responseFormat)).primitive(type,
+          property, options);
+
+      response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+      response.setContent(result.getContent());
+      response.setHeader(HttpHeader.CONTENT_TYPE, 
responseFormat.toContentTypeString());
+    }
+  }
+
+  private EdmAction checkBoundAndExtractAction(final UriInfo uriInfo) throws 
ODataApplicationException {
+    final UriInfoResource resource = uriInfo.asUriInfoResource();
+    List<UriResource> uriResourceParts = resource.getUriResourceParts();
+    if (uriResourceParts.size() > 1) {
+      throw new ODataApplicationException("Bound acctions not supported yet.",
+          HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
+    }
+    UriResourceAction uriResourceAction = (UriResourceAction) 
uriResourceParts.get(0);
+    EdmAction action = uriResourceAction.getAction();
+    return action;
   }
 
   @Override
@@ -188,8 +227,31 @@ public class TechnicalPrimitiveComplexProcessor extends 
TechnicalProcessor
   public void processActionComplexCollection(ODataRequest request, 
ODataResponse response,
       UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat)
       throws ODataApplicationException, DeserializerException, 
SerializerException {
-    throw new ODataApplicationException("Not supported yet.",
-        HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
+    EdmAction action = checkBoundAndExtractAction(uriInfo);
+    DeserializerResult deserializerResult =
+        odata.createDeserializer(ODataFormat.fromContentType(requestFormat))
+            .actionParameters(request.getBody(), action);
+
+    Property property = dataProvider.processActionPrimitive(action.getName(), 
deserializerResult.getActionParameters());
+
+    if (property.isNull()) {
+      // Collection Propertys must never be null
+      throw new ODataApplicationException("The action could no be executed", 
500, Locale.ROOT);
+    } else if (property.asCollection().contains(null) && 
!action.getReturnType().isNullable()) {
+      // Not nullable return type but array contains a null value
+      throw new ODataApplicationException("The action could no be executed", 
500, Locale.ROOT);
+    }
+    EdmComplexType type = (EdmComplexType) action.getReturnType().getType();
+    ContextURL contextURL = 
ContextURL.with().type(type).asCollection().build();
+    ComplexSerializerOptions options = 
ComplexSerializerOptions.with().contextURL(contextURL).build();
+
+    SerializerResult result =
+        
odata.createSerializer(ODataFormat.fromContentType(responseFormat)).complexCollection(serviceMetadata,
 type,
+            property, options);
+
+    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+    response.setContent(result.getContent());
+    response.setHeader(HttpHeader.CONTENT_TYPE, 
responseFormat.toContentTypeString());
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cd23eb96/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
----------------------------------------------------------------------
diff --git 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
index 80c7c47..01166a2 100644
--- 
a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
+++ 
b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerActionParametersTest.java
@@ -24,7 +24,7 @@ import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayInputStream;
 import java.math.BigDecimal;
-import java.util.List;
+import java.util.Map;
 
 import org.apache.olingo.commons.api.data.Parameter;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
@@ -38,7 +38,7 @@ public class ODataJsonDeserializerActionParametersTest 
extends AbstractODataDese
   @Test
   public void empty() throws Exception {
     final String input = "{}";
-    final List<Parameter> parameters = deserialize(input, "UART");
+    final Map<String, Parameter> parameters = deserialize(input, "UART");
     assertNotNull(parameters);
     assertTrue(parameters.isEmpty());
   }
@@ -46,13 +46,13 @@ public class ODataJsonDeserializerActionParametersTest 
extends AbstractODataDese
   @Test
   public void primitive() throws Exception {
     final String input = 
"{\"ParameterDuration\":\"P42DT11H22M33S\",\"ParameterInt16\":42}";
-    final List<Parameter> parameters = deserialize(input, "UARTTwoParam");
+    final Map<String, Parameter> parameters = deserialize(input, 
"UARTTwoParam");
     assertNotNull(parameters);
     assertEquals(2, parameters.size());
-    Parameter parameter = parameters.get(0);
+    Parameter parameter = parameters.get("ParameterInt16");
     assertNotNull(parameter);
     assertEquals((short) 42, parameter.getValue());
-    parameter = parameters.get(1);
+    parameter = parameters.get("ParameterDuration");
     assertNotNull(parameter);
     assertEquals(BigDecimal.valueOf(3669753), parameter.getValue());
   }
@@ -60,7 +60,7 @@ public class ODataJsonDeserializerActionParametersTest 
extends AbstractODataDese
   @Test
   public void boundEmpty() throws Exception {
     final String input = "{}";
-    final List<Parameter> parameters = deserialize(input, "BAETAllPrimRT", 
"ETAllPrim");
+    final Map<String, Parameter> parameters = deserialize(input, 
"BAETAllPrimRT", "ETAllPrim");
     assertNotNull(parameters);
     assertTrue(parameters.isEmpty());
   }
@@ -95,17 +95,17 @@ public class ODataJsonDeserializerActionParametersTest 
extends AbstractODataDese
     deserialize("{\"ParameterInt16\":\"42\"}", "UARTParam");
   }
 
-  private List<Parameter> deserialize(final String input, final String 
actionName) throws DeserializerException {
+  private Map<String, Parameter> deserialize(final String input, final String 
actionName) throws DeserializerException {
     return OData.newInstance().createDeserializer(ODataFormat.JSON)
         .actionParameters(new ByteArrayInputStream(input.getBytes()),
-            edm.getUnboundAction(new FullQualifiedName("Namespace1_Alias", 
actionName))).getActionParameter();
+            edm.getUnboundAction(new FullQualifiedName("Namespace1_Alias", 
actionName))).getActionParameters();
   }
 
-  private List<Parameter> deserialize(final String input, final String 
actionName, final String typeName)
+  private Map<String, Parameter> deserialize(final String input, final String 
actionName, final String typeName)
       throws DeserializerException {
     return OData.newInstance().createDeserializer(ODataFormat.JSON)
         .actionParameters(new ByteArrayInputStream(input.getBytes()),
             edm.getBoundAction(new FullQualifiedName("Namespace1_Alias", 
actionName),
-                new FullQualifiedName("Namespace1_Alias", typeName), 
false)).getActionParameter();
+                new FullQualifiedName("Namespace1_Alias", typeName), 
false)).getActionParameters();
   }
 }

Reply via email to