All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.rapleaf.jack.util.MysqlToJavaScriptTranslator Maven / Gradle / Ivy

There is a newer version: 1.8
Show newest version
// Copyright 2011 Rapleaf
package com.rapleaf.jack.util;

import java.io.IOException;
import java.io.StringReader;
import java.util.Set;


public class MysqlToJavaScriptTranslator {

  public static String translate(String original, Set referencedFields) throws IOException {
    StringBuilder sb = new StringBuilder();
    MysqlFlex yylex = new MysqlFlex(new StringReader(original));
    Token token = null;
    while(true) {
      token = yylex.yylex();
      if(token == null) break;
      switch(token.index) {
      case 0: // ','
      case 3: // '('
      case 4: // ')'
      case 10: // '+'
      case 11: // '-'
      case 12: // '*'
      case 13: // '/'
      case 16: // '<'
      case 17: // '<='
      case 18: // '>'
      case 19: // '>='
      case 20: // '&'
      case 21: // '|'
      case 22: // '&&'
      case 23: // '||'
      case 39: // !=
      case 60: // Double quoted String
      case 62: // Single quoted String
      case 64: // Float
        sb.append(token.text);
        break;
      case 14: // '='
        sb.append("==");
        break;
      case 24: // LIKE
      {
        Token next = yylex.yylex();
        if(next.index == 60 || next.index == 62) {
          String regex = next.text.substring(1, next.text.length()-1);
          if(regex.contains("\\")) {
            throw new IOException("Escape characters in the LIKE regex are not currently supported");
          }
          regex = regex.replaceAll("%", ".*");
          regex = regex.replaceAll("_", ".");
          regex = regex.replaceAll("/", "\\\\/");
          regex = '^' + regex + '$';
          sb.append(".match(/");
          sb.append(regex);
          sb.append("/) != null");
        } else {
          throw new IOException("LIKE token must be followed by a string");
        }
      }
        break;
      case 25: // OR
        sb.append("||");
        break;
      case 26: // AND
        sb.append("&&");
        break;
      case 28: // IN
        throw new IOException("IN must be preceded by an identifier");
      case 32: // IS NULL
        sb.append("== null");
        break;
      case 40: // IS NOT NULL
        sb.append("!= null");
        break;
      case 41: // IS NOT {BOOLEAN}
        sb.append("!=");
        if(token.text.toLowerCase().endsWith("true")) {
          sb.append("true");
        } else if(token.text.toLowerCase().endsWith("false")) {
          sb.append("false");
        } else if(token.text.toLowerCase().endsWith("unknown")) {
          sb.append("unknown");
        }
      case 42: // IS {BOOLEAN}
        sb.append("==");
        if(token.text.toLowerCase().endsWith("true")) {
          sb.append("true");
        } else if(token.text.toLowerCase().endsWith("false")) {
          sb.append("false");
        } else if(token.text.toLowerCase().endsWith("unknown")) {
          sb.append("unknown");
        }
        break;
      case 43: // NOT IN
        throw new IOException("NOT IN must be preceded by an identifier");
      case 44: // NOT LIKE 
      {
        Token next = yylex.yylex();
        if(next.index == 60 || next.index == 62) {
          String regex = next.text.substring(1, next.text.length()-1);
          if(regex.contains("\\")) {
            throw new IOException("Escape characters in the NOT LIKE regex are not currently supported");
          }
          regex = regex.replaceAll("%", ".*");
          regex = regex.replaceAll("_", ".");
          regex = regex.replaceAll("/", "\\/");
          regex = '^' + regex + '$';
          sb.append(".match(/");
          sb.append(regex);
          sb.append("/) == null");
        } else {
          throw new IOException("NOT LIKE token must be followed by a string");
        }
      }
        break;
      case 66: // Identifier
        referencedFields.add(token.text.toLowerCase());
        Token next = yylex.yylex();
        if(next == null) {
          break;
        }
        if(next.index == 28) { // IN
          sb.append("(");
          next = yylex.yylex();
          if(next == null || next.index != 3) { // '('
            throw new IOException("IN must be followed by '('");
          }
          next = yylex.yylex();
          if(next == null) {
            throw new IOException("Unmatched open parenthases");
          }
          sb.append(token.text + "==" + next.text);
          while(true) {
            next = yylex.yylex();
            if(next == null) {
              throw new IOException("Unmatched open parenthases");
            }
            if(next.index == 4) { // ')'
              break;
            }
            if(next.index != 0) {// ','
              throw new IOException("Values in () must be comma separated");
            }
            Token nextValue = yylex.yylex();
            sb.append("||" + token.text + "==" + nextValue.text);
          }
          sb.append(")");
        } else if(next.index == 43) { // NOT IN
          sb.append("(");
          next = yylex.yylex();
          if(next == null || next.index != 3) { // '('
            throw new IOException("IN must be followed by '('");
          }
          next = yylex.yylex();
          if(next == null) {
            throw new IOException("Unmatched open parenthases");
          }
          sb.append(token.text + "!=" + next.text);
          while(true) {
            next = yylex.yylex();
            if(next == null) {
              throw new IOException("Unmatched open parenthases");
            }
            if(next.index == 4) { // ')'
              break;
            }
            if(next.index != 0) {// ','
              throw new IOException("Values in () must be comma separated");
            }
            Token nextValue = yylex.yylex();
            sb.append("&&" + token.text + "!=" + nextValue.text);
          }
          sb.append(")");
        } else {
          sb.append(token.text.toLowerCase());
          yylex.yypushback(next.text.length());
        } 
        break;
      default: // Not supported 1,2,5-9,15,24,27, etc
        throw new IOException("Unsupported token: " + token.text);
      }
    }
    return sb.toString();
  }
  
  private static final void stringifyToken(Token token, StringBuilder sb, Set referencedFields) throws IOException {
    switch(token.index) {
    case 66:
      sb.append(token.text);
      referencedFields.add(token.text);
      break;
    default:
      throw new IOException("Unsupported token");
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy