content: /*
   * Copyright (C) 2016-2023 ActionTech.
   * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher.
   */
  
  package com.actiontech.dble.plan.common.item.function.strfunc;
  
  import com.actiontech.dble.plan.common.field.Field;
  import com.actiontech.dble.plan.common.item.Item;
  import com.actiontech.dble.plan.common.item.function.ItemFunc;
  import com.alibaba.druid.sql.ast.SQLExpr;
  import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
  
  import java.util.List;
  
  
  public class ItemFuncSoundex extends ItemStrFunc {
  
      public ItemFuncSoundex(Item a, int charsetIndex) {
          super(a, charsetIndex);
      }
  
      @Override
      public final String funcName() {
          return "SOUNDEX";
      }
  
      @Override
      public String valStr() {
          String str = args.get(0).valStr();
          if (this.nullValue = args.get(0).isNull())
              return EMPTY;
          return ItemFuncSoundex.soundex(str);
      }
  
      @Override
      public SQLExpr toExpression() {
          SQLMethodInvokeExpr method = new SQLMethodInvokeExpr(funcName());
          method.addArgument(args.get(0).toExpression());
          return method;
      }
  
      @Override
      protected Item cloneStruct(boolean forCalculate, List<Item> calArgs, boolean isPushDown, List<Field> fields) {
          List<Item> newArgs = null;
          if (!forCalculate)
              newArgs = cloneStructList(args);
          else
              newArgs = calArgs;
          return new ItemFuncSoundex(newArgs.get(0), charsetIndex);
      }
  
      public static String soundex(String s) {
          char[] x = s.toUpperCase().toCharArray();
          char firstLetter = x[0];
  
          // convert letters to numeric code
          for (int i = 0; i < x.length; i++) {
              switch (x[i]) {
                  case 'B':
                  case 'F':
                  case 'P':
                  case 'V': {
                      x[i] = '1';
                      break;
                  }
  
                  case 'C':
                  case 'G':
                  case 'J':
                  case 'K':
                  case 'Q':
                  case 'S':
                  case 'X':
                  case 'Z': {
                      x[i] = '2';
                      break;
                  }
  
                  case 'D':
                  case 'T': {
                      x[i] = '3';
                      break;
                  }
  
                  case 'L': {
                      x[i] = '4';
                      break;
                  }
  
                  case 'M':
                  case 'N': {
                      x[i] = '5';
                      break;
                  }
  
                  case 'R': {
                      x[i] = '6';
                      break;
                  }
  
                  default: {
                      x[i] = '0';
                      break;
                  }
              }
          }
  
          // remove duplicates
          StringBuilder output = new StringBuilder();
          output.append(firstLetter);
          for (int i = 1; i < x.length; i++)
              if (x[i] != x[i - 1] && x[i] != '0')
                  output.append(x[i]);
  
          // pad with 0's or truncate
          if (output.length() < 4) {
              output.append("0000");
              return output.substring(0, 4);
          }
          return output.toString();
      }
  
      @Override
      public ItemFunc nativeConstruct(List<Item> realArgs) {
          return new ItemFuncSoundex(realArgs.get(0), charsetIndex);
      }
  
  }
  