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

This commit is contained in:
Christian Amend 2015-04-14 14:52:36 +02:00
parent 34e518a6e0
commit cd23eb96f8
14 changed files with 413 additions and 72 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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));
}
}

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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();
}
}