[OLINGO-1231] Serializer for complex collection properties does not respect

This commit is contained in:
ramya vasanth 2018-02-21 10:20:51 +05:30
parent 00d854f387
commit 48f93fd871
7 changed files with 346 additions and 5 deletions

View File

@ -0,0 +1,164 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.olingo.fit.tecsvc.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.commons.io.IOUtils;
import org.apache.olingo.client.api.ODataClient;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpMethod;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.fit.AbstractBaseTestITCase;
import org.apache.olingo.fit.tecsvc.TecSvcConst;
import org.junit.Test;
public class SelectOnComplexPropertiesITCase extends AbstractBaseTestITCase {
private static final String SERVICE_URI = TecSvcConst.BASE_URI + "/";
@Test
public void queryESKeyColPropertyComp1() throws Exception {
URL url = new URL(SERVICE_URI + "ESKeyNav(1)/CollPropertyComp"
+ "?$select=PropertyComp/PropertyString");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(HttpMethod.GET.name());
connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=minimal");
connection.connect();
assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode());
assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE)));
final String content = IOUtils.toString(connection.getInputStream());
assertTrue(content.contains("\"value\":[{\"PropertyComp\":"
+ "{\"PropertyString\":\"First Resource - positive values\"}},"
+ "{\"PropertyComp\":{\"PropertyString\":\"First Resource - positive values\"}},"
+ "{\"PropertyComp\":{\"PropertyString\":\"First Resource - positive values\"}}]"));
}
@Test
public void queryESKeyColPropertyComp2() throws Exception {
URL url = new URL(SERVICE_URI + "ESKeyNav(1)/CollPropertyComp"
+ "?$select=PropertyInt16");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(HttpMethod.GET.name());
connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=minimal");
connection.connect();
assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode());
assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE)));
final String content = IOUtils.toString(connection.getInputStream());
assertTrue(content.contains("\"value\":[{\"PropertyInt16\":1},{\"PropertyInt16\":2},{\"PropertyInt16\":3}]"));
}
@Test
public void queryESKeyColPropertyComp3() throws Exception {
URL url = new URL(SERVICE_URI + "ESKeyNav(1)/CollPropertyComp"
+ "?$select=PropertyComp");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(HttpMethod.GET.name());
connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=minimal");
connection.connect();
assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode());
assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE)));
final String content = IOUtils.toString(connection.getInputStream());
System.out.println("Content is::"+ content);
assertTrue(content.contains("\"value\":[{\"PropertyComp\":{"
+ "\"PropertyString\":\"First Resource - positive values\","
+ "\"PropertyBinary\":\"ASNFZ4mrze8=\",\"PropertyBoolean\":true,"
+ "\"PropertyByte\":255,\"PropertyDate\":\"2012-12-03\","
+ "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\","
+ "\"PropertyDecimal\":34,\"PropertySingle\":1.79E20,"
+ "\"PropertyDouble\":-1.79E20,\"PropertyDuration\":\"PT6S\","
+ "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\","
+ "\"PropertyInt16\":32767,\"PropertyInt32\":2147483647,"
+ "\"PropertyInt64\":9223372036854775807,\"PropertySByte\":127,"
+ "\"PropertyTimeOfDay\":\"21:05:59\"}},{\"PropertyComp\":"
+ "{\"PropertyString\":\"First Resource - positive values\","
+ "\"PropertyBinary\":\"ASNFZ4mrze8=\",\"PropertyBoolean\":true,"
+ "\"PropertyByte\":255,\"PropertyDate\":\"2012-12-03\","
+ "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\","
+ "\"PropertyDecimal\":34,\"PropertySingle\":1.79E20,"
+ "\"PropertyDouble\":-1.79E20,\"PropertyDuration\":\"PT6S\","
+ "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\","
+ "\"PropertyInt16\":32767,\"PropertyInt32\":2147483647,"
+ "\"PropertyInt64\":9223372036854775807,\"PropertySByte\":127,"
+ "\"PropertyTimeOfDay\":\"21:05:59\"}},{\"PropertyComp\":"
+ "{\"PropertyString\":\"First Resource - positive values\","
+ "\"PropertyBinary\":\"ASNFZ4mrze8=\",\"PropertyBoolean\":true,"
+ "\"PropertyByte\":255,\"PropertyDate\":\"2012-12-03\","
+ "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\","
+ "\"PropertyDecimal\":34,\"PropertySingle\":1.79E20,"
+ "\"PropertyDouble\":-1.79E20,\"PropertyDuration\":\"PT6S\","
+ "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\","
+ "\"PropertyInt16\":32767,\"PropertyInt32\":2147483647,"
+ "\"PropertyInt64\":9223372036854775807,\"PropertySByte\":127,"
+ "\"PropertyTimeOfDay\":\"21:05:59\"}}]"));
}
@Test
public void queryESKeyPropertyCompCompNav() throws Exception {
URL url = new URL(SERVICE_URI + "ESKeyNav(1)/PropertyCompCompNav"
+ "?$select=PropertyCompNav/PropertyInt16");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(HttpMethod.GET.name());
connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=minimal");
connection.connect();
assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode());
assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE)));
final String content = IOUtils.toString(connection.getInputStream());
assertTrue(content.contains("\"PropertyCompNav\":{\"PropertyInt16\":1}"));
connection.disconnect();
}
@Test
public void queryESCompCollDerivedWithMixedComplexTypes() throws Exception {
URL url = new URL(SERVICE_URI + "ESCompCollDerived(12345)/"
+ "CollPropertyCompAno?$select=PropertyString");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod(HttpMethod.GET.name());
connection.setRequestProperty(HttpHeader.ACCEPT, "application/json;odata.metadata=full");
connection.connect();
assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode());
assertEquals(ContentType.JSON_FULL_METADATA, ContentType.create(
connection.getHeaderField(HttpHeader.CONTENT_TYPE)));
final String content = IOUtils.toString(connection.getInputStream());
assertTrue(content.contains("\"@odata.type\":\"#Collection(olingo.odata.test1.CTTwoPrimAno)\","
+ "\"value\":[{\"@odata.type\":\"#olingo.odata.test1.CTBaseAno\","
+ "\"PropertyString\":\"TEST12345\"},{\"@odata.type\":"
+ "\"#olingo.odata.test1.CTTwoPrimAno\",\"PropertyString\":\"TESTabcd\"}]"));
}
@Override
protected ODataClient getClient() {
return null;
}
}

