[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()) + "&amp;width=" + thumbnailWidth + "&amp;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()) + "&amp;width="
  +                     + thumbnailWidth + "&amp;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