package co.codewizards.cloudstore.core.objectfactory;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Abstract base-class for the much easier implementation of a {@link ClassExtension}.
* <p>
* It is highly recommended <i>not</i> to implement the interface {@code ClassExtension} directly. Instead,
* implementors should always extend this abstract base-class.
* <p>
* In most cases, an implementation of a {@code ClassExtension} looks simply like this example:
* <pre>
* public class SsSymlinkClassExtension extends AbstractClassExtension<Symlink, SsSymlink> {
* }
* </pre>
* <p>
* It is recommended to use the naming scheme "${extendingClassName}" + "ClassExtension" as shown in
* the example above.
*
* @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co
*
* @param <T> the type of the base-class. Automatically assigned to the property {@link #getBaseClass() baseClass}.
* @param <E> the type of the extending class. Automatically assigned to the property {@link #getExtendingClass() extendingClass}.
*/
public abstract class AbstractClassExtension<T, E extends T> implements ClassExtension<T> {
private final Class<T> baseClass;
private final Class<E> extendingClass;
public AbstractClassExtension() {
final ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
final Type[] actualTypeArguments = superclass.getActualTypeArguments();
if (actualTypeArguments == null || actualTypeArguments.length < 2)
throw new IllegalStateException("Subclass " + getClass().getName() + " has no generic type argument!");
@SuppressWarnings("unchecked")
final Class<T> c1 = (Class<T>) actualTypeArguments[0];
this.baseClass = c1;
if (this.baseClass == null)
throw new IllegalStateException("Subclass " + getClass().getName() + " has no generic type argument!");
@SuppressWarnings("unchecked")
final Class<E> c2 = (Class<E>) actualTypeArguments[1];
this.extendingClass = c2;
if (this.extendingClass == null)
throw new IllegalStateException("Subclass " + getClass().getName() + " has no generic type argument!");
}
/**
* {@inheritDoc}
* <p>
* The default implementation in {@link AbstractClassExtension} returns 0. Override and return
* either a negative value, if you want to provide a fallback-implementation (that is likely to be
* replaced by a different {@code ClassExtension}) or a positive value in order to override
* another {@code ClassExtension} (make sure your priority is greater than the other extension's priority).
*/
@Override
public int getPriority() {
return 0;
}
@Override
public Class<T> getBaseClass() {
return baseClass;
}
@Override
public Class<E> getExtendingClass() {
return extendingClass;
}
}