Skip to content
This repository has been archived by the owner on May 26, 2020. It is now read-only.

Commit

Permalink
User defined plugins from Maven properties
Browse files Browse the repository at this point in the history
  • Loading branch information
mapingo committed Sep 12, 2017
1 parent f27a09c commit af9f940
Show file tree
Hide file tree
Showing 20 changed files with 481 additions and 270 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package uk.gov.justice.generation.pojo.integration.utils;

import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;

Expand All @@ -10,10 +11,19 @@
import uk.gov.justice.generation.pojo.generators.ClassNameFactory;
import uk.gov.justice.generation.pojo.generators.JavaGeneratorFactory;
import uk.gov.justice.generation.pojo.generators.TypeNameProvider;
import uk.gov.justice.generation.pojo.generators.plugin.DefaultPluginProvider;
import uk.gov.justice.generation.pojo.generators.plugin.ModifyingPluginProvider;
import uk.gov.justice.generation.pojo.generators.plugin.PluginProvider;
import uk.gov.justice.generation.pojo.generators.plugin.TypeNamePluginProcessor;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.AddFieldsAndMethodsToClassPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.ClassModifyingPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.GenerateBuilderForClassPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.MakeClassSerializablePlugin;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.PluginContext;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.builder.BuilderGeneratorFactory;
import uk.gov.justice.generation.pojo.generators.plugin.typename.SupportJavaOptionalsPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.typename.SupportUuidsPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.typename.SupportZonedDateTimePlugin;
import uk.gov.justice.generation.pojo.generators.plugin.typename.TypeModifyingPlugin;
import uk.gov.justice.generation.pojo.visitable.Visitable;
import uk.gov.justice.generation.pojo.visitable.VisitableFactory;
import uk.gov.justice.generation.pojo.visitable.acceptor.AcceptorService;
Expand Down Expand Up @@ -61,7 +71,6 @@ public List<Class<?>> generateAndCompileJavaSource(final File jsonSchemaFile,

final Schema schema = schemaLoader.loadFrom(jsonSchemaFile);


final String fieldName = nameGenerator.rootFieldNameFrom(jsonSchemaFile);

final Visitable visitableSchema = visitableFactory.createWith(fieldName, schema, acceptorService);
Expand All @@ -71,7 +80,19 @@ public List<Class<?>> generateAndCompileJavaSource(final File jsonSchemaFile,
final SourceWriter sourceWriter = new SourceWriter();
final ClassCompiler classCompiler = new ClassCompiler();
final GeneratorFactoryBuilder generatorFactoryBuilder = new GeneratorFactoryBuilder();
final PluginProvider pluginProvider = new DefaultPluginProvider();

final List<ClassModifyingPlugin> classGeneratorPlugins = asList(
new MakeClassSerializablePlugin(),
new AddFieldsAndMethodsToClassPlugin(),
new GenerateBuilderForClassPlugin(new BuilderGeneratorFactory()
));

final List<TypeModifyingPlugin> typeNamePlugins = asList(
new SupportJavaOptionalsPlugin(),
new SupportUuidsPlugin(),
new SupportZonedDateTimePlugin());

final PluginProvider pluginProvider = new ModifyingPluginProvider(classGeneratorPlugins, typeNamePlugins);

final TypeNameProvider typeNameProvider = new TypeNameProvider(generationContext);
final TypeNamePluginProcessor typeNamePluginProcessor = new TypeNamePluginProcessor(pluginProvider);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package uk.gov.justice.generation.pojo.generators.plugin;

import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.ClassModifyingPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.typename.TypeModifyingPlugin;

import java.util.List;

/**
* The standard implementation of {@link PluginProvider} that takes a List of {@link
* ClassModifyingPlugin} and a List of {@link TypeModifyingPlugin}.
*/
public class ModifyingPluginProvider implements PluginProvider {

private final List<ClassModifyingPlugin> classModifyingPlugins;
private final List<TypeModifyingPlugin> typeModifyingPlugins;

/**
* Constructor to take a List of {@link ClassModifyingPlugin} and a List of {@link
* TypeModifyingPlugin}.
*
* @param classModifyingPlugins the List of {@link ClassModifyingPlugin}
* @param typeModifyingPlugins the List of {@link TypeModifyingPlugin}
*/
public ModifyingPluginProvider(final List<ClassModifyingPlugin> classModifyingPlugins,
final List<TypeModifyingPlugin> typeModifyingPlugins) {
this.classModifyingPlugins = classModifyingPlugins;
this.typeModifyingPlugins = typeModifyingPlugins;
}

@Override
public List<ClassModifyingPlugin> classModifyingPlugins() {
return classModifyingPlugins;
}

@Override
public List<TypeModifyingPlugin> typeModifyingPlugins() {
return typeModifyingPlugins;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,27 @@

import java.util.List;

/**
* Defines a Class for providing the List of {@link ClassModifyingPlugin} and a List of {@link
* TypeModifyingPlugin}.
*
* These are used during generation to modify Classes or TypeNames before generation.
*/
public interface PluginProvider {

/**
* Returns a List of {@link ClassModifyingPlugin} that is used to modify Classes before
* generation.
*
* @return the List of {@link ClassModifyingPlugin}
*/
List<ClassModifyingPlugin> classModifyingPlugins();

/**
* Returns a List of {@link TypeModifyingPlugin} that is used to modify TypeNames before
* generation.
*
* @return the List of {@link TypeModifyingPlugin}
*/
List<TypeModifyingPlugin> typeModifyingPlugins();
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,172 @@
package uk.gov.justice.generation.pojo.generators.plugin;

import static java.lang.String.format;
import static java.util.stream.Collectors.partitioningBy;
import static java.util.stream.Collectors.toList;

import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.AddFieldsAndMethodsToClassPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.ClassModifyingPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.GenerateBuilderForClassPlugin;
import uk.gov.justice.generation.pojo.generators.plugin.classgenerator.builder.BuilderGeneratorFactory;
import uk.gov.justice.generation.pojo.generators.plugin.typename.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
* TypeModifyingPlugin}. ClassModifyingPlugins consist of a merge of default ClassModifyingPlugins
* and any user defined plugins added to the Maven Plugin generatorProperties tag.
* TypeModifyingPlugins consist of only plugins added to the Maven Plugin generatorProperties tag.
*
* The default {@link ClassModifyingPlugin} are:
*
* {@link AddFieldsAndMethodsToClassPlugin}
* {@link GenerateBuilderForClassPlugin}
*
* For example the following adds the MakeClassSerializable to the default plugins and adds three
* TypeModifyingPlugins:
*
* <pre>
* {@code
*
* <configuration>
* ...
* <generatorProperties>
* <plugins>
* uk.gov.justice.generation.pojo.generators.plugin.classgenerator.MakeClassSerializablePlugin,
* uk.gov.justice.generation.pojo.generators.plugin.typename.SupportJavaOptionalsPlugin,
* uk.gov.justice.generation.pojo.generators.plugin.typename.SupportUuidsPlugin,
* uk.gov.justice.generation.pojo.generators.plugin.typename.SupportZonedDateTimePlugin
* </plugins>
* </generatorProperties>
* ...
* </configuration>
*
* }
* </pre>
*
* If the default ClassModifyingPlugins are not required and other plugins can be used instead, the
* then the excludeDefaultPlugins tag can be set to true, for example:
*
* <pre>
* {@code
*
* <configuration>
* ...
* <generatorProperties>
* <excludeDefaultPlugins>true</excludeDefaultPlugins>
* <plugins>
* ...
* </plugins>
* </generatorProperties>
* ...
* </configuration>
*
* }
* </pre>
*/
public class PluginProviderFactory {

private static final String POJO_PLUGIN_PROVIDER = "pojo-plugin-provider";
private static final String EXCLUDE_DEFAULT_PROPERTY = "excludeDefaultPlugins";
private static final String PLUGINS_PROPERTY = "plugins";

private static final boolean CLASS_MODIFYING_PLUGINS = true;
private static final boolean TYPE_MODIFYING_PLUGINS = false;

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.";

/**
* Create a {@link PluginProvider} using the settings from the {@link GeneratorConfig}
*
* @param generatorConfig the generatorConfig suppying the generatorProperties
* @return a {@link PluginProvider} instance
*/
public PluginProvider createFor(final GeneratorConfig generatorConfig) {
final Map<String, String> generatorProperties = generatorConfig.getGeneratorProperties();
final Map<Boolean, List<Object>> pluginTypes = partitionPluginsAccordingToType(generatorProperties);

return new ModifyingPluginProvider(
defaultAndCustomClassModifyingPlugins(generatorProperties, pluginTypes),
typeModifyingPlugins(pluginTypes));
}

private Map<Boolean, List<Object>> partitionPluginsAccordingToType(final Map<String, String> generatorProperties) {
return allInstancesOfPluginsFrom(generatorProperties)
.collect(partitioningBy(plugin -> plugin instanceof ClassModifyingPlugin));
}

private List<ClassModifyingPlugin> defaultAndCustomClassModifyingPlugins(final Map<String, String> generatorProperties,
final Map<Boolean, List<Object>> pluginTypes) {
return Stream
.concat(
defaultClassModifyingPlugins(generatorProperties),
userDefinedClassModifyingPlugins(pluginTypes))
.collect(toList());
}

private List<TypeModifyingPlugin> typeModifyingPlugins(final Map<Boolean, List<Object>> pluginTypes) {
return pluginTypes.get(TYPE_MODIFYING_PLUGINS)
.stream()
.map(this::castToTypeModifyingPlugin)
.collect(toList());
}

if (generatorProperties.containsKey(POJO_PLUGIN_PROVIDER)) {
final String className = generatorProperties.get(POJO_PLUGIN_PROVIDER);
private TypeModifyingPlugin castToTypeModifyingPlugin(final Object plugin) {
try {
return (TypeModifyingPlugin) plugin;
} catch (final ClassCastException e) {
throw new PluginProviderException(format(INCORRECT_CLASS_TYPE_MESSAGE, plugin.getClass().getName()), e);
}
}

private Stream<ClassModifyingPlugin> userDefinedClassModifyingPlugins(final Map<Boolean, List<Object>> pluginTypes) {
return pluginTypes.get(CLASS_MODIFYING_PLUGINS)
.stream()
.map(plugin -> (ClassModifyingPlugin) plugin);
}

try {
return (PluginProvider) Class.forName(className).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | ClassCastException e) {
throw new PluginProviderException(format("Unable to create instance of pojo plugin provider with class name %s", className), e);
private Stream<ClassModifyingPlugin> defaultClassModifyingPlugins(final Map<String, String> generatorProperties) {
if (isExcludeDefaultPlugins(generatorProperties)) {
return Stream.empty();
}

return Stream.of(
new AddFieldsAndMethodsToClassPlugin(),
new GenerateBuilderForClassPlugin(new BuilderGeneratorFactory()));
}

private boolean isExcludeDefaultPlugins(final Map<String, String> generatorProperties) {
if (generatorProperties.containsKey(EXCLUDE_DEFAULT_PROPERTY)) {
return Boolean.valueOf(generatorProperties.get(EXCLUDE_DEFAULT_PROPERTY));
}

return false;
}

private Stream<Object> allInstancesOfPluginsFrom(final Map<String, String> 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 new DefaultPluginProvider();
return Stream.empty();
}

private Object pluginInstance(final String className) {
try {
return Class.forName(className.trim()).newInstance();
} catch (final InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new PluginProviderException(format(UNABLE_TO_CREATE_INSTANCE_MESSAGE, className), e);
}
}
}

This file was deleted.

Loading

0 comments on commit af9f940

Please sign in to comment.