public static String removeComments( String text ) {

    if ( text == null ) {
      return null;
    }

    StringBuilder queryWithoutComments = new StringBuilder();
    boolean blkComment = false;
    boolean lineComment = false;
    boolean inString = false;
    StringReader buffer = new StringReader( text );
    int ch;
    char currentStringChar = (char) QUOTE_CHARS[0];
    boolean done = false;

    try {
      while ( !done ) {
        switch ( ch = buffer.read() ) {
          case EOF: { // End Of File
            done = true;
            break;
          }
          case '\'': // NOTE: Add cases for any other quote characters in QUOTE_CHARS
          case '"': { // String literals

            // If we're not in a comment, we're either entering or leaving a string
            if ( !lineComment && !blkComment ) {
              char cch = (char) ch;
              if ( inString ) {
                if ( currentStringChar == cch ) {
                  inString = false;
                }
              } else {
                inString = true;
                currentStringChar = cch;
              }
              queryWithoutComments.append( cch );
            }
            break;
          }
          case '/': { // multi-line comments

            // If we're not in a line comment, we might be entering a line or multi-line comment
            if ( !lineComment ) {
              ch = buffer.read();

              // If we see a multi-line comment starter (/*) and we're not in a string or
              // multi-line comment, then we have started a multi-line comment.
              if ( ( ch == '*' ) && ( !blkComment ) && ( !inString ) ) {
               // Make sure that the next character isn't a + which identifies a hint in Oracle (PDI-13054)
                ch = buffer.read();
                if ( ch == '+' ) {
                  queryWithoutComments.append( '/' );
                  queryWithoutComments.append( '*' );
                  queryWithoutComments.append( '+' );
                } else {
                  blkComment = true;
                }
              } else {
                // Otherwise if we aren't already in a block comment, pass the chars through
                if ( !blkComment ) {
                  queryWithoutComments.append( '/' );
                  queryWithoutComments.append( (char) ch );
                  if ( inString && ( currentStringChar == (char) ch ) ) {
                    inString = false;
                  }
                }
              }
            }
            break;
          }
          case '*': { // multi-line comments

            // If we're in a multi-line comment, look ahead to see if we're about to exit
            if ( blkComment ) {
              ch = buffer.read();
              if ( ch == '/' ) {
                blkComment = false;
              }
            } else {
              // if we're not in a multi-line or line comment, pass the char through
              if ( !lineComment ) {
                queryWithoutComments.append( '*' );
              }
            }
            break;
          }
          case '-': { // single-line comment

            // if we're not in a multi-line or line comment, we might be entering a line comment
            if ( !blkComment && !lineComment ) {
              ch = buffer.read();
              // If we look ahead to see another dash and we're not in a string, we're entering a line comment
              if ( ch == '-' && !inString ) {
                lineComment = true;
              } else {
                queryWithoutComments.append( '-' );
                queryWithoutComments.append( (char) ch );
                // If it's a quote character, we're entering or leaving a string
                if ( isQuoteChar( ch ) ) {
                  char cch = (char) ch;
                  if ( inString ) {
                    if ( currentStringChar == cch ) {
                      inString = false;
                    }
                  } else {
                    inString = true;
                    currentStringChar = cch;
                  }
                }
              }
            }
            break;
          }
          case EOL: { // End Of Line
            // If we're not in a comment, pass the EOL through
            if ( !blkComment && !lineComment ) {
              queryWithoutComments.append( (char) ch );
            }
            lineComment = false;
            break;
          }
          default: {
            // if we're not in a comment, pass the character through
            if ( !blkComment && !lineComment ) {
              queryWithoutComments.append( (char) ch );
            }
            break;
          }
        }
      }
    } catch ( IOException e ) {
      // break on error, exit gracefully with altered query thus far
    }

    return queryWithoutComments.toString();
  }
@Test
  public void testRemoveComments() throws Exception {
    Assert.assertEquals( expected, SqlCommentScrubber.removeComments( input ) );
  }