package com.monead.semantic.education;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.tree.*;
import org.apache.log4j.Logger;
import org.mindswap.pellet.jena.PelletReasonerFactory;
import org.mindswap.pellet.utils.VersionInfo;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.query.ARQ;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
/**
* SemanticUI - A GUI to input assertions, run an inferencing engine and use
* SPARQL queries on the resulting model
*
* This program uses Jena and Pellet to provide the inference support.
*
* Copyright (C) 2010 David S. Read
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* For information on Jena: http://jena.sourceforge.net/ For information on
* Pellet: http://clarkparsia.com/pellet
*
* @author David Read
*
* TODO Add support for reading and writing RDF from URLs
*
* TODO Add support to write inferred triples to a file
*
* TODO Add support for SPARQL queries that use the model and URLs
*
* TODO Store settings in properties file
*/
public class SemanticUI extends JFrame implements Runnable, WindowListener {
/**
* The version identifier
*/
public final static String VERSION = "1.2";
/**
* Serial UID to keep environment happy
*/
private final static long serialVersionUID = 19991231;
/**
* The set of formats that can be loaded. These are defined by Jena
*/
private final static String[] FORMATS = { "N3", "N-Triples", "RDF/XML",
"Turtle" };
/**
* Logger Instance
*/
private static Logger LOGGER = Logger.getLogger(SemanticUI.class);
/**
* Standard prefixes
*
* In N3, N-Triples, RDF/XML and Turtle Order matches that of the FORMAT
* array
*/
private final static String[][] STANDARD_PREFIXES = {
// N3
{ "@prefix rdf: .",
"@prefix rdfs: .",
"@prefix owl: .",
"@prefix xsd: .",
"@prefix dc: .", },
// N-triples
{},
// RDF/XML
{
"" },
// Turtle
{ "@prefix rdf: .",
"@prefix rdfs: .",
"@prefix owl: .",
"@prefix xsd: .",
"@prefix dc: .", },
// SPARQL
{ "prefix rdf: ",
"prefix rdfs: ",
"prefix owl: ",
"prefix xsd: ",
"prefix dc: ", } };
/**
* The set of reasoning levels that will be compared.
*/
protected final static String[] REASONING_LEVELS = { "none", "rdfs", "owl" };
/**
* Constant used if a value cannot be found in an array
*/
private final static int UNKNOWN = -1;
/**
* The name (and path if necessary) to the ontology being loaded
*/
private File rdfFile;
/**
* The processed ontology
*/
private OntModel ontModel;
/**
* The asserted model (no inferred information)
*/
private OntModel ontModelNoInference;
/**
* File open menu item
*
* Used to load an ontology in to the assertions text area
*/
private JMenuItem fileOpen;
/**
* File save menu item
*
* Used to save the ontology text to a file
*/
private JMenuItem fileSave;
/**
* File save menu item
*
* Used to serialize the current model to a file
*/
private JMenuItem fileSaveSerializedModel;
/**
* End the program
*/
private JMenuItem fileExit;
/**
* Edit insert prefixes menu item
*
* Used to insert standard prefixes as a convenience
*/
private JMenuItem editInsertPrefixes;
/**
* Expand all the nodes of the tree view of the model
*/
private JMenuItem editExpandAllTreeNodes;
/**
* Collapse all the nodes of the tree view of the model
*/
private JMenuItem editCollapseAllTreeNodes;
/**
* The format to use when writing the RDF to a file
*/
private JCheckBoxMenuItem[] setupOutputAssertionLanguage;
/**
* Write only assertions when outputting the model
*/
private JCheckBoxMenuItem setupOutputModelTypeAssertions;
/**
* Write assertions and inferences when outputting the model
*/
private JCheckBoxMenuItem setupOutputModelTypeAssertionsAndInferences;
/**
* Set the font used for the major interface display widgets
*/
private JMenuItem setupFont;
/**
* View the about dialog
*/
private JMenuItem helpAbout;
/**
* Allows selection of the reasoning level
*/
private JComboBox reasoningLevel;
/**
* Allows selection of the semantic syntax being used
*/
private JComboBox language;
/**
* The semantic syntax used for the assertions
*
* Set when the assertions are loaded into the model
*/
private String assertionLanguage;
/**
* Run the inferencing engine
*/
private JButton runInferencing;
/**
* Execute the SPARQL query
*/
private JButton runSparql;
/**
* The assertions
*/
private JTextArea assertions;
/**
* SPARQL input
*/
private JTextArea sparqlInput;
/**
* Choose SPARQL service to use
*/
private JComboBox sparqlServiceUrl;
/**
* SPARQL execution results
*/
private JTable sparqlResultsTable;
/**
* Main work area housing the assertions, output and SPARQL text areas
*/
private JTabbedPane tabbedPane;
/**
* Status reporting
*/
private JLabel status;
/**
* The results from running the inferencing engine
*/
private JTextArea results;
/**
* The resulting model displayed as a tree
*/
private JTree ontModelTree;
/**
* Should the reasoner be run (otherwise SPARQL query is being run)
*
* TODO prevent collision (e.g. lock execution)
*/
private boolean isRunReasoner;
/**
* Constructor - sets up the UI
*/
public SemanticUI() {
LOGGER.info("Startup");
addWindowListener(this);
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
setTitle("Semantic UI");
setupGUI();
enableControls(true);
pack();
setStatus("");
setVisible(true);
}
/**
* Place the components in the JFrame
*/
private void setupGUI() {
JPanel panel;
LOGGER.debug("SetupGUI");
setupControls();
setupMenus();
getContentPane().setLayout(new BorderLayout());
panel = new JPanel();
panel.setLayout(new BorderLayout());
getContentPane().add(panel, BorderLayout.CENTER);
tabbedPane = new JTabbedPane();
// Assertions
tabbedPane.add("Assertions", setupAssertionsPanel());
// Inferences
tabbedPane.add("Inferences", setupInferencesPanel());
// Tree
tabbedPane.add("Tree View", setupTreePanel());
// SPARQL
tabbedPane.add("SPARQL", setupSparqlPanel());
// Add the tabbed pane to the main window
panel.add(tabbedPane, BorderLayout.CENTER);
// Status label, bottom of window
panel.add(setupStatusPanel(), BorderLayout.SOUTH);
}
/**
* Present the user with a font selection dialog and update the widgets if
* the user chooses a font.
*/
private void configureFont() {
FontChooser chooser;
Font newFont;
Color newColor;
FontMetrics fontMetrics;
chooser = new FontChooser(this);
LOGGER.debug("Font before choices: " + chooser.getNewFont());
chooser.setVisible(true);
newFont = chooser.getNewFont();
newColor = chooser.getNewColor();
LOGGER.debug("Font after choices: " + newFont);
if (newFont != null) {
assertions.setFont(newFont);
results.setFont(newFont);
sparqlInput.setFont(newFont);
ontModelTree.setFont(newFont);
sparqlResultsTable.setFont(newFont);
sparqlResultsTable.getTableHeader().setFont(newFont);
fontMetrics = sparqlResultsTable.getFontMetrics(newFont);
sparqlResultsTable.setRowHeight(((int) ((double) fontMetrics
.getHeight() * 1.1)));
status.setFont(newFont);
}
if (newColor != null) {
assertions.setForeground(newColor);
results.setForeground(newColor);
sparqlInput.setForeground(newColor);
ontModelTree.setForeground(newColor);
((DefaultTreeCellRenderer) ontModelTree.getCellRenderer())
.setTextNonSelectionColor(newColor);
sparqlResultsTable.setForeground(newColor);
sparqlResultsTable.getTableHeader().setForeground(newColor);
status.setForeground(newColor);
}
}
/**
* Create the assertions panel
*
* @return The assertions JPanel
*/
private JPanel setupAssertionsPanel() {
JPanel assertionPanel;
JPanel gridPanel;
JPanel flowPanel;
assertionPanel = new JPanel();
assertionPanel.setLayout(new BorderLayout());
// Top of panel will allow for configuration of
// inferencing environment
gridPanel = new JPanel();
gridPanel.setLayout(new GridLayout(0, 2));
// First Row (reasoning level and input language)
flowPanel = new JPanel();
flowPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
flowPanel.add(new JLabel("Reasoning Level:"));
flowPanel.add(reasoningLevel);
gridPanel.add(flowPanel);
// Language drop-down
flowPanel = new JPanel();
flowPanel.setLayout(new FlowLayout());
flowPanel.add(new JLabel("Language:"));
flowPanel.add(language);
gridPanel.add(flowPanel);
// Second Row
gridPanel.add(makeFlowPanel(new JLabel("Enter Assertions"),
FlowLayout.LEFT));
flowPanel = new JPanel();
flowPanel.setLayout(new FlowLayout());
flowPanel.add(runInferencing);
gridPanel.add(flowPanel);
assertionPanel.add(gridPanel, BorderLayout.NORTH);
assertionPanel.add(new JScrollPane(assertions), BorderLayout.CENTER);
return assertionPanel;
}
/**
* Setup the inferences panel
*
* @return The inferences JPanel
*/
private JPanel setupInferencesPanel() {
JPanel inferencesPanel;
// output
inferencesPanel = new JPanel();
inferencesPanel.setLayout(new GridLayout(1, 1));
inferencesPanel.add(new JScrollPane(results));
return inferencesPanel;
}
/**
* Setup the model tree display panel
*
* @return The model tree JPanel
*/
private JPanel setupTreePanel() {
JPanel treePanel;
treePanel = new JPanel();
treePanel.setLayout(new GridLayout(1, 1));
treePanel.add(new JScrollPane(ontModelTree));
return treePanel;
}
/**
* Setup the SPARQL panel
*
* @return The SPARQL JPanel
*/
private JPanel setupSparqlPanel() {
JPanel sparqlPanel;
JPanel labelPanel;
JPanel gridPanel;
JPanel innerGridPanel;
JPanel flowPanel;
sparqlPanel = new JPanel();
sparqlPanel.setLayout(new GridLayout(2, 1));
// SPARQL Input
labelPanel = new JPanel();
labelPanel.setLayout(new BorderLayout());
gridPanel = new JPanel();
gridPanel.setLayout(new GridLayout(2, 1));
innerGridPanel = new JPanel();
innerGridPanel.setLayout(new GridLayout(1, 2));
innerGridPanel.add(new JLabel("SPARQL Query"));
flowPanel = new JPanel();
flowPanel.setLayout(new FlowLayout());
flowPanel.add(runSparql);
innerGridPanel.add(flowPanel);
gridPanel.add(innerGridPanel);
flowPanel = new JPanel();
flowPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
flowPanel.add(new JLabel("SPARQL Service: "));
flowPanel.add(sparqlServiceUrl);
gridPanel.add(flowPanel);
labelPanel.add(gridPanel, BorderLayout.NORTH);
labelPanel.add(new JScrollPane(sparqlInput), BorderLayout.CENTER);
sparqlPanel.add(labelPanel);
// SPARQL results
labelPanel = new JPanel();
labelPanel.setLayout(new BorderLayout());
labelPanel.add(new JLabel("Results"), BorderLayout.NORTH);
// labelPanel.add(new JScrollPane(sparqlResults), BorderLayout.CENTER);
labelPanel
.add(new JScrollPane(sparqlResultsTable), BorderLayout.CENTER);
sparqlPanel.add(labelPanel);
return sparqlPanel;
}
/**
* Setup the status panel
*
* @return The status JPanel
*/
private JPanel setupStatusPanel() {
JPanel statusPanel;
statusPanel = new JPanel();
statusPanel.setLayout(new GridLayout(1, 1));
statusPanel.add(makeFlowPanel(status, FlowLayout.LEFT));
return statusPanel;
}
/**
* Setup the frame's menus
*/
private void setupMenus() {
JMenuBar menuBar;
JMenu menu;
ButtonGroup buttonGroup;
menuBar = new JMenuBar();
setJMenuBar(menuBar);
menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.getAccessibleContext().setAccessibleDescription(
"Menu items related to file access");
menuBar.add(menu);
fileOpen = new JMenuItem("Open");
fileOpen.setMnemonic('O');
fileOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
ActionEvent.ALT_MASK));
fileOpen.setMnemonic(KeyEvent.VK_L);
fileOpen.getAccessibleContext().setAccessibleDescription(
"Open an ontology file");
fileOpen.addActionListener(new FileOpenListener());
menu.add(fileOpen);
menu.addSeparator();
fileSave = new JMenuItem("Save Assertions Text");
fileSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
ActionEvent.ALT_MASK));
fileSave.setMnemonic(KeyEvent.VK_S);
fileSave.getAccessibleContext().setAccessibleDescription(
"Write the assertions to a file");
fileSave.addActionListener(new FileSaveListener());
menu.add(fileSave);
fileSaveSerializedModel = new JMenuItem("Save Model");
fileSaveSerializedModel.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_M, ActionEvent.ALT_MASK));
fileSaveSerializedModel.setMnemonic(KeyEvent.VK_M);
fileSaveSerializedModel.getAccessibleContext()
.setAccessibleDescription(
"Write an ontology file from the current model");
fileSaveSerializedModel
.addActionListener(new ModelSerializerListener());
menu.add(fileSaveSerializedModel);
menu.addSeparator();
fileExit = new JMenuItem("Exit");
fileExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
ActionEvent.ALT_MASK));
fileExit.setMnemonic(KeyEvent.VK_X);
fileExit.getAccessibleContext().setAccessibleDescription(
"Exit the application");
fileExit.addActionListener(new EndApplicationListener());
menu.add(fileExit);
// Edit Menu
menu = new JMenu("Edit");
menu.setMnemonic(KeyEvent.VK_E);
menu.getAccessibleContext().setAccessibleDescription(
"Menu items releated to editing the ontology");
menuBar.add(menu);
editInsertPrefixes = new JMenuItem("Insert Prefixes");
editInsertPrefixes.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I,
ActionEvent.ALT_MASK));
editInsertPrefixes.setMnemonic(KeyEvent.VK_I);
editInsertPrefixes.getAccessibleContext().setAccessibleDescription(
"Insert standard prefixes (namespaces)");
editInsertPrefixes.addActionListener(new InsertPrefixesListener());
menu.add(editInsertPrefixes);
menu.addSeparator();
editExpandAllTreeNodes = new JMenuItem("Expand Entire Tree");
editExpandAllTreeNodes.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_ADD, ActionEvent.ALT_MASK));
editExpandAllTreeNodes.setMnemonic(KeyEvent.VK_E);
editExpandAllTreeNodes.getAccessibleContext().setAccessibleDescription(
"Expand all tree nodes");
editExpandAllTreeNodes.addActionListener(new ExpandTreeListener());
menu.add(editExpandAllTreeNodes);
editCollapseAllTreeNodes = new JMenuItem("Collapse Entire Tree");
editCollapseAllTreeNodes.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_SUBTRACT, ActionEvent.ALT_MASK));
editCollapseAllTreeNodes.setMnemonic(KeyEvent.VK_C);
editCollapseAllTreeNodes.getAccessibleContext()
.setAccessibleDescription("Expand all tree nodes");
editCollapseAllTreeNodes.addActionListener(new CollapseTreeListener());
menu.add(editCollapseAllTreeNodes);
// Setup Menu
menu = new JMenu("Setup");
menu.setMnemonic(KeyEvent.VK_S);
menu.getAccessibleContext().setAccessibleDescription(
"Menu items related to configuration");
menuBar.add(menu);
buttonGroup = new ButtonGroup();
setupOutputAssertionLanguage = new JCheckBoxMenuItem[FORMATS.length + 1];
setupOutputAssertionLanguage[0] = new JCheckBoxMenuItem(
"Output Format: Auto");
buttonGroup.add(setupOutputAssertionLanguage[0]);
menu.add(setupOutputAssertionLanguage[0]);
for (int index = 0; index < FORMATS.length; ++index) {
setupOutputAssertionLanguage[index + 1] = new JCheckBoxMenuItem(
"Output Format: " + FORMATS[index]);
buttonGroup.add(setupOutputAssertionLanguage[index + 1]);
menu.add(setupOutputAssertionLanguage[index + 1]);
}
setupOutputAssertionLanguage[0].setSelected(true);
menu.addSeparator();
buttonGroup = new ButtonGroup();
setupOutputModelTypeAssertions = new JCheckBoxMenuItem(
"Output Assertions Only");
buttonGroup.add(setupOutputModelTypeAssertions);
menu.add(setupOutputModelTypeAssertions);
setupOutputModelTypeAssertionsAndInferences = new JCheckBoxMenuItem(
"Output Assertions and Inferences");
buttonGroup.add(setupOutputModelTypeAssertionsAndInferences);
menu.add(setupOutputModelTypeAssertionsAndInferences);
setupOutputModelTypeAssertions.setSelected(true);
menu.addSeparator();
setupFont = new JMenuItem("Font");
setupFont.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F,
ActionEvent.ALT_MASK));
setupFont.setMnemonic(KeyEvent.VK_F);
setupFont.getAccessibleContext().setAccessibleDescription(
"Set the font used for the display");
setupFont.addActionListener(new FontSetupListener());
menu.add(setupFont);
// Help Menu
menu = new JMenu("Help");
menu.setMnemonic(KeyEvent.VK_H);
menu.getAccessibleContext().setAccessibleDescription(
"Menu items releated to user assistance");
menuBar.add(menu);
helpAbout = new JMenuItem("About");
helpAbout.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H,
ActionEvent.ALT_MASK));
helpAbout.setMnemonic(KeyEvent.VK_H);
helpAbout.getAccessibleContext().setAccessibleDescription(
"View version information");
helpAbout.addActionListener(new AboutListener());
menu.add(helpAbout);
}
/**
* Enable and disable controls based on current state
*
* @param enable
* Whether to enable or disable controls
*/
private void enableControls(boolean enable) {
String sparqlService;
LOGGER.debug("Called enableControls with setting " + enable);
assertions.setEditable(enable);
sparqlInput.setEditable(enable);
fileOpen.setEnabled(enable);
if (enable && ontModelNoInference != null) {
fileSaveSerializedModel.setEnabled(true);
} else {
fileSaveSerializedModel.setEnabled(false);
}
if (enable && assertions.getText().trim().length() > 0) {
runInferencing.setEnabled(true);
fileSave.setEnabled(true);
} else {
runInferencing.setEnabled(false);
fileSave.setEnabled(false);
}
sparqlService = ((String) sparqlServiceUrl.getEditor().getItem())
.trim();
if (!sparqlService.equals((String) sparqlServiceUrl.getItemAt(0))
&& sparqlService.length() > 0
&& sparqlInput.getText().trim().length() > 0) {
runSparql.setEnabled(true);
LOGGER.debug("Enabled Run SPARQL Button (" + sparqlService + ")");
} else if (enable && sparqlInput.getText().trim().length() > 0
&& ontModel != null) {
runSparql.setEnabled(true);
LOGGER.debug("Enabled Run SPARQL Button (" + sparqlService + ")");
} else {
runSparql.setEnabled(false);
LOGGER.debug("Disabled Run SPARQL Button (" + sparqlService + ")");
}
}
/**
* Setup all the components
*/
private void setupControls() {
LOGGER.debug("setupControls");
reasoningLevel = new JComboBox();
for (String level : REASONING_LEVELS) {
reasoningLevel.addItem(level);
}
reasoningLevel.setSelectedIndex(reasoningLevel.getItemCount() - 1);
language = new JComboBox();
language.addItem("Auto");
for (String lang : FORMATS) {
language.addItem(lang);
}
language.setSelectedIndex(0);
runInferencing = new JButton("Run Reasoner");
runInferencing.addActionListener(new ReasonerListener());
runSparql = new JButton("Run SPARQL");
runSparql.addActionListener(new SparqlListener());
assertions = new JTextArea(10, 50);
assertions.addKeyListener(new UserInputListener());
results = new JTextArea(10, 50);
results.setEditable(false);
// SPARQL Input
sparqlInput = new JTextArea(10, 50);
sparqlInput.addKeyListener(new UserInputListener());
sparqlServiceUrl = new JComboBox();
sparqlServiceUrl.setEditable(true);
sparqlServiceUrl.addItem("Local Model");
sparqlServiceUrl.addItem("http://DBpedia.org/sparql");
sparqlServiceUrl.addItem("http://lod.openlinksw.com/sparql/");
sparqlServiceUrl.addItem("http://semantic.data.gov/sparql");
sparqlServiceUrl
.addItem("http://www4.wiwiss.fu-berlin.de/gutendata/sparql");
sparqlServiceUrl.addActionListener(new SparqlModelChoiceListener());
sparqlServiceUrl.getEditor().getEditorComponent().addKeyListener(
new UserInputListener());
// A basic default query
sparqlInput.setText("select ?s ?p ?o where { ?s ?p ?o }");
sparqlResultsTable = new JTable(new SparqlTableModel());
ontModelTree = new JTree(new DefaultTreeModel(
new DefaultMutableTreeNode("No Model Created")));
status = new JLabel("Initializing");
status.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 12));
}
/**
* Create a JPanel that uses a FlowLayout and add a component to the JPanel.
* The method creates a JPanel, sets its layout to FlowLayout and adds the
* supplied component to itself.
*
* @param component
* The component to be placed using a FlowLayout
* @param alignment
* How to align the component. Use a FlowLayout constant.
*
* @return The new JPanel instance
*/
private JPanel makeFlowPanel(JComponent component, int alignment) {
JPanel panel;
panel = new JPanel();
panel.setLayout(new FlowLayout(alignment));
panel.add(component);
return panel;
}
/**
* Expand all the nodes in the tree representation of the model
*/
private void expandAll() {
for (int row = 0; row < ontModelTree.getRowCount(); ++row) {
ontModelTree.expandRow(row);
}
}
/**
* Collapse all the nodes in the tree representation of the model
*/
private void collapseAll() {
for (int row = 0; row < ontModelTree.getRowCount(); ++row) {
ontModelTree.collapseRow(row);
}
}
/**
* Set the status message to the supplied text.
*
* @param message
* The message to place in the status field
*/
private void setStatus(String message) {
status.setText(message);
}
/**
* Sets the mouse pointer. If the supplied parameter is true then the wait
* cursor (usually an hourglass) is displayed. otherwise the system default
* cursor is displayed.
*
* @param wait
* Whether to display the system default wait cursor
*/
private void setWaitCursor(boolean wait) {
JRootPane rootPane = getRootPane();
Component glassPane = rootPane.getGlassPane();
if (wait) {
Cursor cursorWait = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
rootPane.setCursor(cursorWait);
glassPane.setCursor(cursorWait);
glassPane.setVisible(true);
} else {
Cursor cursorDefault = Cursor
.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
glassPane.setVisible(false);
glassPane.setCursor(cursorDefault);
rootPane.setCursor(cursorDefault);
}
glassPane.invalidate();
rootPane.validate();
}
/**
* Run the reasoner or the SPARQL query
*/
public void run() {
enableControls(false);
try {
setStatus("Running...");
setWaitCursor(true);
if (isRunReasoner) {
reasonerExecution();
} else {
sparqlExecution();
}
} catch (Throwable throwable) {
setStatus("Error: " + throwable.getClass().getName() + ": "
+ throwable.getMessage());
LOGGER.error("Failed during execution", throwable);
JOptionPane.showMessageDialog(this, "Error: "
+ throwable.getClass().getName() + "\n\n"
+ throwable.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
} finally {
setWaitCursor(false);
enableControls(true);
}
}
/**
* Setup to run the reasoner and start a thread
*/
private void runReasoner() {
isRunReasoner = true;
new Thread(this).start();
}
/**
* Setup to run the SPARQL query and start a thread
*/
private void runSPARQL() {
isRunReasoner = false;
new Thread(this).start();
}
/**
* Execute the steps to run the reasoner
*/
private void reasonerExecution() {
setStatus("Running reasoner");
results.setText("");
loadModel();
outputResults();
setStatus("Ready");
}
/**
* Execute the steps to run the SPARQL query
*/
private void sparqlExecution() {
int numResults;
setStatus("Running SPARQL");
setWaitCursor(true);
// sparqlResults.setText("");
numResults = callSparqlEngine();
setStatus("Number of Results: " + numResults);
}
/**
* Use the SPARQL engine and report the results
*
* @return The number of resulting rows
*/
private int callSparqlEngine() {
QueryExecution qe;
String serviceUrl;
ResultSet resultSet;
// Get the query
String queryString = sparqlInput.getText().trim();
// Create a Query instance
Query query = QueryFactory.create(queryString);
serviceUrl = ((String) sparqlServiceUrl.getSelectedItem()).trim();
// Execute the query and obtain results
if (sparqlServiceUrl.getSelectedIndex() == 0
|| serviceUrl.length() == 0) {
qe = QueryExecutionFactory.create(query, ontModel);
} else {
qe = QueryExecutionFactory.sparqlService(serviceUrl, query);
}
resultSet = qe.execSelect();
SparqlTableModel tableModel = (SparqlTableModel) sparqlResultsTable
.getModel();
tableModel.setupModel(resultSet);
// Important - free up resources used running the query
qe.close();
return tableModel.getRowCount();
}
/**
* Get the set of defined ontology file formats that the program can load as
* a CSV list String
*
* @return The known ontology file formats as a CSV list
*/
public final static String getFormatsAsCSV() {
return getArrayAsCSV(FORMATS);
}
/**
* Get the set of reasoning levels that the program will use as a CSV list
* String
*
* @return The known reasoning levels as a CSV list
*/
public final static String getReasoningLevelsAsCSV() {
return getArrayAsCSV(REASONING_LEVELS);
}
/**
* Create a CSV list from a String array
*
* @param array
* An array
* @return The array values in a CSV list
*/
public final static String getArrayAsCSV(String[] array) {
StringBuffer csv;
csv = new StringBuffer();
for (String value : array) {
if (csv.length() > 0) {
csv.append(", ");
}
csv.append(value);
}
return csv.toString();
}
/**
* Set the RDF file , where the ontology is located
*
* @param pRdfFile
* The file containing the ontology
*/
public void setRdfFile(File pRdfFile) {
rdfFile = pRdfFile;
setTitle();
}
/**
* Set the window title
*/
private void setTitle() {
String title;
title = "Semantic UI";
if (assertionLanguage != null) {
title += " - " + assertionLanguage;
}
if (rdfFile != null) {
title += " - " + rdfFile.getName();
}
setTitle(title);
}
/**
* Convert the ontology into a set of Strings representing the triples
*
* @return A Map containing Lists that relate subjects to objects and
* predicates
*/
private void outputResults() {
StringWriter writer;
Model tempModel;
LOGGER.debug("ontModelNoInference [" + ontModelNoInference + "]");
LOGGER.debug("ontModel [" + ontModel + "]");
tempModel = ontModel.difference(ontModelNoInference);
writer = new StringWriter();
tempModel.write(writer, assertionLanguage);
results.setText(writer.toString());
}
/**
* Create a model with a reasoner set based on the chosen reasoning level.
*
* @param reasoningLevel
* The reasoning level for this model
*
* @return The created ontology model
*/
private OntModel createModel(String reasoningLevelName) {
OntModel model;
int reasoningLevelIndex;
model = null;
LOGGER.debug("Create model using reasoning level: "
+ reasoningLevelName);
reasoningLevelIndex = getReasoningLevelIndex(reasoningLevelName);
LOGGER.debug("Reasoning level index: " + reasoningLevelIndex);
if (reasoningLevelIndex == 0) { // None
model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM);
} else if (reasoningLevelIndex == 1) { // RDFS
model = ModelFactory
.createOntologyModel(OntModelSpec.OWL_DL_MEM_RDFS_INF);
} else if (reasoningLevelIndex == 2) { // OWL
Reasoner reasoner = PelletReasonerFactory.theInstance().create();
Model infModel = ModelFactory.createInfModel(reasoner, ModelFactory
.createDefaultModel());
model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM,
infModel);
}
return model;
}
/**
* Obtain a text file containing a set of assertions. Load the assertions
* into the ontology model.
*/
private void loadModel() {
String modelFormat;
modelFormat = null;
if (language.getSelectedIndex() == 0) {
for (String format : FORMATS) {
try {
tryFormat(format);
modelFormat = format;
break;
} catch (Throwable throwable) {
LOGGER.debug("Error processing assertions as format: "
+ format, throwable);
}
}
} else {
try {
tryFormat(language.getSelectedItem().toString());
modelFormat = language.getSelectedItem().toString();
} catch (Throwable throwable) {
LOGGER.error("Error processing assertions as format: "
+ language.getSelectedItem().toString(), throwable);
}
}
if (modelFormat == null) {
if (language.getSelectedIndex() == 0) {
throw new IllegalStateException(
"The assertions cannot be loaded using known languages.\nTried: "
+ getFormatsAsCSV());
} else {
throw new IllegalStateException(
"The assertions cannot be loaded using the input format: "
+ language.getSelectedItem().toString());
}
} else {
LOGGER.info("Loaded assertions" + " using format: " + modelFormat);
}
assertionLanguage = modelFormat;
setTitle();
}
/**
* Attempt to load a set of assertions with the supplied format (e.g. N3,
* RDF/XML, etc)
*
* @param format
* The format to use, must be a value in the array FORMATS
* @throws UnsupportedEncodingException
* If the assertions cannot be loaded
*/
private void tryFormat(String format) throws UnsupportedEncodingException {
InputStream inputStream = null;
try {
inputStream = new ByteArrayInputStream(assertions.getText()
.getBytes("UTF-8"));
ontModelNoInference = createModel("NONE");
ontModelNoInference.read(inputStream, null, format.toUpperCase());
inputStream = new ByteArrayInputStream(assertions.getText()
.getBytes("UTF-8"));
ontModel = createModel(reasoningLevel.getSelectedItem().toString());
ontModel.read(inputStream, null, format.toUpperCase());
createTreeFromModel();
} finally {
try {
inputStream.close();
} catch (Throwable throwable) {
LOGGER.error("Error closing input file", throwable);
}
}
}
/**
* Build a tree representation of the semantic model
*
* TODO aggregate items from duplicate nodes
*/
private void createTreeFromModel() {
DefaultMutableTreeNode treeTopNode;
DefaultMutableTreeNode classesNode;
DefaultMutableTreeNode oneClassNode;
DefaultMutableTreeNode oneIndividualNode;
DefaultMutableTreeNode onePropertyNode;
OntClass ontClass;
Individual individual;
Statement statement;
Property property;
RDFNode rdfNode;
ExtendedIterator classesIterator;
ExtendedIterator individualsIterator;
StmtIterator stmtIterator;
treeTopNode = new DefaultMutableTreeNode("Model");
// Classes
classesNode = new DefaultMutableTreeNode("Classes");
treeTopNode.add(classesNode);
classesIterator = ontModel.listClasses();
while (classesIterator.hasNext()) {
ontClass = classesIterator.next();
if (ontClass.isAnon()) {
oneClassNode = new DefaultMutableTreeNode("Anonymous Class ("
+ ontClass.getId().getLabelString() + ")");
} else {
oneClassNode = new DefaultMutableTreeNode(ontClass
.getLocalName()
+ " (" + ontClass.getURI() + ")");
}
classesNode.add(oneClassNode);
// Individuals
individualsIterator = ontModel.listIndividuals(ontClass);
while (individualsIterator.hasNext()) {
individual = individualsIterator.next();
if (individual.isAnon()) {
oneIndividualNode = new DefaultMutableTreeNode(
"Anonymous Individual ("
+ individual.getId().getLabelString() + ")");
} else {
oneIndividualNode = new DefaultMutableTreeNode(individual
.getLocalName()
+ " (" + individual.getURI() + ")");
}
oneClassNode.add(oneIndividualNode);
// Properties (predicates) and Objects
stmtIterator = individual.listProperties();
while (stmtIterator.hasNext()) {
statement = stmtIterator.next();
property = statement.getPredicate();
rdfNode = statement.getObject();
if (property.isAnon()) {
onePropertyNode = new DefaultMutableTreeNode(
"Anonymous Property ("
+ property.getId().getLabelString()
+ ")");
} else {
onePropertyNode = new DefaultMutableTreeNode(property
.getLocalName()
+ " (" + property.getURI() + ")");
}
oneIndividualNode.add(onePropertyNode);
if (rdfNode.isLiteral()) {
onePropertyNode.add(new DefaultMutableTreeNode(
"Literal (" + statement.getString() + ")"));
} else {
onePropertyNode.add(new DefaultMutableTreeNode(
statement.getResource().getLocalName() + " ("
+ statement.getResource().getURI()
+ ")"));
}
}
}
}
ontModelTree.setModel(new DefaultTreeModel(treeTopNode));
}
/**
* Get the index position of the supplied reasoning level label
*
* @param reasonerName
* A reasoning level label
*
* @return The index position of the reasoning level. Will be equal to the
* constant UNKNOWN if the value cannot be found in the collection
* of known reasoning levels
*/
public final static int getReasoningLevelIndex(String reasonerName) {
return getIndexValue(REASONING_LEVELS, reasonerName);
}
/**
* Find a String value within an array of Strings. Return the index position
* where the value was found.
*
* @param array
* An array of string to search
* @param name
* The value to find in the array
*
* @return The position where the value was found in the array. Will be
* equal to the constant UNKNOWN if the value cannot be found in the
* collection of known reasoning levels
*/
public final static int getIndexValue(String[] array, String name) {
Integer indexValue;
indexValue = null;
for (int index = 0; index < array.length && indexValue == null; ++index) {
if (array[index].toUpperCase().equals(name.toUpperCase())) {
indexValue = index;
}
}
return indexValue == null ? UNKNOWN : indexValue;
}
/**
* Allow the user to select a file, which is expected to be an ontology, and
* then load the file.
*/
private void openOntologyFile() {
JFileChooser fileChooser;
File chosenFile;
fileChooser = new JFileChooser(new File("."));
fileChooser.showOpenDialog(this);
chosenFile = fileChooser.getSelectedFile();
if (chosenFile != null) {
loadOntologyFile(chosenFile);
} else {
JOptionPane.showMessageDialog(this, "No file to load",
"No File Selected", JOptionPane.WARNING_MESSAGE);
}
enableControls(true);
}
/**
* Load the provided file as an ontology replacing any assertions currently
* in the assertions text area.
*
* @param inputFile
* The file to load (should be an ontology)
*/
private void loadOntologyFile(File inputFile) {
BufferedReader reader;
String data;
StringBuffer allData;
reader = null;
allData = new StringBuffer();
try {
reader = new BufferedReader(new FileReader(inputFile));
while ((data = reader.readLine()) != null) {
allData.append(data);
allData.append('\n');
}
assertions.setText(allData.toString());
assertions.moveCaretPosition(0);
setStatus("Loaded file: " + inputFile.getName());
setRdfFile(inputFile);
} catch (IOException ioExc) {
setStatus("Unable to load file: " + inputFile.getName());
JOptionPane.showMessageDialog(this,
"Error: Unable to read file\n\n"
+ inputFile.getAbsolutePath() + "\n\n"
+ ioExc.getMessage(), "Error Reading File",
JOptionPane.ERROR_MESSAGE);
LOGGER.error("Unable to load the file: "
+ inputFile.getAbsolutePath(), ioExc);
} finally {
if (reader != null) {
try {
reader.close();
} catch (Throwable throwable) {
LOGGER.error("Unable to close input file", throwable);
}
}
}
}
/**
* Save the text from the assertions text area to a file Note that this is
* not the model and it may not be in an legal syntax for RDF triples. It is
* simply storing what the user has placed in the text area.
*
* @see writeOntologyModel
*/
private void saveAssertionsToFile() {
FileWriter out;
JFileChooser fileChooser;
File destinationFile;
boolean okayToWrite;
int choice;
out = null;
fileChooser = new JFileChooser();
if (rdfFile != null) {
fileChooser.setSelectedFile(rdfFile);
} else {
fileChooser.setSelectedFile(new File("."));
}
choice = fileChooser.showSaveDialog(this);
destinationFile = fileChooser.getSelectedFile();
// Did not click save, did not select a file or chose a directory
// So do not write anything
if (choice != JFileChooser.APPROVE_OPTION || destinationFile == null
|| (destinationFile.exists() && !destinationFile.isFile())) {
return; // EARLY EXIT!
}
okayToWrite = !destinationFile.exists();
if (!okayToWrite) {
int verifyOverwrite;
verifyOverwrite = JOptionPane.showConfirmDialog(this,
"The file exists: " + destinationFile.getName()
+ "\n\nOkay to overwrite?", "Overwrite File?",
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
okayToWrite = verifyOverwrite == JOptionPane.YES_OPTION;
}
if (okayToWrite) {
LOGGER.info("Write assertions to file, " + destinationFile
+ ", in format: " + assertionLanguage);
try {
out = new FileWriter(destinationFile, false);
out.write(assertions.getText());
} catch (IOException ioExc) {
LOGGER.error("Unable to write to file: " + destinationFile,
ioExc);
throw new RuntimeException("Unable to write output file ("
+ destinationFile + ")", ioExc);
} finally {
if (out != null) {
try {
out.close();
} catch (Throwable throwable) {
LOGGER.error("Failed to close output file: "
+ destinationFile, throwable);
throw new RuntimeException(
"Failed to close output file", throwable);
}
}
}
}
}
/**
* Get the name of the selected output format
*
* @return the name of the output format (e.g. N3, Turtle, RDF/XML)
*/
private String getSelectedOutputLanguage() {
int selectedItem;
selectedItem = 0;
for (int index = 1; selectedItem == 0
&& index < setupOutputAssertionLanguage.length; ++index) {
if (setupOutputAssertionLanguage[index].isSelected()) {
selectedItem = index;
}
}
return selectedItem == 0 ? assertionLanguage
: FORMATS[selectedItem - 1];
}
/**
* Insert standard prefixes in the assertions text area.
*
* The user must choose the format (syntax) to use.
*/
private void insertPrefixes() {
String whichFormat;
int formatIndex;
String[] formatsToChoose;
List formatsAvail;
StringBuffer prefixesToAdd;
JTextArea areaToUpdate;
formatsAvail = new ArrayList();
for (int format = 0; format < FORMATS.length; ++format) {
if (STANDARD_PREFIXES[format].length > 0) {
formatsAvail.add(FORMATS[format]);
}
}
// SPARQL is a special case - not an RDF serialization
formatsAvail.add("SPARQL (tab)");
formatsToChoose = new String[formatsAvail.size()];
for (int format = 0; format < formatsAvail.size(); ++format) {
formatsToChoose[format] = formatsAvail.get(format);
}
whichFormat = (String) JOptionPane.showInputDialog(this,
"Choose the format for the prefixes", "Choose Format",
JOptionPane.QUESTION_MESSAGE, null, formatsToChoose, null);
LOGGER.debug("Chosen format for prefixes: " + whichFormat);
if (whichFormat != null) {
formatIndex = getIndexValue(FORMATS, whichFormat);
// SPARQL - special case - not an RDF serialization format
if (formatIndex == UNKNOWN) {
formatIndex = STANDARD_PREFIXES.length - 1;
areaToUpdate = sparqlInput;
} else {
areaToUpdate = assertions;
}
LOGGER.debug("Chosen format index for prefixes: " + formatIndex);
if (formatIndex >= 0) {
String currentData;
currentData = areaToUpdate.getText();
prefixesToAdd = new StringBuffer();
for (int prefix = 0; prefix < STANDARD_PREFIXES[formatIndex].length; ++prefix) {
prefixesToAdd
.append(STANDARD_PREFIXES[formatIndex][prefix]);
prefixesToAdd.append('\n');
}
areaToUpdate.setText(prefixesToAdd.toString() + currentData);
}
}
}
/**
* Writes the triples to a data file.
*
* This writes the current model to the file. The current model is the last
* model successfully run through the reasoner. The output will be in the
* same language (N3, Turtle, RDF/XML) as the assertions input unless a
* specific language was set for output.
*
* @see saveAssertionsToFile
*/
private void writeOntologyModel() {
FileWriter out;
JFileChooser fileChooser;
File destinationFile;
boolean okayToWrite;
int choice;
out = null;
fileChooser = new JFileChooser();
if (rdfFile != null) {
fileChooser.setSelectedFile(rdfFile);
} else {
fileChooser.setSelectedFile(new File("."));
}
choice = fileChooser.showSaveDialog(this);
destinationFile = fileChooser.getSelectedFile();
// Did not click save, did not select a file or chose a directory
// So do not write anything
if (choice != JFileChooser.APPROVE_OPTION || destinationFile == null
|| (destinationFile.exists() && !destinationFile.isFile())) {
return; // EARLY EXIT!
}
okayToWrite = !destinationFile.exists();
if (!okayToWrite) {
int verifyOverwrite;
verifyOverwrite = JOptionPane.showConfirmDialog(this,
"The file exists: " + destinationFile.getName()
+ "\n\nOkay to overwrite?", "Overwrite File?",
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
okayToWrite = verifyOverwrite == JOptionPane.YES_OPTION;
}
if (okayToWrite) {
LOGGER.info("Write model to file, " + destinationFile
+ ", in format: " + assertionLanguage);
try {
out = new FileWriter(destinationFile, false);
if (setupOutputModelTypeAssertionsAndInferences.isSelected()) {
LOGGER
.info("Writing complete model (assertions and inferences)");
ontModel.write(out, getSelectedOutputLanguage()
.toUpperCase());
} else {
LOGGER.info("Writing assertions only");
ontModelNoInference.write(out, getSelectedOutputLanguage()
.toUpperCase());
}
} catch (IOException ioExc) {
LOGGER.error("Unable to write to file: " + destinationFile,
ioExc);
throw new RuntimeException("Unable to write output file ("
+ destinationFile + ")", ioExc);
} finally {
if (out != null) {
try {
out.close();
} catch (Throwable throwable) {
LOGGER.error("Failed to close output file: "
+ destinationFile, throwable);
throw new RuntimeException(
"Failed to close output file", throwable);
}
}
}
}
}
/**
* Presents a classic "About" box to the user displaying the current version
* of the application.
*/
private void about() {
StringBuffer message;
message = new StringBuffer();
message.append("Semantic UI\n\nVersion:");
message.append(VERSION);
message.append("\n\nDavid Read\n\n");
message.append("Jena Version: ");
message.append(getJenaVersion());
message.append("\n");
message.append("Pellet Version: ");
message.append(getPelletVersion());
JOptionPane.showMessageDialog(this, message.toString(),
"About Semantic UI", JOptionPane.INFORMATION_MESSAGE);
}
/**
* Get the version of the loaded Jena library
*
* @return The version of the Jena library
*/
private String getJenaVersion() {
return ARQ.VERSION;
}
/**
* Get the version of the loaded Pellet library
*
* @return The version of the Pellet library
*/
private String getPelletVersion() {
return VersionInfo.getInstance().getVersionString() + " ("
+ VersionInfo.getInstance().getReleaseDate() + ")";
}
/**
* End the application
*/
private void closeApplication() {
setVisible(false);
LOGGER.info("Shutdown");
System.exit(0);
}
@Override
public void windowActivated(WindowEvent arg0) {
}
@Override
public void windowClosed(WindowEvent arg0) {
}
@Override
public void windowClosing(WindowEvent arg0) {
closeApplication();
}
@Override
public void windowDeactivated(WindowEvent arg0) {
}
@Override
public void windowDeiconified(WindowEvent arg0) {
}
@Override
public void windowIconified(WindowEvent arg0) {
}
@Override
public void windowOpened(WindowEvent arg0) {
}
/**
* Executes the reasoner in response to action from any widget being
* monitored
*/
private class ReasonerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
runReasoner();
}
}
/**
* Executes the SPARQL query in response to action from any widget being
* monitored
*/
private class SparqlListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
runSPARQL();
}
}
/**
* Opens an ontology file
*/
private class FileOpenListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
openOntologyFile();
}
}
/**
* Exits the application
*/
private class EndApplicationListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
closeApplication();
}
}
/**
* Evaluates control status
*/
private class SparqlModelChoiceListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
enableControls(true);
}
}
/**
* Inserts standard prefixes
*/
private class InsertPrefixesListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
insertPrefixes();
}
}
/**
* Writes assertions to a file
*/
private class FileSaveListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
saveAssertionsToFile();
}
}
/**
* Expands the nodes in the tree representation of the model
*/
private class ExpandTreeListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
expandAll();
}
}
/**
* Collapses the nodes in the tree representation of the model
*/
private class CollapseTreeListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
collapseAll();
}
}
/**
* Allows the user to change the display font
*/
private class FontSetupListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
configureFont();
}
}
/**
* Writes the current model to an ontology file
*/
private class ModelSerializerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
writeOntologyModel();
}
}
/**
* Displays About dialog
*/
private class AboutListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
about();
}
}
/**
* Updates state of controls based on changes to text widgets being
* monitored
*/
private class UserInputListener implements KeyListener {
@Override
public void keyPressed(KeyEvent arg0) {
}
@Override
public void keyReleased(KeyEvent arg0) {
enableControls(true);
}
@Override
public void keyTyped(KeyEvent arg0) {
enableControls(true);
}
}
/**
* The execution point for the program. Creates an instance of the
* SemanticUI class.
*
* @param args
* The array of input arguments, not used yet
*/
public static void main(String[] args) {
org.apache.log4j.PropertyConfigurator.configure("log4j.properties");
new SemanticUI();
}
}
/**
* A basic table model for reporting the SPARQL results
*
* @author David Read
*/
@SuppressWarnings("serial")
class SparqlTableModel extends AbstractTableModel {
/**
* Logger Instance
*/
private static Logger LOGGER = Logger.getLogger(SparqlTableModel.class);
/**
* The result rows
*/
private List> rows = new ArrayList>();
/**
* The column labels
*/
private List columnLabels = new ArrayList();
/**
* Creates a new table model populating the model with the supplied results
*
* @param results
* A Jena query result set
*/
public SparqlTableModel(ResultSet results) {
setupModel(results);
}
/**
* Creates a new table model that contains no data
*/
public SparqlTableModel() {
}
/**
* Replaces the current data in the table model with the supplied data.
*
* @param results
* A Jena query result set
*/
public void setupModel(ResultSet results) {
rows.clear();
columnLabels.clear();
while (results.hasNext()) {
QuerySolution solution = results.next();
if (columnLabels.size() == 0) {
Iterator names;
names = solution.varNames();
while (names.hasNext()) {
columnLabels.add(names.next().toString());
LOGGER.debug("Added column label: "
+ columnLabels.get(columnLabels.size() - 1));
}
}
List row = new ArrayList();
for (String var : columnLabels) {
if (solution.get(var).isLiteral()) {
row.add("Lit: " + solution.getLiteral(var));
} else {
row.add(solution.getResource(var).toString());
}
}
rows.add(row);
LOGGER.debug("Added row with col count: " + row.size());
}
LOGGER.debug("Total rows in results: " + rows.size());
fireTableStructureChanged();
}
@Override
public int getColumnCount() {
// TODO Auto-generated method stub
return columnLabels.size();
}
@Override
public int getRowCount() {
// TODO Auto-generated method stub
return rows.size();
}
@Override
public Object getValueAt(int arg0, int arg1) {
// TODO Auto-generated method stub
return rows.get(arg0).get(arg1);
}
@Override
public String getColumnName(int col) {
return columnLabels.get(col);
}
}
/**
* FontChooser
*
* From: http://examples.oreilly.com/jswing2/code/ch12/FontChooser.java
*
* A font chooser that allows users to pick a font by name, size, style, and
* color. The color selection is provided by a JColorChooser pane. This dialog
* builds an AttributeSet suitable for use with JTextPane.
*
* DSR: Minor alteration to make all attributes private
*/
@SuppressWarnings("serial")
class FontChooser extends JDialog implements ActionListener {
private JColorChooser colorChooser;
private JComboBox fontName;
private JCheckBox fontBold, fontItalic;
private JTextField fontSize;
private JLabel previewLabel;
private SimpleAttributeSet attributes;
private Font newFont;
private Color newColor;
public FontChooser(Frame parent) {
super(parent, "Font Chooser", true);
setSize(450, 450);
attributes = new SimpleAttributeSet();
// Make sure that any way the user cancels the window does the right
// thing
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
closeAndCancel();
}
});
// Start the long process of setting up our interface
Container c = getContentPane();
JPanel fontPanel = new JPanel();
fontName = new JComboBox(new String[] { "TimesRoman", "Helvetica",
"Courier" });
fontName.setSelectedIndex(1);
fontName.addActionListener(this);
fontSize = new JTextField("12", 4);
fontSize.setHorizontalAlignment(SwingConstants.RIGHT);
fontSize.addActionListener(this);
fontBold = new JCheckBox("Bold");
fontBold.setSelected(true);
fontBold.addActionListener(this);
fontItalic = new JCheckBox("Italic");
fontItalic.addActionListener(this);
fontPanel.add(fontName);
fontPanel.add(new JLabel(" Size: "));
fontPanel.add(fontSize);
fontPanel.add(fontBold);
fontPanel.add(fontItalic);
c.add(fontPanel, BorderLayout.NORTH);
// Set up the color chooser panel and attach a change listener so that
// color
// updates get reflected in our preview label.
colorChooser = new JColorChooser(Color.black);
colorChooser.getSelectionModel().addChangeListener(
new ChangeListener() {
public void stateChanged(ChangeEvent e) {
updatePreviewColor();
}
});
c.add(colorChooser, BorderLayout.CENTER);
JPanel previewPanel = new JPanel(new BorderLayout());
previewLabel = new JLabel("Here's a sample of this font.");
previewLabel.setForeground(colorChooser.getColor());
previewPanel.add(previewLabel, BorderLayout.CENTER);
// Add in the Ok and Cancel buttons for our dialog box
JButton okButton = new JButton("Ok");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
closeAndSave();
}
});
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
closeAndCancel();
}
});
JPanel controlPanel = new JPanel();
controlPanel.add(okButton);
controlPanel.add(cancelButton);
previewPanel.add(controlPanel, BorderLayout.SOUTH);
// Give the preview label room to grow.
previewPanel.setMinimumSize(new Dimension(100, 100));
previewPanel.setPreferredSize(new Dimension(100, 100));
c.add(previewPanel, BorderLayout.SOUTH);
}
// Ok, something in the font changed, so figure that out and make a
// new font for the preview label
public void actionPerformed(ActionEvent ae) {
// Check the name of the font
if (!StyleConstants.getFontFamily(attributes).equals(
fontName.getSelectedItem())) {
StyleConstants.setFontFamily(attributes, (String) fontName
.getSelectedItem());
}
// Check the font size (no error checking yet)
if (StyleConstants.getFontSize(attributes) != Integer.parseInt(fontSize
.getText())) {
StyleConstants.setFontSize(attributes, Integer.parseInt(fontSize
.getText()));
}
// Check to see if the font should be bold
if (StyleConstants.isBold(attributes) != fontBold.isSelected()) {
StyleConstants.setBold(attributes, fontBold.isSelected());
}
// Check to see if the font should be italic
if (StyleConstants.isItalic(attributes) != fontItalic.isSelected()) {
StyleConstants.setItalic(attributes, fontItalic.isSelected());
}
// and update our preview label
updatePreviewFont();
}
// Get the appropriate font from our attributes object and update
// the preview label
protected void updatePreviewFont() {
String name = StyleConstants.getFontFamily(attributes);
boolean bold = StyleConstants.isBold(attributes);
boolean ital = StyleConstants.isItalic(attributes);
int size = StyleConstants.getFontSize(attributes);
// Bold and italic don’t work properly in beta 4.
Font f = new Font(name, (bold ? Font.BOLD : 0)
+ (ital ? Font.ITALIC : 0), size);
previewLabel.setFont(f);
}
// Get the appropriate color from our chooser and update previewLabel
protected void updatePreviewColor() {
previewLabel.setForeground(colorChooser.getColor());
// Manually force the label to repaint
previewLabel.repaint();
}
public Font getNewFont() {
return newFont;
}
public Color getNewColor() {
return newColor;
}
public AttributeSet getAttributes() {
return attributes;
}
public void closeAndSave() {
// Save font & color information
newFont = previewLabel.getFont();
newColor = previewLabel.getForeground();
// Close the window
setVisible(false);
}
public void closeAndCancel() {
// Erase any font information and then close the window
newFont = null;
newColor = null;
setVisible(false);
}
}