[OLINGO-530] Bind Operation and tests

This commit is contained in:
Christian Amend 2015-01-21 09:56:37 +01:00
parent 7f7369c7df
commit 5e9fa5431d
12 changed files with 585 additions and 44 deletions

View File

@ -18,6 +18,8 @@
*/
package org.apache.olingo.commons.api.data;
import java.util.List;
public interface Link extends Annotatable {
/**
@ -118,4 +120,28 @@ public interface Link extends Annotatable {
*/
void setInlineEntitySet(EntitySet entitySet);
/**
* If this is a "toOne" relationship this method delivers the binding link or <tt>null</tt> if not set.
* @return String the binding link.
*/
String getBindingLink();
/**
* Sets the binding link.
* @param bindingLink
*/
void setBindingLink(String bindingLink);
/**
* If this is a "toMany" relationship this method delivers the binding links or <tt>emptyList</tt> if not set.
* @return a list of binding links.
*/
List<String> getBindingLinks();
/**
* Sets the binding links. List MUST NOT be <tt>null</tt>.
* @param bindingLinks
*/
void setBindingLinks(List<String> bindingLinks);
}

View File

@ -51,4 +51,18 @@ public interface Linked {
* @return links.
*/
List<Link> getNavigationLinks();
/**
* Gets binding link with given name, if available, otherwise <tt>null</tt>.
* @param name candidate link name
* @return binding link with given name, if available, otherwise <tt>null</tt>
*/
Link getNavigationBinding(String name);
/**
* Gets binding links.
*
* @return links.
*/
List<Link> getNavigationBindings();
}

View File

@ -42,7 +42,17 @@ public enum ODataLinkType {
/**
* Media-edit link.
*/
MEDIA_EDIT("*/*");
MEDIA_EDIT("*/*"),
/**
* Entity binding link.
*/
ENTITY_BINDING(ContentType.APPLICATION_XML),
/**
* Entity collection binding link.
*/
ENTITY_COLLECTION_BINDING(ContentType.APPLICATION_XML);
private String type;

View File

@ -42,6 +42,7 @@ public class EntityImpl extends AbstractODataObject implements Entity {
private final List<Link> associationLinks = new ArrayList<Link>();
private final List<Link> navigationLinks = new ArrayList<Link>();
private final List<Link> mediaEditLinks = new ArrayList<Link>();
private final List<Link> bindingLinks = new ArrayList<Link>();
private final List<ODataOperation> operations = new ArrayList<ODataOperation>();
@ -126,6 +127,16 @@ public class EntityImpl extends AbstractODataObject implements Entity {
public List<Link> getMediaEditLinks() {
return mediaEditLinks;
}
@Override
public Link getNavigationBinding(String name) {
return getOneByTitle(name, bindingLinks);
}
@Override
public List<Link> getNavigationBindings() {
return bindingLinks;
}
@Override
public List<ODataOperation> getOperations() {

View File

@ -18,6 +18,9 @@
*/
package org.apache.olingo.commons.core.data;
import java.util.ArrayList;
import java.util.List;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Link;
@ -31,6 +34,8 @@ public class LinkImpl extends AbstractAnnotatedObject implements Link {
private String mediaETag;
private Entity entity;
private EntitySet entitySet;
private String bindingLink;
private List<String> bindingLinks = new ArrayList<String>();
@Override
public String getTitle() {
@ -101,4 +106,24 @@ public class LinkImpl extends AbstractAnnotatedObject implements Link {
public void setInlineEntitySet(final EntitySet entitySet) {
this.entitySet = entitySet;
}
@Override
public String getBindingLink() {
return bindingLink;
}
@Override
public List<String> getBindingLinks() {
return bindingLinks;
}
@Override
public void setBindingLink(String bindingLink) {
this.bindingLink = bindingLink;
}
@Override
public void setBindingLinks(List<String> bindingLinks) {
this.bindingLinks = bindingLinks;
}
}

View File

@ -31,6 +31,7 @@ public class LinkedComplexValueImpl implements LinkedComplexValue {
private final List<Property> value = new ArrayList<Property>();
private final List<Link> associationLinks = new ArrayList<Link>();
private final List<Link> navigationLinks = new ArrayList<Link>();
private final List<Link> bindingLinks = new ArrayList<Link>();
private final List<Annotation> annotations = new ArrayList<Annotation>();
@Override
@ -74,4 +75,14 @@ public class LinkedComplexValueImpl implements LinkedComplexValue {
public List<Annotation> getAnnotations() {
return annotations;
}
@Override
public Link getNavigationBinding(String name) {
return getOneByTitle(name, bindingLinks);
}
@Override
public List<Link> getNavigationBindings() {
return bindingLinks;
}
}

View File

@ -42,7 +42,10 @@ public class DeserializerException extends ODataTranslatedException {
/** parameter: navigationPropertyName */INVALID_VALUE_FOR_NAVIGATION_PROPERTY,
DUPLICATE_PROPERTY,
DUPLICATE_JSON_PROPERTY,
/** parameters: primitiveTypeName, propertyName */ UNKNOWN_PRIMITIVE_TYPE;
/** parameters: primitiveTypeName, propertyName */ UNKNOWN_PRIMITIVE_TYPE,
/** parameter: navigationPropertyName */NAVIGATION_PROPERTY_NOT_FOUND,
/** parameter: annotationName */INVALID_ANNOTATION_TYPE,
/** parameter: annotationName */INVALID_NULL_ANNOTATION;
@Override
public String getKey() {

View File

@ -29,6 +29,7 @@ import java.util.Map.Entry;
import org.apache.olingo.commons.api.Constants;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.EntitySet;
import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.domain.ODataLinkType;
@ -130,7 +131,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
Iterator<JsonNode> arrayIterator = jsonNode.iterator();
while (arrayIterator.hasNext()) {
JsonNode arrayElement = (JsonNode) arrayIterator.next();
if (arrayElement.isContainerNode() && arrayElement.isArray()) {
if (arrayElement.isArray() || arrayElement.isValueNode()) {
throw new DeserializerException("Nested Arrays and primitive values are not allowed for an entity value.",
DeserializerException.MessageKeys.INVALID_ENTITY);
}
@ -171,8 +172,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
JsonNode jsonNode = tree.get(propertyName);
if (jsonNode != null) {
EdmProperty edmProperty = (EdmProperty) edmEntityType.getProperty(propertyName);
if (jsonNode.isNull() == true && edmProperty.isNullable() != null
&& edmProperty.isNullable().booleanValue() == false) {
boolean isNullable = edmProperty.isNullable() == null ? false : edmProperty.isNullable();
if (jsonNode.isNull() && !isNullable) {
throw new DeserializerException("Property: " + propertyName + " must not be null.",
DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, propertyName);
}
@ -189,8 +190,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
JsonNode jsonNode = tree.get(navigationPropertyName);
if (jsonNode != null) {
EdmNavigationProperty edmNavigationProperty = edmEntityType.getNavigationProperty(navigationPropertyName);
if (jsonNode.isNull() == true && edmNavigationProperty.isNullable() != null
&& edmNavigationProperty.isNullable().booleanValue() == false) {
boolean isNullable = edmNavigationProperty.isNullable() == null ? false : edmNavigationProperty.isNullable();
if (jsonNode.isNull() && !isNullable) {
throw new DeserializerException("Property: " + navigationPropertyName + " must not be null.",
DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, navigationPropertyName);
}
@ -223,7 +224,11 @@ public class ODataJsonDeserializer implements ODataDeserializer {
while (fieldsIterator.hasNext()) {
Map.Entry<String, JsonNode> field = fieldsIterator.next();
if (field.getKey().contains(ODATA_CONTROL_INFORMATION_PREFIX)) {
if (field.getKey().contains(Constants.JSON_BIND_LINK_SUFFIX)) {
Link bindingLink = consumeBindingLink(field.getKey(), field.getValue(), edmEntityType);
entity.getNavigationBindings().add(bindingLink);
toRemove.add(field.getKey());
} else if (field.getKey().contains(ODATA_CONTROL_INFORMATION_PREFIX)) {
// Control Information is ignored for requests as per specification chapter "4.5 Control Information"
toRemove.add(field.getKey());
} else if (field.getKey().contains(ODATA_ANNOTATION_MARKER)) {
@ -244,6 +249,56 @@ public class ODataJsonDeserializer implements ODataDeserializer {
return entity;
}
private Link consumeBindingLink(String key, JsonNode jsonNode, EdmEntityType edmEntityType)
throws DeserializerException {
String[] splitKey = key.split("@");
String navigationPropertyName = splitKey[0];
EdmNavigationProperty edmNavigationProperty = edmEntityType.getNavigationProperty(navigationPropertyName);
if (edmNavigationProperty == null) {
throw new DeserializerException("Invalid navigationPropertyName: " + navigationPropertyName,
DeserializerException.MessageKeys.NAVIGATION_PROPERTY_NOT_FOUND, navigationPropertyName);
}
LinkImpl bindingLink = new LinkImpl();
bindingLink.setTitle(navigationPropertyName);
if (edmNavigationProperty.isCollection()) {
checkNullNode(key, jsonNode);
if (!jsonNode.isArray()) {
throw new DeserializerException("Binding annotation: " + key + " must be an array.",
DeserializerException.MessageKeys.INVALID_ANNOTATION_TYPE, key);
}
List<String> bindingLinkStrings = new ArrayList<String>();
Iterator<JsonNode> arrayIterator = jsonNode.iterator();
while (arrayIterator.hasNext()) {
JsonNode arrayValue = arrayIterator.next();
checkNullNode(key, arrayValue);
if (!arrayValue.isTextual()) {
throw new DeserializerException("Binding annotation: " + key + " must have string valueed array.",
DeserializerException.MessageKeys.INVALID_ANNOTATION_TYPE, key);
}
bindingLinkStrings.add(arrayValue.asText());
}
bindingLink.setType(ODataLinkType.ENTITY_COLLECTION_BINDING.toString());
bindingLink.setBindingLinks(bindingLinkStrings);
} else {
checkNullNode(key, jsonNode);
if (!jsonNode.isValueNode()) {
throw new DeserializerException("Binding annotation: " + key + " must be a string value.",
DeserializerException.MessageKeys.INVALID_ANNOTATION_TYPE, key);
}
bindingLink.setBindingLink(jsonNode.asText());
bindingLink.setType(ODataLinkType.ENTITY_BINDING.toString());
}
return bindingLink;
}
private void checkNullNode(String key, JsonNode jsonNode) throws DeserializerException {
if (jsonNode.isNull()) {
throw new DeserializerException("Annotation: " + key + "must not have a null value.",
DeserializerException.MessageKeys.INVALID_NULL_ANNOTATION, key);
}
}
private Property consumePropertyNode(EdmProperty edmProperty, JsonNode jsonNode) throws DeserializerException {
Property property = new PropertyImpl();
property.setName(edmProperty.getName());
@ -381,7 +436,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
EdmProperty edmProperty = (EdmProperty) edmType.getProperty(propertyName);
JsonNode subNode = jsonNode.get(propertyName);
if (subNode != null) {
if (subNode.isNull() && edmProperty.isNullable() != null && edmProperty.isNullable().booleanValue() == false) {
boolean isNullable = edmProperty.isNullable() == null ? false : edmProperty.isNullable();
if (subNode.isNull() && !isNullable) {
throw new DeserializerException("Property: " + propertyName + " must not be null.",
DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, propertyName);
}
@ -441,7 +497,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
if (!jsonNode.isValueNode()) {
throw new DeserializerException(
"Inavlid value for property: " + edmProperty.getName() + " must not be an object or array.",
DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, edmProperty.getName());
DeserializerException.MessageKeys.INVALID_TYPE_FOR_PROPERTY, edmProperty.getName());
}
try {
EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) edmProperty.getType();

View File

@ -112,6 +112,8 @@ DeserializerException.INVALID_VALUE_FOR_NAVIGATION_PROPERTY=Invalid value for na
DeserializerException.DUPLICATE_PROPERTY="Edm Properties must not appear twice within the same object."
DeserializerException.DUPLICATE_JSON_PROPERTY="JSON properties must not appear twice within the same object."
DeserializerException.UNKNOWN_PRIMITIVE_TYPE=Unknown primitive type '%1$s' for property '%2$s';
DeserializerException.NAVIGATION_PROPERTY_NOT_FOUND=Can`t find navigation property with name: '%1$s'.
DeserializerException.INVALID_ANNOTATION_TYPE=The annotation '%1$s' has the wrong JSON type.
BatchDeserializerException.INVALID_BOUNDARY=Invalid boundary at line '%1$s'.
BatchDeserializerException.INVALID_CHANGESET_METHOD=Invalid method: a ChangeSet cannot contain retrieve requests at line '%1$s'.

View File

@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.apache.olingo.commons.api.data.Entity;
@ -104,4 +105,68 @@ public class ODataDeserializerDeepInsertTest extends AbstractODataDeserializerTe
throw e;
}
}
@Test(expected = DeserializerException.class)
public void expandedToOneInvalidNullValue() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"NavPropertyETTwoPrimOne\":null"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entity(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void expandedToOneInvalidStringValue() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"NavPropertyETTwoPrimOne\":\"First Resource - positive values\""
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entity(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_VALUE_FOR_NAVIGATION_PROPERTY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void expandedToManyInvalidNullValue() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"NavPropertyETTwoPrimMany\":null"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entity(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void expandedToManyInvalidStringValue() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"NavPropertyETTwoPrimMany\":\"First Resource - positive values\""
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entity(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_VALUE_FOR_NAVIGATION_PROPERTY, e.getMessageKey());
throw e;
}
}
}

View File

@ -20,7 +20,9 @@ package org.apache.olingo.server.core.deserializer.json;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.List;
@ -91,6 +93,17 @@ public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserial
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
}
@Test
public void emptyETAllPrim() throws Exception {
String entityCollectionString = "{\"value\" : []}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
EntitySet entityCollection =
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
assertNotNull(entityCollection.getEntities());
assertTrue(entityCollection.getEntities().isEmpty());
}
@Test(expected = DeserializerException.class)
public void esAllPrimCustomAnnotationsLeadToNotImplemented() throws Exception {
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
@ -102,7 +115,7 @@ public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserial
throw e;
}
}
@Test(expected = DeserializerException.class)
public void esAllPrimDoubleKeysLeadToException() throws Exception {
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
@ -114,4 +127,125 @@ public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserial
throw e;
}
}
@Test(expected = DeserializerException.class)
public void wrongValueTagJsonValueNull() throws Exception {
String entityCollectionString = "{\"value\" : null}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void wrongValueTagJsonValueNumber() throws Exception {
String entityCollectionString = "{\"value\" : 1234}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void wrongValueTagJsonValueObject() throws Exception {
String entityCollectionString = "{\"value\" : {}}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void valueTagMissing() throws Exception {
String entityCollectionString = "{}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.VALUE_ARRAY_NOT_PRESENT, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void wrongValueInValueArrayNumber() throws Exception {
String entityCollectionString = "{\"value\" : [1234,123]}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_ENTITY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void wrongValueInValueArrayNestedArray() throws Exception {
String entityCollectionString = "{\"value\" : [[],[]]}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_ENTITY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void invalidJsonSyntax() throws Exception {
String entityCollectionString = "{\"value\" : }";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void unknownContentInCollection() throws Exception {
String entityCollectionString = "{\"value\" : [],"
+ "\"unknown\":null"
+ "}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.UNKOWN_CONTENT, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void customAnnotationNotSupportedYet() throws Exception {
String entityCollectionString = "{\"value\" : [],"
+ "\"@custom.annotation\":null"
+ "}";
InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
try {
OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
throw e;
}
}
}

View File

@ -20,6 +20,7 @@ package org.apache.olingo.server.core.deserializer.json;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@ -29,8 +30,10 @@ import java.math.BigDecimal;
import java.util.List;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.Link;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.data.ValueType;
import org.apache.olingo.commons.api.domain.ODataLinkType;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.format.ODataFormat;
import org.apache.olingo.server.api.OData;
@ -324,6 +327,56 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
assertEquals(2, properties.size());
}
@Test
public void etAllPrimBindingOperation() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"NavPropertyETTwoPrimOne@odata.bind\":\"ESTwoPrim(2)\","
+ "\"NavPropertyETTwoPrimMany@odata.bind\":[\"ESTwoPrim(2)\",\"ESTwoPrim(3)\"]"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
Entity entity =
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
assertNotNull(entity);
Link bindingToOne = entity.getNavigationBinding("NavPropertyETTwoPrimOne");
assertNotNull(bindingToOne);
assertEquals("NavPropertyETTwoPrimOne", bindingToOne.getTitle());
assertEquals("ESTwoPrim(2)", bindingToOne.getBindingLink());
assertEquals(ODataLinkType.ENTITY_BINDING.toString(), bindingToOne.getType());
assertTrue(bindingToOne.getBindingLinks().isEmpty());
assertNull(bindingToOne.getHref());
assertNull(bindingToOne.getRel());
Link bindingToMany = entity.getNavigationBinding("NavPropertyETTwoPrimMany");
assertNotNull(bindingToMany);
assertEquals("NavPropertyETTwoPrimMany", bindingToMany.getTitle());
assertNotNull(bindingToMany.getBindingLinks());
assertEquals(2, bindingToMany.getBindingLinks().size());
assertEquals(ODataLinkType.ENTITY_COLLECTION_BINDING.toString(), bindingToMany.getType());
assertNull(bindingToMany.getBindingLink());
assertNull(bindingToMany.getHref());
assertNull(bindingToMany.getRel());
}
@Test
public void etAllPrimBindingOperationEmptyArray() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"NavPropertyETTwoPrimMany@odata.bind\":[]"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
Entity entity =
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
Link bindingToMany = entity.getNavigationBinding("NavPropertyETTwoPrimMany");
assertNotNull(bindingToMany);
assertTrue(bindingToMany.getBindingLinks().isEmpty());
}
// ---------------------------------- Negative Tests -----------------------------------------------------------
@Test(expected = DeserializerException.class)
@ -350,7 +403,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, e.getMessageKey());
assertEquals(DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, e.getMessageKey());
throw e;
}
}
@ -617,130 +670,261 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
public void propertyInt16JsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyInt16\":\"32767\"}");
checkPropertyJsonType("{\"PropertyInt16\":true}");
checkPropertyJsonType("{\"PropertyInt16\":[]}");
checkPropertyJsonType("{\"PropertyInt16\":{}}");
}
@Test
public void propertyInt32JsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyInt32\":\"2147483647\"}");
checkPropertyJsonType("{\"PropertyInt32\":true}");
checkPropertyJsonType("{\"PropertyInt32\":[]}");
checkPropertyJsonType("{\"PropertyInt32\":{}}");
}
@Test
public void propertyInt64JsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyInt64\":\"9223372036854775807\"}");
checkPropertyJsonType("{\"PropertyInt64\":true}");
checkPropertyJsonType("{\"PropertyInt64\":[]}");
checkPropertyJsonType("{\"PropertyInt64\":{}}");
}
@Test
public void propertyStringJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyString\":32767}");
checkPropertyJsonType("{\"PropertyString\":true}");
checkPropertyJsonType("{\"PropertyString\":[]}");
checkPropertyJsonType("{\"PropertyString\":{}}");
}
@Test
public void propertyBooleanJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyBoolean\":\"true\"}");
checkPropertyJsonType("{\"PropertyBoolean\":123}");
checkPropertyJsonType("{\"PropertyBoolean\":[]}");
checkPropertyJsonType("{\"PropertyBoolean\":{}}");
}
@Test
public void propertyByteJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyByte\":\"255\"}");
checkPropertyJsonType("{\"PropertyByte\":true}");
checkPropertyJsonType("{\"PropertyByte\":[]}");
checkPropertyJsonType("{\"PropertyByte\":{}}");
}
@Test
public void propertySByteJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertySByte\":\"127\"}");
checkPropertyJsonType("{\"PropertySByte\":true}");
checkPropertyJsonType("{\"PropertySByte\":[]}");
checkPropertyJsonType("{\"PropertySByte\":{}}");
}
@Test
public void propertySingleJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertySingle\":\"1.79E20\"}");
checkPropertyJsonType("{\"PropertySingle\":true}");
checkPropertyJsonType("{\"PropertySingle\":[]}");
checkPropertyJsonType("{\"PropertySingle\":{}}");
}
@Test
public void propertyDoubleJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyDouble\":\"-1.79E19\"}");
checkPropertyJsonType("{\"PropertyDouble\":true}");
checkPropertyJsonType("{\"PropertyDouble\":[]}");
checkPropertyJsonType("{\"PropertyDouble\":{}}");
}
@Test
public void propertyDecimalJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyDecimal\":\"34\"}");
checkPropertyJsonType("{\"PropertyDecimal\":true}");
checkPropertyJsonType("{\"PropertyDecimal\":[]}");
checkPropertyJsonType("{\"PropertyDecimal\":{}}");
}
@Test
public void propertyBinaryJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyBinary\":32767}");
checkPropertyJsonType("{\"PropertyBinary\":true}");
checkPropertyJsonType("{\"PropertyBinary\":[]}");
checkPropertyJsonType("{\"PropertyBinary\":{}}");
}
@Test
public void propertyDateJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyDate\":32767}");
checkPropertyJsonType("{\"PropertyDate\":true}");
checkPropertyJsonType("{\"PropertyDate\":[]}");
checkPropertyJsonType("{\"PropertyDate\":{}}");
}
@Test
public void propertyDateTimeOffsetJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyDateTimeOffset\":32767}");
checkPropertyJsonType("{\"PropertyDateTimeOffset\":true}");
checkPropertyJsonType("{\"PropertyDateTimeOffset\":[]}");
checkPropertyJsonType("{\"PropertyDateTimeOffset\":{}}");
}
@Test
public void propertyDurationJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyDuration\":32767}");
checkPropertyJsonType("{\"PropertyDuration\":true}");
checkPropertyJsonType("{\"PropertyDuration\":[]}");
checkPropertyJsonType("{\"PropertyDuration\":{}}");
}
@Test
public void propertyGuidTimeOffsetJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyGuid\":32767}");
checkPropertyJsonType("{\"PropertyGuid\":true}");
checkPropertyJsonType("{\"PropertyGuid\":[]}");
checkPropertyJsonType("{\"PropertyGuid\":{}}");
}
@Test
public void propertyTimeOfDayJsonTypesNegativeCheck() throws Exception {
checkPropertyJsonType("{\"PropertyTimeOfDay\":32767}");
checkPropertyJsonType("{\"PropertyTimeOfDay\":true}");
checkPropertyJsonType("{\"PropertyTimeOfDay\":[]}");
checkPropertyJsonType("{\"PropertyTimeOfDay\":{}}");
}
@Test(expected = DeserializerException.class)
public void bindOperationWrongJsonTypeForToOne() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"NavPropertyETTwoPrimOne@odata.bind\":[\"ESTwoPrim(2)\"]"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_ANNOTATION_TYPE, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void bindOperationWrongJsonTypeForToMany() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"NavPropertyETTwoPrimMany@odata.bind\":\"ESTwoPrim(2)\""
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_ANNOTATION_TYPE, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void bindOperationWrongJsonTypeForToManyNumberInArray() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"NavPropertyETTwoPrimMany@odata.bind\":[123,456]"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_ANNOTATION_TYPE, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void bindOperationWrongAnnotationFormat() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"@odata.bind\":\"ESTwoPrim(2)\""
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.NAVIGATION_PROPERTY_NOT_FOUND, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void bindingOperationNullOnToOne() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"NavPropertyETTwoPrimOne@odata.bind\":null"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_NULL_ANNOTATION, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void bindingOperationNullOnToMany() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"NavPropertyETTwoPrimMany@odata.bind\":null"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_NULL_ANNOTATION, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void bindingOperationNullInArray() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"NavPropertyETTwoPrimMany@odata.bind\":[null]"
+ "}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_NULL_ANNOTATION, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void invalidJsonSyntax() throws Exception {
String entityString =
"{\"PropertyInt16\":32767,}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void invalidJsonValueForPrimTypeArray() throws Exception {
String entityString =
"{\"PropertyInt16\":[]}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_TYPE_FOR_PROPERTY, e.getMessageKey());
throw e;
}
}
@Test(expected = DeserializerException.class)
public void invalidJsonValueForPrimTypeObject() throws Exception {
String entityString =
"{\"PropertyInt16\":{}}";
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
try {
deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
} catch (DeserializerException e) {
assertEquals(DeserializerException.MessageKeys.INVALID_TYPE_FOR_PROPERTY, e.getMessageKey());
throw e;
}
}
private void checkPropertyJsonType(String entityString) throws DeserializerException {
InputStream stream = new ByteArrayInputStream(entityString.getBytes());
ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);