Package org.jboss.seam.wiki.core.wikitext.renderer.jsf

Source Code of org.jboss.seam.wiki.core.wikitext.renderer.jsf.WikiFormattedTextHandler

/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.seam.wiki.core.wikitext.renderer.jsf;

import antlr.ANTLRException;
import antlr.RecognitionException;
import com.sun.facelets.FaceletContext;
import com.sun.facelets.tag.MetaRuleset;
import com.sun.facelets.tag.MetaTagHandler;
import com.sun.facelets.tag.TagAttribute;
import com.sun.facelets.tag.TagConfig;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
import org.jboss.seam.wiki.core.wikitext.engine.WikiTextParser;

import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import java.io.IOException;
import java.util.Iterator;

/**
* Creates a <tt>UIWikiFormattedText</tt> JSF component and substitutes macro names in wiki
* text with real macro components in the tree. These <tt>UIMacro</tt> components are
* build from XHTML fragments/includes. Interacts closely with the state of the
* <tt>UIWikiFormattedText</tt> component to split component tree creation and rendering duties.
*
* @author Peter Muir
* @author Christian Bauer
*/
public class WikiFormattedTextHandler extends MetaTagHandler {

    private Log log = Logging.getLog(WikiFormattedTextHandler.class);

    private static final String MARK = "org.jboss.seam.wiki.core.ui.WikiFormattedTextHandler";
    private TagAttribute valueAttribute;

    public WikiFormattedTextHandler(TagConfig config) {
        super(config);
        this.valueAttribute = this.getRequiredAttribute("value");
    }

    /*
    * Main apply method called by facelets to create this component.
    */
    public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, ELException {
        log.debug(">>> building wiki text components for child of: " + parent.getClientId(ctx.getFacesContext()));
        String id = ctx.generateUniqueId(this.tagId);
        UIComponent cmp = findChildByTagId(parent, id);
        if (cmp == null) {
            cmp = createComponent(ctx);
            cmp.getAttributes().put(MARK, id);
        }
        this.nextHandler.apply(ctx, cmp);
        parent.getChildren().add(cmp);
        createMacroComponents(ctx, cmp);
        log.debug("<<< completed building wiki text components for child of: " + parent.getClientId(ctx.getFacesContext()));
    }

    private UIComponent createComponent(FaceletContext ctx) {
        UIWikiFormattedText wikiFormattedText = new UIWikiFormattedText();
        setAttributes(ctx, wikiFormattedText);
        return wikiFormattedText;
    }

    /*
    * Have to manually wire the component as the Facelets magic wirer
    * is a package scoped class.
    */
    @Override
    protected void setAttributes(FaceletContext ctx, Object instance) {
        UIComponent cmp = (UIComponent) instance;
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_LINK_STYLE_CLASS);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_BROKEN_LINK_STYLE_CLASS);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_ATTACHMENT_LINK_STYLE_CLASS);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_THUMBNAIL_LINK_STYLE_CLASS);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_INTERNAL_TARGET_FRAME);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_EXTERNAL_TARGET_FRAME);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_LINK_BASE_FILE);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_CURRENT_AREA_NUMBER);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_ENABLE_MACRO_RENDERING, false);
        setAttribute(ctx, cmp, UIWikiFormattedText.ATTR_ENABLE_TRANSIENT_MACROS, false);
    }

    @Override
    protected MetaRuleset createMetaRuleset(Class type) {
        return super.createMetaRuleset(type).ignoreAll();
    }

    private void createMacroComponents(final FaceletContext ctx, final UIComponent parent) {
        if (!(parent instanceof UIWikiFormattedText)) return;
        final UIWikiFormattedText wikiFormattedTextComponent = (UIWikiFormattedText) parent;

        String unparsed = valueAttribute.getValue(ctx);

        // Don't forget this, transporting the value to the handled component, we need to render it (again) later
        wikiFormattedTextComponent.setValue(unparsed);

        if (getAttribute(UIWikiFormattedText.ATTR_ENABLE_MACRO_RENDERING) == null ||
            !getAttribute(UIWikiFormattedText.ATTR_ENABLE_MACRO_RENDERING).getBoolean(ctx)) {
            log.debug("macro rendering disabled");
            return;
        }

        // We need to parse the wiki text once (later again for rendering) to find all macros in the text
        log.debug("creating macro components from wiki text macros");
        WikiTextParser parser = new WikiTextParser(unparsed, true, false);

        // This is a special flag that disables/enables caching of ValueExpressions inside macro templates,
        // see the MacroIncludeTextRenderer for an explanation...
        boolean enableTransientMacros =
            (getAttribute(UIWikiFormattedText.ATTR_ENABLE_TRANSIENT_MACROS) != null &&
             getAttribute(UIWikiFormattedText.ATTR_ENABLE_TRANSIENT_MACROS).getBoolean(ctx));

        // We use a renderer to implement the callbacks from the parsing and to create the components in the tree
        parser.setRenderer(
            new MacroIncludeTextRenderer(wikiFormattedTextComponent, ctx, enableTransientMacros)
        );

        try {
            parser.parse();
        } catch (RecognitionException rex) {
            // Swallow parsing errors, we don't really care here...
        } catch (ANTLRException ex) {
            // All other errors are fatal;
            throw new RuntimeException(ex);
        }
    }

    // Some utilities...

    private static UIComponent findChildByTagId(UIComponent parent, String id) {
        Iterator itr = parent.getFacetsAndChildren();
        while (itr.hasNext()) {
            UIComponent c = (UIComponent) itr.next();
            String cid = (String) c.getAttributes().get(MARK);
            if (id.equals(cid)) {
                return c;
            }
        }
        return null;
    }

    private void setAttribute(FaceletContext ctx, UIComponent cmp, String name) {
        setAttribute(ctx, cmp, name, null);
    }

    private void setAttribute(FaceletContext ctx, UIComponent cmp, String name, Object defaultValue) {
        TagAttribute attribute = this.getAttribute(name);
        if (attribute != null) {
            Object o = attribute.getObject(ctx);
            if (o == null && defaultValue == null) {
                throw new IllegalArgumentException("Attribute '" + name + "' resolved to null and no default value specified");
            } else if (o == null) {
                cmp.getAttributes().put(name, defaultValue);
            } else {
                cmp.getAttributes().put(name, o);
            }
        }
    }


}
TOP

Related Classes of org.jboss.seam.wiki.core.wikitext.renderer.jsf.WikiFormattedTextHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.