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

org.nuiton.jaxx.plugin.GenerateMojo Maven / Gradle / Ivy

There is a newer version: 3.1.5
Show newest version
/*
 * #%L
 * JAXX :: Maven plugin
 * %%
 * Copyright (C) 2008 - 2024 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%
 */

package org.nuiton.jaxx.plugin;

import io.ultreia.java4all.i18n.I18n;
import io.ultreia.java4all.i18n.spi.builder.I18nModule;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.nuiton.io.MirroredFileUpdater;
import org.nuiton.jaxx.compiler.CompiledObjectDecorator;
import org.nuiton.jaxx.compiler.CompilerConfiguration;
import org.nuiton.jaxx.compiler.I18nHelper;
import org.nuiton.jaxx.compiler.JAXXCompiler;
import org.nuiton.jaxx.compiler.JAXXEngine;
import org.nuiton.jaxx.compiler.JAXXFactory;
import org.nuiton.jaxx.compiler.beans.BeanInfoUtil;
import org.nuiton.jaxx.compiler.binding.DataBindingHelper;
import org.nuiton.jaxx.compiler.css.StylesheetHelper;
import org.nuiton.jaxx.compiler.finalizers.JAXXCompilerFinalizer;
import org.nuiton.jaxx.compiler.spi.DefaultInitializer;
import org.nuiton.jaxx.compiler.spi.Initializer;
import org.nuiton.jaxx.runtime.JAXXContext;
import org.nuiton.jaxx.runtime.JAXXObject;
import org.nuiton.jaxx.runtime.spi.UIHandler;
import org.nuiton.jaxx.validator.swing.SwingValidator;
import org.nuiton.plugin.PluginHelper;

import java.beans.Introspector;
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Generates some java code from jaxx files.
 *
 * @author Tony Chemit - [email protected]
 */
@Mojo(name = "generate", defaultPhase = LifecyclePhase.PROCESS_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE)
public class GenerateMojo extends AbstractJaxxMojo implements CompilerConfiguration {

    /**
     * Directory where jaxx files are located.
     */
    @Parameter(property = "jaxx.src", defaultValue = "${basedir}/src/main/java")
    protected File src;

    /**
     * Where to generate java files.
     */
    @Parameter(property = "jaxx.outJava", defaultValue = "${basedir}/target/generated-sources/java")
    protected File outJava;

    /**
     * To filter file to treat.
     */
    @Parameter(property = "jaxx.includes")
    protected String[] includes;

    /**
     * To filter files to NOt treat.
     */
    @Parameter(property = "jaxx.excludes")
    protected String[] excludes;

    /**
     * FQN of compiler to use (by default swing one).
     */
    @Parameter(property = "jaxx.compilerFQN", defaultValue = "org.nuiton.jaxx.compiler.JAXXCompiler", required = true)
    protected String compilerFQN;

