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