Java tutorial
/** * License Agreement. * * Rich Faces - Natural Ajax for Java Server Faces (JSF) * * 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.templatecompiler.elements.vcp; import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.ajax4jsf.templatecompiler.builder.CompilationContext; import org.ajax4jsf.templatecompiler.builder.CompilationException; import org.ajax4jsf.templatecompiler.el.ELParser; import org.ajax4jsf.templatecompiler.elements.A4JRendererElementsFactory; import org.ajax4jsf.templatecompiler.elements.TemplateElementBase; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.velocity.VelocityContext; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * Processing f:call-tag. * * @author ayukhovich@exadel.com (latest modification by $Author: * alexeyyukhovich $) * @version $Revision: 1.1.2.3 $ $Date: 2007/02/26 20:48:47 $ */ public class FCallTemplateElement extends TemplateElementBase { private static final Log log = LogFactory.getLog(FCallTemplateElement.class); private String functionName; private String variable; private String fullFunctionName; private boolean useOnlyEnumeratingParaments; private final static String FUNCTION_DELIMITER = "\\."; private final static String VAR_ATTRIBUTE_NAME = "var"; private final static String FUNCTION_NAME_ATTRIBUTE_NAME = "name"; private final static String USE_ONLY_THIS_PARAMETERS = "use_only_this_parameters"; private final static String[][] PARAM_NAMES = new String[][] { { "context" }, { "context", "component" } }; private static final String TEMPLATE = A4JRendererElementsFactory.TEMPLATES_TEMPLATECOMPILER_PATH + "/insertCall.vm"; private ArrayList parameters; public FCallTemplateElement(final Node element, final CompilationContext componentBean) throws CompilationException { super(element, componentBean); this.useOnlyEnumeratingParaments = false; NamedNodeMap nnm = element.getAttributes(); Node functionNameNode = nnm.getNamedItem(FUNCTION_NAME_ATTRIBUTE_NAME); if (functionNameNode != null) { this.functionName = functionNameNode.getNodeValue(); } else { throw new CompilationException("function name is not set"); } Node nodeUseOnlyThisParameters = nnm.getNamedItem(USE_ONLY_THIS_PARAMETERS); if (nodeUseOnlyThisParameters != null) { this.useOnlyEnumeratingParaments = Boolean.getBoolean(nodeUseOnlyThisParameters.getNodeValue()); } // if // read name of variable if need Node variableName = nnm.getNamedItem(VAR_ATTRIBUTE_NAME); if (variableName != null) { this.variable = variableName.getNodeValue(); } // if // read name of parameters if need ParameterProcessor parameterProcessor = new ParameterProcessor(element, componentBean); this.parameters = parameterProcessor.getParameters(); log.debug(this.parameters); List decodeFunctionName = null; decodeFunctionName = Arrays.asList(this.functionName.split(FUNCTION_DELIMITER)); if (null == decodeFunctionName) { decodeFunctionName = new ArrayList(); decodeFunctionName.add(this.functionName); } ArrayList functionNames = new ArrayList(); String lastClassName = componentBean.getFullBaseclass(); for (Iterator iter = decodeFunctionName.iterator(); iter.hasNext();) { String elementFunction = (String) iter.next(); try { log.debug("Try to load class : " + lastClassName); Class clazz = componentBean.loadClass(lastClassName); if (!iter.hasNext()) { String method = getMethod(clazz, elementFunction); if (method != null) { log.debug(method); functionNames.add(method); } else { log.error("Method " + elementFunction + " not found in class : " + lastClassName); throw new CompilationException(); } } else { // // Probing properties !!!! // PropertyDescriptor propertyDescriptor = getPropertyDescriptor(clazz, elementFunction); if (propertyDescriptor != null) { functionNames.add(propertyDescriptor.getReadMethod().getName() + "()"); log.debug("Property " + elementFunction + " mapped to function : " + propertyDescriptor.getReadMethod().getName()); lastClassName = propertyDescriptor.getPropertyType().getName(); } else { log.error("Property " + elementFunction + " not found in class : " + lastClassName); throw new CompilationException(); } } } catch (Throwable e) { log.error("Error load class : " + lastClassName + ", " + e.getLocalizedMessage()); e.printStackTrace(); throw new CompilationException("Error load class : " + lastClassName, e); } } StringBuffer tmpbuf = new StringBuffer(); for (Iterator iter = functionNames.iterator(); iter.hasNext();) { String tmpElement = (String) iter.next(); if (tmpbuf.length() != 0) { tmpbuf.append("."); } tmpbuf.append(tmpElement); } this.fullFunctionName = tmpbuf.toString(); } /** * * @param clazz * @param propertyName * @return */ private PropertyDescriptor getPropertyDescriptor(Class clazz, String propertyName) { PropertyDescriptor returnValue = null; PropertyDescriptor[] propertyDescriptors = PropertyUtils.getPropertyDescriptors(clazz); for (int i = 0; i < propertyDescriptors.length; i++) { PropertyDescriptor descriptor = propertyDescriptors[i]; if (descriptor.getName().equals(propertyName)) { returnValue = descriptor; break; } } return returnValue; } /** * * @param clazz * @param propertyName * @return */ private String getMethod(Class clazz, String methodName) throws ClassNotFoundException, NoSuchMethodException { String returnValue = null; Class[][] arrayParametersTypes = null; if (this.useOnlyEnumeratingParaments) { arrayParametersTypes = new Class[1][this.parameters.size()]; for (int i = 0; i < this.parameters.size(); i++) { arrayParametersTypes[0][i] = ((Parameter) this.parameters.get(i)).getType(); } } else { arrayParametersTypes = new Class[PARAM_NAMES.length + 1][]; for (int i = 0; i < arrayParametersTypes.length; i++) { int addlength = 0; if (i < PARAM_NAMES.length) { addlength = PARAM_NAMES[i].length; } arrayParametersTypes[i] = new Class[addlength + this.parameters.size()]; } for (int i = 0; i < PARAM_NAMES.length; i++) { for (int j = 0; j < PARAM_NAMES[i].length; j++) { arrayParametersTypes[i][j] = this.getComponentBean().getVariableType(PARAM_NAMES[i][j]); } } for (int i = 0; i < arrayParametersTypes.length; i++) { int shift = 0; if (i < PARAM_NAMES.length) { shift = PARAM_NAMES[i].length; } for (int j = 0; j < this.parameters.size(); j++) { Parameter parameter = (Parameter) this.parameters.get(j); arrayParametersTypes[i][shift + j] = parameter.getType(); } } } List<String> methodNotFoundMessagesList = new ArrayList<String>(); boolean found = false; for (int i = 0; i < arrayParametersTypes.length && !found; i++) { try { this.getComponentBean().getMethodReturnedClass(clazz, methodName, arrayParametersTypes[i]); StringBuffer buffer = new StringBuffer(); buffer.append(methodName); buffer.append("("); int shift = 0; if (i < PARAM_NAMES.length) { shift = PARAM_NAMES[i].length; } for (int j = 0; j < arrayParametersTypes[i].length; j++) { if (j > 0) { buffer.append(", "); } if ((i < PARAM_NAMES.length) && (j < PARAM_NAMES[i].length)) { buffer.append(PARAM_NAMES[i][j]); } else { Parameter parameter = (Parameter) this.parameters.get(j - shift); String tmp = ELParser.compileEL(parameter.getValue(), this.getComponentBean()); buffer.append(tmp); } } buffer.append(")"); returnValue = buffer.toString(); found = true; } catch (NoSuchMethodException e) { methodNotFoundMessagesList.add(e.getLocalizedMessage()); } } // for if (!found) { throw new NoSuchMethodException("Could not find methods: " + methodNotFoundMessagesList); } return returnValue; } /** * @throws CompilationException * */ public String getBeginElement() throws CompilationException { VelocityContext context = new VelocityContext(); context.put("variableName", this.variable); context.put("function", this.fullFunctionName); return this.getComponentBean().processTemplate(getTemplateName(), context); } /** * @return */ protected String getTemplateName() { return TEMPLATE; } /** * */ public String getEndElement() { return null; } }