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

com.jsftoolkit.gen.TemplateComponentGenerator Maven / Gradle / Ivy

Go to download

The core classes for the JSF Toolkit Component Framework. Includes all framework base and utility classes as well as component kick-start/code-generation and registration tools. Also includes some classes for testing that are reused in other projects. They cannot be factored out into a separate project because they are referenced by the tests and they reference this code (circular dependence).

The newest version!
package com.jsftoolkit.gen;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.PrintStream;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import javax.faces.component.UIInput;

import org.xml.sax.SAXException;

import com.jsftoolkit.base.ResourceInfo;
import com.jsftoolkit.base.renderer.DecodeEvent;
import com.jsftoolkit.base.renderer.HtmlRenderer;
import com.jsftoolkit.base.renderer.PassThrough;
import com.jsftoolkit.base.renderer.RenderEventsCollector;
import com.jsftoolkit.base.renderer.VarAttribEvent;
import com.jsftoolkit.base.renderer.VarTextEvent;
import com.jsftoolkit.gen.info.ComponentInfo;
import com.jsftoolkit.gen.info.PropertyInfo;
import com.jsftoolkit.gen.info.RendererInfo;
import com.jsftoolkit.utils.Utils;
import com.jsftoolkit.utils.xmlpull.PullEvent;
import com.jsftoolkit.utils.xmlpull.StartElement;

/**
 * Reads in an XHTML template and generates the component, renderer and tag
 * handler. The component and tag handler are generated using
 * {@link ComponentGenerator}, but this class adds additional metadata from the
 * parsed template.
 * 
 * @author noah
 */
public class TemplateComponentGenerator {

	private static final String DEFAULT_TEMPLATE_ENC = "UTF-8";

	private static class Tab {
		public String tab(int count) {
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < count; i++) {
				sb.append(toString());
			}
			return sb.toString();
		}

		@Override
		public String toString() {
			return "    ";
		}
	}

	private static final Tab T = new Tab();

	/**
	 * Debugging method. Prints render, component and tag handler to the given
	 * stream.
	 * 
	 * @param info
	 * @param out
	 * @throws Exception
	 */
	public void generate(ComponentInfo info, PrintStream out) throws Exception {
		generate(info, info.getRenderer().getTemplate(), info.getRenderer()
				.getHeadTemplate(), info.getRenderer().getTemplateEncoding(),
				out, out, out);
	}

	/**
	 * Generates renderer, component and tag handler in the default locations.
	 * 
	 * @see ComponentGenerator#defaultStream(String, String)
	 * @param info
	 * @throws Exception
	 */
	public void generate(ComponentInfo info) throws Exception {
		generate(info, info.getRenderer().getTemplate(), info.getRenderer()
				.getHeadTemplate(), info.getRenderer().getTemplateEncoding());
	}

	/**
	 * Generates renderer, component and tag handler in the default locations
	 * and uses the given template.
	 * 
	 * @see ComponentGenerator#defaultStream(String, String)
	 * @param info
	 * @param resource
	 * @param headTemplate
	 * @param encoding
	 * @throws Exception
	 */
	public void generate(ComponentInfo info, String resource,
			String headTemplate, String encoding) throws Exception {
		generate(info, resource, headTemplate, encoding,
				resource == null ? null : ComponentGenerator
						.defaultRendererStream(info), ComponentGenerator
						.defaultComponentStream(info), ComponentGenerator
						.defaultTagStream(info));
	}

	/**
	 * Writes the generated code to the given streams.
	 * 
	 * @param info
	 * @param resource
	 * @param headTemplate
	 * @param encoding
	 * @param rendererOut
	 * @param componentOut
	 * @param tagOut
	 * @throws Exception
	 */
	public void generate(ComponentInfo info, String resource,
			String headTemplate, String encoding, PrintStream rendererOut,
			PrintStream componentOut, PrintStream tagOut) throws Exception {

		if (resource != null) {
			System.out.println("Creating renderer based on template(s): "
					+ resource + " and " + headTemplate);
			// can't generate a renderer without a template
			fillIn(info, Utils.resourceToString(resource, encoding));
			String head = Utils.resourceToString(headTemplate, encoding, null);
			if (head != null) {
				fillIn(info, head);
			}
			generateRenderer(info, resource, encoding, rendererOut);
		}

		// defer the rest of generation to ComponentGenerator
		ComponentGenerator generator = new ComponentGenerator(info);
		generator.generateComponent(componentOut);
		generator.generateTagHandler(tagOut);
	}

	/**
	 * 
	 * @param info
	 *            the {@link ComponentInfo}
	 * @param resource
	 *            the classpath resource that is the template
	 * @param encoding
	 *            the encoding of the template
	 * @param out
	 */
	public void generateRenderer(ComponentInfo info, String resource,
			String encoding, PrintStream out) {
		RendererInfo renderInfo = info.getRenderer();
		Class[] imports = { IOException.class, SAXException.class, Set.class,
				ResourceInfo.Type.class, ResourceInfo.class,
				HtmlRenderer.class, Utils.class };

		for (Class i : imports) {
			renderInfo.addImport(i);
		}

		ComponentGenerator
				.printDeclaration(out, renderInfo, HtmlRenderer.class);

		Set resources = new LinkedHashSet();

		// create a constant for each resource required
		for (ResourceInfo ii : info.getRenderer().getIncludes()) {
			String id = ii.getId();
			String name = id.substring(id.lastIndexOf('.') + 1);
			out.printf(T + "private static final ResourceInfo %s = %s;\n\n",
					name, ii.getCodeString());
			resources.add(name);
		}

		// create a set of the constants
		out.printf(T + "public static final Set "
				+ "RESOURCES = Utils.asSet(%s);\n\n", Utils.join(resources
				.iterator(), ","));

		// write out the constructor
		out.printf(T + "public %1$s() throws IOException, SAXException {\n" + T
				+ T + "super(Utils.resourceToString(\"%2$s\",%3$s),\n"
				+ T.tab(4) + "Utils.resourceToString(%4$s,%3$s,null),\n"
				+ T.tab(4) + "RESOURCES);\n", renderInfo.getClassName(),
				resource, Utils.toStringConstant(Utils.getValue(encoding,
						DEFAULT_TEMPLATE_ENC)), Utils
						.toStringConstant(renderInfo.getHeadTemplate()));

		// add decode information, if it was provided
		String decodeParam = info.getRenderer().getDecodeParam();
		if (UIInput.class.isAssignableFrom(info.getSuperClass())
				&& !Utils.isEmpty(decodeParam)) {
			writeDecode(out, decodeParam);
		}

		out.println(T + "}\n\n" + T + "public boolean getRendersChildren() {\n"
				+ T + T + "return true;\n" + T + "}\n\n");

		out.println('}');
		out.close();
	}

	protected void writeDecode(PrintStream out, String decodeParam) {
		VarAttribEvent vae = RenderEventsCollector
				.convertToVarAttribute(new DecodeEvent(decodeParam));
		String format = Utils.toStringConstant(vae == null ? decodeParam : vae
				.getPattern());
		String props = Utils.toStringConstantArray(vae.getProperties()
				.toArray());
		String defaults = Utils.toStringConstantArray(vae.getDefaultValues()
				.toArray());
		out.printf(T.tab(2)
				+ "setDecodeInfo(%s,new String[]%s,new String[]%s);\n", format,
				props, defaults);
	}

	public ComponentInfo fillIn(ComponentInfo info) throws IOException,
			SAXException, IntrospectionException {
		RendererInfo ri = info.getRenderer();
		String enc = ri.getTemplateEncoding();
		return fillIn(fillIn(info, Utils
				.resourceToString(ri.getTemplate(), enc)), Utils
				.resourceToString(ri.getHeadTemplate(), enc));
	}

	/**
	 * Scans the given template for references to component properties and
	 * updates info accordingly.
	 * 
	 * @param info
	 *            the {@link ComponentInfo} to update
	 * @param text
	 *            the template text
	 * @return info
	 * @throws IOException
	 * @throws SAXException
	 * @throws IntrospectionException
	 */
	public ComponentInfo fillIn(ComponentInfo info, String text)
			throws IOException, SAXException, IntrospectionException {
		Map properties = info.getProperties();

		for (PullEvent event : new RenderEventsCollector(text)) {
			switch (event.getType()) {
			case VarAttribEvent.TYPE: {
				VarAttribEvent ev = (VarAttribEvent) event;
				for (String property : ev.getProperties()) {
					String name = Utils.toConstantName(property);
					if (!properties.containsKey(name)
							&& !isIgnoreProperty(property)) {
						properties.put(name, new PropertyInfo(null, property));
					}
				}
			}
				break;
			case VarTextEvent.TYPE: {
				VarTextEvent ev = (VarTextEvent) event;

				String name = Utils.toConstantName(ev.getProperty());
				if (!properties.containsKey(name)
						&& !isIgnoreProperty(ev.getProperty())) {
					properties.put(name, new PropertyInfo(null, ev
							.getProperty(), ev.getDefaultValue()));
				}
			}
				break;
			case PassThrough.TYPE: {
				PassThrough ev = (PassThrough) event;

				// remove pass through attributes that already have a
				// getter/setter pair in the super class, because it is not
				// necessary to have another get/set pair
				for (PropertyDescriptor pd : info.getTag()
						.getPropertyDescriptors()) {
					ev.getAllowed().remove(pd.getName());
				}

				info.getRenderer().getAttribs().addAll(ev.getAllowed());
			}
				break;
			case StartElement.TYPE: {
				StartElement ev = (StartElement) event;
				if (ev.getName().startsWith(HtmlRenderer.TAG_PREFIX)) {
					info.getRenderer().addAttribute(HtmlRenderer.TAG);
				}
			}
				break;
			case DecodeEvent.TYPE: {
				info.getRenderer().setDecodeParam(
						((DecodeEvent) event).getValue());
			}
			default:
				// don't care about other events
			}
		}
		return info;
	}

	private boolean isIgnoreProperty(String property) {
		return "id".equalsIgnoreCase(property)
				|| "binding".equalsIgnoreCase(property)
				|| "rendered".equalsIgnoreCase(property);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy