package org.esa.snap.rcp.actions.file;
import com.bc.ceres.core.Assert;
import com.bc.ceres.core.ProgressMonitor;
import org.esa.snap.core.dataio.ProductIO;
import org.esa.snap.core.dataio.dimap.DimapProductConstants;
import org.esa.snap.core.datamodel.MetadataElement;
import org.esa.snap.core.datamodel.Product;
import org.esa.snap.core.datamodel.ProductNodeList;
import org.esa.snap.core.util.Debug;
import org.esa.snap.rcp.SnapApp;
import org.esa.snap.rcp.util.Dialogs;
import org.esa.snap.rcp.util.ProgressHandleMonitor;
import org.netbeans.api.progress.ProgressHandle;
import org.openide.util.Cancellable;
import org.openide.util.NbBundle;
import java.io.File;
import static org.esa.snap.rcp.preferences.general.WriteOptionsController.*;
/**
* @author Norman Fomferra
* @author Marco Peters
*/
@NbBundle.Messages({"CTL_WriteProductOperationName=Write Product"})
public class WriteProductOperation implements Runnable, Cancellable {
private final Product product;
private final Boolean incremental;
private final ProgressHandleMonitor pm;
private final File fileLocation;
private final String formatName;
private Boolean status;
public WriteProductOperation(Product product, Boolean incremental) {
this(product, product.getFileLocation(), DimapProductConstants.DIMAP_FORMAT_NAME, incremental);
}
public WriteProductOperation(Product product, File fileLocation, String formatName, Boolean incremental) {
Assert.notNull(product, "product");
Assert.notNull(fileLocation, "fileLocation");
Assert.notNull(formatName, "formatName");
this.product = product;
this.fileLocation = fileLocation;
this.formatName = formatName;
if (incremental != null) {
this.incremental = incremental;
} else {
this.incremental = SnapApp.getDefault().getPreferences().getBoolean(PREFERENCE_KEY_SAVE_INCREMENTAL,
DEFAULT_VALUE_SAVE_INCREMENTAL);
}
this.pm = ProgressHandleMonitor.create(Bundle.CTL_WriteProductOperationName(), this);
}
public Boolean getStatus() {
return status;
}
public ProgressHandle getProgressHandle() {
return pm.getProgressHandle();
}
@Override
public boolean cancel() {
Dialogs.Answer answer = Dialogs.requestDecision(Bundle.CTL_WriteProductOperationName(),
"Cancellation of writing may lead to an unreadable product.\n\n"
+ "Do you really want to cancel the write process?",
false, null);
return answer == Dialogs.Answer.YES;
}
@Override
public void run() {
boolean saveProductHeaders = SnapApp.getDefault().getPreferences().getBoolean(PREFERENCE_KEY_SAVE_PRODUCT_HEADERS,
DEFAULT_VALUE_SAVE_PRODUCT_HEADERS);
boolean saveProductHistory = SnapApp.getDefault().getPreferences().getBoolean(PREFERENCE_KEY_SAVE_PRODUCT_HISTORY,
DEFAULT_VALUE_SAVE_PRODUCT_HISTORY);
boolean saveADS = SnapApp.getDefault().getPreferences().getBoolean(PREFERENCE_KEY_SAVE_PRODUCT_ANNOTATIONS,
DEFAULT_VALUE_SAVE_PRODUCT_ANNOTATIONS);
MetadataElement metadataRoot = product.getMetadataRoot();
ProductNodeList<MetadataElement> metadataElementBackup = new ProductNodeList<>();
if (!saveProductHeaders) {
String[] headerNames = new String[]{
"MPH", "SPH",
"Earth_Explorer_Header", "Fixed_Header", "Variable_Header", "Specific_Product_Header",
"Global_Attributes", "GlobalAttributes", "Variable_Attributes"
};
for (String headerName : headerNames) {
MetadataElement element = metadataRoot.getElement(headerName);
metadataElementBackup.add(element);
metadataRoot.removeElement(element);
}
}
if (!saveProductHistory) {
final MetadataElement element = metadataRoot.getElement("History");
metadataElementBackup.add(element);
metadataRoot.removeElement(element);
}
if (!saveADS) {
final String[] names = metadataRoot.getElementNames();
for (final String name : names) {
if (name.endsWith("ADS") || name.endsWith("Ads") || name.endsWith("ads")) {
final MetadataElement element = metadataRoot.getElement(name);
metadataElementBackup.add(element);
metadataRoot.removeElement(element);
}
}
}
Boolean saveOk = writeProduct(product, fileLocation, formatName, incremental, pm);
if (saveOk != null && saveOk) {
product.setModified(false);
OpenProductAction.getRecentProductPaths().add(fileLocation.getPath());
} else {
if (metadataRoot != null) {
final MetadataElement[] elementsArray = new MetadataElement[metadataElementBackup.size()];
metadataElementBackup.toArray(elementsArray);
for (final MetadataElement metadataElement : elementsArray) {
metadataRoot.addElement(metadataElement);
}
}
}
status = saveOk;
}
private static Boolean writeProduct(Product product,
File file,
String formatName,
boolean incremental,
ProgressMonitor pm) {
Debug.assertNotNull(product);
try {
// todo - really add GPF dependency?!?
/*
if (product.getProductReader() instanceof OperatorProductReader) {
GPF.writeProduct(product, file, formatName, incremental, pm);
} else {
ProductIO.writeProduct(product, file, formatName, incremental, pm);
}
*/
ProductIO.writeProduct(product, file, formatName, incremental, pm);
return !pm.isCanceled() ? true : null;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
javax.swing.SwingUtilities.invokeLater(() -> Dialogs.showError("Writing failed", e.getMessage()));
return false;
}
}
}