Skip to content

Commit

Permalink
Merge pull request CulverLab#104 from CulverLab/message-fixes
Browse files Browse the repository at this point in the history
Added cancel button to query, removed logout button, added success messages
  • Loading branch information
Chris-Schnaufer authored Jul 22, 2024
2 parents 9dd3f74 + 952d709 commit 9b465a3
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 27 deletions.
6 changes: 3 additions & 3 deletions Sanimal FX/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
<dependency>
<groupId>org.jfxtras</groupId>
<artifactId>jfxtras-controls</artifactId>
<version>11.0-r1-SNAPSHOT</version>
<version>17-r1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-imaging -->
<dependency>
Expand All @@ -112,13 +112,13 @@
<dependency>
<groupId>org.fxmisc.easybind</groupId>
<artifactId>easybind</artifactId>
<version>1.0.4-SNAPSHOT</version>
<version>1.0.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.controlsfx/controlsfx -->
<dependency>
<groupId>org.controlsfx</groupId>
<artifactId>controlsfx</artifactId>
<version>12.0.0-SNAPSHOT</version>
<version>11.2.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-validator/commons-validator -->
<dependency>
Expand Down
65 changes: 55 additions & 10 deletions Sanimal FX/src/main/java/controller/SanimalAnalysisController.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
Expand Down Expand Up @@ -83,6 +84,14 @@ public class SanimalAnalysisController implements Initializable
@FXML
public MaskerPane mpnQuerying;

// The Vbox with the query cancel parameters, used to hide the cancel query button
@FXML
public VBox vbxQueryCancel;

// The cancel query button
@FXML
public Button btnCancelQuery;

///
/// FXML bound fields end
///
Expand All @@ -92,6 +101,8 @@ public class SanimalAnalysisController implements Initializable
private Image standardArrow = new Image("/images/analysisWindow/arrowDivider.png");
private Image highlightedArrow = new Image("/images/analysisWindow/arrowDividerSelected.png");

private boolean queryCancelled = false;

/**
* Initialize sets up the analysis window and bindings
*
Expand Down Expand Up @@ -136,6 +147,7 @@ public void initialize(URL location, ResourceBundle resources)
this.lvwFilters.setItems(SanimalData.getInstance().getQueryEngine().getQueryFilters());

this.mpnQuerying.setVisible(false);
this.vbxQueryCancel.setVisible(false);
}

/**
Expand All @@ -145,7 +157,10 @@ public void initialize(URL location, ResourceBundle resources)
*/
public void query(ActionEvent actionEvent)
{
this.queryCancelled = false;

this.mpnQuerying.setVisible(true);
this.vbxQueryCancel.setVisible(true);

// Default 60s event interval
Integer eventInterval = 60;
Expand Down Expand Up @@ -181,16 +196,21 @@ protected List<String> call()
List<String> cloudAbsolutePaths = queryTask.getValue();

// Ask the user if they would like to continue to part 2 of the query where we retrieve metadata. This takes a while
Optional<ButtonType> buttonTypeOpt = SanimalData.getInstance().getErrorDisplay().showPopup(
Alert.AlertType.CONFIRMATION,
this.lvwFilters.getScene().getWindow(),
"Query Count",
null,
"This query will return " + cloudAbsolutePaths.size() + " results at approximately 6 results per second, continue?",
true);

// If they press OK, query, otherwise just jump out
if (buttonTypeOpt.isPresent() && buttonTypeOpt.get() == ButtonType.OK)
Optional<ButtonType> buttonTypeOpt = null;

if (this.queryCancelled == false)
{
buttonTypeOpt = SanimalData.getInstance().getErrorDisplay().showPopup(
Alert.AlertType.CONFIRMATION,
this.lvwFilters.getScene().getWindow(),
"Query Count",
null,
"This query will return " + cloudAbsolutePaths.size() + " results at approximately 6 results per second, continue?",
true);
}

// If not cancelled and they press OK, then query, otherwise just jump out
if (this.queryCancelled == false && buttonTypeOpt.isPresent() && buttonTypeOpt.get() == ButtonType.OK)
{
// Create a second task to perform the next query
Task<List<ImageEntry>> queryImageTask = new ErrorTask<List<ImageEntry>>()
Expand All @@ -213,15 +233,26 @@ protected List<ImageEntry> call()
visDrSandersonController.visualize(dataAnalyzer);
visCSVController.visualize(dataAnalyzer);
visDownloadController.visualize(dataAnalyzer);

// Hide the loading graphic
this.btnCancelQuery.setDisable(false);
this.btnCancelQuery.setGraphic(null);
// Hide the panes
this.mpnQuerying.setVisible(false);
this.vbxQueryCancel.setVisible(false);
});

