/* Copyright (C) 2005 Tresys Technology, LLC
* License: refer to COPYING file for license information.
* Authors: Spencer Shimko <sshimko@tresys.com>
*
* Converter.java: The reference policy documentation converter
* Version: @version@
*/
import policy.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Map;
/**
* The reference policy documentation generator and xml analyzer class.
* It pulls in XML describing reference policy, transmogrifies it,
* and spits it back out in some other arbitrary format.
*/
public class Converter{
private Policy policy;
private static final String HTMLEXT = ".html";
private static final String indexContent =
"<div id=\"Content\"><h2>Welcome to the reference policy API!</h2><p/>" +
"Please choose from the navigation options to the left.</div>";
private StringBuffer headerOutput = new StringBuffer();
private StringBuffer footerOutput = new StringBuffer();
private File outDir;
public Converter(Policy pol, File headerFile, File footerFile) throws IOException{
policy = pol;
/*
* Setup header and footer.
*/
FileReader headIn = new FileReader(headerFile);
BufferedReader br = new BufferedReader(headIn);
String line = null; //not declared within while loop
while (( line = br.readLine()) != null){
headerOutput.append(line);
headerOutput.append(System.getProperty("line.separator"));
}
FileReader footerIn = new FileReader(footerFile);
br = new BufferedReader(footerIn);
line = null; //not declared within while loop
while (( line = br.readLine()) != null){
footerOutput.append(line);
footerOutput.append(System.getProperty("line.separator"));
}
}
public void Convert(File _outDir) throws IOException{
outDir = _outDir;
// write the index document
FileWrite("index" + HTMLEXT, headerOutput.toString()
+ Menu().toString() + indexContent + footerOutput.toString());
// walk the policy and write pages for each module
for(Map.Entry<String,Layer> lay:policy.Children.entrySet()){
Layer layer = lay.getValue();
// the base output contains the menu and layer content header
StringBuffer baseOutput = new StringBuffer();
// the layer output will be filled with modules and summarys for content
StringBuffer layerOutput = new StringBuffer();
// create the navigation menu
baseOutput.append(Menu(layer.Name));
baseOutput.append("<div id=\"Content\">\n");
baseOutput.append("\t<h1>Layer: " + layer.Name + "</h1><p/>\n");
layerOutput.append("<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\" width=\"75%\">\n");
layerOutput.append("<tr><th class=\"title\">Module Name</th>" +
"<th class=\"title\">Summary</th></tr>");
for(Map.Entry<String,Module> mod:layer.Children.entrySet()){
// module output will be filled with in-depth module info.
StringBuffer moduleOutput = new StringBuffer();
Module module = mod.getValue();
// get the content for the module's document
moduleOutput.append(moduleContent(mod.getValue()).toString() + "</div>");
// get the summary and name for the layer's document
layerOutput.append("<tr><td><a href=\"" + layer.Name + "_" + module.Name + HTMLEXT
+ "\">" + module.Name + "</a></td>" +
"\n<td>" + module.PCDATA + "</td></tr>\n");
// write module document
FileWrite(layer.Name + "_" + module.Name + HTMLEXT,
headerOutput.toString() + "\n" + baseOutput.toString() + moduleOutput.toString() + footerOutput.toString());
}
// write layer document
FileWrite(layer.Name + HTMLEXT,
headerOutput.toString() + "\n" + baseOutput.toString()
+ layerOutput.toString() + "</div>" + footerOutput.toString());
}
}
private StringBuffer Menu(String key){
StringBuffer out = new StringBuffer();
out.append("<div id=\"Menu\">\n");
for(Map.Entry<String,Layer> layer:policy.Children.entrySet()){
String layerName = layer.getKey();
// show the modules for the current key
if (layerName.equals(key)){
out.append("\t<a href=\"" + layerName
+ HTMLEXT + "\">" + layerName + "</a><br />\n");
out.append("\t<div id=\"subitem\">\n");
for(Map.Entry<String,Module> module:layer.getValue().Children.entrySet()){
String moduleName = module.getKey();
out.append("\t\t- <a href=\"" + layerName + "_" + moduleName + HTMLEXT
+ "\">" + moduleName + "</a><br />\n");
}
out.append("\t</div>\n");
} else {
out.append("\t<a href=\"" + layerName +
HTMLEXT + "\">+ " + layerName + "</a><br />\n");
}
}
out.append("</div>");
return out;
}
private StringBuffer Menu(){
StringBuffer out = new StringBuffer();
out.append("<div id=\"Menu\">\n");
for(Map.Entry<String,Layer> layer:policy.Children.entrySet()){
String layerName = layer.getKey();
out.append("\t<a href=\"" + layerName + HTMLEXT + "\">" + layerName + "</a><br />\n");
out.append("\t<div id=\"subitem\">\n");
for(Map.Entry<String,Module> module:layer.getValue().Children.entrySet()){
String moduleName = module.getKey();
out.append("\t\t- <a href=\"" + layerName + "_" + moduleName + HTMLEXT
+ "\">" + moduleName + "</a><br />\n");
}
out.append("\t</div>\n");
}
out.append("</div>");
return out;
}
private StringBuffer moduleContent(Module module){
StringBuffer out = new StringBuffer();
out.append("\t<h2>Module: "+ module.Name + "<br />\n");
out.append("\tSummary: " + module.PCDATA + "</h2>\n");
for (Map.Entry<String,Interface> inter:module.Children.entrySet()){
Interface iface = inter.getValue();
// main table header
out.append("<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\" width=\"75%\">\n");
out.append("<tr><th class=\"title\" colspan=\"3\">Interface</th></tr>\n");
// only show weight when type isnt none
if (iface.Type != InterfaceType.None){
out.append("<tr><td>Name</td><td colspan=\"2\">" + iface.Name + "</td></tr>\n" +
"<tr><td>Flow Type</td><td colspan=\"2\">" + iface.Type.toString() + "</td></tr>\n");
out.append("\t<td>Flow Weight</td><td colspan=\"2\">" + iface.Weight + "</td></tr>\n");
} else {
out.append("<tr><td>Name</td><td colspan=\"2\">" + iface.Name + "</td></tr>\n");
out.append("<tr><td>Flow Type</td><td colspan=\"2\">" + iface.Type.toString() + "</td></tr>\n");
}
out.append("<tr><td>Description</td><td colspan=\"2\">" + iface.PCDATA + "</td></tr>\n");
out.append("<table border=\"1\" cellspacing=\"0\" cellpadding=\"3\" width=\"75%\">\n"
+ "<tr><th class=\"title\">Parameter</th><th class=\"title\">Description</th>"
+ "<th class=\"title\">Optional</th></tr>");
for (Map.Entry<String,Parameter> param:iface.Children.entrySet()){
Parameter parameter = param.getValue();
out.append("\t<tr><td> " + parameter.Name + "</td>\n");
out.append("\t<td>" + parameter.PCDATA + "</td>\n");
String opt = parameter.GetAttribute("optional");
if (opt != null && opt.equalsIgnoreCase("true")){
out.append("\t<td><center>Yes</center></td></tr>\n");
} else {
out.append("\t<td><center>No</center></td></tr>\n");
}
}
out.append("\n</table></table><br/><br/>\n");
}
return out;
}
/**
* Write to sub directory.
* @param path
* @param outFilename
* @param content
* @return
*/
private void FileWrite (String path, String outFilename, String content){
try {
// create parent if necessary
File outParent = new File(outDir, path );
File outFile = new File(outParent, outFilename );
if (outParent.exists() && !outParent.isDirectory()){
throw new IOException("Output directory not really a directory");
} else if (!outParent.exists()){
outParent.mkdirs();
}
PrintStream stream = new PrintStream(new FileOutputStream(outFile));
stream.println(content);
stream.flush();
stream.close();
} catch (Exception e){
System.err.println (e.getMessage());
System.exit(1);
}
}
/**
* Write to output directory directly.
*
* @param path
* @param outFilename
* @param content
* @return
*/
private void FileWrite (String outFilename, String content){
try {
File out = new File(outDir, outFilename );
PrintStream stream = new PrintStream(new FileOutputStream(out));
stream.println(content);
stream.flush();
stream.close();
} catch (Exception e){
System.err.println (e.getMessage());
System.exit(1);
}
}
}