diff --git a/integration-test/src/test/java/uk/gov/justice/generation/pojo/integration/utils/GeneratorUtil.java b/integration-test/src/test/java/uk/gov/justice/generation/pojo/integration/utils/GeneratorUtil.java index a3a706a..705666a 100644 --- a/integration-test/src/test/java/uk/gov/justice/generation/pojo/integration/utils/GeneratorUtil.java +++ b/integration-test/src/test/java/uk/gov/justice/generation/pojo/integration/utils/GeneratorUtil.java @@ -63,7 +63,7 @@ public class GeneratorUtil { ); private List typeModifyingPlugins = asList( new SupportJavaOptionalsPlugin(), - new CustomReturnTypePlugin()); + CustomReturnTypePlugin.create()); public GeneratorUtil withIgnoredClassNames(final List ignoredClassNames) { this.ignoredClassNames = ignoredClassNames; diff --git a/pojo-event-annotation-plugin/src/main/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddEventAnnotationToClassPlugin.java b/pojo-event-annotation-plugin/src/main/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddEventAnnotationToClassPlugin.java index 424b7a9..e027bc0 100644 --- a/pojo-event-annotation-plugin/src/main/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddEventAnnotationToClassPlugin.java +++ b/pojo-event-annotation-plugin/src/main/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddEventAnnotationToClassPlugin.java @@ -8,7 +8,7 @@ /** * Plugin for adding the {@link Event} annotation to the top of the root POJO. - * The name of the event will be taked from the json schema document + * The name of the event will be taken from the json schema document */ public class AddEventAnnotationToClassPlugin implements ClassModifyingPlugin { diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/SchemaPojoGenerator.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/SchemaPojoGenerator.java index e0c814d..5ec42ee 100644 --- a/pojo-generator-core/src/main/java/uk/gov/justice/generation/SchemaPojoGenerator.java +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/SchemaPojoGenerator.java @@ -10,6 +10,7 @@ import uk.gov.justice.generation.pojo.generators.TypeNameProvider; import uk.gov.justice.generation.pojo.plugin.PluginProvider; import uk.gov.justice.generation.pojo.plugin.PluginProviderFactory; +import uk.gov.justice.generation.pojo.plugin.PluginProviderFactoryFactory; import uk.gov.justice.generation.pojo.plugin.TypeNamePluginProcessor; import uk.gov.justice.generation.pojo.plugin.classmodifying.PluginContext; import uk.gov.justice.generation.pojo.visitable.VisitableFactory; @@ -44,6 +45,7 @@ public class SchemaPojoGenerator implements Generator { private final SchemaLoader schemaLoader = new SchemaLoader(); private final VisitableFactory visitableFactory = new VisitableFactory(); private final JavaFileSimpleNameLister javaFileSimpleNameLister = new JavaFileSimpleNameLister(); + private final PluginProviderFactoryFactory pluginProviderFactoryFactory = new PluginProviderFactoryFactory(); /** * Run the pojo generation based on the specified json schema file @@ -80,7 +82,7 @@ public void run(final File jsonSchemaFile, final GeneratorConfig generatorConfig } private PluginProvider createPluginProvider(final GeneratorConfig generatorConfig) { - final PluginProviderFactory pluginProviderFactory = new PluginProviderFactory(); + final PluginProviderFactory pluginProviderFactory = pluginProviderFactoryFactory.create(); return pluginProviderFactory.createFor(generatorConfig); } diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/FactoryMethod.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/FactoryMethod.java new file mode 100644 index 0000000..ac3c2d5 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/FactoryMethod.java @@ -0,0 +1,18 @@ +package uk.gov.justice.generation.pojo.plugin; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Marks a public static method on a plugin as a factory method for creating an instance + * of the plugin + */ +@Documented +@Target(METHOD) +@Retention(RUNTIME) +public @interface FactoryMethod { +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactory.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactory.java index c843c93..47823fc 100644 --- a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactory.java +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactory.java @@ -1,23 +1,19 @@ package uk.gov.justice.generation.pojo.plugin; -import static java.lang.String.format; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.toList; - import uk.gov.justice.generation.pojo.plugin.classmodifying.AddFieldsAndMethodsToClassPlugin; import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; import uk.gov.justice.generation.pojo.plugin.classmodifying.GenerateBuilderForClassPlugin; -import uk.gov.justice.generation.pojo.plugin.classmodifying.builder.BuilderGeneratorFactory; -import uk.gov.justice.generation.pojo.plugin.namegeneratable.NameGeneratablePlugin; -import uk.gov.justice.generation.pojo.plugin.namegeneratable.RootNameGeneratorPlugin; +import uk.gov.justice.generation.pojo.plugin.factory.AllPluginsInstantiator; +import uk.gov.justice.generation.pojo.plugin.factory.ClassModifyingPluginsSelector; +import uk.gov.justice.generation.pojo.plugin.factory.NameGeneratingPluginFactory; +import uk.gov.justice.generation.pojo.plugin.factory.PluginTypeSorter; +import uk.gov.justice.generation.pojo.plugin.factory.PluginsFromClassnameListFactory; +import uk.gov.justice.generation.pojo.plugin.factory.TypeModifyingPluginsSelector; import uk.gov.justice.generation.pojo.plugin.typemodifying.TypeModifyingPlugin; import uk.gov.justice.maven.generator.io.files.parser.core.GeneratorConfig; import java.util.List; import java.util.Map; -import java.util.stream.Stream; /** * Creates a {@link PluginProvider} for both {@link ClassModifyingPlugin} and {@link @@ -72,141 +68,45 @@ */ public class PluginProviderFactory { - private static final String EXCLUDE_DEFAULT_PROPERTY = "excludeDefaultPlugins"; - private static final String PLUGINS_PROPERTY = "plugins"; - - private static final Class CLASS_MODIFYING_PLUGIN = ClassModifyingPlugin.class; - private static final Class TYPE_MODIFYING_PLUGIN = TypeModifyingPlugin.class; - private static final Class NAME_GENERATABLE_PLUGIN = NameGeneratablePlugin.class; - - private static final String UNABLE_TO_CREATE_INSTANCE_MESSAGE = "Unable to create instance of pojo plugin with class name %s"; - private static final String INCORRECT_CLASS_TYPE_MESSAGE = "Incorrect Class Type, Class name: %s, does not implement ClassModifyingPlugin or TypeModifyingPlugin or NameGeneratablePlugin."; - private static final int FIRST_INDEX = 0; + private final NameGeneratingPluginFactory nameGeneratingPluginFactory; + private final ClassModifyingPluginsSelector classModifyingPluginsSelector; + private final TypeModifyingPluginsSelector typeModifyingPluginsSelector; + private final PluginTypeSorter pluginTypeSorter; + private final AllPluginsInstantiator allPluginsInstantiator; + private final PluginsFromClassnameListFactory parsePluginNames; + + public PluginProviderFactory( + final NameGeneratingPluginFactory nameGeneratingPluginFactory, + final ClassModifyingPluginsSelector classModifyingPluginsSelector, + final TypeModifyingPluginsSelector typeModifyingPluginsSelector, + final PluginTypeSorter pluginTypeSorter, + final AllPluginsInstantiator allPluginsInstantiator, + final PluginsFromClassnameListFactory parsePluginNames) { + this.nameGeneratingPluginFactory = nameGeneratingPluginFactory; + this.classModifyingPluginsSelector = classModifyingPluginsSelector; + this.typeModifyingPluginsSelector = typeModifyingPluginsSelector; + this.pluginTypeSorter = pluginTypeSorter; + this.allPluginsInstantiator = allPluginsInstantiator; + this.parsePluginNames = parsePluginNames; + } /** * Create a {@link PluginProvider} using the settings from the {@link GeneratorConfig} * - * @param generatorConfig the generatorConfig suppying the generatorProperties + * @param generatorConfig the generatorConfig supplying the generatorProperties * @return a {@link PluginProvider} instance */ public PluginProvider createFor(final GeneratorConfig generatorConfig) { - final Map generatorProperties = generatorConfig.getGeneratorProperties(); - final Map, List> pluginTypes = partitionPluginsAccordingToType(generatorProperties); - - return new ModifyingPluginProvider( - defaultAndUserDefinedClassModifyingPlugins(generatorProperties, pluginTypes), - typeModifyingPlugins(pluginTypes), - defaultOrUserDefinedNameGeneratablePlugin(pluginTypes)); - } - - private NameGeneratablePlugin defaultOrUserDefinedNameGeneratablePlugin(final Map, List> pluginTypes) { - if (pluginTypes.containsKey(NAME_GENERATABLE_PLUGIN)) { - final List nameGeneratablePlugins = pluginTypes.get(NAME_GENERATABLE_PLUGIN); - - if (nameGeneratablePlugins.size() > 1) { - final List pluginNames = nameGeneratablePlugins.stream().map(plugin -> plugin.getClass().getSimpleName()).collect(toList()); - throw new PluginProviderException(format("Multiple NameGeneratablePlugin identified, please supply only one. List: %s", pluginNames)); - } - - return (NameGeneratablePlugin) nameGeneratablePlugins.get(FIRST_INDEX); - } - - return new RootNameGeneratorPlugin(); - } - - private Map, List> partitionPluginsAccordingToType(final Map generatorProperties) { - return allInstancesOfPluginsFrom(generatorProperties) - .collect(groupingBy(this::groupByPluginInterface)); - } - - private Class groupByPluginInterface(final Object plugin) { - - final List> classList = asList(plugin.getClass().getInterfaces()); - - if (classList.contains(CLASS_MODIFYING_PLUGIN)) { - return CLASS_MODIFYING_PLUGIN; - } - - if (classList.contains(TYPE_MODIFYING_PLUGIN)) { - return TYPE_MODIFYING_PLUGIN; - } - - if (classList.contains(NAME_GENERATABLE_PLUGIN)) { - return NAME_GENERATABLE_PLUGIN; - } - - throw new PluginProviderException(format(INCORRECT_CLASS_TYPE_MESSAGE, plugin.getClass().getName())); - } - - private List defaultAndUserDefinedClassModifyingPlugins(final Map generatorProperties, - final Map, List> pluginTypes) { - return Stream - .concat( - defaultClassModifyingPlugins(generatorProperties), - userDefinedClassModifyingPlugins(pluginTypes)) - .collect(toList()); - } - - private List typeModifyingPlugins(final Map, List> pluginTypes) { - if (pluginTypes.containsKey(TYPE_MODIFYING_PLUGIN)) { - return pluginTypes.get(TYPE_MODIFYING_PLUGIN) - .stream() - .map(plugin -> (TypeModifyingPlugin) plugin) - .collect(toList()); - } - - return emptyList(); - } - private Stream userDefinedClassModifyingPlugins(final Map, List> pluginTypes) { - if (pluginTypes.containsKey(CLASS_MODIFYING_PLUGIN)) { - return pluginTypes.get(CLASS_MODIFYING_PLUGIN) - .stream() - .map(plugin -> (ClassModifyingPlugin) plugin); - } - - return Stream.empty(); - } - - private Stream defaultClassModifyingPlugins(final Map generatorProperties) { - if (isExcludeDefaultPlugins(generatorProperties)) { - return Stream.empty(); - } - - return Stream.of( - new AddFieldsAndMethodsToClassPlugin(), - new GenerateBuilderForClassPlugin(new BuilderGeneratorFactory())); - } - - private boolean isExcludeDefaultPlugins(final Map generatorProperties) { - if (generatorProperties.containsKey(EXCLUDE_DEFAULT_PROPERTY)) { - return Boolean.valueOf(generatorProperties.get(EXCLUDE_DEFAULT_PROPERTY)); - } - - return false; - } - - private Stream allInstancesOfPluginsFrom(final Map generatorProperties) { - if (generatorProperties.containsKey(PLUGINS_PROPERTY)) { - final String pluginValues = generatorProperties.get(PLUGINS_PROPERTY); - - if (!pluginValues.isEmpty()) { - final String[] plugins = pluginValues.split(","); - - return Stream.of(plugins) - .map(this::pluginInstance); - } - } - - return Stream.empty(); - } + final Map generatorProperties = generatorConfig.getGeneratorProperties(); + final List pluginNames = parsePluginNames.parsePluginNames(generatorProperties); + final List plugins = allPluginsInstantiator.instantiate(pluginNames); - private Object pluginInstance(final String className) { + final Map, List> pluginTypes = pluginTypeSorter.sortByType(plugins); - try { - return Class.forName(className.trim()).newInstance(); - } catch (final InstantiationException | IllegalAccessException | ClassNotFoundException e) { - throw new PluginProviderException(format(UNABLE_TO_CREATE_INSTANCE_MESSAGE, className), e); - } + return new ModifyingPluginProvider( + classModifyingPluginsSelector.selectFrom(pluginTypes, generatorProperties), + typeModifyingPluginsSelector.selectFrom(pluginTypes), + nameGeneratingPluginFactory.create(pluginTypes)); } } diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryFactory.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryFactory.java new file mode 100644 index 0000000..c95d456 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryFactory.java @@ -0,0 +1,30 @@ +package uk.gov.justice.generation.pojo.plugin; + +import uk.gov.justice.generation.pojo.plugin.factory.AllPluginsInstantiator; +import uk.gov.justice.generation.pojo.plugin.factory.ClassModifyingPluginsSelector; +import uk.gov.justice.generation.pojo.plugin.factory.DefaultPluginsProvider; +import uk.gov.justice.generation.pojo.plugin.factory.ExcludeDefaultPluginsSwitch; +import uk.gov.justice.generation.pojo.plugin.factory.Instantiator; +import uk.gov.justice.generation.pojo.plugin.factory.NameGeneratingPluginFactory; +import uk.gov.justice.generation.pojo.plugin.factory.PluginInstantiator; +import uk.gov.justice.generation.pojo.plugin.factory.PluginTypeSorter; +import uk.gov.justice.generation.pojo.plugin.factory.PluginsFromClassnameListFactory; +import uk.gov.justice.generation.pojo.plugin.factory.TypeModifyingPluginsSelector; + +public class PluginProviderFactoryFactory { + + public PluginProviderFactory create() { + + final ExcludeDefaultPluginsSwitch excludeDefaultPluginsSwitch = new ExcludeDefaultPluginsSwitch(); + final DefaultPluginsProvider defaultPluginsProvider = new DefaultPluginsProvider(); + + return new PluginProviderFactory( + new NameGeneratingPluginFactory(), + new ClassModifyingPluginsSelector(excludeDefaultPluginsSwitch, defaultPluginsProvider), + new TypeModifyingPluginsSelector(), + new PluginTypeSorter(), + new AllPluginsInstantiator(new PluginInstantiator(new Instantiator())), + new PluginsFromClassnameListFactory() + ); + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddHashcodeAndEqualsPlugin.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddHashcodeAndEqualsPlugin.java index e48169e..601727e 100644 --- a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddHashcodeAndEqualsPlugin.java +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddHashcodeAndEqualsPlugin.java @@ -10,6 +10,7 @@ import uk.gov.justice.generation.pojo.dom.ClassDefinition; import uk.gov.justice.generation.pojo.dom.Definition; +import uk.gov.justice.generation.pojo.plugin.FactoryMethod; import uk.gov.justice.generation.pojo.plugin.classmodifying.properties.AdditionalPropertiesDeterminer; import java.util.List; @@ -42,6 +43,11 @@ public AddHashcodeAndEqualsPlugin(final AdditionalPropertiesDeterminer additiona this.additionalPropertiesDeterminer = additionalPropertiesDeterminer; } + @FactoryMethod + public static AddHashcodeAndEqualsPlugin newInstance() { + return new AddHashcodeAndEqualsPlugin(new AdditionalPropertiesDeterminer()); + } + @Override public TypeSpec.Builder generateWith( final TypeSpec.Builder classBuilder, diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/AllPluginsInstantiator.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/AllPluginsInstantiator.java new file mode 100644 index 0000000..9a86f09 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/AllPluginsInstantiator.java @@ -0,0 +1,21 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.stream.Collectors.toList; + +import java.util.List; + +public class AllPluginsInstantiator { + + private final PluginInstantiator pluginInstantiator; + + public AllPluginsInstantiator(final PluginInstantiator pluginInstantiator) { + this.pluginInstantiator = pluginInstantiator; + } + + public List instantiate(final List pluginNames) { + return pluginNames + .stream() + .map(pluginInstantiator::instantiate) + .collect(toList()); + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/ClassModifyingPluginsSelector.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/ClassModifyingPluginsSelector.java new file mode 100644 index 0000000..a145975 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/ClassModifyingPluginsSelector.java @@ -0,0 +1,50 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.stream.Collectors.toList; +import static java.util.stream.Stream.concat; + +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; + +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +public class ClassModifyingPluginsSelector { + + private static final Class CLASS_MODIFYING_PLUGIN = ClassModifyingPlugin.class; + + private final ExcludeDefaultPluginsSwitch excludeDefaultPluginsSwitch; + private final DefaultPluginsProvider defaultPluginsProvider; + + public ClassModifyingPluginsSelector( + final ExcludeDefaultPluginsSwitch excludeDefaultPluginsSwitch, + final DefaultPluginsProvider defaultPluginsProvider) { + this.excludeDefaultPluginsSwitch = excludeDefaultPluginsSwitch; + this.defaultPluginsProvider = defaultPluginsProvider; + } + + public List selectFrom(final Map, List> pluginTypes, final Map generatorProperties) { + return concat( + defaultClassModifyingPlugins(generatorProperties), + userDefinedClassModifyingPlugins(pluginTypes) + ).collect(toList()); + } + + private Stream userDefinedClassModifyingPlugins(final Map, List> pluginTypes) { + if (pluginTypes.containsKey(CLASS_MODIFYING_PLUGIN)) { + return pluginTypes.get(CLASS_MODIFYING_PLUGIN) + .stream() + .map(plugin -> (ClassModifyingPlugin) plugin); + } + + return Stream.empty(); + } + + private Stream defaultClassModifyingPlugins(final Map generatorProperties) { + if (excludeDefaultPluginsSwitch.shouldExcludeDefaultPlugins(generatorProperties)) { + return Stream.empty(); + } + + return defaultPluginsProvider.getDefaultPlugins().stream(); + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/DefaultPluginsProvider.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/DefaultPluginsProvider.java new file mode 100644 index 0000000..4d78dc8 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/DefaultPluginsProvider.java @@ -0,0 +1,20 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.Arrays.asList; + +import uk.gov.justice.generation.pojo.plugin.classmodifying.AddFieldsAndMethodsToClassPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.GenerateBuilderForClassPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.builder.BuilderGeneratorFactory; + +import java.util.List; + +public class DefaultPluginsProvider { + + public List getDefaultPlugins() { + return asList( + new AddFieldsAndMethodsToClassPlugin(), + new GenerateBuilderForClassPlugin(new BuilderGeneratorFactory()) + ); + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/ExcludeDefaultPluginsSwitch.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/ExcludeDefaultPluginsSwitch.java new file mode 100644 index 0000000..14f2b03 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/ExcludeDefaultPluginsSwitch.java @@ -0,0 +1,18 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.lang.Boolean.valueOf; + +import java.util.Map; + +public class ExcludeDefaultPluginsSwitch { + + private static final String EXCLUDE_DEFAULT_PROPERTY = "excludeDefaultPlugins"; + + public boolean shouldExcludeDefaultPlugins(final Map generatorProperties) { + if (generatorProperties.containsKey(EXCLUDE_DEFAULT_PROPERTY)) { + return valueOf(generatorProperties.get(EXCLUDE_DEFAULT_PROPERTY)); + } + + return false; + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/Instantiator.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/Instantiator.java new file mode 100644 index 0000000..f86bc6d --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/Instantiator.java @@ -0,0 +1,36 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.lang.String.format; + +import uk.gov.justice.generation.pojo.plugin.PluginProviderException; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class Instantiator { + + public Object instantiate(final Class aClass) { + try { + return aClass.newInstance(); + } catch (final InstantiationException | IllegalAccessException e) { + throw new PluginProviderException(format("Unable to create new instance of class %s", aClass.getName()), e); + } + } + + public Object invokeStaticMethod(final Method method, final Class owner) { + try { + return method.invoke(null); + } catch (final IllegalAccessException | InvocationTargetException e) { + throw new PluginProviderException(format("Unable to invoke method %s on class %s", method.getName(), owner.getName()), e); + } + } + + public Class classForName(final String className) { + try { + final String trim = className.trim(); + return Class.forName(trim); + } catch (final ClassNotFoundException e) { + throw new PluginProviderException(format("Unable to create class %s", className), e); + } + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/NameGeneratingPluginFactory.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/NameGeneratingPluginFactory.java new file mode 100644 index 0000000..0535196 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/NameGeneratingPluginFactory.java @@ -0,0 +1,32 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.lang.String.format; +import static java.util.stream.Collectors.toList; + +import uk.gov.justice.generation.pojo.plugin.PluginProviderException; +import uk.gov.justice.generation.pojo.plugin.namegeneratable.NameGeneratablePlugin; +import uk.gov.justice.generation.pojo.plugin.namegeneratable.RootNameGeneratorPlugin; + +import java.util.List; +import java.util.Map; + +public class NameGeneratingPluginFactory { + + private static final Class NAME_GENERATABLE_PLUGIN = NameGeneratablePlugin.class; + + public NameGeneratablePlugin create(final Map, List> pluginTypes) { + + if (pluginTypes.containsKey(NAME_GENERATABLE_PLUGIN)) { + final List nameGeneratablePlugins = pluginTypes.get(NAME_GENERATABLE_PLUGIN); + + if (nameGeneratablePlugins.size() > 1) { + final List pluginNames = nameGeneratablePlugins.stream().map(plugin -> plugin.getClass().getSimpleName()).collect(toList()); + throw new PluginProviderException(format("Multiple NameGeneratablePlugin identified, please supply only one. List: %s", pluginNames)); + } + + return (NameGeneratablePlugin) nameGeneratablePlugins.get(0); + } + + return new RootNameGeneratorPlugin(); + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginInstantiator.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginInstantiator.java new file mode 100644 index 0000000..ecbb676 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginInstantiator.java @@ -0,0 +1,67 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.lang.String.format; +import static java.lang.reflect.Modifier.PUBLIC; +import static java.lang.reflect.Modifier.STATIC; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.toList; + +import uk.gov.justice.generation.pojo.plugin.FactoryMethod; +import uk.gov.justice.generation.pojo.plugin.PluginProviderException; + +import java.lang.reflect.Method; +import java.util.List; + +public class PluginInstantiator { + + private final Instantiator instantiator; + + public PluginInstantiator(final Instantiator instantiator) { + this.instantiator = instantiator; + } + + public Object instantiate(final String className) { + + final Class aClass = instantiator.classForName(className); + + final List methods = stream(aClass.getDeclaredMethods()) + .filter(method -> method.isAnnotationPresent(FactoryMethod.class)) + .collect(toList()); + + if (methods.isEmpty()) { + return instantiator.instantiate(aClass); + } + + if (methods.size() > 1) { + throw new PluginProviderException(format("Plugin '%s' has more than one factory method annotated with '@%s'", aClass.getSimpleName(), FactoryMethod.class.getSimpleName())); + } + + final Method method = methods.get(0); + + if (notPublic(method)) { + throw new PluginProviderException(format("Failed to instantiate Plugin '%s': Factory method '%s' is not public", aClass.getSimpleName(), method.getName())); + } + + if (notStatic(method)) { + throw new PluginProviderException(format("Failed to instantiate Plugin '%s': Factory method '%s' is not static", aClass.getSimpleName(), method.getName())); + } + + if (hasParameters(method)) { + throw new PluginProviderException(format("Failed to instantiate Plugin '%s': Factory method '%s' should have no parameters", aClass.getSimpleName(), method.getName())); + } + + return instantiator.invokeStaticMethod(method, aClass); + } + + private boolean notPublic(final Method method) { + return (method.getModifiers() & PUBLIC) == 0; + } + + private boolean notStatic(final Method method) { + return (method.getModifiers() & STATIC) == 0; + } + + private boolean hasParameters(final Method method) { + return method.getParameterCount() != 0; + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginTypeSorter.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginTypeSorter.java new file mode 100644 index 0000000..b3d5152 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginTypeSorter.java @@ -0,0 +1,48 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.lang.String.format; +import static java.util.Arrays.asList; +import static java.util.stream.Collectors.groupingBy; + +import uk.gov.justice.generation.pojo.plugin.PluginProviderException; +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; +import uk.gov.justice.generation.pojo.plugin.namegeneratable.NameGeneratablePlugin; +import uk.gov.justice.generation.pojo.plugin.typemodifying.TypeModifyingPlugin; + +import java.util.List; +import java.util.Map; + +public class PluginTypeSorter { + + private static final Class CLASS_MODIFYING_PLUGIN = ClassModifyingPlugin.class; + private static final Class TYPE_MODIFYING_PLUGIN = TypeModifyingPlugin.class; + private static final Class NAME_GENERATABLE_PLUGIN = NameGeneratablePlugin.class; + + private static final String INCORRECT_CLASS_TYPE_MESSAGE = "Incorrect Class Type, Class name: %s, does not implement ClassModifyingPlugin or TypeModifyingPlugin or NameGeneratablePlugin."; + + public Map, List> sortByType(final List plugins) { + + return plugins + .stream() + .collect(groupingBy(this::groupByPluginInterface)); + } + + private Class groupByPluginInterface(final Object plugin) { + + final List> classList = asList(plugin.getClass().getInterfaces()); + + if (classList.contains(CLASS_MODIFYING_PLUGIN)) { + return CLASS_MODIFYING_PLUGIN; + } + + if (classList.contains(TYPE_MODIFYING_PLUGIN)) { + return TYPE_MODIFYING_PLUGIN; + } + + if (classList.contains(NAME_GENERATABLE_PLUGIN)) { + return NAME_GENERATABLE_PLUGIN; + } + + throw new PluginProviderException(format(INCORRECT_CLASS_TYPE_MESSAGE, plugin.getClass().getName())); + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginsFromClassnameListFactory.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginsFromClassnameListFactory.java new file mode 100644 index 0000000..c57b4de --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/PluginsFromClassnameListFactory.java @@ -0,0 +1,26 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static org.apache.commons.lang3.StringUtils.isNotEmpty; + +import java.util.List; +import java.util.Map; + +public class PluginsFromClassnameListFactory { + + private static final String PLUGINS_PROPERTY = "plugins"; + + public List parsePluginNames(final Map generatorProperties) { + + if (generatorProperties.containsKey(PLUGINS_PROPERTY)) { + final String pluginValues = generatorProperties.get(PLUGINS_PROPERTY); + + if (isNotEmpty(pluginValues)) { + return asList(pluginValues.split(",")); + } + } + + return emptyList(); + } +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/TypeModifyingPluginsSelector.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/TypeModifyingPluginsSelector.java new file mode 100644 index 0000000..c4898a3 --- /dev/null +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/factory/TypeModifyingPluginsSelector.java @@ -0,0 +1,26 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.toList; + +import uk.gov.justice.generation.pojo.plugin.typemodifying.TypeModifyingPlugin; + +import java.util.List; +import java.util.Map; + +public class TypeModifyingPluginsSelector { + + private static final Class TYPE_MODIFYING_PLUGIN = TypeModifyingPlugin.class; + + public List selectFrom(final Map, List> pluginTypes) { + if (pluginTypes.containsKey(TYPE_MODIFYING_PLUGIN)) { + return pluginTypes.get(TYPE_MODIFYING_PLUGIN) + .stream() + .map(plugin -> (TypeModifyingPlugin) plugin) + .collect(toList()); + } + + return emptyList(); + } + +} diff --git a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/typemodifying/CustomReturnTypePlugin.java b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/typemodifying/CustomReturnTypePlugin.java index c7dfa7e..745879a 100644 --- a/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/typemodifying/CustomReturnTypePlugin.java +++ b/pojo-generator-core/src/main/java/uk/gov/justice/generation/pojo/plugin/typemodifying/CustomReturnTypePlugin.java @@ -4,23 +4,75 @@ import uk.gov.justice.generation.pojo.dom.Definition; import uk.gov.justice.generation.pojo.dom.ReferenceDefinition; +import uk.gov.justice.generation.pojo.plugin.FactoryMethod; + +import java.time.ZonedDateTime; -import com.google.common.annotations.VisibleForTesting; import com.squareup.javapoet.TypeName; +/** + * Adds support for using custom java types as return types and constructor parameters in the generated + * class. + * + *

To Use:

+ * + *

The custom type should be specified as a reference in your json schema file:

+ * + * {@code + * "myProperty": { + * "$ref": "#/definitions/java.time.ZonedDateTime" + * }, + * "definitions": { + * "java.time.ZonedDateTime": { + * "type": "string", + * "pattern": "^[1|2][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$" + * } + * } + * } + * + * The name {@code ZonedDateTime} in the definition is important as this is how we specify that + * the types should be of type {@link ZonedDateTime}. + * + * NB: It is important to use the fully qualified class name as the package name is required to + * create the {@link TypeName} + * + *

This will generate the following code:

+ * + * {@code public class MyClass { + * + * private final ZonedDateTime myProperty; + * + * public MyClass(final ZonedDateTime myProperty) { + * this.myProperty = myProperty; + * } + * + * public ZonedDateTime getMyProperty() { + * return myProperty; + * } + * } + * } + */ public class CustomReturnTypePlugin implements TypeModifyingPlugin { private final ReferenceToClassNameConverter referenceToClassNameConverter; - public CustomReturnTypePlugin() { - this(new ReferenceToClassNameConverter()); - } - - @VisibleForTesting // will fix this next story public CustomReturnTypePlugin(final ReferenceToClassNameConverter referenceToClassNameConverter) { this.referenceToClassNameConverter = referenceToClassNameConverter; } + @FactoryMethod + public static CustomReturnTypePlugin create() { + return new CustomReturnTypePlugin(new ReferenceToClassNameConverter()); + } + + /** + * Modifies the class name to that specified by the schema reference value + * + * @param typeName The type name to be modified + * @param definition The FieldDefinition of the type to be modified + * + * @return The type name as taken from the schema reference value + */ @Override public TypeName modifyTypeName(final TypeName typeName, final Definition definition) { diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryFactoryTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryFactoryTest.java new file mode 100644 index 0000000..b532c58 --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryFactoryTest.java @@ -0,0 +1,48 @@ +package uk.gov.justice.generation.pojo.plugin; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import uk.gov.justice.generation.pojo.plugin.factory.AllPluginsInstantiator; +import uk.gov.justice.generation.pojo.plugin.factory.ClassModifyingPluginsSelector; +import uk.gov.justice.generation.pojo.plugin.factory.NameGeneratingPluginFactory; +import uk.gov.justice.generation.pojo.plugin.factory.PluginTypeSorter; +import uk.gov.justice.generation.pojo.plugin.factory.PluginsFromClassnameListFactory; +import uk.gov.justice.generation.pojo.plugin.factory.TypeModifyingPluginsSelector; + +import java.lang.reflect.Field; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class PluginProviderFactoryFactoryTest { + + @InjectMocks + private PluginProviderFactoryFactory pluginProviderFactoryFactory; + + @Test + public void shouldCreateThePluginProviderFactory() throws Exception { + + final PluginProviderFactory pluginProviderFactory = pluginProviderFactoryFactory.create(); + + assertThat(getFieldFrom(pluginProviderFactory, "nameGeneratingPluginFactory"), is(instanceOf(NameGeneratingPluginFactory.class))); + assertThat(getFieldFrom(pluginProviderFactory, "classModifyingPluginsSelector"), is(instanceOf(ClassModifyingPluginsSelector.class))); + assertThat(getFieldFrom(pluginProviderFactory, "typeModifyingPluginsSelector"), is(instanceOf(TypeModifyingPluginsSelector.class))); + assertThat(getFieldFrom(pluginProviderFactory, "pluginTypeSorter"), is(instanceOf(PluginTypeSorter.class))); + assertThat(getFieldFrom(pluginProviderFactory, "allPluginsInstantiator"), is(instanceOf(AllPluginsInstantiator.class))); + assertThat(getFieldFrom(pluginProviderFactory, "parsePluginNames"), is(instanceOf(PluginsFromClassnameListFactory.class))); + } + + private Object getFieldFrom(final PluginProviderFactory pluginProviderFactory, final String fieldName) throws Exception { + final Field field = pluginProviderFactory.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + + return field.get(pluginProviderFactory); + } + + +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryTest.java index 8ddc5ca..5ac3255 100644 --- a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryTest.java +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/PluginProviderFactoryTest.java @@ -1,316 +1,81 @@ package uk.gov.justice.generation.pojo.plugin; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.CoreMatchers.hasItems; -import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import uk.gov.justice.generation.pojo.plugin.classmodifying.AddFieldsAndMethodsToClassPlugin; -import uk.gov.justice.generation.pojo.plugin.classmodifying.GenerateBuilderForClassPlugin; -import uk.gov.justice.generation.pojo.plugin.classmodifying.MakeClassSerializablePlugin; -import uk.gov.justice.generation.pojo.plugin.namegeneratable.RootNameGeneratorPlugin; -import uk.gov.justice.generation.pojo.plugin.testplugins.UserDefinedNameGeneratorPlugin; -import uk.gov.justice.generation.pojo.plugin.typemodifying.CustomReturnTypePlugin; -import uk.gov.justice.generation.pojo.plugin.typemodifying.SupportJavaOptionalsPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; +import uk.gov.justice.generation.pojo.plugin.factory.AllPluginsInstantiator; +import uk.gov.justice.generation.pojo.plugin.factory.ClassModifyingPluginsSelector; +import uk.gov.justice.generation.pojo.plugin.factory.NameGeneratingPluginFactory; +import uk.gov.justice.generation.pojo.plugin.factory.PluginTypeSorter; +import uk.gov.justice.generation.pojo.plugin.factory.PluginsFromClassnameListFactory; +import uk.gov.justice.generation.pojo.plugin.factory.TypeModifyingPluginsSelector; +import uk.gov.justice.generation.pojo.plugin.namegeneratable.NameGeneratablePlugin; import uk.gov.justice.generation.pojo.plugin.typemodifying.TypeModifyingPlugin; import uk.gov.justice.maven.generator.io.files.parser.core.GeneratorConfig; -import java.util.HashMap; import java.util.List; import java.util.Map; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +@RunWith(MockitoJUnitRunner.class) public class PluginProviderFactoryTest { - private static final String EXCLUDE_DEFAULT_PLUGINS_PROPERTY = "excludeDefaultPlugins"; - private static final String PLUGINS_PROPERTY = "plugins"; + @Mock + private NameGeneratingPluginFactory nameGeneratingPluginFactory; - private static final String MULTIPLE_NAME_GENERATBLE_PLUGINS = - UserDefinedNameGeneratorPlugin.class.getName() + ",\n" + - UserDefinedNameGeneratorPlugin.class.getName(); + @Mock + private ClassModifyingPluginsSelector classModifyingPluginsSelector; + @Mock + private TypeModifyingPluginsSelector typeModifyingPluginsSelector; - private static final String MULTIPLE_TYPES_OF_PLUGIN = - CustomReturnTypePlugin.class.getName() + ",\n" + - SupportJavaOptionalsPlugin.class.getName() + ",\n" + - MakeClassSerializablePlugin.class.getName() + ",\n" + - UserDefinedNameGeneratorPlugin.class.getName(); + @Mock + private PluginTypeSorter pluginTypeSorter; - private static final String BLANK = ""; + @Mock + private AllPluginsInstantiator allPluginsInstantiator; - @Rule - public ExpectedException expectedException = ExpectedException.none(); + @Mock + private PluginsFromClassnameListFactory parsePluginNames; - @Test - @SuppressWarnings("unchecked") - public void shouldReturnProviderWithDefaultClassModifyingPlugins() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.classModifyingPlugins().size(), is(2)); - assertThat(pluginProvider.classModifyingPlugins(), hasItems( - instanceOf(AddFieldsAndMethodsToClassPlugin.class), - instanceOf(GenerateBuilderForClassPlugin.class))); - } - - @Test - @SuppressWarnings("unchecked") - public void shouldReturnProviderWithNoDefaultsIfExcludeDefaultPluginsPropertyIsSetToTrue() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(EXCLUDE_DEFAULT_PLUGINS_PROPERTY, "true"); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.classModifyingPlugins().size(), is(0)); - } - - @Test - @SuppressWarnings("unchecked") - public void shouldReturnProviderWithDefaultsIfExcludeDefaultPluginsPropertyIsSetToFalse() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(EXCLUDE_DEFAULT_PLUGINS_PROPERTY, "false"); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.classModifyingPlugins().size(), is(2)); - assertThat(pluginProvider.classModifyingPlugins(), hasItems( - instanceOf(AddFieldsAndMethodsToClassPlugin.class), - instanceOf(GenerateBuilderForClassPlugin.class))); - } - - @Test - @SuppressWarnings("unchecked") - public void shouldReturnProviderWithDefaultsAndUserDefinedClassModifyingPlugin() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, MakeClassSerializablePlugin.class.getName()); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.classModifyingPlugins().size(), is(3)); - assertThat(pluginProvider.classModifyingPlugins(), hasItems( - instanceOf(AddFieldsAndMethodsToClassPlugin.class), - instanceOf(GenerateBuilderForClassPlugin.class), - instanceOf(MakeClassSerializablePlugin.class))); - } - - @Test - @SuppressWarnings("unchecked") - public void shouldReturnProviderWithDefaultForBlankProperty() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, BLANK); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.classModifyingPlugins().size(), is(2)); - assertThat(pluginProvider.classModifyingPlugins(), hasItems( - instanceOf(AddFieldsAndMethodsToClassPlugin.class), - instanceOf(GenerateBuilderForClassPlugin.class))); - } - - @Test - public void shouldReturnProviderWithNoTypeModifyingPlugins() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.typeModifyingPlugins().size(), is(0)); - } - - @Test - public void shouldReturnProviderWithSingleTypeModifyingPlugin() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, CustomReturnTypePlugin.class.getName()); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.typeModifyingPlugins().size(), is(1)); - assertThat(pluginProvider.typeModifyingPlugins(), hasItem(instanceOf(CustomReturnTypePlugin.class))); - } - - @Test - public void shouldReturnProviderWithDefaultNameGeneratablePlugin() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.nameGeneratablePlugin(), is(instanceOf(RootNameGeneratorPlugin.class))); - } - - @Test - public void shouldReturnProviderWithUserDefinedNameGeneratablePlugin() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, UserDefinedNameGeneratorPlugin.class.getName()); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.nameGeneratablePlugin(), is(instanceOf(UserDefinedNameGeneratorPlugin.class))); - } - - @Test - public void shouldTrhowExceptionIfMoreThanOneUserDefinedNameGeneratablePlugin() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, MULTIPLE_NAME_GENERATBLE_PLUGINS); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - expectedException.expect(PluginProviderException.class); - expectedException.expectMessage("Multiple NameGeneratablePlugin identified, please supply only one. List: [UserDefinedNameGeneratorPlugin, UserDefinedNameGeneratorPlugin]"); - - new PluginProviderFactory().createFor(generatorConfig); - } - - @Test - @SuppressWarnings("unchecked") - public void shouldReturnProviderWithMultipleTypeModifyingPlugin() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, CustomReturnTypePlugin.class.getName() + ",\n" + - SupportJavaOptionalsPlugin.class.getName()); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - final List typeModifyingPlugins = pluginProvider.typeModifyingPlugins(); - - assertThat(typeModifyingPlugins.size(), is(2)); - assertThat(typeModifyingPlugins, hasItems( - instanceOf(CustomReturnTypePlugin.class), - instanceOf(SupportJavaOptionalsPlugin.class))); - } + @InjectMocks + private PluginProviderFactory pluginProviderFactory; @Test @SuppressWarnings("unchecked") - public void shouldReturnProviderWithMultipleTypeModifyingPluginAndClassModifyingPlugin() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); + public void shouldFindAllPluginsTheInstantiateAndReturnThemInThePluginProvider() throws Exception { - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, MULTIPLE_TYPES_OF_PLUGIN); + final Map generatorProperties = mock(Map.class); + final List pluginNames = mock(List.class); + final List plugins = mock(List.class); + final Map, List> pluginTypes = mock(Map.class); + final List classModifyingPlugins = mock(List.class); + final List typeModifyingPlugins = mock(List.class); + final NameGeneratablePlugin nameGeneratablePlugin = mock(NameGeneratablePlugin.class); - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - final PluginProvider pluginProvider = new PluginProviderFactory().createFor(generatorConfig); - - assertThat(pluginProvider.typeModifyingPlugins().size(), is(2)); - assertThat(pluginProvider.typeModifyingPlugins(), hasItems( - instanceOf(CustomReturnTypePlugin.class), - instanceOf(SupportJavaOptionalsPlugin.class))); - - assertThat(pluginProvider.classModifyingPlugins().size(), is(3)); - assertThat(pluginProvider.classModifyingPlugins(), hasItems( - instanceOf(AddFieldsAndMethodsToClassPlugin.class), - instanceOf(GenerateBuilderForClassPlugin.class), - instanceOf(MakeClassSerializablePlugin.class))); - - assertThat(pluginProvider.nameGeneratablePlugin(), is(instanceOf(UserDefinedNameGeneratorPlugin.class))); - } - - @Test - public void shouldThrowExceptionIfUserDefinedPluginDoesNotImplementPluginInterface() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, "uk.gov.justice.generation.pojo.plugin.testplugins.TestNotPlugin"); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - expectedException.expect(PluginProviderException.class); - expectedException.expectMessage("Incorrect Class Type, Class name: uk.gov.justice.generation.pojo.plugin.testplugins.TestNotPlugin, does not implement ClassModifyingPlugin or TypeModifyingPlugin or NameGeneratablePlugin."); - - new PluginProviderFactory().createFor(generatorConfig); - } - - @Test - public void shouldThrowExceptionIfUserDefinedPluginCanNotBeInstantiated() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, "uk.gov.justice.generation.pojo.plugin.testplugins.TestAbstractPlugin"); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - expectedException.expect(PluginProviderException.class); - expectedException.expectMessage("Unable to create instance of pojo plugin with class name uk.gov.justice.generation.pojo.plugin.testplugins.TestAbstractPlugin"); - expectedException.expectCause(instanceOf(InstantiationException.class)); - - new PluginProviderFactory().createFor(generatorConfig); - } - - @Test - public void shouldThrowExceptionIfUserDefinedPluginCanNotBeFound() throws Exception { - final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, "uk.gov.justice.generation.pojo.plugin.testplugins.NotFoundPlugin"); - - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); - - expectedException.expect(PluginProviderException.class); - expectedException.expectMessage("Unable to create instance of pojo plugin with class name uk.gov.justice.generation.pojo.plugin.testplugins.NotFoundPlugin"); - expectedException.expectCause(instanceOf(ClassNotFoundException.class)); - - new PluginProviderFactory().createFor(generatorConfig); - } - - @Test - public void shouldThrowExceptionIfUserDefinedPluginHasPrivateConstructor() throws Exception { final GeneratorConfig generatorConfig = mock(GeneratorConfig.class); - final Map properties = new HashMap<>(); - properties.put(PLUGINS_PROPERTY, "uk.gov.justice.generation.pojo.plugin.testplugins.TestPrivateConstructorPlugin"); + when(generatorConfig.getGeneratorProperties()).thenReturn(generatorProperties); + when(parsePluginNames.parsePluginNames(generatorProperties)).thenReturn(pluginNames); + when(allPluginsInstantiator.instantiate(pluginNames)).thenReturn(plugins); + when(pluginTypeSorter.sortByType(plugins)).thenReturn(pluginTypes); - when(generatorConfig.getGeneratorProperties()).thenReturn(properties); + when(classModifyingPluginsSelector.selectFrom(pluginTypes, generatorProperties)).thenReturn(classModifyingPlugins); + when(typeModifyingPluginsSelector.selectFrom(pluginTypes)).thenReturn(typeModifyingPlugins); + when(nameGeneratingPluginFactory.create(pluginTypes)).thenReturn(nameGeneratablePlugin); - expectedException.expect(PluginProviderException.class); - expectedException.expectMessage("Unable to create instance of pojo plugin with class name uk.gov.justice.generation.pojo.plugin.testplugins.TestPrivateConstructorPlugin"); - expectedException.expectCause(instanceOf(IllegalAccessException.class)); + final PluginProvider pluginProvider = pluginProviderFactory.createFor(generatorConfig); - new PluginProviderFactory().createFor(generatorConfig); + assertThat(pluginProvider.classModifyingPlugins(), is(classModifyingPlugins)); + assertThat(pluginProvider.typeModifyingPlugins(), is(typeModifyingPlugins)); + assertThat(pluginProvider.nameGeneratablePlugin(), is(nameGeneratablePlugin)); } } diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddHashcodeAndEqualsPluginTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddHashcodeAndEqualsPluginTest.java index e800e3c..0452802 100644 --- a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddHashcodeAndEqualsPluginTest.java +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/classmodifying/AddHashcodeAndEqualsPluginTest.java @@ -3,10 +3,13 @@ import static com.squareup.javapoet.ClassName.get; import static com.squareup.javapoet.TypeSpec.classBuilder; import static java.util.Arrays.asList; +import static java.util.Arrays.stream; import static java.util.Collections.emptyList; import static javax.lang.model.element.Modifier.PUBLIC; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static uk.gov.justice.generation.pojo.dom.DefinitionType.STRING; @@ -15,9 +18,12 @@ import uk.gov.justice.generation.pojo.dom.Definition; import uk.gov.justice.generation.pojo.dom.FieldDefinition; import uk.gov.justice.generation.pojo.generators.ClassNameFactory; +import uk.gov.justice.generation.pojo.plugin.FactoryMethod; import uk.gov.justice.generation.pojo.plugin.classmodifying.properties.AdditionalPropertiesDeterminer; +import java.lang.reflect.Method; import java.util.List; +import java.util.Optional; import com.squareup.javapoet.TypeSpec; import org.junit.Test; @@ -145,4 +151,21 @@ public void shouldAddAdditionalPropertiesToHashcodeAndEquals() throws Exception assertThat(modifiedClassBuilder.methodSpecs.get(0).toString(), is(expectedEqualsMethod)); assertThat(modifiedClassBuilder.methodSpecs.get(1).toString(), is(expectedHashCodeMethod)); } + + @Test + public void shouldBeInstantiableUsingItsFactoryMethod() throws Exception { + + final Method[] declaredMethods = AddHashcodeAndEqualsPlugin.class.getDeclaredMethods(); + + final Optional methodOptional = stream(declaredMethods) + .filter(method -> method.isAnnotationPresent(FactoryMethod.class)) + .findFirst(); + + if (methodOptional.isPresent()) { + final Object plugin = methodOptional.get().invoke(null); + assertThat(plugin, is(instanceOf(AddHashcodeAndEqualsPlugin.class))); + } else { + fail(); + } + } } diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/AllPluginsInstantiatorTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/AllPluginsInstantiatorTest.java new file mode 100644 index 0000000..5ac4d03 --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/AllPluginsInstantiatorTest.java @@ -0,0 +1,58 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + + +@RunWith(MockitoJUnitRunner.class) +public class AllPluginsInstantiatorTest { + + @Mock + private PluginInstantiator pluginInstantiator; + + @InjectMocks + private AllPluginsInstantiator allPluginsInstantiator; + + @Test + public void shouldInstantiateAllTheListOfPluginNames() throws Exception { + + final String pluginName_1 = "org.bloggs.fred.Plugin_1"; + final String pluginName_2 = "org.bloggs.fred.Plugin_2"; + final String pluginName_3 = "org.bloggs.fred.Plugin_3"; + + final Object plugin_1 = mock(ClassModifyingPlugin.class); + final Object plugin_2 = mock(ClassModifyingPlugin.class); + final Object plugin_3 = mock(ClassModifyingPlugin.class); + + final List pluginNames = asList( + pluginName_1, + pluginName_2, + pluginName_3 + ); + + when(pluginInstantiator.instantiate(pluginName_1)).thenReturn(plugin_1); + when(pluginInstantiator.instantiate(pluginName_2)).thenReturn(plugin_2); + when(pluginInstantiator.instantiate(pluginName_3)).thenReturn(plugin_3); + + final List plugins = allPluginsInstantiator.instantiate(pluginNames); + + assertThat(plugins.size(), is(3)); + assertThat(plugins, hasItem(plugin_1)); + assertThat(plugins, hasItem(plugin_2)); + assertThat(plugins, hasItem(plugin_3)); + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/ClassModifyingPluginsSelectorTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/ClassModifyingPluginsSelectorTest.java new file mode 100644 index 0000000..fbe24fd --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/ClassModifyingPluginsSelectorTest.java @@ -0,0 +1,104 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import uk.gov.justice.generation.pojo.plugin.classmodifying.AddAdditionalPropertiesToClassPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.AddFieldsAndMethodsToClassPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.AddHashcodeAndEqualsPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.GenerateBuilderForClassPlugin; +import uk.gov.justice.generation.pojo.plugin.typemodifying.CustomReturnTypePlugin; +import uk.gov.justice.generation.pojo.plugin.typemodifying.SupportJavaOptionalsPlugin; +import uk.gov.justice.generation.pojo.plugin.typemodifying.TypeModifyingPlugin; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ClassModifyingPluginsSelectorTest { + + @Mock + private ExcludeDefaultPluginsSwitch excludeDefaultPluginsSwitch; + + @Mock + private DefaultPluginsProvider defaultPluginsProvider; + + @InjectMocks + private ClassModifyingPluginsSelector classModifyingPluginsSelector; + + @Test + public void shouldGetTheListOfClassModifyingPluginsWithDefaultPluginsIfExcludeDefaultPluginsIsFalse() throws Exception { + + final Map generatorProperties = new HashMap<>(); + final Map, List> pluginTypes = new HashMap<>(); + + pluginTypes.put(ClassModifyingPlugin.class, classModifyingPlugins()); + pluginTypes.put(TypeModifyingPlugin.class, typeModifyingPlugins()); + + when(excludeDefaultPluginsSwitch.shouldExcludeDefaultPlugins(generatorProperties)).thenReturn(false); + when(defaultPluginsProvider.getDefaultPlugins()).thenReturn(defaultPlugins()); + + final List classModifyingPlugins = classModifyingPluginsSelector.selectFrom( + pluginTypes, generatorProperties + ); + + assertThat(classModifyingPlugins.size(), is(4)); + assertThat(classModifyingPlugins.get(0), is(instanceOf(AddFieldsAndMethodsToClassPlugin.class))); + assertThat(classModifyingPlugins.get(1), is(instanceOf(GenerateBuilderForClassPlugin.class))); + assertThat(classModifyingPlugins.get(2), is(instanceOf(AddAdditionalPropertiesToClassPlugin.class))); + assertThat(classModifyingPlugins.get(3), is(instanceOf(AddHashcodeAndEqualsPlugin.class))); + } + + @Test + public void shouldGetTheListOfClassModifyingPluginsWithoutDefaultPluginsIfExcludeDefaultPluginsIsTrue() throws Exception { + + final Map generatorProperties = new HashMap<>(); + final Map, List> pluginTypes = new HashMap<>(); + + pluginTypes.put(ClassModifyingPlugin.class, classModifyingPlugins()); + pluginTypes.put(TypeModifyingPlugin.class, typeModifyingPlugins()); + + when(excludeDefaultPluginsSwitch.shouldExcludeDefaultPlugins(generatorProperties)).thenReturn(true); + + final List classModifyingPlugins = classModifyingPluginsSelector.selectFrom( + pluginTypes, generatorProperties + ); + + assertThat(classModifyingPlugins.size(), is(2)); + assertThat(classModifyingPlugins.get(0), is(instanceOf(AddAdditionalPropertiesToClassPlugin.class))); + assertThat(classModifyingPlugins.get(1), is(instanceOf(AddHashcodeAndEqualsPlugin.class))); + + verifyZeroInteractions(defaultPluginsProvider); + } + + private List classModifyingPlugins() { + final Object addAdditionalPropertiesToClassPlugin = mock(AddAdditionalPropertiesToClassPlugin.class); + final Object addHashcodeAndEqualsPlugin = mock(AddHashcodeAndEqualsPlugin.class); + return asList(addAdditionalPropertiesToClassPlugin, addHashcodeAndEqualsPlugin); + } + + private List typeModifyingPlugins() { + final Object customReturnTypePlugin = mock(CustomReturnTypePlugin.class); + final Object supportJavaOptionalsPlugin = mock(SupportJavaOptionalsPlugin.class); + return asList(customReturnTypePlugin, supportJavaOptionalsPlugin); + } + + private List defaultPlugins() { + final ClassModifyingPlugin addFieldsAndMethodsToClassPlugin = mock(AddFieldsAndMethodsToClassPlugin.class); + final ClassModifyingPlugin generateBuilderForClassPlugin = mock(GenerateBuilderForClassPlugin.class); + return asList(addFieldsAndMethodsToClassPlugin, generateBuilderForClassPlugin); + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/DefaultPluginsProviderTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/DefaultPluginsProviderTest.java new file mode 100644 index 0000000..9275569 --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/DefaultPluginsProviderTest.java @@ -0,0 +1,33 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import uk.gov.justice.generation.pojo.plugin.classmodifying.AddFieldsAndMethodsToClassPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.GenerateBuilderForClassPlugin; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class DefaultPluginsProviderTest { + + @InjectMocks + private DefaultPluginsProvider defaultPluginsProvider; + + @Test + public void shouldGetTheListOfDefaultPlugins() throws Exception { + + final List defaultPlugins = defaultPluginsProvider.getDefaultPlugins(); + + assertThat(defaultPlugins.size(), is(2)); + assertThat(defaultPlugins.get(0), is(instanceOf(AddFieldsAndMethodsToClassPlugin.class))); + assertThat(defaultPlugins.get(1), is(instanceOf(GenerateBuilderForClassPlugin.class))); + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/ExcludeDefaultPluginsSwitchTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/ExcludeDefaultPluginsSwitchTest.java new file mode 100644 index 0000000..49f9115 --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/ExcludeDefaultPluginsSwitchTest.java @@ -0,0 +1,65 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static com.google.common.collect.ImmutableMap.of; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ExcludeDefaultPluginsSwitchTest { + + @InjectMocks + private ExcludeDefaultPluginsSwitch excludeDefaultPluginsSwitch; + + @Test + public void shouldGetTheStateOfTheExcludeDefaultPluginsProperty() throws Exception { + + final Map generatorPropertiesWithPluginsTrue = of( + "property_1", "value_1", + "property_2", "value_2", + "excludeDefaultPlugins", "true", + "property_3", "value_3" + ); + + final Map generatorPropertiesWithPluginsFalse = of( + "property_1", "value_1", + "property_2", "value_2", + "excludeDefaultPlugins", "false", + "property_3", "value_3" + ); + + assertThat(excludeDefaultPluginsSwitch.shouldExcludeDefaultPlugins(generatorPropertiesWithPluginsTrue), is(true)); + assertThat(excludeDefaultPluginsSwitch.shouldExcludeDefaultPlugins(generatorPropertiesWithPluginsFalse), is(false)); + } + + @Test + public void shouldHandleAMalformedExcludeDefaultPluginsProperty() throws Exception { + + final Map generatorProperties = of( + "property_1", "value_1", + "property_2", "value_2", + "excludeDefaultPlugins", "troo", + "property_3", "value_3" + ); + + assertThat(excludeDefaultPluginsSwitch.shouldExcludeDefaultPlugins(generatorProperties), is(false)); + } + + @Test + public void shouldReturnFalseIfTheExcludeDefaultPluginsPropertyIsMissing() throws Exception { + + final Map generatorProperties = of( + "property_1", "value_1", + "property_2", "value_2", + "property_3", "value_3" + ); + + assertThat(excludeDefaultPluginsSwitch.shouldExcludeDefaultPlugins(generatorProperties), is(false)); + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/InstantiatorTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/InstantiatorTest.java new file mode 100644 index 0000000..663bedb --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/InstantiatorTest.java @@ -0,0 +1,136 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import uk.gov.justice.generation.pojo.plugin.PluginProviderException; + +import java.io.IOException; +import java.lang.reflect.Method; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + + +@RunWith(MockitoJUnitRunner.class) +public class InstantiatorTest { + + @InjectMocks + private Instantiator instantiator; + + @Test + public void shouldCreateANewInstanceOfAClass() throws Exception { + final Object myClass = instantiator.instantiate(MyClass.class); + + assertThat(myClass, is(instanceOf(MyClass.class))); + } + + @Test + public void shouldFailIfTheClassCannotBeInstantiated() throws Exception { + try { + instantiator.instantiate(MyAbstractClass.class); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Unable to create new instance of class uk.gov.justice.generation.pojo.plugin.factory.MyAbstractClass")); + assertThat(expected.getCause(), is(instanceOf(InstantiationException.class))); + } + } + + @Test + public void shouldFailIfTheClassConstructorCannotBeAccessed() throws Exception { + try { + instantiator.instantiate(MyPrivateConstructorClass.class); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Unable to create new instance of class uk.gov.justice.generation.pojo.plugin.factory.MyPrivateConstructorClass")); + assertThat(expected.getCause(), is(instanceOf(IllegalAccessException.class))); + } + } + + @Test + public void shouldInvokeAStaticMethod() throws Exception { + + final Method method = MyClassWithStaticMethod.class.getDeclaredMethod("getFred"); + + assertThat(instantiator.invokeStaticMethod(method, MyClassWithStaticMethod.class), is("Fred")); + } + + @Test + public void shouldFailWhenInvokingAPrivateStaticMethod() throws Exception { + + final Method method = MyClassWithPrivateStaticMethod.class.getDeclaredMethod("getFred"); + + try { + instantiator.invokeStaticMethod(method, MyClassWithPrivateStaticMethod.class); + } catch (final PluginProviderException expected) { + assertThat(expected.getCause(), is(instanceOf(IllegalAccessException.class))); + assertThat(expected.getMessage(), is("Unable to invoke method getFred on class uk.gov.justice.generation.pojo.plugin.factory.MyClassWithPrivateStaticMethod")); + } + } + + @Test + public void shouldCreateAClassByName() throws Exception { + + final String className = "uk.gov.justice.generation.pojo.plugin.factory.MyClass"; + final Class aClass = instantiator.classForName(className); + + assertThat(aClass, is(equalTo(MyClass.class))); + } + + @Test + public void shouldAlwaysTrimAClassName() throws Exception { + + final String className = "\n\n uk.gov.justice.generation.pojo.plugin.factory.MyClass \n\n"; + final Class aClass = instantiator.classForName(className); + + assertThat(aClass, is(equalTo(MyClass.class))); + } + + @Test + public void shouldFailIfTheClassIsNotFound() throws Exception { + final String className = "uk.gov.justice.does.not.exist.MyMissingClass"; + try { + instantiator.classForName(className); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Unable to create class uk.gov.justice.does.not.exist.MyMissingClass")); + assertThat(expected.getCause(), is(instanceOf(ClassNotFoundException.class))); + } + } +} + +class MyClass { + +} + +abstract class MyAbstractClass { + +} + +class MyPrivateConstructorClass { + private MyPrivateConstructorClass() { + } +} + +class MyClassWithStaticMethod { + public static String getFred() { + return "Fred"; + } +} + +class MyClassWithPrivateStaticMethod { + private static String getFred() { + return "Fred"; + } +} + +class MyClassWithFailingStaticMethod { + public static String getFred() throws IOException { + throw new IOException("Ooops"); + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/NameGeneratingPluginFactoryTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/NameGeneratingPluginFactoryTest.java new file mode 100644 index 0000000..5e8ef17 --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/NameGeneratingPluginFactoryTest.java @@ -0,0 +1,99 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonList; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import uk.gov.justice.generation.pojo.plugin.PluginProviderException; +import uk.gov.justice.generation.pojo.plugin.namegeneratable.NameGeneratablePlugin; +import uk.gov.justice.generation.pojo.plugin.namegeneratable.RootNameGeneratorPlugin; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.everit.json.schema.Schema; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class NameGeneratingPluginFactoryTest { + + @InjectMocks + private NameGeneratingPluginFactory nameGeneratingPluginFactory; + + @Test + public void shouldGetTheRootFieldNameGeneratorPluginIfNoOverriddenNameGeneratingPluginSpecified() throws Exception { + + final Map, List> pluginTypes = emptyMap(); + + final NameGeneratablePlugin nameGeneratablePlugin = nameGeneratingPluginFactory.create(pluginTypes); + + assertThat(nameGeneratablePlugin, is(instanceOf(RootNameGeneratorPlugin.class))); + } + + @Test + public void shouldGetTheOverriddenNameGeneratingPluginSpecified() throws Exception { + + final Map, List> pluginTypes = getSinglePluginTypes(); + + final NameGeneratablePlugin nameGeneratablePlugin = nameGeneratingPluginFactory.create(pluginTypes); + + assertThat(nameGeneratablePlugin, is(instanceOf(MyNameGeneratablePlugin.class))); + } + + @Test + public void shouldFailMoreThanOneOverriddenNameGeneratingPluginSpecified() throws Exception { + + final Map, List> pluginTypes = getMultiplePluginTypes(); + + try { + nameGeneratingPluginFactory.create(pluginTypes); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Multiple NameGeneratablePlugin identified, please supply only one. List: [MyNameGeneratablePlugin, MyOtherNameGeneratablePlugin]")); + } + } + + private Map, List> getSinglePluginTypes() { + + final HashMap, List> pluginTypes = new HashMap<>(); + + final List plugins = singletonList(new MyNameGeneratablePlugin()); + pluginTypes.put(NameGeneratablePlugin.class, plugins); + + return pluginTypes; + } + + private Map, List> getMultiplePluginTypes() { + + final HashMap, List> pluginTypes = new HashMap<>(); + + final List plugins = asList(new MyNameGeneratablePlugin(), new MyOtherNameGeneratablePlugin()); + pluginTypes.put(NameGeneratablePlugin.class, plugins); + + return pluginTypes; + } +} + +class MyNameGeneratablePlugin implements NameGeneratablePlugin { + + @Override + public String rootFieldNameFrom(final Schema schema, final String schemaFilename) { + return null; + } +} + +class MyOtherNameGeneratablePlugin implements NameGeneratablePlugin { + + @Override + public String rootFieldNameFrom(final Schema schema, final String schemaFilename) { + return null; + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginInstantiatorTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginInstantiatorTest.java new file mode 100644 index 0000000..38f85bd --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginInstantiatorTest.java @@ -0,0 +1,225 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.when; + +import uk.gov.justice.generation.pojo.dom.ClassDefinition; +import uk.gov.justice.generation.pojo.plugin.FactoryMethod; +import uk.gov.justice.generation.pojo.plugin.PluginProviderException; +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; +import uk.gov.justice.generation.pojo.plugin.classmodifying.PluginContext; + +import java.lang.reflect.Method; + +import com.squareup.javapoet.TypeSpec; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +@SuppressWarnings("unchecked") +@RunWith(MockitoJUnitRunner.class) +public class PluginInstantiatorTest { + + @Mock + private Instantiator instantiator; + + @InjectMocks + private PluginInstantiator pluginInstantiator; + + @Test + public void shouldInstantiateAPluginUsingItsFactoryMethod() throws Exception { + + final PluginWithFactoryMethod pluginWithFactoryMethod = PluginWithFactoryMethod.createNew(); + final Class pluginWithFactoryMethodClass = pluginWithFactoryMethod.getClass(); + final Method factoryMethod = pluginWithFactoryMethodClass.getDeclaredMethod("createNew"); + + when(instantiator.classForName(pluginWithFactoryMethodClass.getName())).thenReturn(pluginWithFactoryMethodClass); + when(instantiator.invokeStaticMethod(factoryMethod, pluginWithFactoryMethodClass)).thenReturn(pluginWithFactoryMethod); + + assertThat(pluginInstantiator.instantiate(pluginWithFactoryMethodClass.getName()), is(pluginWithFactoryMethod)); + } + + @Test + public void shouldInstantiateAClassWithoutAFactoryMethodUsingItsDefaultConstructor() throws Exception { + + final PluginWithoutFactoryMethod pluginWithoutFactoryMethod = new PluginWithoutFactoryMethod(); + final Class pluginWithoutFactoryMethodClass = pluginWithoutFactoryMethod.getClass(); + when(instantiator.classForName(PluginWithoutFactoryMethod.class.getName())).thenReturn(pluginWithoutFactoryMethodClass); + when(instantiator.instantiate(pluginWithoutFactoryMethodClass)).thenReturn(pluginWithoutFactoryMethod); + + final Object plugin = pluginInstantiator.instantiate(PluginWithoutFactoryMethod.class.getName()); + + assertThat(plugin, is(instanceOf(PluginWithoutFactoryMethod.class))); + } + + @Test + public void shouldFailIfThePluginHasMoreThanOneFactoryMethod() throws Exception { + + final Class pluginWithTwoFactoryMethodsClass = PluginWithTwoFactoryMethods.class; + when(instantiator.classForName(pluginWithTwoFactoryMethodsClass.getName())).thenReturn(pluginWithTwoFactoryMethodsClass); + + try { + pluginInstantiator.instantiate(pluginWithTwoFactoryMethodsClass.getName()); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Plugin 'PluginWithTwoFactoryMethods' has more than one factory method annotated with '@FactoryMethod'")); + } + } + + @Test + public void shouldFailIfThePluginFactoryMethodIsNotStatic() throws Exception { + + final Class pluginWithNonStaticFactoryMethodClass = PluginWithNonStaticFactoryMethod.class; + when(instantiator.classForName(pluginWithNonStaticFactoryMethodClass.getName())).thenReturn(pluginWithNonStaticFactoryMethodClass); + + try { + pluginInstantiator.instantiate(pluginWithNonStaticFactoryMethodClass.getName()); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Failed to instantiate Plugin 'PluginWithNonStaticFactoryMethod': Factory method 'createUsingNonStaticMethod' is not static")); + } + } + + @Test + public void shouldFailIfThePluginFactoryMethodIsNotPublic() throws Exception { + + final Class pluginWithNonPublicFactoryMethodClass = PluginWithNonPublicFactoryMethod.class; + when(instantiator.classForName(pluginWithNonPublicFactoryMethodClass.getName())).thenReturn(pluginWithNonPublicFactoryMethodClass); + + try { + pluginInstantiator.instantiate(pluginWithNonPublicFactoryMethodClass.getName()); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Failed to instantiate Plugin 'PluginWithNonPublicFactoryMethod': Factory method 'createUsingNonPublicMethod' is not public")); + } + } + + @Test + public void shouldFailIfThePluginFactoryMethodHasParameters() throws Exception { + + final Class pluginWithFactoryMethodWithParametersClass = PluginWithFactoryMethodWithParameters.class; + when(instantiator.classForName(pluginWithFactoryMethodWithParametersClass.getName())).thenReturn(pluginWithFactoryMethodWithParametersClass); + try { + pluginInstantiator.instantiate(pluginWithFactoryMethodWithParametersClass.getName()); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Failed to instantiate Plugin 'PluginWithFactoryMethodWithParameters': Factory method 'createUsingMethodWithParameters' should have no parameters")); + } + } +} + +class PluginWithFactoryMethod implements ClassModifyingPlugin { + + private PluginWithFactoryMethod() { + } + + @FactoryMethod + @SuppressWarnings("unused") + public static PluginWithFactoryMethod createNew() { + return new PluginWithFactoryMethod(); + } + + @Override + public TypeSpec.Builder generateWith( + final TypeSpec.Builder classBuilder, + final ClassDefinition classDefinition, + final PluginContext pluginContext) { + return null; + } +} + +class PluginWithoutFactoryMethod implements ClassModifyingPlugin { + + @Override + public TypeSpec.Builder generateWith( + final TypeSpec.Builder classBuilder, + final ClassDefinition classDefinition, + final PluginContext pluginContext) { + return null; + } +} + +class PluginWithTwoFactoryMethods implements ClassModifyingPlugin { + + @FactoryMethod + @SuppressWarnings("unused") + public static PluginWithTwoFactoryMethods factoryMethodOne() { + return new PluginWithTwoFactoryMethods(); + } + + @FactoryMethod + @SuppressWarnings("unused") + public static PluginWithTwoFactoryMethods factoryMethodTwo() { + return new PluginWithTwoFactoryMethods(); + } + + @Override + public TypeSpec.Builder generateWith( + final TypeSpec.Builder classBuilder, + final ClassDefinition classDefinition, + final PluginContext pluginContext) { + return null; + } +} + +class PluginWithNonStaticFactoryMethod implements ClassModifyingPlugin { + + private PluginWithNonStaticFactoryMethod() { + } + + @FactoryMethod + @SuppressWarnings("unused") + public PluginWithNonStaticFactoryMethod createUsingNonStaticMethod() { + return new PluginWithNonStaticFactoryMethod(); + } + + @Override + public TypeSpec.Builder generateWith( + final TypeSpec.Builder classBuilder, + final ClassDefinition classDefinition, + final PluginContext pluginContext) { + return null; + } +} + +class PluginWithNonPublicFactoryMethod implements ClassModifyingPlugin { + + private PluginWithNonPublicFactoryMethod() { + } + + @FactoryMethod + @SuppressWarnings("unused") + static PluginWithNonPublicFactoryMethod createUsingNonPublicMethod() { + return new PluginWithNonPublicFactoryMethod(); + } + + @Override + public TypeSpec.Builder generateWith( + final TypeSpec.Builder classBuilder, + final ClassDefinition classDefinition, + final PluginContext pluginContext) { + return null; + } +} + +class PluginWithFactoryMethodWithParameters implements ClassModifyingPlugin { + + @FactoryMethod + @SuppressWarnings("unused") + public static PluginWithFactoryMethodWithParameters createUsingMethodWithParameters(final int someValue) { + return new PluginWithFactoryMethodWithParameters(); + } + + @Override + public TypeSpec.Builder generateWith( + final TypeSpec.Builder classBuilder, + final ClassDefinition classDefinition, + final PluginContext pluginContext) { + return null; + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginTypeSorterTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginTypeSorterTest.java new file mode 100644 index 0000000..77f1ae7 --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginTypeSorterTest.java @@ -0,0 +1,93 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + +import uk.gov.justice.generation.pojo.plugin.PluginProviderException; +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; +import uk.gov.justice.generation.pojo.plugin.namegeneratable.NameGeneratablePlugin; +import uk.gov.justice.generation.pojo.plugin.typemodifying.TypeModifyingPlugin; + +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class PluginTypeSorterTest { + + @InjectMocks + private PluginTypeSorter pluginTypeSorter; + + @Test + public void shouldSortTheListOfPluginsByTheirPluginType() throws Exception { + + final ClassModifyingPlugin classModifyingPlugin_1 = mock(ClassModifyingPlugin.class); + final ClassModifyingPlugin classModifyingPlugin_2 = mock(ClassModifyingPlugin.class); + final ClassModifyingPlugin classModifyingPlugin_3 = mock(ClassModifyingPlugin.class); + + final TypeModifyingPlugin typeModifyingPlugin_1 = mock(TypeModifyingPlugin.class); + final TypeModifyingPlugin typeModifyingPlugin_2 = mock(TypeModifyingPlugin.class); + final TypeModifyingPlugin typeModifyingPlugin_3 = mock(TypeModifyingPlugin.class); + + final NameGeneratablePlugin nameGeneratablePlugin_1 = mock(NameGeneratablePlugin.class); + final NameGeneratablePlugin nameGeneratablePlugin_2 = mock(NameGeneratablePlugin.class); + final NameGeneratablePlugin nameGeneratablePlugin_3 = mock(NameGeneratablePlugin.class); + + final List plugins = asList( + classModifyingPlugin_1, + typeModifyingPlugin_1, + nameGeneratablePlugin_1, + classModifyingPlugin_2, + typeModifyingPlugin_2, + nameGeneratablePlugin_2, + classModifyingPlugin_3, + typeModifyingPlugin_3, + nameGeneratablePlugin_3 + ); + + final Map, List> pluginsByType = pluginTypeSorter.sortByType(plugins); + + assertThat(pluginsByType.size(), is(3)); + + assertThat(pluginsByType.containsKey(ClassModifyingPlugin.class), is(true)); + assertThat(pluginsByType.containsKey(TypeModifyingPlugin.class), is(true)); + assertThat(pluginsByType.containsKey(NameGeneratablePlugin.class), is(true)); + + final List classModifyingPlugins = pluginsByType.get(ClassModifyingPlugin.class); + final List typeModifyingPlugins = pluginsByType.get(TypeModifyingPlugin.class); + final List nameGeneratablePlugins = pluginsByType.get(NameGeneratablePlugin.class); + + assertThat(classModifyingPlugins, hasItem(classModifyingPlugin_1)); + assertThat(classModifyingPlugins, hasItem(classModifyingPlugin_2)); + assertThat(classModifyingPlugins, hasItem(classModifyingPlugin_3)); + + assertThat(typeModifyingPlugins, hasItem(typeModifyingPlugin_1)); + assertThat(typeModifyingPlugins, hasItem(typeModifyingPlugin_2)); + assertThat(typeModifyingPlugins, hasItem(typeModifyingPlugin_3)); + + assertThat(nameGeneratablePlugins, hasItem(nameGeneratablePlugin_1)); + assertThat(nameGeneratablePlugins, hasItem(nameGeneratablePlugin_2)); + assertThat(nameGeneratablePlugins, hasItem(nameGeneratablePlugin_3)); + } + + @Test + public void shouldFailIfTheClassIsNotAPluginClass() throws Exception { + + try { + final String plugin = "This is not a plugin"; + pluginTypeSorter.sortByType(singletonList(plugin)); + fail(); + } catch (final PluginProviderException expected) { + assertThat(expected.getMessage(), is("Incorrect Class Type, Class name: java.lang.String, does not implement ClassModifyingPlugin or TypeModifyingPlugin or NameGeneratablePlugin.")); + } + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginsFromClassnameListFactoryTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginsFromClassnameListFactoryTest.java new file mode 100644 index 0000000..5cb660b --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/PluginsFromClassnameListFactoryTest.java @@ -0,0 +1,75 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static com.google.common.collect.ImmutableMap.of; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + + +@RunWith(MockitoJUnitRunner.class) +public class PluginsFromClassnameListFactoryTest { + + private static final String AN_EMPTY_STRING = ""; + @InjectMocks + private PluginsFromClassnameListFactory pluginsFromClassnameListFactory; + + @Test + public void shouldGetTheCommaSeparatedPluginNamesStringFromThePropertiesAndParseIntoAListOfStrings() throws Exception { + + final String pluginNames = + "org.bloggs.fred.MyPlugin_1" + "," + + "org.bloggs.fred.MyPlugin_2" + "," + + "org.bloggs.fred.MyPlugin_3" + "," + + "org.bloggs.fred.MyPlugin_4"; + + final Map generatorProperties = of("plugins", pluginNames); + + final List pluginNamesList = pluginsFromClassnameListFactory.parsePluginNames(generatorProperties); + + assertThat(pluginNamesList.size(), is(4)); + assertThat(pluginNamesList, hasItem("org.bloggs.fred.MyPlugin_1")); + assertThat(pluginNamesList, hasItem("org.bloggs.fred.MyPlugin_2")); + assertThat(pluginNamesList, hasItem("org.bloggs.fred.MyPlugin_3")); + assertThat(pluginNamesList, hasItem("org.bloggs.fred.MyPlugin_4")); + } + + @Test + public void shouldReturnAnEmptyListIfThePluginsPropertyIsNull() throws Exception { + + final Map generatorProperties = new HashMap<>(); + generatorProperties.put("plugins", null); + + final List pluginNamesList = pluginsFromClassnameListFactory.parsePluginNames(generatorProperties); + + assertThat(pluginNamesList.isEmpty(), is(true)); + } + + @Test + public void shouldReturnAnEmptyListIfThePluginsPropertyIsAnEmptyString() throws Exception { + + final Map generatorProperties = of("plugins", AN_EMPTY_STRING); + + final List pluginNamesList = pluginsFromClassnameListFactory.parsePluginNames(generatorProperties); + + assertThat(pluginNamesList.isEmpty(), is(true)); + } + + @Test + public void shouldReturnAnEmptyListIfThePluginsPropertyDoesNotExist() throws Exception { + + final Map generatorProperties = new HashMap<>(); + + final List pluginNamesList = pluginsFromClassnameListFactory.parsePluginNames(generatorProperties); + + assertThat(pluginNamesList.isEmpty(), is(true)); + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/TypeModifyingPluginsSelectorTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/TypeModifyingPluginsSelectorTest.java new file mode 100644 index 0000000..6d27dcb --- /dev/null +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/factory/TypeModifyingPluginsSelectorTest.java @@ -0,0 +1,60 @@ +package uk.gov.justice.generation.pojo.plugin.factory; + +import static com.google.common.collect.ImmutableMap.of; +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +import uk.gov.justice.generation.pojo.plugin.classmodifying.ClassModifyingPlugin; +import uk.gov.justice.generation.pojo.plugin.typemodifying.TypeModifyingPlugin; + +import java.util.List; + +import com.google.common.collect.ImmutableMap; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class TypeModifyingPluginsSelectorTest { + + @InjectMocks + private TypeModifyingPluginsSelector typeModifyingPluginsSelector; + + @Test + public void shouldSelectTheTypeModifyingPluginsAndReturnAsAList() throws Exception { + + final TypeModifyingPlugin typeModifyingPlugin_1 = mock(TypeModifyingPlugin.class); + final TypeModifyingPlugin typeModifyingPlugin_2 = mock(TypeModifyingPlugin.class); + final TypeModifyingPlugin typeModifyingPlugin_3 = mock(TypeModifyingPlugin.class); + + final List typeModifyingPlugins = asList( + typeModifyingPlugin_1, + typeModifyingPlugin_2, + typeModifyingPlugin_3); + + final ClassModifyingPlugin classModifyingPlugin_1 = mock(ClassModifyingPlugin.class); + final ClassModifyingPlugin classModifyingPlugin_2 = mock(ClassModifyingPlugin.class); + final ClassModifyingPlugin classModifyingPlugin_3 = mock(ClassModifyingPlugin.class); + + final List classModifyingPlugins = asList( + classModifyingPlugin_1, + classModifyingPlugin_2, + classModifyingPlugin_3 + ); + + final ImmutableMap, List> pluginTypes = of( + TypeModifyingPlugin.class, typeModifyingPlugins, + ClassModifyingPlugin.class, classModifyingPlugins); + + final List plugins = typeModifyingPluginsSelector.selectFrom(pluginTypes); + + assertThat(plugins.size(), is(3)); + assertThat(plugins, hasItem(typeModifyingPlugin_1)); + assertThat(plugins, hasItem(typeModifyingPlugin_2)); + assertThat(plugins, hasItem(typeModifyingPlugin_3)); + } +} diff --git a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/typemodifying/CustomReturnTypePluginTest.java b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/typemodifying/CustomReturnTypePluginTest.java index d70d682..0ed01cd 100644 --- a/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/typemodifying/CustomReturnTypePluginTest.java +++ b/pojo-generator-core/src/test/java/uk/gov/justice/generation/pojo/plugin/typemodifying/CustomReturnTypePluginTest.java @@ -1,15 +1,22 @@ package uk.gov.justice.generation.pojo.plugin.typemodifying; +import static java.util.Arrays.asList; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static uk.gov.justice.generation.pojo.dom.DefinitionType.REFERENCE; import static uk.gov.justice.generation.pojo.dom.DefinitionType.STRING; import uk.gov.justice.generation.pojo.dom.ReferenceDefinition; +import uk.gov.justice.generation.pojo.plugin.FactoryMethod; +import java.lang.reflect.Method; import java.time.ZonedDateTime; +import java.util.List; +import java.util.Optional; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.TypeName; @@ -32,7 +39,7 @@ public class CustomReturnTypePluginTest { public void shouldUseTheClassNameInTheJsonSchemaReferenceValueAsTheTypeName() throws Exception { final String referenceValue = "#/definitions/java.time.ZonedDateTime"; - + final ClassName originalTypeName = ClassName.get(String.class); final ClassName modifiedTypeName = ClassName.get(ZonedDateTime.class); @@ -58,4 +65,30 @@ public void shouldReturnTheOriginalTypeNameIfTheDefinitinIsNotAReferenceDefiniti assertThat(typeName, is(originalTypeName)); } + + @Test + public void shouldHaveAFactoryMethodForInstantiation() throws Exception { + + final List methods = asList(CustomReturnTypePlugin.class.getDeclaredMethods()); + + final Method factoryMethod = getFactoryMethod(methods); + final Object plugin = factoryMethod.invoke(null); + + assertThat(plugin, is(instanceOf(CustomReturnTypePlugin.class))); + + } + + private Method getFactoryMethod(final List methods) { + final Optional factoryMethod = methods.stream() + .filter(method -> method.isAnnotationPresent(FactoryMethod.class)) + .findFirst(); + + if (factoryMethod.isPresent()) { + return factoryMethod.get(); + } + + fail(); + + return null; + } }