Friday, July 13, 2012

Programmatic Facelet:Template

Inspired by the FaceletFactory.createComponent method in the reference implementration, I create a utility to use facelet template programmaitcally.

private String getTemplateComponentString(String template,
            FacesContext context, File tempFile, Object... definitions)
    {
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version='1.0' encoding='UTF-8' ?>");
        sb.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
        sb.append("<html xmlns=\"http://www.w3.org/1999/xhtml\"\n");
        sb.append(" xmlns:f=\"http://java.sun.com/jsf/core\"\n");
        sb.append(" xmlns:ui=\"http://java.sun.com/jsf/facelets\">\n");
        sb.append("  <ui:composition template=\"")
                .append(fileToFile(tempFile.getAbsolutePath(), context
                        .getExternalContext().getRealPath(template)))
                .append("\">");

        // add the facet
        for (int i = 0; i < definitions.length; i++)
        {
            sb.append("<ui:define name=\"").append(definitions[i++].toString())
                    .append("\" >\n");
            sb.append("<ui:include src=\"")
                    .append(fileToFile(
                            tempFile.getAbsolutePath(),
                            context.getExternalContext().getRealPath(
                                    definitions[i].toString())))
                    .append("\" />\n");
            sb.append("</ui:define>\n");
        }

        // end the tag.
        sb.append("</ui:composition>");
        sb.append("</html>");

        return sb.toString();
    }

public static UIComponent instantiateTemplate(String template,
            Object... definitions)
    {
        FacesContext ctx = FacesContext.getCurrentInstance();
        FaceletFactory faceletFactory = (FaceletFactory) FactoryFinder
                .getFactory(FactoryFinder.FACELET_FACTORY);

        UIPanel panel = (UIPanel) ctx.getApplication().createComponent(
                UIPanel.COMPONENT_TYPE);
        File tempFile = createTempFile(ctx);
        String content = getTemplateComponentString(template, ctx, tempFile,
                definitions);
        try
        {
            FileUtils.write(tempFile, content);
            URL furl = tempFile.toURI().toURL();
            Facelet f = faceletFactory.getFacelet(furl);
            f.apply(ctx, panel);
            return panel;
        } catch (IOException e)
        {
            throw new RuntimeException(e);
        } finally
        {
            tempFile.delete();
        }
    }

The method createTempFile and fileToFile can be found here
http://www.flexdms.com/2012/07/programmatic-faceletcomposite-component.html.


No comments:

Post a Comment