MYFACES-2938 Allow @JSFValidator and @JSFConverter to define custom tagHandler class
diff --git a/maven2-plugins/myfaces-builder-annotations/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/annotation/JSFConverter.java b/maven2-plugins/myfaces-builder-annotations/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/annotation/JSFConverter.java
index 915707b..a2338c0 100644
--- a/maven2-plugins/myfaces-builder-annotations/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/annotation/JSFConverter.java
+++ b/maven2-plugins/myfaces-builder-annotations/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/annotation/JSFConverter.java
@@ -80,4 +80,44 @@
* @since 1.0.3
*/
String serialuidtag() default "";
+
+ /**
+ * The fully-qualified-name of a concrete converter class.
+ * <p>
+ * This attribute is only relevant when "name" is also set, ie the
+ * annotation is indicating that a converter is really being declared.
+ * <p>
+ * When this attribute is not defined then it is assumed that this
+ * annotated class is the actual converter class.
+ * <p>
+ * When this attribute is set to something other than the name of the
+ * annotated class then the specified class is the one that the JSF
+ * converter registration in faces-config.xml will refer to. And if that
+ * class does not exist in the classpath (which will normally be the
+ * case) then code-generation will be triggered to create it.
+ * <p>
+ * This attribute is not inheritable.
+ * <p>
+ * The doclet-annotation equivalent of this attribute is named "class".
+ *
+ * @since 1.0.7
+ */
+ String clazz() default "";
+
+ /**
+ * Indicate tag handler class used for this component on facelets.
+ *
+ * @since 1.0.7
+ */
+ String tagHandler() default "";
+
+ /**
+ * Indicate that the EL Expressions should be stored using
+ * setValueExpression() method, instead evaluate them at build view
+ * time. Later the EL Expressions will be evaluated according to
+ * their needs
+ *
+ * @since 1.0.7
+ */
+ boolean evaluateELOnExecution() default false;
}
diff --git a/maven2-plugins/myfaces-builder-annotations/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/annotation/JSFValidator.java b/maven2-plugins/myfaces-builder-annotations/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/annotation/JSFValidator.java
index 60d43ed..253b4b5 100644
--- a/maven2-plugins/myfaces-builder-annotations/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/annotation/JSFValidator.java
+++ b/maven2-plugins/myfaces-builder-annotations/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/annotation/JSFValidator.java
@@ -104,4 +104,21 @@
* @since 1.0.3
*/
String clazz() default "";
+
+ /**
+ * Indicate tag handler class used for this component on facelets.
+ *
+ * @since 1.0.7
+ */
+ String tagHandler() default "";
+
+ /**
+ * Indicate that the EL Expressions should be stored using
+ * setValueExpression() method, instead evaluate them at build view
+ * time. Later the EL Expressions will be evaluated according to
+ * their needs
+ *
+ * @since 1.0.7
+ */
+ boolean evaluateELOnExecution() default false;
}
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/MakeConvertersMojo.java b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/MakeConvertersMojo.java
new file mode 100644
index 0000000..d56230c
--- /dev/null
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/MakeConvertersMojo.java
@@ -0,0 +1,439 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.buildtools.maven2.plugin.builder;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.project.MavenProject;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.model.Model;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.model.ConverterMeta;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.BuildException;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.MavenPluginConsoleLogSystem;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.utils.MyfacesUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.StringUtils;
+
+import com.thoughtworks.qdox.JavaDocBuilder;
+
+/**
+ * Maven goal to generate java source code for Converter classes.
+ *
+ * <p>It uses velocity to generate templates, and has the option to define custom templates.</p>
+ * <p>The executed template has the following variables available to it:</p>
+ * <ul>
+ * <li>utils : Returns an instance of
+ * org.apache.myfaces.buildtools.maven2.plugin.builder.utils.MyfacesUtils,
+ * it contains some useful methods.</li>
+ * <li>converter : Returns the current instance of
+ * org.apache.myfaces.buildtools.maven2.plugin.builder.model.ConverterMeta</li>
+ * </ul>
+ *
+ *
+ * @since 1.0.8
+ * @version $Id: MakeConvertersMojo.java 942970 2010-05-11 00:36:14Z lu4242 $
+ * @requiresDependencyResolution compile
+ * @goal make-converters
+ * @phase generate-sources
+ */
+public class MakeConvertersMojo extends AbstractMojo
+{
+ /**
+ * Injected Maven project.
+ *
+ * @parameter expression="${project}"
+ * @readonly
+ */
+ private MavenProject project;
+
+ /**
+ * Defines the directory where the metadata file (META-INF/myfaces-metadata.xml) is loaded.
+ *
+ * @parameter expression="${project.build.directory}/myfaces-builder-plugin/main/resources"
+ * @readonly
+ */
+ private File buildDirectory;
+
+ /**
+ * Injected name of file generated by earlier run of BuildMetaDataMojo goal.
+ *
+ * @parameter
+ */
+ private String metadataFile = "META-INF/myfaces-metadata.xml";
+
+ /**
+ * The directory used to load templates into velocity environment.
+ *
+ * @parameter expression="src/main/resources/META-INF"
+ */
+ private File templateSourceDirectory;
+
+ /**
+ * The directory where all generated files are created. This directory is added as a
+ * compile source root automatically like src/main/java is.
+ *
+ * @parameter expression="${project.build.directory}/myfaces-builder-plugin/main/java"
+ */
+ private File generatedSourceDirectory;
+
+ /**
+ * Only generate tag classes that contains that package prefix
+ *
+ * @parameter
+ */
+ private String packageContains;
+
+ /**
+ * Log and continue execution when generating converter classes.
+ * <p>
+ * If this property is set to false (default), errors when a converter class is generated stops
+ * execution immediately.
+ * </p>
+ *
+ * @parameter
+ */
+ private boolean force;
+
+ /**
+ * Defines the jsf version (1.1 or 1.2), used to take the default templates for each version.
+ * <p>
+ * If version is 1.1, the default templateConverterName is 'converterClass11.vm' and if version
+ * is 1.2 the default templateConverterName is 'converterClass12.vm'.
+ * </p>
+ *
+ * @parameter
+ */
+ private String jsfVersion;
+
+ /**
+ * Define the models that should be included when generate converter classes. If not set, the
+ * current model identified by the artifactId is used.
+ * <p>
+ * Each model built by build-metadata goal has a modelId, that by default is the artifactId of
+ * the project. Setting this property defines which objects tied in a specified modelId should
+ * be taken into account.
+ * </p>
+ * <p>In this case, limit converter tag generation only to the components defined in the models
+ * identified by the modelId defined. </p>
+ * <p>This is useful when you need to generate files that take information defined on other
+ * projects.</p>
+ * <p>Example:</p>
+ * <pre>
+ * <modelIds>
+ * <modelId>model1</modelId>
+ * <modelId>model2</modelId>
+ * </modelIds>
+ * </pre>
+ *
+ * @parameter
+ */
+ private List modelIds;
+
+ /**
+ * The name of the template used to generate converter classes. According to the value on
+ * jsfVersion property the default if this property is not set could be converterClass11.vm (1.1) or
+ * converterClass12.vm (1.2)
+ *
+ * @parameter
+ */
+ private String templateConverterName;
+
+ /**
+ * This param is used to search in this folder if some file to
+ * be generated exists and avoid generation and duplicate exception.
+ *
+ * @parameter expression="src/main/java"
+ */
+ private File mainSourceDirectory;
+
+ /**
+ * This param is used to search in this folder if some file to
+ * be generated exists and avoid generation and duplicate exception.
+ *
+ * @parameter
+ */
+ private File mainSourceDirectory2;
+
+ /**
+ * Execute the Mojo.
+ */
+ public void execute() throws MojoExecutionException
+ {
+ // This command makes Maven compile the generated source:
+ // getProject().addCompileSourceRoot( absoluteGeneratedPath.getPath() );
+
+ try
+ {
+ project.addCompileSourceRoot( generatedSourceDirectory.getCanonicalPath() );
+
+ if (modelIds == null)
+ {
+ modelIds = new ArrayList();
+ modelIds.add(project.getArtifactId());
+ }
+ Model model = IOUtils.loadModel(new File(buildDirectory,
+ metadataFile));
+ new Flattener(model).flatten();
+ generateConverters(model);
+ }
+ catch (IOException e)
+ {
+ throw new MojoExecutionException("Error generating converters", e);
+ }
+ catch (BuildException e)
+ {
+ throw new MojoExecutionException("Error generating converters", e);
+ }
+ }
+
+
+ private VelocityEngine initVelocity() throws MojoExecutionException
+ {
+ File template = new File(templateSourceDirectory, _getTemplateName());
+
+ if (template.exists())
+ {
+ getLog().info("Using template from file loader: "+template.getPath());
+ }
+ else
+ {
+ getLog().info("Using template from class loader: META-INF/"+_getTemplateName());
+ }
+
+ VelocityEngine velocityEngine = new VelocityEngine();
+
+ try
+ {
+ velocityEngine.setProperty( "resource.loader", "file, class" );
+ velocityEngine.setProperty( "file.resource.loader.class",
+ "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
+ velocityEngine.setProperty( "file.resource.loader.path", templateSourceDirectory.getPath());
+ velocityEngine.setProperty( "class.resource.loader.class",
+ "org.apache.myfaces.buildtools.maven2.plugin.builder.utils.RelativeClasspathResourceLoader" );
+ velocityEngine.setProperty( "class.resource.loader.path", "META-INF");
+ velocityEngine.setProperty( "velocimacro.library", "converterClassMacros11.vm");
+ velocityEngine.setProperty( "velocimacro.permissions.allow.inline","true");
+ velocityEngine.setProperty( "velocimacro.permissions.allow.inline.local.scope", "true");
+ velocityEngine.setProperty( "directive.foreach.counter.initial.value","0");
+ //velocityEngine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
+ // "org.apache.myfaces.buildtools.maven2.plugin.builder.utils.ConsoleLogSystem" );
+
+ velocityEngine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM,
+ new MavenPluginConsoleLogSystem(this.getLog()));
+
+ velocityEngine.init();
+ }
+ catch (Exception e)
+ {
+ throw new MojoExecutionException("Error creating VelocityEngine", e);
+ }
+
+ return velocityEngine;
+ }
+
+
+ /**
+ * Generates parsed converters.
+ */
+ private void generateConverters(Model model) throws IOException,
+ MojoExecutionException
+ {
+ // Make sure generated source directory
+ // is added to compilation source path
+ //project.addCompileSourceRoot(generatedSourceDirectory.getCanonicalPath());
+
+ //Init Qdox for extract code
+ JavaDocBuilder builder = new JavaDocBuilder();
+
+ List sourceDirs = project.getCompileSourceRoots();
+
+ // need a File object representing the original source tree
+ for (Iterator i = sourceDirs.iterator(); i.hasNext();)
+ {
+ String srcDir = (String) i.next();
+ builder.addSourceTree(new File(srcDir));
+ }
+
+ //Init velocity
+ VelocityEngine velocityEngine = initVelocity();
+
+ VelocityContext baseContext = new VelocityContext();
+ baseContext.put("utils", new MyfacesUtils());
+
+ for (Iterator it = model.getConverters().iterator(); it.hasNext();)
+ {
+ ConverterMeta converter = (ConverterMeta) it.next();
+
+ if (converter.getClassName() != null)
+ {
+ File f = new File(mainSourceDirectory, StringUtils.replace(
+ converter.getClassName(), ".", "/")+".java");
+
+ if (!f.exists() && canGenerateConverter(converter))
+ {
+ if (mainSourceDirectory2 != null)
+ {
+ File f2 = new File(mainSourceDirectory2, StringUtils.replace(
+ converter.getClassName(), ".", "/")+".java");
+ if (f2.exists())
+ {
+ //Skip
+ continue;
+ }
+ }
+ getLog().info("Generating converter class:"+converter.getClassName());
+ try
+ {
+ _generateConverter(velocityEngine, builder,converter,baseContext);
+ }
+ catch(MojoExecutionException e)
+ {
+ if (force)
+ {
+ getLog().error(e.getMessage());
+ }
+ else
+ {
+ //Stop execution throwing exception
+ throw e;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public boolean canGenerateConverter(ConverterMeta converter)
+ {
+ if ( modelIds.contains(converter.getModelId())
+ && includePackage(converter))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public boolean includePackage(ConverterMeta converter)
+ {
+ if (packageContains != null)
+ {
+ if (MyfacesUtils.getPackageFromFullClass(converter.getClassName()).startsWith(packageContains))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+
+ /**
+ * Generates a parsed converter.
+ *
+ * @param converter
+ * the parsed converter metadata
+ */
+ private void _generateConverter(VelocityEngine velocityEngine,
+ JavaDocBuilder builder,
+ ConverterMeta converter, VelocityContext baseContext)
+ throws MojoExecutionException
+ {
+ Context context = new VelocityContext(baseContext);
+ context.put("converter", converter);
+
+ Writer writer = null;
+ File outFile = null;
+
+ try
+ {
+ outFile = new File(generatedSourceDirectory, StringUtils.replace(
+ converter.getClassName(), ".", "/")+".java");
+
+ if ( !outFile.getParentFile().exists() )
+ {
+ outFile.getParentFile().mkdirs();
+ }
+
+ writer = new OutputStreamWriter(new FileOutputStream(outFile));
+
+ Template template = velocityEngine.getTemplate(_getTemplateName());
+
+ template.merge(context, writer);
+
+ writer.flush();
+ }
+ catch (Exception e)
+ {
+ throw new MojoExecutionException(
+ "Error merging velocity templates: " + e.getMessage(), e);
+ }
+ finally
+ {
+ IOUtil.close(writer);
+ writer = null;
+ }
+ }
+
+ private String _getTemplateName()
+ {
+ if (templateConverterName == null)
+ {
+ if (_is12())
+ {
+ return "converterClass12.vm";
+ }
+ else
+ {
+ return "converterClass11.vm";
+ }
+ }
+ else
+ {
+ return templateConverterName;
+ }
+ }
+
+ private boolean _is12()
+ {
+ return "1.2".equals(jsfVersion) || "12".equals(jsfVersion);
+ }
+
+}
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/model/ConverterMeta.java b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/model/ConverterMeta.java
index cb0bccd..59298b9 100644
--- a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/model/ConverterMeta.java
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/model/ConverterMeta.java
@@ -49,9 +49,13 @@
private String _tagClass;
private String _tagSuperclass;
private String _serialuidtag;
+ private String _tagHandler;
+ private Boolean _generatedComponentClass;
private Boolean _generatedTagClass;
private Boolean _configExcluded;
+
+ private Boolean _evaluateELOnExecution;
/**
* Write an instance of this class out as xml.
@@ -59,13 +63,17 @@
protected void writeXmlSimple(XmlWriter out)
{
super.writeXmlSimple(out);
+
out.writeElement("converterId", _converterId);
out.writeElement("bodyContent", _bodyContent);
out.writeElement("tagClass", _tagClass);
out.writeElement("tagSuperclass", _tagSuperclass);
+ out.writeElement("tagHandler", _tagHandler);
out.writeElement("serialuidtag", _serialuidtag);
+ out.writeElement("generatedComponentClass", _generatedComponentClass);
out.writeElement("generatedTagClass", _generatedTagClass);
out.writeElement("configExcluded", _configExcluded);
+ out.writeElement("evaluateELOnExecution", _evaluateELOnExecution);
}
/**
@@ -85,9 +93,12 @@
digester.addBeanPropertySetter(newPrefix + "/bodyContent");
digester.addBeanPropertySetter(newPrefix + "/tagClass");
digester.addBeanPropertySetter(newPrefix + "/tagSuperclass");
+ digester.addBeanPropertySetter(newPrefix + "/tagHandler");
digester.addBeanPropertySetter(newPrefix + "/serialuidtag");
+ digester.addBeanPropertySetter(newPrefix + "/generatedComponentClass");
digester.addBeanPropertySetter(newPrefix + "/generatedTagClass");
digester.addBeanPropertySetter(newPrefix + "/configExcluded");
+ digester.addBeanPropertySetter(newPrefix + "/evaluateELOnExecution");
}
public ConverterMeta()
@@ -106,8 +117,18 @@
public void merge(ConverterMeta other)
{
super.merge(other);
+
_bodyContent = ModelUtils.merge(this._bodyContent, other._bodyContent);
+ // inheritParentTag is true if the tag class to be generated for this
+ // artifact extends the tag class generated for the parent artifact.
+ // In this case, the tag for this class already inherits setter methods
+ // from its parent that handle all the inherited properties, so the
+ // tag class for this component just needs to handle its own properties.
+ //
+ // But when the tag class for this component does not extend the tag class
+ // for the parent component (because the parent component does not have
+ // a tag class) then we need to
boolean inheritParentTag = false;
//check if the parent set a tag class
if (other._tagClass != null)
@@ -124,8 +145,11 @@
other._tagSuperclass);
}
- _converterId = ModelUtils.merge(this._converterId, other._converterId);
+ _tagHandler = ModelUtils.merge(this._tagHandler, other._tagHandler);
+ _evaluateELOnExecution = ModelUtils.merge(this._evaluateELOnExecution, other._evaluateELOnExecution);
+ _converterId = ModelUtils.merge(this._converterId, other._converterId);
+
// TODO: _converterClassMOdifiers
if (inheritParentTag)
@@ -158,7 +182,6 @@
}
_propertyTagList = null;
}
-
}
/**
@@ -239,6 +262,29 @@
return _tagSuperclass;
}
+ /**
+ * Specifies the class of the Facelets tag handler (component handler) for
+ * this component.
+ * <p>
+ * Note that a Facelets tag handler class is not needed for most components.
+ * </p>
+ *
+ * @since 1.0.8
+ */
+ public void setTagHandler(String tagHandler)
+ {
+ _tagHandler = tagHandler;
+ }
+
+ /**
+ *
+ * @since 1.0.8
+ */
+ public String getTagHandler()
+ {
+ return _tagHandler;
+ }
+
public void setSerialuidtag(String serialuidtag)
{
_serialuidtag = serialuidtag;
@@ -249,6 +295,24 @@
return _serialuidtag;
}
+ /**
+ *
+ * @since 1.0.8
+ */
+ public void setGeneratedComponentClass(Boolean generatedComponentClass)
+ {
+ _generatedComponentClass = generatedComponentClass;
+ }
+
+ /**
+ *
+ * @since 1.0.8
+ */
+ public Boolean isGeneratedComponentClass()
+ {
+ return ModelUtils.defaultOf(_generatedComponentClass,false);
+ }
+
public void setGeneratedTagClass(Boolean generatedTagClass)
{
_generatedTagClass = generatedTagClass;
@@ -269,8 +333,33 @@
return ModelUtils.defaultOf(_configExcluded,false);
}
+ /**
+ *
+ * @since 1.0.8
+ */
+ public void setEvaluateELOnExecution(Boolean evaluateELOnExecution)
+ {
+ this._evaluateELOnExecution = evaluateELOnExecution;
+ }
+
+ /**
+ *
+ * @since 1.0.8
+ */
+ public Boolean isEvaluateELOnExecution()
+ {
+ return ModelUtils.defaultOf(_evaluateELOnExecution,false);
+ }
+
//THIS METHODS ARE USED FOR VELOCITY TO GET DATA AND GENERATE CLASSES
-
+
+ // A transient attribute that is computed on-demand from the model data
+ // but is not itself stored in the model.
+ //
+ // It holds a list of all the properties which need to be implemented
+ // on the tag class. This is a subset of the properties available on
+ // this component itself, and depends upon what the parent class
+ // of the generated tag already supports.
private List _propertyTagList = null;
public Collection getPropertyTagList()
@@ -292,4 +381,28 @@
return _propertyTagList;
}
+ private List _propertyConverterList = null;
+
+ /**
+ *
+ * @since 1.0.8
+ */
+ public Collection getPropertyConverterList()
+ {
+ if (_propertyConverterList == null)
+ {
+ _propertyConverterList = new ArrayList();
+ for (Iterator it = getPropertyList().iterator(); it.hasNext();)
+ {
+ PropertyMeta prop = (PropertyMeta) it.next();
+ if (!prop.isInherited().booleanValue() && prop.isGenerated().booleanValue())
+ {
+ _propertyConverterList.add(prop);
+ }
+ }
+
+ }
+ return _propertyConverterList;
+ }
+
}
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/model/ValidatorMeta.java b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/model/ValidatorMeta.java
index 2dc3a5a..5c8fe0e 100644
--- a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/model/ValidatorMeta.java
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/model/ValidatorMeta.java
@@ -40,10 +40,13 @@
private String _tagClass;
private String _tagSuperclass;
private String _serialuidtag;
+ private String _tagHandler;
private Boolean _generatedComponentClass;
private Boolean _generatedTagClass;
private Boolean _configExcluded;
+
+ private Boolean _evaluateELOnExecution;
/**
* Write an instance of this class out as xml.
@@ -56,10 +59,12 @@
out.writeElement("bodyContent", _bodyContent);
out.writeElement("tagClass", _tagClass);
out.writeElement("tagSuperclass", _tagSuperclass);
+ out.writeElement("tagHandler", _tagHandler);
out.writeElement("serialuidtag", _serialuidtag);
out.writeElement("generatedComponentClass", _generatedComponentClass);
out.writeElement("generatedTagClass", _generatedTagClass);
out.writeElement("configExcluded", _configExcluded);
+ out.writeElement("evaluateELOnExecution", _evaluateELOnExecution);
}
/**
@@ -79,10 +84,12 @@
digester.addBeanPropertySetter(newPrefix + "/bodyContent");
digester.addBeanPropertySetter(newPrefix + "/tagClass");
digester.addBeanPropertySetter(newPrefix + "/tagSuperclass");
+ digester.addBeanPropertySetter(newPrefix + "/tagHandler");
digester.addBeanPropertySetter(newPrefix + "/serialuidtag");
digester.addBeanPropertySetter(newPrefix + "/generatedComponentClass");
digester.addBeanPropertySetter(newPrefix + "/generatedTagClass");
digester.addBeanPropertySetter(newPrefix + "/configExcluded");
+ digester.addBeanPropertySetter(newPrefix + "/evaluateELOnExecution");
}
public ValidatorMeta()
@@ -128,6 +135,8 @@
other._tagSuperclass);
}
+ _tagHandler = ModelUtils.merge(this._tagHandler, other._tagHandler);
+ _evaluateELOnExecution = ModelUtils.merge(this._evaluateELOnExecution, other._evaluateELOnExecution);
_validatorId = ModelUtils.merge(this._validatorId, other._validatorId);
@@ -243,6 +252,28 @@
return _tagSuperclass;
}
+ /**
+ * Specifies the class of the Facelets tag handler (component handler) for
+ * this component.
+ * <p>
+ * Note that a Facelets tag handler class is not needed for most components.
+ *
+ * @since 1.0.8
+ */
+ public void setTagHandler(String tagHandler)
+ {
+ _tagHandler = tagHandler;
+ }
+
+ /**
+ *
+ * @since 1.0.8
+ */
+ public String getTagHandler()
+ {
+ return _tagHandler;
+ }
+
public void setSerialuidtag(String serialuidtag)
{
_serialuidtag = serialuidtag;
@@ -283,6 +314,24 @@
return ModelUtils.defaultOf(_configExcluded,false);
}
+ /**
+ *
+ * @since 1.0.8
+ */
+ public void setEvaluateELOnExecution(Boolean evaluateELOnExecution)
+ {
+ this._evaluateELOnExecution = evaluateELOnExecution;
+ }
+
+ /**
+ *
+ * @since 1.0.8
+ */
+ public Boolean isEvaluateELOnExecution()
+ {
+ return ModelUtils.defaultOf(_evaluateELOnExecution,false);
+ }
+
//THIS METHODS ARE USED FOR VELOCITY TO GET DATA AND GENERATE CLASSES
// A transient attribute that is computed on-demand from the model data
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/qdox/QdoxModelBuilder.java b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/qdox/QdoxModelBuilder.java
index b5f5ea2..0f4d579 100644
--- a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/qdox/QdoxModelBuilder.java
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/qdox/QdoxModelBuilder.java
@@ -281,9 +281,14 @@
continue;
}
QdoxHelper.initConverterAncestry(processedClasses, model, converter);
- // TODO: why is there no check for Converter class existence here??
- // ANS: there is no automatic generation of converter class.
-
+
+ //Check if the converter class file exists
+ if (!IOUtils.existsSourceFile(StringUtils.replace(
+ converter.getClassName(),".","/")+".java", sourceDirs))
+ {
+ converter.setGeneratedComponentClass(Boolean.TRUE);
+ }
+
// Check if the tag class java file exists in the source dirs
if (QdoxHelper.isTagClassMissing(converter.getTagClass(), sourceDirs))
{
@@ -686,8 +691,10 @@
String bodyContent = QdoxHelper.getString(clazz, "bodyContent", props, null);
String tagClass = QdoxHelper.getString(clazz, "tagClass", props, null);
String tagSuperclass = QdoxHelper.getString(clazz, "tagSuperclass", props, null);
+ String tagHandler = QdoxHelper.getString(clazz, "tagHandler", props, null);
String serialuidtag = QdoxHelper.getString(clazz, "serialuidtag", props, null);
Boolean configExcluded = QdoxHelper.getBoolean(clazz,"configExcluded",props,null);
+ Boolean evaluateELOnExecution = QdoxHelper.getBoolean(clazz,"evaluateELOnExecution",props,null);
ConverterMeta converter = new ConverterMeta();
initClassMeta(model, clazz, converter, classNameOverride);
@@ -695,11 +702,13 @@
converter.setBodyContent(bodyContent);
converter.setTagClass(tagClass);
converter.setTagSuperclass(tagSuperclass);
+ converter.setTagHandler(tagHandler);
converter.setConverterId(converterId);
converter.setDescription(shortDescription);
converter.setLongDescription(longDescription);
converter.setSerialuidtag(serialuidtag);
converter.setConfigExcluded(configExcluded);
+ converter.setEvaluateELOnExecution(evaluateELOnExecution);
// Now here walk the component looking for property annotations.
processComponentProperties(clazz, converter);
@@ -782,8 +791,10 @@
String bodyContent = QdoxHelper.getString(clazz, "bodyContent", props, null);
String tagClass = QdoxHelper.getString(clazz, "tagClass", props, null);
String tagSuperclass = QdoxHelper.getString(clazz, "tagSuperclass", props, null);
+ String tagHandler = QdoxHelper.getString(clazz, "tagHandler", props, null);
String serialuidtag = QdoxHelper.getString(clazz, "serialuidtag", props, null);
- Boolean configExcluded = QdoxHelper.getBoolean(clazz,"configExcluded",props,null);
+ Boolean configExcluded = QdoxHelper.getBoolean(clazz,"configExcluded",props,null);
+ Boolean evaluateELOnExecution = QdoxHelper.getBoolean(clazz,"evaluateELOnExecution",props,null);
ValidatorMeta validator = new ValidatorMeta();
initClassMeta(model, clazz, validator, classNameOverride);
@@ -791,11 +802,13 @@
validator.setBodyContent(bodyContent);
validator.setTagClass(tagClass);
validator.setTagSuperclass(tagSuperclass);
+ validator.setTagHandler(tagHandler);
validator.setValidatorId(validatorId);
validator.setDescription(shortDescription);
validator.setLongDescription(longDescription);
validator.setSerialuidtag(serialuidtag);
validator.setConfigExcluded(configExcluded);
+ validator.setEvaluateELOnExecution(evaluateELOnExecution);
// Now here walk the component looking for property annotations.
processComponentProperties(clazz, validator);
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/unpack/UnpackMojo.java b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/unpack/UnpackMojo.java
index f209213..0be52a4 100644
--- a/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/unpack/UnpackMojo.java
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/java/org/apache/myfaces/buildtools/maven2/plugin/builder/unpack/UnpackMojo.java
@@ -272,6 +272,13 @@
if (converter.getModelId().equals(model.getModelId()))
{
+ if (converter.isGeneratedComponentClass().booleanValue())
+ {
+ getLog().info("Adding Generated: "+ converter.getClassName());
+ exclusions.add(StringUtils.replace(
+ converter.getClassName(), ".", "/")
+ + ".java");
+ }
if (converter.isGeneratedTagClass().booleanValue())
{
getLog().info("Adding Generated: "+ converter.getTagClass());
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/converterClassMacros11.vm b/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/converterClassMacros11.vm
new file mode 100644
index 0000000..8362de7
--- /dev/null
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/converterClassMacros11.vm
@@ -0,0 +1,4 @@
+## Macro definitions for component class definition
+##
+## Velocity macros defined in this file will be available when executing
+## the componentClass11.vm template file.
\ No newline at end of file
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/faces-config11.vm b/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/faces-config11.vm
index f688b2e..22d5731 100644
--- a/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/faces-config11.vm
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/faces-config11.vm
@@ -40,7 +40,9 @@
#end
#set ($converterList = ${model.getConverters()})
#foreach( $converter in $converterList )
-#if ($modelIds.contains($converter.modelId))
+#if ($modelIds.contains($converter.modelId) &&
+ !($converter.isConfigExcluded().booleanValue()) &&
+ $converter.converterId)
<converter>
<converter-id>$converter.converterId</converter-id>
<converter-class>$converter.className</converter-class>
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/faces-config12.vm b/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/faces-config12.vm
index 21630ca..2d5c7e7 100644
--- a/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/faces-config12.vm
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/faces-config12.vm
@@ -39,7 +39,9 @@
#end
#set ($converterList = ${model.getConverters()})
#foreach( $converter in $converterList )
-#if ($modelIds.contains($converter.modelId))
+#if ($modelIds.contains($converter.modelId) &&
+ !($converter.isConfigExcluded().booleanValue()) &&
+ $converter.converterId)
<converter>
<converter-id>$converter.converterId</converter-id>
<converter-class>$converter.className</converter-class>
diff --git a/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/tomahawk.vm b/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/tomahawk.vm
new file mode 100644
index 0000000..c2b9e84
--- /dev/null
+++ b/maven2-plugins/myfaces-builder-plugin/src/main/resources/META-INF/tomahawk.vm
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
+<taglib>
+ <tlib-version>1.0</tlib-version>
+ <jsp-version>1.2</jsp-version>
+ <short-name>$shortname</short-name>
+ <uri>$uri</uri>
+ <display-name>$displayname</display-name>
+ <description>$description</description>
+
+$baseContent
+
+ <!-- Component Tags -->
+#set ($componentList = ${model.getComponents()})
+#foreach( $component in $componentList )
+#if ($modelIds.contains($component.modelId)
+ && ($component.name))
+#if ($utils.getTagPrefix($component.name) == $shortname)
+ <tag>
+ <name>$utils.getTagName($component.name)</name>
+ <tag-class>$component.tagClass</tag-class>
+#if ($component.bodyContent)
+ <body-content>$component.bodyContent</body-content>
+#else
+ <body-content>JSP</body-content>
+#end
+ <description><![CDATA[$component.longDescription]]></description>
+
+#set ($propertyList = ${component.propertyList})
+#foreach( $property in $propertyList )
+#if (!$property.isTagExcluded())
+ <attribute>
+ <name>$property.jspName</name>
+ <required>$property.isRequired()</required>
+ <rtexprvalue>false</rtexprvalue>
+ <type>java.lang.String</type>
+#if ($property.longDescription)
+ <description><![CDATA[$property.longDescription]]></description>
+#else
+ <description><![CDATA[]]></description>
+#end
+ </attribute>
+#end
+#end
+ </tag>
+#end
+#end
+#end
+ <!-- Converter tags -->
+#set ($componentList = ${model.getConverters()})
+#foreach( $component in $componentList )
+#if ($modelIds.contains($component.modelId)
+ && ($component.name))
+#if ($utils.getTagPrefix($component.name) == $shortname)
+ <tag>
+ <name>$utils.getTagName($component.name)</name>
+ <tag-class>$component.tagClass</tag-class>
+#if ($component.bodyContent)
+ <body-content>$component.bodyContent</body-content>
+#else
+ <body-content>empty</body-content>
+#end
+ <description><![CDATA[$component.longDescription]]></description>
+
+#set ($propertyList = ${component.propertyList})
+#foreach( $property in $propertyList )
+#if (!$property.isTagExcluded())
+ <attribute>
+ <name>$property.name</name>
+ <required>$property.isRequired()</required>
+ <rtexprvalue>false</rtexprvalue>
+ <type>java.lang.String</type>
+#if ($property.longDescription)
+ <description><![CDATA[$property.longDescription]]></description>
+#else
+ <description><![CDATA[]]></description>
+#end
+ </attribute>
+#end
+#end
+ </tag>
+#end
+#end
+#end
+ <!-- Validator tags -->
+#set ($componentList = ${model.getValidators()})
+#foreach( $component in $componentList )
+#if ($modelIds.contains($component.modelId)
+ && ($component.name))
+#if ($utils.getTagPrefix($component.name) == $shortname)
+ <tag>
+ <name>$utils.getTagName($component.name)</name>
+ <tag-class>$component.tagClass</tag-class>
+#if ($component.bodyContent)
+ <body-content>$component.bodyContent</body-content>
+#else
+ <body-content>empty</body-content>
+#end
+ <description><![CDATA[$component.longDescription]]></description>
+
+#set ($propertyList = ${component.propertyList})
+#foreach( $property in $propertyList )
+#if (!$property.isTagExcluded())
+ <attribute>
+ <name>$property.name</name>
+ <required>$property.isRequired()</required>
+ <rtexprvalue>false</rtexprvalue>
+ <type>java.lang.String</type>
+#if ($property.longDescription)
+ <description><![CDATA[$property.longDescription]]></description>
+#else
+ <description><![CDATA[]]></description>
+#end
+ </attribute>
+#end
+#end
+ </tag>
+#end
+#end
+#end
+ <!-- Single Tags -->
+#set ($tagList = $model.getTags())
+#foreach( $tag in $tagList )
+#if ($modelIds.contains($tag.modelId))
+ <tag>
+ <name>$utils.getTagName($tag.name)</name>
+ <tag-class>$tag.className</tag-class>
+ <body-content>$tag.bodyContent</body-content>
+ <description><![CDATA[$tag.longDescription]]></description>
+#set ($attributeList = ${tag.attributeList})
+#foreach( $attribute in $attributeList )
+ <attribute>
+ <name>$attribute.name</name>
+ <required>$attribute.isRequired()</required>
+ <rtexprvalue>$attribute.isRtexprvalue()</rtexprvalue>
+#if ($attribute.className)
+ <type>$attribute.className</type>
+#else
+ <type>java.lang.String</type>
+#end
+#if ($property.longDescription)
+ <description><![CDATA[$property.longDescription]]></description>
+#else
+ <description><![CDATA[]]></description>
+#end
+ </attribute>
+#end
+ </tag>
+#end
+#end
+</taglib>
\ No newline at end of file