[TASK] Add rough reasoning debugging window.

This commit is contained in:
Jan Philipp Timme 2016-10-07 14:14:40 +02:00
parent eec451fe8e
commit 5ea6bb38b9
3 changed files with 398 additions and 0 deletions

View File

@ -15,6 +15,7 @@ import eu.larkc.csparql.core.engine.CsparqlEngineImpl;
import eu.larkc.csparql.core.engine.CsparqlQueryResultProxy; import eu.larkc.csparql.core.engine.CsparqlQueryResultProxy;
import eu.larkc.csparql.core.engine.RDFStreamFormatter; import eu.larkc.csparql.core.engine.RDFStreamFormatter;
import lu.jpt.csparqlproject.gui.FancyTextObserverWindow; import lu.jpt.csparqlproject.gui.FancyTextObserverWindow;
import lu.jpt.csparqlproject.misc.ReasoningTester;
import lu.jpt.csparqlproject.rentacar.RentACarSimulation; import lu.jpt.csparqlproject.rentacar.RentACarSimulation;
import lu.jpt.csparqlproject.util.CsparqlQueryHelper; import lu.jpt.csparqlproject.util.CsparqlQueryHelper;
import lu.jpt.csparqlproject.util.CsparqlQueryHelper.CsparqlQueryInfo; import lu.jpt.csparqlproject.util.CsparqlQueryHelper.CsparqlQueryInfo;
@ -145,6 +146,8 @@ public class SimulationContext {
+ "{ GRAPH <http://streamreasoning.org/roomConnection> { :room :isConnectedTo :room2 } }"; + "{ GRAPH <http://streamreasoning.org/roomConnection> { :room :isConnectedTo :room2 } }";
this.engine.execUpdateQueryOverDatasource(updateQuery); this.engine.execUpdateQueryOverDatasource(updateQuery);
*/ */
// DEBUGGING ONLY
ReasoningTester rt = new ReasoningTester(this.engine);
// Spawn the whole simulation - this takes care of simulation-specific things // Spawn the whole simulation - this takes care of simulation-specific things
simulation = new RentACarSimulation(); simulation = new RentACarSimulation();
// Register all the event streams // Register all the event streams

View File

@ -0,0 +1,81 @@
package lu.jpt.csparqlproject.misc;
import java.util.Observable;
import java.util.Observer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.larkc.csparql.cep.api.RdfStream;
import eu.larkc.csparql.common.RDFTable;
import eu.larkc.csparql.common.utils.CsparqlUtils;
import eu.larkc.csparql.common.utils.ReasonerChainingType;
import eu.larkc.csparql.core.engine.CsparqlEngine;
import eu.larkc.csparql.core.engine.CsparqlQueryResultProxy;
/**
* This ugly component acts as a console to throw data in and see how it got enriched.
* Small helper to be registered as an RdfStream and an Observer for its own
* CsparqlQueryResultProxy in order to observe what triples are being generated
*/
public class ReasoningTester extends RdfStream implements Observer {
public static Logger logger = LoggerFactory.getLogger(ReasoningTester.class);
public static String iri = "http://example.org/reasoningTestStr";
private CsparqlEngine engine;
private ReasoningTesterWindow reasoningTesterWindow;
public ReasoningTester(CsparqlEngine engine) {
super(ReasoningTester.iri);
this.engine = engine;
this.reasoningTesterWindow = new ReasoningTesterWindow(this);
this.initialize();
}
private void initialize() {
try {
this.engine.registerStream(this);
CsparqlQueryResultProxy resultProxy = this.engine.registerQuery(this.getQuery(), true);
engine.updateReasoner(
resultProxy.getSparqlQueryId(),
CsparqlUtils.fileToString("data/rdfs.rules"),
ReasonerChainingType.FORWARD,
CsparqlUtils.serializeRDFFile("data/carSimulationTBox.rdf")
);
resultProxy.addObserver(this);
} catch (Exception e) {
ReasoningTester.logger.error(e.toString());
ReasoningTester.logger.error(e.getStackTrace().toString());
}
}
private String getQuery() {
return "REGISTER QUERY ReasoningObserveTest AS "
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> "
+ "PREFIX f: <http://larkc.eu/csparql/sparql/jena/ext#> "
+ "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> "
+ "SELECT ?s ?p ?o "
+ "FROM STREAM <"+ReasoningTester.iri+"> [RANGE 2s STEP 1s] "
+ "WHERE { "
+ " ?s ?p ?o . "
+ "}";
}
@Override
public void update(Observable o, Object arg) {
CsparqlQueryResultProxy resultProxy = null;
RDFTable rdfTable = null;
if(o instanceof CsparqlQueryResultProxy) {
resultProxy = (CsparqlQueryResultProxy) o;
}
if(arg instanceof RDFTable) {
rdfTable = (RDFTable) arg;
}
if(this.reasoningTesterWindow != null) {
this.reasoningTesterWindow.showCsparqlQueryResult(resultProxy, rdfTable);
}
}
}

View File

@ -0,0 +1,314 @@
package lu.jpt.csparqlproject.misc;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Collection;
import java.util.Iterator;
import java.util.StringTokenizer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import eu.larkc.csparql.cep.api.RdfQuadruple;
import eu.larkc.csparql.common.RDFTable;
import eu.larkc.csparql.common.RDFTuple;
import eu.larkc.csparql.core.engine.CsparqlQueryResultProxy;
import lu.jpt.csparqlproject.Main;
public class ReasoningTesterWindow extends JFrame {
private static final long serialVersionUID = 1L;
private ReasoningTester reasoningTester;
private JTextPane textPane;
private JTextField subjectField;
private JTextField predicateField;
private JTextField objectField;
public ReasoningTesterWindow(ReasoningTester reasoningTester) {
this.reasoningTester = reasoningTester;
this.initialize();
}
private void initialize() {
final ReasoningTesterWindow me = this;
Container contentPane = this.getContentPane();
this.setTitle("ReasoningTest");
this.setUndecorated(false);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
// Get a TextPane ready - a little hack to make it always scroll horizontally
this.textPane = new JTextPane() {
private static final long serialVersionUID = 1L;
public boolean getScrollableTracksViewportWidth() {
return false;
}
public void setSize(Dimension dimension) {
if (dimension.width < getParent().getSize().width) {
dimension.width = getParent().getSize().width;
}
super.setSize(dimension);
}
};
this.textPane.setEnabled(true);
this.textPane.setFocusable(false);
this.textPane.setEditable(true);
this.textPane.setAutoscrolls(true);
this.textPane.setMargin(new Insets(5, 5, 5, 5));
contentPane.add(this.textPane, BorderLayout.CENTER);
// Add a ScrollPane
JScrollPane scrollPane = new JScrollPane(this.textPane);
scrollPane.setPreferredSize(new Dimension(800, 600));
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
contentPane.add(scrollPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
// Create three input fields plus a button, add them to panel
this.subjectField = new JTextField(30);
panel.add(this.subjectField);
this.predicateField = new JTextField(30);
panel.add(this.predicateField);
this.objectField = new JTextField(30);
panel.add(this.objectField);
JButton submitButton = new JButton("submit");
panel.add(submitButton);
submitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
RdfQuadruple quad = new RdfQuadruple(
me.subjectField.getText(),
me.predicateField.getText(),
me.objectField.getText(),
System.currentTimeMillis()
);
me.showQuadruple(quad, Color.BLUE);
me.reasoningTester.put(quad);
me.subjectField.setText("");
me.predicateField.setText("");
me.objectField.setText("");
}
});
contentPane.add(panel, BorderLayout.SOUTH);
this.setVisible(true);
this.pack();
}
/**
* Show the given text in the window
* @param text
*/
public void showText(String text) {
this.showText(text, Color.BLACK);
}
/**
* Show given text in the window using the given color
* @param text
* @param color
*/
public void showText(String text, Color color) {
this.appendToTextPane(text, true, color);
}
/**
* Show the given token in the window without appending linebreaks
* @param text
*/
public void showToken(String token) {
this.showText(token, Color.BLACK);
}
/**
* Show given token in the window using the given color without appending linebreaks
* @param text
* @param color
*/
public void showToken(String token, Color color) {
this.appendToTextPane(token, false, color);
}
/**
* Show given RdfQuadruple in the window
* @param quad
*/
public void showQuadruple(RdfQuadruple quad) {
this.showQuadruple(quad, Color.BLACK);
}
/**
* Show given RdfQuadruple in window using given color
* @param quad
* @param color
*/
public void showQuadruple(RdfQuadruple quad, Color color) {
String quadruple = this.shortenUriToPrefix(quad.toString());
this.appendToTextPane(quadruple, true, color);
}
/**
* Internal man-in-the-middle method to pass the task to the AWT EventQueue
* @param text to show within the window
* @param addLinebreak whether or not to add a linebreak (usually yes is better)
* @param color to display the text in
*/
private void appendToTextPane(String text, boolean addLinebreak, Color color) {
final ReasoningTesterWindow me = this;
EventQueue.invokeLater(() -> {
me.actuallyAppendTextToTextPane(text, addLinebreak, color);
});
}
/**
* Internal method to append text to the textpane
* @param text to show within the window
* @param addLinebreak whether or not to add a linebreak (usually yes is better)
* @param color to display the text in
*/
private void actuallyAppendTextToTextPane(String text, boolean addLinebreak, Color color) {
if (addLinebreak) text += "\n";
StyleContext styleContext = StyleContext.getDefaultStyleContext();
AttributeSet attributeSet = styleContext.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, color);
attributeSet = styleContext.addAttribute(attributeSet, StyleConstants.FontFamily, "Lucida Console");
attributeSet = styleContext.addAttribute(attributeSet, StyleConstants.Alignment, StyleConstants.ALIGN_JUSTIFIED);
int length = this.textPane.getDocument().getLength();
boolean success = false;
do {
try {
this.textPane.setCaretPosition(length);
this.textPane.setCharacterAttributes(attributeSet, false);
this.textPane.replaceSelection(text);
success = true;
} catch(Exception e) {
// Yes, i know. :-(
}
} while(!success);
// This is the place to enforce a line limit
this.enforceLineLimit();
// TODO: Fix behaviour when autoscroll is disabled!
if(true) {
Document textPaneDocument = this.textPane.getDocument();
this.textPane.select(textPaneDocument.getLength(), textPaneDocument.getLength());
}
}
/**
* Helper method to enforce a line limit for the window.
*/
private void enforceLineLimit() {
int MAX_LINES = 800;
String[] lines = this.textPane.getText().split("\n");
int totalLines = lines.length;
if(totalLines > MAX_LINES) {
if(true) {
try {
this.textPane.getDocument().remove(0, this.textPane.getDocument().getLength());
} catch (BadLocationException e) {
// This has to work. :-/
}
}
}
}
/**
* Method to actually pretty-print the results of a Csparql query
* @param CsparqlQueryResultProxy result
* @param RDFTable table
*/
public void showCsparqlQueryResult(CsparqlQueryResultProxy result, RDFTable table) {
long currentTime = System.currentTimeMillis();
Collection<String> tupleElementNames = table.getNames();
Collection<RDFTuple> tuples = table.getTuples();
Color[] palette = this.getColorPaletteWithSize(table.getNames().size());
this.showText("SystemTime=["+currentTime+"], Results=["+tuples.size()+"]", Color.BLACK);
// Show names in according color coding
this.showToken("Columns in order: [", Color.BLACK);
Iterator<String> elementNamesIterator = tupleElementNames.iterator();
int nameIndex = 0;
while(elementNamesIterator.hasNext()) {
String elementName = elementNamesIterator.next();
if(elementName == "") elementName = "[NO VALUE]";
if(elementNamesIterator.hasNext()) {
elementName += ", ";
}
this.showToken(elementName, palette[nameIndex]);
nameIndex++;
}
this.showText("]", Color.BLACK);
for(RDFTuple tuple : tuples) {
// This one is separated with \t. Due to the implementation of RDFTuple, it is
// impossible to access the list of its fields directly. Sorry for the mess. :-(
String tupleString = tuple.toString();
// Explode tupleString by \t and show each field with alternating color.
StringTokenizer tokenizer = new StringTokenizer(tupleString);
int tokenIndex = 0;
while(tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
token = this.shortenUriToPrefix(token);
if(token == "") token = "[NO VALUE]";
if(tokenizer.hasMoreTokens()) {
token += "\t";
} else {
token += "\n";
}
this.showToken(token, palette[tokenIndex]);
tokenIndex++;
}
}
this.showText("End of results ----------------------------------------------------------------- \n", Color.BLACK);
}
/**
* Generates a color palette for the given number of colors
* @param sizeOfPalette number of colors
* @return color palette as an array
*/
private Color[] getColorPaletteWithSize(int sizeOfPalette) {
if(sizeOfPalette == 0) {
return new Color[] {Color.BLACK};
}
Color[] result = new Color[sizeOfPalette];
float h = 0.0f;
float s = 0.8f;
float b = 0.65f;
for(int i=0; i<sizeOfPalette; i++) {
h = (((float) i)/((float) sizeOfPalette));
result[i] = Color.getHSBColor(h, s, b);
}
return result;
}
/**
* Helper method to shorten strings using the PrefixManager if
* this window uses it
* @param str input string
* @return output string, shortened or not depending on usePrefixManager variable
*/
private String shortenUriToPrefix(String str) {
return Main.prefixManager.applyPrefix(str);
}
}