[OLINGO-1037] Support GeoTypes in Json

This commit is contained in:
Christian Amend 2016-10-19 14:33:34 +02:00
parent 5255c336eb
commit cc0a6a51a8
4 changed files with 990 additions and 310 deletions

View File

@ -20,9 +20,12 @@ package org.apache.olingo.server.core.deserializer.json;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@ -53,6 +56,14 @@ import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.commons.api.edm.geo.Geospatial;
import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
import org.apache.olingo.commons.api.edm.geo.LineString;
import org.apache.olingo.commons.api.edm.geo.MultiLineString;
import org.apache.olingo.commons.api.edm.geo.MultiPoint;
import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
import org.apache.olingo.commons.api.edm.geo.Point;
import org.apache.olingo.commons.api.edm.geo.Polygon;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.deserializer.DeserializerException;
@ -76,6 +87,19 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
public class ODataJsonDeserializer implements ODataDeserializer {
private static final Map<String, Class<? extends Geospatial>> jsonNameToGeoDataType;
static {
Map<String, Class<? extends Geospatial>> temp = new HashMap<String, Class<? extends Geospatial>>();
temp.put(Constants.ELEM_POINT, Point.class);
temp.put(Constants.ELEM_MULTIPOINT, MultiPoint.class);
temp.put(Constants.ELEM_LINESTRING, LineString.class);
temp.put("MultiLineString", MultiLineString.class);
temp.put(Constants.ELEM_POLYGON, Polygon.class);
temp.put("MultiPolygon", MultiPolygon.class);
temp.put("GeometryCollection", GeospatialCollection.class);
jsonNameToGeoDataType = Collections.unmodifiableMap(temp);
}
private static final String ODATA_ANNOTATION_MARKER = "@";
private static final String ODATA_CONTROL_INFORMATION_PREFIX = "@odata.";
@ -594,16 +618,21 @@ public class ODataJsonDeserializer implements ODataDeserializer {
private Object readPrimitiveValue(final String name, final EdmPrimitiveType type,
final boolean isNullable, final Integer maxLength, final Integer precision, final Integer scale,
final boolean isUnicode, final EdmMapping mapping, final JsonNode jsonNode) throws DeserializerException {
checkForValueNode(name, jsonNode);
if (isValidNull(name, isNullable, jsonNode)) {
return null;
}
final boolean isGeoType = type.getName().startsWith("Geo");
if (!isGeoType) {
checkForValueNode(name, jsonNode);
}
checkJsonTypeBasedOnPrimitiveType(name, type, jsonNode);
Class<?> javaClass = getJavaClassForPrimitiveType(mapping, type);
try {
if (isGeoType) {
return readPrimitiveGeoValue(name, type, (ObjectNode) jsonNode);
}
return type.valueOfString(jsonNode.asText(),
isNullable, maxLength, precision, scale, isUnicode,
javaClass);
getJavaClassForPrimitiveType(mapping, type));
} catch (final EdmPrimitiveTypeException e) {
throw new DeserializerException(
"Invalid value: " + jsonNode.asText() + " for property: " + name, e,
@ -624,6 +653,132 @@ public class ODataJsonDeserializer implements ODataDeserializer {
return false;
}
/**
* Reads a geospatial JSON value following the GeoJSON specification defined in RFC 7946.
* @param name property name
* @param type EDM type of the value
* (can be <code>null</code> for recursive calls while parsing a GeometryCollection)
*/
private Geospatial readPrimitiveGeoValue(final String name, final EdmPrimitiveType type, ObjectNode jsonNode)
throws DeserializerException, EdmPrimitiveTypeException {
JsonNode typeNode = jsonNode.remove(Constants.ATTR_TYPE);
if (typeNode != null && typeNode.isTextual()) {
final Class<? extends Geospatial> geoDataType = jsonNameToGeoDataType.get(typeNode.asText());
if (geoDataType != null && (type == null || geoDataType.equals(type.getDefaultType()))) {
final JsonNode topNode = jsonNode.remove(
geoDataType.equals(GeospatialCollection.class) ? Constants.JSON_GEOMETRIES : Constants.JSON_COORDINATES);
// The "crs" member mentioned in some versions of the OData specification is not part of GeoJSON.
// It used to be used to specify the coordinate reference system.
// TODO: Is it OK to follow RFC 7946 strictly and not allow this element from its obsolete predecessor?
assertJsonNodeIsEmpty(jsonNode);
if (topNode != null && topNode.isArray()) {
final Geospatial.Dimension dimension = type == null || type.getName().startsWith("Geometry") ?
Geospatial.Dimension.GEOMETRY :
Geospatial.Dimension.GEOGRAPHY;
if (geoDataType.equals(Point.class)) {
return readGeoPointValue(name, dimension, topNode);
} else if (geoDataType.equals(MultiPoint.class)) {
return new MultiPoint(dimension, null, readGeoPointValues(name, dimension, 0, false, topNode));
} else if (geoDataType.equals(LineString.class)) {
// Although a line string with less than two points is not really one, the OData specification says:
// "The coordinates member of a LineString can have zero or more positions".
// Therefore the required minimal size of the points array currently is zero.
return new LineString(dimension, null, readGeoPointValues(name, dimension, 0, false, topNode));
} else if (geoDataType.equals(MultiLineString.class)) {
List<LineString> lines = new ArrayList<LineString>();
for (final JsonNode element : topNode) {
// Line strings can be empty (see above).
lines.add(new LineString(dimension, null, readGeoPointValues(name, dimension, 0, false, element)));
}
return new MultiLineString(dimension, null, lines);
} else if (geoDataType.equals(Polygon.class)) {
return readGeoPolygon(name, dimension, topNode);
} else if (geoDataType.equals(MultiPolygon.class)) {
List<Polygon> polygons = new ArrayList<Polygon>();
for (final JsonNode element : topNode) {
polygons.add(readGeoPolygon(name, dimension, element));
}
return new MultiPolygon(dimension, null, polygons);
} else if (geoDataType.equals(GeospatialCollection.class)) {
List<Geospatial> elements = new ArrayList<Geospatial>();
for (final JsonNode element : topNode) {
if (element.isObject()) {
elements.add(readPrimitiveGeoValue(name, null, (ObjectNode) element));
} else {
throw new DeserializerException("Invalid value '" + element + "' in property: " + name,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
}
}
return new GeospatialCollection(dimension, null, elements);
}
}
}
}
throw new DeserializerException("Invalid value '" + jsonNode + "' for property: " + name,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
}
private Point readGeoPointValue(final String name, final Geospatial.Dimension dimension, JsonNode node)
throws DeserializerException, EdmPrimitiveTypeException {
if (node.isArray() && (node.size() ==2 || node.size() == 3)
&& node.get(0).isNumber() && node.get(1).isNumber() && (node.get(2) == null || node.get(2).isNumber())) {
Point point = new Point(dimension, null);
point.setX(getDoubleValue(node.get(0).asText()));
point.setY(getDoubleValue(node.get(1).asText()));
if (node.get(2) != null) {
point.setZ(getDoubleValue(node.get(2).asText()));
}
return point;
}
throw new DeserializerException("Invalid point value '" + node + "' in property: " + name,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
}
private double getDoubleValue(final String value) throws EdmPrimitiveTypeException {
final BigDecimal bigDecimalValue = new BigDecimal(value);
final Double result = bigDecimalValue.doubleValue();
// "Real" infinite values cannot occur, so we can throw an exception
// if the conversion to a double results in an infinite value.
// An exception is also thrown if the number cannot be stored in a double without loss.
if (result.isInfinite() || BigDecimal.valueOf(result).compareTo(bigDecimalValue) != 0) {
throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
}
return result;
}
private List<Point> readGeoPointValues(final String name, final Geospatial.Dimension dimension,
final int minimalSize, final boolean closed, JsonNode node)
throws DeserializerException, EdmPrimitiveTypeException {
if (node.isArray()) {
List<Point> points = new ArrayList<Point>();
for (final JsonNode element : node) {
points.add(readGeoPointValue(name, dimension, element));
}
if (points.size() >= minimalSize
&& (!closed || points.get(points.size() - 1).equals(points.get(0)))) {
return points;
}
}
throw new DeserializerException("Invalid point values '" + node + "' in property: " + name,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
}
private Polygon readGeoPolygon(final String name, final Geospatial.Dimension dimension, JsonNode node)
throws DeserializerException, EdmPrimitiveTypeException {
// GeoJSON would allow for more than one interior polygon (hole).
// But there is no place in the data object to store this information so for now we throw an error.
// There could be a more strict verification that the lines describe boundaries and have the correct winding order.
if (node.isArray() && (node.size() == 1 || node.size() == 2)) {
return new Polygon(dimension, null,
node.size() > 1 ? readGeoPointValues(name, dimension, 4, true, node.get(1)) : null,
readGeoPointValues(name, dimension, 4, true, node.get(0)));
}
throw new DeserializerException("Invalid polygon values '" + node + "' in property: " + name,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
}
/**
* Returns the primitive type's default class or the manually mapped class if present.
* @param mapping
@ -704,7 +859,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
valid = matchTextualCase(jsonNode, primKind)
|| matchNumberCase(jsonNode, primKind)
|| matchBooleanCase(jsonNode, primKind)
|| matchIEEENumberCase(jsonNode, primKind);
|| matchIEEENumberCase(jsonNode, primKind)
|| jsonNode.isObject() && name.startsWith("Geo");
}
if (!valid) {
throw new DeserializerException(
@ -837,17 +993,11 @@ public class ODataJsonDeserializer implements ODataDeserializer {
DeserializerException.MessageKeys.UNKNOWN_CONTENT);
}
EdmStructuredType currentEdmType = null;
if (edmType instanceof EdmEntityType) {
currentEdmType = serviceMetadata.getEdm()
.getEntityType(new FullQualifiedName(odataType));
} else {
currentEdmType = serviceMetadata.getEdm()
.getComplexType(new FullQualifiedName(odataType));
}
final EdmStructuredType currentEdmType = edmType.getKind() == EdmTypeKind.ENTITY ?
serviceMetadata.getEdm().getEntityType(new FullQualifiedName(odataType)) :
serviceMetadata.getEdm().getComplexType(new FullQualifiedName(odataType));
if (!isAssignable(edmType, currentEdmType)) {
throw new DeserializerException(
"Odata type " + odataType + " not allowed here",
throw new DeserializerException("Odata type " + odataType + " not allowed here",
DeserializerException.MessageKeys.UNKNOWN_CONTENT);
}
@ -859,14 +1009,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
private boolean isAssignable(final EdmStructuredType edmStructuredType,
final EdmStructuredType edmStructuredTypeToAssign) {
if (edmStructuredTypeToAssign == null) {
return false;
} else if (edmStructuredType.getFullQualifiedName()
.equals(edmStructuredTypeToAssign.getFullQualifiedName())) {
return true;
} else {
return isAssignable(edmStructuredType,
edmStructuredTypeToAssign.getBaseType());
}
return edmStructuredTypeToAssign != null
&& (edmStructuredType.getFullQualifiedName().equals(edmStructuredTypeToAssign.getFullQualifiedName())
|| isAssignable(edmStructuredType, edmStructuredTypeToAssign.getBaseType()));
}
}

View File

@ -21,8 +21,10 @@ package org.apache.olingo.server.core.serializer.json;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.olingo.commons.api.Constants;
@ -47,6 +49,15 @@ import org.apache.olingo.commons.api.edm.EdmStructuredType;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.commons.api.edm.geo.ComposedGeospatial;
import org.apache.olingo.commons.api.edm.geo.Geospatial;
import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
import org.apache.olingo.commons.api.edm.geo.LineString;
import org.apache.olingo.commons.api.edm.geo.MultiLineString;
import org.apache.olingo.commons.api.edm.geo.MultiPoint;
import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
import org.apache.olingo.commons.api.edm.geo.Point;
import org.apache.olingo.commons.api.edm.geo.Polygon;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
import org.apache.olingo.server.api.ODataServerError;
@ -81,6 +92,19 @@ import com.fasterxml.jackson.core.JsonGenerator;
public class ODataJsonSerializer extends AbstractODataSerializer {
private static final Map<Geospatial.Type, String> geoValueTypeToJsonName;
static {
Map<Geospatial.Type, String> temp = new EnumMap<Geospatial.Type, String>(Geospatial.Type.class);
temp.put(Geospatial.Type.POINT, Constants.ELEM_POINT);
temp.put(Geospatial.Type.MULTIPOINT, Constants.ELEM_MULTIPOINT);
temp.put(Geospatial.Type.LINESTRING, Constants.ELEM_LINESTRING);
temp.put(Geospatial.Type.MULTILINESTRING, "MultiLineString");
temp.put(Geospatial.Type.POLYGON, Constants.ELEM_POLYGON);
temp.put(Geospatial.Type.MULTIPOLYGON, "MultiPolygon");
temp.put(Geospatial.Type.GEOSPATIALCOLLECTION, "GeometryCollection");
geoValueTypeToJsonName = Collections.unmodifiableMap(temp);
}
private final boolean isIEEE754Compatible;
private final boolean isODataMetadataNone;
private final boolean isODataMetadataFull;
@ -701,6 +725,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
switch (property.getValueType()) {
case COLLECTION_PRIMITIVE:
case COLLECTION_ENUM:
case COLLECTION_GEOSPATIAL:
try {
writePrimitiveValue(property.getName(), type, value, isNullable,
maxLength, precision, scale, isUnicode, json);
@ -710,9 +735,6 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
property.getName(), property.getValue().toString());
}
break;
case COLLECTION_GEOSPATIAL:
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, property.getName());
default:
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, property.getName());
@ -753,8 +775,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
writePrimitiveValue(property.getName(), type, property.asPrimitive(),
isNullable, maxLength, precision, scale, isUnicode, json);
} else if (property.isGeospatial()) {
throw new SerializerException("Property type not yet supported!",
SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, property.getName());
writeGeoValue(property.getName(), type, property.asGeospatial(), isNullable, json);
} else if (property.isEnum()) {
writePrimitiveValue(property.getName(), type, property.asEnum(),
isNullable, maxLength, precision, scale, isUnicode, json);
@ -808,12 +829,105 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
}
}
/** Writes a geospatial value following the GeoJSON specification defined in RFC 7946. */
protected void writeGeoValue(final String name, final EdmPrimitiveType type, final Geospatial geoValue,
final Boolean isNullable, JsonGenerator json)
throws EdmPrimitiveTypeException, IOException, SerializerException {
if (geoValue == null) {
if (isNullable == null || isNullable) {
json.writeNull();
} else {
throw new EdmPrimitiveTypeException("The literal 'null' is not allowed.");
}
} else {
if (!type.getDefaultType().isAssignableFrom(geoValue.getClass())) {
throw new EdmPrimitiveTypeException("The value type " + geoValue.getClass() + " is not supported.");
}
if (geoValue.getSrid() != null && geoValue.getSrid().isNotDefault()) {
throw new SerializerException("Non-standard SRID not supported!",
SerializerException.MessageKeys.WRONG_PROPERTY_VALUE, name, geoValue.toString());
}
json.writeStartObject();
json.writeStringField(Constants.ATTR_TYPE, geoValueTypeToJsonName.get(geoValue.getGeoType()));
json.writeFieldName(geoValue.getGeoType() == Geospatial.Type.GEOSPATIALCOLLECTION ?
Constants.JSON_GEOMETRIES :
Constants.JSON_COORDINATES);
json.writeStartArray();
switch (geoValue.getGeoType()) {
case POINT:
writeGeoPoint(json, (Point) geoValue);
break;
case MULTIPOINT:
writeGeoPoints(json, (MultiPoint) geoValue);
break;
case LINESTRING:
writeGeoPoints(json, (LineString) geoValue);
break;
case MULTILINESTRING:
for (final LineString lineString : (MultiLineString) geoValue) {
json.writeStartArray();
writeGeoPoints(json, lineString);
json.writeEndArray();
}
break;
case POLYGON:
writeGeoPolygon(json, (Polygon) geoValue);
break;
case MULTIPOLYGON:
for (final Polygon polygon : (MultiPolygon) geoValue) {
json.writeStartArray();
writeGeoPolygon(json, polygon);
json.writeEndArray();
}
break;
case GEOSPATIALCOLLECTION:
for (final Geospatial element : (GeospatialCollection) geoValue) {
writeGeoValue(name, EdmPrimitiveTypeFactory.getInstance(element.getEdmPrimitiveTypeKind()),
element, isNullable, json);
}
break;
}
json.writeEndArray();
json.writeEndObject();
}
}
private void writeGeoPoint(JsonGenerator json, final Point point) throws IOException {
json.writeNumber(point.getX());
json.writeNumber(point.getY());
if (point.getZ() != 0) {
json.writeNumber(point.getZ());
}
}
private void writeGeoPoints(JsonGenerator json, final ComposedGeospatial<Point> points) throws IOException {
for (final Point point : points) {
json.writeStartArray();
writeGeoPoint(json, point);
json.writeEndArray();
}
}
// TODO: There could be a more strict verification that the lines describe boundaries
// and have the correct winding order.
// But arguably the better place for this is the constructor of the Polygon object.
private void writeGeoPolygon(JsonGenerator json, final Polygon polygon) throws IOException {
json.writeStartArray();
writeGeoPoints(json, polygon.getExterior());
json.writeEndArray();
if (!polygon.getInterior().isEmpty()) {
json.writeStartArray();
writeGeoPoints(json, polygon.getInterior());
json.writeEndArray();
}
}
protected void writeComplexValue(final ServiceMetadata metadata,
final EdmComplexType type, final List<Property> properties,
final Set<List<String>> selectedPaths, final JsonGenerator json)
throws IOException, SerializerException {
for (final String propertyName : type.getPropertyNames()) {
for (final String propertyName : type.getPropertyNames()) {
final Property property = findProperty(propertyName, properties);
if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) {
writeProperty(metadata, (EdmProperty) type.getProperty(propertyName), property,

View File

@ -31,7 +31,9 @@ import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.olingo.commons.api.Constants;
@ -44,6 +46,14 @@ import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edm.geo.Geospatial;
import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
import org.apache.olingo.commons.api.edm.geo.LineString;
import org.apache.olingo.commons.api.edm.geo.MultiLineString;
import org.apache.olingo.commons.api.edm.geo.MultiPoint;
import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
import org.apache.olingo.commons.api.edm.geo.Point;
import org.apache.olingo.commons.api.edm.geo.Polygon;
import org.apache.olingo.commons.api.edm.provider.CsdlMapping;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.OData;
@ -53,11 +63,13 @@ import org.apache.olingo.server.api.deserializer.ODataDeserializer;
import org.apache.olingo.server.core.deserializer.AbstractODataDeserializerTest;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTest {
private static final ContentType CONTENT_TYPE_JSON_IEEE754Compatible =
ContentType.create(ContentType.JSON, ContentType.PARAMETER_IEEE754_COMPATIBLE, "true");
private static final OData odata = OData.newInstance();
@Test
public void emptyEntity() throws Exception {
@ -657,6 +669,231 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
assertEquals((short) 3, entity.getProperty("PropertyEnumString").getValue());
}
@Test
public void geoPoint() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryPoint);
final String preamble = "{\"" + entityType.getPropertyNames().get(0) + "\":{";
final Entity entity = deserialize(preamble + "\"type\":\"Point\",\"coordinates\":[1.25,2.75]}}",
entityType);
assertEquals(1, entity.getProperties().size());
assertTrue(entity.getProperties().get(0).getValue() instanceof Point);
final Point point = (Point) entity.getProperties().get(0).getValue();
assertEquals(Geospatial.Dimension.GEOMETRY, point.getDimension());
assertEquals(1.25, point.getX(), 0);
assertEquals(2.75, point.getY(), 0);
expectException(preamble + "}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":1}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"point\",\"coordinates\":null}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"LineString\"}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\"}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coord\":[]}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.UNKNOWN_CONTENT);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":\"1 2\"}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":{\"x\":1,\"y\":2}}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":[]}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":[1]}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":[\"1\",2]}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":[1,\"2\"]}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":[1,2,\"3\"]}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":[1,2,3,4]}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":[12345678901234567,2]}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException(preamble + "\"type\":\"Point\",\"coordinates\":[1,2],\"extra\":\"extra\"}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.UNKNOWN_CONTENT);
}
@Test
public void geoMultiPoint() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeographyMultiPoint);
final Entity entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiPoint\",\"coordinates\":[[2.5,3.125,99],[3.5,4.125],[4.5,5.125]]}}",
entityType);
assertTrue(entity.getProperties().get(0).getValue() instanceof MultiPoint);
final MultiPoint multiPoint = (MultiPoint) entity.getProperties().get(0).getValue();
assertEquals(Geospatial.Dimension.GEOGRAPHY, multiPoint.getDimension());
Iterator<Point> iterator = multiPoint.iterator();
final Point point1 = iterator.next();
assertEquals(Geospatial.Dimension.GEOGRAPHY, point1.getDimension());
assertEquals(2.5, point1.getX(), 0);
assertEquals(3.125, point1.getY(), 0);
assertEquals(99, point1.getZ(), 0);
final Point point2 = iterator.next();
assertEquals(Geospatial.Dimension.GEOGRAPHY, point2.getDimension());
assertEquals(3.5, point2.getX(), 0);
assertEquals(4.125, point2.getY(), 0);
final Point point3 = iterator.next();
assertEquals(Geospatial.Dimension.GEOGRAPHY, point3.getDimension());
assertEquals(4.5, point3.getX(), 0);
assertEquals(5.125, point3.getY(), 0);
assertFalse(iterator.hasNext());
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiPoint\",\"coordinates\":[{\"x\":1,\"y\":2}]}}",
entityType, ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
}
@Test
public void geoLineString() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryLineString);
final Entity entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"LineString\",\"coordinates\":[[1.0,1.0],[2.0,2.0]]}}",
entityType);
assertTrue(entity.getProperties().get(0).getValue() instanceof LineString);
final LineString lineString = (LineString) entity.getProperties().get(0).getValue();
assertEquals(Geospatial.Dimension.GEOMETRY, lineString.getDimension());
Iterator<Point> iterator = lineString.iterator();
final Point point1 = iterator.next();
assertEquals(Geospatial.Dimension.GEOMETRY, point1.getDimension());
assertEquals(1, point1.getX(), 0);
assertEquals(1, point1.getY(), 0);
final Point point2 = iterator.next();
assertEquals(Geospatial.Dimension.GEOMETRY, point2.getDimension());
assertEquals(2, point2.getX(), 0);
assertEquals(2, point2.getY(), 0);
assertFalse(iterator.hasNext());
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{\"type\":\"LineString\"}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
// A proper line string has at least two points but the OData specification has another opinion
// so the following negative test would fail.
// expectException("{\"" + entityType.getPropertyNames().get(0)
// + "\":{\"type\":\"LineString\",\"coordinates\":[[1,2]]}}", entityType, ContentType.JSON,
// DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException("{\"" + entityType.getPropertyNames().get(0)
+ "\":{\"type\":\"LineString\",\"coordinates\":null}}", entityType, ContentType.JSON,
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
}
@Test
public void geoMultiLineString() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryMultiLineString);
final Entity entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiLineString\",\"coordinates\":["
+ "[[1.0,1.0],[2.0,2.0],[3.0,3.0],[4.0,4.0],[5.0,5.0]],"
+ "[[99.5,101.5],[150.0,151.25]]]}}",
entityType);
assertTrue(entity.getProperties().get(0).getValue() instanceof MultiLineString);
final MultiLineString multiLineString = (MultiLineString) entity.getProperties().get(0).getValue();
assertEquals(Geospatial.Dimension.GEOMETRY, multiLineString.getDimension());
assertEquals(1, multiLineString.iterator().next().iterator().next().getY(), 0);
expectException("{\"" + entityType.getPropertyNames().get(0)
+ "\":{\"type\":\"MultiLineString\",\"coordinates\":null}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException("{\"" + entityType.getPropertyNames().get(0)
+ "\":{\"type\":\"MultiLineString\",\"coordinates\":\"1 2 3 4\"}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException("{\"" + entityType.getPropertyNames().get(0)
+ "\":{\"type\":\"MultiLineString\",\"coordinates\":[{\"first\":[[1,2],[3,4]]}]}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
}
@Test
public void geoPolygon() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryPolygon);
Entity entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":[[[0.0,0.0],[3.0,0.0],[3.0,3.0],[0.0,3.0],[0.0,0.0]],"
+ "[[1.0,1.0],[1.0,2.0],[2.0,2.0],[2.0,1.0],[1.0,1.0]]]}}",
entityType);
assertTrue(entity.getProperties().get(0).getValue() instanceof Polygon);
Polygon polygon = (Polygon) entity.getProperties().get(0).getValue();
assertEquals(Geospatial.Dimension.GEOMETRY, polygon.getDimension());
assertEquals(0, polygon.getExterior().iterator().next().getX(), 0);
assertEquals(1, polygon.getInterior().iterator().next().getY(), 0);
entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":[[[0,0],[3,0],[3,3],[0,3],[0,0]]]}}",
entityType);
polygon = (Polygon) entity.getProperties().get(0).getValue();
assertTrue(polygon.getInterior().isEmpty());
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":{\"ext\":[[0,0],[3,0],[0,3],[0,0]]}}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":[[[0,0],[3,0],[3,3],[0,3]]]}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":[[[0,0],[3,0],[3,3],[0,3],[42,87]]]}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":[[[0,0],[3,0],[3,3],[0,3],[0,0]],"
+ "[[1,1],[1,2],[2,2],[2,1],[1,1]],"
+ "[[1,1],[1,2],[2,2],[2,1],[1,1]]]}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
}
@Test
public void geoMultiPolygon() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryMultiPolygon);
final Entity entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiPolygon\",\"coordinates\":["
+ "[[[0.0,0.0],[3.0,0.0],[3.0,3.0],[0.0,3.0],[0.0,0.0]],"
+ "[[1.0,1.0],[1.0,2.0],[2.0,2.0],[2.0,1.0],[1.0,1.0]]],"
+ "[[[0.0,0.0],[30.0,0.0],[0.0,30.0],[0.0,0.0]]]]}}",
entityType);
final MultiPolygon multiPolygon = (MultiPolygon) entity.getProperties().get(0).getValue();
assertEquals(1, multiPolygon.iterator().next().getInterior().iterator().next().getX(), 0);
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiPolygon\",\"coordinates\":[{\"first\":[[[0,0],[3,0],[3,3],[0,3],[0,0]]]}]}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
}
@Test
public void geoCollection() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryCollection);
final Entity entity = deserialize("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"GeometryCollection\",\"geometries\":["
+ "{\"type\":\"Point\",\"coordinates\":[100.0,0.0]},"
+ "{\"type\":\"LineString\",\"coordinates\":[[101.0,0.0],[102.0,1.0]]}]}}",
entityType);
assertTrue(entity.getProperties().get(0).getValue() instanceof GeospatialCollection);
GeospatialCollection collection = (GeospatialCollection) entity.getProperties().get(0).getValue();
assertEquals(Geospatial.Dimension.GEOMETRY, collection.getDimension());
Iterator<Geospatial> iterator = collection.iterator();
final Geospatial point = iterator.next();
assertEquals(Geospatial.Dimension.GEOMETRY, point.getDimension());
assertEquals(Geospatial.Type.POINT, point.getGeoType());
assertEquals(100, ((Point) point).getX(), 0);
final Geospatial line = iterator.next();
assertEquals(Geospatial.Dimension.GEOMETRY, line.getDimension());
assertEquals(Geospatial.Type.LINESTRING, line.getGeoType());
assertEquals(101, ((LineString) line).iterator().next().getX(), 0);
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"GeometryCollection\",\"coordinates\":[0,0]}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.UNKNOWN_CONTENT);
expectException("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"GeometryCollection\",\"geometries\":[[0,0]]}}", entityType,
ContentType.JSON, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
}
private EdmEntityType mockEntityType(final EdmPrimitiveTypeKind typeKind) {
EdmProperty property = Mockito.mock(EdmProperty.class);
final String name = "Property" + typeKind.name();
Mockito.when(property.getType()).thenReturn(odata.createPrimitiveTypeInstance(typeKind));
EdmEntityType entityType = Mockito.mock(EdmEntityType.class);
Mockito.when(entityType.getFullQualifiedName()).thenReturn(new FullQualifiedName(NAMESPACE, "entityType"));
Mockito.when(entityType.getPropertyNames()).thenReturn(Arrays.asList(name));
Mockito.when(entityType.getProperty(name)).thenReturn(property);
return entityType;
}
@Test
public void mappingTest() throws Exception {
EdmEntityType entityType = mock(EdmEntityType.class);
@ -670,22 +907,21 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
EdmProperty propertyDate = mock(EdmProperty.class);
when(propertyDate.getName()).thenReturn("PropertyDate");
when(propertyDate.getMapping()).thenReturn(mapping);
when(propertyDate.getType()).thenReturn(
OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date));
when(propertyDate.getType()).thenReturn(odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Date));
when(entityType.getProperty("PropertyDate")).thenReturn(propertyDate);
EdmProperty propertyDateTimeOffset = mock(EdmProperty.class);
when(propertyDateTimeOffset.getName()).thenReturn("PropertyDateTimeOffset");
when(propertyDateTimeOffset.getMapping()).thenReturn(mapping);
when(propertyDateTimeOffset.getType()).thenReturn(
OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset));
odata.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.DateTimeOffset));
when(entityType.getProperty("PropertyDateTimeOffset")).thenReturn(propertyDateTimeOffset);
String entityString =
"{\"PropertyDate\":\"2012-12-03\","
+ "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ContentType.JSON, metadata);
ODataDeserializer deserializer = odata.createDeserializer(ContentType.JSON, metadata);
Entity entity = deserializer.entity(stream, entityType).getEntity();
assertNotNull(entity);
List<Property> properties = entity.getProperties();
@ -844,7 +1080,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
}
@Test
public void unkownContentInEntity() throws Exception {
public void unknownContentInEntity() throws Exception {
final String entityString = "{"
+ "\"PropertyInt16\":32767,"
+ "\"unknown\": 12,"
@ -860,7 +1096,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
}
@Test
public void unkownContentInComplexProperty() throws Exception {
public void unknownContentInComplexProperty() throws Exception {
final String entityString = "{"
+ "\"PropertyInt16\":32767,"
+ "\"CollPropertyString\":"
@ -875,7 +1111,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
}
@Test
public void unkownContentInComplexCollectionProperty() throws Exception {
public void unknownContentInComplexCollectionProperty() throws Exception {
final String entityString = "{"
+ "\"PropertyInt16\":32767,"
+ "\"CollPropertyString\":"
@ -1363,15 +1599,18 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
protected static Entity deserialize(final InputStream stream, final String entityTypeName,
final ContentType contentType) throws DeserializerException {
return OData.newInstance().createDeserializer(contentType, metadata)
.entity(stream, edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName)))
.getEntity();
return deserializeWithResult(stream, entityTypeName, contentType).getEntity();
}
protected static DeserializerResult deserializeWithResult(final InputStream stream, final String entityTypeName,
final ContentType contentType) throws DeserializerException {
return OData.newInstance().createDeserializer(contentType, metadata)
.entity(stream, edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName)));
final EdmEntityType entityType = edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName));
return deserializeWithResult(stream, entityType, contentType);
}
protected static DeserializerResult deserializeWithResult(final InputStream stream, final EdmEntityType entityType,
final ContentType contentType) throws DeserializerException {
return odata.createDeserializer(contentType, metadata).entity(stream, entityType);
}
private static Entity deserialize(final String entityString, final String entityTypeName,
@ -1384,22 +1623,34 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
return deserialize(entityString, entityTypeName, ContentType.JSON);
}
private Entity deserialize(final String entityString, final EdmEntityType entityType)
throws DeserializerException {
return deserializeWithResult(new ByteArrayInputStream(entityString.getBytes()), entityType, ContentType.JSON)
.getEntity();
}
private static void checkPropertyJsonType(final String entityString) throws DeserializerException {
expectException(entityString, "ETAllPrim", DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY);
}
protected static void expectException(final String entityString, final String entityTypeName,
final ContentType contentType, final DeserializerException.MessageKeys messageKey) {
expectException(entityString,
edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName)), contentType, messageKey);
}
protected static void expectException(final String entityString, final String entityTypeName,
final DeserializerException.MessageKeys messageKey) {
expectException(entityString, entityTypeName, ContentType.JSON, messageKey);
}
private static void expectException(final String entityString, final String entityTypeName,
private static void expectException(final String entityString, final EdmEntityType entityType,
final ContentType contentType, final DeserializerException.MessageKeys messageKey) {
try {
deserialize(entityString, entityTypeName, contentType);
deserializeWithResult(new ByteArrayInputStream(entityString.getBytes()), entityType, contentType);
fail("Expected exception not thrown.");
} catch (final DeserializerException e) {
assertEquals(messageKey, e.getMessageKey());
}
}
}
}

