Skip to content

Example code for implementing an ExpressionVisitor

package com.ifsworld.projection;

import org.apache.olingo.commons.api.edm.EdmEnumType;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
import org.apache.olingo.server.api.ODataApplicationException;
import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
import org.apache.olingo.server.api.uri.queryoption.expression.*;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;

public class AirportFilterVisitor implements ExpressionVisitor<Object> {


    @Override
    public Object visitBinaryOperator(BinaryOperatorKind operator, Object left, Object right) throws ExpressionVisitException, ODataApplicationException {

        if (operator == BinaryOperatorKind.EQ
                || operator == BinaryOperatorKind.NE
                || operator == BinaryOperatorKind.GE
                || operator == BinaryOperatorKind.GT
                || operator == BinaryOperatorKind.LE
                || operator == BinaryOperatorKind.LT) {
            return evaluateComparisonOperation(operator, left, right);
        } else if (operator == BinaryOperatorKind.AND
                || operator == BinaryOperatorKind.OR) {
            return evaluateBooleanOperation(operator, left, right);
        } else {
            throw new ODataApplicationException("Binary operation " + operator.name() + " is not implemented",
                    HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH);
        }
    }

    @Override
    public Object visitUnaryOperator(UnaryOperatorKind unaryOperatorKind, Object o) throws ExpressionVisitException, ODataApplicationException {
        return null;
    }

    @Override
    public Object visitMethodCall(MethodKind methodKind, List<Object> list) throws ExpressionVisitException, ODataApplicationException {
        return null;
    }

    @Override
    public Object visitLambdaExpression(String s, String s1, Expression expression) throws ExpressionVisitException, ODataApplicationException {
        return null;
    }

    @Override
    public Object visitLiteral(Literal literal) throws ExpressionVisitException, ODataApplicationException {
        String literalAsString = literal.getText();
        if(literal.getType() instanceof EdmString) {
            String stringLiteral = "";
            if(literal.getText().length() > 2) {
                stringLiteral = literalAsString.substring(1, literalAsString.length() - 1);
            }

            return  stringLiteral;
        } else {
            try {
                return Integer.parseInt(literalAsString);
            } catch(NumberFormatException e) {
                throw new ODataApplicationException("Only Edm.Int32 and Edm.String literals are implemented",
                        HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH);
            }
        }
    }

    @Override
    public Object visitMember(final Member member) throws ExpressionVisitException, ODataApplicationException {
        HashMap<String,String> propertyMap = new HashMap<>();
        propertyMap.put("Icao","icao");
        propertyMap.put("Iata","iata");
        propertyMap.put("Name","name");
        propertyMap.put("City","city");
        propertyMap.put("Region","region");
        propertyMap.put("Country","country");
        propertyMap.put("Timezone","timezone");
        final List<UriResource> uriResourceParts = member.getResourcePath().getUriResourceParts();
        if(uriResourceParts.size() == 1 && uriResourceParts.get(0) instanceof UriResourcePrimitiveProperty) {
            UriResourcePrimitiveProperty uriResourceProperty = (UriResourcePrimitiveProperty) uriResourceParts.get(0);
            return propertyMap.get(uriResourceProperty.getProperty().getName());
        } else {
            throw new ODataApplicationException("Only primitive properties are implemented in filter expressions",
                    HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH);
        }
    }

    @Override
    public Object visitAlias(String s) throws ExpressionVisitException, ODataApplicationException {
        return null;
    }

    @Override
    public Object visitTypeLiteral(EdmType edmType) throws ExpressionVisitException, ODataApplicationException {
        return null;
    }

    @Override
    public Object visitLambdaReference(String s) throws ExpressionVisitException, ODataApplicationException {
        return null;
    }

    @Override
    public Object visitEnum(EdmEnumType edmEnumType, List<String> list) throws ExpressionVisitException, ODataApplicationException {
        return null;
    }

    @Override
    public Object visitBinaryOperator(BinaryOperatorKind binaryOperatorKind, Object o, List<Object> list) throws ExpressionVisitException, ODataApplicationException {
        return null;
    }

    private Object evaluateComparisonOperation(BinaryOperatorKind operator, Object left, Object right)
            throws ODataApplicationException {

        // All types in our tutorial supports all logical operations, but we have to make sure that the types are equals
        if(left.getClass().equals(right.getClass()) && left instanceof Comparable) {


            if (operator == BinaryOperatorKind.EQ) {
                return left + "=" + right;
            } else if (operator == BinaryOperatorKind.NE) {
                return left + "!=" + right;
            } else if (operator == BinaryOperatorKind.GE) {
                return left + ">=" + right;
            } else if (operator == BinaryOperatorKind.GT) {
                return left + ">" + right;
            } else if (operator == BinaryOperatorKind.LE) {
                return left + "<=" + right;
            } else {
                return null;
            }

        } else {
            throw new ODataApplicationException("Comparision needs two equal types",
                    HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ENGLISH);
        }
    }


    private Object evaluateBooleanOperation(BinaryOperatorKind operator, Object left, Object right)
            throws ODataApplicationException {



            if(operator == BinaryOperatorKind.AND) {
                return left + "&" + right;
            } else {
                return left + "or" + right;
            }

    }
}