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
   *
   * 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 com.alibaba.graphscope.common.ir.rex;
  
  import com.alibaba.graphscope.common.ir.tools.AliasInference;
  
  import org.apache.calcite.rel.type.RelDataType;
  import org.apache.calcite.rex.RexInputRef;
  import org.apache.calcite.rex.RexVisitor;
  import org.apache.commons.lang3.StringUtils;
  import org.checkerframework.checker.nullness.qual.Nullable;
  
  import java.util.Objects;
  
  /**
   * maintain the necessary info to create a {@code RexGraphVariable}
   * i.e. group().by().by(sum("@.age + 1")):
   * "@.age + 1" need to be projected in advance and is aliased as an inner name (supposing '$f0'), the latter aggregate function will apply on the variable('$f0');
   * However, we cannot generate an actual variable('$f0') at this point in that the name '$f0' does not exist until `project("@.age + 1")` is appended in the {@code GraphBuilder}.
   * {@code RexTmpVariable} is used to cache alias or property names to build an actual {@code RexGraphVariable} in the future.
   */
  public class RexTmpVariable extends RexInputRef {
      private final @Nullable String alias;
      private final @Nullable String property;
      private final RelDataType type;
  
      protected RexTmpVariable(@Nullable String alias, RelDataType type) {
          this(alias, null, type);
      }
  
      protected RexTmpVariable(@Nullable String alias, @Nullable String property, RelDataType type) {
          super(0, type);
          this.digest =
                  (alias == null)
                          ? StringUtils.EMPTY
                          : alias
                                  + ((property == null)
                                          ? StringUtils.EMPTY
                                          : AliasInference.DELIMITER + property);
          this.alias = alias;
          this.property = property;
          this.type = type;
      }
  
      public static RexTmpVariable of(@Nullable String alias, RelDataType type) {
          return new RexTmpVariable(alias, type);
      }
  
      public static RexTmpVariable of(@Nullable String alias, String property, RelDataType type) {
          return new RexTmpVariable(alias, property, type);
      }
  
      @Override
      public RelDataType getType() {
          return this.type;
      }
  
      @Override
      public <R> R accept(RexVisitor<R> rexVisitor) {
          return (rexVisitor instanceof RexTmpVariableConverter)
                  ? rexVisitor.visitInputRef(this)
                  : null;
      }
  
      @Override
      public String getName() {
          return this.digest;
      }
  
      public @Nullable String getAlias() {
          return alias;
      }
  
      public @Nullable String getProperty() {
          return property;
      }
  
      @Override
      public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null || getClass() != o.getClass()) return false;
          if (!super.equals(o)) return false;
          RexTmpVariable that = (RexTmpVariable) o;
          return Objects.equals(alias, that.alias)
                  && Objects.equals(property, that.property)
                  && Objects.equals(type, that.type);
      }
  
      @Override
      public int hashCode() {
          return Objects.hash(super.hashCode(), alias, property, type);
      }
  }
  