// Execute the second query
SanimalData.getInstance().getSanimalExecutor().getQueuedExecutor().addTask(queryImageTask);
}
else
{
// Hide the loading graphic
this.btnCancelQuery.setDisable(false);
this.btnCancelQuery.setGraphic(null);
// Hide the panes
this.mpnQuerying.setVisible(false);
this.vbxQueryCancel.setVisible(false);
}

});
Expand All @@ -230,6 +261,20 @@ protected List<ImageEntry> call()
actionEvent.consume();
}

/**
* Called when the cancel query button is pressed
*
* @param actionEvent consumed
*/
public void queryCancel(ActionEvent actionEvent)
{
SanimalData.getInstance().getConnectionManager().cancelQuery();
this.queryCancelled = true;
this.btnCancelQuery.setGraphic(new ImageView(new Image("/images/mainMenu/loading.gif", 26, 26, true, true)));
this.btnCancelQuery.setDisable(true);
actionEvent.consume();
}

/**
* Called to add athe current filter to the analysis
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ public class SanimalHomeController implements Initializable
// The credits button
@FXML
public Button btnCredits;
// The logout button to disconnect from the Cloud
@FXML
public Button btnLogout;
// The exit button to close the program
@FXML
public Button btnExit;
Expand Down Expand Up @@ -78,7 +75,6 @@ public void initialize(URL location, ResourceBundle resources)
// Hide the logout button and text when not logged in
this.lblUsername.visibleProperty().bind(loggedIn);
this.btnCredits.visibleProperty().bind(loggedIn);
this.btnLogout.visibleProperty().bind(loggedIn);
this.btnExit.visibleProperty().bind(loggedIn);
}

Expand Down
46 changes: 45 additions & 1 deletion Sanimal FX/src/main/java/model/query/S3QueryExecute.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import model.SanimalData;

import org.apache.commons.io.FilenameUtils;
import java.lang.InterruptedException;
import java.util.function.BiFunction;
import java.util.ArrayList;
import java.util.concurrent.Semaphore;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.List;
Expand All @@ -26,6 +28,8 @@ public class S3QueryExecute
{
// The number of significant digits to use when comparing locations
private static Double LOCATION_DECIMAL_MAX_DIFFERENCE = 0.00001;
// Semaphore used to cancel queries
private static final Semaphore cancelQuery = new Semaphore(1, true);

/**
* Performs the query to filter collections and images
Expand All @@ -34,7 +38,7 @@ public class S3QueryExecute
* @param collections the list of collections to check
* @return the result set of found images
*/
public static S3QueryResultSet executeQuery(S3QueryBuilder queryBuilder, final List<ImageCollection> collections) throws InterruptedException, ExecutionException
public static S3QueryResultSet executeQuery(S3QueryBuilder queryBuilder, final List<ImageCollection> collections) throws InterruptedException, ExecutionException
{
S3QueryResultSet resultSet = new S3QueryResultSet();
List<S3QueryBuilderCondition> conditions = queryBuilder.getConditions();
Expand Down Expand Up @@ -72,12 +76,22 @@ class InternalResults
res.matches = matches;
allMatches.add(res);
}

if (S3QueryExecute.cancelQuery.availablePermits() == 0)
{
break;
}
}

return allMatches;
}
);

if (S3QueryExecute.cancelQuery.availablePermits() == 0)
{
throw new InterruptedException();
}

allFutures.add(queryFuture);
}

Expand Down Expand Up @@ -1399,4 +1413,34 @@ private static List<LocalDateTime> getDateValuesArray(final String value)

return valueList;
}

/**
* Cancels the current query
*/
public static void cancelQuery()
{
// Set the semaphore to cancel the query if it's not set already
S3QueryExecute.cancelQuery.tryAcquire();
}

/**
* Clears the canceling of queries
*/
public static void clearCancelQuery()
{
// Set the semaphore to cancel the query
if (S3QueryExecute.cancelQuery.availablePermits() == 0)
{
S3QueryExecute.cancelQuery.release();
}
}

/**
* Returns whether the query has been cancelled
*/
public static boolean hasCancelQuery()
{
// Set the semaphore to cancel the query
return S3QueryExecute.cancelQuery.availablePermits() == 0;
}
}
64 changes: 60 additions & 4 deletions Sanimal FX/src/main/java/model/s3/S3ConnectionManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,15 @@ public void uploadImages(ImageCollection collection, ImageDirectory directoryToW
delFile.delete();

}

