Skip to content

Check if output file exists when exporting #2298

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 4, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public PluginParameters createParameters() {
FileParameterType.setKind(outputParameter, FileParameterType.FileParameterKind.SAVE);
FileParameterType.setFileFilters(outputParameter, getExportType());
FileParameterType.setWarnOverwrite(outputParameter, true);
parameters.addParameter(outputParameter);
parameters.addParameter(outputParameter);

if (includeSpatialReference()) {
final PluginParameter<SingleChoiceParameterValue> spatialReferenceParameter = SingleChoiceParameterType.build(SPATIAL_REFERENCE_PARAMETER_ID, SpatialReferenceParameterValue.class);
Expand Down Expand Up @@ -161,7 +161,7 @@ public PluginParameters createParameters() {
final ReadableGraph readableGraph = activeGraph.getReadableGraph();
try {
final ParameterValue pv = params.get(master.getId()).getSingleChoice();
if (pv instanceof ElementTypeParameterValue elementTypeParameterValue){
if (pv instanceof ElementTypeParameterValue elementTypeParameterValue) {
final GraphElementType elementType = elementTypeParameterValue.getGraphElementType();
switch (elementType) {
case TRANSACTION:
Expand Down Expand Up @@ -462,11 +462,11 @@ public void read(final GraphReadMethods graph, final PluginInteraction interacti
default -> throw new PluginException(PluginNotificationLevel.ERROR, "Invalid element type");
}

try {
try {
//Check for valid path
if (isValidPath(output)) {
exportGeo(parameters, GraphNode.getGraphNode(graph.getId()).getDisplayName(), shapes, attributes, output);
}
exportGeo(parameters, GraphNode.getGraphNode(graph.getId()).getDisplayName(), shapes, attributes, output);
}
} catch (final IOException ex) {
throw new PluginException(PluginNotificationLevel.ERROR, ex);
}
Expand All @@ -478,18 +478,26 @@ public void read(final GraphReadMethods graph, final PluginInteraction interacti
ConstellationLoggerHelper.SUCCESS
);
}
private boolean isValidPath(File output) {
if(StringUtils.isEmpty(output.getPath())) {

protected boolean isValidPath(File output) {
if (StringUtils.isEmpty(output.getPath())) {
NotifyDisplayer.display("Invalid output file provided, cannot be empty", NotifyDescriptor.ERROR_MESSAGE);
return false;
}
if(output.isDirectory() || (!output.isDirectory()
if (output.isDirectory() || (!output.isDirectory()
&& output.getParentFile() != null && output.getParentFile().exists())) {
return true;
} else {
NotifyDisplayer.display("Invalid file path", NotifyDescriptor.ERROR_MESSAGE);
return false;
}
}
}
}

protected boolean doesFileExist(final File output) {
if (Boolean.TRUE.toString().equalsIgnoreCase(System.getProperty("java.awt.headless"))) {
return false;
}
// if file exists
return output.isFile();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
import au.gov.asd.tac.constellation.plugins.Plugin;
import au.gov.asd.tac.constellation.plugins.PluginInfo;
import au.gov.asd.tac.constellation.plugins.PluginType;
import static au.gov.asd.tac.constellation.plugins.importexport.geospatial.AbstractGeoExportPlugin.OUTPUT_PARAMETER_ID;
import static au.gov.asd.tac.constellation.plugins.importexport.geospatial.AbstractGeoExportPlugin.SPATIAL_REFERENCE_PARAMETER_ID;
import au.gov.asd.tac.constellation.plugins.parameters.ParameterChange;
import au.gov.asd.tac.constellation.plugins.parameters.PluginParameters;
import au.gov.asd.tac.constellation.plugins.parameters.types.FileParameterType;
import au.gov.asd.tac.constellation.plugins.parameters.types.ParameterValue;
import au.gov.asd.tac.constellation.plugins.templates.PluginTags;
import au.gov.asd.tac.constellation.utilities.file.FileExtensionConstants;
Expand All @@ -28,6 +31,8 @@
import java.io.IOException;
import java.util.Map;
import javafx.stage.FileChooser.ExtensionFilter;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;

Expand All @@ -41,6 +46,36 @@
@NbBundle.Messages("ExportToGeoPackagePlugin=Export to GeoPackage")
public class ExportToGeoPackagePlugin extends AbstractGeoExportPlugin {

@Override
public PluginParameters createParameters() {

final PluginParameters parametersCreated = super.createParameters();

// Add "listener" on output parameter to check file overwrite
parametersCreated.addController(OUTPUT_PARAMETER_ID, (master, params, change) -> {
final String output = params.get(master.getId()).getStringValue();
final File file = new File(output);
FileParameterType.FileParameterValue fileParamValue = (FileParameterType.FileParameterValue) params.get(master.getId()).getParameterValue();
// do a doesFileExist check if value changed, path is valid and filechooser dialog not previously opened
if (change == ParameterChange.VALUE && super.isValidPath(file) && !fileParamValue.isFileChooserSelected()) {
if (doesFileExist(new File(output))) {
String msg = String.format("The file %s already exists. Do you want to replace the existing file?", file.getName());
final NotifyDescriptor nd = new NotifyDescriptor.Confirmation(msg, "Overwrite file", NotifyDescriptor.YES_NO_CANCEL_OPTION, NotifyDescriptor.QUESTION_MESSAGE);
if (DialogDisplayer.getDefault().notify(nd) == NotifyDescriptor.YES_OPTION) {
return;
} else {
params.get(master.getId()).setError(String.format("The file %s already exists.", file.getName()));
}
}
} else if (change == ParameterChange.ERROR) {
params.get(master.getId()).getParameterValue().setStringValue(output);
// If an error occurs, assume the user has typed in the inputbox
fileParamValue.setFileChooserSelected(false);
}
});
return parametersCreated;
}

@Override
protected ExtensionFilter getExportType() {
return new ExtensionFilter("GeoPackage", FileExtensionConstants.GEO_PACKAGE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ public static class FileParameterValue extends ParameterValue {
private ExtensionFilter filter;
private boolean acceptAllFileFilterUsed;
private boolean warnOverwrite;
private boolean fileChooserSelected;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a boolean, could we instead hold a list of filenames that the user has clicked "Yes" to overwrite the file.
Using the file chooser would always add an entry to the list (even if it's not overwriting an existing file).
Manually modifying the filename afterwards should check if the new filename is in the list ... if not, check if the filename matches an existing file on the machine and if so then display the overwrite warning.
If the user clicks on "yes" to overwrite, then add that filename to the list.
Note it should not clear the list if there's an error in the path while the user is typing a new filename.


/**
* Constructs a new FileParameterValue
Expand All @@ -251,6 +252,7 @@ public FileParameterValue() {
filter = null;
acceptAllFileFilterUsed = false;
warnOverwrite = false;
fileChooserSelected = false;
}

/**
Expand All @@ -265,6 +267,7 @@ public FileParameterValue(final List<String> files) {
filter = null;
acceptAllFileFilterUsed = false;
warnOverwrite = false;
fileChooserSelected = false;
}

/**
Expand All @@ -278,6 +281,7 @@ public FileParameterValue(final FileParameterValue fpv) {
filter = fpv.filter;
acceptAllFileFilterUsed = fpv.acceptAllFileFilterUsed;
warnOverwrite = fpv.warnOverwrite;
fileChooserSelected = fpv.fileChooserSelected;
}

/**
Expand All @@ -293,6 +297,7 @@ public boolean set(final List<File> newFiles) {
final List<File> nf = newFiles != null ? newFiles : Collections.emptyList();
files.clear();
nf.forEach(f -> files.add(f.getAbsolutePath()));
setFileChooserSelected(true);
return true;
}

Expand Down Expand Up @@ -379,6 +384,23 @@ public void setWarningOverwrite(final boolean b) {
public boolean isWarningOverwriteUsed() {
return warnOverwrite;
}

/**
* Check to see if save button has already been selected.
* @return the fileChooserSelected
*/
public boolean isFileChooserSelected() {
return fileChooserSelected;
}

/**
* @param fileChooserSelected the fileChooserSelected to set
*/
public void setFileChooserSelected(final boolean fileChooserSelected) {
this.fileChooserSelected = fileChooserSelected;
}



@Override
public String validateString(final String s) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,18 @@ public void testToString() {
final FileParameterValue fileValue2 = new FileParameterValue(Arrays.asList("file1", "file2", "file3"));
assertEquals(fileValue2.toString(), "file1;file2;file3");
}

/**
* Test of setFileChooserSelected method, of class FileParameterValue.
*/
@Test
public void testIsFileChooserSelected() {
System.out.println("isFileChooserSelected");

final PluginParameter<FileParameterValue> fileParam = FileParameterType.build("My File");
assertEquals(fileParam.getParameterValue().isFileChooserSelected(), false);

fileParam.getParameterValue().setFileChooserSelected(true);
assertEquals(fileParam.getParameterValue().isFileChooserSelected(), true);
}
}