/**
* AbstractVelocityStatus.java
*
* @author Philip Crotwell
*/
package edu.sc.seis.sod.status;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;
import edu.sc.seis.sod.SodUtil;
import edu.sc.seis.sod.process.waveform.LocalSeismogramTemplateGenerator;
import edu.sc.seis.sod.status.networkArm.NetworkMonitor;
import edu.sc.seis.sod.status.waveformArm.WaveformMonitor;
public abstract class AbstractVelocityStatus implements WaveformMonitor,
NetworkMonitor {
public AbstractVelocityStatus(Element config) throws SQLException,
MalformedURLException, IOException {
this(FileWritingTemplate.getBaseDirectoryName(),
getTemplateName(config));
}
public AbstractVelocityStatus(String fileDir, String templateName)
throws SQLException, IOException {
this.fileDir = fileDir;
this.templateName = templateName;
template = loadTemplate(templateName);
try {
Element menuEl = TemplateFileLoader.getTemplate(getClass().getClassLoader(),
MenuTemplate.TEMPLATE_LOC);
MenuTemplate menu = new MenuTemplate(menuEl,
createExamplePath(),
fileDir);
renderedMenu = menu.getResult();
} catch(Exception e) {
GlobalExceptionHandler.handle("Trouble creating menuTemplate for Velocity based status",
e);
}
}
public static String getTemplateName(Element config)
throws MalformedURLException {
String templateName = getNestedTextForElement("template", config);
if(templateName != null) { return templateName; }
throw new MalformedURLException("template config param is null");
}
public static String getNestedTextForElement(String elementName,
Element config) {
NodeList nl = config.getChildNodes();
for(int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
if(n instanceof Element) {
Element element = (Element)n;
if(element.getTagName().equals(elementName)) { return SodUtil.getNestedText(element); }
}
}
return null;
}
//creates a path with the same number of directories as the actual location
//will for use in menu creationw
private String createExamplePath() {
String path = fileDir + '/';
for(int i = 0; i < getNumDirDeep(); i++) {
path += "dir/";
}
return path + "file.html";
}
/**
* Method getNumDirDeep returns how many directories below the base status
* directory this template will write
*/
public abstract int getNumDirDeep();
/** loads the default template, given by the <template> tag in the config. */
protected String loadTemplate() throws IOException {
return loadTemplate(templateName);
}
/**
* loads the named template. This method is in case a velocity processor has
* more than one template generated by the same java class.
*/
protected String loadTemplate(String templateName) throws IOException {
URL templateURL = TemplateFileLoader.getUrl(this.getClass()
.getClassLoader(), templateName);
BufferedReader read = new BufferedReader(new InputStreamReader(templateURL.openStream()));
String line, outTemplate = "";
while((line = read.readLine()) != null) {
outTemplate += line + System.getProperty("line.separator");
}
read.close();
return outTemplate;
}
/**
* Schedules the default template, from the <template> element in the config,
* for output.
*/
public void scheduleOutput(final String filename, final Context context) {
scheduleOutput(filename, context, template);
}
/** Schedules the given template for output. */
public void scheduleOutput(String filename, Context context, String template) {
OutputScheduler.getDefault().schedule(new VelocityRenderer(filename,
context,
template));
}
private final class VelocityRenderer implements Runnable {
private final String filename;
private final Context context;
private final String template;
private VelocityRenderer(String filename, Context context,
String template) {
this.filename = filename;
this.context = context;
this.template = template;
}
public void run() {
StringWriter out = new StringWriter();
try {
VelocityEngine engine = LocalSeismogramTemplateGenerator.getVelocity();
synchronized(engine) {
// the new VeocityContext "wrapper" is to help with a
// possible memory leak
// due to velocity gathering introspection information,
// see
// http://jakarta.apache.org/velocity/developer-guide.html#Other%20Context%20Issues
Context tempContext = new VelocityContext(context);
tempContext.put("menu", renderedMenu);
engine.evaluate(tempContext, out, filename, template);
}
FileWritingTemplate.write(fileDir + "/" + filename,
out.getBuffer().toString());
} catch(Exception e) {
GlobalExceptionHandler.handle(e);
}
}
public boolean equals(Object o) {
if(o instanceof VelocityRenderer) { return ((VelocityRenderer)o).filename.equals(this.filename); }
return false;
}
public int hashCode() {
return filename.hashCode();
}
}
private String renderedMenu, fileDir, templateName, template = "";
}