[jboss-cvs] jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/ui ...
Peter Muir
peter at bleepbleep.org.uk
Tue Apr 17 11:16:54 EDT 2007
User: pmuir
Date: 07/04/17 11:16:54
Modified: examples/wiki/src/main/org/jboss/seam/wiki/core/ui
UIPlugin.java WikiFormattedTextHandler.java
UIWikiFormattedText.java
Added: examples/wiki/src/main/org/jboss/seam/wiki/core/ui
PluginComponentHandler.java
Removed: examples/wiki/src/main/org/jboss/seam/wiki/core/ui
UIStyle.java
Log:
Another go a wiki plugins
Revision Changes Path
1.2 +2 -0 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/UIPlugin.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: UIPlugin.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/UIPlugin.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- UIPlugin.java 11 Apr 2007 15:53:48 -0000 1.1
+++ UIPlugin.java 17 Apr 2007 15:16:54 -0000 1.2
@@ -7,6 +7,8 @@
public static final String COMPONENT_FAMILY = "org.jboss.seam.wiki.core.ui.UIPlugin";
+ public static final String NEXT_PLUGIN = "org.jboss.seam.wiki.core.ui.UIPlugin.nextPlugin";
+
@Override
public String getFamily()
{
1.3 +145 -41 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/WikiFormattedTextHandler.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: WikiFormattedTextHandler.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/WikiFormattedTextHandler.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- WikiFormattedTextHandler.java 11 Apr 2007 17:09:39 -0000 1.2
+++ WikiFormattedTextHandler.java 17 Apr 2007 15:16:54 -0000 1.3
@@ -3,6 +3,7 @@
import java.io.IOException;
import java.net.URL;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -14,68 +15,145 @@
import org.jboss.seam.Component;
import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.ui.UILoadStyle;
import org.jboss.seam.util.Resources;
import org.jboss.seam.wiki.core.action.PluginPreferenceEditor;
import org.jboss.seam.wiki.core.action.prefs.WikiPreferences;
+
import com.sun.facelets.FaceletContext;
import com.sun.facelets.FaceletException;
import com.sun.facelets.el.VariableMapperWrapper;
+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 com.sun.facelets.tag.TagHandler;
import com.sun.facelets.tag.jsf.ComponentSupport;
-public class WikiFormattedTextHandler extends TagHandler
+
+
+public class WikiFormattedTextHandler extends MetaTagHandler
{
+ private static final String MARK = "org.jboss.seam.wiki.core.ui.WikiFormattedTextHandler";
+
public static final String REGEX_MACRO = Pattern.quote("[") + "<=([a-zA-Z0-9]+)"
+ Pattern.quote("]");
- private TagAttribute value;
+ private TagAttribute valueAttribute;
private Set<String> includedMacros;
public WikiFormattedTextHandler(TagConfig config)
{
super(config);
- this.value = this.getRequiredAttribute("value");
+ this.valueAttribute = this.getRequiredAttribute("value");
}
- public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException,
- FaceletException, ELException
+ /*
+ * Main apply method called by facelets to create this component.
+ */
+ public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException, ELException
{
includedMacros = new HashSet<String>();
- String unparsed = value.getValue(ctx);
- Matcher matcher = Pattern.compile(REGEX_MACRO).matcher(unparsed);
- int start = 0;
- this.nextHandler.apply(ctx, null);
- while (matcher.find())
+ String id = ctx.generateUniqueId(this.tagId);
+ UIComponent cmp = findChildByTagId(parent, id);
+ if (cmp == null)
{
- if (ComponentSupport.isNew(parent))
+ cmp = createComponent(ctx);
+ cmp.getAttributes().put(MARK, id);
+
+ }
+ this.nextHandler.apply(ctx, cmp);
+ parent.getChildren().add(cmp);
+ createPlugins(ctx, cmp);
+ }
+
+ /**
+ * Create the Component
+ */
+ private UIComponent createComponent(FaceletContext ctx)
{
- // Include the string before the match
UIWikiFormattedText wikiFormattedText = new UIWikiFormattedText();
- String text = unparsed.substring(start, matcher.start());
- start = matcher.end();
- wikiFormattedText.setValue(text);
- parent.getChildren().add(wikiFormattedText);
+ 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, "linkStyleClass");
+ setAttribute(ctx, cmp, "brokenLinkStyleClass");
+ setAttribute(ctx, cmp, "attachmentLinkStyleClass");
+ setAttribute(ctx, cmp, "thumbnailLinkStyleClass");
+ }
+
+ private void setAttribute(FaceletContext ctx, UIComponent cmp, String name)
+ {
+ TagAttribute attribute = this.getAttribute(name);
+ cmp.getAttributes().put(name, attribute.getObject(ctx));
+ }
+
+ @Override
+ protected MetaRuleset createMetaRuleset(Class type)
+ {
+ return super.createMetaRuleset(type).ignoreAll();
}
+
+
+ /**
+ * We create the plugins as first-class components here.
+ *
+ * The plugins need to be rendered in the correct place in the
+ * rendered wikitext. The plugin name is replaced with a placeholder.
+ *
+ * To allow multiple use of the same plugin
+ * we replace the plugin name with a reference to the component.
+ * The clientId of the component is used as the reference. To
+ * prevent parse errors in the wikitext the clientId is stored in
+ * a list on the parent UIWikiFormattedText component and it's
+ * position is used as the placeholder.
+ */
+ private void createPlugins (FaceletContext ctx, UIComponent parent)
+ {
+ if (parent instanceof UIWikiFormattedText)
+ {
+ UIWikiFormattedText wikiFormattedText = (UIWikiFormattedText) parent;
+ String unparsed = valueAttribute.getValue(ctx);
+ Matcher matcher = Pattern.compile(REGEX_MACRO).matcher(unparsed);
+ StringBuffer parsed = new StringBuffer();
+ while (matcher.find())
+ {
// Include the plugin
String macroName = matcher.group(1);
buildMacro(macroName, ctx, parent);
+
+ // Get the placeholder to use
+ String placeHolder;
+ Object nextPlugin = parent.getAttributes().get(UIPlugin.NEXT_PLUGIN);
+ if (nextPlugin != null)
+ {
+ placeHolder = wikiFormattedText.addPlugin(nextPlugin.toString());
+ parent.getAttributes().remove(UIPlugin.NEXT_PLUGIN);
}
- if (ComponentSupport.isNew(parent))
+ else
{
- // Then include the end of the string
- UIWikiFormattedText endText = new UIWikiFormattedText();
- endText.setValue(unparsed.substring(start));
- parent.getChildren().add(endText);
+ // Best guess based plugin renderer
+ placeHolder = wikiFormattedText.addPlugin((parent.getChildren().get(parent.getChildCount() - 1).getClientId(ctx.getFacesContext())));
+ }
+ matcher.appendReplacement(parsed, " [<=" + placeHolder + "]");
+ }
+ matcher.appendTail(parsed);
+ wikiFormattedText.setValue(parsed.toString());
}
}
- private void include(URL path, FaceletContext ctx, UIComponent parent) throws IOException, FaceletException,
- FacesException, ELException, IOException
+ private void include(URL path, FaceletContext ctx, UIComponent parent)
{
// Cribbed from facelets
VariableMapper orig = ctx.getVariableMapper();
@@ -84,13 +162,17 @@
{
ctx.includeFacelet(parent, path);
}
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
finally
{
ctx.setVariableMapper(orig);
}
}
- private void buildMacro(String macroName, FaceletContext ctx, UIComponent parent) throws IOException, FaceletException, FacesException, ELException, IOException
+ private void buildMacro(String macroName, FaceletContext ctx, UIComponent parent)
{
if (macroName == null || macroName.length() == 0 || includedMacros.contains(macroName))
{
@@ -152,17 +234,39 @@
}
- private void addCss(String macroName, UIComponent parent)
+ /*
+ * Add a CSS resource to the document head
+ */
+ private void addCss(String macroName, UIComponent cmp)
{
// Try to get the CSS for it
WikiPreferences wikiPrefs = (WikiPreferences) Component.getInstance("wikiPreferences");
- URL css = Resources.getResource("/themes/" + wikiPrefs.getThemeName() + "/css/" + macroName + ".css");
- if (css != null && ComponentSupport.isNew(parent))
- {
- UIStyle style = new UIStyle();
- style.setPath(css);
- parent.getChildren().add(style);
+ String css = "/themes/" + wikiPrefs.getThemeName() + "/css/" + macroName
+ + ".css";
+ if (Resources.getResource(css) != null)
+ {
+ UILoadStyle style = new UILoadStyle();
+ style.setSrc(css);
+ cmp.getChildren().add(style);
+ // Clear these out in the next build phase
+ ComponentSupport.markForDeletion(style);
+ }
+ }
+
+ /*
+ * Support method to find the UIWikiFormattedText component created by
+ * this tag on a previous tree build
+ */
+ private static final 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;
}
}
\ No newline at end of file
1.16 +161 -103 jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/UIWikiFormattedText.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: UIWikiFormattedText.java
===================================================================
RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/UIWikiFormattedText.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- UIWikiFormattedText.java 11 Apr 2007 15:53:48 -0000 1.15
+++ UIWikiFormattedText.java 17 Apr 2007 15:16:54 -0000 1.16
@@ -1,123 +1,181 @@
package org.jboss.seam.wiki.core.ui;
import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
import java.util.List;
+import javax.faces.component.UIComponent;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
import org.jboss.seam.Component;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.core.Conversation;
+import org.jboss.seam.ui.JSF;
import org.jboss.seam.wiki.core.engine.WikiLink;
import org.jboss.seam.wiki.core.engine.WikiTextParser;
import org.jboss.seam.wiki.core.engine.WikiTextRenderer;
import org.jboss.seam.wiki.core.model.File;
import org.jboss.seam.wiki.util.WikiUtil;
-public class UIWikiFormattedText extends UIOutput {
+public class UIWikiFormattedText extends UIOutput
+{
+
+ private List<String> plugins;
public static final String COMPONENT_FAMILY = "org.jboss.seam.wiki.core.ui.UIWikiFormattedText";
+
public static final String COMPONENT_TYPE = "org.jboss.seam.wiki.core.ui.UIWikiFormattedText";
- public UIWikiFormattedText() {
+ public UIWikiFormattedText()
+ {
super();
- setRendererType(null);
+ plugins = new ArrayList<String>();
}
- public String getFamily() {
+ @Override
+ public String getFamily()
+ {
return COMPONENT_FAMILY;
}
- public void encodeBegin(FacesContext facesContext) throws IOException {
+ @Override
+ public boolean getRendersChildren()
+ {
+ return true;
+ }
+
+ @Override
+ public String getRendererType()
+ {
+ return null;
+ }
+
+ @Override
+ public void encodeBegin(FacesContext facesContext) throws IOException
+ {
if (!isRendered() || getValue() == null) return;
// Use the WikiTextParser to resolve macros
- WikiTextParser parser = new WikiTextParser((String)getValue(), false);
+ WikiTextParser parser = new WikiTextParser((String) getValue(), false);
// Set a customized renderer for parser macro callbacks
- parser.setRenderer(
- new WikiTextRenderer() {
+ parser.setRenderer(new WikiTextRenderer()
+ {
- public String renderInlineLink(WikiLink inlineLink) {
+ public String renderInlineLink(WikiLink inlineLink)
+ {
return "<a href=\""
- + (inlineLink.isBroken() ? inlineLink.getUrl() : WikiUtil.renderURL(inlineLink.getNode()))
+ + (inlineLink.isBroken() ? inlineLink.getUrl() : WikiUtil.renderURL(inlineLink
+ .getNode()))
+ "\" class=\""
- + (inlineLink.isBroken()
- ? getAttributes().get("brokenLinkStyleClass")
- : getAttributes().get("linkStyleClass"))
- + "\">"
- + inlineLink.getDescription()
- + "</a>";
+ + (inlineLink.isBroken() ? getAttributes().get("brokenLinkStyleClass")
+ : getAttributes().get("linkStyleClass")) + "\">"
+ + inlineLink.getDescription() + "</a>";
}
- public String renderExternalLink(WikiLink externalLink) {
+ public String renderExternalLink(WikiLink externalLink)
+ {
return "<a href=\""
+ externalLink.getUrl()
+ "\" class=\""
- + (externalLink.isBroken()
- ? getAttributes().get("brokenLinkStyleClass")
- : getAttributes().get("linkStyleClass"))
- + "\">"
- + externalLink.getDescription()
- + "</a>";
+ + (externalLink.isBroken() ? getAttributes().get("brokenLinkStyleClass")
+ : getAttributes().get("linkStyleClass")) + "\">"
+ + externalLink.getDescription() + "</a>";
}
- public String renderFileAttachmentLink(int attachmentNumber, WikiLink attachmentLink) {
- return "<a href=\"#attachment"
- + attachmentNumber
- + "\" class=\""
- + getAttributes().get("attachmentLinkStyleClass")
- + "\">"
- + attachmentLink.getDescription()
- + "[" + attachmentNumber + "]"
- + "</a>";
+ public String renderFileAttachmentLink(int attachmentNumber, WikiLink attachmentLink)
+ {
+ return "<a href=\"#attachment" + attachmentNumber + "\" class=\""
+ + getAttributes().get("attachmentLinkStyleClass") + "\">"
+ + attachmentLink.getDescription() + "[" + attachmentNumber + "]" + "</a>";
}
- public String renderThumbnailImageInlineLink(WikiLink inlineLink) {
- File file = (File)inlineLink.getNode();
+ public String renderThumbnailImageInlineLink(WikiLink inlineLink)
+ {
+ File file = (File) inlineLink.getNode();
int thumbnailWidth;
- // TODO: We could make these sizes customizable, maybe as attributes of the JSF tag
- switch(file.getImageMetaInfo().getThumbnail()) {
- case 'S': thumbnailWidth = 80; break;
- case 'M': thumbnailWidth = 160; break;
- case 'L': thumbnailWidth = 320; break;
- default: thumbnailWidth = file.getImageMetaInfo().getSizeX();
+ // TODO: We could make these sizes customizable, maybe as attributes
+ // of the JSF tag
+ switch (file.getImageMetaInfo().getThumbnail())
+ {
+ case 'S':
+ thumbnailWidth = 80;
+ break;
+ case 'M':
+ thumbnailWidth = 160;
+ break;
+ case 'L':
+ thumbnailWidth = 320;
+ break;
+ default:
+ thumbnailWidth = file.getImageMetaInfo().getSizeX();
}
Conversation conversation = (Conversation) Component.getInstance("conversation");
- // I have no idea why this needs HTML entities for the & symbol - Firefox complains about invalid XML if an & is in an attribute value!
- String thumbnailUrl = WikiUtil.renderURL(inlineLink.getNode()) + "&width=" + thumbnailWidth + "&cid=" + conversation.getId();
+ // I have no idea why this needs HTML entities for the & symbol -
+ // Firefox complains about invalid XML if an & is in an attribute
+ // value!
+ String thumbnailUrl = WikiUtil.renderURL(inlineLink.getNode()) + "&width="
+ + thumbnailWidth + "&cid=" + conversation.getId();
return "<a href=\""
- + (inlineLink.isBroken() ? inlineLink.getUrl() : WikiUtil.renderURL(inlineLink.getNode()))
- + "\" class=\""
- + getAttributes().get("thumbnailLinkStyleClass")
- + "\"><img src=\""
- + thumbnailUrl
- + "\"/></a>";
- }
-
- public String renderMacro(String macroName) {
- return "";
- }
-
- public void setAttachmentLinks(List<WikiLink> attachmentLinks) {
- // Put attachments (wiki links...) into the event context for later rendering
+ + (inlineLink.isBroken() ? inlineLink.getUrl() : WikiUtil.renderURL(inlineLink
+ .getNode())) + "\" class=\""
+ + getAttributes().get("thumbnailLinkStyleClass") + "\"><img src=\""
+ + thumbnailUrl + "\"/></a>";
+ }
+
+ public String renderMacro(String macroName)
+ {
+ UIComponent child = findComponent(plugins.get(new Integer(macroName)));
+ ResponseWriter originalResponseWriter = getFacesContext().getResponseWriter();
+ StringWriter stringWriter = new StringWriter();
+ ResponseWriter tempResponseWriter = originalResponseWriter
+ .cloneWithWriter(stringWriter);
+ getFacesContext().setResponseWriter(tempResponseWriter);
+ try
+ {
+ JSF.renderChild(getFacesContext(), child);
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ finally
+ {
+ getFacesContext().setResponseWriter(originalResponseWriter);
+ }
+ return stringWriter.getBuffer().toString();
+ }
+
+ public void setAttachmentLinks(List<WikiLink> attachmentLinks)
+ {
+ // Put attachments (wiki links...) into the event context for later
+ // rendering
Contexts.getEventContext().set("wikiTextAttachments", attachmentLinks);
}
- public void setExternalLinks(List<WikiLink> externalLinks) {
- // Put external links (to targets not on this wiki) into the event context for later rendering
+ public void setExternalLinks(List<WikiLink> externalLinks)
+ {
+ // Put external links (to targets not on this wiki) into the event
+ // context for later rendering
Contexts.getEventContext().set("wikiTextExternalLinks", externalLinks);
}
- }
- );
+ });
// Run the parser
parser.parse(true);
- facesContext.getResponseWriter().write( parser.toString() );
+ facesContext.getResponseWriter().write(parser.toString());
+
+ }
+ protected String addPlugin(String clientId)
+ {
+ plugins.add(clientId);
+ return (plugins.size() - 1) + "";
}
}
1.1 date: 2007/04/17 15:16:54; author: pmuir; state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/ui/PluginComponentHandler.java
Index: PluginComponentHandler.java
===================================================================
package org.jboss.seam.wiki.core.ui;
import javax.faces.component.UIComponent;
import com.sun.facelets.FaceletContext;
import com.sun.facelets.tag.jsf.ComponentConfig;
import com.sun.facelets.tag.jsf.ComponentHandler;
public class PluginComponentHandler extends ComponentHandler
{
public PluginComponentHandler(ComponentConfig config)
{
super(config);
}
@Override
protected void onComponentCreated(FaceletContext ctx, UIComponent c, UIComponent parent)
{
super.onComponentCreated(ctx, c, parent);
parent.getAttributes().put(UIPlugin.NEXT_PLUGIN, c.getClientId(ctx.getFacesContext()));
}
}
More information about the jboss-cvs-commits
mailing list