diff --git a/src/main/java/lu/jpt/csparqltest/Main.java b/src/main/java/lu/jpt/csparqltest/Main.java index 204abaa..108fccc 100644 --- a/src/main/java/lu/jpt/csparqltest/Main.java +++ b/src/main/java/lu/jpt/csparqltest/Main.java @@ -1,125 +1,28 @@ package lu.jpt.csparqltest; -import java.text.ParseException; - import org.apache.log4j.PropertyConfigurator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import eu.larkc.csparql.core.engine.CsparqlEngine; -import eu.larkc.csparql.core.engine.CsparqlEngineImpl; -import eu.larkc.csparql.core.engine.CsparqlQueryResultProxy; -import lu.jpt.csparqltest.gui.TextObserverWindow; -import lu.jpt.csparqltest.misc.TestStreamGenerator; +import lu.jpt.csparqltest.gui.SimulationControlWindow; import lu.jpt.csparqltest.rentacar.RentACarSimulation; public class Main { - private static Logger logger = LoggerFactory.getLogger(Main.class); - public static TextObserverWindow observerWindow; + public static Logger logger = LoggerFactory.getLogger(Main.class); public static void main(String[] args) { - Main.observerWindow = new TextObserverWindow("Result observer window"); - - // Determines the time the engine will be run for - final long millisecondsToRun = 50 * 1000; - - // Load configuration for log4j + // Initialize a logger try { PropertyConfigurator.configure("./src/main/resources/log4j.properties"); } catch(Throwable t) { PropertyConfigurator.configure("/log4j.properties"); } - - // Instantiate and initialize engine - CsparqlEngine engine = new CsparqlEngineImpl(); - engine.initialize(true); - - // Add local background knowledge from file into graph - /* - try { - engine.putStaticNamedModel("http://example.org/carSimKnowledgeGraph", CsparqlUtils.serializeRDFFile("data/carSimulationABox.rdf")); - } catch (Exception e) { - logger.error(e.toString()); - logger.error(e.getStackTrace().toString()); - } - */ - - /* Use a SPARQL Query to update the local knowledge from code instead of using CONSTRUCT within the engine. - String updateQuery = "PREFIX : " - + "INSERT DATA " - + "{ GRAPH { :room :isConnectedTo :room2 } }"; - engine.execUpdateQueryOverDatasource(updateQuery); - */ - - - // Debugging: Needed to verify which engine is being used - logger.debug("CWD: " + System.getProperty("user.dir")); - logger.debug("Engine from: " + engine.getClass().getProtectionDomain().getCodeSource()); - - // Create and register stream generator at specific URI - //RentACarSimulation simulation = new RentACarSimulation(); - //engine.registerStream(simulation.getCarStream()); - //engine.registerStream(simulation.getDriverStream()); - TestStreamGenerator testStreamGenerator = new TestStreamGenerator("http://example.org"); - engine.registerStream(testStreamGenerator); - - // Run simulation that is feeding the streams - //Thread simulationThread = new Thread(simulation); - //simulationThread.start(); - Thread testGeneratorThread = new Thread(testStreamGenerator); - testGeneratorThread.start(); - - // Now build a query to run - interchangeable - String query = Main.getPatternANOTBCQuery(); - //String query = RentACarSimulation.getEventUsingBackgroundKnowledge(); - - // Create a result proxy by registering the query at the engine - CsparqlQueryResultProxy resultProxy = null; - try { - resultProxy = engine.registerQuery(query, true); - } catch (ParseException e) { - logger.error(e.toString()); - logger.error(e.getStackTrace().toString()); - } - - // Enable reasoning with rdfs rules from file and a tbox rdf file. - /*try { - engine.updateReasoner( - resultProxy.getSparqlQueryId(), - CsparqlUtils.fileToString("data/rdfs.rules"), - ReasonerChainingType.FORWARD, - CsparqlUtils.serializeRDFFile("data/carSimulationTBox.rdf") - ); - } catch(Exception e) { - e.printStackTrace(); - logger.error(e.toString()); - logger.error(e.getStackTrace().toString()); - }*/ - - // Add observer to query result proxy - resultProxy.addObserver(Main.observerWindow); - - // Let it all run for some time - try { - Thread.sleep(millisecondsToRun); - } catch (InterruptedException e) { - logger.error(e.getMessage(), e); - } - - // Unregister the resultProxy (and thus the query) from the engine - engine.unregisterQuery(resultProxy.getId()); - - // Softly stop the simulation and unregister its streams - //simulation.pleaseStopSimulation(); - //simulationThread.interrupt(); - //engine.unregisterStream(simulation.getCarStream().getIRI()); - //engine.unregisterStream(simulation.getDriverStream().getIRI()); - - testStreamGenerator.pleaseStop(); - testGeneratorThread.interrupt(); - engine.unregisterStream(testStreamGenerator.getIRI()); - + // Initialize SimulationContext and wire it up with its control window + SimulationContext simulationContext = new SimulationContext(); + @SuppressWarnings("unused") + SimulationControlWindow simulationControlWindow = new SimulationControlWindow(simulationContext); + // That's it, the program is now basically running on its own. } private static String getSPO() { diff --git a/src/main/java/lu/jpt/csparqltest/SimulationContext.java b/src/main/java/lu/jpt/csparqltest/SimulationContext.java new file mode 100644 index 0000000..3d36552 --- /dev/null +++ b/src/main/java/lu/jpt/csparqltest/SimulationContext.java @@ -0,0 +1,149 @@ +package lu.jpt.csparqltest; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; + +import eu.larkc.csparql.cep.api.RdfStream; +import eu.larkc.csparql.core.engine.CsparqlEngine; +import eu.larkc.csparql.core.engine.CsparqlEngineImpl; +import eu.larkc.csparql.core.engine.CsparqlQueryResultProxy; +import lu.jpt.csparqltest.gui.TextObserverWindow; +import lu.jpt.csparqltest.rentacar.RentACarSimulation; + +public class SimulationContext { + + // Internal simulation context + public enum SimulationState { UNINITIALIZED, INITIALIZED, RUNNING, PAUSED, SUSPENDED, TORNDOWN, ERROR}; + private SimulationState currentState; + + // C-SPARQL related + private CsparqlEngine engine; + private Collection registeredStreams; + private Collection queryResultProxies; + + // Custom simulation related + private RentACarSimulation simulation; + private Thread simulationThread; + + /** + * Constructor + */ + public SimulationContext() { + this.currentState = SimulationState.UNINITIALIZED; + this.setup(); + } + + + public void start() { + if(this.currentState != SimulationState.INITIALIZED) { + throw new RuntimeException("Action not allowed in this state!"); + } + simulationThread = new Thread(simulation); + simulationThread.start(); + this.currentState = SimulationState.RUNNING; + } + + public void pause() { + if(this.currentState != SimulationState.RUNNING) { + throw new RuntimeException("Action not allowed in this state!"); + } + // TODO: Implement pausing the generatorThread(s) + + this.currentState = SimulationState.PAUSED; + } + + public void resume() { + if(this.currentState != SimulationState.PAUSED) { + throw new RuntimeException("Action not allowed in this state!"); + } + // TODO: Implement resuming the generatorThread(s) + + this.currentState = SimulationState.RUNNING; + } + + public void suspend() { + if(this.currentState != SimulationState.RUNNING + && this.currentState != SimulationState.PAUSED) { + + throw new RuntimeException("Action not allowed in this state!"); + } + this.simulation.pleaseStopSimulation(); + this.simulationThread.interrupt(); + this.currentState = SimulationState.SUSPENDED; + } + + public void tearDown() { + if(this.currentState != SimulationState.SUSPENDED) { + throw new RuntimeException("Action not allowed in this state!"); + } + // Unregister all queries from the engine + for(CsparqlQueryResultProxy resultProxy : this.queryResultProxies) { + this.engine.unregisterQuery(resultProxy.getId()); + } + // Unregister all rdf streams from the engine + for(RdfStream eventStream : this.registeredStreams) { + this.engine.unregisterStream(eventStream.getIRI()); + } + this.currentState = SimulationState.TORNDOWN; + } + + public SimulationState getSimulationState() { + return this.currentState; + } + + private void setup() { + // Prepare collections for registered streams and query result proxies + this.registeredStreams = new ArrayList(); + this.queryResultProxies = new ArrayList(); + // Instantiate and initialize engine + engine = new CsparqlEngineImpl(); + // Initialize with true to allow use of timestamp function + this.engine.initialize(true); + // Debugging output + Main.logger.debug("CWD: " + System.getProperty("user.dir")); + Main.logger.debug("Engine from: " + engine.getClass().getProtectionDomain().getCodeSource()); + // Load local domain knowledge into its target graph + /* + try { + engine.putStaticNamedModel("http://example.org/carSimKnowledgeGraph", CsparqlUtils.serializeRDFFile("data/carSimulationABox.rdf")); + } catch (Exception e) { + Main.logger.error(e.toString()); + Main.logger.error(e.getStackTrace().toString()); + } + */ + // Note: This is how local domain knowledge can be updated during runtime: + /* Use a SPARQL Query to update the local knowledge from code instead of using CONSTRUCT within the engine. + String updateQuery = "PREFIX : " + + "INSERT DATA " + + "{ GRAPH { :room :isConnectedTo :room2 } }"; + this.engine.execUpdateQueryOverDatasource(updateQuery); + */ + // Spawn the whole simulation - this takes care of simulation-specific things + simulation = new RentACarSimulation(); + // Register all the event streams + // Register car event stream + RdfStream carStream = simulation.getCarStream(); + engine.registerStream(carStream); + this.registeredStreams.add(carStream); + // Register driver event stream + RdfStream driverStream = simulation.getDriverStream(); + engine.registerStream(driverStream); + this.registeredStreams.add(driverStream); + // Register all the queries and add result observers! + String query = RentACarSimulation.getEventsQuery(); + CsparqlQueryResultProxy resultProxy = null; + try { + resultProxy = engine.registerQuery(query, true); + } catch (ParseException e) { + Main.logger.error(e.toString()); + Main.logger.error(e.getStackTrace().toString()); + } + this.queryResultProxies.add(resultProxy); + resultProxy.addObserver(new TextObserverWindow("ResultProxy Observer Window")); + // Setup complete, ready to run. + this.currentState = SimulationState.INITIALIZED; + } + + +} diff --git a/src/main/java/lu/jpt/csparqltest/gui/SimulationControlWindow.java b/src/main/java/lu/jpt/csparqltest/gui/SimulationControlWindow.java new file mode 100644 index 0000000..e5d25be --- /dev/null +++ b/src/main/java/lu/jpt/csparqltest/gui/SimulationControlWindow.java @@ -0,0 +1,89 @@ +package lu.jpt.csparqltest.gui; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import lu.jpt.csparqltest.SimulationContext; + +public class SimulationControlWindow extends JFrame { + + private static final long serialVersionUID = 1L; + + private SimulationContext simulationContext; + + public SimulationControlWindow(SimulationContext simulationContext) { + this.simulationContext = simulationContext; + this.initializeWindow(); + } + + private void initializeWindow() { + final SimulationControlWindow simulationControlWindow = this; + this.setUndecorated(false); + this.setDefaultCloseOperation(EXIT_ON_CLOSE); + this.setTitle("Simulation control window"); + + Container contentPane = this.getContentPane(); + + JPanel buttonPanel = new JPanel(); + // Create start button + JButton startButton = new JButton("Start"); + startButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + simulationControlWindow.simulationContext.start(); + ((JButton) e.getSource()).setEnabled(false); + } + }); + buttonPanel.add(startButton); + // Create pause button + JButton pauseButton = new JButton("Pause"); + pauseButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JButton source = (JButton) e.getSource(); + if(source.getText().equals("Pause")) { + simulationControlWindow.simulationContext.pause(); + source.setText("Resume"); + } else { + simulationControlWindow.simulationContext.resume(); + source.setText("Pause"); + } + simulationControlWindow.pack(); + } + }); + buttonPanel.add(pauseButton); + // Create stop button + JButton stopButton = new JButton("Stop"); + stopButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + simulationControlWindow.simulationContext.suspend(); + ((JButton) e.getSource()).setEnabled(false); + } + }); + buttonPanel.add(stopButton); + // Create shutdown button + JButton shutdownButton = new JButton("Shutdown"); + shutdownButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + simulationControlWindow.simulationContext.tearDown(); + ((JButton) e.getSource()).setEnabled(false); + } + }); + buttonPanel.add(shutdownButton); + + // Add buttonPanel to contentPane + contentPane.add(buttonPanel, BorderLayout.CENTER); + + this.setVisible(true); + this.pack(); + } + +} diff --git a/src/main/java/lu/jpt/csparqltest/rentacar/RentACarSimulation.java b/src/main/java/lu/jpt/csparqltest/rentacar/RentACarSimulation.java index e9dfe57..2cc7d25 100644 --- a/src/main/java/lu/jpt/csparqltest/rentacar/RentACarSimulation.java +++ b/src/main/java/lu/jpt/csparqltest/rentacar/RentACarSimulation.java @@ -101,6 +101,7 @@ public class RentACarSimulation implements Runnable { this.runSimulation = false; } + public static String getEventsQuery() { return "REGISTER QUERY getEvents AS " + "PREFIX rdf: "