[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