/*
* Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. Crate licenses
* this file to you 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.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial agreement.
*/
package io.crate.operation.operator;
import io.crate.analyze.symbol.Function;
import io.crate.analyze.symbol.Symbol;
import io.crate.core.collections.MapComparator;
import io.crate.metadata.*;
import io.crate.data.Input;
import io.crate.types.DataType;
import io.crate.types.DataTypes;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class EqOperator extends CmpOperator {
public static final String NAME = "op_=";
private static final EqOperatorResolver dynamicResolver = new EqOperatorResolver();
public static void register(OperatorModule module) {
module.registerDynamicOperatorFunction(NAME, dynamicResolver);
}
private static FunctionInfo createInfo(List<DataType> dataTypes) {
return new FunctionInfo(new FunctionIdent(NAME, dataTypes), DataTypes.BOOLEAN);
}
public static Function createFunction(Symbol left, Symbol right) {
return new Function(createInfo(Arrays.asList(left.valueType(), right.valueType())),
Arrays.asList(left, right));
}
@Override
protected boolean compare(int comparisonResult) {
return comparisonResult == 0;
}
protected EqOperator(FunctionInfo info) {
super(info);
}
@Override
public Boolean evaluate(Input[] args) {
assert args.length == 2 : "number of args must be 2";
Object left = args[0].value();
if (left == null) {
return null;
}
Object right = args[1].value();
if (right == null) {
return null;
}
return left.equals(right);
}
private static class ArrayEqOperator extends CmpOperator {
ArrayEqOperator(FunctionInfo info) {
super(info);
}
@Override
protected boolean compare(int comparisonResult) {
return comparisonResult == 0;
}
@Override
public Boolean evaluate(Input[] args) {
Object[] left = (Object[]) args[0].value();
if (left == null) {
return null;
}
Object[] right = (Object[]) args[1].value();
if (right == null) {
return null;
}
return Arrays.deepEquals(left, right);
}
}
private static class ObjectEqOperator extends Operator<Object> {
private final FunctionInfo info;
ObjectEqOperator(FunctionInfo info) {
this.info = info;
}
@Override
@SafeVarargs
public final Boolean evaluate(Input<Object>... args) {
Object left = args[0].value();
Object right = args[1].value();
if (left == null || right == null) {
return null;
}
return MapComparator.compareMaps(((Map) left), ((Map) right)) == 0;
}
@Override
public FunctionInfo info() {
return info;
}
}
static class EqOperatorResolver extends BaseFunctionResolver {
EqOperatorResolver() {
super(Signature.numArgs(2).and(Signature.SIGNATURES_ALL_OF_SAME));
}
@Override
public FunctionImplementation getForTypes(List<DataType> dataTypes) throws IllegalArgumentException {
DataType leftType = dataTypes.get(0);
DataType rightType = dataTypes.get(1);
FunctionInfo info = createInfo(dataTypes);
if (DataTypes.isCollectionType(leftType) && DataTypes.isCollectionType(rightType)) {
return new ArrayEqOperator(info);
}
if (leftType.equals(DataTypes.OBJECT) && rightType.equals(DataTypes.OBJECT)) {
return new ObjectEqOperator(info);
}
return new EqOperator(info);
}
}
}