Classes - Utilities to work with class hierarchies
This commit is contained in:
parent
604967af9c
commit
48252c20b5
4 changed files with 197 additions and 0 deletions
80
src/main/java/info/ebenoit/ebul/reflection/Classes.java
Normal file
80
src/main/java/info/ebenoit/ebul/reflection/Classes.java
Normal file
|
@ -0,0 +1,80 @@
|
|||
package info.ebenoit.ebul.reflection;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Utility methods to query classes and interfaces.
|
||||
*
|
||||
* @author <a href="mailto:ebenoit@ebenoit.info">E. Benoît</a>
|
||||
*/
|
||||
public final class Classes
|
||||
{
|
||||
|
||||
/**
|
||||
* List all classes a class inherits from.
|
||||
*
|
||||
* @param cls
|
||||
* the class to examine
|
||||
* @return the list of ancestors, including the class itself
|
||||
*/
|
||||
public static < T > ArrayList< Class< ? super T > > getAncestors( final Class< T > cls )
|
||||
{
|
||||
final ArrayList< Class< ? super T > > result = new ArrayList< >( );
|
||||
Class< ? super T > current = cls;
|
||||
while ( current != null ) {
|
||||
result.add( current );
|
||||
current = current.getSuperclass( );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find all types a class is compatible with: itself, its ancestors, and all implemented interfaces.
|
||||
*
|
||||
* @param cls
|
||||
* the class to examine
|
||||
* @return the set of compatible types
|
||||
*/
|
||||
public static HashSet< Class< ? > > getAllTypes( final Class< ? > cls )
|
||||
{
|
||||
final HashSet< Class< ? > > found = new HashSet< >( );
|
||||
Class< ? > current = cls;
|
||||
while ( current != null ) {
|
||||
found.add( current );
|
||||
Classes.addInterfaces( current , found );
|
||||
current = current.getSuperclass( );
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal method used by {@link #getAllTypes(Class)} to add all interfaces recursively.
|
||||
*
|
||||
* @param current
|
||||
* the class or interface being examined
|
||||
* @param found
|
||||
* the result
|
||||
*/
|
||||
private static void addInterfaces( final Class< ? > current , final HashSet< Class< ? > > found )
|
||||
{
|
||||
if ( current == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Class< ? >[] interfaces = current.getInterfaces( );
|
||||
final int len = interfaces.length;
|
||||
for ( int i = 0 ; i < len ; i++ ) {
|
||||
final Class< ? > itf = interfaces[ i ];
|
||||
if ( found.add( itf ) ) {
|
||||
Classes.addInterfaces( itf , found );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
9
src/test/java/info/ebenoit/ebul/reflection/CTest6.java
Normal file
9
src/test/java/info/ebenoit/ebul/reflection/CTest6.java
Normal file
|
@ -0,0 +1,9 @@
|
|||
package info.ebenoit.ebul.reflection;
|
||||
|
||||
|
||||
public class CTest6
|
||||
extends CTest5
|
||||
implements ITest2
|
||||
{
|
||||
// EMPTY
|
||||
}
|
7
src/test/java/info/ebenoit/ebul/reflection/ITest2.java
Normal file
7
src/test/java/info/ebenoit/ebul/reflection/ITest2.java
Normal file
|
@ -0,0 +1,7 @@
|
|||
package info.ebenoit.ebul.reflection;
|
||||
|
||||
public interface ITest2
|
||||
extends ITest1
|
||||
{
|
||||
|
||||
}
|
101
src/test/java/info/ebenoit/ebul/reflection/TestClasses.java
Normal file
101
src/test/java/info/ebenoit/ebul/reflection/TestClasses.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
package info.ebenoit.ebul.reflection;
|
||||
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
|
||||
/** Tests for {@link Classes} */
|
||||
public class TestClasses
|
||||
{
|
||||
|
||||
/** Test: {@link Classes#getAncestors(Class)} called on Object.class */
|
||||
@Test
|
||||
public void getAncestorsObject( )
|
||||
{
|
||||
@SuppressWarnings( "unchecked" )
|
||||
final Class< ? super Object > expected[] = new Class[] {
|
||||
Object.class
|
||||
};
|
||||
final Class< ? super Object > result[] = Classes.getAncestors( Object.class ).toArray( expected );
|
||||
|
||||
Assert.assertArrayEquals( expected , result );
|
||||
}
|
||||
|
||||
|
||||
/** Test: {@link Classes#getAncestors(Class)} called on an actual hierarchy */
|
||||
@Test
|
||||
public void getAncestors( )
|
||||
{
|
||||
@SuppressWarnings( "unchecked" )
|
||||
final Class< ? super CTest4 > expected[] = new Class[] {
|
||||
CTest4.class , CTest3.class , CTest2.class , CTest1.class , Object.class
|
||||
};
|
||||
final Class< ? super CTest4 > result[] = Classes.getAncestors( CTest4.class ).toArray( expected );
|
||||
|
||||
Assert.assertArrayEquals( expected , result );
|
||||
}
|
||||
|
||||
|
||||
/** Test: {@link Classes#getAllTypes(Class)} called on Object.class */
|
||||
@Test
|
||||
public void getAllTypesObject( )
|
||||
{
|
||||
final Class< ? > expected[] = new Class[] {
|
||||
Object.class
|
||||
};
|
||||
final Class< ? > result[] = Classes.getAllTypes( Object.class ).toArray( expected );
|
||||
|
||||
Assert.assertArrayEquals( expected , result );
|
||||
}
|
||||
|
||||
|
||||
/** Test: {@link Classes#getAllTypes(Class)} called on a hierarchy with no implemented interfaces */
|
||||
@Test
|
||||
public void getAllTypesHierarchy( )
|
||||
{
|
||||
final HashSet< Class< ? > > expected = new HashSet< Class< ? > >( );
|
||||
expected.add( Object.class );
|
||||
expected.add( CTest1.class );
|
||||
expected.add( CTest2.class );
|
||||
expected.add( CTest3.class );
|
||||
expected.add( CTest4.class );
|
||||
|
||||
final HashSet< Class< ? > > result = Classes.getAllTypes( CTest4.class );
|
||||
Assert.assertEquals( expected , result );
|
||||
}
|
||||
|
||||
|
||||
/** Test: {@link Classes#getAllTypes(Class)} called on a hierarchy with one implemented interfaces */
|
||||
@Test
|
||||
public void getAllTypesInterface( )
|
||||
{
|
||||
final HashSet< Class< ? > > expected = new HashSet< Class< ? > >( );
|
||||
expected.add( Object.class );
|
||||
expected.add( ITest1.class );
|
||||
expected.add( CTest5.class );
|
||||
|
||||
final HashSet< Class< ? > > result = Classes.getAllTypes( CTest5.class );
|
||||
Assert.assertEquals( expected , result );
|
||||
}
|
||||
|
||||
|
||||
/** Test: {@link Classes#getAllTypes(Class)} called on a hierarchy with redundant interfaces */
|
||||
@Test
|
||||
public void getAllTypesInterfaces( )
|
||||
{
|
||||
final HashSet< Class< ? > > expected = new HashSet< Class< ? > >( );
|
||||
expected.add( Object.class );
|
||||
expected.add( ITest1.class );
|
||||
expected.add( ITest2.class );
|
||||
expected.add( CTest5.class );
|
||||
expected.add( CTest6.class );
|
||||
|
||||
final HashSet< Class< ? > > result = Classes.getAllTypes( CTest6.class );
|
||||
Assert.assertEquals( expected , result );
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue