All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ultreia.java4all.config.plugin.templates.ApplicationConfigTransformer Maven / Gradle / Ivy

There is a newer version: 1.0.29
Show newest version
package io.ultreia.java4all.config.plugin.templates;

/*-
 * #%L
 * Config :: Maven plugin
 * %%
 * Copyright (C) 2016 - 2018 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import io.ultreia.java4all.config.ApplicationConfig;
import io.ultreia.java4all.config.ApplicationConfigInit;
import io.ultreia.java4all.config.ApplicationConfigProvider;
import io.ultreia.java4all.config.ConfigActionDef;
import io.ultreia.java4all.config.ConfigOptionDef;
import io.ultreia.java4all.config.io.spi.ActionModel;
import io.ultreia.java4all.config.io.spi.ConfigModel;
import io.ultreia.java4all.config.io.spi.OptionModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.codehaus.plexus.util.StringUtils;
import org.nuiton.eugene.GeneratorUtil;
import org.nuiton.eugene.java.JavaGeneratorUtil;
import org.nuiton.eugene.java.ObjectModelTransformerToJava;
import org.nuiton.eugene.models.object.ObjectModel;
import org.nuiton.eugene.models.object.ObjectModelClass;
import org.nuiton.eugene.models.object.ObjectModelEnumeration;
import org.nuiton.eugene.models.object.ObjectModelJavaModifier;
import org.nuiton.eugene.models.object.ObjectModelOperation;
import org.nuiton.i18n.I18n;
import org.nuiton.i18n.spi.GetterFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.Supplier;




/**
 * To generate configuration java files from the options enum file.
 * 

* Created on 15/09/16. * * @author Tony Chemit - [email protected] * @since 3.0 */ public class ApplicationConfigTransformer extends ObjectModelTransformerToJava { private static final Logger log = LogManager.getLogger(ApplicationConfigTransformer.class); public static final String PROP_CONFIG = "config"; private ApplicationConfigTransformerConfig config; private GetterFile getterFile; @Override public void transformFromModel(ObjectModel model) { super.transformFromModel(model); config = getConfiguration().getProperty(PROP_CONFIG, ApplicationConfigTransformerConfig.class); ConfigModel configModel = config.getConfigModel(); boolean useNuitonI18n = config.isUseNuitonI18n(); if (useNuitonI18n) { getterFile = new GetterFile(config.getI18nGettersDirectory(), "config.getter"); } String packageName = config.getPackageName(); String configClassName = config.getConfigClassName(); String configProviderClassName = config.getConfigProviderClassName(); String optionsClassName = config.getOptionsClassName(); List options = configModel.getOptions(); String actionsClassName = config.getActionsClassName(); List actions = configModel.getActions(); boolean withActions = CollectionUtils.isNotEmpty(actions); String abstractClassName = "Generated" + configClassName; generateConfigAbstractClass(packageName, abstractClassName, optionsClassName, actionsClassName, options, withActions); if (canGenerate(packageName + "." + configClassName)) { generateConfigClass(packageName, configClassName, abstractClassName); } else { if (log.isDebugEnabled()) { log.debug("Skip generation for " + configClassName); } } if (config.isGenerateProvider()) { String abstractProviderClassName = "Generated" + configProviderClassName; generateProviderAbstractClass(packageName, abstractProviderClassName, configClassName, optionsClassName, actionsClassName, useNuitonI18n, configModel.getDescription(), withActions); if (canGenerate(packageName + "." + configProviderClassName)) { generateProviderClass(packageName, abstractProviderClassName, configProviderClassName); } } if (canGenerate(packageName + "." + optionsClassName)) { generateOptionsClass(packageName, useNuitonI18n, optionsClassName, options); } if (withActions && canGenerate(packageName + "." + actionsClassName)) { generateActionsClass(packageName, actionsClassName, actions, useNuitonI18n); } if (useNuitonI18n) { try { getterFile.store(); } catch (IOException e) { throw new IllegalStateException("Can't store i18n getter file: " + getterFile, e); } } } private void generateOptionsClass(String packageName, boolean useNuitonI18n, String optionsClassName, List options) { ObjectModelEnumeration output = createEnumeration(optionsClassName, packageName); addInterface(output, ConfigOptionDef.class); if (useNuitonI18n) { addImport(output, I18n.class); } if (log.isInfoEnabled()) { log.info("Generate " + output.getQualifiedName()); } for (OptionModel option : options) { String literalName = GeneratorUtil.convertVariableNameToConstantName(option.getName()); String defaultValue = option.getDefaultValue(); if (defaultValue != null) { defaultValue = "\"" + defaultValue + "\""; } String description = "\"" + option.getDescription() + "\""; if (useNuitonI18n) { description = "I18n.n(" + description + ")"; getterFile.addKey(option.getDescription()); } String literal = "" +"\n" +" "+literalName+"(\n" +" "+option.getType()+".class,\n" +" \""+option.getKey()+"\",\n" +" "+description+",\n" +" "+defaultValue+",\n" +" "+option.isTransient()+",\n" +" "+option.isFinal()+")"; addLiteral(output, literal); } addAttribute(output, "type", Class.class, null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL); addAttribute(output, "key", String.class, null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL); addAttribute(output, "description", String.class, null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL); addAttribute(output, "defaultValue", String.class, null, ObjectModelJavaModifier.PRIVATE); addAttribute(output, "_transient", boolean.class, null, ObjectModelJavaModifier.PRIVATE); addAttribute(output, "_final", boolean.class, null, ObjectModelJavaModifier.PRIVATE); ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PACKAGE); addParameter(constructor, Class.class, "type"); addParameter(constructor, String.class, "key"); addParameter(constructor, String.class, "description"); addParameter(constructor, String.class, "defaultValue"); addParameter(constructor, boolean.class, "_transient"); addParameter(constructor, boolean.class, "_final"); setOperationBody(constructor, "" +"\n" +" this.type = type;\n" +" this.key = key;\n" +" this.description = description;\n" +" this.defaultValue = defaultValue;\n" +" this._final = _final;\n" +" this._transient = _transient;\n" +" " ); ObjectModelOperation getKey = addOperation( output, "getKey", String.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getKey, Override.class); setOperationBody(getKey, "" +"\n" +" return key;\n" +" " ); ObjectModelOperation getType = addOperation( output, "getType", Class.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getType, Override.class); setOperationBody(getType, "" +"\n" +" return type;\n" +" " ); ObjectModelOperation getDescription = addOperation( output, "getDescription", String.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getDescription, Override.class); String descriptionValue = "description"; if (useNuitonI18n) { descriptionValue = "I18n.t(" + descriptionValue + ")"; } setOperationBody(getDescription, "" +"\n" +" return "+descriptionValue+";\n" +" " ); ObjectModelOperation getDefaultValue = addOperation( output, "getDefaultValue", String.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getDefaultValue, Override.class); setOperationBody(getDefaultValue, "" +"\n" +" return defaultValue;\n" +" " ); ObjectModelOperation setDefaultValue = addOperation( output, "setDefaultValue", void.class, ObjectModelJavaModifier.PUBLIC); addParameter(setDefaultValue, String.class, "defaultValue"); addAnnotation(output, setDefaultValue, Override.class); setOperationBody(setDefaultValue, "" +"\n" +" this.defaultValue = defaultValue;\n" +" " ); ObjectModelOperation isTransient = addOperation( output, "isTransient", boolean.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, isTransient, Override.class); setOperationBody(isTransient, "" +"\n" +" return _transient;\n" +" " ); ObjectModelOperation setTransient = addOperation( output, "setTransient", void.class, ObjectModelJavaModifier.PUBLIC); addParameter(setTransient, boolean.class, "_transient"); addAnnotation(output, setTransient, Override.class); setOperationBody(setTransient, "" +"\n" +" this._transient = _transient;\n" +" " ); ObjectModelOperation isFinal = addOperation( output, "isFinal", boolean.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, isFinal, Override.class); setOperationBody(isFinal, "" +"\n" +" return _final;\n" +" " ); ObjectModelOperation setFinal = addOperation( output, "setFinal", void.class, ObjectModelJavaModifier.PUBLIC); addParameter(setFinal, boolean.class, "_final"); addAnnotation(output, setFinal, Override.class); setOperationBody(setFinal, "" +"\n" +" this._final = _final;\n" +" " ); } private void generateActionsClass(String packageName, String actionsClassName, List actions, boolean useNuitonI18n) { ObjectModelEnumeration output = createEnumeration(actionsClassName, packageName); addInterface(output, ConfigActionDef.class); if (log.isInfoEnabled()) { log.info("Generate " + output.getQualifiedName()); } if (useNuitonI18n) { addImport(output, I18n.class); } for (ActionModel action : actions) { String literalName = GeneratorUtil.convertVariableNameToConstantName(action.getName()); String aliases = ""; if (action.getAliases().length > 0) { aliases = ", \"" + Joiner.on("\", \"").join(action.getAliases()) + "\""; } String description = "\"" + action.getDescription() + "\""; if (useNuitonI18n) { description = "I18n.n(" + description + ")"; getterFile.addKey(action.getDescription()); } String literal = "" +"\n" +" "+literalName+" ( \""+action.getAction()+"\", "+description+""+aliases+" )"; addLiteral(output, literal); } addAttribute(output, "action", String.class, null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL); addAttribute(output, "description", String.class, null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL); addAttribute(output, "aliases", "String[]", null, ObjectModelJavaModifier.PRIVATE, ObjectModelJavaModifier.FINAL); ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PACKAGE); addParameter(constructor, String.class, "action"); addParameter(constructor, String.class, "description"); addParameter(constructor, "String...", "aliases"); setOperationBody(constructor, "" +"\n" +" this.action = action;\n" +" this.description = description;\n" +" this.aliases = aliases;\n" +" " ); ObjectModelOperation getAction = addOperation( output, "getAction", String.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getAction, Override.class); setOperationBody(getAction, "" +"\n" +" return action;\n" +" " ); ObjectModelOperation getAliases = addOperation( output, "getAliases", "String[]", ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getAliases, Override.class); setOperationBody(getAliases, "" +"\n" +" return aliases;\n" +" " ); ObjectModelOperation getDescription = addOperation( output, "getDescription", String.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getDescription, Override.class); String descriptionValue = "description"; if (useNuitonI18n) { descriptionValue = "I18n.t(" + descriptionValue + ")"; } setOperationBody(getDescription, "" +"\n" +" return "+descriptionValue+";\n" +" " ); } private void generateProviderAbstractClass(String packageName, String providerClassName, String className, String optionClassName, String actionClassName, boolean useNuitonI18n, String description, boolean withActions) { ObjectModelClass output = createAbstractClass(providerClassName, packageName); addInterface(output, ApplicationConfigProvider.class); if (log.isInfoEnabled()) { log.info("Generate " + output.getQualifiedName()); } ObjectModelOperation getName = addOperation( output, "getName", String.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getName, Override.class); setOperationBody(getName, "" +"\n" +" return \""+className+"\";\n" +" " ); if (useNuitonI18n) { addImport(output, I18n.class); } String optionClassSimpleName = GeneratorUtil.getSimpleName(optionClassName); ObjectModelOperation getOptions = addOperation( output, "getOptions", optionClassName + "[]", ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getOptions, Override.class); setOperationBody(getOptions, "" +"\n" +" return "+optionClassSimpleName+".values();\n" +" " ); if (withActions) { String actionClassSimpleName = GeneratorUtil.getSimpleName(actionClassName); ObjectModelOperation getActions = addOperation( output, "getActions", actionClassName + "[]", ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getActions, Override.class); setOperationBody(getActions, "" +"\n" +" return "+actionClassSimpleName+".values();\n" +" " ); } else { addImport(output, ConfigActionDef.class); ObjectModelOperation getActions = addOperation( output, "getActions", "ConfigActionDef[]", ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getActions, Override.class); setOperationBody(getActions, "" +"\n" +" return new ConfigActionDef[0];\n" +" " ); } String descriptionValue = "\"" + description + "\""; if (useNuitonI18n) { descriptionValue = "I18n.l(locale, " + descriptionValue + ")"; getterFile.addKey(description); } ObjectModelOperation getDescription = addOperation( output, "getDescription", String.class, ObjectModelJavaModifier.PUBLIC); addParameter(getDescription, Locale.class, "locale"); addAnnotation(output, getDescription, Override.class); setOperationBody(getDescription, "" +"\n" +" return "+descriptionValue+";\n" +" " ); } private void generateProviderClass(String packageName, String abstractProviderClassName, String providerClassName) { ObjectModelClass output = createClass(providerClassName, packageName); setSuperClass(output, abstractProviderClassName); addImport(output, I18n.class); if (log.isInfoEnabled()) { log.info("Generate " + output.getQualifiedName()); } } private void generateConfigAbstractClass(String packageName, String abstractClassName, String optionClassName, String actionClassName, List options, boolean withActions) { String optionClassSimpleName = GeneratorUtil.getSimpleName(optionClassName); ObjectModelClass output = createAbstractClass(abstractClassName, packageName); addInterface(output, "java.util.function.Supplier"); addImport(output, "java.util.function.Supplier"); addImport(output, optionClassName); if (log.isInfoEnabled()) { log.info("Generate " + output.getQualifiedName()); } addAttribute(output, "applicationConfig", ApplicationConfig.class, "", ObjectModelJavaModifier.PRIVATE); ObjectModelOperation publicConstructor = addConstructor(output, ObjectModelJavaModifier.PROTECTED); setOperationBody(publicConstructor, "" +"\n" +" this(ApplicationConfigInit.forAllScopes());\n" +" " ); ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PROTECTED); addParameter(constructor, ApplicationConfigInit.class, "init"); StringBuilder builder = new StringBuilder(); builder.append("" +"\n" +" this.applicationConfig = new ApplicationConfig(init);\n" +" this.applicationConfig.loadDefaultOptions("+optionClassSimpleName+".values());\n" +" " ); if (withActions) { addImport(output, actionClassName); String actionClassSimpleName = GeneratorUtil.getSimpleName(actionClassName); builder.append("" +" this.applicationConfig.loadActions("+actionClassSimpleName+".values());\n" +" " ); } setOperationBody(constructor, builder.toString()); ObjectModelOperation getApplicationConfig = addOperation( output, "get", ApplicationConfig.class, ObjectModelJavaModifier.PUBLIC); addAnnotation(output, getApplicationConfig, Override.class); setOperationBody(getApplicationConfig, "" +"\n" +" return applicationConfig;\n" +" " ); ObjectModelOperation setOption = addOperation( output, "setOption", "void", ObjectModelJavaModifier.PROTECTED); addParameter(setOption, String.class, "key"); addParameter(setOption, Object.class, "attrName"); setOperationBody(setOption, "" +"\n" +" applicationConfig.setOption(key, String.valueOf(attrName));\n" +" " ); if (config.isUseGson()) { addImport(output, Supplier.class); addImport(output, Gson.class); addOperation(output, "getGsonSupplier", "Supplier", ObjectModelJavaModifier.PROTECTED, ObjectModelJavaModifier.ABSTRACT); } for (OptionModel option : options) { String attrName = option.getName(); String attrType = option.getType(); String simpleType = JavaGeneratorUtil.getSimpleName(attrType); String constantName = JavaGeneratorUtil.getSimpleName(optionClassName) + "." + JavaGeneratorUtil.convertVariableNameToConstantName(attrName); addImport(output, attrType); boolean useGson = option.isUseGson(); createGetMethod(output, attrName, simpleType, constantName, useGson); createSetMethod(output, attrName, simpleType, constantName, useGson); } ObjectModelOperation getConfigurationDescription = addOperation( output, "getConfigurationDescription", String.class, ObjectModelJavaModifier.PUBLIC); setOperationBody(getConfigurationDescription, "" +"\n" +" StringBuilder builder = new StringBuilder();\n" +" builder.append(\"\\n=====================================================================================================================\");\n" +" builder.append(\"\\n=== Configuration ===================================================================================================\");\n" +" builder.append(\"\\n=====================================================================================================================\");\n" +" for ("+optionClassSimpleName+" option : orderedByKey()) {\n" +" Object optionValue = get().getOption(option.getKey());\n" +" builder.append(String.format(\"\\n=== %1$-40s = %2$s\", option.getKey(), optionValue == null ? \"Not defined\" : optionValue));\n" +" }\n" +" builder.append(\"\\n=====================================================================================================================\");\n" +" return builder.toString();\n" +" " ); ObjectModelOperation orderedByKey = addOperation( output, "orderedByKey", "List<" + optionClassSimpleName + ">", ObjectModelJavaModifier.PROTECTED); addImport(output, List.class); addImport(output, Arrays.class); addImport(output, Collections.class); addImport(output, Comparator.class); setOperationBody(orderedByKey, "" +"\n" +" List<"+optionClassSimpleName+"> values = Arrays.asList("+optionClassSimpleName+".values());\n" +" Collections.sort(values, new Comparator<"+optionClassSimpleName+">() {\n" +" @Override\n" +" public int compare("+optionClassSimpleName+" o1, "+optionClassSimpleName+" o2) {\n" +" return o1.getKey().compareTo(o2.getKey());\n" +" }\n" +" });\n" +" return Collections.unmodifiableList(values);\n" +" " ); } private void generateConfigClass(String packageName, String className, String abstractClassName) { ObjectModelClass output = createClass(className, packageName); if (log.isInfoEnabled()) { log.info("Generate " + output.getQualifiedName()); } setSuperClass(output, abstractClassName); ObjectModelOperation publicConstructor = addConstructor(output, ObjectModelJavaModifier.PUBLIC); setOperationBody(publicConstructor, "" +"\n" +" super();\n" +" " ); ObjectModelOperation constructor = addConstructor(output, ObjectModelJavaModifier.PUBLIC); addParameter(constructor, ApplicationConfigInit.class, "init"); setOperationBody(constructor, "" +"\n" +" super(init);\n" +" " ); } private boolean canGenerate(String input) { return !getResourcesHelper().isJavaFileInClassPath(input); } private static final Set KNOWN_TYPES = ImmutableSet.of( "File", "Color", "KeyStroke", "URL", "Class", "Date", "Time", "Timestamp", "Locale", "Version", "String", "int", "Integer", "long", "Long", "float", "Float", "boolean", "Boolean", "byte", "Byte", "char", "Character", "double", "Double"); private void createGetMethod(ObjectModelClass output, String attrName, String simpleType, String constantName, boolean useGson) { boolean booleanProperty = GeneratorUtil.isBooleanPrimitive(simpleType); String methodPrefix = booleanProperty ? JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX : JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX; String methodName = "getOptionAs" + StringUtils.capitalise(simpleType); if (simpleType.equals("String")) { methodName = "getOption"; } else if (simpleType.equals("Integer")) { methodName = "getOptionAsInt"; } ObjectModelOperation operation = addOperation( output, getJavaBeanMethodName(methodPrefix, attrName), simpleType, ObjectModelJavaModifier.PUBLIC ); if (useGson) { setOperationBody(operation, "" +"\n" +" String option = applicationConfig.getOption("+constantName+".getKey());\n" +" return getGsonSupplier().get().fromJson(option, "+simpleType+".class);\n" +" " ); } else if (!KNOWN_TYPES.contains(simpleType)) { methodName = "getOption"; setOperationBody(operation, "" +"\n" +" return ("+simpleType+") applicationConfig."+methodName+"("+simpleType+".class, "+constantName+".getKey());\n" +" " ); } else { setOperationBody(operation, "" +"\n" +" return applicationConfig."+methodName+"("+constantName+".getKey());\n" +" " ); if ("Boolean".equals(simpleType)) { operation = addOperation( output, getJavaBeanMethodName(JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX, attrName), "boolean", ObjectModelJavaModifier.PUBLIC ); setOperationBody(operation, "" +"\n" +" return applicationConfig."+methodName+"("+constantName+".getKey());\n" +" " ); } } } private void createSetMethod(ObjectModelClass output, String attrName, String simpleType, String constantName, boolean useGson) { boolean booleanProperty = GeneratorUtil.isBooleanPrimitive(simpleType); ObjectModelOperation operation = addOperation( output, getJavaBeanMethodName("set", attrName), "void", ObjectModelJavaModifier.PUBLIC ); addParameter(operation, simpleType, attrName); String methodPrefix = booleanProperty ? JavaGeneratorUtil.OPERATION_GETTER_BOOLEAN_PREFIX : JavaGeneratorUtil.OPERATION_GETTER_DEFAULT_PREFIX; String methodName = getJavaBeanMethodName(methodPrefix, attrName); StringBuilder bodyContent = new StringBuilder(); if (useGson) { bodyContent.append("" +"\n" +" String option = getGsonSupplier().get().toJson("+attrName+");\n" +" setOption("+constantName+".getKey(), option);\n" +" " ); } else { bodyContent.append("" +" setOption("+constantName+".getKey(), "+attrName+");\n" +" " ); } setOperationBody(operation, bodyContent.toString()); if ("Boolean".equals(simpleType)) { operation = addOperation( output, getJavaBeanMethodName("set", attrName), "void", ObjectModelJavaModifier.PUBLIC ); addParameter(operation, "boolean", attrName); setOperationBody(operation, "" +"\n" +" setOption("+constantName+".getKey(), "+attrName+");\n" +" " ); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy