content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF 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.
   */
  package org.apache.calcite.test;
  
  import org.apache.calcite.sql.test.SqlOperatorFixture;
  import org.apache.calcite.util.DelegatingInvocationHandler;
  
  import org.checkerframework.checker.nullness.qual.Nullable;
  
  import java.lang.reflect.Proxy;
  import java.util.regex.Pattern;
  
  /** Utilities for {@link SqlOperatorFixture}. */
  class SqlOperatorFixtures {
    private SqlOperatorFixtures() {
    }
  
    /** Returns a fixture that converts each CAST test into a test for
     * SAFE_CAST or TRY_CAST. */
    static SqlOperatorFixture safeCastWrapper(SqlOperatorFixture fixture, String functionName) {
      return (SqlOperatorFixture) Proxy.newProxyInstance(
          SqlOperatorTest.class.getClassLoader(),
          new Class[]{SqlOperatorFixture.class},
          new SqlOperatorFixtureInvocationHandler(fixture, functionName));
    }
  
    /** A helper for {@link #safeCastWrapper(SqlOperatorFixture, String)} that provides
     * alternative implementations of methods in {@link SqlOperatorFixture}.
     *
     * <p>Must be public, so that its methods can be seen via reflection. */
    @SuppressWarnings("unused")
    public static class SqlOperatorFixtureInvocationHandler
        extends DelegatingInvocationHandler {
      static final Pattern CAST_PATTERN = Pattern.compile("(?i)\\bCAST\\(");
      static final Pattern NOT_NULL_PATTERN = Pattern.compile(" NOT NULL");
  
      final SqlOperatorFixture f;
      final String functionName;
  
      SqlOperatorFixtureInvocationHandler(SqlOperatorFixture f, String functionName) {
        this.f = f;
        this.functionName = functionName;
      }
  
      @Override protected Object getTarget() {
        return f;
      }
  
      String addSafe(String sql) {
        return CAST_PATTERN.matcher(sql).replaceAll(functionName + "(");
      }
  
      String removeNotNull(String type) {
        return NOT_NULL_PATTERN.matcher(type).replaceAll("");
      }
  
      /** Proxy for
       * {@link SqlOperatorFixture#checkCastToString(String, String, String, SqlOperatorFixture.CastType)}. */
      public void checkCastToString(String value, @Nullable String type,
          @Nullable String expected, SqlOperatorFixture.CastType castType) {
        f.checkCastToString(addSafe(value),
            type == null ? null : removeNotNull(type), expected, castType);
      }
  
      /** Proxy for {@link SqlOperatorFixture#checkBoolean(String, Boolean)}. */
      public void checkFails(String expression, @Nullable Boolean result) {
        f.checkBoolean(addSafe(expression), result);
      }
  
      /** Proxy for {@link SqlOperatorFixture#checkNull(String)}. */
      public void checkNull(String expression) {
        f.checkNull(addSafe(expression));
      }
  
      /** Proxy for
       * {@link SqlOperatorFixture#checkFails(String, String, boolean)}. */
      public void checkFails(String expression, String expectedError, boolean runtime) {
        f.checkFails(addSafe(expression), expectedError, runtime);
      }
  
      /** Proxy for
       * {@link SqlOperatorFixture#checkScalar(String, Object, String)}. */
      public void checkScalar(String expression, Object result, String resultType) {
        f.checkScalar(addSafe(expression), result, removeNotNull(resultType));
      }
  
      /** Proxy for {@link SqlOperatorFixture#checkScalarExact(String, int)}. */
      public void checkScalarExact(String expression, int result) {
        f.checkScalarExact(addSafe(expression), result);
      }
  
      /** Proxy for
       * {@link SqlOperatorFixture#checkScalarExact(String, String, String)}. */
      public void checkScalarExact(String expression, String expectedType, String result) {
        f.checkScalarExact(addSafe(expression), removeNotNull(expectedType), result);
      }
  
      /** Proxy for
       * {@link SqlOperatorFixture#checkString(String, String, String)}. */
      public void checkString(String expression, String result, String resultType) {
        f.checkString(addSafe(expression), result, removeNotNull(resultType));
      }
    }
  }
  