// Use the WikiTextParser to resolve macros
WikiTextParser parser = new WikiTextParser((String) getValue(), true, true);
// Resolve the base document and directory we are resolving against
final WikiFile baseFile = (WikiFile)getAttributes().get(ATTR_LINK_BASE_FILE);
final Long currentAreaNumber = (Long)getAttributes().get(ATTR_CURRENT_AREA_NUMBER);
parser.setCurrentAreaNumber(currentAreaNumber);
parser.setResolver((WikiLinkResolver)Component.getInstance("wikiLinkResolver"));
// TODO: Externalize this to separate class, extensible
// Set a customized renderer for parser macro callbacks
class WikiFormattedTextRenderer extends DefaultWikiTextRenderer {
@Override
public String renderInternalLink(WikiLink internalLink) {
return "<a href=\""
+ (
internalLink.isBroken()
? internalLink.getUrl()
: wikiURLRenderer.renderURL(internalLink.getFile())
)
+ (
internalLink.getFragment() != null
? "#"+internalLink.getEncodedFragment()
: ""
)
+ "\" target=\""
+ (getAttributes().get(ATTR_INTERNAL_TARGET_FRAME) != null ? getAttributes().get(ATTR_INTERNAL_TARGET_FRAME) : "")
+ "\" class=\""
+ (internalLink.isBroken() ? getAttributes().get(ATTR_BROKEN_LINK_STYLE_CLASS)
: getAttributes().get(ATTR_LINK_STYLE_CLASS)) + "\">"
+ internalLink.getDescription() + "</a>";
}
@Override
public String renderExternalLink(WikiLink externalLink) {
return "<a href=\""
+ WikiUtil.escapeEmailURL(externalLink.getUrl())
+ "\" target=\""
+ (getAttributes().get(ATTR_EXTERNAL_TARGET_FRAME) != null ? getAttributes().get(ATTR_EXTERNAL_TARGET_FRAME) : "")
+ "\" class=\""
+ (externalLink.isBroken() ? getAttributes().get(ATTR_BROKEN_LINK_STYLE_CLASS)
: getAttributes().get(ATTR_LINK_STYLE_CLASS)) + "\">"
+ WikiUtil.escapeEmailURL(externalLink.getDescription()) + "</a>";
}
@Override
public String renderFileAttachmentLink(int attachmentNumber, WikiLink attachmentLink) {
return "<a href=\""
+ wikiURLRenderer.renderURL(baseFile)
+ "#attachment" + attachmentNumber
+ "\" target=\""
+ (getAttributes().get(ATTR_INTERNAL_TARGET_FRAME) != null ? getAttributes().get(ATTR_INTERNAL_TARGET_FRAME) : "")
+ "\" class=\""
+ getAttributes().get(ATTR_ATTACHMENT_LINK_STYLE_CLASS) + "\">"
+ attachmentLink.getDescription() + "[" + attachmentNumber + "]" + "</a>";
}
@Override
public String renderThumbnailImageLink(WikiLink link) {
// TODO: This is not typesafe and clean, need different rendering strategy for WikiUpload subclasses
WikiUploadImage image = (WikiUploadImage)link.getFile();
if (image.getThumbnail() == WikiUploadImage.Thumbnail.FULL.getFlag()) {
// Full size display, no thumbnail
//TODO: Make sure we really don't need this - but it messes up the comment form conversation:
//String imageUrl = WikiUtil.renderURL(image) + "&cid=" + Conversation.instance().getId();
String imageUrl = wikiURLRenderer.renderURL(image);
return "<img src='"+ imageUrl + "'" +
" width='"+ image.getSizeX()+"'" +
" height='"+ image.getSizeY() +"'/>";
} else {
// Thumbnail with link display
//TODO: Make sure we really don't need this - but it messes up the comment form conversation:
// String thumbnailUrl = WikiUtil.renderURL(image) + "&thumbnail=true&cid=" + Conversation.instance().getId();
String thumbnailUrl = wikiURLRenderer.renderURL(image) + "?thumbnail=true";
return "<a href=\""
+ (link.isBroken() ? link.getUrl() : wikiURLRenderer.renderURL(image))
+ "\" target=\""
+ (getAttributes().get(ATTR_INTERNAL_TARGET_FRAME) != null ? getAttributes().get(ATTR_INTERNAL_TARGET_FRAME) : "")
+ "\" class=\""
+ getAttributes().get(ATTR_THUMBNAIL_LINK_STYLE_CLASS) + "\"><img src=\""
+ thumbnailUrl + "\"/></a>";
}
}
@Override
public String renderMacro(WikiTextMacro macro) {
WikiPluginMacro pluginMacroWithTemplate = macrosWithTemplateByPosition.get(macro.getPosition());
if (pluginMacroWithTemplate == null) {
log.debug("macro does not have an XHTML template/include, skipping: " + macro);
return "";
}
log.debug("firing BEFORE_VIEW_RENDER macro event");
Events.instance().raiseEvent(
pluginMacroWithTemplate.getCallbackEventName(WikiPluginMacro.CallbackEvent.BEFORE_VIEW_RENDER),
pluginMacroWithTemplate
);
log.debug("preparing include rendering for macro: " + pluginMacroWithTemplate);
UIComponent child = findComponent( pluginMacroWithTemplate.getClientId() );
log.debug("JSF child client identifier: " + child.getClientId(getFacesContext()));
ResponseWriter originalResponseWriter = getFacesContext().getResponseWriter();
StringWriter stringWriter = new StringWriter();
ResponseWriter tempResponseWriter = originalResponseWriter
.cloneWithWriter(stringWriter);
getFacesContext().setResponseWriter(tempResponseWriter);
try {
log.debug("rendering template of macro: " + pluginMacroWithTemplate);
JSF.renderChild(getFacesContext(), child);
log.debug("firing AFTER_VIEW_RENDER macro event");
Events.instance().raiseEvent(
pluginMacroWithTemplate.getCallbackEventName(WikiPluginMacro.CallbackEvent.AFTER_VIEW_RENDER),
pluginMacroWithTemplate
);
}
catch (Exception ex) {
throw new RuntimeException(ex);
} finally {
getFacesContext().setResponseWriter(originalResponseWriter);
}
return stringWriter.getBuffer().toString();
}
@Override
public void setAttachmentLinks(List<WikiLink> attachmentLinks) {
// Put attachments (wiki links...) into the event context for later rendering
String contextVariable = "attachmentLinksByWikiFile";
// We need to key them by WikiFile identifier, so we put a map in the context
Map<Long, List<WikiLink>> linksByFile;
if ((linksByFile = (Map)Contexts.getEventContext().get(contextVariable)) == null) {
linksByFile = new HashMap();
}
// This method may be called multiple times when we render a "base file", e.g. header, content, footer, comments
List<WikiLink> linksForBaseFile;
if ((linksForBaseFile = linksByFile.get(baseFile.getId())) != null) {
// Aggregate all links for a base file, don't reset them on each render pass for the same base file
linksForBaseFile.addAll(attachmentLinks);
} else {
linksForBaseFile = attachmentLinks;
}
linksByFile.put(baseFile.getId(), linksForBaseFile);
Contexts.getEventContext().set(contextVariable, linksByFile);
}
@Override