View File

@ -18,6 +18,9 @@
*/
package org.apache.olingo.server.core.serializer.json;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
@ -44,7 +47,17 @@ import org.apache.olingo.commons.api.edm.EdmEntityContainer;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.edm.geo.Point;
import org.apache.olingo.commons.api.edm.geo.Polygon;
import org.apache.olingo.commons.api.edm.geo.SRID;
import org.apache.olingo.commons.api.edm.geo.Geospatial.Dimension;
import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
import org.apache.olingo.commons.api.edm.geo.LineString;
import org.apache.olingo.commons.api.edm.geo.MultiLineString;
import org.apache.olingo.commons.api.edm.geo.MultiPoint;
import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
import org.apache.olingo.commons.api.edmx.EdmxReference;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.OData;
@ -647,13 +660,13 @@ public class ODataJsonSerializerTest {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
InputStream result = serializer
.entity(metadata, edmEntitySet.getEntityType(), entity, EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build()).getContent();
.entity(metadata, edmEntitySet.getEntityType(), entity, EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.build()).getContent();
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"@odata.context\":\"$metadata#ESTwoPrim/$entity\"," +
"\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," +
"\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}";
final String expectedResult = "{\"@odata.context\":\"$metadata#ESTwoPrim/$entity\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}";
Assert.assertEquals(expectedResult, resultString);
}
@ -673,67 +686,67 @@ public class ODataJsonSerializerTest {
+ "\"value\":[{\"@odata.type\":\"#olingo.odata.test1.ETTwoPrim\",\"@odata.id\":\"ESTwoPrim(32766)\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":32766,"
+ "\"PropertyString\":\"Test String1\","
+"\"#olingo.odata.test1.BAETTwoPrimRTString\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\","
+"\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTString\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCollString\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\","
+"\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCollString\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\","
+"\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\","
+"\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}"
+ "\"#olingo.odata.test1.BAETTwoPrimRTString\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\","
+ "\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTString\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\","
+ "\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCollString\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\","
+ "\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\","
+ "\"target\":\"ESTwoPrim(32766)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}"
+ "},"
+ "{\"@odata.type\":\"#olingo.odata.test1.ETTwoPrim\",\"@odata.id\":\"ESTwoPrim(-365)\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":-365,"
+ "\"PropertyString\":\"Test String2\","
+ "\"NavPropertyETAllPrimMany@odata.navigationLink\":\"ESTwoPrim(-365)/NavPropertyETAllPrimMany\","
+"\"#olingo.odata.test1.BAETTwoPrimRTString\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\","
+"\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTString\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCollString\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\","
+"\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCollString\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\","
+"\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\","
+"\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTString\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\","
+ "\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTString\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\","
+ "\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCollString\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\","
+ "\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\","
+ "\"target\":\"ESTwoPrim(-365)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}},"
+ "{\"@odata.type\":\"#olingo.odata.test1.ETTwoPrim\",\"@odata.id\":\"ESTwoPrim(-32766)\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":-32766,"
+ "\"PropertyString\":null,"
+"\"#olingo.odata.test1.BAETTwoPrimRTString\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\","
+"\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTString\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCollString\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\","
+"\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCollString\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\","
+"\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\","
+"\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTString\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\","
+ "\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTString\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\","
+ "\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCollString\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\","
+ "\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\","
+ "\"target\":\"ESTwoPrim(-32766)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}},"
+ "{\"@odata.type\":\"#olingo.odata.test1.ETTwoPrim\",\"@odata.id\":\"ESTwoPrim(32767)\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"Test String4\","
+"\"NavPropertyETAllPrimOne@odata.navigationLink\":\"ESAllPrim(32767)\","
+"\"#olingo.odata.test1.BAETTwoPrimRTString\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\","
+"\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTString\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCollString\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\","
+"\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCollString\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\","
+"\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"},"
+"\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":"
+"{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\","
+"\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}"
+"}]}";
+ "\"NavPropertyETAllPrimOne@odata.navigationLink\":\"ESAllPrim(32767)\","
+ "\"#olingo.odata.test1.BAETTwoPrimRTString\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTString\","
+ "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTString\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCollString\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollString\","
+ "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCollString\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCTAllPrim\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCTAllPrim\","
+ "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCTAllPrim\"},"
+ "\"#olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\":"
+ "{\"title\":\"olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\","
+ "\"target\":\"ESTwoPrim(32767)/olingo.odata.test1.BAETTwoPrimRTCollCTAllPrim\"}"
+ "}]}";
Assert.assertEquals(expectedResult, resultString);
}
@ -972,20 +985,20 @@ public class ODataJsonSerializerTest {
.build()).getContent();
final String resultString = IOUtils.toString(result);
final String expected = "{"
+ "\"@odata.context\":\"$metadata#ESFourKeyAlias"
+ "(PropertyInt16,PropertyCompComp/PropertyComp/PropertyString)\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":["
+ "{"
+ "\"@odata.id\":\""
+ "ESFourKeyAlias(PropertyInt16=1,KeyAlias1=11,KeyAlias2='Num11',KeyAlias3='Num111')\","
+ "\"PropertyInt16\":1,"
+ "\"PropertyCompComp\":{"
+ "\"PropertyComp\":{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTBase\","
+ "\"PropertyString\":\"Num111\""
+ "}}}]}";
+ "\"@odata.context\":\"$metadata#ESFourKeyAlias"
+ "(PropertyInt16,PropertyCompComp/PropertyComp/PropertyString)\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":["
+ "{"
+ "\"@odata.id\":\""
+ "ESFourKeyAlias(PropertyInt16=1,KeyAlias1=11,KeyAlias2='Num11',KeyAlias3='Num111')\","
+ "\"PropertyInt16\":1,"
+ "\"PropertyCompComp\":{"
+ "\"PropertyComp\":{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTBase\","
+ "\"PropertyString\":\"Num111\""
+ "}}}]}";
Assert.assertEquals(expected, resultString);
}
@ -1000,24 +1013,24 @@ public class ODataJsonSerializerTest {
.contextURL(ContextURL.with().entitySet(edmEntitySet).build())
.build()).getContent();
final String resultString = IOUtils.toString(result);
String expected = "{"
+ "\"@odata.context\":\"$metadata#ESFourKeyAlias\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":[{"
+ "\"PropertyInt16\":1,"
+ "\"PropertyComp\":{"
+ "\"PropertyInt16\":11,"
+ "\"PropertyString\":\"Num11\""
+ "},"
+ "\"PropertyCompComp\":{"
+ "\"PropertyComp\":{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTBase\","
+ "\"PropertyInt16\":111,"
+ "\"PropertyString\":\"Num111\","
+ "\"AdditionalPropString\":\"Test123\""
+ "}}}]}";
final String expected = "{"
+ "\"@odata.context\":\"$metadata#ESFourKeyAlias\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":[{"
+ "\"PropertyInt16\":1,"
+ "\"PropertyComp\":{"
+ "\"PropertyInt16\":11,"
+ "\"PropertyString\":\"Num11\""
+ "},"
+ "\"PropertyCompComp\":{"
+ "\"PropertyComp\":{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTBase\","
+ "\"PropertyInt16\":111,"
+ "\"PropertyString\":\"Num111\","
+ "\"AdditionalPropString\":\"Test123\""
+ "}}}]}";
Assert.assertEquals(expected, resultString);
}
@ -1058,127 +1071,127 @@ public class ODataJsonSerializerTest {
Assert.assertEquals(expected, resultString);
}
@Test
public void selectComplexNestedCollectionOfComplexWithMetadataFull() throws Exception{
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp");
final EntityCollection entitySet = data.readAll(edmEntitySet);
InputStream result = serializerFullMetadata
.entityCollection(metadata, edmEntitySet.getEntityType(), entitySet,
@Test
public void selectComplexNestedCollectionOfComplexWithMetadataFull() throws Exception{
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp");
final EntityCollection entitySet = data.readAll(edmEntitySet);
InputStream result = serializerFullMetadata
.entityCollection(metadata, edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).build())
.build())
.getContent();
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"@odata.context\":\"$metadata#ESCompCollComp\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":[{\"@odata.type\":\"#olingo.odata.test1.ETCompCollComp\","
+ "\"@odata.id\":\"ESCompCollComp(32767)\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":32767,"
+ "\"PropertyComp\":{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTCompCollComp\","
+ "\"CollPropertyComp@odata.type\":\"#Collection(olingo.odata.test1.CTTwoPrim)\","
+ "\"CollPropertyComp\":["
+ "{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+ "\"PropertyInt16@odata.type\":\"#Int16\","
+"\"PropertyInt16\":555,"
+"\"PropertyString\":\"1 Test Complex in Complex Property\""
+"},{"
+"\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+"\"PropertyInt16@odata.type\":\"#Int16\","
+"\"PropertyInt16\":666,"
+"\"PropertyString\":\"2 Test Complex in Complex Property\""
+"},{"
+"\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+"\"PropertyInt16@odata.type\":\"#Int16\","
+"\"PropertyInt16\":777,"
+"\"PropertyString\":\"3 Test Complex in Complex Property\""
+"}]}},{"
+"\"@odata.type\":\"#olingo.odata.test1.ETCompCollComp\","
+"\"@odata.id\":\"ESCompCollComp(12345)\","
+"\"PropertyInt16@odata.type\":\"#Int16\","
+"\"PropertyInt16\":12345,"
+"\"PropertyComp\":{"
+"\"@odata.type\":\"#olingo.odata.test1.CTCompCollComp\","
+"\"CollPropertyComp@odata.type\":\"#Collection(olingo.odata.test1.CTTwoPrim)\","
+"\"CollPropertyComp\":["
+"{"
+"\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+"\"PropertyInt16@odata.type\":\"#Int16\","
+"\"PropertyInt16\":888,"
+"\"PropertyString\":\"11 Test Complex in Complex Property\""
+"},{"
+"\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+"\"PropertyInt16@odata.type\":\"#Int16\","
+"\"PropertyInt16\":999,"
+"\"PropertyString\":\"12 Test Complex in Complex Property\""
+"},{"
+"\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+"\"PropertyInt16@odata.type\":\"#Int16\","
+"\"PropertyInt16\":0,"
+"\"PropertyString\":\"13 Test Complex in Complex Property\""
+"}]}}]}";
Assert.assertEquals(expectedResult, resultString);
}
@Test
public void selectComplexNestedCollectionOfComplexWithMetadataMinimal() throws Exception{
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp");
final EntityCollection entitySet = data.readAll(edmEntitySet);
InputStream result = serializer
.entityCollection(metadata, edmEntitySet.getEntityType(), entitySet,
.getContent();
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"@odata.context\":\"$metadata#ESCompCollComp\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":[{\"@odata.type\":\"#olingo.odata.test1.ETCompCollComp\","
+ "\"@odata.id\":\"ESCompCollComp(32767)\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":32767,"
+ "\"PropertyComp\":{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTCompCollComp\","
+ "\"CollPropertyComp@odata.type\":\"#Collection(olingo.odata.test1.CTTwoPrim)\","
+ "\"CollPropertyComp\":["
+ "{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+ "\"PropertyInt16@odata.type\":\"#Int16\","
+ "\"PropertyInt16\":555,"
+ "\"PropertyString\":\"1 Test Complex in Complex Property\""
+ "},{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+ "\"PropertyInt16@odata.type\":\"#Int16\","
+ "\"PropertyInt16\":666,"
+ "\"PropertyString\":\"2 Test Complex in Complex Property\""
+ "},{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+ "\"PropertyInt16@odata.type\":\"#Int16\","
+ "\"PropertyInt16\":777,"
+ "\"PropertyString\":\"3 Test Complex in Complex Property\""
+ "}]}},{"
+ "\"@odata.type\":\"#olingo.odata.test1.ETCompCollComp\","
+ "\"@odata.id\":\"ESCompCollComp(12345)\","
+ "\"PropertyInt16@odata.type\":\"#Int16\","
+ "\"PropertyInt16\":12345,"
+ "\"PropertyComp\":{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTCompCollComp\","
+ "\"CollPropertyComp@odata.type\":\"#Collection(olingo.odata.test1.CTTwoPrim)\","
+ "\"CollPropertyComp\":["
+ "{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+ "\"PropertyInt16@odata.type\":\"#Int16\","
+ "\"PropertyInt16\":888,"
+ "\"PropertyString\":\"11 Test Complex in Complex Property\""
+ "},{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+ "\"PropertyInt16@odata.type\":\"#Int16\","
+ "\"PropertyInt16\":999,"
+ "\"PropertyString\":\"12 Test Complex in Complex Property\""
+ "},{"
+ "\"@odata.type\":\"#olingo.odata.test1.CTTwoPrim\","
+ "\"PropertyInt16@odata.type\":\"#Int16\","
+ "\"PropertyInt16\":0,"
+ "\"PropertyString\":\"13 Test Complex in Complex Property\""
+ "}]}}]}";
Assert.assertEquals(expectedResult, resultString);
}
@Test
public void selectComplexNestedCollectionOfComplexWithMetadataMinimal() throws Exception{
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp");
final EntityCollection entitySet = data.readAll(edmEntitySet);
InputStream result = serializer
.entityCollection(metadata, edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).build())
.build())
.getContent();
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"@odata.context\":\"$metadata#ESCompCollComp\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":[{"
+ "\"PropertyInt16\":32767,"
+ "\"PropertyComp\":{"
+ "\"CollPropertyComp\":["
+ "{"
+"\"PropertyInt16\":555,"
+"\"PropertyString\":\"1 Test Complex in Complex Property\""
+"},{"
+"\"PropertyInt16\":666,"
+"\"PropertyString\":\"2 Test Complex in Complex Property\""
+"},{"
+"\"PropertyInt16\":777,"
+"\"PropertyString\":\"3 Test Complex in Complex Property\""
+"}]}},{"
+"\"PropertyInt16\":12345,"
+"\"PropertyComp\":{"
+"\"CollPropertyComp\":["
+"{"
+"\"PropertyInt16\":888,"
+"\"PropertyString\":\"11 Test Complex in Complex Property\""
+"},{"
+"\"PropertyInt16\":999,"
+"\"PropertyString\":\"12 Test Complex in Complex Property\""
+"},{"
+"\"PropertyInt16\":0,"
+"\"PropertyString\":\"13 Test Complex in Complex Property\""
+"}]}}]}";
Assert.assertEquals(expectedResult, resultString);
}
@Test
public void selectComplexNestedCollectionOfComplexWithMetadataNone() throws Exception{
final String METADATA_TEXT = "@odata.";
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp");
final EntityCollection entitySet = data.readAll(edmEntitySet);
InputStream result = serializerNoMetadata
.entityCollection(metadata, edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).build())
.build())
.getContent();
final String resultString = IOUtils.toString(result);
Assert.assertEquals(false, resultString.contains(METADATA_TEXT));
}
.getContent();
final String resultString = IOUtils.toString(result);
final String expectedResult = "{\"@odata.context\":\"$metadata#ESCompCollComp\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":[{"
+ "\"PropertyInt16\":32767,"
+ "\"PropertyComp\":{"
+ "\"CollPropertyComp\":["
+ "{"
+ "\"PropertyInt16\":555,"
+ "\"PropertyString\":\"1 Test Complex in Complex Property\""
+ "},{"
+ "\"PropertyInt16\":666,"
+ "\"PropertyString\":\"2 Test Complex in Complex Property\""
+ "},{"
+ "\"PropertyInt16\":777,"
+ "\"PropertyString\":\"3 Test Complex in Complex Property\""
+ "}]}},{"
+ "\"PropertyInt16\":12345,"
+ "\"PropertyComp\":{"
+ "\"CollPropertyComp\":["
+ "{"
+ "\"PropertyInt16\":888,"
+ "\"PropertyString\":\"11 Test Complex in Complex Property\""
+ "},{"
+ "\"PropertyInt16\":999,"
+ "\"PropertyString\":\"12 Test Complex in Complex Property\""
+ "},{"
+ "\"PropertyInt16\":0,"
+ "\"PropertyString\":\"13 Test Complex in Complex Property\""
+ "}]}}]}";
Assert.assertEquals(expectedResult, resultString);
}
@Test
public void selectComplexNestedCollectionOfComplexWithMetadataNone() throws Exception{
final String METADATA_TEXT = "@odata.";
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompCollComp");
final EntityCollection entitySet = data.readAll(edmEntitySet);
InputStream result = serializerNoMetadata
.entityCollection(metadata, edmEntitySet.getEntityType(), entitySet,
EntityCollectionSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).build())
.build())
.getContent();
final String resultString = IOUtils.toString(result);
Assert.assertEquals(false, resultString.contains(METADATA_TEXT));
}
@Test(expected = SerializerException.class)
public void selectMissingId() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
@ -1386,27 +1399,27 @@ public class ODataJsonSerializerTest {
.expand(expand)
.build()).getContent());
Assert.assertEquals("{\"@odata.context\":\"$metadata#ESTwoPrim/$entity\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\","
+ "\"NavPropertyETAllPrimOne\":null,"
+ "\"NavPropertyETAllPrimMany\":["
+ "{\"PropertyInt16\":-32768,\"PropertyString\":\"Second Resource - negative values\","
+ "\"PropertyBoolean\":false,\"PropertyByte\":0,\"PropertySByte\":-128,\"PropertyInt32\":-2147483648,"
+ "\"PropertyInt64\":-9223372036854775808,\"PropertySingle\":-1.79E8,\"PropertyDouble\":-179000.0,"
+ "\"PropertyDecimal\":-34,\"PropertyBinary\":\"ASNFZ4mrze8=\",\"PropertyDate\":\"2015-11-05\","
+ "\"PropertyDateTimeOffset\":\"2005-12-03T07:17:08Z\",\"PropertyDuration\":\"PT9S\","
+ "\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789dddfff\",\"PropertyTimeOfDay\":\"23:49:14\","
+ "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]},"
+ "{\"PropertyInt16\":0,\"PropertyString\":\"\",\"PropertyBoolean\":false,\"PropertyByte\":0,"
+ "\"PropertySByte\":0,\"PropertyInt32\":0,\"PropertyInt64\":0,\"PropertySingle\":0.0,"
+ "\"PropertyDouble\":0.0,\"PropertyDecimal\":0,\"PropertyBinary\":\"\","
+ "\"PropertyDate\":\"1970-01-01\",\"PropertyDateTimeOffset\":\"2005-12-03T00:00:00Z\","
+ "\"PropertyDuration\":\"PT0S\",\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789cccddd\","
+ "\"PropertyTimeOfDay\":\"00:01:01\",\"NavPropertyETTwoPrimOne\":null,"
+ "\"NavPropertyETTwoPrimMany\":["
+ "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"},"
+ "{\"PropertyInt16\":-32766,\"PropertyString\":null},"
+ "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}",
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\","
+ "\"NavPropertyETAllPrimOne\":null,"
+ "\"NavPropertyETAllPrimMany\":["
+ "{\"PropertyInt16\":-32768,\"PropertyString\":\"Second Resource - negative values\","
+ "\"PropertyBoolean\":false,\"PropertyByte\":0,\"PropertySByte\":-128,\"PropertyInt32\":-2147483648,"
+ "\"PropertyInt64\":-9223372036854775808,\"PropertySingle\":-1.79E8,\"PropertyDouble\":-179000.0,"
+ "\"PropertyDecimal\":-34,\"PropertyBinary\":\"ASNFZ4mrze8=\",\"PropertyDate\":\"2015-11-05\","
+ "\"PropertyDateTimeOffset\":\"2005-12-03T07:17:08Z\",\"PropertyDuration\":\"PT9S\","
+ "\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789dddfff\",\"PropertyTimeOfDay\":\"23:49:14\","
+ "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]},"
+ "{\"PropertyInt16\":0,\"PropertyString\":\"\",\"PropertyBoolean\":false,\"PropertyByte\":0,"
+ "\"PropertySByte\":0,\"PropertyInt32\":0,\"PropertyInt64\":0,\"PropertySingle\":0.0,"
+ "\"PropertyDouble\":0.0,\"PropertyDecimal\":0,\"PropertyBinary\":\"\","
+ "\"PropertyDate\":\"1970-01-01\",\"PropertyDateTimeOffset\":\"2005-12-03T00:00:00Z\","
+ "\"PropertyDuration\":\"PT0S\",\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789cccddd\","
+ "\"PropertyTimeOfDay\":\"00:01:01\",\"NavPropertyETTwoPrimOne\":null,"
+ "\"NavPropertyETTwoPrimMany\":["
+ "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"},"
+ "{\"PropertyInt16\":-32766,\"PropertyString\":null},"
+ "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}",
resultString);
}
@ -1908,24 +1921,182 @@ public class ODataJsonSerializerTest {
}
Assert.assertEquals(3, count);
}
@Test
public void expandCycle() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESPeople");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(1);
ExpandItem mockExpandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "friends");
LevelsExpandOption levels = Mockito.mock(LevelsExpandOption.class);
Mockito.when(levels.isMax()).thenReturn(Boolean.TRUE);
Mockito.when(mockExpandItem.getLevelsOption()).thenReturn(levels);
final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(
mockExpandItem));
InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.expand(expand)
.build()).getContent();
final String resultString = IOUtils.toString(result);
String expected = "{" +
@Test
public void geoPoint() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryPoint);
Entity entity = new Entity()
.addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
createPoint(1.5, 4.25)));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Point\",\"coordinates\":[1.5,4.25]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
Point point = new Point(Dimension.GEOMETRY, null);
point.setZ(42);
entity = new Entity().addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
point));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Point\",\"coordinates\":[0.0,0.0,42.0]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
}
@Test
public void geoMultiPoint() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryMultiPoint);
final Entity entity = new Entity()
.addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
new MultiPoint(Dimension.GEOMETRY, null, Arrays.asList(
createPoint(2.5, 3.125), createPoint(3.5, 4.125), createPoint(4.5, 5.125)))));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiPoint\",\"coordinates\":[[2.5,3.125],[3.5,4.125],[4.5,5.125]]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
}
@Test
public void geoLineString() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryLineString);
final Entity entity = new Entity()
.addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
new LineString(Dimension.GEOMETRY, null, Arrays.asList(
createPoint(1, 1), createPoint(2, 2), createPoint(3, 3), createPoint(4, 4), createPoint(5, 5)))));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"LineString\",\"coordinates\":[[1.0,1.0],[2.0,2.0],[3.0,3.0],[4.0,4.0],[5.0,5.0]]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
}
@Test
public void geoMultiLineString() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryMultiLineString);
final Entity entity = new Entity()
.addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
new MultiLineString(Dimension.GEOMETRY, null, Arrays.asList(
new LineString(Dimension.GEOMETRY, null, Arrays.asList(
createPoint(1, 1), createPoint(2, 2), createPoint(3, 3), createPoint(4, 4), createPoint(5, 5))),
new LineString(Dimension.GEOMETRY, null, Arrays.asList(
createPoint(99.5, 101.5), createPoint(150, 151.25)))))));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiLineString\",\"coordinates\":["
+ "[[1.0,1.0],[2.0,2.0],[3.0,3.0],[4.0,4.0],[5.0,5.0]],"
+ "[[99.5,101.5],[150.0,151.25]]]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
}
@Test
public void geoPolygon() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryPolygon);
Entity entity = new Entity()
.addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
new Polygon(Dimension.GEOMETRY, null,
Arrays.asList(
createPoint(1, 1), createPoint(1, 2), createPoint(2, 2), createPoint(2, 1), createPoint(1, 1)),
Arrays.asList(
createPoint(0, 0), createPoint(3, 0), createPoint(3, 3), createPoint(0, 3), createPoint(0, 0)))));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":[[[0.0,0.0],[3.0,0.0],[3.0,3.0],[0.0,3.0],[0.0,0.0]],"
+ "[[1.0,1.0],[1.0,2.0],[2.0,2.0],[2.0,1.0],[1.0,1.0]]]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
entity = new Entity().addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
new Polygon(Dimension.GEOMETRY, null, null, Arrays.asList(
createPoint(10, 10), createPoint(30, 10), createPoint(30, 30), createPoint(10, 30),
createPoint(10, 10)))));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"Polygon\",\"coordinates\":[[[10.0,10.0],[30.0,10.0],[30.0,30.0],[10.0,30.0],[10.0,10.0]]]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
}
@Test
public void geoMultiPolygon() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryMultiPolygon);
final Entity entity = new Entity()
.addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
new MultiPolygon(Dimension.GEOMETRY, null, Arrays.asList(
new Polygon(Dimension.GEOMETRY, null,
Arrays.asList(
createPoint(1, 1), createPoint(1, 2), createPoint(2, 2), createPoint(2, 1), createPoint(1, 1)),
Arrays.asList(
createPoint(0, 0), createPoint(3, 0), createPoint(3, 3), createPoint(0, 3),
createPoint(0, 0))),
new Polygon(Dimension.GEOMETRY, null,
Arrays.asList(
createPoint(10, 10), createPoint(10, 20), createPoint(20, 10), createPoint(10, 10)),
Arrays.asList(
createPoint(0, 0), createPoint(30, 0), createPoint(0, 30), createPoint(0, 0)))))));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"MultiPolygon\",\"coordinates\":["
+ "[[[0.0,0.0],[3.0,0.0],[3.0,3.0],[0.0,3.0],[0.0,0.0]],"
+ "[[1.0,1.0],[1.0,2.0],[2.0,2.0],[2.0,1.0],[1.0,1.0]]],"
+ "[[[0.0,0.0],[30.0,0.0],[0.0,30.0],[0.0,0.0]],"
+ "[[10.0,10.0],[10.0,20.0],[20.0,10.0],[10.0,10.0]]]]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
}
@Test
public void geoCollection() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryCollection);
final Entity entity = new Entity()
.addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
new GeospatialCollection(Dimension.GEOMETRY, null, Arrays.asList(
createPoint(100, 0),
new LineString(Dimension.GEOMETRY, null, Arrays.asList(createPoint(101, 0), createPoint(102, 1)))))));
Assert.assertEquals("{\"" + entityType.getPropertyNames().get(0) + "\":{"
+ "\"type\":\"GeometryCollection\",\"geometries\":["
+ "{\"type\":\"Point\",\"coordinates\":[100.0,0.0]},"
+ "{\"type\":\"LineString\",\"coordinates\":[[101.0,0.0],[102.0,1.0]]}]}}",
IOUtils.toString(serializerNoMetadata.entity(metadata, entityType, entity, null).getContent()));
}
private EdmEntityType mockEntityType(final EdmPrimitiveTypeKind type) {
EdmProperty property = Mockito.mock(EdmProperty.class);
final String name = "Property" + type.name();
Mockito.when(property.getName()).thenReturn(name);
Mockito.when(property.getType()).thenReturn(odata.createPrimitiveTypeInstance(type));
Mockito.when(property.isPrimitive()).thenReturn(true);
EdmEntityType entityType = Mockito.mock(EdmEntityType.class);
Mockito.when(entityType.getPropertyNames()).thenReturn(Arrays.asList(name));
Mockito.when(entityType.getStructuralProperty(name)).thenReturn(property);
return entityType;
}
@Test
public void geoNonstandardSRID() throws Exception {
final EdmEntityType entityType = mockEntityType(EdmPrimitiveTypeKind.GeometryPoint);
final Entity entity = new Entity()
.addProperty(new Property(null, entityType.getPropertyNames().get(0), ValueType.GEOSPATIAL,
new Point(Dimension.GEOMETRY, SRID.valueOf("42"))));
try {
serializerNoMetadata.entity(metadata, entityType, entity, null);
fail("Expected exception not thrown.");
} catch (final SerializerException e) {
assertNotNull(e);
}
}
private Point createPoint(final double x, final double y) {
Point point = new Point(Dimension.GEOMETRY, null);
point.setX(x);
point.setY(y);
return point;
}
@Test
public void expandCycle() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESPeople");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(1);
ExpandItem mockExpandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "friends");
LevelsExpandOption levels = Mockito.mock(LevelsExpandOption.class);
Mockito.when(levels.isMax()).thenReturn(Boolean.TRUE);
Mockito.when(mockExpandItem.getLevelsOption()).thenReturn(levels);
final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(mockExpandItem));
InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.expand(expand)
.build())
.getContent();
final String resultString = IOUtils.toString(result);
final String expected = "{" +
"\"@odata.context\":\"$metadata#ESPeople/$entity\"," +
"\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," +
"\"id\":1," +
@ -1981,27 +2152,27 @@ public class ODataJsonSerializerTest {
"}" +
"]" +
"}";
Assert.assertEquals(expected, resultString);
}
@Test
public void expandCycleWith3Level() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESPeople");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(1);
ExpandItem mockExpandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "friends");
LevelsExpandOption levels = Mockito.mock(LevelsExpandOption.class);
Mockito.when(levels.isMax()).thenReturn(Boolean.FALSE);
Mockito.when(levels.getValue()).thenReturn(3);
Mockito.when(mockExpandItem.getLevelsOption()).thenReturn(levels);
final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(
mockExpandItem));
InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.expand(expand)
.build()).getContent();
final String resultString = IOUtils.toString(result);
String expected = "{" +
Assert.assertEquals(expected, resultString);
}
@Test
public void expandCycleWith3Level() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESPeople");
final Entity entity = data.readAll(edmEntitySet).getEntities().get(1);
ExpandItem mockExpandItem = ExpandSelectMock.mockExpandItem(edmEntitySet, "friends");
LevelsExpandOption levels = Mockito.mock(LevelsExpandOption.class);
Mockito.when(levels.isMax()).thenReturn(Boolean.FALSE);
Mockito.when(levels.getValue()).thenReturn(3);
Mockito.when(mockExpandItem.getLevelsOption()).thenReturn(levels);
final ExpandOption expand = ExpandSelectMock.mockExpandOption(Collections.singletonList(mockExpandItem));
InputStream result = serializer.entity(metadata, edmEntitySet.getEntityType(), entity,
EntitySerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build())
.expand(expand)
.build())
.getContent();
final String resultString = IOUtils.toString(result);
final String expected = "{" +
"\"@odata.context\":\"$metadata#ESPeople/$entity\"," +
"\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," +
"\"id\":1," +
@ -2055,6 +2226,6 @@ public class ODataJsonSerializerTest {
"}" +
"]" +
"}";
Assert.assertEquals(expected, resultString);
}
Assert.assertEquals(expected, resultString);
}
}