package com.orbitz.monitoring.lib.renderer;
import com.orbitz.monitoring.api.CompositeMonitor;
import com.orbitz.monitoring.api.Monitor;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.CompactWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import org.apache.commons.beanutils.DynaBean;
import org.apache.log4j.Logger;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* XmlMonitorRenderer uses xstream to render a Monitor to XML format.
*
* @author Operations Architecture
*/
public class XmlMonitorRenderer {
private static final Logger logger = Logger.getLogger(XmlMonitorRenderer.class);
private static final String INDENT_STRING = " ";
private List allowedAttributes;
private int maxCharacters = -1;
private boolean prettyPrint = false;
/**
* Constructor.
*
* @param allowedAttributes List of attributes to allow in rendered XML
*/
public XmlMonitorRenderer(List allowedAttributes) {
this.allowedAttributes = allowedAttributes;
}
public List getAllowedAttributes() {
return allowedAttributes;
}
public static String getIndentString() {
return INDENT_STRING;
}
public int getMaxCharacters() {
return maxCharacters;
}
/**
* Renders a Monitor with attributes filtered to specified set.
*
* @param monitor ERMA monitor
* @return a String of XML
*/
public String renderMonitor(Monitor monitor) {
if (monitor == null) {
return "<null/>";
}
HierarchicalStreamWriter xmlWriter;
StringWriter stringWriter = new StringWriter();
if (prettyPrint) {
xmlWriter = new PrettyPrintWriter(stringWriter, INDENT_STRING);
} else {
xmlWriter = new CompactWriter(stringWriter);
}
writeMonitor(xmlWriter, monitor);
if ((maxCharacters != -1) && (stringWriter.getBuffer().length() > maxCharacters)) {
// clear the buffer and reuse the streams
StringBuffer sb = stringWriter.getBuffer();
int length = sb.length();
sb.delete(0, length);
// required inorder to avoid the state maintained by the previous rendering
xmlWriter = new PrettyPrintWriter(stringWriter, INDENT_STRING);
writeMonitorTerse(xmlWriter, monitor, length);
}
return stringWriter.toString();
}
public void setMaxCharacters(int maxCharacters) {
this.maxCharacters = maxCharacters;
}
public boolean isPrettyPrint() {
return prettyPrint;
}
public void setPrettyPrint(boolean prettyPrint) {
this.prettyPrint = prettyPrint;
}
protected void writeMonitorTerse(HierarchicalStreamWriter writer, Monitor monitor, int length) {
String monitorClassName = monitor.getClass().getName();
int classIdx = monitorClassName.lastIndexOf('.');
if (classIdx >= 0) {
monitorClassName = monitorClassName.substring(classIdx + 1);
}
String message = "Error rendering event pattern: length is " + length + ", max length is "
+ maxCharacters;
writer.startNode(monitorClassName);
appendMonitorDataAsAttributes(writer, monitor);
writer.setValue("\n" + INDENT_STRING + message + "\n");
writer.endNode();
logger.warn(message);
}
// private methods ********************************************************
protected void writeMonitor(HierarchicalStreamWriter writer, Monitor monitor) {
String monitorClassName = monitor.getClass().getName();
int classIdx = monitorClassName.lastIndexOf('.');
if (classIdx >= 0) {
monitorClassName = monitorClassName.substring(classIdx + 1);
}
writer.startNode(monitorClassName);
appendMonitorDataAsAttributes(writer, monitor);
// recursively add all child monitors to dom tree
if (CompositeMonitor.class.isAssignableFrom(monitor.getClass())) {
CompositeMonitor cm = (CompositeMonitor) monitor;
Collection childMonitors = cm.getChildMonitors();
Iterator childIterator = childMonitors.iterator();
while (childIterator.hasNext()) {
Monitor childMonitor = (Monitor) childIterator.next();
writeMonitor(writer, childMonitor);
}
}
writer.endNode();
}
protected void appendMonitorDataAsAttributes(HierarchicalStreamWriter writer, Monitor monitor) {
Iterator it = allowedAttributes.iterator();
while (it.hasNext()) {
String attributeName = (String) it.next();
if (monitor.hasAttribute(attributeName)) {
String attributeValue = monitor.getAsString(attributeName);
if (attributeValue == null) {
writer.addAttribute(attributeName, "null");
} else {
if (attributeValue.indexOf("LazyDynaBean") > -1) {
DynaBean dynaBean = (DynaBean) monitor.get(attributeName);
Object clazz = dynaBean.get("class");
if (clazz != null) {
attributeValue = clazz.toString();
}
}
int idx = attributeValue.indexOf("\n");
if (idx > -1) {
attributeValue = attributeValue.substring(0, idx);
}
writer.addAttribute(attributeName, attributeValue);
}
}
}
}
}