[jboss-cvs] jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/links ...

Christian Bauer christian.bauer at jboss.com
Fri Feb 16 11:26:44 EST 2007


  User: cbauer  
  Date: 07/02/16 11:26:44

  Modified:    examples/wiki/src/org/jboss/seam/wiki/core/links  
                        WikiTextParser.java WikiLinkResolver.java
  Log:
  Fixed the Wiki, basics work now
  
  Revision  Changes    Path
  1.2       +9 -2      jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/links/WikiTextParser.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: WikiTextParser.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/links/WikiTextParser.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- WikiTextParser.java	1 Feb 2007 07:08:28 -0000	1.1
  +++ WikiTextParser.java	16 Feb 2007 16:26:44 -0000	1.2
  @@ -9,25 +9,32 @@
   
   public class WikiTextParser extends SeamTextParser {
   
  -    private Map<String, WikiLinkResolver.WikiLink> links = new HashMap<String, WikiLinkResolver.WikiLink>();
  +    private String linkClass;
  +    private String brokenLinkClass;
   
  +    private Map<String, WikiLinkResolver.WikiLink> links = new HashMap<String, WikiLinkResolver.WikiLink>();
       private WikiLinkResolver resolver;
   
       public WikiTextParser(TokenStream tokenStream, String linkClass, String brokenLinkClass) {
           super(tokenStream);
  +        this.linkClass = linkClass;
  +        this.brokenLinkClass = brokenLinkClass;
           resolver = (WikiLinkResolver)Component.getInstance(WikiLinkResolver.class);
       }
   
  +    // TODO: Not a pretty dependency... this needs to be called first
       protected String linkUrl(String linkText) {
           resolver.resolveWikiLink(links, linkText.trim());
           return links.get(linkText).url;
       }
   
  +    // then this needs to be called by the parser
       protected String linkDescription(String descriptionText, String linkText) {
  +        if (descriptionText != null && descriptionText.length() >0) return descriptionText;
           return links.get(linkText).description;
       }
   
       protected String linkClass(String linkText) {
  -        return links.get(linkText).broken ? "foo" : "bar";
  +        return links.get(linkText).broken ? brokenLinkClass : linkClass;
       }
   }
  
  
  
  1.2       +156 -54   jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/links/WikiLinkResolver.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: WikiLinkResolver.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/wiki/src/org/jboss/seam/wiki/core/links/WikiLinkResolver.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- WikiLinkResolver.java	1 Feb 2007 07:08:28 -0000	1.1
  +++ WikiLinkResolver.java	16 Feb 2007 16:26:44 -0000	1.2
  @@ -6,37 +6,46 @@
   import org.jboss.seam.wiki.core.node.Document;
   import org.jboss.seam.wiki.core.node.Directory;
   import org.jboss.seam.wiki.core.node.Node;
  +import org.jboss.seam.wiki.core.prefs.GlobalPreferences;
  +import org.jboss.seam.Component;
   
   import javax.persistence.EntityManager;
   import javax.persistence.EntityNotFoundException;
   import javax.persistence.NoResultException;
  +import javax.faces.context.FacesContext;
   import java.util.regex.Pattern;
   import java.util.regex.Matcher;
   import java.util.Map;
  -import java.net.URLEncoder;
  -import java.io.UnsupportedEncodingException;
   
   @Name("wikiLinkResolver")
   public class WikiLinkResolver {
   
       // Prepended to primary keys in the database, e.g. [This is a stored link=>wiki://5]
  -    public static final String WIKI_PROTOCOL = "wiki://";
  +    public static final String WIKI_PROTOCOL = "wiki://([0-9]+)";
   
  -    // Used against page names, wimply remove everything that is not alphanumeric, should do for most strings
  +    // Known protocols are rendered as is
  +    public static final String KNOWN_PROTOCOLS = "(http://)|(https://)|(ftp://)|(mailto:)";
  +
  +    // Used against page names, simply remove everything that is not alphanumeric, should do for most strings
       public static final String WIKINAME_REMOVECHARACTERS = "[^\\p{Alnum}]+";
   
  -    // Render this string whenever [=>wiki://123] needs to be resolved but can't
  -    public static final String BROKENLINK_MARKER = "BROKEN LINK";
  +    // Render these strings whenever [=>wiki://123] needs to be resolved but can't
  +    public static final String BROKENLINK_URL = "PageDoesNotExist";
  +    public static final String BROKENLINK_DESCRIPTION = "?BROKEN LINK?";
   
       // Match [GROUP1=>GROUP2], used to replace links from user input with wiki:// URLs
       public static final String WIKILINK_REGEX_FORWARD =
               Pattern.quote("[") + "([^" + Pattern.quote("]") + "|" + Pattern.quote("[") + "]*)" +
  -            "=>([^(?://|@|" + Pattern.quote("]") + "|" + Pattern.quote("[") + ")]+)" + Pattern.quote("]");
  +            "=>([^(?://)@" + Pattern.quote("]") + Pattern.quote("[") + "]+)" + Pattern.quote("]");
  +
  +    // Match "Foo Bar|Baz Brrr" as two groups
  +    public static final String WIKILINK_REGEX_CROSSAREA = "^(.*)" + Pattern.quote("|") + "(.*)$";
  +
   
       // Match [GROUP1=>wiki://GROUP2], used to replace wiki:// URLs with page names
       public static final String WIKILINK_REGEX_REVERSE =
               Pattern.quote("[") + "([^" + Pattern.quote("]") + "|" + Pattern.quote("[") + "]*)" +
  -            "=>" + WIKI_PROTOCOL + "([0-9]+)" + Pattern.quote("]");
  +            "=>" + WIKI_PROTOCOL + Pattern.quote("]");
   
       @In(create = true)
       protected EntityManager entityManager;
  @@ -47,43 +56,52 @@
       @In(required = false)
       private Directory currentDirectory;
   
  +    @In(create = true)
  +    protected Directory wikiRoot;
  +
       public static String convertToWikiName(String realName) {
           return realName.replaceAll(WIKINAME_REMOVECHARACTERS, "");
       }
   
       public String convertToWikiLinks(Directory area, String wikiText) {
  -        StringBuffer replacedWikiText = new StringBuffer(wikiText.length());
  +        if (wikiText == null) return null;
   
  -        Pattern pattern = Pattern.compile(WIKILINK_REGEX_FORWARD);
  -        Matcher matcher = pattern.matcher(wikiText);
  +        StringBuffer replacedWikiText = new StringBuffer(wikiText.length());
  +        Matcher matcher = Pattern.compile(WIKILINK_REGEX_FORWARD).matcher(wikiText);
   
           // Replace with [Link Text=>wiki://<node id>] or leave as is if not found
           while (matcher.find()) {
  -            Node node = findNodeInArea(area, convertToWikiName(matcher.group(2)));
  -            if (node != null) {
  -                matcher.appendReplacement(replacedWikiText, "[$1=>wiki://" + node.getId() + "]");
  -            }
  +            String linkText = matcher.group(2);
  +            Node node = resolveCrossAreaLinkText(area, linkText);
  +            if (node != null) matcher.appendReplacement(replacedWikiText, "[$1=>wiki://" + node.getId() + "]");
           }
           matcher.appendTail(replacedWikiText);
           return replacedWikiText.toString();
       }
   
  -    public String convertFromWikiLinks(String wikiText) {
  +    public String convertFromWikiLinks(Directory area, String wikiText) {
           if (wikiText == null) return null;
           
           StringBuffer replacedWikiText = new StringBuffer(wikiText.length());
  +        Matcher matcher = Pattern.compile(WIKILINK_REGEX_REVERSE).matcher(wikiText);
   
  -        Pattern pattern = Pattern.compile(WIKILINK_REGEX_REVERSE);
  -        Matcher matcher = pattern.matcher(wikiText);
  -
  -        // Replace with [Link Text=>Page Name] or replace with BROKEN LINK marker
  +        // Replace with [Link Text=>Page Name] or replace with BROKENLINK "page name"
           while (matcher.find()) {
  +
               // Find the node by PK
               Node node = findNode(Long.valueOf(matcher.group(2)));
  -            if (node != null) {
  +
  +            // Node is in current area, just use its name
  +            if (node != null && node.getAreaNumber().equals(area.getAreaNumber())) {
                   matcher.appendReplacement(replacedWikiText, "[$1=>" + node.getName() + "]");
  +
  +            // Node is in different area, prepend the area name
  +            } else if (node != null && !node.getAreaNumber().equals(area.getAreaNumber())) {
  +                matcher.appendReplacement(replacedWikiText, "[$1=>" + node.getArea().getName() + "|" + node.getName() + "]");
  +
  +            // Couldn't find it anymore, its a broken link
               } else {
  -                matcher.appendReplacement(replacedWikiText, "[$1=>" + BROKENLINK_MARKER + "]");
  +                matcher.appendReplacement(replacedWikiText, "[$1=>" + BROKENLINK_DESCRIPTION + "]");
               }
           }
           matcher.appendTail(replacedWikiText);
  @@ -96,54 +114,72 @@
           // Don't resolve twice
           if (links.containsKey(linkText)) return;
   
  -        Pattern pattern = Pattern.compile(WIKI_PROTOCOL + "([0-9]+)");
  -        Matcher matcher = pattern.matcher(linkText);
  +        Matcher wikiUrlMatcher = Pattern.compile(WIKI_PROTOCOL).matcher(linkText);
  +        Matcher knownProtocolMatcher = Pattern.compile(KNOWN_PROTOCOLS).matcher(linkText);
   
           WikiLink wikiLink = null;
   
           // Check if its a common protocol
  -        if ("http://".equals(linkText.substring(0, 6)) ||
  -            "https://".equals(linkText.substring(0,7)) ||
  -            "mailto://".equals(linkText.substring(0,8)) ||
  -            "ftp://".equals(linkText.substring(0,5))
  -           ) {
  +        if (knownProtocolMatcher.find()) {
               wikiLink = new WikiLink(null, false, linkText, linkText);
   
           // Check if it is a wiki protocol
  -        } else if (matcher.find()) {
  +        } else if (wikiUrlMatcher.find()) {
   
               // Find the node by PK
  -            Node node = findNode(Long.valueOf(matcher.group(1)));
  +            Node node = findNode(Long.valueOf(wikiUrlMatcher.group(1)));
               if (node != null) {
  -                wikiLink = new WikiLink(node.getId(), false, node.getId() + ".html", node.getName());
  +                wikiLink = new WikiLink(node.getId(), false, renderURL(node), node.getName());
               } else {
  -                wikiLink = new WikiLink(Long.valueOf(matcher.group(1)), true, BROKENLINK_MARKER, BROKENLINK_MARKER);
  +                wikiLink = new WikiLink(null, true, BROKENLINK_URL, BROKENLINK_DESCRIPTION);
               }
   
  -        // Try a WikiWord search in the current area
  +        // Try a WikiWord search in the current or named area
  +        // (This can happen if the string [foo=>bar] or [foo=>bar|baz] was stored in the database because bar or baz
  +        // didn't exist at the time of saving, so we need to resolve it now and replace it with wiki://123)
           } else {
   
  -            Node node = findNodeInArea(currentDirectory, convertToWikiName(linkText));
  +            Node node = resolveCrossAreaLinkText(currentDirectory, linkText);
               if (node!=null) {
  -                wikiLink = new WikiLink(node.getId(), false, node.getId() + ".html", node.getName());
  -                // Run the converter again and UPDATE the currentDocument (yes, not the best solution)
  +                wikiLink = new WikiLink(node.getId(), false, renderURL(node), node.getName());
  +                // Run the converter again and UPDATE the currentDocument (yes, this happens during rendering!)
                   currentDocument.setContent(convertToWikiLinks(currentDirectory, currentDocument.getContent()));
                   // This should be updated in the database during the next flush()
  -            }
  -        }
   
  -        // Let's assume its a page name and render a real /Area/WikiLink (but encoded, so it gets transported fully)
  -        if (wikiLink == null) {
  +            } else {
  +                /* TODO: Not sure we should actually implement this..., one of these things that the wiki "designers" got wrong
  +                // OK, so it's not any recognized URL and we can't find a node with that wikiname
  +                // Let's assume its a page name and render /Area/WikiLink (but encoded, so it gets transported fully)
  +                // into the edit page when the user clicks on the link to create the document
               try {
                   String encodedPagename = currentDirectory.getWikiname() + "/" + URLEncoder.encode(linkText, "UTF-8");
                   wikiLink = new WikiLink(null, true, encodedPagename, linkText);
               } catch (UnsupportedEncodingException e) {
                   throw new RuntimeException(e); // Java is so great...
               }
  +                */
  +                wikiLink = new WikiLink(null, true, BROKENLINK_URL, BROKENLINK_DESCRIPTION);
  +            }
           }
           links.put(linkText, wikiLink);
       }
   
  +    private Node resolveCrossAreaLinkText(Node currentArea, String linkText) {
  +        Matcher crossLinkMatcher = Pattern.compile(WIKILINK_REGEX_CROSSAREA).matcher(linkText);
  +        if (crossLinkMatcher.find()) {
  +            // Try to find the node in the referenced area
  +            String areaName = crossLinkMatcher.group(1);
  +            String nodeName = crossLinkMatcher.group(2);
  +            Node crossLinkArea = findArea(convertToWikiName(areaName));
  +            if (crossLinkArea != null)
  +                return findNodeInArea(crossLinkArea.getAreaNumber(), convertToWikiName(nodeName));
  +        } else {
  +            // Try the current area
  +            return findNodeInArea(currentArea.getAreaNumber(), convertToWikiName(linkText));
  +        }
  +        return null;
  +    }
  +
       public class WikiLink {
           Long nodeId;
           boolean broken = false;
  @@ -152,8 +188,8 @@
   
           public WikiLink(Long nodeId, boolean broken, String url, String description) {
               this.nodeId = nodeId;
  -            this.broken = broken;
               this.url = url;
  +            this.broken = broken;
               this.description = description;
           }
   
  @@ -162,7 +198,23 @@
           }
       }
   
  -    // Convenience methods
  +    public static String renderURL(Node node) {
  +        GlobalPreferences globalPrefs = (GlobalPreferences) Component.getInstance("globalPrefs");
  +
  +        String contextPath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
  +
  +        if (globalPrefs.getDefaultURLRendering().equals(GlobalPreferences.URLRendering.PERMLINK)) {
  +            return contextPath + "/" + node.getId() + globalPrefs.getPermlinkSuffix();
  +        } else {
  +            if (node.getArea().getWikiname().equals(node.getWikiname()))
  +                return contextPath + "/" + node.getArea().getWikiname();
  +            return contextPath + "/" + node.getArea().getWikiname()  + "/" + node.getWikiname();
  +        }
  +    }
  +
  +    // #########################################################################################
  +
  +    // Convenience DAO methods
   
       @Transactional
       public Node findNode(Long nodeId) {
  @@ -175,13 +227,13 @@
       }
   
       @Transactional
  -    public Node findNodeInArea(Directory area, String wikiname) {
  +    public Node findNodeInArea(Long areaNumber, String wikiname) {
           entityManager.joinTransaction();
   
           try {
               return (Node) entityManager
                       .createQuery("select n from Node n where n.areaNumber = :areaNumber and n.wikiname = :wikiname")
  -                    .setParameter("areaNumber", area.getAreaNumber())
  +                    .setParameter("areaNumber", areaNumber)
                       .setParameter("wikiname", wikiname)
                       .getSingleResult();
           } catch (EntityNotFoundException ex) {
  @@ -191,13 +243,13 @@
       }
   
       @Transactional
  -    public Document findDocumentInArea(Directory area, String wikiname) {
  +    public Document findDocumentInArea(Long areaNumber, String wikiname) {
           entityManager.joinTransaction();
   
           try {
               return (Document) entityManager
                       .createQuery("select d from Document d where d.areaNumber = :areaNumber and d.wikiname = :wikiname")
  -                    .setParameter("areaNumber", area.getAreaNumber())
  +                    .setParameter("areaNumber", areaNumber)
                       .setParameter("wikiname", wikiname)
                       .getSingleResult();
           } catch (EntityNotFoundException ex) {
  @@ -207,13 +259,29 @@
       }
   
       @Transactional
  -    public Directory findDirectoryInArea(Directory area, String wikiname) {
  +    public Directory findDirectoryInArea(Long areaNumber, String wikiname) {
           entityManager.joinTransaction();
   
           try {
               return (Directory) entityManager
                       .createQuery("select d from Directory d where d.areaNumber = :areaNumber and d.wikiname = :wikiname")
  -                    .setParameter("areaNumber", area.getAreaNumber())
  +                    .setParameter("areaNumber", areaNumber)
  +                    .setParameter("wikiname", wikiname)
  +                    .getSingleResult();
  +        } catch (EntityNotFoundException ex) {
  +        } catch (NoResultException ex) {
  +        }
  +        return null;
  +    }
  +
  +    @Transactional
  +    public Directory findArea(String wikiname) {
  +        entityManager.joinTransaction();
  +
  +        try {
  +            return (Directory) entityManager
  +                    .createQuery("select d from Directory d where d.parent = :root and d.wikiname = :wikiname")
  +                    .setParameter("root", wikiRoot)
                       .setParameter("wikiname", wikiname)
                       .getSingleResult();
           } catch (EntityNotFoundException ex) {
  @@ -222,4 +290,38 @@
           return null;
       }
   
  +    // I need these methods because find() is broken, e.g. find(Document,1) would return a Directory if the
  +    // persistence context contains a directory with id 1... even more annoying, I need to catch NoResultException,
  +    // so there really is no easy and correct way to look for the existence of a row.
  +
  +    @Transactional
  +    public Document findDocument(Long documentId) {
  +        entityManager.joinTransaction();
  +
  +        try {
  +            return (Document) entityManager
  +                    .createQuery("select d from Document d where d.id = :id")
  +                    .setParameter("id", documentId)
  +                    .getSingleResult();
  +        } catch (EntityNotFoundException ex) {
  +        } catch (NoResultException ex) {
  +        }
  +        return null;
  +    }
  +
  +    @Transactional
  +    public Directory findDirectory(Long directoryId) {
  +        entityManager.joinTransaction();
  +
  +        try {
  +            return (Directory) entityManager
  +                    .createQuery("select d from Directory d where d.id = :id")
  +                    .setParameter("id", directoryId)
  +                    .getSingleResult();
  +        } catch (EntityNotFoundException ex) {
  +        } catch (NoResultException ex) {
  +        }
  +        return null;
  +    }
  +
   }
  
  
  



More information about the jboss-cvs-commits mailing list