diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java index 2045802d2..aa2296684 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/FilterSystemQueryITCase.java @@ -19,6 +19,7 @@ package org.apache.olingo.fit.tecsvc.client; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.net.URI; import java.util.LinkedHashMap; @@ -41,6 +42,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase { private static final String ES_COMP_ALL_PRIM = "ESCompAllPrim"; private static final String ES_TWO_KEY_NAV = "ESTwoKeyNav"; private static final String ES_ALL_PRIM = "ESAllPrim"; + private static final String ES_MIX_ENUM_DEF_COLL_COMP = "ESMixEnumDefCollComp"; @Test public void timeOfDayLiteral() { @@ -184,6 +186,9 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase { clientEntity = result.getBody().getEntities().get(1); assertShortOrInt(1, clientEntity.getProperty("PropertyInt16").getPrimitiveValue().toValue()); assertEquals("2", clientEntity.getProperty("PropertyString").getPrimitiveValue().toValue()); + + result = sendRequest(ES_MIX_ENUM_DEF_COLL_COMP, "PropertyEnumString has Namespace1_Alias.ENString'String1'"); + assertTrue(result.getBody().getEntities().isEmpty()); } @Test @@ -994,7 +999,7 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase { result = sendRequest(ES_ALL_PRIM, "'Test1' ne 'Test'"); assertEquals(3, result.getBody().getEntities().size()); } - + @Test public void castException() { fail("ESAllPrim", "PropertyInt16 eq '1'", HttpStatusCode.BAD_REQUEST); @@ -1004,7 +1009,6 @@ public class FilterSystemQueryITCase extends AbstractParamTecSvcITCase { fail("ESAllPrim", "PropertyInt16 eq duration'PT4S'", HttpStatusCode.BAD_REQUEST); } - @Test public void stringFunctionWithoutStringParameters() { fail("ESServerSidePaging", "contains(PropertyInt16, 3) eq 'hallo'", HttpStatusCode.BAD_REQUEST); diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java index 95bcdc731..74cdd51f1 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java @@ -91,15 +91,15 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } @Override - public void countEntityCollection(final ODataRequest request, final ODataResponse response, final UriInfo - uriInfo) throws ODataApplicationException, ODataLibraryException { + public void countEntityCollection(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo) throws ODataApplicationException, ODataLibraryException { validateOptions(uriInfo.asUriInfoResource()); - final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo); // including checks + getEdmEntitySet(uriInfo); // including checks final EntityCollection entitySetInitial = readEntityCollection(uriInfo); EntityCollection entitySet = new EntityCollection(); entitySet.getEntities().addAll(entitySetInitial.getEntities()); - FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, edmEntitySet); + FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, uriInfo, serviceMetadata.getEdm()); response.setContent(odata.createFixedFormatSerializer().count( entitySet.getEntities().size())); response.setStatusCode(HttpStatusCode.OK.getStatusCode()); @@ -430,7 +430,8 @@ public class TechnicalEntityProcessor extends TechnicalProcessor final ExpandSystemQueryOptionHandler expandHandler = new ExpandSystemQueryOptionHandler(); final Entity entitySerialization = expandHandler.transformEntityGraphToTree(entity, edmEntitySet, expand); - expandHandler.applyExpandQueryOptions(entitySerialization, edmEntitySet, expand); + expandHandler.applyExpandQueryOptions(entitySerialization, edmEntitySet, expand, uriInfo, + serviceMetadata.getEdm()); final SerializerResult serializerResult = isReference ? serializeReference(entity, edmEntitySet, requestedFormat) : @@ -480,9 +481,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor entitySet.getEntities().addAll(entitySetInitial.getEntities()); // Apply system query options - FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, edmEntitySet); + FilterHandler.applyFilterSystemQuery(uriInfo.getFilterOption(), entitySet, uriInfo, serviceMetadata.getEdm()); CountHandler.applyCountSystemQueryOption(uriInfo.getCountOption(), entitySet); - OrderByHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, edmEntitySet); + OrderByHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, uriInfo, serviceMetadata.getEdm()); SkipHandler.applySkipSystemQueryHandler(uriInfo.getSkipOption(), entitySet); TopHandler.applyTopSystemQueryOption(uriInfo.getTopOption(), entitySet); @@ -505,7 +506,8 @@ public class TechnicalEntityProcessor extends TechnicalProcessor final EntityCollection entitySetSerialization = expandHandler.transformEntitySetGraphToTree(entitySet, edmEntitySet, expand); - expandHandler.applyExpandQueryOptions(entitySetSerialization, edmEntitySet, expand); + expandHandler.applyExpandQueryOptions(entitySetSerialization, edmEntitySet, expand, uriInfo, + serviceMetadata.getEdm()); final CountOption countOption = uriInfo.getCountOption(); String id; diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java index e0faf4185..4cc88f817 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/ExpandSystemQueryOptionHandler.java @@ -27,6 +27,7 @@ import java.util.Set; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.data.Link; +import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmBindingTarget; import org.apache.olingo.commons.api.edm.EdmElement; import org.apache.olingo.commons.api.edm.EdmEntitySet; @@ -35,6 +36,7 @@ import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.commons.api.edm.EdmNavigationPropertyBinding; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.queryoption.CountOption; @@ -53,29 +55,28 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.options.TopHandler public class ExpandSystemQueryOptionHandler { public void applyExpandQueryOptions(final EntityCollection entitySet, final EdmEntitySet edmEntitySet, - final ExpandOption expandOption) throws ODataApplicationException { + final ExpandOption expandOption, final UriInfoResource uriInfo, final Edm edm) throws ODataApplicationException { if (expandOption == null) { return; } for (final Entity entity : entitySet.getEntities()) { - applyExpandOptionToEntity(entity, edmEntitySet, expandOption); + applyExpandOptionToEntity(entity, edmEntitySet, expandOption, uriInfo, edm); } } public void applyExpandQueryOptions(final Entity entity, final EdmEntitySet edmEntitySet, - final ExpandOption expandOption) - throws ODataApplicationException { + final ExpandOption expandOption, final UriInfoResource uriInfo, final Edm edm) throws ODataApplicationException { if (expandOption == null) { return; } - applyExpandOptionToEntity(entity, edmEntitySet, expandOption); + applyExpandOptionToEntity(entity, edmEntitySet, expandOption, uriInfo, edm); } private void applyExpandOptionToEntity(final Entity entity, final EdmBindingTarget edmBindingTarget, - final ExpandOption expandOption) throws ODataApplicationException { - + final ExpandOption expandOption, final UriInfoResource uriInfo, final Edm edm) throws ODataApplicationException { + final EdmEntityType entityType = edmBindingTarget.getEntityType(); for (ExpandItem item : expandOption.getExpandItems()) { @@ -103,7 +104,7 @@ public class ExpandSystemQueryOptionHandler { } } - for(EdmNavigationProperty navigationProperty: navigationProperties) { + for (EdmNavigationProperty navigationProperty: navigationProperties) { final String navPropertyName = navigationProperty.getName(); final EdmBindingTarget targetEdmEntitySet = edmBindingTarget.getRelatedBindingTarget(navPropertyName); @@ -116,7 +117,8 @@ public class ExpandSystemQueryOptionHandler { item.getCountOption(), item.getSkipOption(), item.getTopOption(), - item.getExpandOption()); + item.getExpandOption(), + uriInfo, edm); } } } @@ -125,11 +127,12 @@ public class ExpandSystemQueryOptionHandler { private void applyOptionsToEntityCollection(final EntityCollection entitySet, final EdmBindingTarget edmBindingTarget, final FilterOption filterOption, final OrderByOption orderByOption, final CountOption countOption, - final SkipOption skipOption, final TopOption topOption, final ExpandOption expandOption) + final SkipOption skipOption, final TopOption topOption, final ExpandOption expandOption, + final UriInfoResource uriInfo, final Edm edm) throws ODataApplicationException { - FilterHandler.applyFilterSystemQuery(filterOption, entitySet, edmBindingTarget); - OrderByHandler.applyOrderByOption(orderByOption, entitySet, edmBindingTarget); + FilterHandler.applyFilterSystemQuery(filterOption, entitySet, uriInfo, edm); + OrderByHandler.applyOrderByOption(orderByOption, entitySet, uriInfo, edm); CountHandler.applyCountSystemQueryOption(countOption, entitySet); SkipHandler.applySkipSystemQueryHandler(skipOption, entitySet); TopHandler.applyTopSystemQueryOption(topOption, entitySet); @@ -137,7 +140,7 @@ public class ExpandSystemQueryOptionHandler { // Apply nested expand system query options to remaining entities if (expandOption != null) { for (final Entity entity : entitySet.getEntities()) { - applyExpandOptionToEntity(entity, edmBindingTarget, expandOption); + applyExpandOptionToEntity(entity, edmBindingTarget, expandOption, uriInfo, edm); } } } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/ExpressionVisitorImpl.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/ExpressionVisitorImpl.java index 969a75422..b36245608 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/ExpressionVisitorImpl.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/ExpressionVisitorImpl.java @@ -23,8 +23,9 @@ 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.Edm; import org.apache.olingo.commons.api.edm.EdmEnumType; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.EdmType; import org.apache.olingo.commons.api.http.HttpStatusCode; @@ -48,16 +49,19 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operati public class ExpressionVisitorImpl implements ExpressionVisitor { - final private Entity entity; + private final Entity entity; + private final UriInfoResource uriInfo; + private final Edm edm; - public ExpressionVisitorImpl(final Entity entity, final EdmBindingTarget bindingTarget) { + public ExpressionVisitorImpl(final Entity entity, final UriInfoResource uriInfo, final Edm edm) { this.entity = entity; + this.uriInfo = uriInfo; + this.edm = edm; } @Override public VisitorOperand visitBinaryOperator(final BinaryOperatorKind operator, final VisitorOperand left, - final VisitorOperand right) - throws ExpressionVisitException, ODataApplicationException { + final VisitorOperand right) throws ExpressionVisitException, ODataApplicationException { final BinaryOperator binaryOperator = new BinaryOperator(left, right); @@ -84,6 +88,9 @@ public class ExpressionVisitorImpl implements ExpressionVisitor case DIV: case MOD: return binaryOperator.arithmeticOperator(operator); + case HAS: + return binaryOperator.hasOperator(); + default: return throwNotImplemented(); } @@ -161,15 +168,13 @@ public class ExpressionVisitorImpl implements ExpressionVisitor @Override public VisitorOperand visitLambdaExpression(final String lambdaFunction, final String lambdaVariable, - final Expression expression) - throws ExpressionVisitException, ODataApplicationException { - + final Expression expression) throws ExpressionVisitException, ODataApplicationException { return throwNotImplemented(); } @Override public VisitorOperand visitLiteral(final Literal literal) throws ExpressionVisitException, ODataApplicationException { - return new UntypedOperand(literal.getText()); + return new UntypedOperand(literal.getText(), edm); } @Override @@ -204,12 +209,12 @@ public class ExpressionVisitorImpl implements ExpressionVisitor @Override public VisitorOperand visitAlias(final String aliasName) throws ExpressionVisitException, ODataApplicationException { - return throwNotImplemented(); + return new UntypedOperand(uriInfo.getValueForAlias(aliasName), edm); } @Override - public VisitorOperand visitTypeLiteral(final EdmType type) throws ExpressionVisitException, - ODataApplicationException { + public VisitorOperand visitTypeLiteral(final EdmType type) + throws ExpressionVisitException, ODataApplicationException { return throwNotImplemented(); } @@ -221,9 +226,18 @@ public class ExpressionVisitorImpl implements ExpressionVisitor @Override public VisitorOperand visitEnum(final EdmEnumType type, final List enumValues) - throws ExpressionVisitException, - ODataApplicationException { - return throwNotImplemented(); + throws ExpressionVisitException, ODataApplicationException { + Long result = null; + try { + for (final String enumValue : enumValues) { + final Long value = type.valueOfString(enumValue, null, null, null, null, null, Long.class); + result = result == null ? value : result | value; + } + } catch (final EdmPrimitiveTypeException e) { + throw new ODataApplicationException("Illegal enum value.", + HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT, e); + } + return new TypedOperand(result, type); } private VisitorOperand throwNotImplemented() throws ODataApplicationException { diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/TypedOperand.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/TypedOperand.java index 11cf3abe0..fc36f9685 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/TypedOperand.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/TypedOperand.java @@ -19,6 +19,7 @@ package org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operand; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Locale; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; @@ -54,36 +55,42 @@ public class TypedOperand extends VisitorOperand { } @Override - public TypedOperand asTypedOperand(final EdmPrimitiveType... asTypes) throws ODataApplicationException { + public TypedOperand asTypedOperand(final EdmPrimitiveType asType) throws ODataApplicationException { if (is(primNull)) { return this; } else if (isNull()) { - return new TypedOperand(null, asTypes[0]); + return new TypedOperand(null, asType); } Object newValue = null; - for (EdmPrimitiveType asType : asTypes) { - // Use BigDecimal for unlimited precision - if (asType.equals(primDouble) || asType.equals(primSingle) || asType.equals(primDecimal)) { - - try { - newValue = new BigDecimal(value.toString()); - } catch (NumberFormatException e) { - // Nothing to do - } - } else { - // Use type conversion of EdmPrimitive types - try { - final String literal = getLiteral(value); - newValue = tryCast(literal, asType); - } catch (EdmPrimitiveTypeException e) { - // Nothing to do - } + // Use BigInteger for arbitrarily large whole numbers. + if (asType.equals(primSByte) || asType.equals(primByte) + || asType.equals(primInt16) || asType.equals(primInt32) || asType.equals(primInt64)) { + if (value instanceof BigInteger) { + newValue = value; + } else if (value instanceof Byte || value instanceof Short + || value instanceof Integer || value instanceof Long) { + newValue = BigInteger.valueOf(((Number) value).longValue()); } - - if (newValue != null) { - return new TypedOperand(newValue, asType); + // Use BigDecimal for unlimited precision. + } else if (asType.equals(primDouble) || asType.equals(primSingle) || asType.equals(primDecimal)) { + try { + newValue = new BigDecimal(value.toString()); + } catch (NumberFormatException e) { + // Nothing to do } + } else { + // Use type conversion of EdmPrimitive types + try { + final String literal = getLiteral(value); + newValue = tryCast(literal, asType); + } catch (EdmPrimitiveTypeException e) { + // Nothing to do + } + } + + if (newValue != null) { + return new TypedOperand(newValue, asType); } throw new ODataApplicationException("Cast failed", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT); @@ -93,11 +100,9 @@ public class TypedOperand extends VisitorOperand { final TypedOperand other = otherOperand.asTypedOperand(); final EdmType oType = other.getType(); - // In case of numberic values make sure that the EDM type is equals, check also the java type. - // So it is possible, that there is an conversation even if the same - // EdmType is provided. - // For example consider an Edm16 (internal Integer) and Edm16(internal - // Short) + // In case of numberic values make sure that the EDM type is equal, check also the java type. + // It is possible that there is an conversion even if the same EdmType is provided. + // For example consider an Edm.Int32 (internal Integer) and an Edm.Int16 (internal Short) value: // shortInstance.equals(intInstance) will always be false! if (type == oType && value != null && other.getValue() != null && value.getClass() == other.getValue().getClass()) { diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/UntypedOperand.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/UntypedOperand.java index ffc4a62ab..755d8d1c8 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/UntypedOperand.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/UntypedOperand.java @@ -20,15 +20,21 @@ package org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operan import java.util.Locale; +import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmEnumType; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.edm.EdmSchema; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.ODataApplicationException; public class UntypedOperand extends VisitorOperand { - public UntypedOperand(final String literal) { + private final Edm edm; + + public UntypedOperand(final String literal, final Edm edm) { super(literal); + this.edm = edm; } @Override @@ -37,22 +43,18 @@ public class UntypedOperand extends VisitorOperand { } @Override - public TypedOperand asTypedOperand(final EdmPrimitiveType... types) throws ODataApplicationException { + public TypedOperand asTypedOperand(final EdmPrimitiveType type) throws ODataApplicationException { final String literal = (String) value; Object newValue = null; - // First try the null literal + // First try the null literal. if ((newValue = tryCast(literal, primNull)) != null) { return new TypedOperand(newValue, primNull); } - // Than try the given types - for (EdmPrimitiveType type : types) { - newValue = tryCast(literal, type); - - if (newValue != null) { - return new TypedOperand(newValue, type); - } + // Then try the given type. + if ((newValue = tryCast(literal, type)) != null) { + return new TypedOperand(newValue, type); } throw new ODataApplicationException("Cast failed", HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), @@ -130,6 +132,17 @@ public class UntypedOperand extends VisitorOperand { return new TypedOperand(newValue, primDouble); } + // Enum + final EdmSchema schema = edm.getSchema(edm.getEntityContainer().getNamespace()); + final String enumValue = schema.getAlias() != null && literal.startsWith(schema.getAlias()) ? + literal.replace(schema.getAlias(), schema.getNamespace()) : + literal; + for (final EdmEnumType enumType : schema.getEnumTypes()) { + if ((newValue = tryCast(enumValue, enumType)) != null) { + return new TypedOperand(newValue, enumType); + } + } + throw new ODataApplicationException("Could not determine type for literal " + literal, HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT); } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/VisitorOperand.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/VisitorOperand.java index bc4bfd582..c06b6bb38 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/VisitorOperand.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operand/VisitorOperand.java @@ -85,7 +85,7 @@ public abstract class VisitorOperand { public abstract TypedOperand asTypedOperand() throws ODataApplicationException; - public abstract TypedOperand asTypedOperand(EdmPrimitiveType... types) throws ODataApplicationException; + public abstract TypedOperand asTypedOperand(EdmPrimitiveType type) throws ODataApplicationException; public abstract EdmProperty getEdmProperty(); diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operation/BinaryOperator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operation/BinaryOperator.java index 9ff1bc271..5c2412775 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operation/BinaryOperator.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/expression/operation/BinaryOperator.java @@ -168,7 +168,15 @@ public class BinaryOperator { return new TypedOperand(result, primBoolean); } - @SuppressWarnings({ "rawtypes", "unchecked" }) + public VisitorOperand hasOperator() throws ODataApplicationException { + final boolean result = isBinaryComparisonNecessary() + && !left.getTypedValue(BigInteger.class).equals(BigInteger.ZERO) + && left.getTypedValue(BigInteger.class).and(BigInteger.valueOf(right.getTypedValue(Number.class).longValue())) + .equals(BigInteger.valueOf(right.getTypedValue(Number.class).longValue())); + return new TypedOperand(result, primBoolean); + } + + @SuppressWarnings("unchecked") private boolean binaryComparison(final int... expect) { int result; @@ -180,13 +188,14 @@ public class BinaryOperator { result = left.getTypedValue(BigInteger.class).compareTo(right.getTypedValue(BigInteger.class)); } else if (left.isDecimalType()) { result = left.getTypedValue(BigDecimal.class).compareTo(right.getTypedValue(BigDecimal.class)); - } else if(left.getValue().getClass() == right.getValue().getClass() && left.getValue() instanceof Comparable) { - result = ((Comparable)left.getValue()).compareTo(right.getValue()); + } else if(left.getValue().getClass() == right.getValue().getClass() + && left.getValue() instanceof Comparable) { + result = ((Comparable) left.getValue()).compareTo(right.getValue()); } else { result = left.getValue().equals(right.getValue()) ? 0 : 1; } } - + for (int expectedValue : expect) { if (expectedValue == result) { return true; diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/FilterHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/FilterHandler.java index 5f5c9df34..b2bd405db 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/FilterHandler.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/FilterHandler.java @@ -23,12 +23,13 @@ import java.util.Locale; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; -import org.apache.olingo.commons.api.edm.EdmBindingTarget; +import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.queryoption.FilterOption; import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException; import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.ExpressionVisitorImpl; @@ -37,16 +38,11 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operand public class FilterHandler { - protected static final OData oData; - protected static final EdmPrimitiveType primBoolean; - - static { - oData = OData.newInstance(); - primBoolean = oData.createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean); - } + protected static final EdmPrimitiveType primBoolean = + OData.newInstance().createPrimitiveTypeInstance(EdmPrimitiveTypeKind.Boolean); public static void applyFilterSystemQuery(final FilterOption filterOption, final EntityCollection entitySet, - final EdmBindingTarget edmEntitySet) throws ODataApplicationException { + final UriInfoResource uriInfo, final Edm edm) throws ODataApplicationException { if (filterOption == null) { return; @@ -57,16 +53,17 @@ public class FilterHandler { while (iter.hasNext()) { final VisitorOperand operand = filterOption.getExpression() - .accept(new ExpressionVisitorImpl(iter.next(), edmEntitySet)); + .accept(new ExpressionVisitorImpl(iter.next(), uriInfo, edm)); final TypedOperand typedOperand = operand.asTypedOperand(); - - if(typedOperand.is(primBoolean)) { - if(Boolean.FALSE.equals(typedOperand.getTypedValue(Boolean.class))) { + + if (typedOperand.is(primBoolean)) { + if (Boolean.FALSE.equals(typedOperand.getTypedValue(Boolean.class))) { iter.remove(); } } else { - throw new ODataApplicationException("Invalid filter expression. Filter expressions must return a value of " - + "type Edm.Boolean", HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT); + throw new ODataApplicationException( + "Invalid filter expression. Filter expressions must return a value of type Edm.Boolean", + HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ROOT); } } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/OrderByHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/OrderByHandler.java index ce472ba2a..ad1d2d541 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/OrderByHandler.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/OrderByHandler.java @@ -24,9 +24,10 @@ import java.util.Locale; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; -import org.apache.olingo.commons.api.edm.EdmBindingTarget; +import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.queryoption.OrderByItem; import org.apache.olingo.server.api.uri.queryoption.OrderByOption; import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException; @@ -35,43 +36,43 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.expression.operand public class OrderByHandler { public static void applyOrderByOption(final OrderByOption orderByOption, final EntityCollection entitySet, - final EdmBindingTarget edmBindingTarget) throws ODataApplicationException { + final UriInfoResource uriInfo, final Edm edm) throws ODataApplicationException { if (orderByOption == null) { return; } try { - applyOrderByOptionInternal(orderByOption, entitySet, edmBindingTarget); + applyOrderByOptionInternal(orderByOption, entitySet, uriInfo, edm); } catch (SystemQueryOptionsRuntimeException e) { if (e.getCause() instanceof ODataApplicationException) { // Throw the nested exception, to send the correct HTTP status code in the HTTP response throw (ODataApplicationException) e.getCause(); } else { - throw new ODataApplicationException("Exception in orderBy evaluation", HttpStatusCode.INTERNAL_SERVER_ERROR - .getStatusCode(), Locale.ROOT); + throw new ODataApplicationException("Exception in orderBy evaluation", + HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT); } } } private static void applyOrderByOptionInternal(final OrderByOption orderByOption, final EntityCollection entitySet, - final EdmBindingTarget edmBindingTarget) throws ODataApplicationException { + final UriInfoResource uriInfo, final Edm edm) throws ODataApplicationException { Collections.sort(entitySet.getEntities(), new Comparator() { @Override - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings("unchecked") public int compare(final Entity e1, final Entity e2) { - // Evaluate the first order option for both entity - // If and only if the result of the previous order option is equals to 0 - // evaluate the next order option until all options are evaluated or they are not equals + // Evaluate the first order option for both entities. + // If and only if the result of the previous order option is equal to 0 + // evaluate the next order option until all options are evaluated or they are not equal. int result = 0; for (int i = 0; i < orderByOption.getOrders().size() && result == 0; i++) { try { final OrderByItem item = orderByOption.getOrders().get(i); final TypedOperand op1 = - item.getExpression().accept(new ExpressionVisitorImpl(e1, edmBindingTarget)).asTypedOperand(); + item.getExpression().accept(new ExpressionVisitorImpl(e1, uriInfo, edm)).asTypedOperand(); final TypedOperand op2 = - item.getExpression().accept(new ExpressionVisitorImpl(e2, edmBindingTarget)).asTypedOperand(); + item.getExpression().accept(new ExpressionVisitorImpl(e2, uriInfo, edm)).asTypedOperand(); if (op1.isNull() || op2.isNull()) { if (op1.isNull() && op2.isNull()) { @@ -84,7 +85,7 @@ public class OrderByHandler { Object o2 = op2.getValue(); if (o1.getClass() == o2.getClass() && o1 instanceof Comparable) { - result = ((Comparable) o1).compareTo(o2); + result = ((Comparable) o1).compareTo(o2); } else { result = 0; }