[jboss-cvs] jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/links ...
Christian Bauer
christian at hibernate.org
Wed Mar 7 13:37:38 EST 2007
User: cbauer
Date: 07/03/07 13:37:38
Added: examples/wiki/src/main/org/jboss/seam/wiki/core/links
WikiLinkResolver.java
Log:
Moved to hot-redeploy WAR build structure
Revision Changes Path
1.1 date: 2007/03/07 18:37:38; author: cbauer; state: Exp;jboss-seam/examples/wiki/src/main/org/jboss/seam/wiki/core/links/WikiLinkResolver.java
Index: WikiLinkResolver.java
===================================================================
package org.jboss.seam.wiki.core.links;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.wiki.core.model.Document;
import org.jboss.seam.wiki.core.model.Directory;
import org.jboss.seam.wiki.core.dao.NodeDAO;
import org.jboss.seam.wiki.core.model.*;
import org.jboss.seam.wiki.core.ui.WikiUtil;
import org.jboss.seam.wiki.core.ui.WikiLink;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Map;
@Name("wikiLinkResolver")
@AutoCreate
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://([0-9]+)";
// 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 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("]");
// 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 + Pattern.quote("]");
@In
private NodeDAO nodeDAO;
@In(required = false)
private Document currentDocument;
@In(required = false)
private Directory currentDirectory;
public static String convertToWikiName(String realName) {
return realName.replaceAll(WIKINAME_REMOVECHARACTERS, "");
}
public String convertToWikiLinks(Directory area, String wikiText) {
if (wikiText == null) return null;
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()) {
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(Directory area, String wikiText) {
if (wikiText == null) return null;
StringBuffer replacedWikiText = new StringBuffer(wikiText.length());
Matcher matcher = Pattern.compile(WIKILINK_REGEX_REVERSE).matcher(wikiText);
// Replace with [Link Text=>Page Name] or replace with BROKENLINK "page name"
while (matcher.find()) {
// Find the node by PK
Node node = nodeDAO.findNode(Long.valueOf(matcher.group(2)));
// 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_DESCRIPTION + "]");
}
}
matcher.appendTail(replacedWikiText);
return replacedWikiText.toString();
}
@Transactional
public void resolveWikiLink(Map<String, WikiLink> links, String linkText) {
// Don't resolve twice
if (links.containsKey(linkText)) return;
Matcher wikiUrlMatcher = Pattern.compile(WIKI_PROTOCOL).matcher(linkText);
Matcher knownProtocolMatcher = Pattern.compile(KNOWN_PROTOCOLS).matcher(linkText);
WikiLink wikiLink;
// Check if its a common protocol
if (knownProtocolMatcher.find()) {
wikiLink = new WikiLink(null, false, linkText, linkText, true);
// Check if it is a wiki protocol
} else if (wikiUrlMatcher.find()) {
// Find the node by PK
Node node = nodeDAO.findNode(Long.valueOf(wikiUrlMatcher.group(1)));
if (node != null) {
wikiLink = new WikiLink(node, false, WikiUtil.renderURL(node), node.getName(), false);
} else {
wikiLink = new WikiLink(null, true, BROKENLINK_URL, BROKENLINK_DESCRIPTION, false);
}
// 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 = resolveCrossAreaLinkText(currentDirectory, linkText);
if (node!=null) {
wikiLink = new WikiLink(node, false, WikiUtil.renderURL(node), node.getName(), false);
// 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()
} 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, false);
}
}
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 = nodeDAO.findArea(convertToWikiName(areaName));
if ( crossLinkArea != null && (nodeName == null || nodeName.length() == 0) )
return crossLinkArea; // Support [=>This is an Area Link|] syntax
else if (crossLinkArea != null)
return nodeDAO.findNodeInArea(crossLinkArea.getAreaNumber(), convertToWikiName(nodeName));
} else {
// Try the current area
return nodeDAO.findNodeInArea(currentArea.getAreaNumber(), convertToWikiName(linkText));
}
return null;
}
}
More information about the jboss-cvs-commits
mailing list