Author: nbelaevski
Date: 2008-03-20 15:36:23 -0400 (Thu, 20 Mar 2008)
New Revision: 7032
Added:
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/config/FunctionBean.java
Modified:
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/config/BuilderConfig.java
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/generator/FaceletsTaglibGenerator.java
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/generator/TaglibGenerator.java
trunk/cdk/generator/src/main/resources/META-INF/schema/component-config.dtd
trunk/cdk/generator/src/main/resources/META-INF/templates12/facelets.taglib.vm
trunk/cdk/generator/src/main/resources/META-INF/templates12/taglib.vm
Log:
Function support in CDK
Modified:
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/config/BuilderConfig.java
===================================================================
---
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/config/BuilderConfig.java 2008-03-20
19:05:40 UTC (rev 7031)
+++
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/config/BuilderConfig.java 2008-03-20
19:36:23 UTC (rev 7032)
@@ -100,6 +100,8 @@
private List<ListenerBean> listeners = new ArrayList<ListenerBean>();
+ private List<FunctionBean> functions = new ArrayList<FunctionBean>();
+
private ClassLoader _loader;
private Logger _log;
@@ -290,6 +292,15 @@
digester.addSetProperties(path);
digester.addSetNext(path, "addConverter");
+ // Functions
+
+ path = "components/function";
+ digester.addObjectCreate(path, FunctionBean.class);
+ digester.addBeanPropertySetter(path + "/name");
+ digester.addBeanPropertySetter(path + "/description");
+ digester.addBeanPropertySetter(path + "/method");
+ digester.addSetNext(path, "addFunction");
+
// - Tags & Tag handlers
path = "components/component/tag";
@@ -569,6 +580,11 @@
listener.setParent(this);
}
+ public void addFunction(FunctionBean function) {
+ this.functions.add(function);
+ function.setParent(this);
+ }
+
/*
* (non-Javadoc)
*
@@ -643,6 +659,10 @@
return this.renderers;
}
+ public List<FunctionBean> getFunctions() {
+ return functions;
+ }
+
/*
* (non-Javadoc)
*
Added: trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/config/FunctionBean.java
===================================================================
--- trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/config/FunctionBean.java
(rev 0)
+++
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/config/FunctionBean.java 2008-03-20
19:36:23 UTC (rev 7032)
@@ -0,0 +1,196 @@
+/**
+ * License Agreement.
+ *
+ * JBoss RichFaces - Ajax4jsf Component Library
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+package org.ajax4jsf.builder.config;
+
+import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created 20.03.2008
+ * @author Nick Belaevski
+ * @since 3.2
+ */
+
+public class FunctionBean extends ComponentBaseBean {
+
+ private String method;
+
+ private String signature;
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ private static final Pattern SIGNATURE =
Pattern.compile("\\s*((?:\\[\\s*\\]\\s*)*)(\\.\\.\\.)?\\s*$");
+
+ private static final int getArrayDepth(Class<?> clazz) {
+ if (clazz.isArray()) {
+ return getArrayDepth(clazz.getComponentType()) + 1;
+ } else {
+ return 0;
+ }
+ }
+
+ private static final int getArrayDepth(String signature) {
+ Matcher matcher = SIGNATURE.matcher(signature);
+ if (matcher.find()) {
+ int depth = 0;
+
+ int groupCount = matcher.groupCount();
+ for (int i = 1; i <= groupCount; i++) {
+ String string = matcher.group(i);
+ if (string != null) {
+ String group = matcher.group(i).trim();
+ if ("...".equals(group)) {
+ depth++;
+ } else {
+ int l = group.length();
+ for (int j = 0; j < l; j++) {
+ if (group.charAt(j) == '[') {
+ depth++;
+ }
+ }
+ }
+ }
+ }
+
+ return depth;
+ } else {
+ return 0;
+ }
+ }
+
+ private static final Class<?> getComponentType(Class<?> clazz) {
+ if (clazz.isArray()) {
+ return getComponentType(clazz.getComponentType());
+ } else {
+ return clazz;
+ }
+ }
+
+ private static final String getComponentType(String signature) {
+ return SIGNATURE.matcher(signature).replaceFirst("");
+ }
+
+ private void findMethod() {
+ if (method == null || method.length() == 0) {
+ throw new IllegalArgumentException("Method " + getName() + " is null
or empty!");
+ }
+
+ int i = method.indexOf('(');
+ if (i == -1 || method.charAt(method.length() - 1) != ')') {
+ throw new IllegalArgumentException("Method " + method + ": brace(s)
are missing!");
+ }
+
+ String fqMethodName = method.substring(0, i);
+ String signature = method.substring(i + 1, method.length() - 1);
+
+ int j = fqMethodName.lastIndexOf('.');
+ int k = fqMethodName.lastIndexOf('#');
+
+ int sepIdx = Math.max(j, k);
+ if (sepIdx == -1) {
+ throw new IllegalArgumentException("Method: " + method + ":
doesn't have '.' or '#' method name separator char!");
+ }
+
+ String classname = fqMethodName.substring(0, sepIdx);
+ Class<?> clazz;
+
+ try {
+ clazz = getLoader().loadClass(classname);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e.getLocalizedMessage(), e);
+ }
+
+ setClassname(classname);
+
+ String methodName = fqMethodName.substring(sepIdx + 1);
+
+ String[] parameters = signature.split("\\s*,\\s*");
+
+ Method[] methods = clazz.getMethods();
+ for (Method method : methods) {
+ Class<?>[] parameterTypes = method.getParameterTypes();
+
+ if (parameters.length == parameterTypes.length) {
+ StringBuilder signatureBuilder = new StringBuilder();
+ signatureBuilder.append('(');
+ boolean matches = true;
+
+ for (int l = 0; l < parameterTypes.length; l++) {
+ String parameter = parameters[l];
+ int depth = getArrayDepth(parameter);
+ String componentType = getComponentType(parameter);
+
+ Class<?> type = getComponentType(parameterTypes[l]);
+ int arrayDepth = getArrayDepth(parameterTypes[l]);
+
+ if (depth != arrayDepth || (!componentType.equals(type.getSimpleName())
+ && !componentType.equals(type.getName()))) {
+
+ matches = false;
+ break;
+ }
+
+ signatureBuilder.append(parameterTypes[l].getCanonicalName());
+ if (l != parameterTypes.length - 1) {
+ signatureBuilder.append(", ");
+ } else {
+ signatureBuilder.append(')');
+ }
+ }
+
+ if (matches) {
+ this.signature = method.getReturnType().getCanonicalName() + " " +
methodName + signatureBuilder.toString();
+
+ break;
+ }
+ }
+ }
+
+ if (this.signature == null) {
+ throw new IllegalStateException("Method: " + method + " not
found!");
+ }
+ }
+
+ public String getMethodClassname() {
+ if (getClassname() == null) {
+ findMethod();
+ }
+
+ return getClassname();
+ }
+
+ public String getMethodSignature() {
+ if (signature == null) {
+ findMethod();
+ }
+
+ return signature;
+ }
+
+}
Modified:
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/generator/FaceletsTaglibGenerator.java
===================================================================
---
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/generator/FaceletsTaglibGenerator.java 2008-03-20
19:05:40 UTC (rev 7031)
+++
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/generator/FaceletsTaglibGenerator.java 2008-03-20
19:36:23 UTC (rev 7032)
@@ -33,6 +33,7 @@
import org.ajax4jsf.builder.config.ComponentBaseBean;
import org.ajax4jsf.builder.config.ComponentBean;
import org.ajax4jsf.builder.config.ConverterBean;
+import org.ajax4jsf.builder.config.FunctionBean;
import org.ajax4jsf.builder.config.ListenerBean;
import org.ajax4jsf.builder.config.ValidatorBean;
import org.apache.velocity.Template;
@@ -130,7 +131,17 @@
}
}
- if (components.size() > 0 || validators.size() > 0 || converters.size() > 0)
{
+ List<FunctionBean> functions = new ArrayList<FunctionBean>();
+ for (FunctionBean functionBean : config.getFunctions()) {
+ if (isIncludeComponent(functionBean)) {
+ info("Function "+functionBean.getName() +" included in
taglib "+getShortname());
+ functions.add(functionBean);
+ } else {
+ info("Function "+functionBean.getName() +" excluded from
taglib "+getShortname());
+ }
+ };
+
+ if (components.size() > 0 || validators.size() > 0 || converters.size() > 0 ||
functions.size() > 0) {
if (listeners.size() > 0) {
context.put("listeners", listeners);
}
@@ -147,6 +158,9 @@
{
context.put("converters", converters);
}
+ if (functions.size() > 0) {
+ context.put("functions", functions);
+ }
context.put("taglib", this);
File taglibFile = getTaglib();//new File(getDestDir(), resultPath);
File javaDir = taglibFile.getParentFile();
Modified:
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/generator/TaglibGenerator.java
===================================================================
---
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/generator/TaglibGenerator.java 2008-03-20
19:05:40 UTC (rev 7031)
+++
trunk/cdk/generator/src/main/java/org/ajax4jsf/builder/generator/TaglibGenerator.java 2008-03-20
19:36:23 UTC (rev 7032)
@@ -32,6 +32,7 @@
import org.ajax4jsf.builder.config.BuilderConfig;
import org.ajax4jsf.builder.config.ComponentBean;
import org.ajax4jsf.builder.config.ConverterBean;
+import org.ajax4jsf.builder.config.FunctionBean;
import org.ajax4jsf.builder.config.ListenerBean;
import org.ajax4jsf.builder.config.ValidatorBean;
import org.apache.velocity.Template;
@@ -166,8 +167,17 @@
}
}
+ List<FunctionBean> functions = new ArrayList<FunctionBean>();
+ for (FunctionBean functionBean : config.getFunctions()) {
+ if (isIncludeComponent(functionBean)) {
+ info("Function "+functionBean.getName() +" included in
taglib "+getShortname());
+ functions.add(functionBean);
+ } else {
+ info("Function "+functionBean.getName() +" excluded from
taglib "+getShortname());
+ }
+ };
- if (compmnents.size() > 0 || validators.size() > 0 || converters.size() > 0)
{
+ if (compmnents.size() > 0 || validators.size() > 0 || converters.size() > 0
|| functions.size() > 0) {
VelocityContext context = new VelocityContext();
Template template = getTemplate();
// Put common properties
@@ -183,6 +193,9 @@
if (listeners.size() > 0) {
context.put("listeners", listeners);
}
+ if (functions.size() > 0) {
+ context.put("functions", functions);
+ }
context.put("taglib", this);
File taglibFile = getTaglib();//new File(getDestDir(), resultPath);
File javaDir = taglibFile.getParentFile();
Modified: trunk/cdk/generator/src/main/resources/META-INF/schema/component-config.dtd
===================================================================
--- trunk/cdk/generator/src/main/resources/META-INF/schema/component-config.dtd 2008-03-20
19:05:40 UTC (rev 7031)
+++ trunk/cdk/generator/src/main/resources/META-INF/schema/component-config.dtd 2008-03-20
19:36:23 UTC (rev 7032)
@@ -2,7 +2,7 @@
PUBLIC-ID "-//AJAX4JSF//CDK Generator config/EN"
SYSTEM-ID
https://ajax4jsf.dev.java.net/nonav/dtds/component-config.dtd -->
<!-- Root element for components and renderers -->
-<!ELEMENT components (component*,renderer*,listener*,validator*,converter*) >
+<!ELEMENT components (component*,renderer*,listener*,validator*,converter*,function*)
>
<!-- Component description with common properties, tags and renderers descriptions
-->
<!ELEMENT component
(name,family?,classname?,superclass?,test*,description?,displayname?,icon?,facet*,renderer*,tag?,taghandler?,(include|properties|property)*)>
<!-- Validator description with properties and tags -->
@@ -10,6 +10,8 @@
<!-- Validator description with properties and tags -->
<!ELEMENT converter
(name,classname?,superclass?,test*,description?,displayname?,icon?,tag?,taghandler?,(include|properties|property)*)>
+<!ELEMENT function (name,description?,method)>
+
<!-- components with generate=false not produce component class,
use for describe superclasses for other components -->
<!ATTLIST component
@@ -51,6 +53,8 @@
<!ELEMENT renderkit (#PCDATA)>
<!-- Template file name -->
<!ELEMENT template (#PCDATA)>
+<!-- Fully-qualified method name and signature -->
+<!ELEMENT method (#PCDATA)>
<!ATTLIST renderer
generate (true|false) "false"
@@ -111,7 +115,6 @@
existintag (true|false) "false"
attachedstate (true|false) "false"
transient (true|false) "false"
- hidden (true|false) "false"
required (true|false) "false"
disabled (true|false) "false"
Modified: trunk/cdk/generator/src/main/resources/META-INF/templates12/facelets.taglib.vm
===================================================================
---
trunk/cdk/generator/src/main/resources/META-INF/templates12/facelets.taglib.vm 2008-03-20
19:05:40 UTC (rev 7031)
+++
trunk/cdk/generator/src/main/resources/META-INF/templates12/facelets.taglib.vm 2008-03-20
19:36:23 UTC (rev 7032)
@@ -65,4 +65,11 @@
</tag>
#end
+ #foreach( $function in ${functions} )
+ <function>
+ <function-name>${function.name}</function-name>
+ <function-class>${function.methodClassname}</function-class>
+ <function-signature>${function.methodSignature}</function-signature>
+ </function>
+ #end
</facelet-taglib>
\ No newline at end of file
Modified: trunk/cdk/generator/src/main/resources/META-INF/templates12/taglib.vm
===================================================================
--- trunk/cdk/generator/src/main/resources/META-INF/templates12/taglib.vm 2008-03-20
19:05:40 UTC (rev 7031)
+++ trunk/cdk/generator/src/main/resources/META-INF/templates12/taglib.vm 2008-03-20
19:36:23 UTC (rev 7032)
@@ -91,4 +91,15 @@
#generateBunchOfTags(${converters})
#generateBunchOfTags(${listeners})
+ #foreach( $function in ${functions} )
+ <function>
+ #if (${function.description})
+ <description>${function.description}</description>
+ #end
+ <name>${function.name}</name>
+ <function-class>${function.methodClassname}</function-class>
+ <function-signature>${function.methodSignature}</function-signature>
+ </function>
+ #end
+
</taglib>