diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataErrorSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataErrorSerializer.java index b6357425b..c453de5e1 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataErrorSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataErrorSerializer.java @@ -18,34 +18,29 @@ */ package org.apache.olingo.server.core.serializer.json; -import com.fasterxml.jackson.core.JsonGenerationException; -import com.fasterxml.jackson.core.JsonGenerator; +import java.io.IOException; + +import org.apache.olingo.commons.api.Constants; import org.apache.olingo.commons.api.ODataRuntimeException; import org.apache.olingo.commons.api.domain.ODataError; import org.apache.olingo.commons.api.domain.ODataErrorDetail; -import java.io.IOException; +import com.fasterxml.jackson.core.JsonGenerator; public class ODataErrorSerializer { - private static final String ERROR = "error"; - private static final String CODE = "code"; - private static final String MESSAGE = "message"; - private static final String TARGET = "target"; - private static final String DETAILS = "details"; - public void writeErrorDocument(JsonGenerator json, ODataError error) throws IOException { if (error == null) { throw new ODataRuntimeException("ODataError object MUST NOT be null!"); } json.writeStartObject(); - json.writeFieldName(ERROR); + json.writeFieldName(Constants.JSON_ERROR); json.writeStartObject(); writeODataError(json, error.getCode(), error.getMessage(), error.getTarget()); if (error.getDetails() != null) { - json.writeArrayFieldStart(DETAILS); + json.writeArrayFieldStart(Constants.ERROR_DETAILS); for (ODataErrorDetail detail : error.getDetails()) { json.writeStartObject(); writeODataError(json, detail.getCode(), detail.getMessage(), detail.getTarget()); @@ -58,21 +53,23 @@ public class ODataErrorSerializer { json.writeEndObject(); } - private void writeODataError(JsonGenerator json, String code, String message, String target) throws IOException, - JsonGenerationException { + private void writeODataError(JsonGenerator json, String code, String message, String target) throws IOException { + json.writeFieldName(Constants.ERROR_CODE); if (code == null) { - json.writeNullField(CODE); + json.writeNull(); } else { - json.writeStringField(CODE, code); + json.writeString(code); } + + json.writeFieldName(Constants.ERROR_MESSAGE); if (message == null) { - json.writeNullField(MESSAGE); + json.writeNull(); } else { - json.writeStringField(MESSAGE, message); + json.writeString(message); } if (target != null) { - json.writeStringField(TARGET, target); + json.writeStringField(Constants.ERROR_TARGET, target); } } } diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java index cc817de5a..27af0d8b2 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java @@ -18,9 +18,10 @@ */ package org.apache.olingo.server.core.serializer.json; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + import org.apache.olingo.commons.api.Constants; import org.apache.olingo.commons.api.ODataRuntimeException; import org.apache.olingo.commons.api.data.ContextURL; @@ -45,11 +46,9 @@ import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStreamWriter; -import java.util.List; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; public class ODataJsonSerializer implements ODataSerializer { @@ -64,21 +63,15 @@ public class ODataJsonSerializer implements ODataSerializer { @Override public InputStream serviceDocument(final Edm edm, final String serviceRoot) { CircleStreamBuffer buffer; - BufferedWriter writer; - JsonFactory factory; JsonGenerator gen = null; // TODO: move stream initialization into separate method try { buffer = new CircleStreamBuffer(); - writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET)); - factory = new JsonFactory(); + gen = new JsonFactory().createGenerator(buffer.getOutputStream()) + .setPrettyPrinter(new DefaultPrettyPrinter()); - gen = factory.createGenerator(writer); - gen.setPrettyPrinter(new DefaultPrettyPrinter()); - - ServiceDocumentJsonSerializer serializer = new ServiceDocumentJsonSerializer(edm, serviceRoot); - serializer.writeServiceDocument(gen); + new ServiceDocumentJsonSerializer(edm, serviceRoot).writeServiceDocument(gen); gen.close(); @@ -130,7 +123,7 @@ public class ODataJsonSerializer implements ODataSerializer { try { JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream()); json.writeStartObject(); - if (entitySetContextURL != null && format != ODataFormat.JSON_NO_METADATA) { + if (format != ODataFormat.JSON_NO_METADATA) { json.writeStringField(Constants.JSON_CONTEXT, entitySetContextURL.getURI().toASCIIString()); } if (entitySet.getCount() != null) { @@ -174,6 +167,7 @@ public class ODataJsonSerializer implements ODataSerializer { protected void writeEntity(final EdmEntitySet entitySet, final Entity entity, final ContextURL contextURL, final JsonGenerator json) throws IOException, EdmPrimitiveTypeException { + final EdmEntityType entityType = entitySet.getEntityType(); json.writeStartObject(); if (format != ODataFormat.JSON_NO_METADATA) { if (contextURL != null) { @@ -182,14 +176,15 @@ public class ODataJsonSerializer implements ODataSerializer { if (entity.getETag() != null) { json.writeStringField(Constants.JSON_ETAG, entity.getETag()); } - if (entity.getMediaETag() != null) { - json.writeStringField(Constants.JSON_MEDIA_ETAG, entity.getMediaETag()); - } - if (entity.getMediaContentType() != null) { - json.writeStringField(Constants.JSON_MEDIA_CONTENT_TYPE, entity.getMediaContentType()); + if (entityType.hasStream()) { + if (entity.getMediaETag() != null) { + json.writeStringField(Constants.JSON_MEDIA_ETAG, entity.getMediaETag()); + } + if (entity.getMediaContentType() != null) { + json.writeStringField(Constants.JSON_MEDIA_CONTENT_TYPE, entity.getMediaContentType()); + } } } - final EdmEntityType entityType = entitySet.getEntityType(); for (final String propertyName : entityType.getPropertyNames()) { final EdmProperty edmProperty = (EdmProperty) entityType.getProperty(propertyName); final Property property = entity.getProperty(propertyName); @@ -214,7 +209,7 @@ public class ODataJsonSerializer implements ODataSerializer { writePrimitive(edmProperty, property, json); } else if (property.isLinkedComplex()) { writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), json); - } else if(property.isComplex()) { + } else if (property.isComplex()) { writeComplexValue(edmProperty, property.asComplex(), json); } else { throw new ODataRuntimeException("Property type not yet supported!"); @@ -285,7 +280,7 @@ public class ODataJsonSerializer implements ODataSerializer { } private void writeComplexValue(final EdmProperty edmProperty, final List properties, - JsonGenerator json) throws IOException, EdmPrimitiveTypeException { + JsonGenerator json) throws IOException, EdmPrimitiveTypeException { final EdmComplexType type = (EdmComplexType) edmProperty.getType(); json.writeStartObject(); for (final String propertyName : type.getPropertyNames()) { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ServiceDocumentJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ServiceDocumentJsonSerializer.java index 95a8b3914..e2f7261df 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ServiceDocumentJsonSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ServiceDocumentJsonSerializer.java @@ -18,22 +18,18 @@ */ package org.apache.olingo.server.core.serializer.json; -import com.fasterxml.jackson.core.JsonGenerationException; -import com.fasterxml.jackson.core.JsonGenerator; +import java.io.IOException; + +import org.apache.olingo.commons.api.Constants; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntityContainer; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmFunctionImport; import org.apache.olingo.commons.api.edm.EdmSingleton; -import java.io.IOException; +import com.fasterxml.jackson.core.JsonGenerator; public class ServiceDocumentJsonSerializer { - public static final String ODATA_CONTEXT = "@odata.context"; - public static final String METADATA = "$metadata"; - public static final String VALUE = "value"; - public static final String NAME = "name"; - public static final String URL = "url"; public static final String KIND = "kind"; public static final String FUNCTION_IMPORT = "FunctionImport"; @@ -48,64 +44,63 @@ public class ServiceDocumentJsonSerializer { this.serviceRoot = serviceRoot; } - public void writeServiceDocument(final JsonGenerator gen) throws JsonGenerationException, IOException { + public void writeServiceDocument(final JsonGenerator gen) throws IOException { gen.writeStartObject(); Object metadataUri; if (serviceRoot == null) { - metadataUri = METADATA; + metadataUri = Constants.METADATA; } else { if (serviceRoot.endsWith("/")) { - metadataUri = serviceRoot + METADATA; + metadataUri = serviceRoot + Constants.METADATA; } else { - metadataUri = serviceRoot + "/" + METADATA; + metadataUri = serviceRoot + "/" + Constants.METADATA; } } - gen.writeObjectField(ODATA_CONTEXT, metadataUri); - gen.writeArrayFieldStart(VALUE); + gen.writeObjectField(Constants.JSON_CONTEXT, metadataUri); + gen.writeArrayFieldStart(Constants.VALUE); writeEntitySets(gen, edm); writeFunctionImports(gen, edm); writeSingletons(gen, edm); } - private void writeEntitySets(final JsonGenerator gen, final Edm edm) throws JsonGenerationException, IOException { + private void writeEntitySets(final JsonGenerator gen, final Edm edm) throws IOException { EdmEntityContainer container = edm.getEntityContainer(null); for (EdmEntitySet edmEntitySet : container.getEntitySets()) { if (edmEntitySet.isIncludeInServiceDocument()) { gen.writeStartObject(); - gen.writeObjectField(NAME, edmEntitySet.getName()); - gen.writeObjectField(URL, edmEntitySet.getName()); + gen.writeObjectField(Constants.JSON_NAME, edmEntitySet.getName()); + gen.writeObjectField(Constants.JSON_URL, edmEntitySet.getName()); gen.writeEndObject(); } } } - private void writeFunctionImports(final JsonGenerator gen, final Edm edm) throws JsonGenerationException, - IOException { + private void writeFunctionImports(final JsonGenerator gen, final Edm edm) throws IOException { EdmEntityContainer container = edm.getEntityContainer(null); for (EdmFunctionImport edmFunctionImport : container.getFunctionImports()) { if (edmFunctionImport.isIncludeInServiceDocument()) { gen.writeStartObject(); - gen.writeObjectField(NAME, edmFunctionImport.getName()); - gen.writeObjectField(URL, edmFunctionImport.getName()); + gen.writeObjectField(Constants.JSON_NAME, edmFunctionImport.getName()); + gen.writeObjectField(Constants.JSON_URL, edmFunctionImport.getName()); gen.writeObjectField(KIND, FUNCTION_IMPORT); gen.writeEndObject(); } } } - private void writeSingletons(final JsonGenerator gen, final Edm edm) throws JsonGenerationException, IOException { + private void writeSingletons(final JsonGenerator gen, final Edm edm) throws IOException { EdmEntityContainer container = edm.getEntityContainer(null); for (EdmSingleton edmSingleton : container.getSingletons()) { gen.writeStartObject(); - gen.writeObjectField(NAME, edmSingleton.getName()); - gen.writeObjectField(URL, edmSingleton.getName()); + gen.writeObjectField(Constants.JSON_NAME, edmSingleton.getName()); + gen.writeObjectField(Constants.JSON_URL, edmSingleton.getName()); gen.writeObjectField(KIND, SINGLETON); gen.writeEndObject(); } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java index 41e94f647..71bdf7a57 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java @@ -18,6 +18,16 @@ */ package org.apache.olingo.server.tecsvc.data; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.UUID; + import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.data.LinkedComplexValue; @@ -35,16 +45,6 @@ import org.apache.olingo.commons.core.data.LinkedComplexValueImpl; import org.apache.olingo.commons.core.data.PropertyImpl; import org.apache.olingo.server.api.uri.UriParameter; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; -import java.util.UUID; - public class DataProvider { private static final UUID GUID = UUID.fromString("01234567-89ab-cdef-0123-456789abcdef"); @@ -61,6 +61,7 @@ public class DataProvider { data.put("ESCollAllPrim", createESCollAllPrim()); data.put("ESMixPrimCollComp", createESMixPrimCollComp()); data.put("ESAllKey", createESAllKey()); + data.put("ESMedia", createESMedia()); } public EntitySet readAll(final EdmEntitySet edmEntitySet) throws DataProviderException { @@ -419,6 +420,32 @@ public class DataProvider { return entitySet; } + private EntitySet createESMedia() { + EntitySet entitySet = new EntitySetImpl(); + + Entity entity = new EntityImpl(); + entity.addProperty(createPrimitive("PropertyInt16", 1)); + entity.setMediaContentType("image/png"); + entitySet.getEntities().add(entity); + + entity = new EntityImpl(); + entity.addProperty(createPrimitive("PropertyInt16", 2)); + entity.setMediaContentType("image/bmp"); + entitySet.getEntities().add(entity); + + entity = new EntityImpl(); + entity.addProperty(createPrimitive("PropertyInt16", 3)); + entity.setMediaContentType("image/jpeg"); + entitySet.getEntities().add(entity); + + entity = new EntityImpl(); + entity.addProperty(createPrimitive("PropertyInt16", 4)); + entity.setMediaContentType("foo"); + entitySet.getEntities().add(entity); + + return entitySet; + } + private Property createPrimitive(final String name, final Object value) { return new PropertyImpl(null, name, ValueType.PRIMITIVE, value); } diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java index dc29a9365..974e33827 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java @@ -18,11 +18,17 @@ */ package org.apache.olingo.server.core.serializer.json; +import java.io.InputStream; +import java.net.URI; +import java.util.Arrays; + import org.apache.commons.io.IOUtils; +import org.apache.olingo.commons.api.ODataRuntimeException; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.ContextURL.Suffix; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; +import org.apache.olingo.commons.api.data.ValueType; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntityContainer; import org.apache.olingo.commons.api.edm.EdmEntitySet; @@ -35,9 +41,6 @@ import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.junit.Assert; import org.junit.Test; -import java.io.InputStream; -import java.net.URI; - public class ODataJsonSerializerTest { private final Edm edm = OData.newInstance().createEdm(new EdmTechProvider()); @@ -75,6 +78,40 @@ public class ODataJsonSerializerTest { Assert.assertEquals(expectedResult, resultString); } + @Test + public void entityAllPrimAllNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.getProperties().retainAll(Arrays.asList(entity.getProperties().get(0))); + final String resultString = IOUtils.toString(serializer.entity(edmEntitySet, entity, null)); + final String expectedResult = "{\"@odata.context\":\"$metadata#ESAllPrim/$entity\"," + + "\"PropertyInt16\":32767," + + "\"PropertyString\":null,\"PropertyBoolean\":null," + + "\"PropertyByte\":null,\"PropertySByte\":null," + + "\"PropertyInt32\":null,\"PropertyInt64\":null," + + "\"PropertySingle\":null,\"PropertyDouble\":null,\"PropertyDecimal\":null," + + "\"PropertyBinary\":null," + + "\"PropertyDate\":null,\"PropertyDateTimeOffset\":null,\"PropertyDuration\":null," + + "\"PropertyGuid\":null,\"PropertyTimeOfDay\":null}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test(expected = ODataRuntimeException.class) + public void entityAllPrimKeyNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.getProperties().clear(); + serializer.entity(edmEntitySet, entity, null); + } + + @Test(expected = ODataRuntimeException.class) + public void entityWrongData() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.getProperties().get(0).setValue(ValueType.PRIMITIVE, false); + serializer.entity(edmEntitySet, entity, null); + } + @Test public void entitySetAllPrim() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); @@ -180,6 +217,18 @@ public class ODataJsonSerializerTest { Assert.assertEquals(expectedResult, resultString); } + @Test + public void entityMixPrimCollCompAllNull() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.getProperties().retainAll(Arrays.asList(entity.getProperties().get(0))); + final String resultString = IOUtils.toString(serializer.entity(edmEntitySet, entity, null)); + final String expectedResult = "{\"@odata.context\":\"$metadata#ESMixPrimCollComp/$entity\"," + + "\"PropertyInt16\":32767," + + "\"CollPropertyString\":null,\"PropertyComp\":null,\"CollPropertyComp\":null}"; + Assert.assertEquals(expectedResult, resultString); + } + @Test public void entityTwoPrimNoMetadata() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); @@ -205,4 +254,29 @@ public class ODataJsonSerializerTest { + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}"; Assert.assertEquals(expectedResult, resultString); } + + @Test + public void entityMedia() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia"); + Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + entity.setMediaETag("theMediaETag"); + final String resultString = IOUtils.toString(serializer.entity(edmEntitySet, entity, null)); + final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia/$entity\"," + + "\"@odata.mediaEtag\":\"theMediaETag\",\"@odata.mediaContentType\":\"image/png\"," + + "\"PropertyInt16\":1}"; + Assert.assertEquals(expectedResult, resultString); + } + + @Test + public void entitySetMedia() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMedia"); + final EntitySet entitySet = data.readAll(edmEntitySet); + final String resultString = IOUtils.toString(serializer.entitySet(edmEntitySet, entitySet, null)); + final String expectedResult = "{\"@odata.context\":\"$metadata#ESMedia\",\"value\":[" + + "{\"@odata.mediaContentType\":\"image/png\",\"PropertyInt16\":1}," + + "{\"@odata.mediaContentType\":\"image/bmp\",\"PropertyInt16\":2}," + + "{\"@odata.mediaContentType\":\"image/jpeg\",\"PropertyInt16\":3}," + + "{\"@odata.mediaContentType\":\"foo\",\"PropertyInt16\":4}]}"; + Assert.assertEquals(expectedResult, resultString); + } }