001package co.codewizards.cloudstore.core.objectfactory; 002 003import java.lang.reflect.ParameterizedType; 004import java.lang.reflect.Type; 005 006/** 007 * Abstract base-class for the much easier implementation of a {@link ClassExtension}. 008 * <p> 009 * It is highly recommended <i>not</i> to implement the interface {@code ClassExtension} directly. Instead, 010 * implementors should always extend this abstract base-class. 011 * <p> 012 * In most cases, an implementation of a {@code ClassExtension} looks simply like this example: 013 * <pre> 014 * public class SsSymlinkClassExtension extends AbstractClassExtension<Symlink, SsSymlink> { 015 * } 016 * </pre> 017 * <p> 018 * It is recommended to use the naming scheme "${extendingClassName}" + "ClassExtension" as shown in 019 * the example above. 020 * 021 * @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co 022 * 023 * @param <T> the type of the base-class. Automatically assigned to the property {@link #getBaseClass() baseClass}. 024 * @param <E> the type of the extending class. Automatically assigned to the property {@link #getExtendingClass() extendingClass}. 025 */ 026public abstract class AbstractClassExtension<T, E extends T> implements ClassExtension<T> { 027 028 private final Class<T> baseClass; 029 030 private final Class<E> extendingClass; 031 032 public AbstractClassExtension() { 033 final ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass(); 034 final Type[] actualTypeArguments = superclass.getActualTypeArguments(); 035 if (actualTypeArguments == null || actualTypeArguments.length < 2) 036 throw new IllegalStateException("Subclass " + getClass().getName() + " has no generic type argument!"); 037 038 @SuppressWarnings("unchecked") 039 final Class<T> c1 = (Class<T>) actualTypeArguments[0]; 040 this.baseClass = c1; 041 if (this.baseClass == null) 042 throw new IllegalStateException("Subclass " + getClass().getName() + " has no generic type argument!"); 043 044 @SuppressWarnings("unchecked") 045 final Class<E> c2 = (Class<E>) actualTypeArguments[1]; 046 this.extendingClass = c2; 047 if (this.extendingClass == null) 048 throw new IllegalStateException("Subclass " + getClass().getName() + " has no generic type argument!"); 049 } 050 051 /** 052 * {@inheritDoc} 053 * <p> 054 * The default implementation in {@link AbstractClassExtension} returns 0. Override and return 055 * either a negative value, if you want to provide a fallback-implementation (that is likely to be 056 * replaced by a different {@code ClassExtension}) or a positive value in order to override 057 * another {@code ClassExtension} (make sure your priority is greater than the other extension's priority). 058 */ 059 @Override 060 public int getPriority() { 061 return 0; 062 } 063 064 @Override 065 public Class<T> getBaseClass() { 066 return baseClass; 067 } 068 069 @Override 070 public Class<E> getExtendingClass() { 071 return extendingClass; 072 } 073 074}