You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ra...@apache.org on 2015/09/11 22:53:53 UTC

[1/2] olingo-odata4 git commit: OLINGO-700: added action parameter parsing rountines for atom and json payloads

Repository: olingo-odata4
Updated Branches:
  refs/heads/master ba88c43b5 -> fcec0c349


OLINGO-700: added action parameter parsing rountines for atom and json payloads


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

Branch: refs/heads/master
Commit: e99b07008ef021da592efd2c1f42662da4588abb
Parents: 11ebbb5
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Fri Sep 11 15:50:32 2015 -0500
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Fri Sep 11 15:50:32 2015 -0500

----------------------------------------------------------------------
 .../server/core/requests/ActionRequest.java     |  13 +-
 .../json/ODataJsonDeserializer.java             |   6 +-
 .../deserializer/xml/ODataXmlDeserializer.java  | 183 +++++++++--
 ...ataJsonDeserializerActionParametersTest.java | 140 +++++++++
 ...DataXMLDeserializerActionParametersTest.java | 303 +++++++++++++++++++
 5 files changed, 614 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e99b0700/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java
index bef9da0..9ff4cde 100644
--- a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/requests/ActionRequest.java
@@ -20,15 +20,20 @@
 package org.apache.olingo.server.core.requests;
 
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.olingo.commons.api.data.ContextURL;
+import org.apache.olingo.commons.api.data.Parameter;
 import org.apache.olingo.commons.api.edm.EdmAction;
 import org.apache.olingo.commons.api.edm.EdmReturnType;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.ODataApplicationException;
-import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ODataLibraryException;
+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.ODataDeserializer;
 import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
 import org.apache.olingo.server.api.uri.UriResourceAction;
 import org.apache.olingo.server.core.ContentNegotiatorException;
@@ -138,4 +143,10 @@ public class ActionRequest extends OperationRequest {
   public InputStream getPayload() {
     return getODataRequest().getBody();
   }
+  
+  public List<Parameter> getParameters() throws DeserializerException {
+    ODataDeserializer deserializer = odata.createDeserializer(getRequestContentType());
+    return new ArrayList<Parameter>(deserializer.actionParameters(getPayload(), getAction()).getActionParameters()
+        .values());
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e99b0700/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 759cf66..e2ea7cf 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
@@ -261,14 +261,14 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       case PRIMITIVE:
       case DEFINITION:
       case ENUM:
+      case COMPLEX:
         Parameter parameter = createParameter(node.get(paramName), paramName, edmParameter);
         parameters.put(paramName, parameter);
         node.remove(paramName);
         break;
-      case COMPLEX:
       case ENTITY:
-        throw new DeserializerException("Entity and complex parameters currently not Implemented",
-            DeserializerException.MessageKeys.NOT_IMPLEMENTED);
+        throw new DeserializerException("Entity parameters are not allowed",
+            DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE);
       default:
         throw new DeserializerException("Invalid type kind " + edmParameter.getType().getKind().toString()
             + " for action parameter: " + paramName, DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE,

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e99b0700/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
index 29c29e7..a762f5c 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
@@ -21,7 +21,9 @@ package org.apache.olingo.server.core.deserializer.xml;
 import java.io.InputStream;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.xml.namespace.QName;
 import javax.xml.stream.XMLEventReader;
@@ -38,6 +40,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.data.Valuable;
 import org.apache.olingo.commons.api.data.ValueType;
@@ -46,6 +49,7 @@ import org.apache.olingo.commons.api.edm.EdmComplexType;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.EdmEnumType;
 import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmParameter;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmProperty;
@@ -67,7 +71,8 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   private static final String ATOM = "a";
   private static final String NS_ATOM = "http://www.w3.org/2005/Atom";  
   private static final QName REF_ELEMENT = new QName("http://docs.oasis-open.org/odata/ns/metadata", "ref");
-//  private static final QName FEED_ELEMENT = new QName("http://www.w3.org/2005/Atom", "feed");
+  private static final QName PARAMETERS_ELEMENT = 
+      new QName("http://docs.oasis-open.org/odata/ns/metadata", "parameters");
   private static final QName ID_ATTR = new QName(NS_ATOM, ATOM);
 
   private final QName propertiesQName = new QName(Constants.NS_METADATA, Constants.PROPERTIES);
@@ -93,7 +98,8 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   }
 
   private Object primitive(final XMLEventReader reader, final StartElement start,
-      final EdmProperty edmProperty) throws XMLStreamException, EdmPrimitiveTypeException, 
+      final EdmType type, final boolean isNullable, final Integer maxLength, final Integer precision, 
+      final Integer scale, final boolean isUnicode) throws XMLStreamException, EdmPrimitiveTypeException, 
       DeserializerException {
 
     Object value = null;
@@ -103,18 +109,18 @@ public class ODataXmlDeserializer implements ODataDeserializer {
       final XMLEvent event = reader.nextEvent();
 
       if (event.isCharacters() && !event.asCharacters().isWhiteSpace()) {
-        if (edmProperty.getType() instanceof AbstractGeospatialType<?>) {
+        if (type instanceof AbstractGeospatialType<?>) {
           throw new DeserializerException("geo types support not implemented",
               DeserializerException.MessageKeys.NOT_IMPLEMENTED);
         }
         final String stringValue = event.asCharacters().getData();
-        value = ((EdmPrimitiveType)edmProperty.getType()).valueOfString(stringValue, 
-            edmProperty.isNullable(), 
-            edmProperty.getMaxLength(), 
-            edmProperty.getPrecision(), 
-            edmProperty.getScale(), 
-            edmProperty.isUnicode(), 
-            ((EdmPrimitiveType)edmProperty.getType()).getDefaultType());
+        value = ((EdmPrimitiveType)type).valueOfString(stringValue, 
+            isNullable, 
+            maxLength, 
+            precision, 
+            scale, 
+            isUnicode, 
+            ((EdmPrimitiveType)type).getDefaultType());
       }
 
       if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
@@ -132,7 +138,9 @@ public class ODataXmlDeserializer implements ODataDeserializer {
       final XMLEvent event = reader.nextEvent();
       if (event.isStartElement()) {
         StartElement se = event.asStartElement();
-        value.getValue().add(property(reader, se, (EdmProperty)edmComplex.getProperty(se.getName().getLocalPart())));
+        EdmProperty p = (EdmProperty)edmComplex.getProperty(se.getName().getLocalPart());
+        value.getValue().add(property(reader, se, p.getType(), p.isNullable(), p.getMaxLength(), 
+            p.getPrecision(), p.getScale(), p.isUnicode(), p.isCollection()));
       }
       if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
         foundEndProperty = true;
@@ -142,10 +150,12 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   }
 
   private void collection(final Valuable valuable, final XMLEventReader reader, final StartElement start,
-      final EdmProperty edmProperty) throws XMLStreamException, EdmPrimitiveTypeException, DeserializerException {
+      final EdmType type, final boolean isNullable, final Integer maxLength, final Integer precision,
+      final Integer scale, final boolean isUnicode) throws XMLStreamException, EdmPrimitiveTypeException,
+      DeserializerException {
 
     List<Object> values = new ArrayList<Object>();
-    EdmType edmType = edmProperty.getType();
+    EdmType edmType = type;
 
     boolean foundEndProperty = false;
     while (reader.hasNext() && !foundEndProperty) {
@@ -153,7 +163,8 @@ public class ODataXmlDeserializer implements ODataDeserializer {
 
       if (event.isStartElement()) {        
         if (edmType instanceof SingletonPrimitiveType) {
-          values.add(primitive(reader, event.asStartElement(), edmProperty));          
+          values.add(primitive(reader, event.asStartElement(), type, isNullable, 
+              maxLength, precision, scale, isUnicode));          
         } else if (edmType instanceof EdmComplexType) {
           values.add(complex(reader, event.asStartElement(), (EdmComplexType) edmType));                    
         } else if (edmType instanceof EdmEnumType) {
@@ -184,7 +195,9 @@ public class ODataXmlDeserializer implements ODataDeserializer {
     return value;
   }
 
-  private Property property(final XMLEventReader reader, final StartElement start, final EdmProperty edmProperty)
+  private Property property(final XMLEventReader reader, final StartElement start, final EdmType edmType,
+      final boolean isNullable, final Integer maxLength, final Integer precision,
+      final Integer scale, final boolean isUnicode, final boolean isCollection)
       throws XMLStreamException, EdmPrimitiveTypeException, DeserializerException {
 
     final Property property = new Property();
@@ -198,7 +211,7 @@ public class ODataXmlDeserializer implements ODataDeserializer {
     } else {
       property.setName(start.getName().getLocalPart());
     }
-    valuable(property, reader, start, edmProperty);
+    valuable(property, reader, start, edmType, isNullable, maxLength, precision, scale, isUnicode, isCollection);
     return property;
   }
 
@@ -215,8 +228,9 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   }
   
   private void valuable(final Valuable valuable, final XMLEventReader reader, final StartElement start,
-      EdmProperty edmProperty) throws XMLStreamException, EdmPrimitiveTypeException,
-      DeserializerException {
+      final EdmType edmType, final boolean isNullable, final Integer maxLength, final Integer precision,
+      final Integer scale, final boolean isUnicode, final boolean isCollection) throws XMLStreamException,
+      EdmPrimitiveTypeException, DeserializerException {
 
     final Attribute nullAttr = start.getAttributeByName(nullQName);
     if (nullAttr != null) {
@@ -228,23 +242,26 @@ public class ODataXmlDeserializer implements ODataDeserializer {
           foundEndProperty = true;
         }
       }
-      valuable.setValue(getValueType(edmProperty.getType(), false), null);  
+      valuable.setValue(getValueType(edmType, false), null);  
       return;
     }
 
-    EdmType edmType = edmProperty.getType();
-    if (edmProperty.isCollection()) {
-      collection(valuable, reader, start, edmProperty);
+    if (isCollection) {
+      collection(valuable, reader, start, edmType, isNullable, maxLength, precision, scale, isUnicode);
       valuable.setType("Collection("+edmType.getFullQualifiedName().getFullQualifiedNameAsString()+")");
     } else if (edmType instanceof SingletonPrimitiveType) {
       valuable.setType(edmType.getFullQualifiedName().getFullQualifiedNameAsString());
-      valuable.setValue(ValueType.PRIMITIVE, primitive(reader, start, edmProperty));          
+      valuable.setValue(ValueType.PRIMITIVE, 
+          primitive(reader, start, edmType, isNullable, maxLength, precision, scale, isUnicode));          
     } else if (edmType instanceof EdmComplexType) {
       valuable.setValue(ValueType.COMPLEX, complex(reader, start, (EdmComplexType) edmType));
       valuable.setType(edmType.getFullQualifiedName().getFullQualifiedNameAsString());
     } else if (edmType instanceof EdmEnumType) {
       valuable.setValue(ValueType.ENUM, readEnum(reader, start));
       valuable.setType(edmType.getFullQualifiedName().getFullQualifiedNameAsString());
+    } else if (edmType instanceof EdmEntityType) {
+      valuable.setValue(ValueType.ENTITY, entity(reader, start, (EdmEntityType)edmType));
+      valuable.setType(edmType.getFullQualifiedName().getFullQualifiedNameAsString());
     }
     // do not add null or empty values    
   }
@@ -255,7 +272,14 @@ public class ODataXmlDeserializer implements ODataDeserializer {
     try {
       final XMLEventReader reader = getReader(input);
       final StartElement start = skipBeforeFirstStartElement(reader);
-      Property property = property(reader, start, edmProperty);
+      Property property = property(reader, start, 
+          edmProperty.getType(), 
+          edmProperty.isNullable(),
+          edmProperty.getMaxLength(),
+          edmProperty.getPrecision(),
+          edmProperty.getScale(),
+          edmProperty.isUnicode(),
+          edmProperty.isCollection());
       return DeserializerResultImpl.with().property(property)
           .build();
     } catch (XMLStreamException e) {
@@ -409,7 +433,14 @@ public class ODataXmlDeserializer implements ODataDeserializer {
       if (event.isStartElement()) {
         EdmProperty edmProperty = (EdmProperty)edmEntityType
             .getProperty(event.asStartElement().getName().getLocalPart());
-        entity.getProperties().add(property(reader, event.asStartElement(), edmProperty));
+        entity.getProperties().add(property(reader, event.asStartElement(), 
+            edmProperty.getType(), 
+            edmProperty.isNullable(),
+            edmProperty.getMaxLength(),
+            edmProperty.getPrecision(),
+            edmProperty.getScale(),
+            edmProperty.isUnicode(),
+            edmProperty.isCollection()));
       }
 
       if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
@@ -683,6 +714,104 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   @Override
   public DeserializerResult actionParameters(InputStream stream, EdmAction edmAction) 
       throws DeserializerException {
-    throw new DeserializerException("Not implemented", DeserializerException.MessageKeys.NOT_IMPLEMENTED);
-  } 
+    Map<String, Parameter> parameters = new LinkedHashMap<String, Parameter>();
+    if(edmAction.getParameterNames() == null || edmAction.getParameterNames().isEmpty()
+        || (edmAction.isBound() && edmAction.getParameterNames().size() == 1)) {
+      return DeserializerResultImpl.with().actionParameters(parameters)
+          .build();
+    }
+        
+    try {             
+      final XMLEventReader reader = getReader(stream);
+      while (reader.hasNext()) {
+        final XMLEvent event = reader.nextEvent();
+        if (event.isStartElement() && PARAMETERS_ELEMENT.equals(event.asStartElement().getName())) {
+          consumeParameters(edmAction, reader, event.asStartElement(), parameters);
+        }        
+      }
+      // NULL fill for missing parameters
+      Parameter nullParameter = new Parameter();
+      nullParameter.setValue(ValueType.PRIMITIVE, null);
+      for (String param:edmAction.getParameterNames()) {
+        if (parameters.get(param) == null) {
+          parameters.put(param, nullParameter);
+        }
+      }      
+      return DeserializerResultImpl.with().actionParameters(parameters)
+          .build();
+    } catch (XMLStreamException e) {
+      throw new DeserializerException(e.getMessage(), e, DeserializerException.MessageKeys.IO_EXCEPTION);
+    } catch (final EdmPrimitiveTypeException e) {
+      throw new DeserializerException(e.getMessage(), e, 
+          DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);    
+    }
+  }
+
+  private void consumeParameters(EdmAction edmAction, XMLEventReader reader, 
+      StartElement start, Map<String, Parameter> parameters) throws DeserializerException, 
+      EdmPrimitiveTypeException, XMLStreamException {
+    
+    List<String> parameterNames = edmAction.getParameterNames();
+    if (edmAction.isBound()) {
+      // The binding parameter must not occur in the payload.
+      parameterNames = parameterNames.subList(1, parameterNames.size());
+    }
+    
+    boolean foundEndElement = false;    
+    while (reader.hasNext() && !foundEndElement) {
+      final XMLEvent event = reader.nextEvent();
+      if (event.isStartElement()) {
+        boolean found = false;
+        for(String paramName:parameterNames) {
+          if(paramName.equals(event.asStartElement().getName().getLocalPart())) {
+            found = true;
+            Parameter parameter = createParameter(reader, event.asStartElement(), paramName, 
+                edmAction.getParameter(paramName));
+            Parameter previous = parameters.put(paramName, parameter);
+            if (previous != null) {
+              throw new DeserializerException("Duplicate property detected", 
+                  DeserializerException.MessageKeys.DUPLICATE_PROPERTY);              
+            }
+            break; //for
+          }
+        }
+        if (!found) {
+          throw new DeserializerException("failed to read "+event.asStartElement().getName().getLocalPart(), 
+              DeserializerException.MessageKeys.UNKNOWN_CONTENT);          
+        }
+      }      
+      if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) {
+        foundEndElement = true;
+      }      
+    }    
+  }
+
+  private Parameter createParameter(XMLEventReader reader, StartElement start, String paramName, 
+      EdmParameter edmParameter) throws DeserializerException, EdmPrimitiveTypeException, XMLStreamException {
+    
+    switch (edmParameter.getType().getKind()) {
+    case PRIMITIVE:
+    case ENUM:
+    case COMPLEX:
+      Parameter parameter = new Parameter();
+      parameter.setName(paramName);
+      Property property = property(reader, start, 
+        edmParameter.getType(),
+        edmParameter.isNullable(), 
+        edmParameter.getMaxLength(), 
+        edmParameter.getPrecision(), 
+        edmParameter.getScale(), 
+        true,
+        edmParameter.isCollection());
+      parameter.setValue(property.getValueType(), property.getValue());
+      return parameter;
+    case ENTITY:
+      throw new DeserializerException("Entity parameters are not allowed",
+          DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE);
+    default:
+      throw new DeserializerException("Invalid type kind " + edmParameter.getType().getKind().toString()
+          + " for action parameter: " + paramName, DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE,
+          paramName);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e99b0700/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 3ed9f89..ab82684 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
@@ -20,17 +20,35 @@ package org.apache.olingo.server.core.deserializer.json;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
 
 import java.io.ByteArrayInputStream;
 import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 
+import org.apache.olingo.commons.api.data.ComplexValue;
+import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.Parameter;
+import org.apache.olingo.commons.api.edm.EdmAction;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.provider.CsdlAction;
+import org.apache.olingo.commons.api.edm.provider.CsdlComplexType;
+import org.apache.olingo.commons.api.edm.provider.CsdlEntityType;
+import org.apache.olingo.commons.api.edm.provider.CsdlParameter;
+import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
+import org.apache.olingo.commons.core.edm.EdmActionImpl;
+import org.apache.olingo.commons.core.edm.EdmComplexTypeImpl;
+import org.apache.olingo.commons.core.edm.EdmEntityTypeImpl;
+import org.apache.olingo.commons.core.edm.EdmProviderImpl;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 public class ODataJsonDeserializerActionParametersTest extends AbstractODataDeserializerTest {
 
@@ -55,7 +73,129 @@ public class ODataJsonDeserializerActionParametersTest extends AbstractODataDese
     assertNotNull(parameter);
     assertEquals(BigDecimal.valueOf(3669753), parameter.getValue());
   }
+  
+  @Test
+  public void complex() throws Exception {
+    EdmProviderImpl provider = mock(EdmProviderImpl.class);
+    CsdlComplexType address = new CsdlComplexType();
+    address.setProperties(Arrays.asList(createProperty("Street", "Edm.String"), 
+        createProperty("Zip", "Edm.Int32")));
+    address.setName("Address");
+    EdmComplexTypeImpl edmAddress = new EdmComplexTypeImpl(provider, 
+        new FullQualifiedName("namespace.Address"), address);    
+    Mockito.stub(provider.getComplexType(Mockito.any(FullQualifiedName.class))).toReturn(edmAddress);
+    
+    List<CsdlParameter> parameters = new ArrayList<CsdlParameter>();
+    parameters.add(createParam("param1", "Edm.Int16"));
+    parameters.add(createParam("param2", "namespace.Address"));
+    parameters.add(createParam("param3", "Edm.Int32").setCollection(true));
+    parameters.add(createParam("param4", "Edm.String").setNullable(true));
+    
+    FullQualifiedName actionName = new FullQualifiedName("namespace", "action");
+    CsdlAction csdlAction = new CsdlAction().setName("action1").setParameters(parameters);
+    EdmAction action = new EdmActionImpl(provider, actionName, csdlAction);
+    
+    final String input = "{\n" + 
+        "  \"param1\": 42,\n" + 
+        "  \"param2\": {\n" + 
+        "    \"Street\": \"One Microsoft Way\",\n" + 
+        "    \"Zip\": 98052\n" + 
+        "  },\n" + 
+        "  \"param3\": [ 1, 42, 99 ],\n" + 
+        "  \"param4\": null\n" + 
+        "}";
+    final Map<String, Parameter> response = OData.newInstance().createDeserializer(CONTENT_TYPE_JSON)
+        .actionParameters(new ByteArrayInputStream(input.getBytes()), action).getActionParameters();
+    
+    assertNotNull(response);
+    assertEquals(4, response.size());
+    Parameter parameter = response.get("param1");
+    assertNotNull(response);
+    assertEquals((short) 42, parameter.getValue());
+    parameter = response.get("param2");
+    assertNotNull(parameter);
+    ComplexValue addressValue = (ComplexValue)parameter.getValue();
+    assertEquals("Street", addressValue.getValue().get(0).getName());
+    assertEquals("One Microsoft Way", addressValue.getValue().get(0).getValue());
+    assertEquals("Zip", addressValue.getValue().get(1).getName());
+    assertEquals(98052, addressValue.getValue().get(1).getValue());
+    
+    parameter = response.get("param3");
+    assertNotNull(parameter);
+    assertEquals(Arrays.asList(1, 42, 99), parameter.getValue());
+    
+    parameter = response.get("param4");
+    assertNull(parameter.getValue());
+  }
+  
+  @Test
+  public void complexCollection() throws Exception {
+    EdmProviderImpl provider = mock(EdmProviderImpl.class);
+    CsdlComplexType address = new CsdlComplexType();
+    address.setProperties(Arrays.asList(createProperty("Street", "Edm.String"), 
+        createProperty("Zip", "Edm.Int32")));
+    address.setName("Address");
+    EdmComplexTypeImpl edmAddress = new EdmComplexTypeImpl(provider, 
+        new FullQualifiedName("namespace.Address"), address);    
+    Mockito.stub(provider.getComplexType(Mockito.any(FullQualifiedName.class))).toReturn(edmAddress);
+    
+    List<CsdlParameter> parameters = new ArrayList<CsdlParameter>();
+    parameters.add(createParam("param1", "Edm.Int16"));
+    parameters.add(createParam("param2", "namespace.Address").setCollection(true));
+    parameters.add(createParam("param3", "Edm.Int32").setCollection(true));
+    parameters.add(createParam("param4", "Edm.String").setNullable(true));
+    
+    FullQualifiedName actionName = new FullQualifiedName("namespace", "action");
+    CsdlAction csdlAction = new CsdlAction().setName("action1").setParameters(parameters);
+    EdmAction action = new EdmActionImpl(provider, actionName, csdlAction);
+    
+    final String input = "{\n" + 
+        "  \"param1\": 42,\n" + 
+        "  \"param2\": [{\n" + 
+        "    \"Street\": \"One Microsoft Way\",\n" + 
+        "    \"Zip\": 98052\n" + 
+        "  },\n" +
+        "  {\n" + 
+        "    \"Street\": \"Two Microsoft Way\",\n" + 
+        "    \"Zip\": 98052\n" + 
+        "  }],\n" +         
+        "  \"param3\": [ 1, 42, 99 ],\n" + 
+        "  \"param4\": null\n" + 
+        "}";
+    final Map<String, Parameter> response = OData.newInstance().createDeserializer(CONTENT_TYPE_JSON)
+        .actionParameters(new ByteArrayInputStream(input.getBytes()), action).getActionParameters();
+    
+    assertNotNull(response);
+    assertEquals(4, response.size());
+    Parameter parameter = response.get("param1");
+    assertNotNull(response);
+    assertEquals((short) 42, parameter.getValue());
+    parameter = response.get("param2");
+    assertNotNull(parameter);
+    ComplexValue addressValue = (ComplexValue)((List<?>)parameter.getValue()).get(0);
+    assertEquals("One Microsoft Way", addressValue.getValue().get(0).getValue());
+    assertEquals(98052, addressValue.getValue().get(1).getValue());
+
+    addressValue = (ComplexValue)((List<?>)parameter.getValue()).get(1);
+    assertEquals("Two Microsoft Way", addressValue.getValue().get(0).getValue());
+    assertEquals(98052, addressValue.getValue().get(1).getValue());
+    
+    parameter = response.get("param3");
+    assertNotNull(parameter);
+    assertEquals(Arrays.asList(1, 42, 99), parameter.getValue());
+    
+    parameter = response.get("param4");
+    assertNull(parameter.getValue());
+  }  
 
+  private CsdlParameter createParam(String name, String type) {
+    return new CsdlParameter().setName(name).setType(new FullQualifiedName(type));
+  }  
+
+  private CsdlProperty createProperty(String name, String type) {
+    return new CsdlProperty().setName(name).setType(type);
+  }
+  
   @Test
   public void boundEmpty() throws Exception {
     final String input = "{}";

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/e99b0700/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXMLDeserializerActionParametersTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXMLDeserializerActionParametersTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXMLDeserializerActionParametersTest.java
new file mode 100644
index 0000000..c63d036
--- /dev/null
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/ODataXMLDeserializerActionParametersTest.java
@@ -0,0 +1,303 @@
+/*
+ * 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.core.serializer.xml;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.data.ComplexValue;
+import org.apache.olingo.commons.api.data.Parameter;
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmAction;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.provider.CsdlAction;
+import org.apache.olingo.commons.api.edm.provider.CsdlComplexType;
+import org.apache.olingo.commons.api.edm.provider.CsdlParameter;
+import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.core.edm.EdmActionImpl;
+import org.apache.olingo.commons.core.edm.EdmComplexTypeImpl;
+import org.apache.olingo.commons.core.edm.EdmProviderImpl;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.deserializer.DeserializerException;
+import org.apache.olingo.server.api.edmx.EdmxReference;
+import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class ODataXMLDeserializerActionParametersTest {
+
+  @Test
+  public void empty() throws Exception {
+    final String input = "";
+    final Map<String, Parameter> parameters = deserialize(input, "UART");
+    assertNotNull(parameters);
+    assertTrue(parameters.isEmpty());
+  }
+
+  @Test
+  public void primitive() throws Exception {
+    final String input = "<?xml version='1.0' encoding='UTF-8'?>"
+        +"<metadata:parameters xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\">"        
+        +"<ParameterInt16>42</ParameterInt16>"
+        +"<ParameterDuration>P42DT11H22M33S</ParameterDuration>"
+        +"</metadata:parameters>";
+    
+    final Map<String, Parameter> parameters = deserialize(input, "UARTTwoParam");
+    assertNotNull(parameters);
+    assertEquals(2, parameters.size());
+    Parameter parameter = parameters.get("ParameterInt16");
+    assertNotNull(parameter);
+    assertEquals((short) 42, parameter.getValue());
+    parameter = parameters.get("ParameterDuration");
+    assertNotNull(parameter);
+    assertEquals(BigDecimal.valueOf(3669753), parameter.getValue());
+  }
+  
+  @Test
+  public void complex() throws Exception {
+    EdmProviderImpl provider = mock(EdmProviderImpl.class);
+    CsdlComplexType address = new CsdlComplexType();
+    address.setProperties(Arrays.asList(createProperty("Street", "Edm.String"), 
+        createProperty("Zip", "Edm.Int32")));
+    address.setName("Address");
+    EdmComplexTypeImpl edmAddress = new EdmComplexTypeImpl(provider, 
+        new FullQualifiedName("namespace.Address"), address);    
+    Mockito.stub(provider.getComplexType(Mockito.any(FullQualifiedName.class))).toReturn(edmAddress);
+    
+    List<CsdlParameter> parameters = new ArrayList<CsdlParameter>();
+    parameters.add(createParam("param1", "Edm.Int16"));
+    parameters.add(createParam("param2", "namespace.Address"));
+    parameters.add(createParam("param3", "Edm.Int32").setCollection(true));
+    parameters.add(createParam("param4", "Edm.String").setNullable(true));
+    
+    FullQualifiedName actionName = new FullQualifiedName("namespace", "action");
+    CsdlAction csdlAction = new CsdlAction().setName("action1").setParameters(parameters);
+    EdmAction action = new EdmActionImpl(provider, actionName, csdlAction);
+    
+    final String input = "<?xml version='1.0' encoding='UTF-8'?>" + 
+        "<metadata:parameters xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\">\n" + 
+        "  <param1>42</param1>\n" + 
+        "  <param2 metadata:type=\"#namespace.Address\">\n" + 
+        "    <Street>One Microsoft Way</Street>\n" + 
+        "    <Zip>98052</Zip>\n" + 
+        "  </param2>\n" + 
+        "  <param3>\n" + 
+        "    <element>1</element>\n" + 
+        "    <element>42</element>\n" + 
+        "    <element>99</element>\n" + 
+        "  </param3>\n" + 
+        "  <param4 metadata:null=\"true\"/>\n" + 
+        "</metadata:parameters>";
+    final Map<String, Parameter> response = OData.newInstance().createDeserializer(ContentType.APPLICATION_XML)
+        .actionParameters(new ByteArrayInputStream(input.getBytes()), action).getActionParameters();
+    
+    assertNotNull(response);
+    assertEquals(4, response.size());
+    Parameter parameter = response.get("param1");
+    assertNotNull(response);
+    assertEquals((short) 42, parameter.getValue());
+    parameter = response.get("param2");
+    assertNotNull(parameter);
+    ComplexValue addressValue = (ComplexValue)parameter.getValue();
+    assertEquals("Street", addressValue.getValue().get(0).getName());
+    assertEquals("One Microsoft Way", addressValue.getValue().get(0).getValue());
+    assertEquals("Zip", addressValue.getValue().get(1).getName());
+    assertEquals(98052, addressValue.getValue().get(1).getValue());
+    
+    parameter = response.get("param3");
+    assertNotNull(parameter);
+    assertEquals(Arrays.asList(1, 42, 99), parameter.getValue());
+    
+    parameter = response.get("param4");
+    assertNull(parameter.getValue());
+  }
+  
+  @Test
+  public void complexCollection() throws Exception {
+    EdmProviderImpl provider = mock(EdmProviderImpl.class);
+    CsdlComplexType address = new CsdlComplexType();
+    address.setProperties(Arrays.asList(createProperty("Street", "Edm.String"), 
+        createProperty("Zip", "Edm.Int32")));
+    address.setName("Address");
+    EdmComplexTypeImpl edmAddress = new EdmComplexTypeImpl(provider, 
+        new FullQualifiedName("namespace.Address"), address);    
+    Mockito.stub(provider.getComplexType(Mockito.any(FullQualifiedName.class))).toReturn(edmAddress);
+    
+    List<CsdlParameter> parameters = new ArrayList<CsdlParameter>();
+    parameters.add(createParam("param1", "Edm.Int16"));
+    parameters.add(createParam("param2", "namespace.Address").setCollection(true));
+    parameters.add(createParam("param3", "Edm.Int32").setCollection(true));
+    parameters.add(createParam("param4", "Edm.String").setNullable(true));
+    
+    FullQualifiedName actionName = new FullQualifiedName("namespace", "action");
+    CsdlAction csdlAction = new CsdlAction().setName("action1").setParameters(parameters);
+    EdmAction action = new EdmActionImpl(provider, actionName, csdlAction);
+    
+    final String input = "<?xml version='1.0' encoding='UTF-8'?>" + 
+        "<metadata:parameters xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\">\n" + 
+        "  <param1>42</param1>\n" + 
+        "  <param2 metadata:type=\"#namespace.Address\">\n" +
+        "    <element>" +
+        "    <Street>One Microsoft Way</Street>\n" + 
+        "    <Zip>98052</Zip>\n" +
+        "    </element>" +
+        "    <element>" +
+        "    <Street>Two Microsoft Way</Street>\n" + 
+        "    <Zip>98052</Zip>\n" +
+        "    </element>" +        
+        "  </param2>\n" + 
+        "  <param3>\n" + 
+        "    <element>1</element>\n" + 
+        "    <element>42</element>\n" + 
+        "    <element>99</element>\n" + 
+        "  </param3>\n" + 
+        "  <param4 metadata:null=\"true\"/>\n" + 
+        "</metadata:parameters>";
+    final Map<String, Parameter> response = OData.newInstance().createDeserializer(ContentType.APPLICATION_XML)
+        .actionParameters(new ByteArrayInputStream(input.getBytes()), action).getActionParameters();
+    
+    assertNotNull(response);
+    assertEquals(4, response.size());
+    Parameter parameter = response.get("param1");
+    assertNotNull(response);
+    assertEquals((short) 42, parameter.getValue());
+    parameter = response.get("param2");
+    assertNotNull(parameter);
+    ComplexValue addressValue = (ComplexValue)((List<?>)parameter.getValue()).get(0);
+    assertEquals("One Microsoft Way", addressValue.getValue().get(0).getValue());
+    assertEquals(98052, addressValue.getValue().get(1).getValue());
+
+    addressValue = (ComplexValue)((List<?>)parameter.getValue()).get(1);
+    assertEquals("Two Microsoft Way", addressValue.getValue().get(0).getValue());
+    assertEquals(98052, addressValue.getValue().get(1).getValue());
+    
+    parameter = response.get("param3");
+    assertNotNull(parameter);
+    assertEquals(Arrays.asList(1, 42, 99), parameter.getValue());
+    
+    parameter = response.get("param4");
+    assertNull(parameter.getValue());
+  } 
+
+  private CsdlParameter createParam(String name, String type) {
+    return new CsdlParameter().setName(name).setType(new FullQualifiedName(type));
+  }  
+
+  private CsdlProperty createProperty(String name, String type) {
+    return new CsdlProperty().setName(name).setType(type);
+  }
+  
+  @Test
+  public void boundEmpty() throws Exception {
+    final String input = "";
+    final Map<String, Parameter> parameters = deserialize(input, "BAETAllPrimRT", "ETAllPrim");
+    assertNotNull(parameters);
+    assertTrue(parameters.isEmpty());
+  }
+
+  @Test
+  public void testParameterWithNullLiteral() throws Exception {
+    final String input = "<?xml version='1.0' encoding='UTF-8'?>"
+        +"<metadata:parameters xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\">"        
+        +"<ParameterInt16>1</ParameterInt16>"
+        +"</metadata:parameters>";
+    
+    final Map<String, Parameter> parameters = deserialize(input, 
+        "UARTCollStringTwoParam");
+    assertNotNull(parameters);
+    assertEquals(2, parameters.size());
+    Parameter parameter = parameters.get("ParameterInt16");
+    assertNotNull(parameter);
+    assertEquals((short) 1, parameter.getValue());
+    parameter = parameters.get("ParameterDuration");
+    assertNotNull(parameter);
+    assertEquals(null, parameter.getValue());
+  }
+  
+  @Test
+  public void bindingParameter() throws Exception {
+    final String input = "<?xml version='1.0' encoding='UTF-8'?>"
+        +"<metadata:parameters xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\">"        
+        +"<ParameterETAllPrim>1</ParameterETAllPrim>"
+        +"</metadata:parameters>";    
+    deserialize(input, "BAETAllPrimRT", "ETAllPrim");
+  }
+
+  @Test(expected = DeserializerException.class)
+  public void wrongName() throws Exception {
+    final String input = "<?xml version='1.0' encoding='UTF-8'?>"
+        +"<metadata:parameters xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\">"        
+        +"<ParameterWrong>1</ParameterWrong>"
+        +"</metadata:parameters>";      
+    deserialize(input, "UARTParam");
+  }
+
+  @Test(expected = DeserializerException.class)
+  public void nullNotNullable() throws Exception {
+    final String input = "<?xml version='1.0' encoding='UTF-8'?>"
+        +"<metadata:parameters xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\">"        
+        +"<ParameterInt16>null</ParameterInt16>"
+        +"</metadata:parameters>";     
+    deserialize(input, "UARTCTTwoPrimParam");
+  }
+
+  @Test(expected = DeserializerException.class)
+  public void missingParameter() throws Exception {
+    deserialize("", "UARTCTTwoPrimParam");
+  }
+
+  @Test(expected = DeserializerException.class)
+  public void parameterTwice() throws Exception {
+    final String input = "<?xml version='1.0' encoding='UTF-8'?>"
+        +"<metadata:parameters xmlns:metadata=\"http://docs.oasis-open.org/odata/ns/metadata\">"        
+        +"<ParameterInt16>1</ParameterInt16>"
+        +"<ParameterInt16>2</ParameterInt16>"
+        +"</metadata:parameters>";      
+    deserialize(input, "UARTParam");
+  }
+  
+  protected static final Edm edm = OData.newInstance().createServiceMetadata(
+      new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
+  
+  private Map<String, Parameter> deserialize(final String input, final String actionName) throws DeserializerException {
+    return OData.newInstance().createDeserializer(ContentType.APPLICATION_XML)
+        .actionParameters(new ByteArrayInputStream(input.getBytes()),
+            edm.getUnboundAction(new FullQualifiedName("Namespace1_Alias", actionName))).getActionParameters();
+  }
+
+  private Map<String, Parameter> deserialize(final String input, final String actionName, final String typeName)
+      throws DeserializerException {
+    return OData.newInstance().createDeserializer(ContentType.APPLICATION_XML)
+        .actionParameters(new ByteArrayInputStream(input.getBytes()),
+            edm.getBoundAction(new FullQualifiedName("Namespace1_Alias", actionName),
+                new FullQualifiedName("Namespace1_Alias", typeName), false)).getActionParameters();
+  }
+}


[2/2] olingo-odata4 git commit: Merge branch 'OLINGO-700'

Posted by ra...@apache.org.
Merge branch 'OLINGO-700'


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

Branch: refs/heads/master
Commit: fcec0c349b9f64cf2db3d94aabcc2b4f8d4020f2
Parents: ba88c43 e99b070
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Fri Sep 11 15:51:17 2015 -0500
Committer: Ramesh Reddy <ra...@jboss.org>
Committed: Fri Sep 11 15:51:17 2015 -0500

----------------------------------------------------------------------
 .../server/core/requests/ActionRequest.java     |  13 +-
 .../json/ODataJsonDeserializer.java             |   6 +-
 .../deserializer/xml/ODataXmlDeserializer.java  | 183 +++++++++--
 ...ataJsonDeserializerActionParametersTest.java | 140 +++++++++
 ...DataXMLDeserializerActionParametersTest.java | 303 +++++++++++++++++++
 5 files changed, 614 insertions(+), 31 deletions(-)
----------------------------------------------------------------------