package org.openprovenance.prov.dot;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.xml.bind.JAXBException;
import org.openprovenance.prov.model.Element;
import org.openprovenance.prov.model.NamespacePrefixMapper;
import org.openprovenance.prov.model.Activity;
import org.openprovenance.prov.model.Agent;
import org.openprovenance.prov.model.Attribute;
import org.openprovenance.prov.model.Document;
import org.openprovenance.prov.model.Entity;
import org.openprovenance.prov.model.HasOther;
import org.openprovenance.prov.model.HasRole;
import org.openprovenance.prov.model.HasType;
import org.openprovenance.prov.model.HasLabel;
import org.openprovenance.prov.model.HasValue;
import org.openprovenance.prov.model.LangString;
import org.openprovenance.prov.model.Identifiable;
import org.openprovenance.prov.model.Bundle;
import org.openprovenance.prov.model.Other;
import org.openprovenance.prov.model.QualifiedName;
import org.openprovenance.prov.model.QualifiedRelation;
import org.openprovenance.prov.model.Relation;
import org.openprovenance.prov.model.Role;
import org.openprovenance.prov.model.Type;
import org.openprovenance.prov.model.ActedOnBehalfOf;
import org.openprovenance.prov.model.AlternateOf;
import org.openprovenance.prov.model.DerivedByInsertionFrom;
import org.openprovenance.prov.model.Value;
import org.openprovenance.prov.xml.ProvDeserialiser;
import org.openprovenance.prov.xml.ProvFactory;
import org.openprovenance.prov.model.ProvUtilities;
import org.openprovenance.prov.model.SpecializationOf;
import org.openprovenance.prov.model.Used;
import org.openprovenance.prov.model.WasAssociatedWith;
import org.openprovenance.prov.model.WasAttributedTo;
import org.openprovenance.prov.model.WasDerivedFrom;
import org.openprovenance.prov.model.WasEndedBy;
import org.openprovenance.prov.model.WasGeneratedBy;
import org.openprovenance.prov.model.WasInfluencedBy;
import org.openprovenance.prov.model.WasInformedBy;
import org.openprovenance.prov.model.WasInvalidatedBy;
import org.openprovenance.prov.model.WasStartedBy;
/** Serialisation of Prov representation to DOT format. */
public class ProvToDot {
public final static String DEFAULT_CONFIGURATION_FILE="defaultConfig.xml";
public final static String DEFAULT_CONFIGURATION_FILE_WITH_ROLE="defaultConfigWithRole.xml";
public final static String DEFAULT_CONFIGURATION_FILE_WITH_ROLE_NO_LABEL="defaultConfigWithRoleNoLabel.xml";
public final static String USAGE="prov2dot provFile.xml out.dot out.pdf [configuration.xml]";
public int MAX_TOOLTIP_LENGTH = 2000;
ProvUtilities u=new ProvUtilities();
ProvFactory pf=new ProvFactory();
QualifiedName SUM_SIZE=pf.newQualifiedName(NamespacePrefixMapper.SUMMARY_NS, "size", NamespacePrefixMapper.SUMMARY_PREFIX);
public String qualifiedNameToString(QualifiedName qName) {
return qName.getNamespaceURI()+qName.getLocalPart();
}
public String localnameToString(QualifiedName qName) {
//return qName.getLocalPart();
return nonEmptyLocalName(qName);
}
public enum Config { DEFAULT, ROLE, ROLE_NO_LABEL };
public static void main(String [] args) throws Exception {
if ((args==null) || (args.length==0) || (args.length>4)) {
System.out.println(USAGE);
return;
}
String opmFile=args[0];
String outDot=args[1];
String outPdf=args[2];
String configFile=((args.length==4) ? args[3] : null);
ProvToDot converter=((configFile==null) ? new ProvToDot() : new ProvToDot(configFile));
converter.convert(opmFile,outDot,outPdf,null);
}
public ProvToDot() {
InputStream is=this.getClass().getClassLoader().getResourceAsStream(DEFAULT_CONFIGURATION_FILE);
init(is);
}
public ProvToDot(boolean withRoleFlag) {
InputStream is;
if (withRoleFlag) {
is=this.getClass().getClassLoader().getResourceAsStream(DEFAULT_CONFIGURATION_FILE_WITH_ROLE);
} else {
is=this.getClass().getClassLoader().getResourceAsStream(DEFAULT_CONFIGURATION_FILE);
}
init(is);
}
public ProvToDot(Config config) {
InputStream is=null;
switch (config) {
case DEFAULT:
System.out.println("ProvToDot DEFAULT");
is=this.getClass().getClassLoader().getResourceAsStream(DEFAULT_CONFIGURATION_FILE);
break;
case ROLE:
System.out.println("ProvToDot role");
is=this.getClass().getClassLoader().getResourceAsStream(DEFAULT_CONFIGURATION_FILE_WITH_ROLE);
break;
case ROLE_NO_LABEL:
//System.out.println("ProvToDot role no label");
default:
//System.out.println("ProvToDot role no label (by default)");
is=this.getClass().getClassLoader().getResourceAsStream(DEFAULT_CONFIGURATION_FILE_WITH_ROLE_NO_LABEL);
break;
}
init(is);
}
public ProvToDot(String configurationFile) {
this();
init(configurationFile);
}
public ProvToDot(String configurationFile, String other) {
InputStream is=this.getClass().getClassLoader().getResourceAsStream(configurationFile);
init(is);
}
public ProvPrinterConfigDeserialiser getDeserialiser() {
return ProvPrinterConfigDeserialiser.getThreadProvPrinterConfigDeserialiser();
}
public void init(String configurationFile) {
ProvPrinterConfigDeserialiser printerDeserial=getDeserialiser();
try {
ProvPrinterConfiguration opc=printerDeserial.deserialiseProvPrinterConfiguration(new File(configurationFile));
init(opc);
} catch (JAXBException je) {
je.printStackTrace();
}
}
public void init(InputStream is) {
ProvPrinterConfigDeserialiser printerDeserial=getDeserialiser();
try {
ProvPrinterConfiguration opc=printerDeserial.deserialiseProvPrinterConfiguration(is);
init(opc);
} catch (JAXBException je) {
je.printStackTrace();
}
}
public void init(ProvPrinterConfiguration configuration) {
if (configuration==null) return;
if (configuration.getRelations()!=null) {
if (configuration.getRelations().getDefault()!=null) {
defaultRelationStyle=configuration.getRelations().getDefault();
}
for (RelationStyleMapEntry edge: configuration.getRelations().getRelation()) {
edgeStyleMap.put(edge.getType(),edge);
}
}
if (configuration.getActivities()!=null) {
if (configuration.getActivities().isDisplayValue()!=null) {
this.displayActivityValue=configuration.getActivities().isDisplayValue();
}
if (configuration.getActivities().isColoredAsAccount()!=null) {
this.displayActivityColor=configuration.getActivities().isColoredAsAccount();
}
for (ActivityMapEntry process: configuration.getActivities().getActivity()) {
processNameMap.put(process.getValue(),process.getDisplay());
}
}
if (configuration.getEntities()!=null) {
if (configuration.getEntities().isDisplayValue()!=null) {
this.displayEntityValue=configuration.getEntities().isDisplayValue();
}
if (configuration.getEntities().isColoredAsAccount()!=null) {
this.displayEntityColor=configuration.getEntities().isColoredAsAccount();
}
for (EntityMapEntry artifact: configuration.getEntities().getEntity()) {
artifactNameMap.put(artifact.getValue(),artifact.getDisplay());
}
}
if (configuration.getAgents()!=null) {
if (configuration.getAgents().isDisplayValue()!=null) {
this.displayAgentValue=configuration.getAgents().isDisplayValue();
}
if (configuration.getAgents().isColoredAsAccount()!=null) {
this.displayAgentColor=configuration.getAgents().isColoredAsAccount();
}
for (AgentMapEntry agent: configuration.getAgents().getAgent()) {
agentNameMap.put(agent.getValue(),agent.getDisplay());
}
}
if (configuration.getAccounts()!=null) {
if (configuration.getAccounts().getDefaultAccount()!=null) {
this.defaultAccountLabel=configuration.getAccounts().getDefaultAccount();
}
if (configuration.getAccounts().getDefaultColor()!=null) {
this.defaultAccountColor=configuration.getAccounts().getDefaultColor();
}
for (AccountColorMapEntry account: configuration.getAccounts().getAccount()) {
accountColourMap.put(account.getName(),account.getColor());
}
}
if (configuration.getGraphName()!=null) {
this.name=configuration.getGraphName();
}
}
public void convert(String opmFile, String dotFile, String pdfFile, String title)
throws java.io.FileNotFoundException, java.io.IOException, JAXBException {
convert (ProvDeserialiser.getThreadProvDeserialiser().deserialiseDocument(new File(opmFile)),dotFile,pdfFile,title);
}
public void convert(Document graph, String dotFile, String pdfFile, String title)
throws java.io.FileNotFoundException, java.io.IOException {
convert(graph,new File(dotFile), title);
Runtime runtime = Runtime.getRuntime();
@SuppressWarnings("unused")
java.lang.Process proc = runtime.exec("dot -o " + pdfFile + " -Tpdf " + dotFile);
}
public void convert(Document graph, String dotFile, OutputStream pdfStream, String title)
throws java.io.FileNotFoundException, java.io.IOException {
convert(graph,new File(dotFile), title);
Runtime runtime = Runtime.getRuntime();
java.lang.Process proc = runtime.exec("dot -Tpdf " + dotFile);
InputStream is=proc.getInputStream();
org.apache.commons.io.IOUtils.copy(is, pdfStream);
}
public void convert(Document graph, String dotFile, String title)
throws java.io.FileNotFoundException, java.io.IOException {
convert(graph,new File(dotFile),title);
}
public void convert(Document graph, String dotFile, String aFile, String type, String title)
throws java.io.FileNotFoundException, java.io.IOException {
convert(graph,new File(dotFile),title);
Runtime runtime = Runtime.getRuntime();
java.lang.Process proc = runtime.exec("dot -o " + aFile + " -T" + type + " " + dotFile);
try {
BufferedReader errorReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
String s_error=errorReader.readLine();
if (s_error!=null) {
System.out.println("Error: " + s_error);
}
proc.waitFor();
//System.err.println("exit value " + proc.exitValue());
} catch (InterruptedException e){};
}
public void convert(Document graph, String dotFile, OutputStream os, String type, String title)
throws java.io.FileNotFoundException, java.io.IOException {
convert(graph,new File(dotFile),title);
Runtime runtime = Runtime.getRuntime();
java.lang.Process proc = runtime.exec("dot -T" + type + " " + dotFile);
InputStream is=proc.getInputStream();
org.apache.commons.io.IOUtils.copy(is, os);
}
public void convert(Document graph, File file, String title) throws java.io.FileNotFoundException{
OutputStream os=new FileOutputStream(file);
convert(graph, new PrintStream(os), title);
}
public void convert(Document graph, OutputStream os, String title) {
convert(graph, new PrintStream(os), title);
}
public void convert(Document doc, PrintStream out, String title) {
if (title!=null) name=title;
List<Relation> edges=u.getRelations(doc);
prelude(doc, out);
if (u.getActivity(doc)!=null) {
for (Activity p: u.getActivity(doc)) {
emitActivity(p,out);
}
}
if (u.getEntity(doc)!=null) {
for (Entity p: u.getEntity(doc)) {
emitEntity(p,out);
}
}
if (u.getAgent(doc)!=null) {
for (Agent p: u.getAgent(doc)) {
emitAgent(p,out);
}
}
if (u.getBundle(doc)!=null) {
for (Bundle bun: u.getBundle(doc)) {
convert(bun,out);
}
}
for (Relation e: edges) {
emitDependency(e,out);
}
postlude(doc, out);
}
public void convert(Bundle bun, PrintStream out) {
List<Relation> edges=u.getRelations(bun);
prelude(bun, out);
if (u.getActivity(bun)!=null) {
for (Activity p: u.getActivity(bun)) {
emitActivity(p,out);
}
}
if (u.getEntity(bun)!=null) {
for (Entity p: u.getEntity(bun)) {
emitEntity(p,out);
}
}
if (u.getAgent(bun)!=null) {
for (Agent p: u.getAgent(bun)) {
emitAgent(p,out);
}
}
for (Relation e: edges) {
emitDependency(e,out);
}
postlude(bun, out);
}
boolean collapseAnnotations=true;
static int embeddedAnnotationCounter=0;
public void emitAnnotations(HasOther node, PrintStream out) {
}
//////////////////////////////////////////////////////////////////////
///
/// ELEMENTS
///
//////////////////////////////////////////////////////////////////////
public void emitActivity(Activity p, PrintStream out) {
HashMap<String,String> properties=new HashMap<String, String>();
emitElement(p.getId(),
addURL(p.getId(), addActivityShape(p,addActivityLabel(p, addActivityColor(p,properties)))),
out);
emitAnnotations("", p,out);
}
public void emitEntity(Entity a, PrintStream out) {
HashMap<String,String> properties=new HashMap<String, String>();
emitElement(a.getId(),
addURL(a.getId(), addEntityShape(a,addEntityLabel(a, addEntityColor(a,properties)))),
out);
emitAnnotations("", a,out);
}
public void emitAgent(Agent ag, PrintStream out) {
HashMap<String,String> properties=new HashMap<String, String>();
emitElement(ag.getId(),
addURL(ag.getId(), addAgentShape(ag,addAgentLabel(ag, addAgentColor(ag,properties)))),
out);
emitAnnotations("", ag,out);
}
public void emitAnnotations(String id, HasOther statement, PrintStream out) {
if (((statement.getOther()==null)
|| (statement.getOther().isEmpty())
|| (countOthers(statement)==0))
&&
(((HasType)statement).getType().isEmpty())
&&
(! (statement instanceof HasValue) || ((HasValue)statement).getValue()==null)
&&
(! (statement instanceof HasRole) || ((HasRole)statement).getRole().isEmpty())
&&
(((HasLabel)statement).getLabel().isEmpty())
) return;
HashMap<String,String> properties=new HashMap<String, String>();
QualifiedName newId=annotationId(((Identifiable)statement).getId(),id);
emitElement(newId,
addAnnotationShape(statement,addAnnotationColor(statement,addAnnotationLabel(statement,properties))),
out);
HashMap<String,String> linkProperties=new HashMap<String, String>();
emitRelation(qualifiedNameToString(newId),
qualifiedNameToString(((Identifiable)statement).getId()),
addAnnotationLinkProperties(statement,linkProperties),out,true);
}
int annotationCount=0;
@SuppressWarnings("unused")
public QualifiedName annotationId(QualifiedName id,String node) {
if (true || id==null) {
return pf.newQualifiedName("-","attrs" + node + (annotationCount++),null);
} else {
return id;
}
}
public HashMap<String, String> addURL(QualifiedName id,
HashMap<String, String> properties) {
if (id!=null) properties.put("URL", id.getNamespaceURI()+id.getLocalPart());
return properties;
}
public HashMap<String,String> addAnnotationLinkProperties(HasOther ann, HashMap<String,String> properties) {
properties.put("arrowhead","none");
properties.put("style","dashed");
properties.put("color","gray");
return properties;
}
public HashMap<String,String> addActivityShape(Activity p, HashMap<String,String> properties) {
properties.put("shape","polygon");
properties.put("sides","4");
return properties;
}
public HashMap<String,String> addBlankNodeShape(HashMap<String,String> properties) {
properties.put("shape","point");
properties.put("label","");
return properties;
}
public HashMap<String,String> addActivityLabel(Activity p, HashMap<String,String> properties) {
properties.put("label",activityLabel(p) + displaySize(p));
return properties;
}
public HashMap<String,String> addActivityColor(Activity p, HashMap<String,String> properties) {
if (displayActivityColor) {
properties.put("color",processColor(p));
properties.put("fontcolor",processColor(p));
} else {
properties.put("fillcolor","#9FB1FC"); //blue
properties.put("color","#0000FF"); //blue
properties.put("style", "filled");
}
addColors(p,properties);
return properties;
}
public HashMap<String,String> addColors(HasOther object, HashMap<String,String> properties) {
Hashtable<String,List<Other>> table=u.attributesWithNamespace(object,NamespacePrefixMapper.DOT_NS);
List<Other> o=table.get("fillcolor");
if (o!=null && !o.isEmpty()) {
properties.put("fillcolor", o.get(0).getValue().toString());
properties.put("style", "filled");
}
o=table.get("color");
if (o!=null && !o.isEmpty()) {
properties.put("color", o.get(0).getValue().toString());
}
o=table.get("url");
if (o!=null && !o.isEmpty()) {
properties.put("URL", o.get(0).getValue().toString());
}
o=table.get("size");
if (o!=null && !o.isEmpty()) {
if ((object instanceof QualifiedRelation)) {
String val=o.get(0).getValue().toString();
properties.put("penwidth", val);
} else {
if (object instanceof Element) {
properties.put("width", "" + Double.valueOf(o.get(0).getValue().toString()) * 0.75);
}
}
}
o=table.get("tooltip");
if (o!=null && !o.isEmpty()) {
String val=o.get(0).getValue().toString();
if (val.length()>MAX_TOOLTIP_LENGTH) {
val=val.substring(0,Math.min(val.length(), MAX_TOOLTIP_LENGTH))+" ...";
}
properties.put("tooltip", val);
}
return properties;
}
public HashMap<String,String> addEntityShape(Entity p, HashMap<String,String> properties) {
// default is good for entity
List<Type> types=p.getType();
for (Type type: types) {
if (type.getValue() instanceof QualifiedName) {
QualifiedName name=(QualifiedName) type.getValue();
if (("Dictionary".equals(name.getLocalPart()))
||
("EmptyDictionary".equals(name.getLocalPart()))) {
properties.put("shape","folder");
}
}
}
return properties;
}
public HashMap<String,String> addEntityColor(Entity a, HashMap<String,String> properties) {
if (displayEntityColor) {
properties.put("color",entityColor(a));
properties.put("fontcolor",entityColor(a));
} else {
properties.put("fillcolor","#FFFC87");//yellow
properties.put("color","#808080"); //gray
properties.put("style", "filled");
}
addColors(a,properties);
return properties;
}
public HashMap<String,String> addEntityLabel(Entity p, HashMap<String,String> properties) {
properties.put("label",entityLabel(p) + displaySize(p));
return properties;
}
public String displaySize(HasOther p) {
for (Other o: p.getOther()) {
if (SUM_SIZE.equals(o.getElementName())) {
return " (" + o.getConvertedValue() + ")";
}
}
return "";
}
public HashMap<String,String> addAgentShape(Agent p, HashMap<String,String> properties) {
properties.put("shape","house");
//properties.put("sides","8");
return properties;
}
public HashMap<String,String> addAgentLabel(Agent p, HashMap<String,String> properties) {
properties.put("label",agentLabel(p) + displaySize(p));
return properties;
}
public HashMap<String,String> addAgentColor(Agent a, HashMap<String,String> properties) {
if (displayAgentColor) {
properties.put("color",agentColor(a));
properties.put("fontcolor",agentColor(a));
} else {
properties.put("fillcolor","#FDB266"); //orange
properties.put("style", "filled");
}
addColors(a,properties);
return properties;
}
public HashMap<String,String> addAnnotationShape(HasOther ann, HashMap<String,String> properties) {
properties.put("shape","note");
return properties;
}
public HashMap<String,String> addAnnotationLabel(HasOther ann, HashMap<String,String> properties) {
String label="";
label=label+"<<TABLE cellpadding=\"0\" border=\"0\">\n";
for (Type type: ((HasType)ann).getType()) {
label=label+" <TR>\n";
label=label+" <TD align=\"left\">" + "type" + ":</TD>\n";
label=label+" <TD align=\"left\">" + getPropertyValueWithUrl(type) + "</TD>\n"; //FIXME: could we have URL in <a></a>?
label=label+" </TR>\n";
}
for (LangString lab: ((HasLabel)ann).getLabel()) {
label=label+" <TR>\n";
label=label+" <TD align=\"left\">" + "label" + ":</TD>\n";
label=label+" <TD align=\"left\">" + htmlify(lab.getValue()) + "</TD>\n";
label=label+" </TR>\n";
}
if (ann instanceof HasValue) {
Value val=((HasValue)ann).getValue();
if (val!=null) {
label=label+" <TR>\n";
label=label+" <TD align=\"left\">" + "value" + ":</TD>\n";
label=label+" <TD align=\"left\">" + getPropertyValueWithUrl(val) + "</TD>\n";
label=label+" </TR>\n";
}
}
if (ann instanceof HasRole) {
for (Role role: ((HasRole)ann).getRole()) {
label=label+" <TR>\n";
label=label+" <TD align=\"left\">" + "role" + ":</TD>\n";
label=label+" <TD align=\"left\">" + getPropertyValueWithUrl(role) + "</TD>\n";
label=label+" </TR>\n";
}
}
for (Other prop: ann.getOther()) {
if (prop.getElementName().getNamespaceURI().startsWith(NamespacePrefixMapper.SHARED_PROV_TOOLBOX_PREFIX)) {
// no need to display this attribute
continue;
}
/*
if ("fillcolor".equals(prop.getElementName().getLocalPart())) {
// no need to display this attribute
continue;
}
if ("size".equals(prop.getElementName().getLocalPart())) {
// no need to display this attribute
continue;
}
if ("tooltip".equals(prop.getElementName().getLocalPart())) {
// no need to display this attribute
continue;
}
*/
label=label+" <TR>\n";
label=label+" <TD align=\"left\">" + convertProperty((Attribute)prop) + ":</TD>\n";
label=label+" <TD align=\"left\">" + getPropertyValueWithUrl((Attribute)prop) + "</TD>\n";
label=label+" </TR>\n";
}
label=label+" </TABLE>>\n";
properties.put("label",label);
properties.put("fontsize","10");
return properties;
}
public int countOthers(HasOther ann) {
int count=0;
for (Other obj: ann.getOther()) {
if (!(obj.getElementName().getNamespaceURI().startsWith(NamespacePrefixMapper.SHARED_PROV_TOOLBOX_PREFIX))) {
count++;
}
}
return count;
}
public String convertValue(Attribute v) {
if (v.getValue() instanceof QualifiedName) {
QualifiedName name=(QualifiedName) v.getValue();
return htmlify(nonEmptyLocalName(name));
}
String label=getPropertyValueFromAny(v);
int i=label.lastIndexOf("#");
int j=label.lastIndexOf("/");
return htmlify(label.substring(Math.max(i,j)+1, label.length()));
}
public String nonEmptyLocalName(QualifiedName name) {
final String localPart = name.getLocalPart();
if ("".equals(localPart)) {
// we are in this case for url finishing with /
String uri=name.getNamespaceURI();
String label=uri.substring(0, uri.length()-1);
int i=label.lastIndexOf("#");
int j=label.lastIndexOf("/");
return uri.substring(Math.max(i,j)+1, uri.length());
} else {
return localPart;
}
}
public String convertProperty(Attribute oLabel) {
String label=getPropertyFromAny(oLabel);
int i=label.lastIndexOf("#");
int j=label.lastIndexOf("/");
return label.substring(Math.max(i,j)+1, label.length());
}
public String getPropertyFromAny (Attribute o) {
return o.getElementName().getUri();
}
public String getPropertyValueFromAny (Type t) {
Object val=t.getValue();
if (val instanceof QualifiedName) {
QualifiedName q=(QualifiedName)val;
return q.getNamespaceURI() + q.getLocalPart();
} else {
return "" + val;
}
}
public String getPropertyValueWithUrl (Attribute t) {
Object val=t.getValue();
if (val instanceof QualifiedName) {
QualifiedName q=(QualifiedName)val;
return q.getPrefix() + ":" + q.getLocalPart();
//return "<a xlink:href='" + q.getNamespaceURI() + q.getLocalPart() + "'>" + q.getLocalPart() + "</a>";
//return "<a href=\"" + q.getPrefix() + ":" + q.getLocalPart() + "\">" + q.getLocalPart() + "</a>";
} else {
return htmlify(""+val);
}
}
public String getPropertyValueFromAny (Attribute o) {
Object val=o.getValue();
if (val instanceof QualifiedName) {
QualifiedName q=(QualifiedName)val;
return q.getNamespaceURI() + q.getLocalPart();
} else {
return "" + val;
}
}
public HashMap<String,String> addAnnotationColor(HasOther ann, HashMap<String,String> properties) {
if (displayAnnotationColor) {
properties.put("color",annotationColor(ann));
properties.put("fontcolor","black");
//properties.put("style","filled");
}
return properties;
}
boolean displayActivityValue=false;
boolean displayActivityColor=false;
boolean displayEntityValue=false;
boolean displayEntityColor=false;
boolean displayAgentColor=false;
boolean displayAgentValue=false;
boolean displayAnnotationColor=true;
public String activityLabel(Activity p) {
if (displayActivityValue) {
return convertActivityName(""+pf.getLabel(p));
} else {
return localnameToString(p.getId());
}
}
public String processColor(Activity p) {
// Note, I should compute effective account membership
List<String> colors=new LinkedList<String>();
// for (AccountRef acc: p.getAccount()) {
// String accountLabel=((Account)acc.getRef()).getId();
// String colour=convertAccount(accountLabel);
// colors.add(colour);
// }
return selectColor(colors);
}
// returns the first non transparent color
public String selectColor(List<String> colors) {
String tr="transparent";
for (String c: colors) {
if (!(c.equals(tr))) return c;
}
return tr;
}
public String entityLabel(Entity p) {
if (displayEntityValue) {
return convertEntityName(""+pf.getLabel(p));
} else {
return localnameToString(p.getId());
}
}
public String entityColor(Entity p) {
// Note, I should compute effective account membership
List<String> colors=new LinkedList<String>();
// for (AccountRef acc: p.getAccount()) {
// String accountLabel=((Account)acc.getRef()).getId();
// String colour=convertAccount(accountLabel);
// colors.add(colour);
// }
return selectColor(colors);
}
public String agentColor(Agent p) {
// Note, I should compute effective account membership
List<String> colors=new LinkedList<String>();
// for (AccountRef acc: p.getAccount()) {
// String accountLabel=((Account)acc.getRef()).getId();
// String colour=convertAccount(accountLabel);
// colors.add(colour);
// }
return selectColor(colors);
}
public String annotationColor(HasOther ann) {
List<String> colors=new LinkedList<String>();
colors.add("gray");
return selectColor(colors);
}
public String agentLabel(Agent p) {
if (displayAgentValue) {
return convertAgentName(""+pf.getLabel(p));
} else {
return localnameToString(p.getId());
}
}
HashMap<String,String> processNameMap=new HashMap<String,String>();
public String convertActivityName(String process) {
String name=processNameMap.get(process);
if (name!=null) return name;
return process;
}
HashMap<String,String> artifactNameMap=new HashMap<String,String>();
public String convertEntityName(String artifact) {
String name=artifactNameMap.get(artifact);
if (name!=null) return name;
return artifact;
}
HashMap<String,String> agentNameMap=new HashMap<String,String>();
public String convertAgentName(String agent) {
String name=agentNameMap.get(agent);
if (name!=null) return name;
return agent;
}
int bncounter=0;
//////////////////////////////////////////////////////////////////////
///
/// EDGES
///
//////////////////////////////////////////////////////////////////////
public void emitDependency(Relation e, PrintStream out) {
HashMap<String,String> properties=new HashMap<String, String>();
List<QualifiedName> others=u.getOtherCauses(e);
if (others !=null) { // n-ary case
String bnid="bn" + (bncounter++);
emitBlankNode(dotify(bnid), addBlankNodeShape(properties), out);
HashMap<String,String> properties2=new HashMap<String, String>();
properties2.put("arrowhead","none");
String arrowTail=getArrowShapeForRelation(e);
if (arrowTail!=null) {
properties2.put("arrowtail",arrowTail);
properties2.put("dir","back");
}
if (e instanceof HasOther) {
addColors((HasOther)e,properties2);
}
HashMap<String,String> properties3=new HashMap<String, String>();
QualifiedName effect=u.getEffect(e);
if (effect!=null) {
emitRelation( qualifiedNameToString(effect),
bnid,
properties2,
out,
true);
}
relationName(e, properties3);
if (e instanceof HasOther) {
addColors((HasOther)e,properties3);
}
if (e instanceof DerivedByInsertionFrom) {
properties3.put("arrowhead","onormal");
}
if (u.getCause(e)!=null) {
emitRelation( bnid,
qualifiedNameToString(u.getCause(e)),
properties3,
out,
true);
}
HashMap<String,String> properties4=new HashMap<String, String>();
if (e instanceof HasOther) {
addColors((HasOther)e,properties4);
}
for (QualifiedName other: others) {
if (other!=null) {
emitRelation( bnid,
qualifiedNameToString(other),
properties4,
out,
true);
}
}
} else { // binary case
if (u.getCause(e)!=null) { // make sure there is a cuase
relationName(e, properties);
if (e instanceof QualifiedRelation) {
addColors((QualifiedRelation)e,properties);
}
String arrowTail=getArrowShapeForRelation(e);
if (arrowTail!=null) {
properties.put("arrowtail",arrowTail);
properties.put("dir","both");
}
QualifiedName effect=u.getEffect(e);
QualifiedName cause=u.getCause(e);
if (effect!=null && cause!=null) {
emitRelation( qualifiedNameToString(effect),
qualifiedNameToString(cause),
properties,
out,
true);
}
}
}
}
void relationName(Relation e, HashMap<String,String> properties) {
String l=getShortLabelForRelation(e);
if (l!=null) {
properties.put("taillabel",l);
properties.put("labelangle", "60.0");
properties.put("labeldistance", "1.5");
properties.put("rotation", "20");
properties.put("labelfontsize", "8");
}
}
String getArrowShapeForRelation(Relation e) {
if (e instanceof WasStartedBy) return "oinv";
if (e instanceof WasEndedBy) return "odiamond";
if (e instanceof WasInvalidatedBy) return "odiamond";
return null;
}
String getLabelForRelation(Relation e) {
if (e instanceof Used) return "used";
if (e instanceof WasGeneratedBy) return "wasGeneratedBy";
if (e instanceof WasDerivedFrom) return "wasDerivedFrom";
if (e instanceof WasStartedBy) return "wasStartedBy";
if (e instanceof WasEndedBy) return "wasEndedBy";
if (e instanceof WasInvalidatedBy) return "wasInvalidatedBy";
if (e instanceof WasInformedBy) return "wasInformedBy";
if (e instanceof WasAssociatedWith) return "wasAssociatedWith";
if (e instanceof WasAttributedTo) return "wasAttributedTo";
if (e instanceof WasInfluencedBy) return "wasInfluencedBy";
if (e instanceof ActedOnBehalfOf) return "actedOnBehalfOf";
if (e instanceof SpecializationOf) return "specializationOf";
if (e instanceof AlternateOf) return "alternateOf";
return null;
}
String getShortLabelForRelation(Relation e) {
if (e instanceof Used) return "use";
if (e instanceof WasGeneratedBy) return "gen";
if (e instanceof WasDerivedFrom) return "der";
if (e instanceof WasStartedBy) return "start";
if (e instanceof WasEndedBy) return "end";
if (e instanceof WasInvalidatedBy) return "inv";
if (e instanceof WasInformedBy) return "inf";
if (e instanceof WasAssociatedWith) return "assoc";
if (e instanceof WasAttributedTo) return "att";
if (e instanceof WasInfluencedBy) return "inf";
if (e instanceof ActedOnBehalfOf) return "del";
if (e instanceof SpecializationOf) return "spe";
if (e instanceof AlternateOf) return "alt";
return null;
}
public HashMap<String,String> addRelationAttributes(String accountLabel,
Relation e,
HashMap<String,String> properties) {
String colour=convertAccount(accountLabel);
properties.put("color",colour);
properties.put("fontcolor",colour);
properties.put("style",getRelationStyle(e));
addRelationLabel(e,properties);
return properties;
}
/* Displays type if any, role otherwise. */
public void addRelationLabel(Relation e0, HashMap<String,String> properties) {
String label=null;
if (!(e0 instanceof QualifiedRelation)) return;
QualifiedRelation e=(QualifiedRelation)e0;
List<Type> type=pf.getType(e);
if ((type!=null) && (!type.isEmpty())) {
label=type.get(0).getValue().toString();
} else if (getRelationPrintRole(e)) {
String role=pf.getRole(e);
if (role!=null) {
label=displayRole(role);
properties.put("fontsize","8");
}
}
if (label!=null) {
properties.put("label",convertRelationLabel(label));
if (properties.get("fontsize")==null) {
properties.put("fontsize","10");
}
}
}
public String displayRole(String role) {
return "(" + role + ")";
}
public String convertRelationLabel(String label) {
return label.substring(label.indexOf("#")+1, label.length());
}
HashMap<String,String> accountColourMap=new HashMap<String,String>();
public String convertAccount(String account) {
String colour=accountColourMap.get(account);
if (colour!=null) return colour;
return defaultAccountColor;
}
String defaultRelationStyle;
HashMap<String,RelationStyleMapEntry> edgeStyleMap=new HashMap<String,RelationStyleMapEntry>();
public String getRelationStyle(Relation edge) {
String name=edge.getClass().getName();
RelationStyleMapEntry style=edgeStyleMap.get(name);
if (style!=null) return style.getStyle();
return defaultRelationStyle;
}
public boolean getRelationPrintRole(Relation edge) {
String name=edge.getClass().getName();
RelationStyleMapEntry style=edgeStyleMap.get(name);
if (style!=null) {
Boolean flag=style.isPrintRole();
if (flag==null) return false;
return flag;
} else {
return false;
}
}
//////////////////////////////////////////////////////////////////////
///
/// DOT FORMAT GENERATION
///
//////////////////////////////////////////////////////////////////////
String name;
String defaultAccountLabel;
String defaultAccountColor;
private String layout;
/* make name compatible with dot notation*/
public String OLDdotify(String name) {
return "n" + name.replace('-','_').replace('.','_').replace('/','_').replace(':','_').replace('#','_').replace('~','_').replace('&','_').replace('=','_').replace('?','_');
}
public String dotify(String name) {
//return name.replace('-','_').replace('.','_').replace('/','_').replace(':','_').replace('#','_').replace('~','_').replace("&","&").replace('=','_').replace('?','_');
//return htmlify(name);
return "\"" + name + "\"";
}
public String htmlify(String name) {
return name.replace("&","&")
.replace("<","<")
.replace(">",">");
}
public void emitElement(QualifiedName name, HashMap<String,String> properties, PrintStream out) {
StringBuffer sb=new StringBuffer();
sb.append(""+dotify(qualifiedNameToString(name)));
emitProperties(sb,properties);
out.println(sb.toString());
}
public void emitBlankNode(String bnid, HashMap<String,String> properties, PrintStream out) {
StringBuffer sb=new StringBuffer();
sb.append(bnid);
emitProperties(sb,properties);
out.println(sb.toString());
}
public void emitRelation(String src, String dest, HashMap<String,String> properties, PrintStream out, boolean directional) {
StringBuffer sb=new StringBuffer();
sb.append(dotify(src));
if (directional) {
sb.append(" -> ");
} else {
sb.append(" -- ");
}
sb.append(dotify(dest));
emitProperties(sb,properties);
out.println(sb.toString());
}
public void emitProperties(StringBuffer sb,HashMap<String,String> properties) {
sb.append(" [");
boolean first=true;
for (String key: properties.keySet()) {
if (first) {
first=false;
} else {
sb.append(",");
}
String value=properties.get(key);
sb.append(key);
if (value.startsWith("<")) {
sb.append("=");
sb.append(value);
} else {
sb.append("=\"");
sb.append(value);
sb.append("\"");
}
}
sb.append("]");
}
void prelude(Document doc, PrintStream out) {
out.println("digraph \"" + name + "\" { size=\"16,12\"; rankdir=\"BT\"; ");
if (layout!=null) {
out.println("layout=\"" + layout + "\"; ");
}
}
void postlude(Document doc, PrintStream out) {
out.println("}");
out.close();
}
void prelude(Bundle doc, PrintStream out) {
out.println("subgraph " + dotify("cluster" + qualifiedNameToString(doc.getId())) + " { ");
out.println(" label=\"" + localnameToString(doc.getId()) + "\";");
out.println(" URL=\"" + qualifiedNameToString(doc.getId()) + "\";");
}
void postlude(Bundle doc, PrintStream out) {
out.println("}");
}
public void setLayout(String layout) {
this.layout=layout;
}
}