/*
 * Licensed to Crate under one or more contributor license agreements.
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.  Crate 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.
 *
 * However, if you have executed another commercial license agreement
 * with Crate these terms will supersede the license and you may use the
 * software solely pursuant to the terms of the relevant commercial
 * agreement.
 */

package io.crate.sql;

import io.crate.sql.parser.SqlParser;

import java.util.Locale;

public class Identifiers {

    /**
     * quote and escape the given identifier
     */
    public static String quote(String identifier) {
        return String.format(Locale.ENGLISH, "\"%s\"", escape(identifier));
    }


    /**
     * quote and escape identifier only if it needs to be quoted to be a valid identifier
     * i.e. when it contain a double-quote, has upper case letters or is a SQL keyword
     */
    public static String quoteIfNeeded(String identifier) {
        if (identifier.contains("\"") || hasUpperCase(identifier) || isKeyWord(identifier)) {
            return quote(identifier);
        }
        return identifier;
    }

    private static boolean hasUpperCase(String s) {
        for (int i = 0; i < s.length(); i++) {
            if (Character.isUpperCase(s.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    private static boolean isKeyWord(String identifier) {
        if (identifier.length() < 1) {
            return false;
        }
        try {
            SqlParser.createIdentifier(identifier);
            return false;
        } catch (Throwable e) {
            return true;
        }
    }

    /**
     * escape the given identifier
     * i.e. replace " with ""
     */
    public static String escape(String identifier) {
        return identifier.replace("\"", "\"\"");
    }
}

@@ -1075,43 +1075,263 @@
 til.
-Locale;%0A%0Apublic class Identifiers %7B
+regex.Matcher;%0Aimport java.util.regex.Pattern;%0A%0Apublic class Identifiers %7B%0A%0A    private static final Pattern ESCAPE_REPLACE_RE = Pattern.compile(%22%5C%22%22, Pattern.LITERAL);%0A    private static final String ESCAPE_REPLACEMENT = Matcher.quoteReplacement(%22%5C%22%5C%22%22);
 %0A%0A  
@@ -1460,47 +1460,14 @@
 urn 
-String.format(Locale.ENGLISH, %22%5C%22%25s%5C%22%22,
+%22%5C%22%22 +
  esc
@@ -1481,17 +1481,23 @@
 ntifier)
-)
+ + %22%5C%22%22
 ;%0A    %7D%0A
@@ -1497,17 +1497,16 @@
 %0A    %7D%0A%0A
-%0A
     /**%0A
@@ -1766,73 +1766,24 @@
 if (
-identifier.contains(%22%5C%22%22) %7C%7C hasUpperCase(identifier) %7C%7C isKeyWor
+areQuotesRequire
 d(id
@@ -1908,29 +1908,43 @@
 ean 
-hasUpperCase(String s
+areQuotesRequired(String identifier
 ) %7B%0A
@@ -1971,17 +1971,26 @@
  0; i %3C 
-s
+identifier
 .length(
@@ -2012,19 +2012,80 @@
        i
-f (
+nt cp = identifier.codePointAt(i);%0A            if (cp == '%22' %7C%7C 
 Characte
@@ -2102,19 +2102,10 @@
 ase(
-s.charAt(i)
+cp
 )) %7B
@@ -2169,29 +2169,45 @@
      return 
-false
+isKeyWord(identifier)
 ;%0A    %7D%0A%0A   
@@ -2328,32 +2328,130 @@
 alse;%0A        %7D%0A
+        // TODO: this is causing gazillion allocations and creates expensive exceptions. FIX THIS%0A
         try %7B%0A  
@@ -2741,32 +2741,58 @@
 %0A        return 
+ESCAPE_REPLACE_RE.matcher(
 identifier.repla
@@ -2789,16 +2789,17 @@
 fier
+)
 .replace
 (%22%5C%22
@@ -2798,21 +2798,30 @@
 lace
-(%22%5C%22%22, %22%5C%22%5C%22%22
+All(ESCAPE_REPLACEMENT
 );%0A 

optimize methods in Identifiers class