View File

@ -1203,7 +1203,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
}
writeOperations(property.getOperations(), json);
json.writeFieldName(Constants.VALUE);
writeComplexCollection(metadata, type, property, null, json);
Set<List<String>> selectedPaths = null;
if (null != options && null != options.getSelect()) {
final boolean all = ExpandSelectHelper.isAll(options.getSelect());
selectedPaths = all || property.isPrimitive() ? null : ExpandSelectHelper
.getSelectedPaths(options.getSelect().getSelectItems());
}
writeComplexCollection(metadata, type, property, selectedPaths, json);
json.writeEndObject();
json.close();

View File

@ -85,6 +85,28 @@ public abstract class ExpandSelectHelper {
return selectedPaths.isEmpty() ? null : selectedPaths;
}
public static Set<List<String>> getSelectedPaths(final List<SelectItem> selectItems) {
Set<List<String>> selectedPaths = new HashSet<List<String>>();
for (final SelectItem item : selectItems) {
final List<UriResource> parts = item.getResourcePath().getUriResourceParts();
final UriResource resource = parts.get(0);
if (resource instanceof UriResourceProperty) {
if (parts.size() > 0) {
List<String> path = new ArrayList<String>();
for (final UriResource part : parts.subList(0, parts.size())) {
if (part instanceof UriResourceProperty) {
path.add(((UriResourceProperty) part).getProperty().getName());
}
}
selectedPaths.add(path);
} else {
return null;
}
}
}
return selectedPaths.isEmpty() ? null : selectedPaths;
}
public static boolean isSelected(final Set<List<String>> selectedPaths, final String propertyName) {
for (final List<String> path : selectedPaths) {
if (propertyName.equals(path.get(0))) {

View File

@ -1176,7 +1176,13 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
writer.writeAttribute(METADATA, NS_METADATA, Constants.CONTEXT,
ContextURLBuilder.create(contextURL).toASCIIString());
writeMetadataETag(metadata, writer);
writeComplexCollection(metadata, type, property, null,
Set<List<String>> selectedPaths = null;
if (null != options && null != options.getSelect()) {
final boolean all = ExpandSelectHelper.isAll(options.getSelect());
selectedPaths = all || property.isPrimitive() ? null : ExpandSelectHelper
.getSelectedPaths(options.getSelect().getSelectItems());
}
writeComplexCollection(metadata, type, property, selectedPaths,
options == null ? null:options.xml10InvalidCharReplacement(), writer);
writer.writeEndElement();
writer.writeEndDocument();

View File

@ -87,4 +87,28 @@ public final class ExpandSelectMock {
Mockito.when(expand.getExpandItems()).thenReturn(expandItems);
return expand;
}
/**
* @param resource
* @return
*/
public static SelectItem mockSelectItemForColComplexProperty(final UriInfoResource resource) {
SelectItem selectItem = Mockito.mock(SelectItem.class);
Mockito.when(selectItem.getResourcePath()).thenReturn(resource);
return selectItem;
}
/**
* @param propertyWithinCT
* @return
*/
public static UriInfoResource mockComplexTypeResource(final EdmProperty propertyWithinCT) {
final UriInfoResource resource = Mockito.mock(UriInfoResource.class);
final List<UriResource> elements = new ArrayList<UriResource>();
final UriResourceProperty element = Mockito.mock(UriResourceProperty.class);
Mockito.when(element.getProperty()).thenReturn(propertyWithinCT);
elements.add(element);
Mockito.when(resource.getUriResourceParts()).thenReturn(elements);
return resource;
}
}

View File

@ -19,6 +19,7 @@
package org.apache.olingo.server.core.serializer.json;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
@ -51,15 +52,15 @@ 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.FullQualifiedName;
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.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.edmx.EdmxReference;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.OData;
@ -77,6 +78,7 @@ import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.serializer.SerializerResult;
import org.apache.olingo.server.api.uri.UriHelper;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@ -2592,4 +2594,86 @@ public class ODataJsonSerializerTest {
Assert.assertEquals(expected, resultString);
}
@Test
public void complexCollectionWithSelectProperty() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESKeyNav");
final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp");
final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
final EdmComplexType complexType = metadata.getEdm().getComplexType(
new FullQualifiedName("olingo.odata.test1", "CTPrimComp"));
final EdmProperty propertyWithinCT = (EdmProperty) complexType.getProperty("PropertyInt16");
final UriInfoResource resource = ExpandSelectMock.mockComplexTypeResource(propertyWithinCT);
final SelectItem selectItem = ExpandSelectMock.mockSelectItemForColComplexProperty(resource);
final SelectOption selectOption = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem));
final String resultString = IOUtils.toString(serializer
.complexCollection(metadata, (EdmComplexType) edmProperty.getType(), property,
ComplexSerializerOptions.with()
.contextURL(ContextURL.with()
.entitySet(edmEntitySet).keyPath("1")
.navOrPropertyPath("CollPropertyComp")
.build()).select(selectOption)
.build()).getContent());
Assert.assertEquals("{\"@odata.context\":\"$metadata#ESKeyNav(1)/CollPropertyComp\","
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
+ "\"value\":[{\"PropertyInt16\":1},{\"PropertyInt16\":2},{\"PropertyInt16\":3}]}",
resultString);
}
@Test
public void complexCollectionPropertyWithSelectNoMetadata() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESKeyNav");
final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp");
final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
final EdmComplexType complexType = metadata.getEdm().getComplexType(
new FullQualifiedName("olingo.odata.test1", "CTPrimComp"));
final EdmProperty propertyWithinCT = (EdmProperty) complexType.getProperty("PropertyInt16");
final UriInfoResource resource = ExpandSelectMock.mockComplexTypeResource(propertyWithinCT);
final SelectItem selectItem = ExpandSelectMock.mockSelectItemForColComplexProperty(resource);
final SelectOption selectOption = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem));
final String resultString = IOUtils.toString(serializerNoMetadata
.complexCollection(metadata, (EdmComplexType) edmProperty.getType(), property, ComplexSerializerOptions.with()
.contextURL(ContextURL.with()
.entitySet(edmEntitySet).keyPath("1")
.navOrPropertyPath("CollPropertyComp")
.build()).select(selectOption).build()).getContent());
Assert.assertEquals("{\"value\":[{\"PropertyInt16\":1},{\"PropertyInt16\":2},{\"PropertyInt16\":3}]}",
resultString);
}
@Test
public void complexCollectionPropertyWithSelectWithMetadataFull() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESKeyNav");
final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp");
final EdmComplexType complexType = metadata.getEdm().getComplexType(
new FullQualifiedName("olingo.odata.test1", "CTPrimComp"));
final EdmProperty propertyWithinCT = (EdmProperty) complexType.getProperty("PropertyInt16");
final UriInfoResource resource = ExpandSelectMock.mockComplexTypeResource(propertyWithinCT);
final SelectItem selectItem = ExpandSelectMock.mockSelectItemForColComplexProperty(resource);
final SelectOption selectOption = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem));
final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
final String resultString = IOUtils.toString(serializerFullMetadata
.complexCollection(metadata, (EdmComplexType) edmProperty.getType(),
property, ComplexSerializerOptions.with()
.contextURL(ContextURL.with().entitySet(edmEntitySet)
.keyPath("1")
.navOrPropertyPath("CollPropertyComp").build())
.select(selectOption)
.build())
.getContent());
assertTrue(resultString.contains("\"value\":[{\"@odata.type\":\"#olingo.odata.test1.CTPrimComp\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":1},"
+ "{\"@odata.type\":\"#olingo.odata.test1.CTPrimComp\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":2},"
+ "{\"@odata.type\":\"#olingo.odata.test1.CTPrimComp\","
+ "\"PropertyInt16@odata.type\":\"#Int16\",\"PropertyInt16\":3}]"));
}
}

