use of au.gov.asd.tac.constellation.views.dataaccess.tasks.WaitForQueriesToCompleteTask in project constellation by constellation-app.
the class ExecuteListener method handle.
/**
* Handles the click of the execute button in the data access view.
* <p/>
* If the execute button was in the "Go" state then it will iterate through
* all the tabs and run the enabled and valid plugins.
* <p/>
* If the execute button was in the "Stop" state then cancel any running plugins.
*
* @param event the event triggered by clicking the execute button
*/
@Override
public void handle(final ActionEvent event) {
// When no graph present, create a new one
if (DataAccessPaneState.getCurrentGraphId() == null && dataAccessPane.getDataAccessTabPane().hasActiveAndValidPlugins()) {
// Create new graph
final NewDefaultSchemaGraphAction graphAction = new NewDefaultSchemaGraphAction();
graphAction.actionPerformed(null);
Graph newActiveGraph = null;
// Wait while graph is getting made
while (newActiveGraph == null) {
newActiveGraph = GraphManager.getDefault().getActiveGraph();
}
// Set the state's current graph ID to the ID of the new graph
DataAccessPaneState.setCurrentGraphId(newActiveGraph.getId());
}
// Run the selected queries
final ObservableList<Tab> tabs = dataAccessPane.getDataAccessTabPane().getTabPane().getTabs();
if (CollectionUtils.isNotEmpty(tabs) && DataAccessPaneState.isExecuteButtonIsGo()) {
// Change the execute button to "Stop" and do not disable because it is now running
dataAccessPane.setExecuteButtonToStop(false);
// Set the state for the current graph state to running queries
DataAccessPaneState.setQueriesRunning(true);
// Check to see if an output dir exists. Non exisiting dirs do not prevent the
// plugins running, just triggers a notification
final File outputDir = DataAccessPreferenceUtilities.getDataAccessResultsDirEx();
if (outputDir != null && outputDir.isDirectory()) {
StatusDisplayer.getDefault().setStatusText(String.format(STATUS_MESSAGE_FORMAT, outputDir.getAbsolutePath()));
} else if (outputDir != null) {
NotificationDisplayer.getDefault().notify(RESULTS_DIR_NOT_FOUND_TITLE, ERROR_ICON, String.format(RESULTS_DIR_NOT_FOUND_MSG, outputDir.getAbsolutePath()), null);
}
// Save the current data access view state
PluginExecution.withPlugin(new SimplePlugin(SAVE_STATE_PLUGIN_NAME) {
@Override
protected void execute(final PluginGraphs graphs, final PluginInteraction interaction, final PluginParameters parameters) throws InterruptedException, PluginException {
DataAccessUtilities.saveDataAccessState(dataAccessPane.getDataAccessTabPane().getTabPane(), GraphNode.getGraph(DataAccessPaneState.getCurrentGraphId()));
}
}).executeLater(null);
// Run the plugins from each tab. The barrier is the plugin run futures
// from the previous tab. When the tab is run, it has the option to
// wait for the previous tab to complete.
List<Future<?>> barrier = null;
for (final Tab tab : tabs) {
LOGGER.log(Level.INFO, String.format("Running tab: %s", tab.getText()));
barrier = DataAccessTabPane.getQueryPhasePane(tab).runPlugins(barrier);
}
// Asynchronously start the task that waits for all the plugins to complete.
// Once they are complete this task will perform cleanup.
CompletableFuture.runAsync(new WaitForQueriesToCompleteTask(dataAccessPane, DataAccessPaneState.getCurrentGraphId()), dataAccessPane.getParentComponent().getExecutorService());
LOGGER.info("Plugins run.");
} else {
// The execute button is in a "Stop" state. So cancel any running plugins.
DataAccessPaneState.getRunningPlugins().keySet().forEach(running -> running.cancel(true));
// Nothing is running now, so change the execute button to "Go".
dataAccessPane.setExecuteButtonToGo(false);
}
// Disables all plugins in the plugin pane
if (DataAccessPreferenceUtilities.isDeselectPluginsOnExecuteEnabled()) {
deselectAllPlugins();
}
}
use of au.gov.asd.tac.constellation.views.dataaccess.tasks.WaitForQueriesToCompleteTask in project constellation by constellation-app.
the class DataAccessTabPane method runTabs.
/**
* Run the given range of tabs inclusively. As each tab is run, the jobs from
* the previous tab are passed so that it can block if necessary until they
* are complete.
* <p/>
* Before returning a {@link WaitForQueriesToCompleteTask} will be started
* that will deal with the clean up of the run once it is complete.
*
* @param firstTab the first tab to be run
* @param lastTab the last tab to be run
*/
public void runTabs(final int firstTab, final int lastTab) {
// Change execute button to stop but do not disable
getDataAccessPane().setExecuteButtonToStop(false);
// Need to take a copy for when it changes while this thread is still running
final String activeGraphId = GraphManager.getDefault().getActiveGraph().getId();
DataAccessPaneState.setQueriesRunning(activeGraphId, true);
// TODO This was being called every time runPlugins is called but can't
// see the point..could break!!!
storeParameterValues();
List<Future<?>> barrier = null;
for (int i = firstTab; i <= lastTab; i++) {
final Tab tab = getTabPane().getTabs().get(i);
LOGGER.log(Level.INFO, String.format("Running tab: %s", tab.getText()));
barrier = getQueryPhasePane(tab).runPlugins(barrier);
}
CompletableFuture.runAsync(() -> new WaitForQueriesToCompleteTask(getDataAccessPane(), activeGraphId), getDataAccessPane().getParentComponent().getExecutorService());
}
use of au.gov.asd.tac.constellation.views.dataaccess.tasks.WaitForQueriesToCompleteTask in project constellation by constellation-app.
the class ExecuteListenerNGTest method handle_sunny_days.
@Test
public void handle_sunny_days() {
// Set the results directory
final File tmpDir = new File(System.getProperty("java.io.tmpdir"));
DataAccessPreferenceUtilities.setDataAccessResultsDir(tmpDir);
// Setting this to true ensures that active plugins are de-selected at the end
DataAccessPreferenceUtilities.setDeselectPluginsOnExecute(true);
// We don't set the current graph ID in the state but ensure that there
// active and valid plugins in the tab pane so that a new graph is created
// on the fly
when(dataAccessTabPane.hasActiveAndValidPlugins()).thenReturn(true);
graphNodeMockedStatic.when(() -> GraphNode.getGraph(anyString())).thenReturn(activeGraph);
// Set up our fake tab pane
final Tab tab1 = mock(Tab.class);
final Tab tab2 = mock(Tab.class);
when(tabPane.getTabs()).thenReturn(FXCollections.observableArrayList(tab1, tab2));
final QueryPhasePane queryPhasePane1 = mock(QueryPhasePane.class);
final QueryPhasePane queryPhasePane2 = mock(QueryPhasePane.class);
dataAccessTabPaneMockedStatic.when(() -> DataAccessTabPane.getQueryPhasePane(tab1)).thenReturn(queryPhasePane1);
dataAccessTabPaneMockedStatic.when(() -> DataAccessTabPane.getQueryPhasePane(tab2)).thenReturn(queryPhasePane2);
// Tab 1 does not have enabled plugins and tab 2 does. This is testing the deselect
// plugin code. The deselection should not happen on tab 1 because it has no enabled
// plugins
dataAccessTabPaneMockedStatic.when(() -> DataAccessTabPane.tabHasEnabledPlugins(tab1)).thenReturn(false);
dataAccessTabPaneMockedStatic.when(() -> DataAccessTabPane.tabHasEnabledPlugins(tab2)).thenReturn(true);
// Because tab 1 is not enabled de-selection should happen on pane 2 and 3, but
// not pane 1.
final DataSourceTitledPane dataSourceTitledPane1 = mock(DataSourceTitledPane.class);
when(queryPhasePane1.getDataAccessPanes()).thenReturn(List.of(dataSourceTitledPane1));
final DataSourceTitledPane dataSourceTitledPane2 = mock(DataSourceTitledPane.class);
final DataSourceTitledPane dataSourceTitledPane3 = mock(DataSourceTitledPane.class);
when(queryPhasePane2.getDataAccessPanes()).thenReturn(List.of(dataSourceTitledPane2, dataSourceTitledPane3));
// Set up the plugin running. Tab 1 is run first which returns a future. That future
// is then passed in when tab 2 is run.
final List<Future<?>> barrier1 = List.of(CompletableFuture.completedFuture("First tab run"));
doReturn(barrier1).when(queryPhasePane1).runPlugins(null);
doReturn(null).when(queryPhasePane2).runPlugins(barrier1);
final ActionEvent event = mock(ActionEvent.class);
try (MockedConstruction<WaitForQueriesToCompleteTask> waitForMockedConstruction = Mockito.mockConstruction(WaitForQueriesToCompleteTask.class, (waitForMock, cntxt) -> {
assertEquals(cntxt.arguments(), List.of(dataAccessPane, GRAPH_ID));
})) {
executeListener.handle(event);
// There was not current graph set during the test setup. So we
// should see one construction of the graph action to create on.
assertEquals(graphActionMockedConstruction.constructed().size(), 1);
// Verify the execute button is changed to "Stop" and the status
// displayer is sent some text describing the action success
verify(dataAccessPane).setExecuteButtonToStop(false);
verify(statusDisplayer).setStatusText("Data access results will be written to " + tmpDir.getAbsolutePath());
// Verify the current state is saved before the plugins are run
utilitiesMockedStatic.verify(() -> DataAccessUtilities.saveDataAccessState(tabPane, activeGraph));
verify(pluginExecution).executeLater(null);
// Verify the plugins are run
verify(queryPhasePane1).runPlugins(or(anyList(), isNull()));
verify(queryPhasePane2).runPlugins(or(anyList(), isNull()));
verify(queryPhasePane1).runPlugins(null);
verify(queryPhasePane2).runPlugins(barrier1);
// Verify that the wait and clean up task is started
assertEquals(waitForMockedConstruction.constructed().size(), 1);
completableFutureMockedStatic.verify(() -> CompletableFuture.runAsync(same(waitForMockedConstruction.constructed().get(0)), any(ExecutorService.class)));
// Verify that the correct plugins are de-selected
verifyNoInteractions(dataSourceTitledPane1);
verify(dataSourceTitledPane2).validityChanged(false);
verify(dataSourceTitledPane3).validityChanged(false);
verifyNoInteractions(event);
// Verify that the state for the current graph is that queries are running
assertTrue(DataAccessPaneState.isQueriesRunning());
}
}
use of au.gov.asd.tac.constellation.views.dataaccess.tasks.WaitForQueriesToCompleteTask in project constellation by constellation-app.
the class DataAccessTabPaneNGTest method runTabs.
@Test
public void runTabs() {
final String graphId = "graphId";
try (final MockedStatic<GraphManager> graphManagerMockedStatic = Mockito.mockStatic(GraphManager.class);
final MockedStatic<DataAccessTabPane> datPaneMockedStatic = Mockito.mockStatic(DataAccessTabPane.class);
final MockedStatic<CompletableFuture> futureMockedStatic = Mockito.mockStatic(CompletableFuture.class, Mockito.CALLS_REAL_METHODS)) {
// Set up the active graph
final GraphManager graphManager = mock(GraphManager.class);
final Graph graph = mock(Graph.class);
graphManagerMockedStatic.when(GraphManager::getDefault).thenReturn(graphManager);
when(graphManager.getActiveGraph()).thenReturn(graph);
when(graph.getId()).thenReturn(graphId);
// No need to actually call, storeParameterValues. We will just verify
// that it is called.
doNothing().when(dataAccessTabPane).storeParameterValues();
// Set up our fake tab pane
final TabPane tabPane = mock(TabPane.class);
final Tab tab1 = mock(Tab.class);
final Tab tab2 = mock(Tab.class);
final Tab tab3 = mock(Tab.class);
final Tab tab4 = mock(Tab.class);
final Tab tab5 = mock(Tab.class);
doReturn(tabPane).when(dataAccessTabPane).getTabPane();
when(tabPane.getTabs()).thenReturn(FXCollections.observableArrayList(tab1, tab2, tab3, tab4, tab5));
// No need for a different query pane per tab, so just return the same
// one for all of them
final QueryPhasePane queryPhasePane = mock(QueryPhasePane.class);
datPaneMockedStatic.when(() -> DataAccessTabPane.getQueryPhasePane(any(Tab.class))).thenReturn(queryPhasePane);
final List<Future<?>> barrier1 = List.of(CompletableFuture.completedFuture("Future 1 Complete"));
final List<Future<?>> barrier2 = List.of(CompletableFuture.completedFuture("Future 2 Complete"));
final List<Future<?>> barrier3 = List.of(CompletableFuture.completedFuture("Future 3 Complete"));
when(queryPhasePane.runPlugins(null)).thenReturn(barrier1);
when(queryPhasePane.runPlugins(barrier1)).thenReturn(barrier2);
when(queryPhasePane.runPlugins(barrier2)).thenReturn(barrier3);
futureMockedStatic.when(() -> CompletableFuture.runAsync(any(Runnable.class), any(ExecutorService.class))).thenAnswer(iom -> {
WaitForQueriesToCompleteTask task = iom.getArgument(0);
assertEquals(task.getDataAccessPane(), dataAccessPane);
assertEquals(task.getGraphId(), graphId);
return null;
});
dataAccessTabPane.runTabs(1, 3);
verify(dataAccessTabPane).storeParameterValues();
verify(dataAccessPane).setExecuteButtonToStop(false);
verify(dataAccessTabPane).storeParameterValues();
datPaneMockedStatic.verify(() -> DataAccessTabPane.getQueryPhasePane(tab1), never());
datPaneMockedStatic.verify(() -> DataAccessTabPane.getQueryPhasePane(tab2));
datPaneMockedStatic.verify(() -> DataAccessTabPane.getQueryPhasePane(tab3));
datPaneMockedStatic.verify(() -> DataAccessTabPane.getQueryPhasePane(tab4));
datPaneMockedStatic.verify(() -> DataAccessTabPane.getQueryPhasePane(tab5), never());
// Verify that run plugins was called only 3 times
verify(queryPhasePane, times(1)).runPlugins(isNull());
verify(queryPhasePane, times(2)).runPlugins(any(List.class));
// Verify that the futures of the last run is passed into the next
verify(queryPhasePane).runPlugins(null);
verify(queryPhasePane).runPlugins(barrier1);
verify(queryPhasePane).runPlugins(barrier2);
// Verify the query is running state has been set to true
assertTrue(DataAccessPaneState.isQueriesRunning(graphId));
}
}
use of au.gov.asd.tac.constellation.views.dataaccess.tasks.WaitForQueriesToCompleteTask in project constellation by constellation-app.
the class ExecuteListenerNGTest method handle_results_dir_does_not_exist.
@Test
public void handle_results_dir_does_not_exist() {
// Because the DataAccessPreferenceUtilities setter has null and non-dir
// checks we have to manually add this into the preferences.
final File tmpDir = new File("/SOMETHING_THAT_WOULD_NEVER_EXIST");
Preferences prefs = NbPreferences.forModule(DataAccessPreferenceUtilities.class);
prefs.put("saveDataDir", tmpDir.getAbsolutePath());
// Set this preference to false so that plugins are not de-selected at the end
DataAccessPreferenceUtilities.setDeselectPluginsOnExecute(false);
// Set the current graph ID so the code doesn't try to create one
DataAccessPaneState.setCurrentGraphId(GRAPH_ID);
// Set up our fake tab pane
final Tab tab1 = mock(Tab.class);
when(tabPane.getTabs()).thenReturn(FXCollections.observableArrayList(tab1));
final QueryPhasePane queryPhasePane1 = mock(QueryPhasePane.class);
dataAccessTabPaneMockedStatic.when(() -> DataAccessTabPane.getQueryPhasePane(tab1)).thenReturn(queryPhasePane1);
dataAccessTabPaneMockedStatic.when(() -> DataAccessTabPane.tabHasEnabledPlugins(tab1)).thenReturn(true);
final DataSourceTitledPane dataSourceTitledPane1 = mock(DataSourceTitledPane.class);
when(queryPhasePane1.getDataAccessPanes()).thenReturn(List.of(dataSourceTitledPane1));
final ActionEvent event = mock(ActionEvent.class);
try (MockedConstruction<WaitForQueriesToCompleteTask> waitForMockedConstruction = Mockito.mockConstruction(WaitForQueriesToCompleteTask.class, (waitForMock, cntxt) -> {
assertEquals(cntxt.arguments(), List.of(dataAccessPane, GRAPH_ID));
})) {
executeListener.handle(event);
// So the directory the results are meant to be written to doesn't exist,
// verify that the notifier is displayed.
verify(notificationDisplayer).notify("Save raw results", UserInterfaceIconProvider.ERROR.buildIcon(16, ConstellationColor.CHERRY.getJavaColor()), "Results directory /SOMETHING_THAT_WOULD_NEVER_EXIST does not exist", null);
// No need to verify everything. Just make sure the main parts are still
// executed to show that the plugins are still run after the error
verify(pluginExecution).executeLater(null);
verify(queryPhasePane1).runPlugins(null);
completableFutureMockedStatic.verify(() -> CompletableFuture.runAsync(same(waitForMockedConstruction.constructed().get(0)), any(ExecutorService.class)));
// Verify that the plugins are not de-selected
verifyNoInteractions(dataSourceTitledPane1);
}
}
Aggregations