You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2015/07/29 20:44:36 UTC
olingo-odata4 git commit: [OLINGO-659] Minor code refactoring
Repository: olingo-odata4
Updated Branches:
refs/heads/master 57a11aff6 -> 305f54dcf
[OLINGO-659] Minor code refactoring
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/305f54dc
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/305f54dc
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/305f54dc
Branch: refs/heads/master
Commit: 305f54dcf27dabca5fdeefe01fb4cc9e7fd67d56
Parents: 57a11af
Author: Michael Bolz <mi...@sap.com>
Authored: Tue Jul 28 20:25:52 2015 +0200
Committer: Michael Bolz <mi...@sap.com>
Committed: Wed Jul 29 20:40:30 2015 +0200
----------------------------------------------------------------------
.../json/ODataJsonDeserializer.java | 275 +++++++++++--------
.../json/ODataJsonDeserializerEntityTest.java | 50 ++++
2 files changed, 203 insertions(+), 122 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/305f54dc/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 84beb61..9c6798d 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
@@ -63,7 +63,6 @@ import org.apache.olingo.server.core.deserializer.helper.ExpandTreeBuilderImpl;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
@@ -202,9 +201,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
throws DeserializerException {
try {
ObjectNode tree = parseJsonTree(stream);
- Map<String, Parameter> parameters = new LinkedHashMap<String, Parameter>();
if (tree != null) {
- consumeParameters(edmAction, tree, parameters);
+ Map<String, Parameter> parameters = consumeParameters(edmAction, tree);
final List<String> toRemove = new ArrayList<String>();
Iterator<Entry<String, JsonNode>> fieldsIterator = tree.fields();
@@ -222,8 +220,9 @@ public class ODataJsonDeserializer implements ODataDeserializer {
// remove here to avoid iterator issues.
tree.remove(toRemove);
assertJsonNodeIsEmpty(tree);
- }
return DeserializerResultImpl.with().actionParameters(parameters).build();
+ }
+ return DeserializerResultImpl.with().build();
} catch (final JsonParseException e) {
throw new DeserializerException("An JsonParseException occurred", e,
@@ -237,58 +236,35 @@ public class ODataJsonDeserializer implements ODataDeserializer {
}
}
- private ObjectNode parseJsonTree(final InputStream stream)
- throws IOException, JsonParseException, JsonProcessingException {
+ private ObjectNode parseJsonTree(final InputStream stream) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true);
JsonParser parser = new JsonFactory(objectMapper).createParser(stream);
- ObjectNode tree = parser.getCodec().readTree(parser);
- return tree;
+ return parser.getCodec().readTree(parser);
}
- private void consumeParameters(final EdmAction edmAction, final ObjectNode node,
- final Map<String, Parameter> parameters)
+ private Map<String, Parameter> consumeParameters(final EdmAction edmAction, final ObjectNode node)
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());
}
+ Map<String, Parameter> parameters = new LinkedHashMap<String, Parameter>();
for (final String paramName : parameterNames) {
final EdmParameter edmParameter = edmAction.getParameter(paramName);
- Parameter parameter = new Parameter();
- parameter.setName(paramName);
- JsonNode jsonNode = node.get(paramName);
switch (edmParameter.getType().getKind()) {
case PRIMITIVE:
case DEFINITION:
case ENUM:
- if (jsonNode == null || jsonNode.isNull()) {
- if (!edmParameter.isNullable()) {
- throw new DeserializerException("Non-nullable parameter not present or null",
- DeserializerException.MessageKeys.INVALID_NULL_PARAMETER, paramName);
- }
- if (edmParameter.isCollection()) {
- throw new DeserializerException("Collection must not be null for parameter: " + paramName,
- 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(),
- edmParameter.isNullable(), edmParameter.getMaxLength(), edmParameter.getPrecision(), edmParameter
- .getScale(), true, edmParameter.getMapping(), jsonNode);
- parameter.setValue(consumePropertyNode.getValueType(), consumePropertyNode.getValue());
- parameters.put(paramName, parameter);
- node.remove(paramName);
- }
+ Parameter parameter = createParameter(node.get(paramName), paramName, edmParameter);
+ parameters.put(paramName, parameter);
+ node.remove(paramName);
break;
case COMPLEX:
case ENTITY:
- throw new DeserializerException("Entity an complex parameters currently not Implemented",
+ throw new DeserializerException("Entity and complex parameters currently not Implemented",
DeserializerException.MessageKeys.NOT_IMPLEMENTED);
default:
throw new DeserializerException("Invalid type kind " + edmParameter.getType().getKind().toString()
@@ -296,6 +272,31 @@ public class ODataJsonDeserializer implements ODataDeserializer {
paramName);
}
}
+ return parameters;
+ }
+
+ private Parameter createParameter(JsonNode node, String paramName, EdmParameter edmParameter) throws
+ DeserializerException {
+ Parameter parameter = new Parameter();
+ parameter.setName(paramName);
+ if (node == null || node.isNull()) {
+ if (!edmParameter.isNullable()) {
+ throw new DeserializerException("Non-nullable parameter not present or null",
+ MessageKeys.INVALID_NULL_PARAMETER, paramName);
+ }
+ if (edmParameter.isCollection()) {
+ throw new DeserializerException("Collection must not be null for parameter: " + paramName,
+ MessageKeys.INVALID_NULL_PARAMETER, paramName);
+ }
+ parameter.setValue(ValueType.PRIMITIVE, null);
+ } else {
+ Property consumePropertyNode =
+ consumePropertyNode(edmParameter.getName(), edmParameter.getType(), edmParameter.isCollection(),
+ edmParameter.isNullable(), edmParameter.getMaxLength(), edmParameter.getPrecision(), edmParameter
+ .getScale(), true, edmParameter.getMapping(), node);
+ parameter.setValue(consumePropertyNode.getValueType(), consumePropertyNode.getValue());
+ }
+ return parameter;
}
/**
@@ -342,9 +343,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, propertyName);
}
Property property = consumePropertyNode(edmProperty.getName(), edmProperty.getType(),
- edmProperty.isCollection(),
- edmProperty.isNullable(), edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(),
- edmProperty.isUnicode(), edmProperty.getMapping(),
+ edmProperty.isCollection(), edmProperty.isNullable(), edmProperty.getMaxLength(),
+ edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode(), edmProperty.getMapping(),
jsonNode);
entity.addProperty(property);
node.remove(propertyName);
@@ -360,41 +360,59 @@ public class ODataJsonDeserializer implements ODataDeserializer {
JsonNode jsonNode = node.get(navigationPropertyName);
if (jsonNode != null) {
EdmNavigationProperty edmNavigationProperty = edmEntityType.getNavigationProperty(navigationPropertyName);
- boolean isNullable = edmNavigationProperty.isNullable();
- if ((jsonNode.isNull() && !isNullable) || (jsonNode.isNull() && edmNavigationProperty.isCollection())) {
- throw new DeserializerException("Property: " + navigationPropertyName + " must not be null.",
- DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, navigationPropertyName);
- }
+ checkNotNullOrValidNull(jsonNode, edmNavigationProperty);
- Link link = new Link();
- link.setTitle(navigationPropertyName);
- final ExpandTreeBuilder childExpandBuilder = (expandBuilder != null) ?
- expandBuilder.expand(edmNavigationProperty) : null;
- if (jsonNode.isArray() && edmNavigationProperty.isCollection()) {
- link.setType(Constants.ENTITY_SET_NAVIGATION_LINK_TYPE);
- EntityCollection inlineEntitySet = new EntityCollection();
- inlineEntitySet.getEntities().addAll(consumeEntitySetArray(edmNavigationProperty.getType(), jsonNode,
- childExpandBuilder));
- link.setInlineEntitySet(inlineEntitySet);
- } else if (!jsonNode.isArray() && (!jsonNode.isValueNode() || jsonNode.isNull())
- && !edmNavigationProperty.isCollection()) {
- link.setType(Constants.ENTITY_NAVIGATION_LINK_TYPE);
- if (!jsonNode.isNull()) {
- Entity inlineEntity = consumeEntityNode(edmNavigationProperty.getType(), (ObjectNode) jsonNode,
- childExpandBuilder);
- link.setInlineEntity(inlineEntity);
- }
- } else {
- throw new DeserializerException("Invalid value: " + jsonNode.getNodeType()
- + " for expanded navigation property: " + navigationPropertyName,
- DeserializerException.MessageKeys.INVALID_VALUE_FOR_NAVIGATION_PROPERTY, navigationPropertyName);
- }
+ Link link = createLink(expandBuilder, navigationPropertyName, jsonNode, edmNavigationProperty);
entity.getNavigationLinks().add(link);
node.remove(navigationPropertyName);
}
}
}
+ /**
+ * Check if jsonNode is not null or if null but nullable or collection navigationProperty
+ *
+ * @param jsonNode related json node
+ * @param edmNavigationProperty related navigation property
+ * @throws DeserializerException if jsonNode is not null or if null but nullable or collection navigationProperty
+ */
+ private void checkNotNullOrValidNull(JsonNode jsonNode,
+ EdmNavigationProperty edmNavigationProperty) throws DeserializerException {
+ boolean isNullable = edmNavigationProperty.isNullable();
+ if ((jsonNode.isNull() && !isNullable) || (jsonNode.isNull() && edmNavigationProperty.isCollection())) {
+ throw new DeserializerException("Property: " + edmNavigationProperty.getName() + " must not be null.",
+ MessageKeys.INVALID_NULL_PROPERTY, edmNavigationProperty.getName());
+ }
+ }
+
+ private Link createLink(ExpandTreeBuilder expandBuilder, String navigationPropertyName, JsonNode jsonNode,
+ EdmNavigationProperty edmNavigationProperty) throws DeserializerException {
+ Link link = new Link();
+ link.setTitle(navigationPropertyName);
+ final ExpandTreeBuilder childExpandBuilder = (expandBuilder != null) ?
+ expandBuilder.expand(edmNavigationProperty) : null;
+ if (jsonNode.isArray() && edmNavigationProperty.isCollection()) {
+ link.setType(Constants.ENTITY_SET_NAVIGATION_LINK_TYPE);
+ EntityCollection inlineEntitySet = new EntityCollection();
+ inlineEntitySet.getEntities().addAll(
+ consumeEntitySetArray(edmNavigationProperty.getType(), jsonNode, childExpandBuilder));
+ link.setInlineEntitySet(inlineEntitySet);
+ } else if (!jsonNode.isArray() && (!jsonNode.isValueNode() || jsonNode.isNull())
+ && !edmNavigationProperty.isCollection()) {
+ link.setType(Constants.ENTITY_NAVIGATION_LINK_TYPE);
+ if (!jsonNode.isNull()) {
+ Entity inlineEntity = consumeEntityNode(edmNavigationProperty.getType(), (ObjectNode) jsonNode,
+ childExpandBuilder);
+ link.setInlineEntity(inlineEntity);
+ }
+ } else {
+ throw new DeserializerException("Invalid value: " + jsonNode.getNodeType()
+ + " for expanded navigation property: " + navigationPropertyName,
+ MessageKeys.INVALID_VALUE_FOR_NAVIGATION_PROPERTY, navigationPropertyName);
+ }
+ return link;
+ }
+
private Link consumeBindingLink(final String key, final JsonNode jsonNode, final EdmEntityType edmEntityType)
throws DeserializerException {
String[] splitKey = key.split("@");
@@ -450,11 +468,11 @@ public class ODataJsonDeserializer implements ODataDeserializer {
property.setName(name);
property.setType(type.getFullQualifiedName().getFullQualifiedNameAsString());
if (isCollection) {
- consumePropertyCollectionNode(name, type, isNullable, maxLength, precision, scale, isUnicode, mapping,
- jsonNode, property);
+ consumePropertyCollectionNode(name, type, isNullable, maxLength, precision, scale, isUnicode, mapping, jsonNode,
+ property);
} else {
- consumePropertySingleNode(name, type, isNullable, maxLength, precision, scale, isUnicode, mapping,
- jsonNode, property);
+ consumePropertySingleNode(name, type, isNullable, maxLength, precision, scale, isUnicode, mapping, jsonNode,
+ property);
}
return property;
}
@@ -695,7 +713,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
/**
* This method either returns the primitive types default class or the manually mapped class if present.
- * @param edmMapping
+ * @param mapping
* @param edmPrimitiveType
* @return the java class to be used during deserialization
*/
@@ -736,7 +754,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
private void checkJsonTypeBasedOnPrimitiveType(final String propertyName, final String edmPrimitiveTypeName,
final JsonNode jsonNode)
- throws DeserializerException {
+ throws DeserializerException {
+
EdmPrimitiveTypeKind primKind;
try {
primKind = EdmPrimitiveTypeKind.valueOf(edmPrimitiveTypeName);
@@ -744,60 +763,72 @@ public class ODataJsonDeserializer implements ODataDeserializer {
throw new DeserializerException("Unknown Primitive Type: " + edmPrimitiveTypeName, e,
DeserializerException.MessageKeys.UNKNOWN_PRIMITIVE_TYPE, edmPrimitiveTypeName, propertyName);
}
- switch (primKind) {
- // Booleans
- case Boolean:
- if (!jsonNode.isBoolean()) {
- throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
- + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
+
+ boolean valid = matchTextualCase(jsonNode, primKind);
+ valid |= matchNumberCase(jsonNode, primKind);
+ valid |= matchBooleanCase(jsonNode, primKind);
+ valid |= matchIEEENumberCase(jsonNode, primKind);
+
+ if(!valid) {
+ throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
+ + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
+ }
+ }
+
+ private boolean matchIEEENumberCase(JsonNode node, EdmPrimitiveTypeKind primKind) {
+ switch (primKind) {
+ case Int64:
+ case Decimal:
+ // Numbers (either numbers or string)
+ if (isIEEE754Compatible) {
+ return node.isTextual();
+ } else {
+ return node.isNumber();
+ }
}
- break;
- // Numbers (must be numbers)
- case Int16:
- case Int32:
- case Byte:
- case SByte:
- case Single:
- case Double:
- if (!jsonNode.isNumber()) {
- throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
- + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
+ return false;
+ }
+
+ private boolean matchBooleanCase(JsonNode node, EdmPrimitiveTypeKind primKind) {
+ if(node.isBoolean()) {
+ switch (primKind) {
+ case Boolean:
+ return true;
}
- break;
- case Int64:
- case Decimal:
- // Numbers (eighter numers or string)
- if (isIEEE754Compatible) {
- if (!jsonNode.isTextual()) {
- throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
- + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY,
- propertyName);
- }
- } else {
- if (!jsonNode.isNumber()) {
- throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
- + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY,
- propertyName);
- }
+ }
+ return false;
+ }
+
+ private boolean matchNumberCase(JsonNode node, EdmPrimitiveTypeKind primKind) {
+ if(node.isNumber()) {
+ switch (primKind) {
+ // Numbers (must be numbers)
+ case Int16:
+ case Int32:
+ case Byte:
+ case SByte:
+ case Single:
+ case Double:
+ return true;
}
- break;
- // Strings
- case String:
- case Binary:
- case Date:
- case DateTimeOffset:
- case Duration:
- case Guid:
- case TimeOfDay:
- if (!jsonNode.isTextual()) {
- throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
- + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
+ }
+ return false;
+ }
+
+ private boolean matchTextualCase(JsonNode node, EdmPrimitiveTypeKind primKind) {
+ if(node.isTextual()) {
+ switch (primKind) {
+ case String:
+ case Binary:
+ case Date:
+ case DateTimeOffset:
+ case Duration:
+ case Guid:
+ case TimeOfDay:
+ return true;
}
- break;
- default:
- throw new DeserializerException("Unsupported Edm Primitive Type: " + primKind,
- DeserializerException.MessageKeys.NOT_IMPLEMENTED);
}
+ return false;
}
@Override
@@ -809,7 +840,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
JsonParser parser = new JsonFactory(objectMapper).createParser(stream);
final ObjectNode tree = parser.getCodec().readTree(parser);
- Property property = null;
+ final Property property;
JsonNode jsonNode = tree.get(Constants.VALUE);
if (jsonNode != null) {
property = consumePropertyNode(edmProperty.getName(), edmProperty.getType(),
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/305f54dc/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
index 4a03b03..5388b40 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
@@ -1520,6 +1520,56 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"))).getEntity();
}
+ @Test(expected = DeserializerException.class)
+ public void ieee754CompatibleAsNumber() throws Exception {
+ ODataDeserializer deserializer = OData.newInstance().createDeserializer(CONTENT_TYPE_JSON_IEEE754Compatible);
+ String entityString =
+ "{\"PropertyInt16\":32767," +
+ "\"PropertyString\":\"First Resource - positive values\"," +
+ "\"PropertyBoolean\":null," +
+ "\"PropertyByte\":255," +
+ "\"PropertySByte\":127," +
+ "\"PropertyInt32\":2147483647," +
+ "\"PropertyInt64\":123," +
+ "\"PropertySingle\":1.79E20," +
+ "\"PropertyDouble\":-1.79E19," +
+ "\"PropertyDecimal\":\"null\"," +
+ "\"PropertyBinary\":\"ASNFZ4mrze8=\"," +
+ "\"PropertyDate\":null," +
+ "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," +
+ "\"PropertyDuration\":\"PT6S\"," +
+ "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," +
+ "\"PropertyTimeOfDay\":\"03:26:05\"}";
+
+ final InputStream stream = new ByteArrayInputStream(entityString.getBytes());
+ deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"))).getEntity();
+ }
+
+ @Test(expected = DeserializerException.class)
+ public void ieee754NotCompatibleAsString() throws Exception {
+ ODataDeserializer deserializer = OData.newInstance().createDeserializer(CONTENT_TYPE_JSON);
+ String entityString =
+ "{\"PropertyInt16\":32767," +
+ "\"PropertyString\":\"First Resource - positive values\"," +
+ "\"PropertyBoolean\":null," +
+ "\"PropertyByte\":255," +
+ "\"PropertySByte\":127," +
+ "\"PropertyInt32\":2147483647," +
+ "\"PropertyInt64\":\"123\"," +
+ "\"PropertySingle\":1.79E20," +
+ "\"PropertyDouble\":-1.79E19," +
+ "\"PropertyDecimal\":\"null\"," +
+ "\"PropertyBinary\":\"ASNFZ4mrze8=\"," +
+ "\"PropertyDate\":null," +
+ "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," +
+ "\"PropertyDuration\":\"PT6S\"," +
+ "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," +
+ "\"PropertyTimeOfDay\":\"03:26:05\"}";
+
+ final InputStream stream = new ByteArrayInputStream(entityString.getBytes());
+ deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"))).getEntity();
+ }
+
private void checkPropertyJsonType(final String entityString) throws DeserializerException {
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(CONTENT_TYPE_JSON);