View File

@ -42,6 +42,7 @@ 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.EdmProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.apache.olingo.commons.api.edmx.EdmxReference;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.OData;
@ -56,6 +57,7 @@ import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.serializer.SerializerResult;
import org.apache.olingo.server.api.uri.UriHelper;
import org.apache.olingo.server.api.uri.UriInfoResource;
import org.apache.olingo.server.api.uri.queryoption.CountOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@ -3176,4 +3178,37 @@ public class ODataXmlSerializerTest {
public void skippedComparison(Node control, Node test) { }
};
@Test
public void complexCollectionWithSelectProperty() throws Exception {
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESKeyNav");
final EdmProperty edmProperty = (EdmProperty) edmEntitySet.getEntityType().getProperty("CollPropertyComp");
final Property property = data.readAll(edmEntitySet).getEntities().get(0).getProperty(edmProperty.getName());
final EdmComplexType complexType = metadata.getEdm().getComplexType(
new FullQualifiedName("olingo.odata.test1", "CTPrimComp"));
final EdmProperty propertyWithinCT = (EdmProperty) complexType.getProperty("PropertyInt16");
final UriInfoResource resource = ExpandSelectMock.mockComplexTypeResource(propertyWithinCT);
final SelectItem selectItem = ExpandSelectMock.mockSelectItemForColComplexProperty(resource);
final SelectOption selectOption = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem));
final String resultString = IOUtils.toString(serializer
.complexCollection(metadata, (EdmComplexType) edmProperty.getType(), property,
ComplexSerializerOptions.with()
.contextURL(ContextURL.with()
.entitySet(edmEntitySet).keyPath("1")
.navOrPropertyPath("CollPropertyComp")
.build()).select(selectOption)
.build()).getContent());
final String expectedResult = "<?xml version='1.0' encoding='UTF-8'?>"
+ "<m:value xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" "
+ "xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" "
+ "m:type=\"#Collection(olingo.odata.test1.CTPrimComp)\" "
+ "m:context=\"$metadata#ESKeyNav(1)/CollPropertyComp\" "
+ "m:metadata-etag=\"metadataETag\">"
+ "<m:element><d:PropertyInt16 m:type=\"Int16\">1</d:PropertyInt16>"
+ "</m:element><m:element><d:PropertyInt16 m:type=\"Int16\">2</d:PropertyInt16>"
+ "</m:element><m:element><d:PropertyInt16 m:type=\"Int16\">3</d:PropertyInt16>"
+ "</m:element></m:value>";
Assert.assertEquals(expectedResult, resultString);
}
}