/**
* Mule Development Kit
* Copyright 2010-2011 (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
*
* 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 org.mule.devkit.utils;
import org.apache.commons.lang.StringUtils;
import org.mule.devkit.generation.DefaultDevKitTypeElement;
import org.mule.devkit.generation.TypeElementImpl;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
public class NameUtils {
private Elements elements;
private static final List<Inflection> plural = new ArrayList<Inflection>();
private static final List<Inflection> singular = new ArrayList<Inflection>();
private static final List<String> uncountable = new ArrayList<String>();
static {
// plural is "singular to plural form"
// singular is "plural to singular form"
plural("$", "s");
plural("s$", "s");
plural("(ax|test)is$", "$1es");
plural("(octop|vir)us$", "$1i");
plural("(alias|status)$", "$1es");
plural("(bu)s$", "$1ses");
plural("(buffal|tomat)o$", "$1oes");
plural("([ti])um$", "$1a");
plural("sis$", "ses");
plural("(?:([^f])fe|([lr])f)$", "$1$2ves");
plural("(hive)$", "$1s");
plural("([^aeiouy]|qu)y$", "$1ies");
//plural("([^aeiouy]|qu)ies$", "$1y");
plural("(x|ch|ss|sh)$", "$1es");
plural("(matr|vert|ind)ix|ex$", "$1ices");
plural("([m|l])ouse$", "$1ice");
plural("^(ox)$", "$1en");
plural("(quiz)$", "$1zes");
singular("s$", "");
singular("(n)ews$", "$1ews");
singular("([ti])a$", "$1um");
singular("((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$", "$1$2sis");
singular("(^analy)ses$", "$1sis");
singular("([^f])ves$", "$1fe");
singular("(hive)s$", "$1");
singular("(tive)s$", "$1");
singular("([lr])ves$", "$1f");
singular("([^aeiouy]|qu)ies$", "$1y");
singular("(s)eries$", "$1eries");
singular("(m)ovies$", "$1ovie");
singular("(x|ch|ss|sh)es$", "$1");
singular("([m|l])ice$", "$1ouse");
singular("(bus)es$", "$1");
singular("(o)es$", "$1");
singular("(shoe)s$", "$1");
singular("(cris|ax|test)es$", "$1is");
singular("(octop|vir)i$", "$1us");
singular("(alias|status)es$", "$1");
singular("^(ox)en", "$1");
singular("(vert|ind)ices$", "$1ex");
singular("(matr)ices$", "$1ix");
singular("(quiz)zes$", "$1");
// irregular
irregular("person", "people");
irregular("man", "men");
irregular("child", "children");
irregular("sex", "sexes");
irregular("move", "moves");
uncountable("equipment");
uncountable("information");
uncountable("rice");
uncountable("money");
uncountable("species");
uncountable("series");
uncountable("fish");
uncountable("sheep");
}
public NameUtils(Elements elements) {
this.elements = elements;
}
private static void plural(String pattern, String replacement) {
plural.add(0, new Inflection(pattern, replacement));
}
private static void singular(String pattern, String replacement) {
singular.add(0, new Inflection(pattern, replacement));
}
private static void irregular(String s, String p) {
plural("(" + s.substring(0, 1) + ")" + s.substring(1) + "$", "$1" + p.substring(1));
singular("(" + p.substring(0, 1) + ")" + p.substring(1) + "$", "$1" + s.substring(1));
}
private static void uncountable(String word) {
uncountable.add(word);
}
public String camel(String uncamelCaseName) {
String result = "";
String[] parts = uncamelCaseName.split("-");
for (int i = 0; i < parts.length; i++) {
result += StringUtils.capitalize(parts[i].toLowerCase());
}
return result;
}
public String uncamel(String camelCaseName) {
String result = "";
String[] parts = camelCaseName.split("(?<!^)(?=[A-Z])");
for (int i = 0; i < parts.length; i++) {
result += parts[i].toLowerCase() + (i < parts.length - 1 ? "-" : "");
}
return result;
}
public String friendlyNameFromCamelCase(String camelCaseName) {
return StringUtils.capitalize(uncamel(camelCaseName)).replaceAll("-", " ");
}
public String getClassName(String fullyQualifiedClassName) {
int lastDot = fullyQualifiedClassName.lastIndexOf('.');
return fullyQualifiedClassName.substring(lastDot + 1);
}
public String getPackageName(String fullyQualifiedClassName) {
int lastDot = fullyQualifiedClassName.lastIndexOf('.');
return fullyQualifiedClassName.substring(0, lastDot);
}
/**
* Return the pluralized version of a word.
*
* @param word The word
* @return The pluralized word
*/
public String pluralize(String word) {
if (isUncountable(word)) {
return word;
} else {
for (Inflection inflection : plural) {
if (inflection.match(word)) {
return inflection.replace(word);
}
}
return word;
}
}
/**
* Return the singularized version of a word.
*
* @param word The word
* @return The singularized word
*/
public String singularize(String word) {
if (isUncountable(word)) {
return word;
} else {
for (Inflection inflection : singular) {
if (inflection.match(word)) {
return inflection.replace(word);
}
}
}
return word;
}
/**
* Return true if the word is uncountable.
*
* @param word The word
* @return True if it is uncountable
*/
public boolean isUncountable(String word) {
for (String w : uncountable) {
if (w.equalsIgnoreCase(word)) {
return true;
}
}
return false;
}
public String generateClassName(ExecutableElement executableElement, String append) {
TypeElement parentClass = ElementFilter.typesIn(Arrays.asList(executableElement.getEnclosingElement())).get(0);
String packageName = getPackageName(getBinaryName(parentClass));
String className = StringUtils.capitalize(executableElement.getSimpleName().toString()) + append;
return packageName + "." + className;
}
public String generateClassName(ExecutableElement executableElement, String extraPackage, String append) {
TypeElement parentClass = ElementFilter.typesIn(Arrays.asList(executableElement.getEnclosingElement())).get(0);
String packageName = getPackageName(elements.getBinaryName(parentClass).toString());
String className = StringUtils.capitalize(executableElement.getSimpleName().toString()) + append;
return packageName + extraPackage + "." + className;
}
public String generateClassNameInPackage(Element element, String className) {
Element enclosingElement = element.getEnclosingElement();
String packageName;
if (enclosingElement.getKind() == ElementKind.CLASS) {
packageName = getPackageName(getBinaryName((TypeElement) enclosingElement));
} else if (enclosingElement.getEnclosingElement() != null) {
TypeElement parentClass = ElementFilter.typesIn(Arrays.asList(enclosingElement.getEnclosingElement())).get(0);
packageName = getPackageName(getBinaryName(parentClass));
} else {
// inner enum or parametrized type
DeclaredType declaredType = (DeclaredType) element.asType();
packageName = getPackageName(declaredType.toString());
}
return packageName + "." + className;
}
public String generateClassNameInPackage(TypeElement typeElement, String extraPackage, String className) {
String packageName = getPackageName(getBinaryName(typeElement));
return packageName + extraPackage + "." + className;
}
public String generateModuleObjectRoleKey(TypeElement typeElement) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + "." + className + "ModuleObject";
}
public String generateConnectorObjectRoleKey(TypeElement typeElement) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + "." + className + "Connector";
}
public String generateConnectionParametersRoleKey(TypeElement typeElement) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + "." + className + "ConnectionKey";
}
public String generateConnectionManagerRoleKey(TypeElement typeElement) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + "." + className + "ConnectionManager";
}
public String getBinaryName(TypeElement typeElement) {
if (typeElement instanceof TypeElementImpl) {
typeElement = ((DefaultDevKitTypeElement) typeElement).unWrap();
}
return elements.getBinaryName(typeElement).toString();
}
public String generateConfigDefParserRoleKey(TypeElement typeElement) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + "." + className + "ConfigDefinitionParser";
}
public String generatePoolingProfileDefParserRoleKey(TypeElement typeElement) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + "." + className + "PoolingProfileDefinitionParser";
}
public String generatePojoFactoryKey(TypeElement typeElement) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + "." + className + "Factory";
}
public String generatePoolObjectRoleKey(TypeElement typeElement) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + "." + className + "PoolObject";
}
public String generateClassName(TypeElement typeElement, String extraPackage, String classNameAppend) {
String typeFullName = getBinaryName(typeElement);
String pkg = getPackageName(typeFullName);
String className = getClassName(typeFullName);
return pkg + extraPackage + "." + className + classNameAppend;
}
private static class Inflection {
private String pattern;
private String replacement;
private boolean ignoreCase;
public Inflection(String pattern) {
this(pattern, null, true);
}
public Inflection(String pattern, String replacement) {
this(pattern, replacement, true);
}
public Inflection(String pattern, String replacement, boolean ignoreCase) {
this.pattern = pattern;
this.replacement = replacement;
this.ignoreCase = ignoreCase;
}
/**
* Does the given word match?
*
* @param word The word
* @return True if it matches the inflection pattern
*/
public boolean match(String word) {
int flags = 0;
if (ignoreCase) {
flags = flags | Pattern.CASE_INSENSITIVE;
}
return Pattern.compile(pattern, flags).matcher(word).find();
}
/**
* Replace the word with its pattern.
*
* @param word The word
* @return The result
*/
public String replace(String word) {
int flags = 0;
if (ignoreCase) {
flags = flags | Pattern.CASE_INSENSITIVE;
}
return Pattern.compile(pattern, flags).matcher(word).replaceAll(replacement);
}
}
}