log.warn("macros are not reentrant, duplicate macro on page stack: " + wikiTextMacro);
return null;
}
// Check if the wikiTextMacro actually is registered, we don't build unknown macros
WikiPluginMacro pluginMacro = PluginRegistry.instance().createWikiPluginMacro(wikiTextMacro);
if (pluginMacro == null) {
log.info("macro is not bound in plugin registry: " + wikiTextMacro);
getPageMacroStack().pop();
return null;
}
// Check if we can find the template to include for this wikiTextMacro
String macroIncludePath = getMacroIncludePath(pluginMacro);
if (macroIncludePath == null) {
getPageMacroStack().pop();
return null;
}
// Before we build the nested components, set the WikiMacro instance in the PAGE context under a
// unique name, so we can use a VariableMapper later and alias this as 'currentMacro'
String macroPageVariableName = pluginMacro.getPageVariableName();
log.debug("setting WikiMacro instance in PAGE context as variable named: " + macroPageVariableName);
Contexts.getPageContext().set(macroPageVariableName, pluginMacro);
// Whoever wants to do something before we finally build the XHTML template
log.debug("firing VIEW_BUILD macro event");
Events.instance().raiseEvent(pluginMacro.getCallbackEventName(WikiPluginMacro.CallbackEvent.VIEW_BUILD), pluginMacro);
// This is where the magic happens... the UIWikiFormattedText component should have one child after that, a UIMacro
includeMacroFacelet(pluginMacro, macroIncludePath, context, parent);
// Now get the identifier of the newly created UIMacro instance and set it for future use
Object macroId = parent.getAttributes().get(UIMacro.NEXT_MACRO);
if (macroId != null) {
pluginMacro.setClientId(macroId.toString());
parent.getAttributes().remove(UIMacro.NEXT_MACRO);
} else {
// Best guess based wikiTextMacro renderer, needed during reRendering when we don't build the child
// - only then is NEXT_MACRO set by the MacroComponentHandler
macroId =
parent.getChildren().get(
parent.getChildCount() - 1
).getClientId(context.getFacesContext());
pluginMacro.setClientId(macroId.toString());
}
// Put an optional CSS include in the header of the wiki document we are rendering in.
// (This needs to happen after the clientId is set, as CSS resource path rendering needs to
// know if it occurs in a JSF request (clientId present) or not.