package de.flower.common.util;
import com.google.common.collect.Lists;
import java.util.List;
/**
* http://stackoverflow.com/questions/936684/getting-the-class-name-from-a-static-method-in-java
*
* @author flowerrrr
*/
public final class Clazz {
private Clazz() {
}
/**
* Get the class of the caller in a static method.
*
* @return class
*/
public static Class<?> getClassStatic() {
return getClassStatic(3);
}
public static Class<?> getThisClassStatic(final Class<?> baseClass) {
CurrentClassGetter ccg = new CurrentClassGetter();
final Class[] classContext = ccg.getClassContext2();
int index = -1;
for (int i = 0; i < classContext.length; i++) {
if (classContext[i].equals(baseClass)) {
index = i;
break;
}
}
// search for next class in stack that differs from clazz
for (int i = index + 1; i < classContext.length; i++) {
Class<?> callingClass = classContext[i];
if (!(callingClass.equals(classContext[i-1]) || isSubClass(callingClass, classContext[i - 1]))) {
return classContext[i - 1];
}
}
throw new RuntimeException("This should not happen");
}
public static boolean isSubClass(final Class<?> subClass, final Class<?> baseClass) {
Class<?> tmp = subClass.getSuperclass();
while (tmp != null) {
if (tmp.equals(baseClass)) {
return true;
}
tmp = tmp.getSuperclass();
}
return false;
}
/**
* Returns the class that is calling the caller of this method.
* <p/>
* If A has a method that calls this method and B calls A's method, then
* B is returned.
*
* @param callee
* @return
*/
public static Class<?> getCallingClassStatic(final Class<?> callee) {
CurrentClassGetter ccg = new CurrentClassGetter();
final Class[] classContext = ccg.getClassContext2();
int index = -1;
for (int i = 0; i < classContext.length; i++) {
if (classContext[i].equals(callee)) {
index = i;
break;
}
}
// search for next class in stack that differs from clazz
for (int i = index; i < classContext.length; i++) {
Class<?> callingClass = classContext[i];
if (!callingClass.equals(callee)) {
return callingClass;
}
}
throw new RuntimeException("This should not happen");
}
public static Class<?> getClassStatic(int frame) {
// noinspection RawUseOfParameterizedType
CurrentClassGetter ccg = new CurrentClassGetter();
return ccg.getClass(frame);
}
@Deprecated // has issues when used with groovy compiled code
public static String getShortName(final Class<?> clazz) {
if (isAnonymousClass(clazz)) {
return clazz.getName().substring(clazz.getName().lastIndexOf(".") + 1);
} else {
return clazz.getSimpleName();
}
}
private static class CurrentClassGetter extends SecurityManager {
public Class getClass(int frame) {
final Class[] classContext = getClassContext();
return classContext[frame];
}
public Class[] getClassContext2() {
return getClassContext();
}
}
/**
* Method currently does not return correct results for groovy-compiled classes.
* See http://jira.codehaus.org/browse/GROOVY-4980.
*/
@Deprecated // has issues when used with groovy compiled code
public static boolean isAnonymousClass(Class<?> clazz) {
boolean hasEnclosingClass = clazz.getEnclosingClass() != null;
boolean nameContainsDollar = clazz.getName().contains("$");
boolean simpleNameEmpty = clazz.getSimpleName().equals("");
boolean isAnonymousClass = hasEnclosingClass && nameContainsDollar && simpleNameEmpty;
if (isAnonymousClass != clazz.isAnonymousClass()) {
throw new IllegalStateException("Something wrong");
}
return clazz.isAnonymousClass();
}
@Deprecated // has issues when used with groovy compiled code
public static Class<?> getSuperClass(Class<?> anonymousClass) {
Check.isTrue(isAnonymousClass(anonymousClass));
return anonymousClass.getSuperclass();
}
/**
* Returns class hierarchy. Starts at object.getClass() and descends down to baseClass.
*
*/
public static List<Class<?>> getClassList(Class<?> subClass, Class<?> baseClass) {
List<Class<?>> classes = Lists.newArrayList();
Class<?> c = subClass;
classes.add(c);
while (!c.equals(baseClass)) {
c = c.getSuperclass();
if (c == null) {
throw new IllegalArgumentException(String.format("Baseclass [%s] not part of type hierarchy of [%s]", baseClass, subClass));
}
classes.add(c);
}
return classes;
}
}