Package org.jboss.seam.wiki.core.plugin

Source Code of org.jboss.seam.wiki.core.plugin.WikiPluginMacro

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

import org.jboss.seam.Component;
import org.jboss.seam.web.ServletContexts;
import org.jboss.seam.international.Messages;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
import org.jboss.seam.wiki.core.model.WikiDocument;
import org.jboss.seam.wiki.core.model.WikiTextMacro;
import org.jboss.seam.wiki.core.plugin.metamodel.MacroPluginModule;
import org.jboss.seam.wiki.util.Hash;

import java.io.Serializable;
import java.util.Map;
import java.util.HashMap;
import java.util.Date;

/**
* An instance of a macro in wiki text that has an XHTML include/template.
* <p>
* Internally it ties the wiki text parsing engine to the plugin and
* preferences functionality, as well as template/UI rendering. It is also
* the primary API for plugin developers, it's the 'currentMacro' that is
* available at all times when writing plugin templates, plugin classes, or
* interpolated plugin resources (CSS that contains EL expressions, etc.).
* </p>
* <p>
* It extends a <tt>WikiTextMacro</tt> with additional features that are only
* relevant for rendering the macro and its template.
* </p>
* <p>
* A new instance of this class is created for <i>every</i> rendering of wiki
* text in the wiki user interface (the visible GUI). You can use the
* <tt>attributes</tt> map of this instance to store values that you want to
* retrieve again during such rendering. This is especially useful if you
* want to avoid generating or loading a value again and again during rendering
* of a single piece of wiki text, which can occur if a JSF value binding method
* (a getter) is generating/loading a value based on the macro instance.
* </p>
* <p>
* An instance of this class can only be created by the <tt>PluginRegistry</tt>.
*
* @see PluginRegistry
*
* @author Christian Bauer
*/
public class WikiPluginMacro extends WikiTextMacro implements Serializable {

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

    public static final String CURRENT_MACRO_EL_VARIABLE = "currentMacro";
    public static final String PAGE_VARIABLE_PREFIX = "macro";
    public static final String PAGE_VARIABLE_SEPARATOR = "_";
    public static final String EVENT_PREFIX = "Macro.";

    public static enum CallbackEvent {
        VIEW_BUILD(".callback.viewBuild"),
        BEFORE_VIEW_RENDER(".callback.beforeViewRender"),
        AFTER_VIEW_RENDER(".callback.afterViewRender");
        private String name;
        CallbackEvent(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
    }

    private String uniqueId = Long.toString(new Date().getTime());
    private String clientId;
    private MacroPluginModule metadata;
    private Map attributes = new HashMap();

    WikiPluginMacro(MacroPluginModule metadata, WikiTextMacro wikiTextMacro) {
        super(wikiTextMacro);
        this.metadata = metadata;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public MacroPluginModule getMetadata() {
        return metadata;
    }

    public void setMetadata(MacroPluginModule metadata) {
        this.metadata = metadata;
    }

    public Map getAttributes() {
        return attributes;
    }

    public void setAttributes(Map attributes) {
        this.attributes = attributes;
    }

    // Some convenience methods that generate Strings used all over the place

    // This needs to be unique _across_ different wiki texts. So the numeric position and the name is not enough,
    // the hashCode() is overriden in the superclass to be the name/position combination... so we need the uniqueId.
    // TODO: We can now actually remove the position and name, but they help us with debugging.
    public String getPageVariableName() {
        return PAGE_VARIABLE_PREFIX + getPosition() + PAGE_VARIABLE_SEPARATOR + this.uniqueId + PAGE_VARIABLE_SEPARATOR + getName();
    }

    public String getCallbackEventName(CallbackEvent event) {
        return EVENT_PREFIX+getName()+event.getName();
    }

    public String getRequestImagePath() {
        return getRequestPathPrefix() + getMetadata().getImagePath();
    }

    public String getRequestStylesheetPath() {
        return getRequestPathPrefix() + getMetadata().getStylesheetPath();
    }

    private String getRequestPathPrefix() {
        if (getClientId() == null) {
            // We need to prefix any request with the currenct web context name if this
            // is not a JSF request. That means, at this time, simple resource (img, css)
            // GET requests that use EL which in turn uses instances of this class.
            return ServletContexts.instance().getRequest().getContextPath();
        }
        return "";
    }
   
    public String getCacheRegion(String name) {
        return getMetadata().getQualifiedCacheRegionName(name);
    }

    public String getMessage(String message) {
        return Messages.instance().get(getMetadata().getPlugin().getKey() + "." + message);
    }

    /*
        Cache keys for macros are unique hashes:

        - unique in all wiki areas: the id of the current document
        - unique in a particular document: the name and position of the macro in the document
        - unique with changing macro parameters: the hashcode of any macro parameters
        - unique for a particular user access level: the current users access level
        - unique considering the hashCode() of any additional objects passed to the method

     */
    public String getCacheKey() {
        return getCacheKey(new Object[]{});
    }

    public String getCacheKey(Object o) {
        return getCacheKey(new Object[]{o});
    }

    public String getCacheKey(Object... objects) {
        WikiDocument currentDocument = (WikiDocument)Component.getInstance("currentDocument");
        Integer accessLevel = (Integer) Component.getInstance("currentAccessLevel");
        Hash hash = (Hash)Component.getInstance(Hash.class);

        log.debug("generating cache key for document: " + currentDocument + " and macro: " + this + " and access level: " + accessLevel);
        StringBuilder builder = new StringBuilder();

        if (log.isDebugEnabled()) log.debug("including id of document: " + currentDocument.getId());
        builder.append( currentDocument.getId() );

        int namePositionHash = (getName() + "_" + getPosition()).hashCode();
        if (log.isDebugEnabled()) log.debug("including name/position of this macro: " + Math.abs(namePositionHash));
        builder.append( Math.abs(namePositionHash) );

        if (log.isDebugEnabled()) log.debug("including hashCode of macro params: " + Math.abs(getParams().hashCode()));
        builder.append( Math.abs(getParams().hashCode()) );

        if (log.isDebugEnabled()) log.debug("including accessLevel: " + accessLevel);
        builder.append( accessLevel );

        // This needs to be empty-String safe (the additional objects might be some of the
        // JSF "oh let's map a non-existant request parameter to an empty string" genius behavior...
        if (objects != null && objects.length > 0) {
            for (Object o : objects) {
                if (o != null && Math.abs(o.hashCode()) != 0) {
                    log.debug("including hashCode of object: " + Math.abs(o.hashCode()));
                    builder.append( Math.abs(o.hashCode()) );
                }
            }
        }
        return hash.hash(builder.toString());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        WikiPluginMacro that = (WikiPluginMacro) o;
        return uniqueId.equals(that.uniqueId);

    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + uniqueId.hashCode();
        return result;
    }

    public String toString() {
        return "WikiPluginMacro UniqueId '" + this.uniqueId + "' (" + getPosition() + "): "
                + getName() + " Params: " + getParams().size();
    }

}
TOP

Related Classes of org.jboss.seam.wiki.core.plugin.WikiPluginMacro

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.