From b9f4b3c64c893d731d6d6ff326486c6667791388 Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Tue, 15 Jul 2014 15:38:30 +0200 Subject: [PATCH] [OLINGO-317] ContextURL integration --- lib/commons-api/pom.xml | 10 +- .../apache/olingo/commons/api/Constants.java | 16 ++- .../olingo/commons/api/data/ContextURL.java | 135 ++++++++++++++---- .../edm/constants/ODataServiceVersion.java | 30 ++-- .../commons/api/data/ContextURLTest.java | 90 ++++++++++++ lib/commons-core/pom.xml | 4 +- .../api/serializer/ODataSerializer.java | 5 +- .../serializer/ODataXmlSerializerImpl.java | 3 +- .../serializer/json/ODataJsonSerializer.java | 30 ++-- .../tecsvc/processor/TechnicalProcessor.java | 11 +- .../tecsvc/data/JsonDataProviderTest.java | 8 +- .../json/ODataJsonSerializerTest.java | 25 ++-- 12 files changed, 281 insertions(+), 86 deletions(-) diff --git a/lib/commons-api/pom.xml b/lib/commons-api/pom.xml index ce6849ae8..6f9768fb2 100644 --- a/lib/commons-api/pom.xml +++ b/lib/commons-api/pom.xml @@ -33,23 +33,27 @@ 0.1.0-SNAPSHOT .. - + org.apache.commons commons-lang3 - org.slf4j slf4j-api - + junit junit test + + org.mockito + mockito-all + test + diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java index 8241457bc..80e56963d 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java @@ -163,11 +163,23 @@ public interface Constants { // JSON stuff public final static String JSON_METADATA = "odata.metadata"; + public final static String JSON_TYPE = "@odata.type"; + public final static String JSON_ID = "@odata.id"; + public final static String JSON_READ_LINK = "@odata.readLink"; + public final static String JSON_EDIT_LINK = "@odata.editLink"; public final static String JSON_CONTEXT = "@odata.context"; - + public final static String JSON_ETAG = "@odata.etag"; + public final static String JSON_MEDIA_ETAG = "@odata.mediaEtag"; + public final static String JSON_MEDIA_CONTENT_TYPE = "@odata.mediaContentType"; + public final static String JSON_MEDIA_READ_LINK = "@odata.mediaReadLink"; + public final static String JSON_MEDIA_EDIT_LINK = "@odata.mediaEditLink"; public final static String JSON_METADATA_ETAG = "@odata.metadataEtag"; - public final static String JSON_BIND_LINK_SUFFIX = "@odata.bind"; + public final static String JSON_ASSOCIATION_LINK = "@odata.associationLink"; + public final static String JSON_NAVIGATION_LINK = "@odata.navigationLink"; + public final static String JSON_COUNT = "@odata.count"; + public final static String JSON_NEXT_LINK = "@odata.nextLink"; + public final static String JSON_DELTA_LINK = "@odata.deltaLink"; public final static String JSON_NULL = "odata.null"; diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/ContextURL.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/ContextURL.java index 8926cebc9..2628ebd44 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/ContextURL.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/data/ContextURL.java @@ -22,6 +22,8 @@ import java.net.URI; import org.apache.commons.lang3.StringUtils; import org.apache.olingo.commons.api.Constants; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; /** * High-level representation of a context URL, built from the string value returned by a service; provides access to the @@ -34,24 +36,31 @@ public class ContextURL { private URI uri; private URI serviceRoot; - private String entitySetOrSingletonOrType; - private String derivedEntity; - private String selectList; - private String navOrPropertyPath; - private boolean entity; + public enum Suffix { + ENTITY("$entity"), + REFERENCE("$ref"), + DELTA("$delta"), + DELTA_DELETED_ENTITY("$deletedEntity"), + DELTA_LINK("$link"), + DELTA_DELETED_LINK("$deletedLink"); - private boolean delta; + private final String representation; + private Suffix(final String representation) { + this.representation = representation; + } + public String getRepresentation() { + return representation; + } + } - private boolean deltaDeletedEntity; + private Suffix suffix; - private boolean deltaLink; - - private boolean deltaDeletedLink; + private ContextURL() {} public static ContextURL getInstance(final URI contextURL) { final ContextURL instance = new ContextURL(); @@ -59,21 +68,31 @@ public class ContextURL { String contextURLasString = instance.uri.toASCIIString(); - instance.entity = contextURLasString.endsWith("/$entity") || contextURLasString.endsWith("/@Element"); - contextURLasString = contextURLasString. - replace("/$entity", StringUtils.EMPTY).replace("/@Element", StringUtils.EMPTY); + if (contextURLasString.endsWith("/$entity") || contextURLasString.endsWith("/@Element")) { + instance.suffix = Suffix.ENTITY; + contextURLasString = contextURLasString.replace("/$entity", StringUtils.EMPTY) + .replace("/@Element", StringUtils.EMPTY); - instance.delta = contextURLasString.endsWith("/$delta"); - contextURLasString = contextURLasString.replace("/$delta", StringUtils.EMPTY); + } else if (contextURLasString.endsWith("/$ref")) { + instance.suffix = Suffix.REFERENCE; + contextURLasString = contextURLasString.replace("/$ref", StringUtils.EMPTY); - instance.deltaDeletedEntity = contextURLasString.endsWith("/$deletedEntity"); - contextURLasString = contextURLasString.replace("/$deletedEntity", StringUtils.EMPTY); + } else if (contextURLasString.endsWith("/$delta")) { + instance.suffix = Suffix.DELTA; + contextURLasString = contextURLasString.replace("/$delta", StringUtils.EMPTY); - instance.deltaLink = contextURLasString.endsWith("/$link"); - contextURLasString = contextURLasString.replace("/$link", StringUtils.EMPTY); + } else if (contextURLasString.endsWith("/$deletedEntity")) { + instance.suffix = Suffix.DELTA_DELETED_ENTITY; + contextURLasString = contextURLasString.replace("/$deletedEntity", StringUtils.EMPTY); - instance.deltaDeletedLink = contextURLasString.endsWith("/$deletedLink"); - contextURLasString = contextURLasString.replace("/$deletedLink", StringUtils.EMPTY); + } else if (contextURLasString.endsWith("/$link")) { + instance.suffix = Suffix.DELTA_LINK; + contextURLasString = contextURLasString.replace("/$link", StringUtils.EMPTY); + + } else if (contextURLasString.endsWith("/$deletedLink")) { + instance.suffix = Suffix.DELTA_DELETED_LINK; + contextURLasString = contextURLasString.replace("/$deletedLink", StringUtils.EMPTY); + } instance.serviceRoot = URI.create(StringUtils.substringBefore(contextURLasString, Constants.METADATA)); @@ -150,23 +169,87 @@ public class ContextURL { } public boolean isEntity() { - return entity; + return suffix == Suffix.ENTITY; + } + + public boolean isReference() { + return suffix == Suffix.REFERENCE; } public boolean isDelta() { - return delta; + return suffix == Suffix.DELTA; } public boolean isDeltaDeletedEntity() { - return deltaDeletedEntity; + return suffix == Suffix.DELTA_DELETED_ENTITY; } public boolean isDeltaLink() { - return deltaLink; + return suffix == Suffix.DELTA_LINK; } public boolean isDeltaDeletedLink() { - return deltaDeletedLink; + return suffix == Suffix.DELTA_DELETED_LINK; + } + + public static final class ContextURLBuilder { + private ContextURL contextURL = new ContextURL(); + + private ContextURLBuilder() {} + + public ContextURLBuilder serviceRoot(final URI serviceRoot) { + contextURL.serviceRoot = serviceRoot; + return this; + } + + public ContextURLBuilder entitySet(final EdmEntitySet entitySet) { + contextURL.entitySetOrSingletonOrType = entitySet.getName(); + return this; + } + + public ContextURLBuilder derived(final EdmEntityType derivedType) { + contextURL.derivedEntity = derivedType.getFullQualifiedName().getFullQualifiedNameAsString(); + return this; + } + + public ContextURLBuilder suffix(final Suffix suffix) { + contextURL.suffix = suffix; + return this; + } + + public ContextURL build() { + StringBuilder result = new StringBuilder(); + if (contextURL.serviceRoot != null) { + result.append(contextURL.serviceRoot); + } + result.append(Constants.METADATA); + if (contextURL.entitySetOrSingletonOrType != null) { + result.append('#').append(contextURL.entitySetOrSingletonOrType); + } + if (contextURL.derivedEntity != null) { + if (contextURL.entitySetOrSingletonOrType == null) { + throw new IllegalArgumentException("ContextURL: Derived Type without anything to derive from!"); + } + result.append('/').append(contextURL.derivedEntity); + } + if (contextURL.suffix == Suffix.REFERENCE) { + if (contextURL.entitySetOrSingletonOrType != null) { + throw new IllegalArgumentException("ContextURL: $ref with Entity Set"); + } + result.append('#').append(contextURL.suffix.getRepresentation()); + } else if (contextURL.suffix != null) { + if (contextURL.entitySetOrSingletonOrType == null) { + throw new IllegalArgumentException("ContextURL: Suffix without preceding Entity Set!"); + } + result.append('/').append(contextURL.suffix.getRepresentation()); + } + contextURL.uri = URI.create(result.toString()); + return contextURL; + } + } + + public static final ContextURLBuilder create() { + return new ContextURLBuilder(); } @Override diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/constants/ODataServiceVersion.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/constants/ODataServiceVersion.java index 3b321bc19..862443232 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/constants/ODataServiceVersion.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/constants/ODataServiceVersion.java @@ -24,6 +24,8 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.olingo.commons.api.Constants; + /** * This class is a container for the supported ODataServiceVersions. */ @@ -133,20 +135,20 @@ public enum ODataServiceVersion { private static final long serialVersionUID = 3109256773218160485L; { - put(JSON_TYPE, "@odata.type"); - put(JSON_ID, "@odata.id"); - put(JSON_ETAG, "@odata.etag"); - put(JSON_READ_LINK, "@odata.readLink"); - put(JSON_EDIT_LINK, "@odata.editLink"); - put(JSON_MEDIAREAD_LINK, "@odata.mediaReadLink"); - put(JSON_MEDIAEDIT_LINK, "@odata.mediaEditLink"); - put(JSON_MEDIA_CONTENT_TYPE, "@odata.mediaContentType"); - put(JSON_MEDIA_ETAG, "@odata.mediaEtag"); - put(JSON_ASSOCIATION_LINK, "@odata.associationLink"); - put(JSON_NAVIGATION_LINK, "@odata.navigationLink"); - put(JSON_COUNT, "@odata.count"); - put(JSON_NEXT_LINK, "@odata.nextLink"); - put(JSON_DELTA_LINK, "@odata.deltaLink"); + put(JSON_TYPE, Constants.JSON_TYPE); + put(JSON_ID, Constants.JSON_ID); + put(JSON_ETAG, Constants.JSON_ETAG); + put(JSON_READ_LINK, Constants.JSON_READ_LINK); + put(JSON_EDIT_LINK, Constants.JSON_EDIT_LINK); + put(JSON_MEDIAREAD_LINK, Constants.JSON_MEDIA_READ_LINK); + put(JSON_MEDIAEDIT_LINK, Constants.JSON_MEDIA_EDIT_LINK); + put(JSON_MEDIA_CONTENT_TYPE, Constants.JSON_MEDIA_CONTENT_TYPE); + put(JSON_MEDIA_ETAG, Constants.JSON_MEDIA_ETAG); + put(JSON_ASSOCIATION_LINK, Constants.JSON_ASSOCIATION_LINK); + put(JSON_NAVIGATION_LINK, Constants.JSON_NAVIGATION_LINK); + put(JSON_COUNT, Constants.JSON_COUNT); + put(JSON_NEXT_LINK, Constants.JSON_NEXT_LINK); + put(JSON_DELTA_LINK, Constants.JSON_DELTA_LINK); put(JSON_ERROR, "error"); } }); diff --git a/lib/commons-api/src/test/java/org/apache/olingo/commons/api/data/ContextURLTest.java b/lib/commons-api/src/test/java/org/apache/olingo/commons/api/data/ContextURLTest.java index 84046b214..7575e825c 100644 --- a/lib/commons-api/src/test/java/org/apache/olingo/commons/api/data/ContextURLTest.java +++ b/lib/commons-api/src/test/java/org/apache/olingo/commons/api/data/ContextURLTest.java @@ -25,7 +25,12 @@ import static org.junit.Assert.assertTrue; import java.net.URI; +import org.apache.olingo.commons.api.data.ContextURL.Suffix; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.junit.Test; +import org.mockito.Mockito; public class ContextURLTest { @@ -201,6 +206,16 @@ public class ContextURLTest { assertFalse(contextURL.isEntity()); } + @Test + public void reference() { + ContextURL contextURL = ContextURL.getInstance(URI.create("http://host/service/$metadata#Customers/$ref")); + assertTrue(contextURL.isReference()); + assertNull(contextURL.getSelectList()); + assertNull(contextURL.getNavOrPropertyPath()); + assertFalse(contextURL.isEntity()); + assertFalse(contextURL.isDelta()); + } + @Test public void delta() { ContextURL contextURL = ContextURL.getInstance(URI.create("http://host/service/$metadata#Customers/$delta")); @@ -227,4 +242,79 @@ public class ContextURLTest { assertNull(contextURL.getNavOrPropertyPath()); assertFalse(contextURL.isEntity()); } + + @Test + public void buildServiceDocument() { + ContextURL contextURL = ContextURL.create().serviceRoot(URI.create("http://host/service/")).build(); + assertEquals("http://host/service/$metadata", contextURL.getURI().toASCIIString()); + } + + @Test + public void buildRelative() { + ContextURL contextURL = ContextURL.create().build(); + assertEquals("$metadata", contextURL.getURI().toASCIIString()); + } + + @Test + public void buildEntitySet() { + EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class); + Mockito.when(entitySet.getName()).thenReturn("Customers"); + ContextURL contextURL = ContextURL.create().serviceRoot(URI.create("http://host/service/")) + .entitySet(entitySet) + .build(); + assertEquals("http://host/service/$metadata#Customers", contextURL.getURI().toASCIIString()); + } + + @Test + public void buildDerivedEntitySet() { + EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class); + Mockito.when(entitySet.getName()).thenReturn("Customers"); + EdmEntityType derivedType = Mockito.mock(EdmEntityType.class); + Mockito.when(derivedType.getFullQualifiedName()).thenReturn(new FullQualifiedName("Model", "VipCustomer")); + ContextURL contextURL = ContextURL.create().serviceRoot(URI.create("http://host/service/")) + .entitySet(entitySet) + .derived(derivedType) + .build(); + assertEquals("http://host/service/$metadata#Customers/Model.VipCustomer", contextURL.getURI().toASCIIString()); + } + + @Test(expected = IllegalArgumentException.class) + public void buildDerivedEntitySetWithoutEntitySet() { + EdmEntityType derivedType = Mockito.mock(EdmEntityType.class); + Mockito.when(derivedType.getFullQualifiedName()).thenReturn(new FullQualifiedName("Model", "VipCustomer")); + ContextURL.create().derived(derivedType).build(); + } + + @Test + public void buildDerivedEntity() { + EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class); + Mockito.when(entitySet.getName()).thenReturn("Customers"); + EdmEntityType derivedType = Mockito.mock(EdmEntityType.class); + Mockito.when(derivedType.getFullQualifiedName()).thenReturn(new FullQualifiedName("Model", "VipCustomer")); + ContextURL contextURL = ContextURL.create().serviceRoot(URI.create("http://host/service/")) + .entitySet(entitySet) + .derived(derivedType) + .suffix(Suffix.ENTITY) + .build(); + assertEquals("http://host/service/$metadata#Customers/Model.VipCustomer/$entity", + contextURL.getURI().toASCIIString()); + } + + @Test(expected = IllegalArgumentException.class) + public void buildSuffixWithoutEntitySet() { + ContextURL.create().suffix(Suffix.ENTITY).build(); + } + + @Test + public void buildReference() { + ContextURL contextURL = ContextURL.create().suffix(Suffix.REFERENCE).build(); + assertEquals("$metadata#$ref", contextURL.getURI().toASCIIString()); + } + + @Test(expected = IllegalArgumentException.class) + public void buildReferenceWithEntitySet() { + EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class); + Mockito.when(entitySet.getName()).thenReturn("Customers"); + ContextURL.create().entitySet(entitySet).suffix(Suffix.REFERENCE).build(); + } } diff --git a/lib/commons-core/pom.xml b/lib/commons-core/pom.xml index 8977822f6..f2b7e0a49 100644 --- a/lib/commons-core/pom.xml +++ b/lib/commons-core/pom.xml @@ -65,14 +65,16 @@ com.fasterxml aalto-xml - + junit junit + test org.mockito mockito-all + test diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java index d1037c588..24e18da98 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java @@ -26,7 +26,6 @@ import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.domain.ODataError; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntitySet; -import org.apache.olingo.commons.api.edm.EdmEntityType; public interface ODataSerializer { @@ -36,12 +35,12 @@ public interface ODataSerializer { InputStream metadataDocument(Edm edm); - InputStream entity(EdmEntityType edmEntityType, Entity entity, ContextURL contextURL); + InputStream entity(EdmEntitySet edmEntitySet, Entity entity, ContextURL contextURL); InputStream entitySet(EdmEntitySet edmEntitySet, EntitySet entitySet, ContextURL contextURL); /** - * Writes an ODataError into an InputStream + * Writes an ODataError into an InputStream. * @param error the main error * @return inputStream containing the OData formatted error */ diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java index 2f2afeb38..da8380879 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.domain.ODataError; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntitySet; -import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; import org.apache.olingo.server.core.serializer.xml.MetadataDocumentXmlSerializer; @@ -77,7 +76,7 @@ public class ODataXmlSerializerImpl implements ODataSerializer { } @Override - public InputStream entity(final EdmEntityType edmEntityType, final Entity entity, final ContextURL contextURL) { + public InputStream entity(final EdmEntitySet edmEntitySet, final Entity entity, final ContextURL contextURL) { throw new ODataRuntimeException("Entity serialization not implemented for XML format"); } 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 b2025eb5b..e1f1992f8 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 @@ -27,6 +27,7 @@ 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; +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.LinkedComplexValue; @@ -123,24 +124,27 @@ public class ODataJsonSerializer implements ODataSerializer { @Override public InputStream entitySet(final EdmEntitySet edmEntitySet, final EntitySet entitySet, final ContextURL contextURL) { + final ContextURL entitySetContextURL = contextURL == null ? + ContextURL.create().entitySet(edmEntitySet).build() : + contextURL; CircleStreamBuffer buffer = new CircleStreamBuffer(); try { JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream()); json.writeStartObject(); - if (contextURL != null && format != ODataFormat.JSON_NO_METADATA) { - json.writeStringField(Constants.JSON_CONTEXT, contextURL.getURI().toASCIIString()); + if (entitySetContextURL != null && format != ODataFormat.JSON_NO_METADATA) { + json.writeStringField(Constants.JSON_CONTEXT, entitySetContextURL.getURI().toASCIIString()); } if (entitySet.getCount() != null) { - json.writeNumberField("@odata.count", entitySet.getCount()); + json.writeNumberField(Constants.JSON_COUNT, entitySet.getCount()); } json.writeFieldName(Constants.VALUE); json.writeStartArray(); for (Entity entity : entitySet.getEntities()) { - writeEntity(edmEntitySet.getEntityType(), entity, null, json); + writeEntity(edmEntitySet, entity, null, json); } json.writeEndArray(); if (entitySet.getNext() != null) { - json.writeStringField("@odata.nextLink", entitySet.getNext().toASCIIString()); + json.writeStringField(Constants.JSON_NEXT_LINK, entitySet.getNext().toASCIIString()); } json.close(); } catch (final IOException e) { @@ -152,11 +156,14 @@ public class ODataJsonSerializer implements ODataSerializer { } @Override - public InputStream entity(final EdmEntityType edmEntityType, final Entity entity, final ContextURL contextURL) { + public InputStream entity(final EdmEntitySet edmEntitySet, final Entity entity, final ContextURL contextURL) { + final ContextURL entityContextURL = contextURL == null ? + ContextURL.create().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build() : + contextURL; CircleStreamBuffer buffer = new CircleStreamBuffer(); try { JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream()); - writeEntity(edmEntityType, entity, contextURL, json); + writeEntity(edmEntitySet, entity, entityContextURL, json); json.close(); } catch (final IOException e) { throw new ODataRuntimeException(e); @@ -166,7 +173,7 @@ public class ODataJsonSerializer implements ODataSerializer { return buffer.getInputStream(); } - protected void writeEntity(final EdmEntityType entityType, final Entity entity, final ContextURL contextURL, + protected void writeEntity(final EdmEntitySet entitySet, final Entity entity, final ContextURL contextURL, final JsonGenerator json) throws IOException, EdmPrimitiveTypeException { json.writeStartObject(); if (format != ODataFormat.JSON_NO_METADATA) { @@ -174,15 +181,16 @@ public class ODataJsonSerializer implements ODataSerializer { json.writeStringField(Constants.JSON_CONTEXT, contextURL.getURI().toASCIIString()); } if (entity.getETag() != null) { - json.writeStringField("@odata.etag", entity.getETag()); + json.writeStringField(Constants.JSON_ETAG, entity.getETag()); } if (entity.getMediaETag() != null) { - json.writeStringField("@odata.mediaEtag", entity.getMediaETag()); + json.writeStringField(Constants.JSON_MEDIA_ETAG, entity.getMediaETag()); } if (entity.getMediaContentType() != null) { - json.writeStringField("@odata.mediaContentType", entity.getMediaContentType()); + 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); diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java index f9d1e5584..2badfab44 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java @@ -26,7 +26,6 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmEntitySet; -import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; @@ -73,8 +72,7 @@ public class TechnicalProcessor implements CollectionProcessor, EntityProcessor if (entitySet == null) { response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode()); } else { - response.setContent(serializer.entitySet(edmEntitySet, entitySet, - getContextUrl(request, edmEntitySet.getEntityType()))); + response.setContent(serializer.entitySet(edmEntitySet, entitySet, getContextUrl(edmEntitySet))); response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString()); } @@ -97,8 +95,7 @@ public class TechnicalProcessor implements CollectionProcessor, EntityProcessor if (entity == null) { response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode()); } else { - response.setContent(serializer.entity(edmEntitySet.getEntityType(), entity, - getContextUrl(request, edmEntitySet.getEntityType()))); + response.setContent(serializer.entity(edmEntitySet, entity, getContextUrl(edmEntitySet))); response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString()); } @@ -149,7 +146,7 @@ public class TechnicalProcessor implements CollectionProcessor, EntityProcessor return uriResource.getEntitySet(); } - private ContextURL getContextUrl(final ODataRequest request, final EdmEntityType entityType) { - return ContextURL.getInstance(URI.create(request.getRawBaseUri() + "/" + entityType.getName())); + private ContextURL getContextUrl(final EdmEntitySet entitySet) { + return ContextURL.create().entitySet(entitySet).build(); } } diff --git a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/JsonDataProviderTest.java b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/JsonDataProviderTest.java index 462855c4e..37600f86e 100644 --- a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/JsonDataProviderTest.java +++ b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/JsonDataProviderTest.java @@ -65,10 +65,10 @@ public class JsonDataProviderTest { @Test public void doRoundTrip() throws Exception { - doRoundTrip(entityContainer.getEntitySet("ESAllPrim"), 1401); - doRoundTrip(entityContainer.getEntitySet("ESCompAllPrim"), 1592); - doRoundTrip(entityContainer.getEntitySet("ESCollAllPrim"), 2855); - doRoundTrip(entityContainer.getEntitySet("ESMixPrimCollComp"), 1032); + doRoundTrip(entityContainer.getEntitySet("ESAllPrim"), 1440); + doRoundTrip(entityContainer.getEntitySet("ESCompAllPrim"), 1635); + doRoundTrip(entityContainer.getEntitySet("ESCollAllPrim"), 2898); + doRoundTrip(entityContainer.getEntitySet("ESMixPrimCollComp"), 1079); } @Test 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 d3753b400..3eaba5644 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 @@ -23,6 +23,7 @@ import java.net.URI; import org.apache.commons.io.IOUtils; 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.edm.Edm; @@ -49,8 +50,8 @@ public class ODataJsonSerializerTest { public void entitySimple() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); - InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity, - ContextURL.getInstance(URI.create("$metadata#ESAllPrim/$entity"))); + InputStream result = serializer.entity(edmEntitySet, entity, + ContextURL.create().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()); final String resultString = IOUtils.toString(result); final String expectedResult = "{" + "\"@odata.context\":\"$metadata#ESAllPrim/$entity\"," @@ -80,8 +81,7 @@ public class ODataJsonSerializerTest { EntitySet entitySet = data.readAll(edmEntitySet); entitySet.setCount(entitySet.getEntities().size()); entitySet.setNext(URI.create("/next")); - InputStream result = serializer.entitySet(edmEntitySet, entitySet, - ContextURL.getInstance(URI.create("$metadata#ESAllPrim"))); + InputStream result = serializer.entitySet(edmEntitySet, entitySet, null); final String resultString = IOUtils.toString(result); Assert.assertTrue(resultString.matches("\\{" @@ -103,11 +103,12 @@ public class ODataJsonSerializerTest { public void entityCollAllPrim() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); - InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity, - ContextURL.getInstance(URI.create("$metadata#ESCollAllPrim/$entity"))); + InputStream result = serializer.entity(edmEntitySet, entity, + ContextURL.create().serviceRoot(URI.create("http://host/service/")) + .entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()); final String resultString = IOUtils.toString(result); final String expectedResult = "{" - + "\"@odata.context\":\"$metadata#ESCollAllPrim/$entity\"," + + "\"@odata.context\":\"http://host/service/$metadata#ESCollAllPrim/$entity\"," + "\"PropertyInt16\":1," + "\"CollPropertyString\":[\"spiderman@comic.com\",\"spidermaus@comic.com\",\"spidergirl@comic.com\"]," + "\"CollPropertyBoolean\":[true,false,true]," @@ -135,8 +136,7 @@ public class ODataJsonSerializerTest { public void entityCompAllPrim() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCompAllPrim"); final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); - InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity, - ContextURL.getInstance(URI.create("$metadata#ESCompAllPrim/$entity"))); + InputStream result = serializer.entity(edmEntitySet, entity, null); final String resultString = IOUtils.toString(result); final String expectedResult = "{" + "\"@odata.context\":\"$metadata#ESCompAllPrim/$entity\"," @@ -166,8 +166,7 @@ public class ODataJsonSerializerTest { public void entityMixPrimCollComp() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp"); final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); - InputStream result = serializer.entity(edmEntitySet.getEntityType(), entity, - ContextURL.getInstance(URI.create("$metadata#ESMixPrimCollComp/$entity"))); + InputStream result = serializer.entity(edmEntitySet, entity, null); final String resultString = IOUtils.toString(result); final String expectedResult = "{" + "\"@odata.context\":\"$metadata#ESMixPrimCollComp/$entity\"," @@ -186,7 +185,7 @@ public class ODataJsonSerializerTest { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); InputStream result = new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) - .entity(edmEntitySet.getEntityType(), entity, ContextURL.getInstance(URI.create("contextURL"))); + .entity(edmEntitySet, entity, ContextURL.create().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()); final String resultString = IOUtils.toString(result); final String expectedResult = "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"}"; Assert.assertEquals(expectedResult, resultString); @@ -197,7 +196,7 @@ public class ODataJsonSerializerTest { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESTwoPrim"); final EntitySet entitySet = data.readAll(edmEntitySet); InputStream result = new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) - .entitySet(edmEntitySet, entitySet, ContextURL.getInstance(URI.create("contextURL"))); + .entitySet(edmEntitySet, entitySet, ContextURL.create().entitySet(edmEntitySet).build()); final String resultString = IOUtils.toString(result); final String expectedResult = "{\"value\":[" + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"},"