001package co.codewizards.cloudstore.core.objectfactory; 002 003import java.util.ServiceLoader; 004 005/** 006 * Simple API to use the {@link ObjectFactory}. 007 * <p> 008 * Devs should add the following import: 009 * <pre> 010 * import static co.codewizards.cloudstore.core.objectfactory.ObjectFactoryUtil.*; 011 * </pre> 012 * They can then invoke one of the {@code createObject(...)} methods simply without any prefix. 013 * <p> 014 * In order to register a sub-class as replacement for a certain base-class, implementors have to provide a 015 * {@link ClassExtension} and register it using the {@link ServiceLoader}-mechanism. 016 * <p> 017 * <b>Important:</b> If a certain base-class should be replaceable using this mechanism, <b>all</b> occurrences 018 * of {@code new MyBaseClass(...)} in the entire code-base must be replaced by {@code createObject(MyBaseClass.class, ...)}. 019 * <p> 020 * <b>Important 2:</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 (=> {@link ServiceLoader}). There are situations, though, e.g. data-model-classes 022 * (a.k.a. entities), where services are not possible and {@code ObjectFactoryUtil} + {@code ClassExtension} is the perfect solution. 023 * <p> 024 * 025 * @author Marco หงุ่ยตระกูล-Schulze - marco at codewizards dot co 026 */ 027public class ObjectFactoryUtil { 028 protected ObjectFactoryUtil() { } 029 030 /** 031 * Create an instance of the given class or a sub-class registered as replacement. 032 * <p> 033 * If at least one {@link ClassExtension} is registered for the given class, the {@code ClassExtension} 034 * with the highest {@link ClassExtension#getPriority() priority} is chosen and its 035 * {@link ClassExtension#getExtendingClass() extendingClass} instantiated instead of the base-class passed as {@code clazz}. 036 * <p> 037 * This method always invokes the default constructor (without any parameters). 038 * @param clazz the base-class to be instantiated. Must not be <code>null</code>. 039 * @return the object instantiated either from the given base-class or a sub-class registered via {@link ClassExtension}. 040 * Never <code>null</code>. 041 * @see #createObject(Class, Class[], Object...) 042 */ 043 public static <T> T createObject(final Class<T> clazz) { 044 return ObjectFactory.getInstance().createObject(clazz); 045 } 046 047 /** 048 * Create an instance of the given class or a sub-class registered as replacement. 049 * <p> 050 * If at least one {@link ClassExtension} is registered for the given class, the {@code ClassExtension} 051 * with the highest {@link ClassExtension#getPriority() priority} is chosen and its 052 * {@link ClassExtension#getExtendingClass() extendingClass} instantiated instead of the base-class passed as {@code clazz}. 053 * <p> 054 * This method tries to automatically find the best constructor matching the given parameters. 055 * If multiple constructors might match and they are not semantically the same (only doing some implicit conversions), 056 * you should instead use {@link #createObject(Class, Class[], Object...)} and pass the specific parameter types. 057 * @param clazz the base-class to be instantiated. Must not be <code>null</code>. 058 * @param parameters the parameters to be passed to the constructor. 059 * @return the object instantiated either from the given base-class or a sub-class registered via {@link ClassExtension}. 060 * Never <code>null</code>. 061 * @see #createObject(Class, Class[], Object...) 062 */ 063 public static <T> T createObject(final Class<T> clazz, final Object ... parameters) { 064 return ObjectFactory.getInstance().createObject(clazz, (Class<?>[]) null, parameters); 065 } 066 067 /** 068 * Create an instance of the given class or a sub-class registered as replacement. 069 * <p> 070 * If at least one {@link ClassExtension} is registered for the given class, the {@code ClassExtension} 071 * with the highest {@link ClassExtension#getPriority() priority} is chosen and its 072 * {@link ClassExtension#getExtendingClass() extendingClass} instantiated instead of the base-class passed as {@code clazz}. 073 * <p> 074 * This method invokes the constructor matching exactly the given parameter-types. If {@code parameterTypes} is 075 * <code>null</code>, a matching constructor is searched automatically based on the concrete {@code parameters}. 076 * 077 * @param clazz the base-class to be instantiated. Must not be <code>null</code>. 078 * @param parameterTypes either <code>null</code> or the exact argument-types of the constructor to be invoked. 079 * @param parameters the parameters to be passed to the constructor. 080 * @return the object instantiated either from the given base-class or a sub-class registered via {@link ClassExtension}. 081 * Never <code>null</code>. 082 */ 083 public static <T> T createObject(final Class<T> clazz, final Class<?>[] parameterTypes, final Object ... parameters) { 084 return ObjectFactory.getInstance().createObject(clazz, parameterTypes, parameters); 085 } 086 087 public static <T> Class<? extends T> getExtendingClass(final Class<T> clazz) { 088 return ObjectFactory.getInstance().getExtendingClass(clazz); 089 } 090}