/* * Copyright 2013-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.data.mongodb.core.spel; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.springframework.expression.spel.ExpressionState; import org.springframework.expression.spel.ast.OpAnd; import org.springframework.expression.spel.ast.OpDivide; import org.springframework.expression.spel.ast.OpEQ; import org.springframework.expression.spel.ast.OpGE; import org.springframework.expression.spel.ast.OpGT; import org.springframework.expression.spel.ast.OpLE; import org.springframework.expression.spel.ast.OpLT; import org.springframework.expression.spel.ast.OpMinus; import org.springframework.expression.spel.ast.OpModulus; import org.springframework.expression.spel.ast.OpMultiply; import org.springframework.expression.spel.ast.OpNE; import org.springframework.expression.spel.ast.OpOr; import org.springframework.expression.spel.ast.OpPlus; import org.springframework.expression.spel.ast.Operator; import org.springframework.expression.spel.ast.OperatorPower; /** * An {@link ExpressionNode} representing an operator. * * @author Oliver Gierke * @author Thomas Darimont * @author Christoph Strobl */ public class OperatorNode extends ExpressionNode { private static final Map<String, String> OPERATORS; private static final Set<Class> SUPPORTED_MATH_OPERATORS; static { Map<String, String> map = new HashMap<String, String>(14, 1); map.put("+", "$add"); map.put("-", "$subtract"); map.put("*", "$multiply"); map.put("/", "$divide"); map.put("%", "$mod"); map.put("^", "$pow"); map.put("==", "$eq"); map.put("!=", "$ne"); map.put(">", "$gt"); map.put(">=", "$gte"); map.put("<", "$lt"); map.put("<=", "$lte"); map.put("and", "$and"); map.put("or", "$or"); OPERATORS = Collections.unmodifiableMap(map); Set<Class> set = new HashSet<Class>(12, 1); set.add(OpMinus.class); set.add(OpPlus.class); set.add(OpMultiply.class); set.add(OpDivide.class); set.add(OpModulus.class); set.add(OperatorPower.class); set.add(OpNE.class); set.add(OpEQ.class); set.add(OpGT.class); set.add(OpGE.class); set.add(OpLT.class); set.add(OpLE.class); SUPPORTED_MATH_OPERATORS = Collections.unmodifiableSet(set); } private final Operator operator; /** * Creates a new {@link OperatorNode} from the given {@link Operator} and {@link ExpressionState}. * * @param node must not be {@literal null}. * @param state must not be {@literal null}. */ OperatorNode(Operator node, ExpressionState state) { super(node, state); this.operator = node; } /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.spel.ExpressionNode#isMathematicalOperation() */ @Override public boolean isMathematicalOperation() { return SUPPORTED_MATH_OPERATORS.contains(operator.getClass()); } /* * (non-Javadoc) * @see org.springframework.data.mongodb.core.spel.ExpressionNode#isConjunctionOperator() */ @Override public boolean isLogicalOperator() { return operator instanceof OpOr || operator instanceof OpAnd; } /** * Returns whether the operator is unary. * * @return */ public boolean isUnaryOperator() { return operator.getRightOperand() == null; } /** * Returns the Mongo expression of the operator. * * @return */ public String getMongoOperator() { if (!OPERATORS.containsKey(operator.getOperatorName())) { throw new IllegalArgumentException(String.format( "Unknown operator name. Cannot translate %s into its MongoDB aggregation function representation.", operator.getOperatorName())); } return OPERATORS.get(operator.getOperatorName()); } /** * Returns whether the operator is a unary minus, e.g. -1. * * @return */ public boolean isUnaryMinus() { return isUnaryOperator() && operator instanceof OpMinus; } /** * Returns the left operand as {@link ExpressionNode}. * * @return */ public ExpressionNode getLeft() { return from(operator.getLeftOperand()); } /** * Returns the right operand as {@link ExpressionNode}. * * @return */ public ExpressionNode getRight() { return from(operator.getRightOperand()); } }