content: /*
   * Copyright 2020 Alibaba Group Holding Limited.
   *
   * 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
   *
   * https://github.com/apache/calcite/blob/main/core/src/main/java/org/apache/calcite/rex/RexCallBinding.java
   *
   * 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 com.alibaba.graphscope.common.ir.rex;
  
  import org.apache.calcite.rel.RelCollation;
  import org.apache.calcite.rel.type.RelDataType;
  import org.apache.calcite.rel.type.RelDataTypeFactory;
  import org.apache.calcite.rex.RexLiteral;
  import org.apache.calcite.rex.RexNode;
  import org.apache.calcite.rex.RexUtil;
  import org.apache.calcite.runtime.CalciteException;
  import org.apache.calcite.runtime.Resources;
  import org.apache.calcite.sql.SqlOperator;
  import org.apache.calcite.sql.SqlUtil;
  import org.apache.calcite.sql.validate.SqlMonotonicity;
  import org.apache.calcite.sql.validate.SqlValidatorException;
  import org.checkerframework.checker.nullness.qual.Nullable;
  
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * Extends {@link org.apache.calcite.sql.SqlCallBinding} by referring to an underlying collection of {@link RexNode} operands
   */
  public class RexCallBinding extends AbstractCallBinding {
      private List<RexNode> rexOperands;
      private List<RelCollation> inputCollations;
  
      public RexCallBinding(
              RelDataTypeFactory typeFactory,
              SqlOperator operator,
              List<RexNode> operands,
              List<RelCollation> inputCollations) {
          super(typeFactory, operator);
          this.rexOperands = operands;
          this.inputCollations = inputCollations;
      }
  
      // implement SqlOperatorBinding
      @Override
      public @Nullable String getStringLiteralOperand(int ordinal) {
          return RexLiteral.stringValue(rexOperands.get(ordinal));
      }
  
      @Override
      public int getIntLiteralOperand(int ordinal) {
          return RexLiteral.intValue(rexOperands.get(ordinal));
      }
  
      @Override
      public <T> @Nullable T getOperandLiteralValue(int ordinal, Class<T> clazz) {
          final RexNode node = rexOperands.get(ordinal);
          if (node instanceof RexLiteral) {
              return ((RexLiteral) node).getValueAs(clazz);
          }
          return clazz.cast(RexLiteral.value(node));
      }
  
      @Override
      public boolean isOperandNull(int ordinal, boolean allowCast) {
          return RexUtil.isNullLiteral(rexOperands.get(ordinal), allowCast);
      }
  
      @Override
      public boolean isOperandLiteral(int ordinal, boolean allowCast) {
          return RexUtil.isLiteral(rexOperands.get(ordinal), allowCast);
      }
  
      @Override
      public int getOperandCount() {
          return rexOperands.size();
      }
  
      @Override
      public RelDataType getOperandType(int ordinal) {
          return rexOperands.get(ordinal).getType();
      }
  
      @Override
      public SqlMonotonicity getOperandMonotonicity(int ordinal) {
          throw new UnsupportedOperationException(
                  "getOperandMonotonicity is unsupported for we will never use it");
      }
  
      // override SqlCallBinding
      @Override
      public CalciteException newValidationSignatureError() {
          String message =
                  String.format(
                          "Cannot apply %s to arguments of type %s. Supported form(s): %s",
                          getOperator().getName(),
                          getCallSignature(),
                          getOperator().getAllowedSignatures());
          return new CalciteException(message, null);
      }
  
      @Override
      public CalciteException newValidationError(Resources.ExInst<SqlValidatorException> ex) {
          Throwable t = ex.ex();
          return new CalciteException(t.getMessage(), t);
      }
  
      private String getCallSignature() {
          List<String> signatureList = new ArrayList<>();
          for (RexNode operand : getRexOperands()) {
              RelDataType argType = operand.getType();
              if (null == argType) {
                  continue;
              }
              signatureList.add(argType.toString());
          }
          return SqlUtil.getOperatorSignature(getOperator(), signatureList);
      }
  
      public List<RexNode> getRexOperands() {
          return rexOperands;
      }
  }
  