diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ActionImportITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ActionImportITCase.java index 00d55ad0a..1aada74b1 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ActionImportITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ActionImportITCase.java @@ -39,6 +39,7 @@ import org.apache.olingo.client.api.domain.ClientCollectionValue; import org.apache.olingo.client.api.domain.ClientComplexValue; import org.apache.olingo.client.api.domain.ClientEntity; import org.apache.olingo.client.api.domain.ClientEntitySet; +import org.apache.olingo.client.api.domain.ClientObjectFactory; import org.apache.olingo.client.api.domain.ClientProperty; import org.apache.olingo.client.api.domain.ClientValue; import org.apache.olingo.client.core.ODataClientFactory; @@ -113,9 +114,9 @@ public class ActionImportITCase extends AbstractBaseTestITCase { ClientCollectionValue valueArray = response.getBody().getCollectionValue(); assertEquals(3, valueArray.size()); Iterator iterator = valueArray.iterator(); - assertEquals("PT1S", iterator.next().asPrimitive().toValue()); - assertEquals("PT2S", iterator.next().asPrimitive().toValue()); - assertEquals("PT3S", iterator.next().asPrimitive().toValue()); + assertEquals("UARTCollStringTwoParam duration value: PT1S", iterator.next().asPrimitive().toValue()); + assertEquals("UARTCollStringTwoParam duration value: PT2S", iterator.next().asPrimitive().toValue()); + assertEquals("UARTCollStringTwoParam duration value: PT3S", iterator.next().asPrimitive().toValue()); } @Test @@ -324,7 +325,47 @@ public class ActionImportITCase extends AbstractBaseTestITCase { assertEquals(location, response.getHeader(HttpHeader.LOCATION).iterator().next()); assertEquals(location, response.getHeader(HttpHeader.ODATA_ENTITY_ID).iterator().next()); } + + @Test + public void airtCollStringTwoParanNotNull() { + final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI) + .appendActionCallSegment("AIRTCollStringTwoParam").build(); + final Map parameters = new HashMap(); + final ClientObjectFactory of = getClient().getObjectFactory(); + parameters.put("ParameterInt16", of.newPrimitiveValueBuilder().buildInt16((short) 2)); + parameters.put("ParameterDuration", of.newPrimitiveValueBuilder().buildDuration(BigDecimal.valueOf(1))); + final ODataInvokeResponse response = getClient() + .getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class, parameters).execute(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); + ClientCollectionValue collectionValue = response.getBody().getCollectionValue().asCollection(); + assertEquals(2, collectionValue.size()); + final Iterator iter = collectionValue.iterator(); + + assertEquals("UARTCollStringTwoParam duration value: PT1S", iter.next().asPrimitive().toValue()); + assertEquals("UARTCollStringTwoParam duration value: PT2S", iter.next().asPrimitive().toValue()); + } + + @Test + public void airtCollStringTwoParanNull() { + final URI actionURI = getClient().newURIBuilder(TecSvcConst.BASE_URI) + .appendActionCallSegment("AIRTCollStringTwoParam").build(); + final Map parameters = new HashMap(); + final ClientObjectFactory of = getClient().getObjectFactory(); + parameters.put("ParameterInt16", of.newPrimitiveValueBuilder().buildInt16((short) 2)); + parameters.put("ParameterDuration", of.newPrimitiveValueBuilder().buildDuration(null)); + final ODataInvokeResponse response = getClient() + .getInvokeRequestFactory().getActionInvokeRequest(actionURI, ClientProperty.class, parameters).execute(); + + assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); + ClientCollectionValue collectionValue = response.getBody().getCollectionValue().asCollection(); + assertEquals(2, collectionValue.size()); + final Iterator iter = collectionValue.iterator(); + assertEquals("UARTCollStringTwoParam int16 value: 2", iter.next().asPrimitive().toValue()); + assertEquals("UARTCollStringTwoParam duration value: null", iter.next().asPrimitive().toValue()); + } + @Override protected ODataClient getClient() { ODataClient odata = ODataClientFactory.getClient(); diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FunctionImportITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FunctionImportITCase.java index f2ea75e1f..eb45765f8 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FunctionImportITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FunctionImportITCase.java @@ -22,17 +22,22 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.olingo.client.api.ODataClient; import org.apache.olingo.client.api.communication.request.invoke.ODataInvokeRequest; +import org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataRawRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataValueRequest; import org.apache.olingo.client.api.communication.response.ODataInvokeResponse; import org.apache.olingo.client.api.communication.response.ODataRawResponse; import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; +import org.apache.olingo.client.api.domain.ClientCollectionValue; +import org.apache.olingo.client.api.domain.ClientComplexValue; import org.apache.olingo.client.api.domain.ClientEntity; import org.apache.olingo.client.api.domain.ClientEntitySet; import org.apache.olingo.client.api.domain.ClientPrimitiveValue; @@ -220,6 +225,77 @@ public class FunctionImportITCase extends AbstractBaseTestITCase { assertEquals("UFCRTCTTwoPrim string value", response.getBody().toValue()); } + @Test + public void testFICRTStringTwoParamNotNull() { + final Map keys = new HashMap(); + keys.put("ParameterInt16", 3); + keys.put("ParameterString", "ab"); + + ODataPropertyRequest request = getClient().getRetrieveRequestFactory() + .getPropertyRequest(getClient().newURIBuilder(TecSvcConst.BASE_URI) + .appendPropertySegment("FICRTStringTwoParam").appendKeySegment(keys).build()); + final ODataRetrieveResponse response = request.execute(); + assertEquals("\"ab\",\"ab\",\"ab\"", response.getBody().getPrimitiveValue().toValue()); + } + + @Test + public void testFICRTStringTwoParamNull() { + final Map keys = new HashMap(); + keys.put("ParameterInt16", 1); + + ODataPropertyRequest request = getClient().getRetrieveRequestFactory() + .getPropertyRequest(getClient().newURIBuilder(TecSvcConst.BASE_URI) + .appendPropertySegment("FICRTStringTwoParam").appendKeySegment(keys).build()); + final ODataRetrieveResponse response = request.execute(); + assertEquals(HttpStatusCode.NO_CONTENT.getStatusCode(), response.getStatusCode()); + } + + @Test + public void testFICRTCollCTTwoPrimTwoParamNotNull() { + final Map keys = new HashMap(); + keys.put("ParameterInt16", 2); + keys.put("ParameterString", "TestString"); + + ODataPropertyRequest request = getClient().getRetrieveRequestFactory() + .getPropertyRequest(getClient().newURIBuilder(TecSvcConst.BASE_URI) + .appendEntitySetSegment("FICRTCollCTTwoPrimTwoParam").appendKeySegment(keys).build()); + final ODataRetrieveResponse response = request.execute(); + final ClientCollectionValue collection = response.getBody().getCollectionValue().asCollection(); + final Iterator iter = collection.iterator(); + + ClientComplexValue complexValue = iter.next().asComplex(); + assertEquals(1, complexValue.get("PropertyInt16").getPrimitiveValue().toValue()); + assertEquals("UFCRTCollCTTwoPrimTwoParam string value: TestString", complexValue.get("PropertyString") + .getPrimitiveValue().toValue()); + complexValue = iter.next().asComplex(); + assertEquals(2, complexValue.get("PropertyInt16").getPrimitiveValue().toValue()); + assertEquals("UFCRTCollCTTwoPrimTwoParam string value: TestString", complexValue.get("PropertyString") + .getPrimitiveValue().toValue()); + } + + @Test + public void testFICRTCollCTTwoPrimTwoParamNull() { + final Map keys = new HashMap(); + keys.put("ParameterInt16", 2); + keys.put("ParameterString", null); + + ODataPropertyRequest request = getClient().getRetrieveRequestFactory() + .getPropertyRequest(getClient().newURIBuilder(TecSvcConst.BASE_URI) + .appendEntitySetSegment("FICRTCollCTTwoPrimTwoParam").appendKeySegment(keys).build()); + final ODataRetrieveResponse response = request.execute(); + final ClientCollectionValue collection = response.getBody().getCollectionValue().asCollection(); + final Iterator iter = collection.iterator(); + + ClientComplexValue complexValue = iter.next().asComplex(); + assertEquals(1, complexValue.get("PropertyInt16").getPrimitiveValue().toValue()); + assertEquals("UFCRTCollCTTwoPrimTwoParam int16 value: 2", complexValue.get("PropertyString") + .getPrimitiveValue().toValue()); + complexValue = iter.next().asComplex(); + assertEquals(2, complexValue.get("PropertyInt16").getPrimitiveValue().toValue()); + assertEquals("UFCRTCollCTTwoPrimTwoParamstring value: null", complexValue.get("PropertyString") + .getPrimitiveValue().toValue()); + } + @Override protected ODataClient getClient() { ODataClient odata = ODataClientFactory.getClient(); diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientPrimitiveValue.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientPrimitiveValue.java index 445af8435..cd3339ce8 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientPrimitiveValue.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ClientPrimitiveValue.java @@ -57,6 +57,8 @@ public interface ClientPrimitiveValue extends ClientValue { ClientPrimitiveValue buildBinary(byte[] value); ClientPrimitiveValue buildDecimal(BigDecimal value); + + ClientPrimitiveValue buildDuration(BigDecimal value); } EdmPrimitiveTypeKind getTypeKind(); diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java index e6f7fa614..1c18c0200 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/domain/ClientPrimitiveValueImpl.java @@ -139,6 +139,11 @@ public class ClientPrimitiveValueImpl extends AbstractClientValue implements Cli return setType(EdmPrimitiveTypeKind.Decimal).setValue(value).build(); } + @Override + public ClientPrimitiveValue buildDuration(BigDecimal value) { + return setType(EdmPrimitiveTypeKind.Duration).setValue(value).build(); + } + } /** diff --git a/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriLexer.g4 b/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriLexer.g4 index a74fd2fba..f2ec3787b 100644 --- a/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriLexer.g4 +++ b/lib/server-core/src/main/antlr4/org/apache/olingo/server/core/uri/antlr/UriLexer.g4 @@ -112,10 +112,10 @@ REF : '$ref'; COUNT : '$count'; //inlined query parameters ( e.g. $skip) -TOP_I : '$top' -> type(TOP); -SKIP_QO_I : '$skip' -> type(SKIP_QO); +TOP_I : '$top' -> type(TOP); +SKIP_QO_I : '$skip' -> type(SKIP_QO); FILTER_I : '$filter' -> type(FILTER); -ORDERBY_I : '$orderby' -> type(ORDERBY); +ORDERBY_I : '$orderby'-> type(ORDERBY); SELECT_I : '$select' -> type(SELECT); EXPAND_I : '$expand' -> type(EXPAND); LEVELS_I : '$levels' -> type(LEVELS); 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 71e50301d..84beb61c7 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 @@ -274,6 +274,8 @@ public class ODataJsonDeserializer implements ODataDeserializer { DeserializerException.MessageKeys.INVALID_NULL_PARAMETER, paramName); } parameter.setValue(ValueType.PRIMITIVE, null); + parameters.put(paramName, parameter); + node.remove(paramName); } else { Property consumePropertyNode = consumePropertyNode(edmParameter.getName(), edmParameter.getType(), edmParameter.isCollection(), @@ -859,7 +861,6 @@ public class ODataJsonDeserializer implements ODataDeserializer { throw new DeserializerException("Value must be an array", DeserializerException.MessageKeys.UNKNOWN_CONTENT); } tree.remove(Constants.VALUE); - // if this is value there can be only one property return DeserializerResultImpl.with().entityReferences(parsedValues).build(); } if (tree.get(key) != null) { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java index 803b0ad62..16aa42e44 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java @@ -1636,7 +1636,8 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor { uriParameter.setName(ctx.vODI.getText()); if (ctx.vCOM != null) { - uriParameter.setText(ctx.vCOM.getText()); + final String text = ctx.vCOM.getText(); + uriParameter.setText("null".equals(text) ? null : text); uriParameter.setExpression((ExpressionImpl) ctx.vCOM.accept(this)); } else { uriParameter.setAlias("@" + ctx.vALI.getText()); 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 index 81a723a6c..6d7a41f45 100644 --- 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 @@ -20,6 +20,7 @@ package org.apache.olingo.server.tecsvc.data; import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.Map; @@ -52,9 +53,18 @@ public class ActionData { if ("UARTCollStringTwoParam".equals(name)) { Parameter paramInt16 = parameters.get("ParameterInt16"); Parameter paramDuration = parameters.get("ParameterDuration"); - if (paramInt16 == null || paramDuration == null) { - throw new DataProviderException("Missing parameters for action: UARTCollStringTwoParam", - HttpStatusCode.BAD_REQUEST); + if ((paramInt16 == null || paramInt16.isNull()) || (paramDuration == null || paramDuration.isNull())) { + try { + String param16String = valueAsString(paramInt16, EdmPrimitiveTypeKind.Int16); + String paramDurationString = valueAsString(paramDuration, EdmPrimitiveTypeKind.Duration); + + return new Property(null, name, ValueType.COLLECTION_PRIMITIVE, Arrays.asList(new String[] { + name + " int16 value: " + param16String, + name + " duration value: " + paramDurationString + })); + } catch(EdmPrimitiveTypeException e) { + throw new DataProviderException("EdmPrimitiveTypeException", e); + } } short loopCount = (Short) paramInt16.asPrimitive(); BigDecimal duration = (BigDecimal) paramDuration.asPrimitive(); @@ -64,7 +74,7 @@ public class ActionData { for (int i = 0; i < loopCount; i++) { try { String value = primDuration.valueToString(duration, false, null, null, null, null); - collectionValues.add(value); + collectionValues.add(name + " duration value: " + value); } catch (EdmPrimitiveTypeException e) { throw new DataProviderException("EdmPrimitiveTypeException", e); } @@ -75,6 +85,13 @@ public class ActionData { throw new DataProviderException("Action " + name + " is not yet implemented."); } + private static String valueAsString(final Parameter parameter, final EdmPrimitiveTypeKind kind) + throws EdmPrimitiveTypeException { + return parameter == null ? "null" + : OData.newInstance().createPrimitiveTypeInstance(kind) + .valueToString(parameter.asPrimitive(), null, null, null, null, null); + } + protected static Property complexAction(final String name, final Map parameters) throws DataProviderException { if ("UARTCTTwoPrimParam".equals(name)) { 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 341a7b1f5..759516c70 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 @@ -698,7 +698,7 @@ public class DataCreator { createPrimitive("PropertyByte", (short) 255), createPrimitive("PropertyDate", getDateTime(2014, 12, 5, 0, 0, 0)), createPrimitive("PropertyDateTimeOffset", getTimestamp(2014, 12, 5, 8, 17, 45, 123456700)), - createPrimitive("PropertyDecimal", 17.98), + createPrimitive("PropertyDecimal", BigDecimal.valueOf(17.98)), createPrimitive("PropertySingle", 1.79000000E+20), createPrimitive("PropertyDouble", -1.7900000000000000E+02), createPrimitive("PropertyDuration", BigDecimal.valueOf(6)), @@ -710,7 +710,29 @@ public class DataCreator { createPrimitive("PropertyTimeOfDay", getTime(13, 27, 45)))); entity.setETag("W/\"0\""); entityCollection.getEntities().add(entity); - + + entity = new Entity() + .addProperty(createPrimitive("PropertyInt16", (short) -32768)) + .addProperty(createComplex("PropertyComp", + createPrimitive("PropertyString", null), + createPrimitive("PropertyBinary", null), + createPrimitive("PropertyBoolean", null), + createPrimitive("PropertyByte", null), + createPrimitive("PropertyDate", null), + createPrimitive("PropertyDateTimeOffset", null), + createPrimitive("PropertyDecimal", null), + createPrimitive("PropertySingle", null), + createPrimitive("PropertyDouble", null), + createPrimitive("PropertyDuration", null), + createPrimitive("PropertyGuid", null), + createPrimitive("PropertyInt16", null), + createPrimitive("PropertyInt32", null), + createPrimitive("PropertyInt64", null), + createPrimitive("PropertySByte", null), + createPrimitive("PropertyTimeOfDay", null))); + entity.setETag("W/\"-32768\""); + entityCollection.getEntities().add(entity); + return entityCollection; } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java index 238dd8b53..65099dc16 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/FunctionData.java @@ -18,13 +18,17 @@ */ package org.apache.olingo.server.tecsvc.data; +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.EntityCollection; 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.server.api.OData; @@ -108,6 +112,78 @@ public class FunctionData { DataCreator.createPrimitive("PropertyString", "Test456")), Arrays.asList(DataCreator.createPrimitive("PropertyInt16", 18), DataCreator.createPrimitive("PropertyString", "Test678"))); + } else if(name.equals("UFCRTStringTwoParam")) { + final String parameterStringRaw = getParameterText("ParameterString", parameters); + final String parameterInt16Raw = getParameterText("ParameterInt16", parameters); + + // ParameterString is not provided + if(parameterStringRaw == null) { + return new Property(null, "value", ValueType.PRIMITIVE, null); + } else { + try { + EdmPrimitiveType edmInt16 = OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16); + EdmPrimitiveType edmString = OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String); + Short parameterInt16 = edmInt16.valueOfString(parameterInt16Raw, null, null, null, null, null, Short.class); + String parameterString = edmString.fromUriLiteral(parameterStringRaw); + final StringBuilder builder = new StringBuilder(); + + // if parameterInt16 <= 0 return an empty string + for(short i = parameterInt16; i > 0; i--) { + if(builder.length() != 0) { + builder.append(','); + } + builder.append('"'); + builder.append(parameterString); + builder.append('"'); + } + return new Property(null, "value", ValueType.PRIMITIVE, builder.toString()); + } catch (EdmPrimitiveTypeException e) { + throw new DataProviderException("Invalid function parameter."); + } + } + } else if(name.equals("UFCRTCollCTTwoPrimTwoParam")) { + String parameterStringRaw = getParameterText("ParameterString", parameters); + String parameteInt16Raw = getParameterText("ParameterInt16", parameters); + EdmPrimitiveType edmInt16 = OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Int16); + EdmPrimitiveType edmString = OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.String); + try { + Short parameterInt16 = edmInt16.valueOfString(parameteInt16Raw, null, null, null, null, null, Short.class); + + if (parameterStringRaw == null) { + ComplexValue complexValue1 = new ComplexValue(); + ComplexValue complexValue2 = new ComplexValue(); + + complexValue1.getValue().add(new Property(null, "PropertyInt16", ValueType.PRIMITIVE, 1)); + complexValue1.getValue().add(new Property(null, "PropertyString", ValueType.PRIMITIVE, + name + " int16 value: " + parameterInt16)); + + complexValue2.getValue().add(new Property(null, "PropertyInt16", ValueType.PRIMITIVE, 2)); + complexValue2.getValue().add(new Property(null, "PropertyString", ValueType.PRIMITIVE, + name + "string value: null")); + + + return new Property(null, "value", ValueType.COLLECTION_COMPLEX, Arrays.asList(new ComplexValue[] { + complexValue1, complexValue2 + })); + } else { + String parameterString = edmString.fromUriLiteral(parameterStringRaw); + List complexValues = new ArrayList(); + short counter = 1; + + for(short i = parameterInt16; 0 < i; i--) { + ComplexValue complexValue = new ComplexValue(); + complexValue.getValue().add(new Property(null, "PropertyInt16", ValueType.PRIMITIVE, counter++)); + complexValue.getValue().add(new Property(null, "PropertyString", ValueType.PRIMITIVE, + name + " string value: " + parameterString)); + complexValues.add(complexValue); + } + + return new Property(null, "value", ValueType.COLLECTION_COMPLEX, complexValues); + } + } catch (EdmPrimitiveTypeException e) { + throw new DataProviderException("Invalid function parameter"); + } + } else { throw new DataProviderException("Function " + name + " is not yet implemented."); } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java index 1f5bd03e1..3a1777556 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java @@ -142,12 +142,12 @@ public class ContainerProvider { functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCollCTTwoPrim")); functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTESMedia")); functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCollESMedia")); - functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCTTwoPrimParam")); + functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCTTwoPrimTwoParam")); functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCTTwoPrim")); functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCollString")); functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTString")); functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCollESTwoKeyNavParam")); - functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCollCTTwoPrimParam")); + functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCollCTTwoPrimTwoParam")); functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FINRTCollCTNavFiveProp")); functionImports.add(prov.getFunctionImport(ContainerProvider.nameContainer, "FICRTCollESKeyNavContParam")); @@ -598,10 +598,10 @@ public class ContainerProvider { .setEntitySet(entityContainer.getFullQualifiedNameAsString() + "/ESMedia") .setIncludeInServiceDocument(true); - } else if (name.equals("FICRTCTTwoPrimParam")) { + } else if (name.equals("FICRTCTTwoPrimTwoParam")) { return new CsdlFunctionImport() .setName(name) - .setFunction(FunctionProvider.nameUFCRTCTTwoPrimParam) + .setFunction(FunctionProvider.nameUFCRTCTTwoPrimTwoParam) .setIncludeInServiceDocument(true); } else if (name.equals("FICRTCTTwoPrim")) { @@ -629,10 +629,10 @@ public class ContainerProvider { .setEntitySet(entityContainer.getFullQualifiedNameAsString() + "/ESTwoKeyNav") .setIncludeInServiceDocument(true); - } else if (name.equals("FICRTCollCTTwoPrimParam")) { + } else if (name.equals("FICRTCollCTTwoPrimTwoParam")) { return new CsdlFunctionImport() .setName(name) - .setFunction(FunctionProvider.nameUFCRTCollCTTwoPrimParam) + .setFunction(FunctionProvider.nameUFCRTCollCTTwoPrimTwoParam) .setIncludeInServiceDocument(true); } else if (name.equals("FINRTCollCTNavFiveProp")) { diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java index 63dfec12c..1694d1370 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java @@ -125,8 +125,8 @@ public class FunctionProvider { // Unbound Functions public static final FullQualifiedName nameUFCRTCollCTTwoPrim = new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTCollCTTwoPrim"); - public static final FullQualifiedName nameUFCRTCollCTTwoPrimParam = - new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTCollCTTwoPrimParam"); + public static final FullQualifiedName nameUFCRTCollCTTwoPrimTwoParam = + new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTCollCTTwoPrimTwoParam"); public static final FullQualifiedName nameUFCRTCollString = new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTCollString"); public static final FullQualifiedName nameUFCRTCollStringTwoParam = @@ -135,8 +135,8 @@ public class FunctionProvider { new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTCTAllPrimTwoParam"); public static final FullQualifiedName nameUFCRTCTTwoPrim = new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTCTTwoPrim"); - public static final FullQualifiedName nameUFCRTCTTwoPrimParam = - new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTCTTwoPrimParam"); + public static final FullQualifiedName nameUFCRTCTTwoPrimTwoParam = + new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTCTTwoPrimTwoParam"); public static final FullQualifiedName nameUFCRTESMixPrimCollCompTwoParam = new FullQualifiedName(SchemaProvider.NAMESPACE, "UFCRTESMixPrimCollCompTwoParam"); public static final FullQualifiedName nameUFCRTCollETTwoKeyNavParam = @@ -243,7 +243,7 @@ public class FunctionProvider { .setNullable(false))) .setComposable(true) .setReturnType( - new CsdlReturnType().setType(PropertyProvider.nameString).setNullable(false)), + new CsdlReturnType().setType(PropertyProvider.nameString).setNullable(true)), new CsdlFunction() .setName("UFCRTStringTwoParam") .setParameters(Arrays.asList( @@ -256,7 +256,7 @@ public class FunctionProvider { .setType(PropertyProvider.nameInt16) .setNullable(false))) .setComposable(true) - .setReturnType(new CsdlReturnType().setType(PropertyProvider.nameString).setNullable(false)) + .setReturnType(new CsdlReturnType().setType(PropertyProvider.nameString).setNullable(true)) ); @@ -360,10 +360,10 @@ public class FunctionProvider { .setNullable(false) .setCollection(true)) ); - } else if (functionName.equals(nameUFCRTCTTwoPrimParam)) { + } else if (functionName.equals(nameUFCRTCTTwoPrimTwoParam)) { return Arrays.asList( new CsdlFunction() - .setName("UFCRTCTTwoPrimParam") + .setName("UFCRTCTTwoPrimTwoParam") .setParameters( Arrays.asList( new CsdlParameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16).setNullable( @@ -374,10 +374,10 @@ public class FunctionProvider { .setReturnType( new CsdlReturnType().setType(ComplexTypeProvider.nameCTTwoPrim).setNullable(false)) ); - } else if (functionName.equals(nameUFCRTCollCTTwoPrimParam)) { + } else if (functionName.equals(nameUFCRTCollCTTwoPrimTwoParam)) { return Arrays.asList( new CsdlFunction() - .setName("UFCRTCollCTTwoPrimParam") + .setName("UFCRTCollCTTwoPrimTwoParam") .setParameters( Arrays.asList( new CsdlParameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16).setNullable( diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java index c8d299d27..7891556dc 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java @@ -146,8 +146,8 @@ public class SchemaProvider { functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCollStringTwoParam)); functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCollString)); functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCTAllPrimTwoParam)); - functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCTTwoPrimParam)); - functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCollCTTwoPrimParam)); + functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCTTwoPrimTwoParam)); + functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCollCTTwoPrimTwoParam)); functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCTTwoPrim)); functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTCollCTTwoPrim)); functions.addAll(prov.getFunctions(FunctionProvider.nameUFCRTETMedia)); diff --git a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java index 4300ade98..1d29a8e5a 100644 --- a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java +++ b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/DataProviderTest.java @@ -122,7 +122,7 @@ public class DataProviderTest { public void esCompAllPrim() throws Exception { EntityCollection outSet = new DataProvider().readAll(esCompAllPrim); - Assert.assertEquals(3, outSet.getEntities().size()); + Assert.assertEquals(4, outSet.getEntities().size()); Assert.assertEquals(2, outSet.getEntities().get(0).getProperties().size()); Property complex = outSet.getEntities().get(0).getProperties().get(1); Assert.assertTrue(complex.isComplex()); 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 b3568f573..3ed9f89f6 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 @@ -79,7 +79,21 @@ public class ODataJsonDeserializerActionParametersTest extends AbstractODataDese assertNotNull(parameter); assertEquals(BigDecimal.valueOf(3669753), parameter.getValue()); } - + + @Test + public void testParameterWithNullLiteral() throws Exception { + final Map parameters = deserialize("{\"ParameterInt16\":1,\"ParameterDuration\":null}", + "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(expected = DeserializerException.class) public void bindingParameter() throws Exception { deserialize("{\"ParameterETAllPrim\":{\"PropertyInt16\":42}}", "BAETAllPrimRT", "ETAllPrim"); @@ -109,7 +123,7 @@ public class ODataJsonDeserializerActionParametersTest extends AbstractODataDese public void wrongType() throws Exception { deserialize("{\"ParameterInt16\":\"42\"}", "UARTParam"); } - + private Map deserialize(final String input, final String actionName) throws DeserializerException { return OData.newInstance().createDeserializer(CONTENT_TYPE_JSON) .actionParameters(new ByteArrayInputStream(input.getBytes()), diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java index 0877df630..ca070a973 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java @@ -179,9 +179,9 @@ public class ODataJsonSerializerTest { Assert.assertThat(resultString, CoreMatchers.startsWith("{" + "\"@odata.context\":\"$metadata#ESCompAllPrim\"," + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," - + "\"@odata.count\":3,\"value\":[" + + "\"@odata.count\":4,\"value\":[" + "{\"@odata.etag\":\"W/\\\"32767\\\"\",")); - Assert.assertThat(resultString, CoreMatchers.endsWith("\"}}]," + Assert.assertThat(resultString, CoreMatchers.endsWith("}}]," + "\"@odata.nextLink\":\"/next\"}")); int count = 0; @@ -189,7 +189,7 @@ public class ODataJsonSerializerTest { while ((index = resultString.indexOf("PropertyInt16\":", ++index)) > 0) { count++; } - Assert.assertEquals(6, count); + Assert.assertEquals(8, count); } @Test diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java index db58288cd..d1ffaab9c 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestFullResourcePath.java @@ -1705,6 +1705,14 @@ public class TestFullResourcePath { .isKeyPredicate(1, "PropertyString", "'3'") .n() .isFunction("BFCETBaseTwoKeyNavRTETTwoKeyNav"); + + testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString=null)") + .isKind(UriInfoKind.resource).goPath() + .first() + .isFunctionImport("FICRTCollCTTwoPrimTwoParam") + .isFunction("UFCRTCollCTTwoPrimTwoParam") + .isParameter(0, "ParameterInt16", "1") + .isParameter(1, "ParameterString", null); } @Test @@ -1817,11 +1825,11 @@ public class TestFullResourcePath { @Test public void runFunctionImpError() { - testUri.runEx("FICRTCollCTTwoPrimParam") + testUri.runEx("FICRTCollCTTwoPrimTwoParam") .isExSyntax(UriParserSyntaxException.MessageKeys.SYNTAX); - testUri.runEx("FICRTCollCTTwoPrimParam()") + testUri.runEx("FICRTCollCTTwoPrimTwoParam()") .isExSemantic(UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND); - testUri.runEx("FICRTCollCTTwoPrimParam(invalidParam=2)") + testUri.runEx("FICRTCollCTTwoPrimTwoParam(invalidParam=2)") .isExSemantic(UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND); } @@ -4606,11 +4614,11 @@ public class TestFullResourcePath { .goParameter(0).isLiteral("'Walldorf'") .root().left().goParameter(1).isLiteral("'Wall'"); - testFilter.runOnETAllPrim("olingo.odata.test1.UFCRTCTTwoPrimParam(ParameterInt16=null,ParameterString=null)") + testFilter.runOnETAllPrim("olingo.odata.test1.UFCRTCTTwoPrimTwoParam(ParameterInt16=null,ParameterString=null)") .goPath() - .isFunction("UFCRTCTTwoPrimParam") - .isParameter(0, "ParameterInt16", "null") - .isParameter(1, "ParameterString", "null"); + .isFunction("UFCRTCTTwoPrimTwoParam") + .isParameter(0, "ParameterInt16", null) + .isParameter(1, "ParameterString", null); testFilter.runOnETAllPrim("PropertyBoolean eq true") .is("< eq >") @@ -5180,12 +5188,12 @@ public class TestFullResourcePath { .isExSemantic(UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER); // type filter for complex double on entry - testUri.runEx("FICRTCTTwoPrimParam(ParameterInt16=1,ParameterString='2')" + testUri.runEx("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')" + "/olingo.odata.test1.CTBase/olingo.odata.test1.CTBase") .isExSemantic(UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE); // type filter for complex double on collection - testUri.runEx("FICRTCollCTTwoPrimParam(ParameterInt16=1,ParameterString='2')" + testUri.runEx("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')" + "/olingo.odata.test1.CTBase/olingo.odata.test1.CTBase") .isExSemantic(UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE); diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java index 0d333f3e3..9f79a84ce 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/antlr/TestUriParserImpl.java @@ -1018,7 +1018,7 @@ public class TestUriParserImpl { @Test(expected = UriValidationException.class) public void testMemberStartingWithCastFailOnValidation2() throws Exception { - testUri.run("FICRTCTTwoPrimParam(ParameterInt16=1,ParameterString='2')", + testUri.run("FICRTCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')", "$filter=olingo.odata.test1.CTBase/AdditionalPropString") .goFilter().root().isMember() .isMemberStartType(ComplexTypeProvider.nameCTBase).goPath() @@ -1043,7 +1043,7 @@ public class TestUriParserImpl { .at(0).isType(PropertyProvider.nameDate); // on Complex collection - testUri.run("FICRTCollCTTwoPrimParam(ParameterInt16=1,ParameterString='2')", + testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')", "$filter=olingo.odata.test1.CTBase/AdditionalPropString") .goFilter().root().isMember() .isMemberStartType(ComplexTypeProvider.nameCTBase).goPath() @@ -1057,7 +1057,7 @@ public class TestUriParserImpl { @Test public void testComplexTypeCastFollowingAsCollection() throws Exception { - testUri.run("FICRTCollCTTwoPrimParam(ParameterInt16=1,ParameterString='2')/olingo.odata.test1.CTBase"); + testUri.run("FICRTCollCTTwoPrimTwoParam(ParameterInt16=1,ParameterString='2')/olingo.odata.test1.CTBase"); } @Test