001package co.codewizards.cloudstore.core.objectfactory;
002
003import java.util.ServiceLoader;
004
005/**
006 * A {@code ClassExtension} declares that a sub-class must be instantiated instead of a certain base-class.
007 * <p>
008 * In order to register a sub-class as replacement for a certain base-class, implementors have to provide a
009 * {@code ClassExtension} and register it using the {@link ServiceLoader}-mechanism. This means, they must place a file
010 * named {@code co.codewizards.cloudstore.core.objectfactory.ClassExtension} into {@code src/main/resources/META-INF/services/}
011 * in their extension-project and enlist their {@code ClassExtension}-implementation there.
012 * <p>
013 * <b>Important:</b> It is recommended <i>not</i> to directly implement this interface, but to sub-class {@link AbstractClassExtension}
014 * instead.
015 * <p>
016 * <b>Important 2:</b> If a certain base-class should be replaceable using this mechanism, <b>all</b> occurrences
017 * of {@code new MyBaseClass(...)} in the entire code-base must be replaced by
018 * {@link ObjectFactoryUtil#createObject(Class) createObject(MyBaseClass.class, ...)}.
019 * <p>
020 * <b>Important 3:</b> It is urgently recommended <i>not</i> to use this approach, whenever it is possible to use a better solution,
021 * preferably a well-defined service (=&gt; {@link ServiceLoader}). There are situations, though, e.g. data-model-classes
022 * (a.k.a. entities), where services are not possible and {@link ObjectFactoryUtil} + {@code ClassExtension} is the perfect solution.
023 *
024 * @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co
025 *
026 * @param <T> the type of the base-class to be extended (i.e. replaced in all instantiations) by a certain sub-class.
027 */
028public interface ClassExtension<T> {
029
030        /**
031         * Gets the priority of this extension.
032         * <p>
033         * If there are multiple {@code ClassExtension}-implementations for the same {@link #getBaseClass() baseClass}, the
034         * extension with the highest priority (i.e the greatest number returned here) is chosen.
035         * @return the priority of this extension. Might be negative, 0 or positive.
036         */
037        int getPriority();
038
039        /**
040         * Gets the base-class to be extended by instantiating a sub-class instead.
041         * @return the base-class to be replaced in all instantiations. Never <code>null</code>.
042         */
043        Class<T> getBaseClass();
044
045        /**
046         * Gets the sub-class extending the {@link #getBaseClass() baseClass} to be instantiated whenever
047         * a new instance of the base-class is requested.
048         * @return the sub-class to be instantiated instead of the {@link #getBaseClass() baseClass}. Never <code>null</code>.
049         */
050        Class<? extends T> getExtendingClass();
051}