[OLINGO-545] TecSvc: Support of cyclic expands and filtering on arbitrary
level
This commit is contained in:
parent
583c4bd078
commit
518a3a418e
|
@ -19,6 +19,7 @@
|
|||
package org.apache.olingo.fit.tecsvc.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.net.URI;
|
||||
|
@ -291,6 +292,161 @@ public class ExpandWithSystemQueryOptionsITCase extends AbstractBaseTestITCase {
|
|||
assertEquals(4, entities.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCyclicExpand() {
|
||||
// Expand entity in the following order
|
||||
// 1 => 2 => 1
|
||||
// Entity with Key (PropertyInt16=1, PrroperyString='1') holds references to (PropertyInt16=1, PropertyString='1')
|
||||
// and (PropertyInt16=1, PropertyString='2')
|
||||
// Entity with Key (PropertyInt16=1, PropertyString='2') holds references to (PropertyInt16=1, PropertyString='1')
|
||||
// Define filters to select explicit the entities at any level => Circle
|
||||
|
||||
final ODataClient client = getClient();
|
||||
final Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
|
||||
options.put(QueryOption.EXPAND, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
|
||||
+ "($expand=" + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
|
||||
+ "($expand=" + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY + "))");
|
||||
options.put(QueryOption.FILTER, "PropertyString eq '2'");
|
||||
|
||||
final Map<String, Object> keys = new HashMap<String, Object>();
|
||||
keys.put(PROPERTY_INT16, 1);
|
||||
keys.put(PROPERTY_STRING, "1");
|
||||
|
||||
final URI uri = client.newURIBuilder(SERVICE_URI)
|
||||
.appendEntitySetSegment(ES_TWO_KEY_NAV)
|
||||
.appendKeySegment(keys)
|
||||
.expandWithOptions(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, options)
|
||||
.build();
|
||||
|
||||
final ODataRetrieveResponse<ODataEntity> response = client.getRetrieveRequestFactory()
|
||||
.getEntityRequest(uri)
|
||||
.execute();
|
||||
|
||||
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
|
||||
assertNotNull(response.getBody().getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY));
|
||||
assertEquals(1, response.getBody().getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.size());
|
||||
|
||||
final ODataEntity entitySecondLevel = response.getBody().getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.get(0);
|
||||
|
||||
assertEquals(1, entitySecondLevel.getProperty(PROPERTY_INT16).getPrimitiveValue().toValue());
|
||||
assertEquals("2", entitySecondLevel.getProperty(PROPERTY_STRING).getPrimitiveValue().toValue());
|
||||
|
||||
assertNotNull(entitySecondLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY));
|
||||
assertEquals(1, entitySecondLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.size());
|
||||
|
||||
final ODataEntity entityThirdLevel = entitySecondLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.get(0);
|
||||
|
||||
assertEquals(1, entityThirdLevel.getProperty(PROPERTY_INT16).getPrimitiveValue().toValue());
|
||||
assertEquals("1", entityThirdLevel.getProperty(PROPERTY_STRING).getPrimitiveValue().toValue());
|
||||
|
||||
assertNotNull(entityThirdLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY));
|
||||
assertEquals(2, entityThirdLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.size());
|
||||
|
||||
final List<ODataEntity> fourthLevelEntites = entityThirdLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities();
|
||||
|
||||
assertEquals(1, fourthLevelEntites.get(0).getProperty(PROPERTY_INT16).getPrimitiveValue().toValue());
|
||||
assertEquals("1", fourthLevelEntites.get(0).getProperty(PROPERTY_STRING).getPrimitiveValue().toValue());
|
||||
|
||||
assertEquals(1, fourthLevelEntites.get(1).getProperty(PROPERTY_INT16).getPrimitiveValue().toValue());
|
||||
assertEquals("2", fourthLevelEntites.get(1).getProperty(PROPERTY_STRING).getPrimitiveValue().toValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSystemQueryOptionOnThirdLevel() {
|
||||
final ODataClient client = getClient();
|
||||
final Map<QueryOption, Object> options = new HashMap<QueryOption, Object>();
|
||||
options.put(QueryOption.EXPAND, NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
|
||||
+ "($expand=" + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
|
||||
+ "($expand=" + NAV_PROPERTY_ET_TWO_KEY_NAV_MANY
|
||||
+ ";$filter=PropertyString eq '1'))");
|
||||
options.put(QueryOption.FILTER, "PropertyString eq '2'");
|
||||
|
||||
final Map<String, Object> keys = new HashMap<String, Object>();
|
||||
keys.put(PROPERTY_INT16, 1);
|
||||
keys.put(PROPERTY_STRING, "1");
|
||||
|
||||
final URI uri = client.newURIBuilder(SERVICE_URI)
|
||||
.appendEntitySetSegment(ES_TWO_KEY_NAV)
|
||||
.appendKeySegment(keys)
|
||||
.expandWithOptions(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY, options)
|
||||
.build();
|
||||
|
||||
final ODataRetrieveResponse<ODataEntity> response = client.getRetrieveRequestFactory()
|
||||
.getEntityRequest(uri)
|
||||
.execute();
|
||||
|
||||
assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
|
||||
assertNotNull(response.getBody().getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY));
|
||||
assertEquals(1, response.getBody().getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.size());
|
||||
|
||||
final ODataEntity entitySecondLevel = response.getBody().getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.get(0);
|
||||
|
||||
assertEquals(1, entitySecondLevel.getProperty(PROPERTY_INT16).getPrimitiveValue().toValue());
|
||||
assertEquals("2", entitySecondLevel.getProperty(PROPERTY_STRING).getPrimitiveValue().toValue());
|
||||
|
||||
assertNotNull(entitySecondLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY));
|
||||
assertEquals(1, entitySecondLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.size());
|
||||
|
||||
final ODataEntity entityThirdLevel = entitySecondLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.get(0);
|
||||
|
||||
assertEquals(1, entityThirdLevel.getProperty(PROPERTY_INT16).getPrimitiveValue().toValue());
|
||||
assertEquals("1", entityThirdLevel.getProperty(PROPERTY_STRING).getPrimitiveValue().toValue());
|
||||
|
||||
assertNotNull(entityThirdLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY));
|
||||
assertEquals(1, entityThirdLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities()
|
||||
.size());
|
||||
|
||||
final List<ODataEntity> fourthLevelEntites = entityThirdLevel.getNavigationLink(NAV_PROPERTY_ET_TWO_KEY_NAV_MANY)
|
||||
.asInlineEntitySet()
|
||||
.getEntitySet()
|
||||
.getEntities();
|
||||
|
||||
assertEquals(1, fourthLevelEntites.get(0).getProperty(PROPERTY_INT16).getPrimitiveValue().toValue());
|
||||
assertEquals("1", fourthLevelEntites.get(0).getProperty(PROPERTY_STRING).getPrimitiveValue().toValue());
|
||||
}
|
||||
|
||||
private ODataRetrieveResponse<ODataEntitySet> buildRequest(final String entitySet, final String navigationProperty,
|
||||
final Map<QueryOption, Object> expandOptions) {
|
||||
return buildRequest(entitySet, navigationProperty, expandOptions, null);
|
||||
|
|
|
@ -125,7 +125,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
|||
// Create a shallow copy of each entity. So the expanded navigation properties can be modified for serialization,
|
||||
// without affecting the data stored in the database.
|
||||
final ExpandSystemQueryOptionHandler expandHandler = new ExpandSystemQueryOptionHandler();
|
||||
final EntitySet entitySetSerialization = expandHandler.copyEntitySetShallowRekursive(entitySet);
|
||||
final EntitySet entitySetSerialization = expandHandler.transformEntitySetGraphToTree(entitySet,
|
||||
edmEntitySet,
|
||||
expand);
|
||||
expandHandler.applyExpandQueryOptions(entitySetSerialization, edmEntitySet, expand);
|
||||
|
||||
// Serialize
|
||||
|
@ -186,7 +188,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
|||
final SelectOption select = uriInfo.getSelectOption();
|
||||
|
||||
final ExpandSystemQueryOptionHandler expandHandler = new ExpandSystemQueryOptionHandler();
|
||||
final Entity entitySerialization = expandHandler.copyEntityShallowRekursive(entity);
|
||||
final Entity entitySerialization = expandHandler.transformEntityGraphToTree(entity, edmEntitySet, expand);
|
||||
expandHandler.applyExpandQueryOptions(entitySerialization, edmEntitySet, expand);
|
||||
|
||||
response.setContent(serializer.entity(
|
||||
|
|
|
@ -18,15 +18,18 @@
|
|||
*/
|
||||
package org.apache.olingo.server.tecsvc.processor.queryoptions;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.olingo.commons.api.data.Entity;
|
||||
import org.apache.olingo.commons.api.data.EntitySet;
|
||||
import org.apache.olingo.commons.api.data.Link;
|
||||
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||
import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
|
||||
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||
import org.apache.olingo.commons.core.data.EntityImpl;
|
||||
import org.apache.olingo.commons.core.data.EntitySetImpl;
|
||||
|
@ -47,8 +50,6 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.options.SkipHandle
|
|||
import org.apache.olingo.server.tecsvc.processor.queryoptions.options.TopHandler;
|
||||
|
||||
public class ExpandSystemQueryOptionHandler {
|
||||
private IdentityHashMap<Entity, Entity> copiedEntities = new IdentityHashMap<Entity, Entity>();
|
||||
private IdentityHashMap<EntitySet, EntitySet> copiedEntitySets = new IdentityHashMap<EntitySet, EntitySet>();
|
||||
|
||||
public void applyExpandQueryOptions(final EntitySet entitySet, final EdmEntitySet edmEntitySet,
|
||||
final ExpandOption expandOption) throws ODataApplicationException {
|
||||
|
@ -70,20 +71,26 @@ public class ExpandSystemQueryOptionHandler {
|
|||
applyExpandOptionToEntity(entity, edmEntitySet, expandOption);
|
||||
}
|
||||
|
||||
private void applyExpandOptionToEntity(final Entity entity, final EdmEntitySet edmEntitySet,
|
||||
private void applyExpandOptionToEntity(final Entity entity, final EdmBindingTarget edmBindingTarget,
|
||||
final ExpandOption expandOption) throws ODataApplicationException {
|
||||
final EdmEntityType entityType = edmEntitySet.getEntityType();
|
||||
final EdmEntityType entityType = edmBindingTarget.getEntityType();
|
||||
|
||||
for (ExpandItem item : expandOption.getExpandItems()) {
|
||||
final List<UriResource> uriResourceParts = item.getResourcePath().getUriResourceParts();
|
||||
if (uriResourceParts.size() == 1 && uriResourceParts.get(0) instanceof UriResourceNavigation) {
|
||||
final String navPropertyName = ((UriResourceNavigation) uriResourceParts.get(0)).getProperty().getName();
|
||||
final EdmEntitySet targetEdmEntitySet = (EdmEntitySet) edmEntitySet.getRelatedBindingTarget(navPropertyName);
|
||||
final EdmBindingTarget targetEdmEntitySet = edmBindingTarget.getRelatedBindingTarget(navPropertyName);
|
||||
|
||||
final Link link = entity.getNavigationLink(navPropertyName);
|
||||
if (link != null && entityType.getNavigationProperty(navPropertyName).isCollection()) {
|
||||
applyOptionsToEntityCollection(link.getInlineEntitySet(), targetEdmEntitySet, item.getFilterOption(),
|
||||
item.getOrderByOption(), item.getCountOption(), item.getSkipOption(), item.getTopOption());
|
||||
applyOptionsToEntityCollection(link.getInlineEntitySet(),
|
||||
targetEdmEntitySet,
|
||||
item.getFilterOption(),
|
||||
item.getOrderByOption(),
|
||||
item.getCountOption(),
|
||||
item.getSkipOption(),
|
||||
item.getTopOption(),
|
||||
item.getExpandOption());
|
||||
}
|
||||
} else {
|
||||
throw new ODataApplicationException("Not supported resource part in expand system query option",
|
||||
|
@ -92,77 +99,150 @@ public class ExpandSystemQueryOptionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private void applyOptionsToEntityCollection(final EntitySet entitySet, final EdmEntitySet edmEntitySet,
|
||||
private void applyOptionsToEntityCollection(final EntitySet entitySet, final EdmBindingTarget edmBindingTarget,
|
||||
final FilterOption filterOption, final OrderByOption orderByOption, final CountOption countOption,
|
||||
final SkipOption skipOption, final TopOption topOption) throws ODataApplicationException {
|
||||
final SkipOption skipOption, final TopOption topOption, final ExpandOption expandOption)
|
||||
throws ODataApplicationException {
|
||||
|
||||
FilterHandler.applyFilterSystemQuery(filterOption, entitySet, edmEntitySet);
|
||||
OrderByHandler.applyOrderByOption(orderByOption, entitySet, edmEntitySet);
|
||||
FilterHandler.applyFilterSystemQuery(filterOption, entitySet, edmBindingTarget);
|
||||
OrderByHandler.applyOrderByOption(orderByOption, entitySet, edmBindingTarget);
|
||||
// TODO Add CountHandler
|
||||
SkipHandler.applySkipSystemQueryHandler(skipOption, entitySet);
|
||||
TopHandler.applyTopSystemQueryOption(topOption, entitySet);
|
||||
|
||||
// Apply nested expand system query options to remaining entities
|
||||
if(expandOption != null) {
|
||||
for(final Entity entity : entitySet.getEntities()) {
|
||||
applyExpandOptionToEntity(entity, edmBindingTarget, expandOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EntitySet copyEntitySetShallowRekursive(final EntitySet entitySet) {
|
||||
if (!copiedEntitySets.containsKey(entitySet)) {
|
||||
final EntitySet copiedEntitySet = new EntitySetImpl();
|
||||
copiedEntitySet.setCount(entitySet.getCount());
|
||||
copiedEntitySet.setDeltaLink(entitySet.getDeltaLink());
|
||||
copiedEntitySet.setNext(entitySet.getNext());
|
||||
public EntitySet transformEntitySetGraphToTree(final EntitySet entitySet, final EdmBindingTarget edmBindingTarget,
|
||||
final ExpandOption expand) throws ODataApplicationException {
|
||||
|
||||
copiedEntitySets.put(entitySet, copiedEntitySet);
|
||||
copiedEntitySets.put(copiedEntitySet, copiedEntitySet);
|
||||
final EntitySet newEntitySet = newEntitySet(entitySet);
|
||||
|
||||
for (Entity entity : entitySet.getEntities()) {
|
||||
copiedEntitySet.getEntities().add(copyEntityShallowRekursive(entity));
|
||||
}
|
||||
return copiedEntitySet;
|
||||
}
|
||||
return copiedEntitySets.get(entitySet);
|
||||
for(final Entity entity : entitySet.getEntities()) {
|
||||
newEntitySet.getEntities().add(transformEntityGraphToTree(entity, edmBindingTarget, expand));
|
||||
}
|
||||
|
||||
public Entity copyEntityShallowRekursive(final Entity entity) {
|
||||
if (!copiedEntities.containsKey(entity)) {
|
||||
final Entity copiedEntity = new EntityImpl();
|
||||
copiedEntity.getProperties().addAll(entity.getProperties());
|
||||
copiedEntity.getAnnotations().addAll(entity.getAnnotations());
|
||||
copiedEntity.getAssociationLinks().addAll(entity.getAssociationLinks());
|
||||
copiedEntity.setEditLink(entity.getEditLink());
|
||||
copiedEntity.setId(entity.getId());
|
||||
copiedEntity.setMediaContentSource(entity.getMediaContentSource());
|
||||
copiedEntity.setMediaContentType(entity.getMediaContentType());
|
||||
copiedEntity.setMediaETag(entity.getMediaETag());
|
||||
copiedEntity.getOperations().addAll(entity.getOperations());
|
||||
copiedEntity.setSelfLink(entity.getSelfLink());
|
||||
copiedEntity.setType(entity.getType());
|
||||
copiedEntity.getNavigationBindings().addAll(entity.getNavigationBindings());
|
||||
return newEntitySet;
|
||||
}
|
||||
|
||||
copiedEntities.put(entity, copiedEntity);
|
||||
copiedEntities.put(copiedEntity, copiedEntity);
|
||||
public Entity transformEntityGraphToTree(final Entity entity, EdmBindingTarget edmEntitySet,
|
||||
final ExpandOption expand) throws ODataApplicationException {
|
||||
|
||||
// The system query options change the amount and sequence of inline entities (feeds)
|
||||
// So we have to make a shallow copy of all navigation link lists
|
||||
// Make sure, that each entity is only copied once.
|
||||
// Otherwise an infinite loop can occur caused by cyclic navigation relationships.
|
||||
final Entity newEntity = newEntity(entity);
|
||||
|
||||
if (hasExpandItems(expand)) {
|
||||
final boolean expandAll = expandAll(expand);
|
||||
final Set<String> expanded = expandAll ? null : getExpandedPropertyNames(expand.getExpandItems());
|
||||
final EdmEntityType edmType = edmEntitySet.getEntityType();
|
||||
|
||||
for (final Link link : entity.getNavigationLinks()) {
|
||||
final String propertyName = link.getTitle();
|
||||
|
||||
if (expandAll || expanded.contains(propertyName)) {
|
||||
final EdmNavigationProperty edmNavigationProperty = edmType.getNavigationProperty(propertyName);
|
||||
final EdmBindingTarget edmBindingTarget = edmEntitySet.getRelatedBindingTarget(propertyName);
|
||||
final Link newLink = newLink(link);
|
||||
newEntity.getNavigationLinks().add(newLink);
|
||||
final ExpandOption innerExpandOption = getInnerExpandOption(expand, propertyName);
|
||||
|
||||
if(edmNavigationProperty.isCollection()) {
|
||||
newLink.setInlineEntitySet(transformEntitySetGraphToTree(link.getInlineEntitySet(),
|
||||
edmBindingTarget,
|
||||
innerExpandOption));
|
||||
} else {
|
||||
newLink.setInlineEntity(transformEntityGraphToTree(link.getInlineEntity(),
|
||||
edmBindingTarget,
|
||||
innerExpandOption));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
public EntitySet newEntitySet(final EntitySet entitySet) {
|
||||
final EntitySet newEntitySet = new EntitySetImpl();
|
||||
newEntitySet.setCount(entitySet.getCount());
|
||||
newEntitySet.setDeltaLink(entitySet.getDeltaLink());
|
||||
newEntitySet.setNext(entitySet.getNext());
|
||||
|
||||
return newEntitySet;
|
||||
}
|
||||
|
||||
private Entity newEntity(final Entity entity) {
|
||||
final Entity newEntity = new EntityImpl();
|
||||
|
||||
newEntity.getProperties().addAll(entity.getProperties());
|
||||
newEntity.getAnnotations().addAll(entity.getAnnotations());
|
||||
newEntity.getAssociationLinks().addAll(entity.getAssociationLinks());
|
||||
newEntity.setEditLink(entity.getEditLink());
|
||||
newEntity.setId(entity.getId());
|
||||
newEntity.setMediaContentSource(entity.getMediaContentSource());
|
||||
newEntity.setMediaContentType(entity.getMediaContentType());
|
||||
newEntity.setMediaETag(entity.getMediaETag());
|
||||
newEntity.getOperations().addAll(entity.getOperations());
|
||||
newEntity.setSelfLink(entity.getSelfLink());
|
||||
newEntity.setType(entity.getType());
|
||||
newEntity.getNavigationBindings().addAll(entity.getNavigationBindings());
|
||||
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
private Link newLink(Link link) {
|
||||
final Link newLink = new LinkImpl();
|
||||
newLink.setMediaETag(link.getMediaETag());
|
||||
newLink.setTitle(link.getTitle());
|
||||
newLink.setType(link.getType());
|
||||
newLink.setRel(link.getRel());
|
||||
|
||||
final EntitySet inlineEntitySet = link.getInlineEntitySet();
|
||||
if (inlineEntitySet != null) {
|
||||
newLink.setInlineEntitySet(copyEntitySetShallowRekursive(inlineEntitySet));
|
||||
} else if (link.getInlineEntity() != null) {
|
||||
newLink.setInlineEntity(copyEntityShallowRekursive(link.getInlineEntity()));
|
||||
}
|
||||
copiedEntity.getNavigationLinks().add(newLink);
|
||||
return newLink;
|
||||
}
|
||||
|
||||
return copiedEntity;
|
||||
private boolean hasExpandItems(ExpandOption expand) {
|
||||
return expand != null && expand.getExpandItems() != null && !expand.getExpandItems().isEmpty();
|
||||
}
|
||||
return copiedEntities.get(entity);
|
||||
|
||||
private boolean expandAll(ExpandOption expand) {
|
||||
for (final ExpandItem item : expand.getExpandItems()) {
|
||||
if (item.isStar()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Set<String> getExpandedPropertyNames(List<ExpandItem> expandItems) throws ODataApplicationException {
|
||||
Set<String> expanded = new HashSet<String>();
|
||||
for (final ExpandItem item : expandItems) {
|
||||
final List<UriResource> resourceParts = item.getResourcePath().getUriResourceParts();
|
||||
if (resourceParts.size() == 1) {
|
||||
final UriResource resource = resourceParts.get(0);
|
||||
if (resource instanceof UriResourceNavigation) {
|
||||
expanded.add(((UriResourceNavigation) resource).getProperty().getName());
|
||||
}
|
||||
} else {
|
||||
throw new ODataApplicationException("Expand is not supported within complex properties.",
|
||||
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
|
||||
}
|
||||
}
|
||||
return expanded;
|
||||
}
|
||||
|
||||
private ExpandOption getInnerExpandOption(final ExpandOption expand, final String propertyName) {
|
||||
for(final ExpandItem item : expand.getExpandItems()) {
|
||||
final UriResource resource = item.getResourcePath().getUriResourceParts().get(0);
|
||||
if(resource instanceof UriResourceNavigation
|
||||
&& propertyName.equals(((UriResourceNavigation) resource).getProperty().getName())) {
|
||||
return item.getExpandOption();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.util.Locale;
|
|||
|
||||
import org.apache.olingo.commons.api.data.Entity;
|
||||
import org.apache.olingo.commons.api.data.Property;
|
||||
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
|
||||
import org.apache.olingo.commons.api.edm.EdmComplexType;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmEnumType;
|
||||
import org.apache.olingo.commons.api.edm.EdmProperty;
|
||||
import org.apache.olingo.commons.api.edm.EdmType;
|
||||
|
@ -49,11 +49,11 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operati
|
|||
public class ExpressionVisitorImpl implements ExpressionVisitor<VisitorOperand> {
|
||||
|
||||
final private Entity entity;
|
||||
final private EdmEntitySet edmEntitySet;
|
||||
final private EdmBindingTarget bindingTarget;
|
||||
|
||||
public ExpressionVisitorImpl(Entity entity, EdmEntitySet edmEntitySet) {
|
||||
public ExpressionVisitorImpl(Entity entity, EdmBindingTarget bindingTarget) {
|
||||
this.entity = entity;
|
||||
this.edmEntitySet = edmEntitySet;
|
||||
this.bindingTarget = bindingTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -183,7 +183,7 @@ public class ExpressionVisitorImpl implements ExpressionVisitor<VisitorOperand>
|
|||
Property currentProperty = entity.getProperty(uriResourceParts.get(0).toString());
|
||||
EdmType currentType = ((UriResourcePartTyped) uriResourceParts.get(0)).getType();
|
||||
|
||||
EdmProperty currentEdmProperty = edmEntitySet.getEntityType()
|
||||
EdmProperty currentEdmProperty = bindingTarget.getEntityType()
|
||||
.getStructuralProperty(uriResourceParts.get(0).toString());
|
||||
|
||||
for (int i = 1; i < uriResourceParts.size(); i++) {
|
||||
|
|
|
@ -23,7 +23,7 @@ import java.util.Locale;
|
|||
|
||||
import org.apache.olingo.commons.api.data.Entity;
|
||||
import org.apache.olingo.commons.api.data.EntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
|
||||
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||
import org.apache.olingo.commons.core.edm.primitivetype.EdmBoolean;
|
||||
import org.apache.olingo.server.api.ODataApplicationException;
|
||||
|
@ -53,8 +53,8 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operand
|
|||
|
||||
public class FilterHandler {
|
||||
|
||||
public static void applyFilterSystemQuery(FilterOption filterOption, EntitySet entitySet, EdmEntitySet edmEntitySet)
|
||||
throws ODataApplicationException {
|
||||
public static void applyFilterSystemQuery(FilterOption filterOption, EntitySet entitySet,
|
||||
EdmBindingTarget edmEntitySet) throws ODataApplicationException {
|
||||
|
||||
if (filterOption == null) {
|
||||
return;
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.Locale;
|
|||
|
||||
import org.apache.olingo.commons.api.data.Entity;
|
||||
import org.apache.olingo.commons.api.data.EntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||
import org.apache.olingo.commons.api.edm.EdmBindingTarget;
|
||||
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||
import org.apache.olingo.server.api.ODataApplicationException;
|
||||
import org.apache.olingo.server.api.uri.queryoption.OrderByItem;
|
||||
|
@ -35,14 +35,14 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operand
|
|||
|
||||
public class OrderByHandler {
|
||||
public static void applyOrderByOption(final OrderByOption orderByOption, final EntitySet entitySet,
|
||||
final EdmEntitySet edmEntitySet) throws ODataApplicationException {
|
||||
final EdmBindingTarget edmBindingTarget) throws ODataApplicationException {
|
||||
|
||||
if (orderByOption == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
applyOrderByOptionInternal(orderByOption, entitySet, edmEntitySet);
|
||||
applyOrderByOptionInternal(orderByOption, entitySet, edmBindingTarget);
|
||||
} catch (SystemQueryOptionsRuntimeException e) {
|
||||
if (e.getCause() instanceof ODataApplicationException) {
|
||||
// Throw the nested exception, to send the correct HTTP status code in the HTTP response
|
||||
|
@ -55,7 +55,7 @@ public class OrderByHandler {
|
|||
}
|
||||
|
||||
private static void applyOrderByOptionInternal(final OrderByOption orderByOption, final EntitySet entitySet,
|
||||
final EdmEntitySet edmEntitySet) throws ODataApplicationException {
|
||||
final EdmBindingTarget edmBindingTarget) throws ODataApplicationException {
|
||||
Collections.sort(entitySet.getEntities(), new Comparator<Entity>() {
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
|
@ -69,9 +69,9 @@ public class OrderByHandler {
|
|||
try {
|
||||
final OrderByItem item = orderByOption.getOrders().get(i);
|
||||
final TypedOperand op1 =
|
||||
item.getExpression().accept(new ExpressionVisitorImpl(e1, edmEntitySet)).asTypedOperand();
|
||||
item.getExpression().accept(new ExpressionVisitorImpl(e1, edmBindingTarget)).asTypedOperand();
|
||||
final TypedOperand op2 =
|
||||
item.getExpression().accept(new ExpressionVisitorImpl(e2, edmEntitySet)).asTypedOperand();
|
||||
item.getExpression().accept(new ExpressionVisitorImpl(e2, edmBindingTarget)).asTypedOperand();
|
||||
|
||||
if (op1.isNull() || op2.isNull()) {
|
||||
if (op1.isNull() && op2.isNull()) {
|
||||
|
|
Loading…
Reference in New Issue