// Showw success
SanimalData.getInstance().getErrorDisplay().showPopup(
Alert.AlertType.INFORMATION,
null,
"Success",
"Your upload has finished",
"Your images have been uploaded to S3!",
false);
}
}
catch (IOException e)
Expand Down Expand Up @@ -1324,6 +1333,15 @@ else if (!cloudImageEntry.getSpeciesPresent().isEmpty() && !cloudImageEntry.wasT
String remoteFilePath = String.join("/", uploadPath, FilenameUtils.getName(oneFile));
this.uploadFile(collectionBucket, remoteFilePath, oneFile);
}

// Showw success
SanimalData.getInstance().getErrorDisplay().showPopup(
Alert.AlertType.INFORMATION,
null,
"Success",
"Your update has finished",
"Your images have been updated to S3!",
false);
}
}
catch (Exception e)
Expand Down Expand Up @@ -1392,6 +1410,11 @@ public void retrieveAndInsertUploadList(ImageCollection collection, DoubleProper
false);
}
}

if (S3QueryExecute.hasCancelQuery() == true)
{
break;
}
}
}
}
Expand Down Expand Up @@ -1486,6 +1509,10 @@ public List<String> performQuery(S3Query queryBuilder, final List<ImageCollectio
{
try
{
// Clear any previous query cancel request
S3QueryExecute.clearCancelQuery();

// Go through the queries
List<String> collFilterIDs = queryBuilder.getCollectionIDs();
List<CompletableFuture<Void>> allFutures = new ArrayList<CompletableFuture<Void>>();
long collFilterIDLen = collFilterIDs.size();
Expand All @@ -1497,9 +1524,16 @@ public List<String> performQuery(S3Query queryBuilder, final List<ImageCollectio
if (loadColl)
{
CompletableFuture<Void> getFuture = CompletableFuture.supplyAsync(() -> {
DoubleProperty progress = new SimpleDoubleProperty(0.0);
this.retrieveAndInsertUploadList(oneCollection, progress);
oneCollection.setUploadsWereSynced(true);
if (S3QueryExecute.hasCancelQuery() == false)
{
DoubleProperty progress = new SimpleDoubleProperty(0.0);
this.retrieveAndInsertUploadList(oneCollection, progress);
if (S3QueryExecute.hasCancelQuery() == false)
{
// Only set this if the query was not cancelled before we finished
oneCollection.setUploadsWereSynced(true);
}
}
return null;
}
);
Expand All @@ -1508,13 +1542,27 @@ public List<String> performQuery(S3Query queryBuilder, final List<ImageCollectio
}
}

// Don't continue if query was cancelled
if (S3QueryExecute.hasCancelQuery() == true)
{
return Collections.emptyList();
}

if (allFutures.size() > 0)
{
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(allFutures.toArray(new CompletableFuture[allFutures.size()]));
combinedFuture.get();
}

S3QueryResultSet resultSet = S3QueryExecute.executeQuery(queryBuilder.build(), collections);
S3QueryResultSet resultSet = null;
try
{
resultSet = S3QueryExecute.executeQuery(queryBuilder.build(), collections);
}
catch (InterruptedException e)
{
// This exception is caused by the user cancelling the query, do nothing
}

List<String> matchingFilePaths = new ArrayList<>();

Expand Down Expand Up @@ -1549,6 +1597,14 @@ public List<String> performQuery(S3Query queryBuilder, final List<ImageCollectio
return Collections.emptyList();
}

/**
* Cancels the outstanding query
*/
public void cancelQuery()
{
S3QueryExecute.cancelQuery();
}

/**
* Given a list of cloud absolute paths, this fetches the metadata for each image and returns it as an image entry
*
Expand Down
10 changes: 10 additions & 0 deletions Sanimal FX/src/main/resources/view/SanimalAnalysis.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,14 @@
</items>
</SplitPane>
<MaskerPane fx:id="mpnQuerying" text="Performing Query..." progressVisible="true"/>
<VBox fx:id="vbxQueryCancel" spacing="5" alignment="CENTER">
<Button fx:id="btnCancelQuery" onAction="#queryCancel" VBox.vgrow="NEVER" text="Cancel">
<font>
<Font size="16"/>
</font>
<VBox.margin>
<Insets top="200"/>
</VBox.margin>
</Button>
</VBox>
</StackPane>
Loading

0 comments on commit 9b465a3

Please sign in to comment.