blob: ca3c2cac09fb5de21256be1bccd47001158c957b [file] [log] [blame]
package org.eclipse.stem.util.loggers.htmlgeneration;
/*******************************************************************************
* Copyright (c) 2011 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.stem.core.common.DublinCore;
import org.eclipse.stem.core.common.Identifiable;
import org.eclipse.stem.core.graph.Graph;
import org.eclipse.stem.core.model.Decorator;
import org.eclipse.stem.core.model.EdgeDecorator;
import org.eclipse.stem.core.model.GraphDecorator;
import org.eclipse.stem.core.model.Model;
import org.eclipse.stem.core.model.NodeDecorator;
import org.eclipse.stem.core.scenario.Scenario;
import org.eclipse.stem.core.sequencer.Sequencer;
import org.eclipse.stem.core.solver.Solver;
import org.eclipse.stem.util.loggers.Activator;
/**
*
* @author jhkauf
*
*/
public class HtmlScenarioPage extends HTMLdocument {
// readable labels
private static final String DECORATOR_STRING = "Decorator";
private static final String DUBLIN_CORE_STRING = "Dublin Core";
private static final String MODEL_STRING = "Model";
private static final String MODEL_GRAPH_STRING = "Graph";
private static final String SCENARIO_STRING = "Scenario";
private static final String SEQUENCER_STRING = "Sequencer";
private static final String SOLVER_STRING = "Solver";
private static final String STEM_SCENARIO_STRING = "STEM Scenario";
// ID's
private static final String DATA_ROW_ID_PREFIX = "DATA_ROW_";
private static final String DUBLINCORE_ROW_ID_PREFIX = "DUBLINCORE_ROW_";
private static final String TITLE_ROW_ID_PREFIX = "TITLE_ROW_";
// colors
private static final String COLOR_WHITE = "rgb(255, 255, 255)";
private static final String COLOR_TITLE0 = "rgb(200, 200, 255)";
private static final String COLOR_TITLE1 = "rgb(102, 255, 255)";
private static final String COLOR_DATA = "rgb(202, 255, 255)";
private static final String COLOR_DUBLINCORE = "rgb(200, 255, 200)";
private static final String COLOR_DUBLINCORE_DATA = "rgb(225, 255, 225)";
// other
private static final String FILENAME = "ScenarioLog.html";
private int indent = 0;
private static final String COLLAPSE = "-";
private static final String EXPAND = "+";
private static final String[] CELL_WIDTH = {"100px","100px","200px"};
private static final String INDENT_WIDTH = "80px";
/**
*
* @param scenario
* @param directoryName
*/
public HtmlScenarioPage(Scenario scenario, String directoryName) {
super();
createDocument(scenario);
String fileName = directoryName + FILENAME;
this.writeDocument(fileName,this.getContents());
}
/**
*
* @param scenario
*/
private void createDocument(Scenario scenario) {
Head head = new Head();
this.add(head);
String jsContent = readJsFromFile();
String cssContent = readCssFromFile();
if (!"".equals(jsContent)) {
Script jsContainer = new Script("type", "text/javascript");
jsContainer.setData(jsContent);
head.add(jsContainer);
}
if (!"".equals(cssContent)) {
Style cssContainer = new Style("type", "text/css");
cssContainer.setData(cssContent);
head.add(cssContainer);
}
Model parentModel = scenario.getModel();
EList<Decorator> decoratorList = scenario.getScenarioDecorators();
Sequencer sequencer = scenario.getSequencer();
Solver solver = scenario.getSolver();
// set up the title
String scenarioURI = scenario.getURI().toString();
String scenarioTitle = getShortName(scenarioURI);
Title title = new Title(scenarioTitle);
head.add(title);
Body body = new Body();
body.addAttribute("onload", "collapseDublinCores();");
this.add(body);
Table table = new Table("style","text-align: left; width: 100%;");
table.addAttribute("border", "4");
table.addAttribute("cellpadding", "2");
table.addAttribute("cellspacing", "5");
body.add(table);
Tbody tbody = new Tbody();
table.add(tbody);
table.setTbody(tbody);
TR tr = new TR("id",TITLE_ROW_ID_PREFIX+scenarioTitle);
tr.addAttribute("align","left");
tbody.add(tr);
TD td = new TD("style","background-color: "+COLOR_TITLE0+";");
tr.add(td);
Span span2 = new Span("style","font-weight: bold;");
span2.setData(COLLAPSE+STEM_SCENARIO_STRING+": "+scenarioTitle);
td.add(span2);
// Add the scenario itself. the method adds it to the parent as well.
Table scenarioTable = getNewTable(tbody);
populateTablefromObject(scenarioTable.getTbody(), scenario, SCENARIO_STRING, null, true);
// Add all the Scenario's decorators
addSectionList(scenarioTable.getTbody(), decoratorList, DECORATOR_STRING, true);
// Iterate through the Scenario's sequencer
populateTablefromObject(scenarioTable.getTbody(), sequencer, SEQUENCER_STRING, null, true);
// Iterate through the Scenario's SOLVER
populateTablefromObject(scenarioTable.getTbody(), solver, SOLVER_STRING, null, true);
// DESCEND into the Scenario's parent Model
addModelContents(tbody, parentModel, true);
/*
TR tr2 = new TR();
tbody.add(tr2);
TD td2 = new TD();
tr2.add(td2);
UL ul = new UL();
td2.add(ul);
LI li1 = new LI("modelA");
LI li2 = new LI("modelB");
ul.add(li1);
UL ul2 = new UL();
ul.add(ul2);
ul2.add(li2);
UL ul3 = new UL();
ul2.add(ul3);
LI li2a = new LI("decorator1");
LI li2b = new LI("decorator2");
ul3.add(li2a);
ul3.add(li2b);
LI li3 = new LI("sequencer");
LI li4 = new LI("solver");
ul.add(li3);
ul.add(li4);
*/
this.writeDocument("/test.html",this.getContents());
//System.out.println(doc.getContents());
}// createDocument()
/**
*
* @param tbody
* @param model
* @param top
*/
public void addModelContents(final Tbody tbody, final Model model, boolean top) {
// DESCEND into the Scenario's parent Model
if(model!=null) {
indent++;
// create the model table and add to the parent itself
final Table modelTable = getNewTable(tbody);
populateTablefromObject(modelTable.getTbody(), model, MODEL_STRING, null, true );
final Tbody modelTableBody = modelTable.getTbody();
// The models decorators
final EList<NodeDecorator> nodeDecoratorList = model.getNodeDecorators();
if((nodeDecoratorList!=null)&&(nodeDecoratorList.size()>=1)) {
addSectionList(modelTableBody, nodeDecoratorList, DECORATOR_STRING, true);
}
final EList<EdgeDecorator> edgeDecoratorList = model.getEdgeDecorators();
if((edgeDecoratorList!=null)&&(edgeDecoratorList.size()>=1)) {
addSectionList(modelTableBody, edgeDecoratorList, DECORATOR_STRING, true);
}
final EList<GraphDecorator> graphDecoratorList = model.getGraphDecorators();
if((graphDecoratorList!=null)&&(graphDecoratorList.size()>=1)) {
addSectionList(modelTableBody, graphDecoratorList, DECORATOR_STRING, true);
}
EList<Graph> graphList = model.getGraphs();
if((graphList!=null)&&(graphList.size()>=1)) {
addSectionList(modelTableBody, graphList, MODEL_GRAPH_STRING, true);
}
// Recurse into the model
final EList<Model> modelList = model.getModels();
if((modelList!=null)&&(modelList.size()>=1)&&(modelTableBody!=null)) {
for(int i = 0; i < modelList.size(); i++) {
Model innerModel = modelList.get(i);
addModelContents(tbody, innerModel, false );
}// for all models inside
}
}// model not null
}//addModelContents
/**
*
* @param tbody
* @param eList
* @param type
* @param addDublinCore
*/
public void addSectionList(Tbody tbody, EList<?> eList, String type, boolean addDublinCore) {
if(eList!=null) {
for(int i = 0; i < eList.size(); i ++) {
Object object = eList.get(i);
// should always be true
if(object instanceof EObject) {
populateTablefromObject(tbody, (EObject) object, type, null, addDublinCore);
}
}// for all identifiable
}
}// addSectionList
/**
*
* @param table
* @param eObject
* @param description
* @param name
* @param addDublinCore
*/
private void populateTablefromObject(Tbody tbody, EObject eObject, String description, String name, boolean addDublinCore) {
if(eObject != null) {
// check the name
if((eObject instanceof Identifiable)) {
// IF the name is not forced, look it up
if((name==null)||(name.length()==0)){
Identifiable ident = (Identifiable) eObject;
name = getShortName(ident.getURI().toString());
}
}
String eClass = eObject.eClass().getName();
TR trSpacer = new TR();
tbody.add(trSpacer);
indentTableRow(trSpacer);
String rowId = TITLE_ROW_ID_PREFIX+name;
TR tr = new TR("id",rowId);
tr.addAttribute("class", "idHeader");
indentTableRow(tr);
tbody.add(tr);
//the three HEADER columns
for(int i = 0; i < 3; i ++) {
TD td = new TD();
//td.addAttribute("style", "width: "+CELL_WIDTH[i]+";");
tr.add(td);
//td.addAttribute("style","background-color: "+COLOR_TITLE1+";");
if(i==0) {
A anchor = new A(null,null);
anchor.addAttribute("href", "#");
anchor.addAttribute("onclick", "toggle(this);return false;");
anchor.addAttribute("id", rowId+"_toggle");
anchor.setData(COLLAPSE+description);
td.add(anchor);
//Span span = new Span("style","font-weight: bold;");
//span.setData(COLLAPSE+description);
//td.add(span);
}
if((name == null) ||(name.length()==0)){
name = "name not set";
}
if(i==1){
// Span span = new Span("style","font-weight: bold;");
// span.setData(name);
// td.add(span);
td.setData(name);
}
if(i==2){
// Span span = new Span("style","font-weight: bold;");
// span.setData(eClass);
// td.add(span);
td.setData(eClass);
}
}
EList<EAttribute> attrList = eObject.eClass().getEAllAttributes();
if(attrList!=null){
for(int i = 0; i < attrList.size(); i ++) {
EAttribute feature = attrList.get(i);
if(!feature.isTransient()) {
String attribute = feature.getName();
Object target = eObject.eGet(feature);
if(target !=null) {
String val = target.toString();
if(val.length()>=1) {
// label every data row with a unique ID
String idSuffix = null;
if(eObject instanceof Identifiable) {
Identifiable ident = (Identifiable) eObject;
idSuffix = ident.getURI().toString();
} else {
double r = Math.random();
r *= 1e8;
idSuffix = "id"+((int)r);
}
idSuffix += "_"+attribute;
TR tr2 = new TR("id",DATA_ROW_ID_PREFIX+i+"_"+idSuffix);
tr2.addAttribute("class", "idBody");
//tr2.addAttribute("align","left");
indentTableRow(tr2);
tbody.add(tr2);
TD td1 = new TD("align","left");
tr2.add(td1);
// td1.addAttribute("style", "width: "+CELL_WIDTH[0]+";");
// td1.addAttribute("style","background-color: "+COLOR_DATA+";");
TD td2 = new TD("align","right");
tr2.add(td2);
td2.setData(attribute+": ");
// td2.addAttribute("style", "width: "+CELL_WIDTH[1]+";");
// td2.addAttribute("style","background-color: "+COLOR_DATA+";");
// Span span2 = new Span("style","font-weight: normal;");
// span2.setData(attribute+": ");
// td2.add(span2);
TD td3 = new TD("align","left");
tr2.add(td3);
td3.setData(val);
//td3.addAttribute("style", "width: "+CELL_WIDTH[2]+";");
//td3.addAttribute("style","background-color: "+COLOR_DATA+";");
// Span span3 = new Span("style","font-weight: normal;");
// span3.setData(val);
// td3.add(span3);
}// string length >0
} // target attribute not null
}// not transient?
}// for all attributes
}// attrList
if(addDublinCore) {
Identifiable ident= (Identifiable)eObject;
DublinCore dc = ident.getDublinCore();
if(ident != null) {
addDCtoTable(dc, tbody);
}
}
}// object not null
} // populateTableFromObject
/**
*
* @param dublinCore
* @param tbody
*/
private void addDCtoTable(DublinCore dublinCore, Tbody tbody) {
TR tr = new TR("align","center");
tbody.add(tr);
EList<EStructuralFeature> attrList = dublinCore.eClass().getEStructuralFeatures();
if(attrList!=null){
for(int i = 0; i < attrList.size(); i ++) {
EAttribute attr = (EAttribute)attrList.get(i);
Object obj = dublinCore.eGet(attr);
if(obj != null) {
String val = obj.toString();
if(val.length()>=0) {
// label every dublin core row with a unique ID
String idSuffix = dublinCore.getIdentifier();
if((idSuffix==null)||(idSuffix.length()==0)) {
double r = Math.random();
r *= 1e8;
idSuffix = "id"+((int)r);
}
String rowId = DUBLINCORE_ROW_ID_PREFIX+i+"_"+idSuffix;
TR tr2 = new TR("id",rowId);
//tr2.addAttribute("align","left");
tbody.add(tr2);
// indentation
indentTableRow(tr2);
// col 1
TD td1 = new TD();
td1.addAttribute("style", "width: "+CELL_WIDTH[0]+";");
td1.addAttribute("class", "dcHeader");
//td1.addAttribute("style","background-color: "+COLOR_DUBLINCORE+";");
if(i==0) {
A anchor = new A("href", "#");
anchor.addAttribute("onclick", "toggle(this);return false;");
anchor.setData(EXPAND+DUBLIN_CORE_STRING);
td1.add(anchor);
// Span span1 = new Span("style","font-weight: normal;");
// span1.setData(COLLAPSE+DUBLIN_CORE_STRING);
// td1.add(span1);
}
tr2.add(td1);
// col 2
TD td2 = new TD("align","right");
td2.addAttribute("style", "width: "+CELL_WIDTH[1]+";");
//td2.addAttribute("style","background-color: "+COLOR_DUBLINCORE_DATA+";");
td2.addAttribute("class", "dcBody");
td2.setData(attr.getName()+": ");
tr2.add(td2);
// Span span2 = new Span("style","font-weight: normal;");
// span2.setData(attr.getName()+": ");
// td2.add(span2);
// tr2.add(td2);
// col 3
TD td3 = new TD();
td3.addAttribute("style", "width: "+CELL_WIDTH[2]+";");
td3.addAttribute("class", "dcBody");
//td3.addAttribute("style","background-color: "+COLOR_DUBLINCORE_DATA+";");
td3.setData(val);
tr2.add(td3);
// Span span3 = new Span("style","font-weight: normal;");
// span3.setData(val);
// td3.add(span3);
}
}
}
}
}//addDCtoTable()
/**
* make a new inner table
* @param parentTableBody
* @return a new table
*/
public Table getNewTable(Tbody parentTableBody) {
Table newTable = new Table("style","text-align: left;");
newTable.addAttribute("width", "100%");
newTable.addAttribute("border", "0");
newTable.addAttribute("frame", "box");
newTable.addAttribute("cellpadding", "2");
newTable.addAttribute("cellspacing", "2");
Tbody newTbody = new Tbody();
newTable.add(newTbody);
newTable.setTbody(newTbody);
TR trParent = new TR();
parentTableBody.add(trParent);
TD tdParent = new TD();
trParent.add(tdParent);
tdParent.add(newTable);
// Spacer row
TR trSpacer = new TR();
newTbody.add(trSpacer);
// indent spacer cols
indentTableRow(trSpacer);
// and three cols of data
for(int i = 0; i < 3; i ++) {
// the header line in its' own color
TD td = new TD("style","background-color: "+COLOR_WHITE+";");
td.addAttribute("style", "width: "+CELL_WIDTH[i]+";");
trSpacer.add(td);
}
// fill any remaining space to the right
TD td2 = new TD("style","background-color: "+COLOR_WHITE+";");
trSpacer.add(td2);
return newTable;
}//getNewTable()
/**
*
* @param trSpacer
*/
public void indentTableRow(TR trSpacer) {
// indent spacer cols
for(int i = 0; i < indent; i ++) {
// the header line in its' own color
TD td = new TD();
td.addAttribute("style", "width: "+INDENT_WIDTH+";");
td.addAttribute("class", "blank");
trSpacer.add(td);
}
}// indent table row
/**
*
* @param longName
* @return the short name
*/
public static String getShortName(String longName) {
int idx = longName.lastIndexOf("/");
String name = longName.substring(idx+1, longName.length());
idx = name.indexOf(".");
if(idx >=3) {
name = name.substring(0,idx);
}
if((name==null)||(name.length()==0)) {
name = "Name not set";
}
return name;
}
private String readJsFromFile()
{
return readFromFile("resources/source.js");
}
private String readCssFromFile()
{
return readFromFile("resources/source.css");
}
private String readFromFile(String fileName)
{
StringBuilder data = new StringBuilder();
URL jsData = Activator.getDefault().getBundle().getResource(fileName);
if (jsData != null) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(jsData.openStream()));
char[] buf = new char[1024];
int bytesRead=0;
while((bytesRead=reader.read(buf)) != -1){
data.append(buf, 0, bytesRead);
}
} catch (IOException ioe) {
// don't care
ioe.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
// do nothing
}
}
}
return data.toString();
}
}