    /**
     * The name of implementation of {@link JAXXContext}to be used on {@link JAXXObject}.
     * 

* Must not be abstract. */ @Parameter(property = "jaxx.jaxxContextFQN", defaultValue = "org.nuiton.jaxx.runtime.context.DefaultJAXXContext", required = true) protected String jaxxContextFQN; /** * The FQN of the ui to use for error notification. *

* If not given, will use the one defined in validator */ @Parameter(property = "jaxx.defaultErrorUIFQN", defaultValue = "org.nuiton.jaxx.validator.swing.ui.ImageValidationUI") protected String defaultErrorUIFQN; /** * The FQN of the ui to use for error notification. *

* If not given, will use the one defined in validator * * @see CompiledObjectDecorator */ @Parameter(property = "jaxx.defaultDecoratorFQN", defaultValue = "org.nuiton.jaxx.compiler.decorators.DefaultCompiledObjectDecorator") protected String defaultDecoratorFQN; /** * Flag to include in compiler classpath the java sources directories (src * and outJava). *

* By default, false. */ @Parameter(property = "jaxx.addSourcesToClassPath", defaultValue = "true") protected boolean addSourcesToClassPath; /** * Flag to include in compiler classpath the java resources directories (src * and outJava). *

* By default, false. * * @since 1.6.0 */ @Parameter(property = "jaxx.addResourcesToClassPath", defaultValue = "false") protected boolean addResourcesToClassPath; /** * Flag to include in compiler classpath the compile class-path (can only be * used in a test phase). *

* By default, false. * * @since 1.6.0 */ @Parameter(property = "jaxx.addCompileClassPath", defaultValue = "false") protected boolean addCompileClassPath; /** * Flag to include in compiler classpath the project compile classpath. *

* By default, false. */ @Parameter(property = "jaxx.addProjectClassPath", defaultValue = "true") protected boolean addProjectClassPath; /** * A flag to mark the mojo to be used in a test phase. This will permits to * add generated sources in test compile roots. * * @since 1.6.0 */ @Parameter(property = "jaxx.testPhase", defaultValue = "false") protected boolean testPhase; /** * To make compiler i18nable, says add the {@link I18n#t(String, Object...)} * method invocation on {@link I18nHelper#I18N_ATTRIBUTES} attributes. * * @see I18nHelper */ @Parameter(property = "jaxx.i18nable", defaultValue = "true") protected boolean i18nable; /** * To optimize generated code. */ @Parameter(property = "jaxx.optimize", defaultValue = "false") protected boolean optimize; /** * To let jaxx recurses in css when a JAXX Object auto import css files * for a jaxx file. *

* Warning: This option will be removed in version 3.0 or at least * default value will become {@code false}. * * @since 2.0.2 */ @Parameter(property = "jaxx.autoRecurseInCss", defaultValue = "false") protected boolean autoRecurseInCss; /** * Flag to add logger to each generated jaxx file. *

* By default, always add it. */ @Parameter(property = "jaxx.addLogger", defaultValue = "true") protected boolean addLogger; /** * Flag to keep compilers after the generate operation (usefull for tests. *

* By default, always reset. */ @Parameter(property = "jaxx.resetAfterCompile", defaultValue = "true") protected boolean resetAfterCompile; /** * Extra path to be added in {@link Introspector#setBeanInfoSearchPath(String[])}. *

* add beanInfoSearchPath to be registred by {@link BeanInfoUtil#addJaxxBeanInfoPath(String...)} *

* and then will be use by {@link DefaultInitializer#initialize()}. *

*

* This permit to use real beanInfo of imported graphic libraries. */ @Parameter(property = "jaxx.beanInfoSearchPath") protected String[] beanInfoSearchPath; /** * List of fqn of class toimport for all generated jaxx files. */ @Parameter(property = "jaxx.extraImportList") protected String extraImportList; /** * A flag to use UIManager to retreave icons. */ @Parameter(property = "jaxx.useUIManagerForIcon", defaultValue = "true") protected boolean useUIManagerForIcon; /** * flag to activate profile mode. *

* By default, not active. */ @Parameter(property = "jaxx.profile", defaultValue = "false") protected boolean profile; /** * To show detected bindings. *

* By default, do not show them. * * @since 2.0.0 */ @Parameter(property = "jaxx.showBinding", defaultValue = "false") protected boolean showBinding; /** * the FQN of validator factory. *

* By default, use the JAXX implementation {@link SwingValidator}. * * @since 2.6 */ @Parameter(property = "jaxx.validatorFactoryFQN", defaultValue = "org.nuiton.jaxx.validator.swing.SwingValidator") protected String validatorFactoryFQN; /** * To trace class descriptor loading. *

* By default, do not trace it. * * @since 2.4 */ @Parameter(property = "jaxx.showClassDescriptorLoading", defaultValue = "false") private boolean showClassDescriptorLoading; /** * For each jaxx file, try to add a {@link UIHandler} on it. *

* The fqn of the handler must be jaxxFileName{@code Handler}. * * @since 2.6 */ @Parameter(property = "jaxx.addAutoHandlerUI", defaultValue = "true") private boolean addAutoHandlerUI; /** * To detect action from conventions (says in actions sub package with classes with same name as button). * * Default behaviour should be {@code true} on version 3, bu tstill stay to {@code false} until we migrate all the widgets. * @since 3.0 */ @Parameter(property = "jaxx.detectAction", defaultValue = "false") private boolean detectAction; /** * For each jaxx file, generate the rules in the css files for the ids and style classes which have not been defined. * * @since 2.29 */ @Parameter(property = "jaxx.generateMissingIdsInCss", defaultValue = "false") private boolean generateMissingIdsAndStyleClassesInCss; /** * A optional common css (must be an uri) to inject in all jaxx files. * * Can be in class path if you start your uri by classpath: * * @since 2.13 */ @Parameter(property = "jaxx.commonCss") private String commonCss; /** * The extension of css files. * * @since 2.28 */ @Parameter(property = "jaxx.cssExtension", defaultValue = DEFAULT_CSS_EXTENSION) private String cssExtension; /** * To generate i18n helper from i18n keys files. * * @since 3.0 */ @Parameter(property = "jaxx.generateI18nHelper") private boolean generateI18nHelper; /** * To apply i18n helper from i18n keys files. * * @since 3.0 */ @Parameter(property = "jaxx.applyI18nHelper") private boolean applyI18nHelper; /** * Decorators available in engine. * * @since 2.0.2 */ @Component(role = CompiledObjectDecorator.class) protected Map decorators; /** * Finalizers available in engine. * * @since 2.0.2 */ @Component(role = JAXXCompilerFinalizer.class) protected Map finalizers; /** * Initializers available to init engine. * * @since 2.0.2 */ @Component(role = Initializer.class) protected Map initializers; /** detected jaxx files in {@link #init()} method */ protected String[] files; /** * file updater used to detect jaxx files. *

* Note: if {@link #isVerbose()} flag is on, will ne be used */ protected MirroredFileUpdater updater; /** type of error ui class (in validation) to use */ private Class defaultErrorUIClass; /** type of {@link CompiledObjectDecorator} to use */ private Class defaultDecoratorClass; /** type of {@link JAXXContext} to use */ private Class jaxxContextClass; /** type of compiler to use */ private Class compilerClass; /** extra imports to always add in each generated java file */ private String[] extraImports; /** internal state to known if a files has to be generated */ private boolean nofiles; /** customized classloader to use in engine */ protected ClassLoader cl; /** JAXX engine */ private JAXXEngine engine; private URL commonCssURI; private I18nModule i18nModule; @SuppressWarnings("unchecked") @Override public void init() throws Exception { if (getLog().isDebugEnabled()) { // if debug is on, then verbose also setVerbose(true); } fixCompileSourceRoots(); if (cssExtension == null) { cssExtension = DEFAULT_CSS_EXTENSION; } if (includes == null || includes.length == 0) { // use default includes includes = new String[]{"**/*.jaxx", "**/*." + cssExtension}; } updater = new JaxxFileUpdater(cssExtension, src, outJava); Map result = new HashMap<>(); getFilesToTreateForRoots( includes, excludes, Collections.singletonList(src.getAbsolutePath()), result, isForce() ? null : updater); files = result.get(src); // Evolution #435: Regenerates jaxx files when his css file is modified // filter css and jaxx files to obtain only jaxx files // if a css is modified, try to find the corresponding jaxx files if (files != null && files.length > 0) { Set filterFiles = new HashSet<>(files.length); int cssExtensionLength = cssExtension.length() + 1; for (String path : files) { if (path.endsWith("." + cssExtension)) { // take the jaxx file String jaxxFilePath = path.substring(0, path.length() - cssExtensionLength) + ".jaxx"; File f = new File(src, jaxxFilePath); if (f.exists()) { if (isVerbose()) { getLog().info("will treate jaxx file from css " + f); } filterFiles.add(jaxxFilePath); } continue; } if (path.endsWith(".jaxx")) { filterFiles.add(path); } } files = filterFiles.toArray(new String[0]); } nofiles = files == null || files.length == 0; if (nofiles) { if (getLog().isDebugEnabled()) { getLog().debug("No file to treate."); } return; } cl = initClassLoader(getProject(), src, addSourcesToClassPath, testPhase, addResourcesToClassPath, addCompileClassPath, addProjectClassPath); Thread.currentThread().setContextClassLoader(cl); compilerClass = (Class) Class.forName(compilerFQN, false, cl); defaultDecoratorClass = (Class) Class.forName(defaultDecoratorFQN, false, cl); jaxxContextClass = (Class) Class.forName(jaxxContextFQN, false, cl); if (!JAXXContext.class.isAssignableFrom(jaxxContextClass)) { throw new MojoExecutionException( "jaxxContextFQN must be an implementation of " + JAXXContext.class + " but was : " + jaxxContextClass); } // validatorClass = Class.forName(validatorFQN, false, cl); if (defaultErrorUIFQN != null && !defaultErrorUIFQN.trim().isEmpty()) { defaultErrorUIClass = Class.forName(defaultErrorUIFQN, false, cl); } if (beanInfoSearchPath != null && beanInfoSearchPath.length > 0) { // register extra path BeanInfoUtil.addJaxxBeanInfoPath(beanInfoSearchPath); } if (StringUtils.isNotEmpty(commonCss)) { commonCssURI = StylesheetHelper.getStyleURL(commonCss, null, cl); if (commonCssURI == null) { throw new MojoFailureException("Can't find commonCss in classpath from " + commonCss); } } createDirectoryIfNecessary(getTargetDirectory()); // compute extra imports (can not use java classes since some of // imports can not be still compiled) if (extraImportList != null && !extraImportList.isEmpty()) { String[] imports = extraImportList.split(","); int i = 0; for (String importS : imports) { imports[i++] = importS.trim(); } if (isVerbose()) { getLog().info("extra imports " + Arrays.toString(imports)); } extraImports = imports; } if (i18nable) { i18nModule = I18nModule.forGetter(getProject().getProperties()); } if (isVerbose()) { // getLog().info(toString()); getLog().info("includes : " + Arrays.toString(includes)); for (String file : files) { getLog().info("will parse " + file); } } } @Override protected boolean checkSkip() { if (nofiles) { getLog().info("Nothing to generate - all files are up to date."); return false; } return true; } @Override public void doAction() throws Exception { getLog().info("Detects " + files.length + " modified jaxx file(s). "); if (showBinding) { DataBindingHelper.SHOW_LOG = showBinding; } try { long t0 = System.nanoTime(); // register configuration to factory JAXXFactory.setConfiguration(this); // create new engine engine = JAXXFactory.newEngine(src, files); //FIXME-TC20100502 remove this managment by -1 for error! // run engine int nbFiles = engine.run(); // report engine results (errors, warnings,...) report(engine); if (nbFiles == -1) { throw new MojoExecutionException( "Aborting due to errors reported by jaxxc"); } String delay = PluginHelper.convertTime(System.nanoTime() - t0); getLog().info("Generated " + nbFiles + " file(s) in " + delay); } finally { DataBindingHelper.SHOW_LOG = false; } } @Override public File getTargetDirectory() { return outJava; } @Override public void setTargetDirectory(File targetDirectory) { outJava = targetDirectory; } @Override public boolean getOptimize() { return optimize; } @Override public boolean isAutoRecurseInCss() { return autoRecurseInCss; } @Override public boolean isI18nable() { return i18nable; } @Override public boolean isUseUIManagerForIcon() { return useUIManagerForIcon; } @Override public boolean isAddLogger() { return addLogger; } @Override public boolean isShowClassDescriptorLoading() { return showClassDescriptorLoading; } @Override public boolean isDetectAction() { return detectAction; } @Override public void setDetectAction(boolean detectAction) { this.detectAction = detectAction; } @Override public boolean isAddAutoHandlerUI() { return addAutoHandlerUI; } @Override public void setAddAutoHandlerUI(boolean addAutoHandlerUI) { this.addAutoHandlerUI = addAutoHandlerUI; } @Override public boolean isGenerateMissingIdsAndStyleClassesInCss() { return generateMissingIdsAndStyleClassesInCss; } @Override public void setGenerateMissingIdsAndStyleClassesInCss(boolean generateMissingIdsAndStyleClassesInCss) { this.generateMissingIdsAndStyleClassesInCss = generateMissingIdsAndStyleClassesInCss; } @Override public Class getJaxxContextClass() { return jaxxContextClass; } @Override public String[] getExtraImports() { return extraImports; } @Override public boolean isResetAfterCompile() { return resetAfterCompile; } @Override public boolean isOptimize() { return optimize; } @Override public Class getDefaultErrorUI() { return defaultErrorUIClass; } @Override public ClassLoader getClassLoader() { return cl; } @Override public Class getCompilerClass() { return compilerClass; } @Override public Class getDefaultDecoratorClass() { return defaultDecoratorClass; } @Override public boolean isProfile() { return profile; } @Override public String getValidatorFactoryFQN() { return validatorFactoryFQN; } @Override public Map getDecorators() { return decorators; } @Override public Map getFinalizers() { return finalizers; } @Override public Map getInitializers() { return initializers; } @Override public URL getCommonCss() { return commonCssURI; } @Override public String getCssExtension() { return cssExtension; } @Override public I18nModule getI18nModule() { return i18nModule; } @Override public void setI18nModule(I18nModule i18nModule) { this.i18nModule=i18nModule; } public JAXXEngine getEngine() { return engine; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } protected void fixCompileSourceRoots() { //FIXME TC20091222 : why this test ? should always have a project ? // even in tests... if (getProject() == null) { // no project defined, can not fix anything // this case could appear if we wanted to do some tests of the plugin return; } if (testPhase) { addTestCompileSourceRoots(getTargetDirectory()); } else { addCompileSourceRoots(getTargetDirectory()); } } protected void report(JAXXEngine engine) { List warnings = engine.getWarnings(); if (!warnings.isEmpty()) { StringBuilder buffer = new StringBuilder( "JAXX detects " + (warnings.size() == 1 ? "1 warning" : warnings.size() + " warnings")); buffer.append(" :"); for (String s : warnings) { buffer.append("\n").append(s); } getLog().warn(buffer.toString()); } List errors = engine.getErrors(); if (!errors.isEmpty()) { StringBuilder buffer = new StringBuilder( "JAXX detects " + (errors.size() == 1 ? "1 error" : errors.size() + " errors")); buffer.append(" :"); for (String s : errors) { buffer.append("\n").append(s); } getLog().error(buffer.toString()); } } @Override public boolean isGenerateI18nHelper() { return generateI18nHelper; } @Override public void setGenerateI18nHelper(boolean generateI18nHelper) { this.generateI18nHelper = generateI18nHelper; } @Override public boolean isApplyI18nHelper() { return applyI18nHelper; } @Override public void setApplyI18nHelper(boolean applyI18nHelper) { this.applyI18nHelper = applyI18nHelper; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy