org.nustaq.serialization.FSTClazzLineageInfo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fst Show documentation
Show all versions of fst Show documentation
A fast java serialization drop in-replacement and some serialization based utils such as Structs and OffHeap Memory.
package org.nustaq.serialization;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Represents a ordered class lineage based on the specificity of classes, where specificity is defined as follows:
*
* null has specificity 0
* java.lang.Object has specificity 0
* an interface without any extends clause has specificity 1
* a class or interface has a specificity of 1 + the specificity of the superclass + the sum of the specificity of the implemented interfaces.
*
* @author Odd Moeller 2017-03-08.
*/
public final class FSTClazzLineageInfo {
private static final Class>[] EMPTY_CLASS_ARRAY = new Class>[0];
private static final LineageInfo OBJECT_LINEAGE_INFO = new LineageInfo(new LinkedHashSet>(Collections.singletonList(Object.class)), 0);
private static final ConcurrentMap, LineageInfo> lineageInfos = new ConcurrentHashMap, LineageInfo>();
public static final Comparator SPECIFICITY_CLASS_COMPARATOR = new Comparator() {
@Override
public int compare(final Class c1, final Class c2) {
return getLineageInfo(c2).specificity - getLineageInfo(c1).specificity;
}
};
private FSTClazzLineageInfo() {}
/**
* Returns the specificity of the specified class as defined above.
*/
public static int getSpecificity(final Class> clazz) {
if (clazz == null) return 0;
final LineageInfo lineageInfo = FSTClazzLineageInfo.getLineageInfo(clazz);
return lineageInfo == null ? 0 : lineageInfo.specificity;
}
/**
* Returns the lineage of the specified class ordered by specificity (the class itself is at position 0 since it is most specific in its lineage).
*/
public static Class>[] getLineage(final Class> clazz) {
final LineageInfo lineageInfo = getLineageInfo(clazz);
return lineageInfo == null ? EMPTY_CLASS_ARRAY : lineageInfo.lineage.toArray(new Class>[lineageInfo.lineage.size()]);
}
private static LineageInfo getLineageInfo(final Class> clazz) {
if (clazz == null) return null;
else if (clazz.equals(Object.class)) return OBJECT_LINEAGE_INFO;
final LineageInfo lineageInfo = lineageInfos.get(clazz);
if (lineageInfo != null) {
return lineageInfo;
}
int specificity = 1;
final LinkedHashSet> ancestors = new LinkedHashSet>();
final Class> sc = getSuperclass(clazz);
final LineageInfo sl = getLineageInfo(sc);
if (sl != null) {
ancestors.addAll(sl.lineage);
specificity += sl.specificity;
}
for (final Class> i : getInterfaces(clazz)) {
final LineageInfo il = getLineageInfo(i);
if (il != null) {
ancestors.removeAll(il.lineage);
ancestors.addAll(il.lineage);
specificity += il.specificity;
}
}
final Class>[] array = ancestors.toArray(new Class>[ancestors.size()]);
Arrays.sort(array, SPECIFICITY_CLASS_COMPARATOR);
final LinkedHashSet> lineage = new LinkedHashSet>(array.length + 1);
lineage.add(clazz);
Collections.addAll(lineage, array);
final LineageInfo result = new LineageInfo(lineage, specificity);
lineageInfos.putIfAbsent(clazz, result);
return result;
}
private static Class> getSuperclass(final Class> c) {
if (c == null) return null;
return c.getSuperclass();
}
private static Class>[] getInterfaces(final Class> c) {
if (c == null) return null;
return c.getInterfaces();
}
private static final class LineageInfo {
private final LinkedHashSet> lineage;
private final int specificity;
private LineageInfo(final LinkedHashSet> lineage, final int specificity) {
this.lineage = lineage;
this.specificity = specificity;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy