Repository: olingo-odata4 Updated Branches: refs/heads/master eb112032d -> bf4e2017f
[OLINGO-1246] Fixes for Context url when the URL has select clause and expand clause having select Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/bf4e2017 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/bf4e2017 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/bf4e2017 Branch: refs/heads/master Commit: bf4e2017f244c4c0649b3a7c16f3cfa5ba42a572 Parents: eb11203 Author: ramya vasanth <ramya.vasa...@sap.com> Authored: Tue Mar 13 15:31:15 2018 +0530 Committer: ramya vasanth <ramya.vasa...@sap.com> Committed: Tue Mar 13 15:31:15 2018 +0530 ---------------------------------------------------------------------- .../core/serializer/utils/ContextURLHelper.java | 256 +++++++++++++++++-- .../serializer/utils/ExpandSelectHelper.java | 83 ++++++ .../serializer/utils/ContextURLBuilderTest.java | 38 +++ .../core/serializer/ExpandSelectMock.java | 182 +++++++++++++ .../serializer/utils/ContextURLHelperTest.java | 144 ++++++++++- .../olingo/server/core/uri/UriHelperTest.java | 2 - 6 files changed, 674 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/bf4e2017/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 index 66dd84f..c2efcdd 100644 --- 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 @@ -23,13 +23,21 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; +import org.apache.olingo.commons.api.edm.EdmAction; import org.apache.olingo.commons.api.edm.EdmComplexType; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmFunction; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.EdmStructuredType; import org.apache.olingo.commons.core.Encoder; import org.apache.olingo.server.api.serializer.SerializerException; import org.apache.olingo.server.api.uri.UriParameter; import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceAction; +import org.apache.olingo.server.api.uri.UriResourceComplexProperty; +import org.apache.olingo.server.api.uri.UriResourceFunction; +import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourceProperty; import org.apache.olingo.server.api.uri.queryoption.ExpandItem; import org.apache.olingo.server.api.uri.queryoption.ExpandOption; @@ -63,47 +71,222 @@ public final class ContextURLHelper { return result.length() == 0 ? null : result.toString(); } - private static void handleSelect(final EdmStructuredType type, final SelectOption select, + private static void handleSelect(EdmStructuredType type, final SelectOption select, final StringBuilder result) { if (ExpandSelectHelper.isAll(select)) { result.append('*'); } else { final List<SelectItem> selectItems = select.getSelectItems(); + type = getTypeFromSelectItems(selectItems, type); final Set<String> selectedPropertyNames = ExpandSelectHelper.getSelectedPropertyNames(selectItems); for (final String propertyName : type.getPropertyNames()) { - if (selectedPropertyNames.contains(propertyName)) { - if (result.length() > 0) { - result.append(','); + constructSelectItemList(type, result, selectItems, selectedPropertyNames, propertyName); + } + for (final String propertyName : type.getNavigationPropertyNames()) { + constructSelectItemList(type, result, selectItems, selectedPropertyNames, propertyName); + } + if ((result.toString().length() == 0 && selectItems.size() > 0) || + (result.toString().split(",").length < selectItems.size())) { + constructSelectItemListForActionsAndFunctions(type, result, selectItems); + } + } + } + + /** + * This constructs the result based on the qualified action name + * and qualified function name specified in the select option of the url + * @param type + * @param result + * @param selectItems + */ + private static void constructSelectItemListForActionsAndFunctions(EdmStructuredType type, StringBuilder result, + List<SelectItem> selectItems) { + for (SelectItem item : selectItems) { + final UriResource resource = item.getResourcePath().getUriResourceParts().get(0); + if (resource instanceof UriResourceAction) { + EdmAction action = ((UriResourceAction)resource).getAction(); + if (action != null && action.isBound()) { + String actionBindingParamType = action.getBindingParameterTypeFqn(). + getFullQualifiedNameAsString(); + if (type.getFullQualifiedName().getFullQualifiedNameAsString(). + equalsIgnoreCase(actionBindingParamType)) { + if (result.length() > 0) { + result.append(','); + } + result.append(Encoder.encode(action.getName())); } - final EdmProperty edmProperty = type.getStructuralProperty(propertyName); - final Set<List<String>> selectedPaths = ExpandSelectHelper.getSelectedPaths(selectItems, propertyName); - if (selectedPaths == null) { - result.append(Encoder.encode(propertyName)); + } + } else if (resource instanceof UriResourceFunction) { + EdmFunction function = ((UriResourceFunction)resource).getFunction(); + if (function != null && function.isBound()) { + String functionBindingParamType = function.getBindingParameterTypeFqn(). + getFullQualifiedNameAsString(); + if (type.getFullQualifiedName().getFullQualifiedNameAsString(). + equalsIgnoreCase(functionBindingParamType)) { + if (result.length() > 0) { + result.append(','); + } + result.append(Encoder.encode(function.getName())); + } + } + } + } + } + + /** + * This fetches the correct EntityType if there is an entity type cast + * specified in the select option of the url + * @param selectItems + * @param type + * @return + */ + private static EdmStructuredType getTypeFromSelectItems(List<SelectItem> selectItems, EdmStructuredType type) { + EdmStructuredType edmType = type; + for (final SelectItem item : selectItems) { + if (item.getStartTypeFilter() != null && item.getStartTypeFilter() instanceof EdmEntityType) { + edmType = (EdmEntityType) item.getStartTypeFilter(); + } + } + return edmType; + } + + /** + * @param type + * @param result + * @param selectItems + * @param selectedPropertyNames + * @param propertyName + */ + private static void constructSelectItemList(final EdmStructuredType type, final StringBuilder result, + final List<SelectItem> selectItems, final Set<String> selectedPropertyNames, final String propertyName) { + if (selectedPropertyNames.contains(propertyName)) { + if (result.length() > 0) { + result.append(','); + } + final EdmProperty edmProperty = type.getStructuralProperty(propertyName); + final Set<List<String>> selectedPaths = ExpandSelectHelper. + getSelectedPathsWithTypeCasts(selectItems, propertyName); + if (selectedPaths == null) { + result.append(Encoder.encode(propertyName)); + } else { + List<List<String>> complexSelectedPaths = edmProperty != null && + edmProperty.getType() instanceof EdmComplexType ? + getComplexSelectedPaths(edmProperty, selectedPaths) : new ArrayList<List<String>>(); + if (complexSelectedPaths.isEmpty()) { + for (List<String> path : selectedPaths) { + complexSelectedPaths.add(path); + } + int position = getPositionToAddProperty(selectItems, propertyName, selectedPaths); + if (position == -1) { + complexSelectedPaths.get(0).add(propertyName); + } else { + complexSelectedPaths.get(0).add(position, propertyName); + } + } + + boolean first = true; + for (final List<String> path : complexSelectedPaths) { + if (first) { + first = false; } 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)); - } + result.append(','); + } + boolean innerFirst = true; + for (final String name : path) { + if (innerFirst) { + innerFirst = false; + } else { + result.append('/'); } + result.append(Encoder.encode(name)); } } } } } + /** + * If there is a type filter on a complex property (complex type cast) or + * a type filter on a navigation property, this method finds the appropriate position + * to add the complex property or the navigation property in the result object + * @param selectItems + * @param propertyName + * @param selectedPaths + * @return + */ + private static int getPositionToAddProperty(List<SelectItem> selectItems, String propertyName, + Set<List<String>> selectedPaths) { + for (SelectItem item : selectItems) { + final List<UriResource> parts = item.getResourcePath().getUriResourceParts(); + int i = 0; + for (UriResource part : parts) { + if (part instanceof UriResourceComplexProperty && + ((UriResourceComplexProperty) part).getProperty().getName().equalsIgnoreCase(propertyName)) { + if (((UriResourceComplexProperty)part).getComplexTypeFilter() != null) { + return getComplexPropertyPosition(selectedPaths, (UriResourceComplexProperty)part); + } else { + return i; + } + } else if (part instanceof UriResourceNavigation && + ((UriResourceNavigation) part).getProperty().getName().equalsIgnoreCase(propertyName)) { + return getNavigationPropertyPosition(selectedPaths, (UriResourceNavigation)part); + } + i++; + } + } + return -1; + } + + /** + * @param selectedPaths + * @param part + * @return + */ + private static int getNavigationPropertyPosition(Set<List<String>> selectedPaths, UriResourceNavigation part) { + if (part.getTypeFilterOnCollection() != null) { + for (List<String> pathSel : selectedPaths) { + int i = 0; + for (String sel : pathSel) { + if (sel.equalsIgnoreCase(part.getTypeFilterOnCollection(). + getFullQualifiedName().getFullQualifiedNameAsString())) { + return i; + } + i++; + } + } + } else if (part.getTypeFilterOnEntry() != null) { + for (List<String> pathSel : selectedPaths) { + int i = 0; + for (String sel : pathSel) { + if (sel.equalsIgnoreCase(part.getTypeFilterOnEntry(). + getFullQualifiedName().getFullQualifiedNameAsString())) { + return i; + } + i++; + } + } + } + return -1; + } + + /** + * @param selectedPaths + * @param part + */ + private static int getComplexPropertyPosition(Set<List<String>> selectedPaths, UriResourceComplexProperty part) { + for (List<String> pathSel : selectedPaths) { + int i = 0; + for (String sel : pathSel) { + if (sel.equalsIgnoreCase(part.getComplexTypeFilter(). + getFullQualifiedName().getFullQualifiedNameAsString())) { + return i; + } + i++; + } + } + return 0; + } + private static void handleExpand(final EdmStructuredType type, final ExpandOption expand, final StringBuilder result) throws SerializerException { final Set<String> expandedPropertyNames = ExpandSelectHelper.getExpandedPropertyNames(expand.getExpandItems()); @@ -131,6 +314,11 @@ public final class ContextURLHelper { String propertyPath = buildPropertyPath(path); result.append(Encoder.encode(propertyName)); result.append("/").append(propertyPath); + } else { + if (result.length() > 0) { + result.append(','); + } + result.append(Encoder.encode(propertyName) + "()"); } } } @@ -175,9 +363,27 @@ public final class ContextURLHelper { } } } + for (final String complexPropertyName : type.getNavigationPropertyNames()) { + if (ExpandSelectHelper.isSelected(selectedPaths, complexPropertyName)) { + List<List<String>> complexSelectedPaths = getComplexSelectedPaths( + (EdmNavigationProperty) type.getProperty(complexPropertyName)); + for (final List<String> path : complexSelectedPaths) { + path.add(0, edmProperty.getName()); + result.add(path); + } + } + } } return result; } + + private static List<List<String>> getComplexSelectedPaths(EdmNavigationProperty edmProperty) { + List<List<String>> result = new ArrayList<List<String>>(); + List<String> path = new LinkedList<String>(); + path.add(edmProperty.getName()); + result.add(path); + return result; + } /** * Builds a key predicate for the ContextURL. http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/bf4e2017/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 a6e5012..25897e3 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 @@ -25,6 +25,10 @@ import java.util.Set; import org.apache.olingo.server.api.serializer.SerializerException; import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceAction; +import org.apache.olingo.server.api.uri.UriResourceComplexProperty; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourceFunction; import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourceProperty; import org.apache.olingo.server.api.uri.queryoption.ExpandItem; @@ -57,10 +61,87 @@ public abstract class ExpandSelectHelper { final UriResource resource = item.getResourcePath().getUriResourceParts().get(0); if (resource instanceof UriResourceProperty) { selected.add(((UriResourceProperty) resource).getProperty().getName()); + } else if (resource instanceof UriResourceNavigation) { + selected.add(((UriResourceNavigation) resource).getProperty().getName()); + } else if (resource instanceof UriResourceAction) { + selected.add(((UriResourceAction) resource).getAction().getName()); + } else if (resource instanceof UriResourceFunction) { + selected.add(((UriResourceFunction) resource).getFunction().getName()); } } return selected; } + + /** + * This method creates selectedPath list checking if the resource has entity type filter, + * complex type filter, or if resource is navigation property and if it has type filter + * @param selectItems + * @param propertyName + * @return + */ + public static Set<List<String>> getSelectedPathsWithTypeCasts( + final List<SelectItem> selectItems, final String propertyName) { + 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 + && propertyName.equals(((UriResourceProperty) resource).getProperty().getName())) { + List<String> path = new ArrayList<String>(); + if (item.getStartTypeFilter() != null) { + path.add(item.getStartTypeFilter().getFullQualifiedName().getFullQualifiedNameAsString()); + } + if (resource instanceof UriResourceComplexProperty && + ((UriResourceComplexProperty) resource).getComplexTypeFilter() != null) { + path.add(((UriResourceComplexProperty) resource).getComplexTypeFilter(). + getFullQualifiedName().getFullQualifiedNameAsString()); + } else if (resource instanceof UriResourceEntitySet && + ((UriResourceEntitySet) resource).getTypeFilterOnCollection() != null) { + path.add(((UriResourceEntitySet) resource).getTypeFilterOnCollection(). + getFullQualifiedName().getFullQualifiedNameAsString()); + } + extractPathsFromResourceParts(selectedPaths, parts, path); + } else if (resource instanceof UriResourceNavigation + && propertyName.equals(((UriResourceNavigation) resource).getProperty().getName()) ) { + List<String> path = new ArrayList<String>(); + if (item.getStartTypeFilter() != null) { + path.add(item.getStartTypeFilter().getFullQualifiedName().getFullQualifiedNameAsString()); + } + extractPathsFromResourceParts(selectedPaths, parts, path); + } + } + return selectedPaths.isEmpty() ? null : selectedPaths; + } + + /** + * @param selectedPaths + * @param parts + * @param path + */ + private static Set<List<String>> extractPathsFromResourceParts( + Set<List<String>> selectedPaths, final List<UriResource> parts, + List<String> path) { + if (parts.size() > 1) { + for (final UriResource part : parts.subList(1, parts.size())) { + if (part instanceof UriResourceProperty) { + path.add(((UriResourceProperty) part).getProperty().getName()); + } else if (part instanceof UriResourceNavigation) { + path.add(((UriResourceNavigation) part).getProperty().getName()); + } + if (part instanceof UriResourceComplexProperty && + ((UriResourceComplexProperty) part).getComplexTypeFilter() != null) { + path.add(((UriResourceComplexProperty) part).getComplexTypeFilter(). + getFullQualifiedName().getFullQualifiedNameAsString()); + } + } + selectedPaths.add(path); + } else if (!path.isEmpty()) { + selectedPaths.add(path); + } else { + return null; + } + return selectedPaths.isEmpty() ? null : selectedPaths; + } public static Set<List<String>> getSelectedPaths(final List<SelectItem> selectItems, final String propertyName) { Set<List<String>> selectedPaths = new HashSet<List<String>>(); @@ -74,6 +155,8 @@ public abstract class ExpandSelectHelper { for (final UriResource part : parts.subList(1, parts.size())) { if (part instanceof UriResourceProperty) { path.add(((UriResourceProperty) part).getProperty().getName()); + } else if (part instanceof UriResourceNavigation) { + path.add(((UriResourceNavigation) part).getProperty().getName()); } } selectedPaths.add(path); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/bf4e2017/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 3928985..bd28d78 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 @@ -212,4 +212,42 @@ public class ContextURLBuilderTest { assertEquals("$metadata#Entit%C3%A4ten/Namensr%C3%A4umchen.Un%C3%BCblicherName", ContextURLBuilder.create(contextURL).toString()); } + + @Test + public void buildWithComplexDerivedTypeInSelect1() { + EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class); + Mockito.when(entitySet.getName()).thenReturn("ESCompCollDerived"); + ContextURL contextURL = ContextURL.with().serviceRoot(serviceRoot) + .entitySet(entitySet) + .selectList("PropertyCompAno/olingo.odata.test1.CTBaseAno/AdditionalPropString") + .build(); + assertEquals(serviceRoot + "$metadata#ESCompCollDerived(PropertyCompAno/" + + "olingo.odata.test1.CTBaseAno/AdditionalPropString)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildWithComplexDerivedTypeInSelect2() { + EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class); + Mockito.when(entitySet.getName()).thenReturn("ESCompCollComp"); + ContextURL contextURL = ContextURL.with().serviceRoot(serviceRoot) + .entitySet(entitySet) + .selectList("PropertyComp/CollPropertyComp/olingo.odata.test1.CTBase/AdditionalPropString") + .build(); + assertEquals(serviceRoot + "$metadata#ESCompCollComp(PropertyComp/CollPropertyComp/" + + "olingo.odata.test1.CTBase/AdditionalPropString)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildWithNavPropertyInSelect() { + EdmEntitySet entitySet = Mockito.mock(EdmEntitySet.class); + Mockito.when(entitySet.getName()).thenReturn("ESTwoKeyNav"); + ContextURL contextURL = ContextURL.with().serviceRoot(serviceRoot) + .entitySet(entitySet) + .selectList("CollPropertyCompNav/NavPropertyETTwoKeyNavMany") + .build(); + assertEquals(serviceRoot + "$metadata#ESTwoKeyNav(CollPropertyCompNav/NavPropertyETTwoKeyNavMany)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/bf4e2017/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java index 5c9ab16..4cd6a0e 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/ExpandSelectMock.java @@ -22,14 +22,17 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.olingo.commons.api.edm.EdmComplexType; import org.apache.olingo.commons.api.edm.EdmElement; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.EdmStructuredType; +import org.apache.olingo.commons.api.edm.EdmType; import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceComplexProperty; import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourceProperty; import org.apache.olingo.server.api.uri.queryoption.ExpandItem; @@ -62,12 +65,191 @@ public final class ExpandSelectMock { return resource; } + private static UriInfoResource mockResourceOnDerivedComplexTypes(final EdmEntitySet edmEntitySet, + final String name, final EdmType derivedType, final String pathSegmentAfterCast) { + EdmStructuredType type = edmEntitySet.getEntityType(); + List<UriResource> elements = new ArrayList<UriResource>(); + mockComplexPropertyWithTypeFilter(name, derivedType, type, elements); + + mockPropertyOnDerivedType(derivedType, pathSegmentAfterCast, elements); + + UriInfoResource resource = Mockito.mock(UriInfoResource.class); + Mockito.when(resource.getUriResourceParts()).thenReturn(elements); + return resource; + } + + private static UriInfoResource mockResourceOnComplexTypesWithNav(final EdmEntitySet edmEntitySet, + final String name, final String navProperty) { + EdmStructuredType type = edmEntitySet.getEntityType(); + List<UriResource> elements = new ArrayList<UriResource>(); + final EdmElement edmElement = type.getProperty(name); + final EdmProperty property = (EdmProperty) edmElement; + UriResourceComplexProperty element = Mockito.mock(UriResourceComplexProperty.class); + Mockito.when(element.getProperty()).thenReturn(property); + elements.add(element); + + mockNavPropertyOnEdmType(navProperty, elements, property); + + UriInfoResource resource = Mockito.mock(UriInfoResource.class); + Mockito.when(resource.getUriResourceParts()).thenReturn(elements); + return resource; + } + + /** + * @param navProperty + * @param elements + * @param property + */ + private static void mockNavPropertyOnEdmType(final String navProperty, List<UriResource> elements, + final EdmProperty property) { + final EdmElement edmElement1 = ((EdmStructuredType) property.getType()).getProperty(navProperty); + UriResourceNavigation element1 = Mockito.mock(UriResourceNavigation.class); + Mockito.when(element1.getProperty()).thenReturn((EdmNavigationProperty) edmElement1); + elements.add(element1); + } + + private static UriInfoResource mockResourceOnDerivedEntityTypes( + final String name, final EdmType derivedType) { + EdmStructuredType type = (EdmStructuredType) derivedType; + List<UriResource> elements = new ArrayList<UriResource>(); + final EdmElement edmElement = type.getProperty(name); + if (edmElement.getType().getKind() == EdmTypeKind.ENTITY) { + UriResourceNavigation element = Mockito.mock(UriResourceNavigation.class); + Mockito.when(element.getProperty()).thenReturn((EdmNavigationProperty) edmElement); + elements.add(element); + } else { + final EdmProperty property = (EdmProperty) edmElement; + UriResourceProperty element = Mockito.mock(UriResourceProperty.class); + Mockito.when(element.getProperty()).thenReturn(property); + elements.add(element); + } + UriInfoResource resource = Mockito.mock(UriInfoResource.class); + Mockito.when(resource.getUriResourceParts()).thenReturn(elements); + return resource; + } + + private static UriInfoResource mockResourceOnDerivedEntityAndComplexTypes( + final String name, final EdmType derivedEntityType, final EdmType derivedComplexType, + final String pathSegment) { + EdmStructuredType type = (EdmStructuredType) derivedEntityType; + List<UriResource> elements = new ArrayList<UriResource>(); + mockComplexPropertyWithTypeFilter(name, derivedComplexType, type, elements); + + final EdmElement edmElement1 = ((EdmStructuredType) derivedComplexType).getProperty(pathSegment); + UriResourceNavigation element1 = Mockito.mock(UriResourceNavigation.class); + Mockito.when(element1.getProperty()).thenReturn((EdmNavigationProperty) edmElement1); + elements.add(element1); + + UriInfoResource resource = Mockito.mock(UriInfoResource.class); + Mockito.when(resource.getUriResourceParts()).thenReturn(elements); + return resource; + } + + /** + * @param name + * @param derivedComplexType + * @param type + * @param elements + */ + private static void mockComplexPropertyWithTypeFilter(final String name, final EdmType derivedComplexType, + EdmStructuredType type, List<UriResource> elements) { + final EdmElement edmElement = type.getProperty(name); + final EdmProperty property = (EdmProperty) edmElement; + UriResourceComplexProperty element = Mockito.mock(UriResourceComplexProperty.class); + Mockito.when(element.getProperty()).thenReturn(property); + Mockito.when(element.getComplexTypeFilter()).thenReturn((EdmComplexType) derivedComplexType); + elements.add(element); + } + + private static UriInfoResource mockResourceMultiLevelOnDerivedComplexTypes(final EdmEntitySet edmEntitySet, + final String pathSegmentBeforeCast, + final String name, final EdmType derivedType, final String pathSegmentAfterCast) { + EdmStructuredType type = edmEntitySet.getEntityType(); + List<UriResource> elements = new ArrayList<UriResource>(); + final EdmElement edmElement = type.getProperty(name); + final EdmProperty property = (EdmProperty) edmElement; + UriResourceComplexProperty element = Mockito.mock(UriResourceComplexProperty.class); + Mockito.when(element.getProperty()).thenReturn(property); + elements.add(element); + + if (pathSegmentBeforeCast != null) { + mockComplexPropertyWithTypeFilter(pathSegmentBeforeCast, (EdmComplexType) derivedType, + (EdmStructuredType) edmElement.getType(), elements); + } + + mockPropertyOnDerivedType(derivedType, pathSegmentAfterCast, elements); + + UriInfoResource resource = Mockito.mock(UriInfoResource.class); + Mockito.when(resource.getUriResourceParts()).thenReturn(elements); + return resource; + } + + /** + * @param derivedType + * @param pathSegment + * @param elements + */ + private static void mockPropertyOnDerivedType(final EdmType derivedType, final String pathSegment, + List<UriResource> elements) { + if (pathSegment != null) { + final EdmElement edmElement1 = ((EdmStructuredType) derivedType).getProperty(pathSegment); + final EdmProperty property1 = (EdmProperty) edmElement1; + UriResourceProperty element1 = Mockito.mock(UriResourceProperty.class); + Mockito.when(element1.getProperty()).thenReturn(property1); + elements.add(element1); + } + } + 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; } + + public static SelectItem mockSelectItemOnDerivedComplexTypes(final EdmEntitySet edmEntitySet, final String name, + final EdmType type, final String pathSegmentAfterCast) { + final UriInfoResource resource = mockResourceOnDerivedComplexTypes(edmEntitySet, + name, type, pathSegmentAfterCast); + SelectItem selectItem = Mockito.mock(SelectItem.class); + Mockito.when(selectItem.getResourcePath()).thenReturn(resource); + return selectItem; + } + + public static SelectItem mockSelectItemOnDerivedEntityTypes(final String name, final EdmType type) { + final UriInfoResource resource = mockResourceOnDerivedEntityTypes(name, type); + SelectItem selectItem = Mockito.mock(SelectItem.class); + Mockito.when(selectItem.getResourcePath()).thenReturn(resource); + return selectItem; + } + + public static SelectItem mockSelectItemOnDerivedEntityAndComplexTypes( + final String name, final EdmType entityType, final EdmType complexType, final String pathSegment) { + final UriInfoResource resource = mockResourceOnDerivedEntityAndComplexTypes( + name, entityType, complexType, pathSegment); + SelectItem selectItem = Mockito.mock(SelectItem.class); + Mockito.when(selectItem.getResourcePath()).thenReturn(resource); + return selectItem; + } + + public static SelectItem mockSelectItemMultiLevelOnDerivedComplexTypes( + final EdmEntitySet edmEntitySet, final String name, + final String pathSegmentBeforeCast, final EdmType type, final String pathSegmentAfterCast) { + final UriInfoResource resource = mockResourceMultiLevelOnDerivedComplexTypes( + edmEntitySet, pathSegmentBeforeCast, name, type, pathSegmentAfterCast); + SelectItem selectItem = Mockito.mock(SelectItem.class); + Mockito.when(selectItem.getResourcePath()).thenReturn(resource); + return selectItem; + } + + public static SelectItem mockSelectItemOnComplexTypesWithNav ( + final EdmEntitySet edmEntitySet, final String name, final String navProperty) { + final UriInfoResource resource = mockResourceOnComplexTypesWithNav( + edmEntitySet, name, navProperty); + SelectItem selectItem = Mockito.mock(SelectItem.class); + Mockito.when(selectItem.getResourcePath()).thenReturn(resource); + return selectItem; + } public static SelectOption mockSelectOption(final List<SelectItem> selectItems) { SelectOption select = Mockito.mock(SelectOption.class); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/bf4e2017/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 index ec94fb0..9bb05ec 100644 --- 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 @@ -25,11 +25,15 @@ import java.util.Collections; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmComplexType; import org.apache.olingo.commons.api.edm.EdmEntityContainer; import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; 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.server.api.OData; +import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.UriParameter; import org.apache.olingo.server.api.uri.queryoption.ExpandItem; import org.apache.olingo.server.api.uri.queryoption.ExpandOption; @@ -181,7 +185,8 @@ public class ContextURLHelperTest { ExpandSelectMock.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()); + assertEquals("$metadata#ESTwoPrim(NavPropertyETAllPrimOne())", + ContextURLBuilder.create(contextURL).toASCIIString()); } @Test @@ -215,7 +220,8 @@ public class ContextURLHelperTest { final SelectOption select = ExpandSelectMock.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))", + assertEquals("$metadata#ESTwoPrim(PropertyString,NavPropertyETAllPrimOne()," + + "NavPropertyETAllPrimMany(PropertyInt32))", ContextURLBuilder.create(contextURL).toASCIIString()); } @@ -230,7 +236,8 @@ public class ContextURLHelperTest { final ExpandOption expand = ExpandSelectMock.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()); + assertEquals("$metadata#ESTwoPrim(NavPropertyETAllPrimOne(NavPropertyETTwoPrimOne()))", + ContextURLBuilder.create(contextURL).toASCIIString()); } @Test @@ -244,7 +251,8 @@ public class ContextURLHelperTest { final ExpandOption expand = ExpandSelectMock.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()); + assertEquals("$metadata#ESTwoPrim(NavPropertyETAllPrimOne())", + ContextURLBuilder.create(contextURL).toASCIIString()); } @Test @@ -320,4 +328,132 @@ public class ContextURLHelperTest { + "(PropertyInt16=1,KeyAlias1=11,KeyAlias2='Num11',KeyAlias3='Num111')/PropertyComp", ContextURLBuilder.create(contextURL).toASCIIString()); } + + @Test + public void buildComplexDerivedTypeInSelect() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESCompCollDerived"); + final EdmComplexType derivedComplexType = edm.getComplexType( + new FullQualifiedName("olingo.odata.test1.CTBaseAno")); + final SelectItem selectItem = ExpandSelectMock.mockSelectItemOnDerivedComplexTypes(entitySet, + "PropertyCompAno", derivedComplexType, "AdditionalPropString"); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESCompCollDerived(PropertyCompAno/olingo.odata.test1.CTBaseAno/AdditionalPropString)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildMultiLevelComplexDerivedTypeInSelect() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESCompCollComp"); + final EdmComplexType derivedComplexType = edm.getComplexType( + new FullQualifiedName("olingo.odata.test1.CTBase")); + final SelectItem selectItem = ExpandSelectMock.mockSelectItemMultiLevelOnDerivedComplexTypes( + entitySet, "PropertyComp", "CollPropertyComp", derivedComplexType, "AdditionalPropString"); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESCompCollComp(PropertyComp/CollPropertyComp/" + + "olingo.odata.test1.CTBase/AdditionalPropString)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildEntityTypeCastInSelect1() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoKeyNav"); + final EdmEntityType derivedEntityType = edm.getEntityType( + new FullQualifiedName("olingo.odata.test1.ETBaseTwoKeyNav")); + final SelectItem selectItem = ExpandSelectMock.mockSelectItemOnDerivedEntityTypes( + "NavPropertyETBaseTwoKeyNavOne", derivedEntityType); + Mockito.when(selectItem.getStartTypeFilter()).thenReturn(derivedEntityType); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESTwoKeyNav(olingo.odata.test1.ETBaseTwoKeyNav/NavPropertyETBaseTwoKeyNavOne)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildEntityTypeCastInSelect2() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoKeyNav"); + final EdmEntityType derivedEntityType = edm.getEntityType( + new FullQualifiedName("olingo.odata.test1.ETBaseTwoKeyNav")); + final SelectItem selectItem = ExpandSelectMock.mockSelectItemOnDerivedEntityTypes( + "PropertyDate", derivedEntityType); + Mockito.when(selectItem.getStartTypeFilter()).thenReturn(derivedEntityType); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESTwoKeyNav(olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildMultipleSelectWithEntityTypeCastInSelect() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoKeyNav"); + final EdmEntityType derivedEntityType = edm.getEntityType( + new FullQualifiedName("olingo.odata.test1.ETBaseTwoKeyNav")); + final SelectItem selectItem1 = ExpandSelectMock.mockSelectItem(entitySet, "CollPropertyComp"); + final SelectItem selectItem2 = ExpandSelectMock.mockSelectItemOnDerivedEntityTypes( + "NavPropertyETTwoBaseTwoKeyNavOne", derivedEntityType); + Mockito.when(selectItem2.getStartTypeFilter()).thenReturn(derivedEntityType); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem1, selectItem2)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESTwoKeyNav(CollPropertyComp,olingo.odata.test1.ETBaseTwoKeyNav/" + + "NavPropertyETTwoBaseTwoKeyNavOne)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildEntityTypeCastAndComplexTypeCastInSelect() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoKeyNav"); + final EdmEntityType derivedEntityType = edm.getEntityType( + new FullQualifiedName("olingo.odata.test1.ETBaseTwoKeyNav")); + final EdmComplexType derivedComplexType = edm.getComplexType( + new FullQualifiedName("olingo.odata.test1.CTBasePrimCompNav")); + final SelectItem selectItem = ExpandSelectMock.mockSelectItemOnDerivedEntityAndComplexTypes( + "CollPropertyComp", derivedEntityType, derivedComplexType, "NavPropertyETTwoKeyNavOne"); + Mockito.when(selectItem.getStartTypeFilter()).thenReturn(derivedEntityType); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESTwoKeyNav(olingo.odata.test1.ETBaseTwoKeyNav/CollPropertyComp/" + + "olingo.odata.test1.CTBasePrimCompNav/NavPropertyETTwoKeyNavOne)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildExpandWithSelectHavingDerivedEntityType() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESKeyNavCont"); + final EdmEntityType derivedEntityType = edm.getEntityType( + new FullQualifiedName("olingo.odata.test1.ETBaseTwoKeyNav")); + final EdmProperty edmProperty = derivedEntityType.getStructuralProperty("PropertyDate"); + ExpandItem expandItem = ExpandSelectMock.mockExpandItem(entitySet, "NavPropertyETTwoKeyNavContOne"); + SelectItem selectItem = Mockito.mock(SelectItem.class); + Mockito.when(selectItem.getStartTypeFilter()).thenReturn(derivedEntityType); + final UriInfoResource resource = ExpandSelectMock.mockComplexTypeResource(edmProperty); + Mockito.when(selectItem.getResourcePath()).thenReturn(resource); + final SelectOption selectOption = ExpandSelectMock.mockSelectOption(Arrays.asList(selectItem)); + Mockito.when(expandItem.getSelectOption()).thenReturn(selectOption); + final ExpandOption expand = ExpandSelectMock.mockExpandOption(Arrays.asList(expandItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), expand, null)).build(); + assertEquals("$metadata#ESKeyNavCont(NavPropertyETTwoKeyNavContOne(" + + "olingo.odata.test1.ETBaseTwoKeyNav/PropertyDate))", + ContextURLBuilder.create(contextURL).toASCIIString()); + } + + @Test + public void buildSelectWithComplexPropertyWithNav() throws Exception { + final EdmEntitySet entitySet = entityContainer.getEntitySet("ESTwoKeyNav"); + final SelectItem selectItem = ExpandSelectMock.mockSelectItemOnComplexTypesWithNav( + entitySet, "CollPropertyCompNav", "NavPropertyETTwoKeyNavMany"); + final SelectOption select = ExpandSelectMock.mockSelectOption(Arrays.asList( + selectItem)); + final ContextURL contextURL = ContextURL.with().entitySet(entitySet) + .selectList(ContextURLHelper.buildSelectList(entitySet.getEntityType(), null, select)).build(); + assertEquals("$metadata#ESTwoKeyNav(CollPropertyCompNav/NavPropertyETTwoKeyNavMany)", + ContextURLBuilder.create(contextURL).toASCIIString()); + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/bf4e2017/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java index 8e19835..c23569b 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriHelperTest.java @@ -18,8 +18,6 @@ */ package org.apache.olingo.server.core.uri; -import static org.junit.Assert.assertEquals; - import java.util.Collections; import java.util.List;