/*
* Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky
*
* 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 freemarker.core;
import freemarker.template.Configuration;
import freemarker.template.utility.StringUtil;
/**
* For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
* This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can
* access things inside this package that users shouldn't.
*/
public final class _CoreStringUtils {
private _CoreStringUtils() {
// No meant to be instantiated
}
public static String toFTLIdentifierReferenceAfterDot(String name) {
return backslashEscapeIdentifier(name);
}
public static String toFTLTopLevelIdentifierReference(String name) {
return backslashEscapeIdentifier(name);
}
public static String toFTLTopLevelTragetIdentifier(final String name) {
char quotationType = 0;
scanForQuotationType: for (int i = 0; i < name.length(); i++) {
final char c = name.charAt(i);
if (!(i == 0 ? StringUtil.isFTLIdentifierStart(c) : StringUtil.isFTLIdentifierPart(c)) && c != '@') {
if ((quotationType == 0 || quotationType == '\\') && (c == '-' || c == '.' || c == ':')) {
quotationType = '\\';
} else {
quotationType = '"';
break scanForQuotationType;
}
}
}
switch (quotationType) {
case 0:
return name;
case '"':
return StringUtil.ftlQuote(name);
case '\\':
return backslashEscapeIdentifier(name);
default:
throw new BugException();
}
}
private static String backslashEscapeIdentifier(String name) {
return StringUtil.replace(StringUtil.replace(StringUtil.replace(name, "-", "\\-"), ".", "\\."), ":", "\\:");
}
/**
* @return {@link Configuration#CAMEL_CASE_NAMING_CONVENTION}, or {@link Configuration#LEGACY_NAMING_CONVENTION}
* or, {@link Configuration#AUTO_DETECT_NAMING_CONVENTION} when undecidable.
*/
public static int getIdentifierNamingConvention(String name) {
final int ln = name.length();
for (int i = 0; i < ln; i++) {
final char c = name.charAt(i);
if (c == '_') {
return Configuration.LEGACY_NAMING_CONVENTION;
}
if (isUpperUSASCII(c)) {
return Configuration.CAMEL_CASE_NAMING_CONVENTION;
}
}
return Configuration.AUTO_DETECT_NAMING_CONVENTION;
}
// [2.4] Won't be needed anymore
/**
* A deliberately very inflexible camel case to underscored converter; it must not convert improper camel case
* names to a proper underscored name.
*/
public static String camelCaseToUnderscored(String camelCaseName) {
int i = 0;
while (i < camelCaseName.length() && Character.isLowerCase(camelCaseName.charAt(i))) {
i++;
}
if (i == camelCaseName.length()) {
// No conversion needed
return camelCaseName;
}
StringBuilder sb = new StringBuilder();
sb.append(camelCaseName.substring(0, i));
while (i < camelCaseName.length()) {
final char c = camelCaseName.charAt(i);
if (isUpperUSASCII(c)) {
sb.append('_');
sb.append(Character.toLowerCase(c));
} else {
sb.append(c);
}
i++;
}
return sb.toString();
}
public static boolean isUpperUSASCII(char c) {
return c >= 'A' && c <= 'Z';
}
}