package org.caudexorigo.jpt;
import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.mvel2.MVEL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JptMacroNode extends JptParentNode
{
private static final Logger log = LoggerFactory.getLogger(JptMacroNode.class);
private boolean _isInSlot;
private final String _ctx_object_type;
private final Map<String, String> _macroParams;
private final URI _muri;
private final String _tmpl;
public JptMacroNode(URI muri, String ctx_object_type, boolean isInSlot, Map<String, String> macroParams)
{
_muri = muri;
_ctx_object_type = ctx_object_type;
_isInSlot = isInSlot;
_macroParams = macroParams;
_tmpl = StringUtils.substringAfterLast(StringUtils.substringBefore(_muri.toString(), "?"), "/");
}
public boolean isInSlot()
{
return _isInSlot;
}
boolean isMacroNode()
{
return true;
}
public void render(Map<String, Object> context, Writer out) throws IOException
{
Map<String, Object> originalContext = new HashMap<String, Object>();
originalContext.putAll(context);
Map<String, Object> macroContext = new HashMap<String, Object>();
// System.out.printf("JptMacroNode template: %s # _ctx_object_type -> %s%n", _tmpl, _ctx_object_type);
// System.out.printf("JptMacroNode template: %s # isInSlot -> %s%n", _tmpl, _isInSlot);
// System.out.printf("JptMacroNode template: %s # renderContext -> %s%n", _tmpl, context.toString());
// System.out.printf("JptMacroNode template: %s # macroParams -> %s%n", _tmpl, _macroParams.toString());
Set<Entry<String, String>> param_entries = _macroParams.entrySet();
for (Entry<String, String> entry : param_entries)
{
if ("macro".equals(entry.getKey()))
{
continue;
}
// System.out.printf("JptMacroNode params: %s -> %s%n", entry.getKey(), entry.getValue());
try
{
Object value = MVEL.eval(entry.getValue().toString(), context);
// System.out.printf("JptMacroNode parsedParamValue: %s -> %s%n", entry.getValue().toString(), value.toString());
macroContext.put(entry.getKey(), value);
}
catch (org.mvel2.PropertyAccessException t)
{
log.warn(String.format("%nPropertyAccessException for parameter value: '%s' in template '%s'. Using the value as string.%nRender context: %s%n%n", entry.getValue(), _tmpl, context.toString()));
macroContext.put(entry.getKey(), entry.getValue());
}
}
originalContext.putAll(macroContext);
Set<String> keys = context.keySet();
for (String key : keys)
{
if (key.equals("$this"))
{
macroContext.put("$parent", context.get(key));
}
else
{
macroContext.put(key, context.get(key));
}
}
try
{
Object oCtx = Class.forName(_ctx_object_type).newInstance();
macroContext.put("$this", oCtx);
}
catch (Throwable t)
{
throw new RuntimeException(t);
}
// System.out.printf("JptMacroNode template: %s # context: %s%n", _tmpl, originalContext);
// System.out.printf("JptMacroNode template: %s # macroContext: %s%n", _tmpl, macroContext);
try
{
int child_count = getChildCount();
for (int i = 0; i < child_count; i++)
{
JptNode jpt_node = getChild(i);
// System.out.printf("JptMacroNode.render.jpt_node.isInSlot: %s%n", jpt_node.isInSlot());
if (jpt_node.isInSlot())
jpt_node.render(originalContext, out);
else
jpt_node.render(macroContext, out);
}
}
catch (Throwable t)
{
String s = String.format("Error during the processing of '%s'", _muri);
log.error(s);
throw new RuntimeException(s, t);
}
}
public String getMacroTemplate()
{
return _tmpl;
}
}