Repository: olingo-odata4 Updated Branches: refs/heads/OLINGO-422-SelectExpandSupport 461cdbbe2 -> a1d9f747b
[OLINGO-422] More support for expand and select in ContextURL Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/a1d9f747 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/a1d9f747 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/a1d9f747 Branch: refs/heads/OLINGO-422-SelectExpandSupport Commit: a1d9f747b8a44c1993f49b772eff149aab0c8db9 Parents: 461cdbb Author: mibo <[email protected]> Authored: Wed Sep 17 06:27:19 2014 +0200 Committer: mibo <[email protected]> Committed: Wed Sep 17 06:32:28 2014 +0200 ---------------------------------------------------------------------- .../server/api/serializer/ODataSerializer.java | 13 ++ .../core/serializer/ODataXmlSerializerImpl.java | 8 + .../serializer/json/ODataJsonSerializer.java | 32 +--- .../serializer/utils/ContextURLBuilder.java | 4 +- .../core/serializer/utils/ContextURLHelper.java | 144 ++++++++++++++++++ .../serializer/utils/ExpandSelectHelper.java | 35 ++++- .../serializer/utils/ContextURLBuilderTest.java | 15 +- .../tecsvc/processor/TechnicalProcessor.java | 24 ++- .../json/ODataJsonSerializerTest.java | 148 +++++++++--------- .../serializer/utils/ContextURLHelperTest.java | 151 +++++++++++++++++++ 10 files changed, 452 insertions(+), 122 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java ---------------------------------------------------------------------- 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 cc13485..91542aa 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 @@ -25,6 +25,8 @@ 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.server.api.ODataServerError; +import org.apache.olingo.server.api.uri.queryoption.ExpandOption; +import org.apache.olingo.server.api.uri.queryoption.SelectOption; public interface ODataSerializer { @@ -47,4 +49,15 @@ public interface ODataSerializer { * @throws ODataSerializerException */ InputStream error(ODataServerError error) throws ODataSerializerException; + + /** + * Builds the select-list part of a {@link org.apache.olingo.commons.api.data.ContextURL ContextURL}. + * @param edmEntitySet the Entity Set + * @param expand the $expand option + * @param select the $select option + * @return a String with the select list + * @throws ODataSerializerException + */ + String buildContextURLSelectList(EdmEntitySet edmEntitySet, ExpandOption expand, SelectOption select) + throws ODataSerializerException; } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java ---------------------------------------------------------------------- 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 65b0b3a..580833a 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 @@ -32,7 +32,10 @@ import org.apache.olingo.server.api.ODataServerError; import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.api.serializer.ODataSerializerException; import org.apache.olingo.server.api.serializer.ODataSerializerOptions; +import org.apache.olingo.server.api.uri.queryoption.ExpandOption; +import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; +import org.apache.olingo.server.core.serializer.utils.ContextURLHelper; import org.apache.olingo.server.core.serializer.xml.MetadataDocumentXmlSerializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -98,4 +101,9 @@ public class ODataXmlSerializerImpl implements ODataSerializer { ODataSerializerException.MessageKeys.NOT_IMPLEMENTED); } + @Override + public String buildContextURLSelectList(final EdmEntitySet edmEntitySet, + final ExpandOption expand, final SelectOption select) throws ODataSerializerException { + return ContextURLHelper.buildSelectList(edmEntitySet.getEntityType(), expand, select); + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java ---------------------------------------------------------------------- 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 6ab22b5..094b72e 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 @@ -20,7 +20,6 @@ package org.apache.olingo.server.core.serializer.json; import java.io.IOException; import java.io.InputStream; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -51,6 +50,7 @@ import org.apache.olingo.server.api.uri.queryoption.ExpandOption; import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer; import org.apache.olingo.server.core.serializer.utils.ContextURLBuilder; +import org.apache.olingo.server.core.serializer.utils.ContextURLHelper; import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -382,9 +382,9 @@ public class ODataJsonSerializer implements ODataSerializer { json.writeStartObject(); for (final String propertyName : type.getPropertyNames()) { final Property property = findProperty(propertyName, properties); - if (selectedPaths == null || isSelected(selectedPaths, propertyName)) { + if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) { writeProperty((EdmProperty) type.getProperty(propertyName), property, - selectedPaths == null ? null : getReducedSelectedPaths(selectedPaths, propertyName), + selectedPaths == null ? null : ExpandSelectHelper.getReducedSelectedPaths(selectedPaths, propertyName), json); } } @@ -400,27 +400,9 @@ public class ODataJsonSerializer implements ODataSerializer { return null; } - private static boolean isSelected(final Set<List<String>> selectedPaths, final String propertyName) { - for (final List<String> path : selectedPaths) { - if (propertyName.equals(path.get(0))) { - return true; - } - } - return false; - } - - private static Set<List<String>> getReducedSelectedPaths(final Set<List<String>> selectedPaths, - final String propertyName) { - Set<List<String>> reducedPaths = new HashSet<List<String>>(); - for (final List<String> path : selectedPaths) { - if (path.size() > 1) { - if (propertyName.equals(path.get(0))) { - reducedPaths.add(path.subList(1, path.size())); - } - } else { - return null; - } - } - return reducedPaths.isEmpty() ? null : reducedPaths; + @Override + public String buildContextURLSelectList(final EdmEntitySet edmEntitySet, + final ExpandOption expand, final SelectOption select) throws ODataSerializerException { + return ContextURLHelper.buildSelectList(edmEntitySet.getEntityType(), expand, select); } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java index faeb571..a9c1315 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilder.java @@ -19,7 +19,6 @@ package org.apache.olingo.server.core.serializer.utils; import java.net.URI; - import org.apache.olingo.commons.api.Constants; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.core.Encoder; @@ -41,6 +40,9 @@ public final class ContextURLBuilder { } result.append('/').append(Encoder.encode(contextURL.getDerivedEntity())); } + if (contextURL.getSelectList() != null) { + result.append('(').append(contextURL.getSelectList()).append(')'); + } if (contextURL.isReference()) { if (contextURL.getEntitySetOrSingletonOrType() != null) { throw new IllegalArgumentException("ContextURL: $ref with Entity Set"); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java new file mode 100644 index 0000000..49aa3c3 --- /dev/null +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelper.java @@ -0,0 +1,144 @@ +/* + * 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.server.core.serializer.utils; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.apache.olingo.commons.api.edm.EdmComplexType; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.core.Encoder; +import org.apache.olingo.server.api.serializer.ODataSerializerException; +import org.apache.olingo.server.api.uri.queryoption.ExpandItem; +import org.apache.olingo.server.api.uri.queryoption.ExpandOption; +import org.apache.olingo.server.api.uri.queryoption.SelectItem; +import org.apache.olingo.server.api.uri.queryoption.SelectOption; + +public final class ContextURLHelper { + + /** Builds a list of selected Properties for the ContextURL, + * taking care to preserve the order as defined in the EDM; + * returns NULL if no selection has taken place. + * @param entityType the Entity Type + * @param expand the Expand option (from the URL's $expand query option) + * @param select the Select option (from the URL's $select query option) + * @return a select-list String + * @throws ODataSerializerException if an unsupported feature is used + */ + public static String buildSelectList(final EdmEntityType entityType, + final ExpandOption expand, final SelectOption select) throws ODataSerializerException { + StringBuilder result = new StringBuilder(); + boolean isSelected = select != null && select.getSelectItems() != null && !select.getSelectItems().isEmpty(); + if(isSelected) { + handleSelect(entityType, select, result); + } + + if (ExpandSelectHelper.hasExpand(expand) && !ExpandSelectHelper.isExpandAll(expand)) { + handleExpand(entityType, expand, result); + } + return result.length() == 0 ? null : result.toString(); + } + + private static void handleSelect(EdmEntityType entityType, SelectOption select, StringBuilder result) { + if (ExpandSelectHelper.isAll(select)) { + result.append('*'); + } else { + final List<SelectItem> selectItems = select.getSelectItems(); + final Set<String> selectedPropertyNames = ExpandSelectHelper.getSelectedPropertyNames(selectItems); + for (final String propertyName : entityType.getPropertyNames()) { + if (selectedPropertyNames.contains(propertyName)) { + if (result.length() > 0) { + result.append(','); + } + final EdmProperty edmProperty = (EdmProperty) entityType.getProperty(propertyName); + final Set<List<String>> selectedPaths = ExpandSelectHelper.getSelectedPaths(selectItems, propertyName); + if (selectedPaths == null) { + result.append(Encoder.encode(propertyName)); + } else { + final List<List<String>> complexSelectedPaths = getComplexSelectedPaths(edmProperty, selectedPaths); + boolean first = true; + for (final List<String> path : complexSelectedPaths) { + if (first) { + first = false; + } else { + result.append(','); + } + boolean innerFirst = true; + for (final String name : path) { + if (innerFirst) { + innerFirst = false; + } else { + result.append('/'); + } + result.append(Encoder.encode(name)); + } + } + } + } + } + } + } + + private static void handleExpand(EdmEntityType entityType, ExpandOption expand, StringBuilder result) + throws ODataSerializerException { + final Set<String> expandedPropertyNames = ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems()); + for (final String propertyName : entityType.getNavigationPropertyNames()) { + if (expandedPropertyNames.contains(propertyName)) { + final ExpandItem expandItem = ExpandSelectHelper.getExpandItem(expand.getExpandItems(), propertyName); + if (ExpandSelectHelper.hasExpand(expandItem.getExpandOption()) + && !ExpandSelectHelper.isExpandAll(expandItem.getExpandOption()) + || ExpandSelectHelper.hasSelect(expandItem.getSelectOption())) { + final String innerSelectList = buildSelectList(entityType.getNavigationProperty(propertyName).getType(), + expandItem.getExpandOption(), expandItem.getSelectOption()); + if (result.length() > 0) { + result.append(','); + } + result.append(Encoder.encode(propertyName)).append('(').append(innerSelectList).append(')'); + } + } + } + } + + private static List<List<String>> getComplexSelectedPaths(final EdmProperty edmProperty, + final Set<List<String>> selectedPaths) { + List<List<String>> result = new ArrayList<List<String>>(); + if (selectedPaths == null) { + List<String> path = new LinkedList<String>(); + path.add(edmProperty.getName()); + result.add(path); + } else { + final EdmComplexType type = (EdmComplexType) edmProperty.getType(); + for (final String complexPropertyName : type.getPropertyNames()) { + if (ExpandSelectHelper.isSelected(selectedPaths, complexPropertyName)) { + List<List<String>> complexSelectedPaths = getComplexSelectedPaths( + (EdmProperty) type.getProperty(complexPropertyName), + ExpandSelectHelper.getReducedSelectedPaths(selectedPaths, complexPropertyName)); + for (final List<String> path : complexSelectedPaths) { + path.add(0, edmProperty.getName()); + result.add(path); + } + } + } + } + return result; + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java index c5dcbbe..37dbbac 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/utils/ExpandSelectHelper.java @@ -34,16 +34,20 @@ import org.apache.olingo.server.api.uri.queryoption.SelectOption; public abstract class ExpandSelectHelper { + public static boolean hasSelect(final SelectOption select) { + return select != null && select.getSelectItems() != null && !select.getSelectItems().isEmpty(); + } + public static boolean isAll(final SelectOption select) { - if (select == null || select.getSelectItems() == null || select.getSelectItems().isEmpty()) { - return true; - } else { + if (hasSelect(select)) { for (final SelectItem item : select.getSelectItems()) { if (item.isStar()) { return true; } } return false; + } else { + return true; } } @@ -81,6 +85,31 @@ public abstract class ExpandSelectHelper { 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))) { + return true; + } + } + return false; + } + + public static Set<List<String>> getReducedSelectedPaths(final Set<List<String>> selectedPaths, + final String propertyName) { + Set<List<String>> reducedPaths = new HashSet<List<String>>(); + for (final List<String> path : selectedPaths) { + if (propertyName.equals(path.get(0))) { + if (path.size() > 1) { + reducedPaths.add(path.subList(1, path.size())); + } else { + return null; + } + } + } + return reducedPaths.isEmpty() ? null : reducedPaths; + } + public static boolean hasExpand(final ExpandOption expand) { return expand != null && expand.getExpandItems() != null && !expand.getExpandItems().isEmpty(); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilderTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilderTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilderTest.java index 7a01643..bc136f4 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilderTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLBuilderTest.java @@ -21,7 +21,6 @@ package org.apache.olingo.server.core.serializer.utils; import static org.junit.Assert.assertEquals; import java.net.URI; - import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.ContextURL.Suffix; import org.apache.olingo.commons.api.edm.EdmEntitySet; @@ -34,14 +33,14 @@ public class ContextURLBuilderTest { @Test public void buildServiceDocument() { - ContextURL contextURL = ContextURL.with() + final ContextURL contextURL = ContextURL.with() .serviceRoot(URI.create("http://host/service/")).build(); assertEquals("http://host/service/$metadata", ContextURLBuilder.create(contextURL).toASCIIString()); } @Test public void buildRelative() { - ContextURL contextURL = ContextURL.with().build(); + final ContextURL contextURL = ContextURL.with().build(); assertEquals("$metadata", ContextURLBuilder.create(contextURL).toASCIIString()); } @@ -49,7 +48,7 @@ public class ContextURLBuilderTest { public void buildEntitySet() { EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class); Mockito.when(entitySet.getName()).thenReturn("Customers"); - ContextURL contextURL = ContextURL.with().serviceRoot(URI.create("http://host/service/")) + final ContextURL contextURL = ContextURL.with().serviceRoot(URI.create("http://host/service/")) .entitySet(entitySet) .build(); assertEquals("http://host/service/$metadata#Customers", ContextURLBuilder.create(contextURL).toASCIIString()); @@ -61,7 +60,7 @@ public class ContextURLBuilderTest { Mockito.when(entitySet.getName()).thenReturn("Customers"); EdmEntityType derivedType = Mockito.mock(EdmEntityType.class); Mockito.when(derivedType.getFullQualifiedName()).thenReturn(new FullQualifiedName("Model", "VipCustomer")); - ContextURL contextURL = ContextURL.with().serviceRoot(URI.create("http://host/service/")) + final ContextURL contextURL = ContextURL.with().serviceRoot(URI.create("http://host/service/")) .entitySet(entitySet) .derived(derivedType) .build(); @@ -82,7 +81,7 @@ public class ContextURLBuilderTest { Mockito.when(entitySet.getName()).thenReturn("Customers"); EdmEntityType derivedType = Mockito.mock(EdmEntityType.class); Mockito.when(derivedType.getFullQualifiedName()).thenReturn(new FullQualifiedName("Model", "VipCustomer")); - ContextURL contextURL = ContextURL.with().serviceRoot(URI.create("http://host/service/")) + final ContextURL contextURL = ContextURL.with().serviceRoot(URI.create("http://host/service/")) .entitySet(entitySet) .derived(derivedType) .suffix(Suffix.ENTITY) @@ -98,7 +97,7 @@ public class ContextURLBuilderTest { @Test public void buildReference() { - ContextURL contextURL = ContextURL.with().suffix(Suffix.REFERENCE).build(); + final ContextURL contextURL = ContextURL.with().suffix(Suffix.REFERENCE).build(); assertEquals("$metadata#$ref", ContextURLBuilder.create(contextURL).toASCIIString()); } @@ -116,7 +115,7 @@ public class ContextURLBuilderTest { EdmEntityType derivedType = Mockito.mock(EdmEntityType.class); Mockito.when(derivedType.getFullQualifiedName()).thenReturn( new FullQualifiedName("Namensräumchen", "UnüblicherName")); - ContextURL contextURL = ContextURL.with().entitySet(entitySet).derived(derivedType).build(); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet).derived(derivedType).build(); assertEquals("$metadata#Entit%C3%A4ten/Namensr%C3%A4umchen.Un%C3%BCblicherName", ContextURLBuilder.create(contextURL).toString()); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java ---------------------------------------------------------------------- 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 950ce95..926353f 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 @@ -36,11 +36,14 @@ import org.apache.olingo.server.api.ODataTranslatedException; import org.apache.olingo.server.api.processor.EntityCollectionProcessor; import org.apache.olingo.server.api.processor.EntityProcessor; import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.ODataSerializerException; import org.apache.olingo.server.api.serializer.ODataSerializerOptions; import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.queryoption.ExpandOption; +import org.apache.olingo.server.api.uri.queryoption.SelectOption; import org.apache.olingo.server.tecsvc.data.DataProvider; import java.util.List; @@ -74,11 +77,13 @@ public class TechnicalProcessor implements EntityCollectionProcessor, EntityProc response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode()); } else { ODataSerializer serializer = odata.createSerializer(ODataFormat.fromContentType(requestedContentType)); + final ExpandOption expand = uriInfo.getExpandOption(); + final SelectOption select = uriInfo.getSelectOption(); response.setContent(serializer.entitySet(edmEntitySet, entitySet, ODataSerializerOptions.with() - .contextURL(getContextUrl(edmEntitySet, false)) + .contextURL(getContextUrl(serializer, edmEntitySet, false, expand, select)) .count(uriInfo.getCountOption()) - .expand(uriInfo.getExpandOption()).select(uriInfo.getSelectOption()) + .expand(expand).select(select) .build())); response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString()); @@ -106,12 +111,13 @@ public class TechnicalProcessor implements EntityCollectionProcessor, EntityProc response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode()); } else { ODataSerializer serializer = odata.createSerializer(ODataFormat.fromContentType(requestedContentType)); + final ExpandOption expand = uriInfo.getExpandOption(); + final SelectOption select = uriInfo.getSelectOption(); response.setContent(serializer.entity(edmEntitySet, entity, ODataSerializerOptions.with() - .contextURL(getContextUrl(edmEntitySet, true)) + .contextURL(getContextUrl(serializer, edmEntitySet, true, expand, select)) .count(uriInfo.getCountOption()) - .expand(uriInfo.getExpandOption()) - .select(uriInfo.getSelectOption()) + .expand(uriInfo.getExpandOption()).select(uriInfo.getSelectOption()) .build())); response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString()); @@ -167,7 +173,11 @@ public class TechnicalProcessor implements EntityCollectionProcessor, EntityProc return uriResource.getEntitySet(); } - private ContextURL getContextUrl(final EdmEntitySet entitySet, final boolean isSingleEntity) { - return ContextURL.with().entitySet(entitySet).suffix(isSingleEntity ? Suffix.ENTITY : null).build(); + private ContextURL getContextUrl(final ODataSerializer serializer, + final EdmEntitySet entitySet, final boolean isSingleEntity, + final ExpandOption expand, final SelectOption select) throws ODataSerializerException { + return ContextURL.with().entitySet(entitySet) + .selectList(serializer.buildContextURLSelectList(entitySet, expand, select)) + .suffix(isSingleEntity ? Suffix.ENTITY : null).build(); } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java ---------------------------------------------------------------------- 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 213c26d..c22f677 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 @@ -350,18 +350,17 @@ public class ODataJsonSerializerTest { final SelectItem selectItem1 = mockSelectItem(edmEntitySet, "PropertyDate"); final SelectItem selectItem2 = mockSelectItem(edmEntitySet, "PropertyBoolean"); final SelectOption select = mockSelectOption(Arrays.asList(selectItem1, selectItem2, selectItem2)); - InputStream result = - new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) // serializer - .entity(edmEntitySet, entity, - ODataSerializerOptions.with() - .contextURL(null) - // ContextURL.Builder.with().entitySet(edmEntitySet).selectList("PropertyBoolean,PropertyDate") - // .suffix(Suffix.ENTITY).build(), - .select(select) - .build()); + InputStream result = serializer + .entity(edmEntitySet, entity, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(serializer.buildContextURLSelectList(edmEntitySet, null, select)) + .suffix(Suffix.ENTITY).build()) + .select(select) + .build()); final String resultString = IOUtils.toString(result); final String expectedResult = "{" - // + "\"@odata.context\":\"$metadata#ESAllPrim(PropertyBoolean,PropertyDate)/$entity\"," + + "\"@odata.context\":\"$metadata#ESAllPrim(PropertyBoolean,PropertyDate)/$entity\"," + "\"PropertyBoolean\":true,\"PropertyDate\":\"2012-12-03\"}"; Assert.assertEquals(expectedResult, resultString); } @@ -391,18 +390,17 @@ public class ODataJsonSerializerTest { final EntitySet entitySet = data.readAll(edmEntitySet); final SelectOption select = mockSelectOption(Arrays.asList( mockSelectItem(edmEntitySet, "PropertyComp", "PropertyComp", "PropertyString"))); - InputStream result = - new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) // serializer - .entitySet(edmEntitySet, entitySet, - ODataSerializerOptions.with() - .contextURL(null) - // ContextURL.Builder.with().entitySet(edmEntitySet) - // .selectList("PropertyComp/PropertyComp/PropertyString").build(), - .select(select) - .build()); + InputStream result = serializer + .entitySet(edmEntitySet, entitySet, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(serializer.buildContextURLSelectList(edmEntitySet, null, select)) + .build()) + .select(select) + .build()); final String resultString = IOUtils.toString(result); Assert.assertEquals("{" - // + "\"@odata.context\":\"$metadata#ESCompComp(PropertyComp/PropertyComp/PropertyString)\"," + + "\"@odata.context\":\"$metadata#ESCompComp(PropertyComp/PropertyComp/PropertyString)\"," + "\"value\":[" + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyString\":\"String 1\"}}}," + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyString\":\"String 2\"}}}]}", @@ -416,18 +414,16 @@ public class ODataJsonSerializerTest { final SelectOption select = mockSelectOption(Arrays.asList( mockSelectItem(edmEntitySet, "PropertyComp", "PropertyComp", "PropertyString"), mockSelectItem(edmEntitySet, "PropertyComp", "PropertyComp"))); - InputStream result = - new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) // serializer - .entitySet(edmEntitySet, entitySet, - ODataSerializerOptions.with() - .contextURL(null) - // ContextURL.Builder.with().entitySet(edmEntitySet) - // .selectList("PropertyComp/PropertyComp").build() - .select(select) - .build()); - final String resultString = IOUtils.toString(result); + final String resultString = IOUtils.toString(serializer + .entitySet(edmEntitySet, entitySet, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(serializer.buildContextURLSelectList(edmEntitySet, null, select)) + .build()) + .select(select) + .build())); Assert.assertEquals("{" - // + "\"@odata.context\":\"$metadata#ESCompComp(PropertyComp/PropertyComp)\"," + + "\"@odata.context\":\"$metadata#ESCompComp(PropertyComp/PropertyComp)\"," + "\"value\":[" + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyInt16\":123,\"PropertyString\":\"String 1\"}}}," + "{\"PropertyComp\":{\"PropertyComp\":{\"PropertyInt16\":987,\"PropertyString\":\"String 2\"}}}]}", @@ -477,17 +473,16 @@ public class ODataJsonSerializerTest { ExpandItem expandItem = mockExpandItem(edmEntitySet, "NavPropertyETAllPrimOne"); Mockito.when(expandItem.getSelectOption()).thenReturn(select); final ExpandOption expand = mockExpandOption(Arrays.asList(expandItem)); - InputStream result = - new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) // serializer - .entity(edmEntitySet, entity, - ODataSerializerOptions.with() - .contextURL(null) - // ContextURL.Builder.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build() - .expand(expand) - .build()); - final String resultString = IOUtils.toString(result); + final String resultString = IOUtils.toString(serializer + .entity(edmEntitySet, entity, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(serializer.buildContextURLSelectList(edmEntitySet, expand, select)) + .suffix(Suffix.ENTITY).build()) + .expand(expand) + .build())); Assert.assertEquals("{" - // + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimOne(PropertyDate))/$entity\"," + + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimOne(PropertyDate))/$entity\"," + "\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"," + "\"NavPropertyETAllPrimOne\":{\"PropertyDate\":\"2012-12-03\"}}", resultString); @@ -502,18 +497,17 @@ public class ODataJsonSerializerTest { Mockito.when(expandItemAll.isStar()).thenReturn(true); final ExpandOption expand = mockExpandOption(Arrays.asList(expandItem, expandItem, expandItemAll)); final SelectOption select = mockSelectOption(Arrays.asList(mockSelectItem(edmEntitySet, "PropertySByte"))); - InputStream result = - new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) // serializer - .entity(edmEntitySet, entity, - ODataSerializerOptions.with() - .contextURL(null) - // ContextURL.Builder.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build() - .expand(expand) - .select(select) - .build()); - final String resultString = IOUtils.toString(result); + final String resultString = IOUtils.toString(serializer + .entity(edmEntitySet, entity, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(serializer.buildContextURLSelectList(edmEntitySet, expand, select)) + .suffix(Suffix.ENTITY).build()) + .expand(expand) + .select(select) + .build())); Assert.assertEquals("{" - // + "\"@odata.context\":\"$metadata#ESAllPrim(PropertySByte)/$entity\"," + + "\"@odata.context\":\"$metadata#ESAllPrim(PropertySByte)/$entity\"," + "\"PropertySByte\":127," + "\"NavPropertyETTwoPrimOne\":{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}," + "\"NavPropertyETTwoPrimMany\":[{\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"}]}", @@ -528,18 +522,17 @@ public class ODataJsonSerializerTest { Mockito.when(expandItemAll.isStar()).thenReturn(true); final ExpandOption expand = mockExpandOption(Arrays.asList(expandItemAll)); final SelectOption select = mockSelectOption(Arrays.asList(mockSelectItem(edmEntitySet, "PropertyTimeOfDay"))); - InputStream result = - new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) // serializer - .entity(edmEntitySet, entity, - ODataSerializerOptions.with() - .contextURL(null) - // ContextURL.Builder.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build() - .expand(expand) - .select(select) - .build()); - final String resultString = IOUtils.toString(result); + final String resultString = IOUtils.toString(serializer + .entity(edmEntitySet, entity, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(serializer.buildContextURLSelectList(edmEntitySet, expand, select)) + .suffix(Suffix.ENTITY).build()) + .expand(expand) + .select(select) + .build())); Assert.assertEquals("{" - // + "\"@odata.context\":\"$metadata#ESAllPrim(PropertyTimeOfDay)/$entity\"," + + "\"@odata.context\":\"$metadata#ESAllPrim(PropertyTimeOfDay)/$entity\"," + "\"PropertyTimeOfDay\":\"23:49:14\"," + "\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}", resultString); @@ -559,17 +552,16 @@ public class ODataJsonSerializerTest { mockSelectItem(innerEntitySet, "PropertyInt32"))); Mockito.when(expandItemFirst.getSelectOption()).thenReturn(select); final ExpandOption expand = mockExpandOption(Arrays.asList(expandItemFirst)); - InputStream result = - new ODataJsonSerializer(ODataFormat.JSON_NO_METADATA) // serializer - .entity(edmEntitySet, entity, - ODataSerializerOptions.with() - .contextURL(null) - // ContextURL.Builder.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build() - .expand(expand) - .build()); - final String resultString = IOUtils.toString(result); + final String resultString = IOUtils.toString(serializer + .entity(edmEntitySet, entity, + ODataSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet) + .selectList(serializer.buildContextURLSelectList(edmEntitySet, expand, select)) + .suffix(Suffix.ENTITY).build()) + .expand(expand) + .build())); Assert.assertEquals("{" - // + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimMany(PropertyInt32))/$entity\"," + + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimMany(PropertyInt32))/$entity\"," + "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\"," + "\"NavPropertyETAllPrimMany\":[" + "{\"PropertyInt32\":-2147483648,\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]}," @@ -581,7 +573,7 @@ public class ODataJsonSerializerTest { resultString); } - private UriInfoResource mockResource(final EdmEntitySet edmEntitySet, final String... names) { + private static UriInfoResource mockResource(final EdmEntitySet edmEntitySet, final String... names) { EdmStructuredType type = edmEntitySet.getEntityType(); List<UriResource> elements = new ArrayList<UriResource>(); for (final String name : Arrays.asList(names)) { @@ -603,27 +595,27 @@ public class ODataJsonSerializerTest { return resource; } - private SelectItem mockSelectItem(final EdmEntitySet edmEntitySet, final String... names) { + public static SelectItem mockSelectItem(final EdmEntitySet edmEntitySet, final String... names) { final UriInfoResource resource = mockResource(edmEntitySet, names); SelectItem selectItem = Mockito.mock(SelectItem.class); Mockito.when(selectItem.getResourcePath()).thenReturn(resource); return selectItem; } - private SelectOption mockSelectOption(final List<SelectItem> selectItems) { + public static SelectOption mockSelectOption(final List<SelectItem> selectItems) { SelectOption select = Mockito.mock(SelectOption.class); Mockito.when(select.getSelectItems()).thenReturn(selectItems); return select; } - private ExpandItem mockExpandItem(final EdmEntitySet edmEntitySet, final String... names) { + public static ExpandItem mockExpandItem(final EdmEntitySet edmEntitySet, final String... names) { final UriInfoResource resource = mockResource(edmEntitySet, names); ExpandItem expandItem = Mockito.mock(ExpandItem.class); Mockito.when(expandItem.getResourcePath()).thenReturn(resource); return expandItem; } - private ExpandOption mockExpandOption(final List<ExpandItem> expandItems) { + public static ExpandOption mockExpandOption(final List<ExpandItem> expandItems) { ExpandOption expand = Mockito.mock(ExpandOption.class); Mockito.when(expand.getExpandItems()).thenReturn(expandItems); return expand; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/a1d9f747/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java new file mode 100644 index 0000000..96f8817 --- /dev/null +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/utils/ContextURLHelperTest.java @@ -0,0 +1,151 @@ +/* + * 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.server.core.serializer.utils; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.apache.olingo.commons.api.data.ContextURL; +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.FullQualifiedName; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.uri.queryoption.ExpandItem; +import org.apache.olingo.server.api.uri.queryoption.ExpandOption; +import org.apache.olingo.server.api.uri.queryoption.SelectItem; +import org.apache.olingo.server.api.uri.queryoption.SelectOption; +import org.apache.olingo.server.core.serializer.json.ODataJsonSerializerTest; +import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; +import org.junit.Test; +import org.mockito.Mockito; + +public class ContextURLHelperTest { + + private static final Edm edm = OData.newInstance().createEdm(new EdmTechProvider()); + private static final EdmEntityContainer entityContainer = edm.getEntityContainer( + new FullQualifiedName("olingo.odata.test1", "Container")); + + @Test + public void buildSelect() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESAllPrim"); + final SelectItem selectItem1 = ODataJsonSerializerTest.mockSelectItem(entitySet, "PropertyString"); + final SelectItem selectItem2 = ODataJsonSerializerTest.mockSelectItem(entitySet, "PropertyInt16"); + final SelectOption select = ODataJsonSerializerTest.mockSelectOption(Arrays.asList( + selectItem1, selectItem2, selectItem2)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESAllPrim(PropertyInt16,PropertyString)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildSelectAll() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESAllPrim"); + final SelectItem selectItem1 = ODataJsonSerializerTest.mockSelectItem(entitySet, "PropertyGuid"); + SelectItem selectItem2 = Mockito.mock(SelectItem.class); + Mockito.when(selectItem2.isStar()).thenReturn(true); + final SelectOption select = ODataJsonSerializerTest.mockSelectOption(Arrays.asList(selectItem1, selectItem2)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESAllPrim(*)", ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildSelectComplex() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESCompMixPrimCollComp"); + final SelectOption select = ODataJsonSerializerTest.mockSelectOption(Arrays.asList( + ODataJsonSerializerTest.mockSelectItem(entitySet, + "PropertyMixedPrimCollComp", "PropertyComp", "PropertyString"), + ODataJsonSerializerTest.mockSelectItem(entitySet, + "PropertyMixedPrimCollComp", "PropertyComp", "PropertyInt16"), + ODataJsonSerializerTest.mockSelectItem(entitySet, "PropertyMixedPrimCollComp", "CollPropertyString"), + ODataJsonSerializerTest.mockSelectItem(entitySet, "PropertyMixedPrimCollComp", "CollPropertyComp"), + ODataJsonSerializerTest.mockSelectItem(entitySet, "PropertyInt16"))); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESCompMixPrimCollComp(" + + "PropertyInt16," + + "PropertyMixedPrimCollComp/CollPropertyString," + + "PropertyMixedPrimCollComp/PropertyComp/PropertyInt16," + + "PropertyMixedPrimCollComp/PropertyComp/PropertyString," + + "PropertyMixedPrimCollComp/CollPropertyComp)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildExpandAll() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoPrim"); + ExpandItem expandItem = Mockito.mock(ExpandItem.class); + Mockito.when(expandItem.isStar()).thenReturn(true); + final ExpandOption expand = ODataJsonSerializerTest.mockExpandOption(Arrays.asList(expandItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), expand, null)).build(); + assertEquals("$metadata#ESTwoPrim", ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildExpandNoSelect() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoPrim"); + final ExpandOption expand = ODataJsonSerializerTest.mockExpandOption(Arrays.asList( + ODataJsonSerializerTest.mockExpandItem(entitySet, "NavPropertyETAllPrimOne"))); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), expand, null)).build(); + assertEquals("$metadata#ESTwoPrim", ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildExpandSelect() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoPrim"); + final ExpandItem expandItem1 = ODataJsonSerializerTest.mockExpandItem(entitySet, "NavPropertyETAllPrimOne"); + final EdmEntitySet innerEntitySet = entityContainer.getEntitySet("ESAllPrim"); + ExpandItem expandItem2 = ODataJsonSerializerTest.mockExpandItem(entitySet, "NavPropertyETAllPrimMany"); + final SelectOption innerSelect = ODataJsonSerializerTest.mockSelectOption(Arrays.asList( + ODataJsonSerializerTest.mockSelectItem(innerEntitySet, "PropertyInt32"))); + Mockito.when(expandItem2.getSelectOption()).thenReturn(innerSelect); + final ExpandOption expand = ODataJsonSerializerTest.mockExpandOption(Arrays.asList( + expandItem1, expandItem2)); + final SelectItem selectItem = ODataJsonSerializerTest.mockSelectItem(entitySet, "PropertyString"); + final SelectOption select = ODataJsonSerializerTest.mockSelectOption(Arrays.asList(selectItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), expand, select)).build(); + assertEquals("$metadata#ESTwoPrim(PropertyString,NavPropertyETAllPrimMany(PropertyInt32))", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildExpandSelectTwoLevels() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoPrim"); + final EdmEntitySet innerEntitySet = entityContainer.getEntitySet("ESAllPrim"); + ExpandItem expandItemInner = ODataJsonSerializerTest.mockExpandItem(innerEntitySet, "NavPropertyETTwoPrimOne"); + SelectItem innerSelectItem = Mockito.mock(SelectItem.class); + Mockito.when(innerSelectItem.isStar()).thenReturn(true); + final SelectOption innerSelect = ODataJsonSerializerTest.mockSelectOption(Arrays.asList(innerSelectItem)); + Mockito.when(expandItemInner.getSelectOption()).thenReturn(innerSelect); + final ExpandOption innerExpand = ODataJsonSerializerTest.mockExpandOption(Arrays.asList(expandItemInner)); + ExpandItem expandItem = ODataJsonSerializerTest.mockExpandItem(entitySet, "NavPropertyETAllPrimOne"); + Mockito.when(expandItem.getExpandOption()).thenReturn(innerExpand); + final ExpandOption expand = ODataJsonSerializerTest.mockExpandOption(Arrays.asList(expandItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), expand, null)).build(); + assertEquals("$metadata#ESTwoPrim(NavPropertyETAllPrimOne(NavPropertyETTwoPrimOne(*)))", + ContextURLBuilder.create(contextURL).toASCIIString()); + } +}
