[TASK] Add rough reasoning debugging window.
This commit is contained in:
parent
eec451fe8e
commit
5ea6bb38b9
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue