package me.tomassetti.jvm;
import com.google.common.collect.ImmutableSet;
import java.util.Arrays;
import java.util.Set;
public final class JvmNameUtils {
/**
* See http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.9
*/
public static String[] KEYWORDS = new String[]{
"abstract", "continue", "for", "new", "switch",
"assert", "default", "if", "package", "synchronized",
"boolean", "do", "goto", "private", "this",
"break", "double", "implements", "protected", "throw",
"byte", "else", "import", "public", "throws",
"case", "enum", "instanceof", "return", "transient",
"catch", "extends", "int", "short", "try",
"char", "final", "interface", "static", "void",
"class", "finally", "long", "strictfp", "volatile",
"const", "float", "native", "super", "while"
};
private JvmNameUtils() {
// prevent instantiation
}
public static boolean isValidJavaIdentifier(String name){
if (name == null) {
throw new IllegalArgumentException();
}
if (name.isEmpty()) {
return false;
}
if (Arrays.asList(KEYWORDS).contains(name)) {
return false;
}
char firstChar = name.charAt(0);
if (firstChar != '$' && firstChar != '_' && !Character.isLetter(firstChar)) {
return false;
}
for (int i=0; i<name.length(); i++){
char c = name.charAt(i);
if (c != '$' && c != '_' && !Character.isLetter(c) && !Character.isDigit(c)) {
return false;
}
}
return true;
}
public static String canonicalToInternal(String canonicalName) {
return canonicalName.replaceAll("\\.", "/");
}
public static boolean isValidInternalName(String internalName) {
if (internalName == null) {
throw new IllegalArgumentException();
}
if (internalName.isEmpty()) {
return false;
}
// the part would be discarded, we have to check explicitly
if (internalName.endsWith("/")){
return false;
}
String[] parts = internalName.split("/");
for (String part : parts) {
if (!isValidJavaIdentifier(part)) {
return false;
}
}
return true;
}
public static boolean isValidQualifiedName(String name) {
if (name == null) {
throw new IllegalArgumentException();
}
if (name.isEmpty()) {
return false;
}
// the part would be discarded, we have to check explicitly
if (name.endsWith(".")){
return false;
}
String[] parts = name.split("\\.");
for (String part : parts) {
if (!isValidJavaIdentifier(part)) {
return false;
}
}
return true;
}
public static boolean isSimpleName(String name) {
return -1 == name.indexOf('.');
}
public static boolean isPrimitiveTypeName(String name) {
Set<String> names = ImmutableSet.of("boolean", "char", "byte", "short", "int", "long", "float", "double");
return names.contains(name);
}
public static String canonicalToSimple(String qualifiedName) {
String[] parts = qualifiedName.split("\\.");
return parts[parts.length - 1];
}
public static String getPackagePart(String qualifiedName) {
int index = qualifiedName.lastIndexOf('.');
if (index == -1) {
throw new IllegalArgumentException();
}
return qualifiedName.substring(0, index);
}
public static String getSimplePart(String qualifiedName) {
int index = qualifiedName.lastIndexOf('.');
if (index == -1) {
throw new IllegalArgumentException();
}
return qualifiedName.substring(index + 1);
}
public static String canonicalToDescriptor(String canonicalName) {
return "L" + canonicalToInternal(canonicalName) + ";";
}
public static String descriptor(Class<?> clazz) {
if (clazz.isMemberClass()) {
String container = descriptor(clazz.getDeclaringClass());
return container.substring(0, container.length() - 1) + "$" + clazz.getSimpleName() + ";";
} else {
return canonicalToDescriptor(clazz.getCanonicalName());
}
}
public static String internalName(Class<?> clazz) {
if (clazz.isMemberClass()) {
String container = internalName(clazz.getDeclaringClass());
return container + "$" + clazz.getSimpleName();
} else {
return canonicalToInternal(clazz.getCanonicalName());
}
}
}