com.articulate.sigma.Graph Maven / Gradle / Ivy
Show all versions of sigma-component Show documentation
package com.articulate.sigma;
/** This code is copyright Articulate Software (c) 2003. Some portions
copyright Teknowledge (c) 2003 and reused under the terms of the GNU license.
This software is released under the GNU Public License .
Users of this code also consent, by use of this code, to credit Articulate Software
and Teknowledge in any writings, briefings, publications, presentations, or
other representations of any software which incorporates, builds on, or uses this
code. Please cite the following article in any publication with references:
Pease, A., (2003). The Sigma Ontology Development Environment,
in Working Notes of the IJCAI-2003 Workshop on Ontology and Distributed Systems,
August 9, Acapulco, Mexico.
*/
import java.awt.image.RenderedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeMap;
import javax.imageio.ImageIO;
import com.articulate.sigma.KB;
/** Handle operations for creating a graphical representation of partial
* ordering relations. Supports Graph.jsp. */
public class Graph {
// a limit counter to prevent pathologically large graphs
private int graphsize = 0;
// A map of the fields to display in the graph in addition to the
// indented term name with option names as keys and "yes", "no" as values.
public TreeMap columnList = new TreeMap();
/** *************************************************************
*/
public Graph() {
columnList.put("documentation","yes");
columnList.put("direct-children","yes");
columnList.put("graph","yes");
}
/** *************************************************************
* @return in a String a count of the number of "children" which consists of
* instance, subclass, subrelation and subAttribute links.
*/
private String generateChildrenColumn(KB kb, String term) {
// probably should find all instances of PartialOrderingRelation
ArrayList relations = new ArrayList();
relations.add("instance");
relations.add("subclass");
relations.add("subrelation");
relations.add("subAttribute");
int count = 0;
for (int i = 0; i < relations.size(); i++) {
ArrayList children = kb.askWithRestriction(0,relations.get(i),2,term);
if (children != null)
count = count + children.size();
}
if (count > 0)
return Integer.toString(count);
else
return ".";
}
/** *************************************************************
* @return a String URL link from the term to the graph page for the term,
* given the href input that already includes the kb and lang
* parameters.
*/
private String generateGraphLink(KB kb, String term, String href) {
String result = href.replace("Browse.jsp","Graph.jsp");
return "^";
}
/** *************************************************************
* @return an HTML-formatted String consisting of the first 100
* characters of the documentation string for the term parameter
*/
private String generateDocumentationColumn(KB kb, String term, String href, String language) {
String docString = "";
ArrayList docStmts = kb.askWithRestriction(0,"documentation",1,term);
if (docStmts.size() > 0) {
Formula doc = (Formula) docStmts.get(0);
docString = doc.getArgument(3);
if (!DB.emptyString(docString)) {
if (docString.length() > 100)
docString = docString.substring(1,100) + "...";
else
docString = docString.substring(1,docString.length()-1);
return kb.formatDocumentation(href,docString,language);
}
}
return "";
}
/** *************************************************************
* @return a count of the number of elements in columnList with the value
* "yes".
*/
public int columnCount() {
int counter = 0;
Iterator it = columnList.keySet().iterator();
while (it.hasNext()) {
String col = it.next();
String val = columnList.get(col);
if (val.equals("yes"))
counter++;
}
return counter;
}
/** *************************************************************
* @return in a String a header that shows each of the columns to be
* displayed in the HTML-based graph.
*/
private String createColumnHeader() {
StringBuffer result = new StringBuffer();
result.append(" "); // a blank column for the indented terms
Iterator it = columnList.keySet().iterator();
while (it.hasNext()) {
String col = it.next();
String val = columnList.get(col);
if (val.equals("yes"))
result.append("" + col + " ");
}
result.append(" ");
return result.toString();
}
/** *************************************************************
* @return in a String a header that shows each of the columns to be
* displayed in the HTML-based graph.
*/
private String createGraphEntry(KB kb, String prefix, String kbHref, String term, String language) {
StringBuffer result = new StringBuffer();
result.append("");
String formattedTerm = "" + term + "";
result.append("" + prefix + formattedTerm + " ");
Iterator it = columnList.keySet().iterator();
while (it.hasNext()) {
String col = it.next();
String val = columnList.get(col);
if (val.equals("yes")) {
if (col.equals("documentation"))
result.append("" + generateDocumentationColumn(kb,term,kbHref,language) + " ");
if (col.equals("direct-children"))
result.append("" + generateChildrenColumn(kb,term) + " ");
if (col.equals("graph"))
result.append("" + generateGraphLink(kb,term,kbHref) + " ");
}
}
result.append(" ");
return result.toString();
}
/** *************************************************************
* Create a graph of a bounded size by incrementing the number of
* levels above and below until the limit is reached or there are
* no more levels in the knowledge base from the given term and
* relation. creatGraphBody() does most of the work.
*/
public ArrayList createBoundedSizeGraph(KB kb, String term, String relation,
int size, String indentChars, String language) {
ArrayList result = new ArrayList();
ArrayList oldresult = new ArrayList();
int above = 1;
int below = 1;
int oldlimit = -1;
while ((result.size() < size) && (result.size() != oldlimit)) {
oldlimit = result.size();
oldresult = result;
HashSet checkAbove = new HashSet();
HashSet checkBelow = new HashSet();
result = createGraphBody(kb,checkAbove,term,relation,above,0,indentChars,above,true,language);
result.addAll(createGraphBody(kb,checkBelow,term,relation,0,below,indentChars,above,false,language));
above++;
below++;
}
return oldresult;
}
/** *************************************************************
* Create an ArrayList with a set of terms comprising a hierarchy
* Each term String will be prefixed with an appropriate number of
* indentChars. @see creatGraphBody() does most of the work.
*
* @param kb the knowledge base being graphed
* @param term the term in the KB being graphed
* @param relation the binary relation that is used to forms the arcs
* in the graph.
* @param above the number of levels above the given term in the graph
* @param below the number of levels below the given term in the graph
* @param indentChars a String of characters to be used for indenting the terms
*/
public ArrayList createGraph(KB kb, String term, String relation,
int above, int below, String indentChars, String language) {
graphsize = 0;
ArrayList result = new ArrayList(); // a list of Strings
HashSet checkAbove = new HashSet();
HashSet checkBelow = new HashSet();
result.add(createColumnHeader());
result.addAll(createGraphBody(kb,checkAbove,term,relation,above,0,indentChars,above,true,language));
result.addAll(createGraphBody(kb,checkBelow,term,relation,0,below,indentChars,above,false,language));
if (graphsize == 100)
result.add("Graph size limited to 100 terms.
\n");
return result;
}
/** *************************************************************
* The main body for @see createGraph(). Creates an indented,
* HTML-formatted display of terms.
* @param check collects all the terms added to the graph so
* far, which is used to prevent cycles
*/
private ArrayList createGraphBody(KB kb, Set check, String term, String relation,
int above, int below, String indentChars,int level,
boolean show, String language) {
ArrayList result = new ArrayList();
int graphMax = Integer.valueOf(KBmanager.getMgr().getPref("adminBrowserLimit")).intValue();
if (!check.contains(term) && graphsize < graphMax) {
if (above > 0) {
ArrayList stmtAbove = new ArrayList();
if (!DB.emptyString(relation) && relation.equals("all"))
stmtAbove = kb.ask("arg",1,term);
else
stmtAbove = kb.askWithRestriction(0,relation,1,term);
for (int i = 0; i < stmtAbove.size(); i++) {
Formula f = stmtAbove.get(i);
String newTerm = f.getArgument(2);
if (!newTerm.equals(term) && !f.sourceFile.endsWith("_Cache.kif"))
result.addAll(createGraphBody(kb,check,newTerm,relation,above-1,0,indentChars,level-1,true,language));
check.add(term);
}
}
StringBuffer prefix = new StringBuffer();
for (int i = 0; i < level; i++)
prefix = prefix.append(indentChars);
String hostname = KBmanager.getMgr().getPref("hostname");
if (hostname == null)
hostname = "localhost";
String port = KBmanager.getMgr().getPref("port");
if (port == null)
port = "8080";
String kbHref = "http://" + hostname + ":" + port + "/sigma/Browse.jsp?lang=" + kb.language + "&kb=" + kb.name;
if (show) {
graphsize++;
if (graphsize < 100)
result.add(createGraphEntry(kb,prefix.toString(),kbHref,term,language));
else
return result;
}
if (below > 0) {
ArrayList stmtBelow = kb.askWithRestriction(0,relation,2,term);
for (int i = 0; i < stmtBelow.size(); i++) {
Formula f = stmtBelow.get(i);
String newTerm = f.getArgument(1);
if (!newTerm.equals(term) && !f.sourceFile.endsWith("_Cache.kif"))
result.addAll(createGraphBody(kb,check,newTerm,relation,0,below-1,indentChars,level+1,true,language));
check.add(term);
}
}
}
return result;
}
/** *************************************************************
* Create a ArrayList with a set of terms comprising a hierarchy
* in a format suitable for GraphViz' input format
* http://www.graphviz.org/
* Generate a GIF from the .dot output with a command like
* dot SUMO-graph.dot -Tgif > graph.gif
*
* @param kb the knowledge base being graphed
* @param term the term in the KB being graphed
* @param relation the binary relation that is used to forms the arcs
* in the graph.
*/
public boolean createDotGraph(KB kb, String term, String relation, int above, int below, String fname) throws IOException {
FileWriter fw = null;
PrintWriter pw = null;
String filename = KBmanager.getMgr().getPref("graphDir") + File.separator + fname;
String graphVizDir = KBmanager.getMgr().getPref("graphVizDir");
try {
fw = new FileWriter(filename + ".dot");
pw = new PrintWriter(fw);
HashSet result = new HashSet();
HashSet start = new HashSet();
HashSet checked = new HashSet();
start.add(term);
result = createDotGraphBody(kb,start,checked,relation,above,below,true);
start.add(term);
result.addAll(createDotGraphBody(kb,start,checked,relation,above,below,false));
pw.println("digraph G {");
pw.println(" rankdir=LR");
Iterator it = result.iterator();
while (it.hasNext()) {
String s = it.next();
pw.println(s);
}
pw.println("}");
pw.close();
fw.close();
String command = graphVizDir + File.separator + "dot " + filename + ".dot -Tgif";
Process proc = Runtime.getRuntime().exec(command);
BufferedInputStream img = new BufferedInputStream(proc.getInputStream());
RenderedImage image = ImageIO.read(img);
File file = new File(filename + ".gif");
ImageIO.write(image, "gif", file);
return true;
}
catch (java.io.IOException e) {
throw new IOException("Error writing file " + filename + "\n" + e.getMessage());
}
finally {
if (pw != null) pw.close();
if (fw != null) fw.close();
}
}
/** *************************************************************
* The main body for createDotGraph().
*/
private HashSet createDotGraphBody(KB kb, HashSet startSet, HashSet checkedSet,
String relation, int above, int below, boolean upSearch) {
HashSet result = new HashSet();
HashSet newStartSet = new HashSet();
newStartSet.addAll(startSet);
if (upSearch) {
above--;
if (above < 0) return result;
}
else {
below--;
if (below < 0) return result;
}
while (startSet.size() > 0) {
Iterator it = startSet.iterator();
String term = (String) it.next();
boolean removed = startSet.remove(term);
if (!removed)
System.out.println("Error in Graph.createDotGraphBody(): " + term + " not removed");
ArrayList stmts;
if (upSearch)
stmts = kb.askWithRestriction(0,relation,1,term);
else
stmts = kb.askWithRestriction(0,relation,2,term);
for (int i = 0; i < stmts.size(); i++) {
Formula f = stmts.get(i);
if (f.isCached())
continue;
String parent = f.getArgument(2);
String child = f.getArgument(1);
String s = " \"" + parent + "\" -> \"" + child + "\";";
graphsize++;
if (graphsize < 100)
result.add(s);
else
return result;
checkedSet.add(term);
if (upSearch) {
newStartSet.add(parent);
}
else {
newStartSet.add(child);
}
result.addAll(createDotGraphBody(kb,newStartSet,checkedSet,relation,above,below,upSearch));
}
}
return result;
}
/** ***************************************************************
* A test method.
*/
public static void main(String[] args) {
try {
KBmanager.getMgr().initializeOnce();
KB kb = KBmanager.getMgr().getKB("SUMO");
Graph g = new Graph();
String start = "Process";
String relation = "subclass";
HashSet result = new HashSet();
HashSet checked = new HashSet();
HashSet startSet = new HashSet();
startSet.add(start);
result = g.createDotGraphBody(kb,startSet,checked,relation,0,2,false);
System.out.println(result);
//g.createDotGraph(kb, "Process", "subclass", 2,2, "graph.txt");
}
catch (Exception ex ) {
System.out.println(ex.getMessage());
}
/*
Graph g = new Graph();
HashSet result = g.createDotGraph(kb,"Entity","subclass");
System.out.println("digraph G {");
System.out.println(" rankdir=LR");
Iterator it = result.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
System.out.println("}");
*/
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy