Java tutorial
/* * Copyright (C) 2014 by Array Systems Computing Inc. http://www.array.ca * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.s1tbx.dat.toolviews.Projects; import com.bc.ceres.swing.progress.ProgressMonitorSwingWorker; import org.esa.s1tbx.dat.dialogs.ProductSetDialog; import org.esa.snap.core.dataio.ProductIO; import org.esa.snap.core.dataio.ProductReader; import org.esa.snap.core.dataio.dimap.DimapProductConstants; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.datamodel.ProductManager; import org.esa.snap.core.datamodel.ProductNodeList; import org.esa.snap.core.dataop.downloadable.XMLSupport; import org.esa.snap.engine_utilities.db.CommonReaders; import org.esa.snap.engine_utilities.util.ProductFunctions; import org.esa.snap.engine_utilities.util.ResourceUtils; import org.esa.snap.graphbuilder.rcp.dialogs.GraphBuilderDialog; import org.esa.snap.graphbuilder.rcp.dialogs.PromptDialog; import org.esa.snap.graphbuilder.rcp.utils.FileFolderUtils; import org.esa.snap.rcp.SnapApp; import org.esa.snap.rcp.actions.file.SaveProductAsAction; import org.esa.snap.rcp.util.Dialogs; import org.esa.snap.ui.ModelessDialog; import org.esa.snap.ui.NewProductDialog; import org.esa.snap.ui.product.ProductSubsetDialog; import org.jdom2.Attribute; import org.jdom2.Document; import org.jdom2.Element; import javax.swing.SwingWorker; import java.awt.Frame; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Observable; import java.util.StringTokenizer; import java.util.Timer; import java.util.TimerTask; import java.util.Vector; /** * A Project helps to organize your data by storing all your work in one folder. * User: lveci * Date: Jan 23, 2008 */ public class Project extends Observable { private final static Project _instance = new Project(); private File projectFolder = null; private File projectFile = null; private ProductManager.Listener productManagerListener = null; private ProjectSubFolder projectSubFolders = null; private final static boolean SAVE_PROJECT = true; private final Timer timer = new Timer(); /** * @return The unique instance of this class. */ public static Project instance() { return _instance; } @Override public void finalize() throws Throwable { timer.cancel(); super.finalize(); } void notifyEvent(boolean saveProject) { setChanged(); notifyObservers(); clearChanged(); if (saveProject) SaveProject(); } private static void showProjectsView() { // final ExecCommand command = VisatApp.getApp().getCommandManager(). // getExecCommand("org.esa.s1tbx.dat.toolviews.Projects.ProjectsToolView.showCmd"); // command.execute(); } public void CreateNewProject() { final File file = FileFolderUtils.GetFilePath("Create Project", "xml", "xml", "myProject", "Project File", true); if (file != null) { final String prjName = file.getName(); final String folderName = prjName.substring(0, prjName.lastIndexOf('.')); final File prjFolder = new File(file.getParentFile(), folderName); if (!prjFolder.exists()) prjFolder.mkdir(); final File newProjectFile = new File(prjFolder, prjName); initProject(newProjectFile); addExistingOpenedProducts(); notifyEvent(SAVE_PROJECT); showProjectsView(); } } private void addExistingOpenedProducts() { final ProductManager prodman = SnapApp.getDefault().getProductManager(); final int numProducts = prodman.getProductCount(); for (int i = 0; i < numProducts; ++i) { addProductLink(prodman.getProduct(i)); } } private static boolean findSubFolders(final File currentFolder, final ProjectSubFolder projSubFolder) { final File[] files = currentFolder.listFiles(); boolean hasProducts = false; if (files == null) return false; for (File f : files) { if (f.isDirectory()) { if (!f.getName().endsWith(DimapProductConstants.DIMAP_DATA_DIRECTORY_EXTENSION)) { final ProjectSubFolder newProjFolder = projSubFolder.addSubFolder(f.getName()); if (findSubFolders(f, newProjFolder)) hasProducts = true; //else if(!newProjFolder.isCreatedByUser()) //projSubFolder.removeSubFolder(newProjFolder); } } else if (!projSubFolder.containsFile(f)) { boolean found = false; final ProjectSubFolder.FolderType folderType = projSubFolder.getFolderType(); if (folderType == ProjectSubFolder.FolderType.PRODUCT) { found = ProductFunctions.isValidProduct(f); } else if (folderType == ProjectSubFolder.FolderType.PRODUCTSET || folderType == ProjectSubFolder.FolderType.GRAPH) { found = f.getName().toLowerCase().endsWith(".xml"); } if (found) { hasProducts = true; final ProjectFile newFile = new ProjectFile(f, f.getName()); boolean added = projSubFolder.addFile(newFile); if (added) { newFile.setFolderType(folderType); } } } } return hasProducts; } public File getProjectFolder() { return projectFolder; } public File getProjectFile() { return projectFile; } String getProjectName() { final String name = projectFile.getName(); if (name.endsWith(".xml")) return name.substring(0, name.length() - 4); return name; } protected void initProject(final File file) { if (productManagerListener == null) { productManagerListener = new ProductManager.Listener() { @Override public void productAdded(ProductManager.Event event) { if (projectSubFolders == null) return; addProductLink(event.getProduct()); notifyEvent(SAVE_PROJECT); } @Override public void productRemoved(ProductManager.Event event) { Product product = event.getProduct(); //if (getSelectedProduct() == product) { // setSelectedProduct(product); //} //setProducts(VisatApp.getApp()); } }; SnapApp.getDefault().getProductManager().addListener(productManagerListener); } projectFile = file; projectFolder = file.getParentFile(); projectSubFolders = new ProjectSubFolder(projectFolder, getProjectName(), false, ProjectSubFolder.FolderType.ROOT); projectSubFolders.setRemoveable(false); final ProjectSubFolder productSetsFolder = new ProjectSubFolder(new File(projectFolder, "ProductSets"), "ProductSets", true, ProjectSubFolder.FolderType.PRODUCTSET); projectSubFolders.addSubFolder(productSetsFolder); productSetsFolder.setRemoveable(false); final ProjectSubFolder graphsFolder = new ProjectSubFolder(new File(projectFolder, "Graphs"), "Graphs", true, ProjectSubFolder.FolderType.GRAPH); projectSubFolders.addSubFolder(graphsFolder); graphsFolder.setRemoveable(false); final ProjectSubFolder productLinksFolder = projectSubFolders.addSubFolder("External Product Links"); productLinksFolder.setRemoveable(false); productLinksFolder.setFolderType(ProjectSubFolder.FolderType.PRODUCT); final ProjectSubFolder importedFolder = new ProjectSubFolder(new File(projectFolder, "Imported Products"), "Imported Products", true, ProjectSubFolder.FolderType.PRODUCT); projectSubFolders.addSubFolder(importedFolder); importedFolder.setRemoveable(false); final ProjectSubFolder processedFolder = new ProjectSubFolder(new File(projectFolder, "Processed Products"), "Processed Products", true, ProjectSubFolder.FolderType.PRODUCT); projectSubFolders.addSubFolder(processedFolder); processedFolder.setRemoveable(false); refreshProjectTree(); final String[] defaultFolders = getDefaultProjectFolders(); for (String folderName : defaultFolders) { final ProjectSubFolder newFolder = processedFolder.addSubFolder(folderName); newFolder.setCreatedByUser(true); } SnapApp.getDefault().getPreferences().put(SaveProductAsAction.PREFERENCES_KEY_LAST_PRODUCT_DIR, processedFolder.getPath().getAbsolutePath()); // start refresh timer for any outside changes to project folder startUpdateTimer(); } private static String[] getDefaultProjectFolders() { String defaultProjectFolders = System.getProperty("defaultProjectFolders"); if (defaultProjectFolders == null) { defaultProjectFolders = "Calibrated Products, Coregistered Products, Orthorectified Products"; } final List<String> folderNames = new ArrayList<String>(5); final StringTokenizer st = new StringTokenizer(defaultProjectFolders, ","); int length = st.countTokens(); for (int i = 0; i < length; i++) { folderNames.add(st.nextToken().trim()); } return folderNames.toArray(new String[folderNames.size()]); } private void startUpdateTimer() { timer.scheduleAtFixedRate(new TimerTask() { public void run() { if (IsProjectOpen()) { if (refreshProjectTree()) notifyEvent(SAVE_PROJECT); } } }, 2000, 1000 * 5); } private void addProductLink(final Product product) { final File productFile = product.getFileLocation(); if (productFile == null) return; if (projectSubFolders.containsFile(productFile)) return; refreshProjectTree(); if (projectSubFolders.containsFile(productFile)) return; final ProjectSubFolder productLinksFolder = projectSubFolders.addSubFolder("External Product Links"); ProjectSubFolder destFolder = productLinksFolder; final String[] formats = product.getProductReader().getReaderPlugIn().getFormatNames(); if (formats.length > 0) destFolder = productLinksFolder.addSubFolder(formats[0]); final ProjectFile newFile = new ProjectFile(productFile, product.getName()); destFolder.addFile(newFile); newFile.setFolderType(ProjectSubFolder.FolderType.PRODUCT); } public boolean refreshProjectTree() { boolean found = false; final ProjectSubFolder productSetsFolder = projectSubFolders.findFolder("ProductSets"); if (findSubFolders(productSetsFolder.getPath(), productSetsFolder)) found = true; pruneNonExistantFiles(productSetsFolder); final ProjectSubFolder graphsFolder = projectSubFolders.findFolder("Graphs"); if (findSubFolders(graphsFolder.getPath(), graphsFolder)) found = true; pruneNonExistantFiles(graphsFolder); final ProjectSubFolder importedFolder = projectSubFolders.findFolder("Imported Products"); if (findSubFolders(importedFolder.getPath(), importedFolder)) found = true; pruneNonExistantFiles(importedFolder); final ProjectSubFolder processedFolder = projectSubFolders.findFolder("Processed Products"); if (findSubFolders(processedFolder.getPath(), processedFolder)) found = true; pruneNonExistantFiles(processedFolder); return found; } private static void pruneNonExistantFiles(final ProjectSubFolder projSubFolder) { // check for files to remove final ProjectFile[] fileList = projSubFolder.getFileList() .toArray(new ProjectFile[projSubFolder.getFileList().size()]); for (ProjectFile projFile : fileList) { final File f = projFile.getFile(); if (!f.exists() || f.getName().endsWith(DimapProductConstants.DIMAP_DATA_DIRECTORY_EXTENSION)) { projSubFolder.removeFile(f); } } for (ProjectSubFolder subFolder : projSubFolder.getSubFolders()) { pruneNonExistantFiles(subFolder); } } public void createNewFolder(final ProjectSubFolder subFolder) { final PromptDialog dlg = new PromptDialog("New Folder", "Name", "", false); dlg.show(); if (dlg.IsOK()) { final ProjectSubFolder newFolder = subFolder.addSubFolder(dlg.getValue()); newFolder.setCreatedByUser(true); if (subFolder == projectSubFolders || subFolder.isPhysical()) newFolder.setPhysical(true); notifyEvent(SAVE_PROJECT); } } public void createNewProductSet(final ProjectSubFolder subFolder) { final String name = "ProductSet" + (subFolder.getFileList().size() + 1); final ProductSet prodSet = new ProductSet(new File(subFolder.getPath(), name)); final ProductSetDialog dlg = new ProductSetDialog("New ProductSet", prodSet); dlg.show(); if (dlg.IsOK()) { final ProjectFile newFile = new ProjectFile(prodSet.getFile(), prodSet.getName()); newFile.setFolderType(ProjectSubFolder.FolderType.PRODUCTSET); subFolder.addFile(newFile); notifyEvent(SAVE_PROJECT); refreshProjectTree(); } } public static void createNewGraph(final ProjectSubFolder subFolder) { final ModelessDialog dialog = new GraphBuilderDialog(SnapApp.getDefault().getAppContext(), "Graph Builder", "graph_builder"); dialog.show(); } public static void openFile(final ProjectSubFolder parentFolder, final File file) { if (parentFolder.getFolderType() == ProjectSubFolder.FolderType.PRODUCTSET) { ProductSet.OpenProductSet(file); } else if (parentFolder.getFolderType() == ProjectSubFolder.FolderType.GRAPH) { final GraphBuilderDialog dialog = new GraphBuilderDialog(SnapApp.getDefault().getAppContext(), "Graph Builder", "graph_builder"); dialog.show(); dialog.LoadGraph(file); } else if (parentFolder.getFolderType() == ProjectSubFolder.FolderType.PRODUCT) { //todo VisatApp.getApp().openProduct(file); } } public static void openSubset(final ProjectSubFolder parentFolder, final File prodFile) { try { final Product product = CommonReaders.readProduct(prodFile); if (product != null) { final Product subsetProduct = getProductSubset(product); if (subsetProduct != null) SnapApp.getDefault().getProductManager().addProduct(subsetProduct); } } catch (Exception e) { Dialogs.showError(e.getMessage()); } } public void importSubset(final ProjectSubFolder parentFolder, final File prodFile) { final ProductReader reader = ProductIO.getProductReaderForInput(prodFile); if (reader != null) { final ProjectSubFolder importedFolder = projectSubFolders.findFolder("Imported Products"); try { final Product product = reader.readProductNodes(prodFile, null); final Product subsetProduct = getProductSubset(product); if (subsetProduct != null) { final File destFile = new File(importedFolder.getPath(), subsetProduct.getName()); writeProduct(subsetProduct, destFile); } } catch (Exception e) { Dialogs.showError("Unable to import product:" + e.getMessage()); } } } private static Product getProductSubset(final Product product) { if (product != null) { final Frame mainFrame = SnapApp.getDefault().getMainFrame(); final ProductSubsetDialog productSubsetDialog = new ProductSubsetDialog(mainFrame, product); if (productSubsetDialog.show() == ProductSubsetDialog.ID_OK) { final ProductNodeList<Product> products = new ProductNodeList<Product>(); products.add(product); final NewProductDialog newProductDialog = new NewProductDialog(mainFrame, products, 0, true); newProductDialog.setSubsetDef(productSubsetDialog.getProductSubsetDef()); if (newProductDialog.show() == NewProductDialog.ID_OK) { final Product subsetProduct = newProductDialog.getResultProduct(); if (subsetProduct == null || newProductDialog.getException() != null) { Dialogs.showError("The product subset could not be created:\n" + newProductDialog.getException().getMessage()); } else { return subsetProduct; } } } } return null; } private static class ImportProducts extends ProgressMonitorSwingWorker { final File[] productFilesToOpen; final ProjectSubFolder importedFolder; ImportProducts(final File[] productFilesToOpen, final ProjectSubFolder importedFolder) { super(SnapApp.getDefault().getMainFrame(), "Writing..."); this.productFilesToOpen = productFilesToOpen; this.importedFolder = importedFolder; } @Override protected Object doInBackground(com.bc.ceres.core.ProgressMonitor pm) throws Exception { pm.beginTask("Importing", productFilesToOpen.length); if (importedFolder.getFolderType() == ProjectSubFolder.FolderType.PRODUCT) { for (File prodFile : productFilesToOpen) { final ProductReader reader = ProductIO.getProductReaderForInput(prodFile); if (reader != null) { try { final Product product = reader.readProductNodes(prodFile, null); if (product != null) { // special case for WSS products if (product.getProductType().equals("ASA_WSS_1P")) { throw new Exception("WSS products need to be debursted before saving as DIMAP"); } final File destFile = new File(importedFolder.getPath(), product.getName()); //todo VisatApp.getApp().writeProductImpl(product, destFile, "BEAM-DIMAP", false); } } catch (Exception e) { Dialogs.showError(e.getMessage()); } } pm.worked(1); } } pm.done(); return true; } } private void writeProduct(final Product product, final File destFile) { final SwingWorker worker = new SwingWorker() { @Override protected Object doInBackground() throws Exception { //todo VisatApp.getApp().writeProduct(product, destFile, "BEAM-DIMAP"); return null; } @Override public void done() { refreshProjectTree(); notifyEvent(SAVE_PROJECT); } }; worker.execute(); } public void ImportFileList(final File[] productFilesToOpen) { if (!IsProjectOpen()) { CreateNewProject(); } final ProjectSubFolder importedFolder = projectSubFolders.findFolder("Imported Products"); final ImportProducts worker = new ImportProducts(productFilesToOpen, importedFolder); worker.execute(); refreshProjectTree(); notifyEvent(SAVE_PROJECT); } public void deleteFolder(final ProjectSubFolder parentFolder, final ProjectSubFolder subFolder) { parentFolder.removeSubFolder(subFolder); notifyEvent(SAVE_PROJECT); } public void clearFolder(final ProjectSubFolder subFolder) { subFolder.clear(); notifyEvent(SAVE_PROJECT); } public void renameFolder(final ProjectSubFolder subFolder) { final PromptDialog dlg = new PromptDialog("Rename Folder", "Name", "", false); dlg.show(); if (dlg.IsOK()) { subFolder.renameTo(dlg.getValue()); notifyEvent(SAVE_PROJECT); } } public void removeFile(final ProjectSubFolder parentFolder, final File file) { parentFolder.removeFile(file); if (parentFolder.getFolderType() == ProjectSubFolder.FolderType.PRODUCTSET || parentFolder.getFolderType() == ProjectSubFolder.FolderType.GRAPH) file.delete(); else if (parentFolder.getFolderType() == ProjectSubFolder.FolderType.PRODUCT) { if (file.getName().endsWith(DimapProductConstants.DIMAP_HEADER_FILE_EXTENSION)) { final String pathStr = file.getAbsolutePath(); final File dataDir = new File(pathStr.substring(0, pathStr.length() - 4) + DimapProductConstants.DIMAP_DATA_DIRECTORY_EXTENSION); if (dataDir.exists()) { ResourceUtils.deleteFile(dataDir); file.delete(); } } else { file.delete(); } } notifyEvent(SAVE_PROJECT); } public ProjectSubFolder getProjectSubFolders() { return projectSubFolders; } public void CloseProject() { projectSubFolders = null; notifyEvent(false); } public boolean IsProjectOpen() { return projectSubFolders != null; } public void SaveProjectAs() { final File file = FileFolderUtils.GetFilePath("Save Project", "XML", "xml", getProjectName(), "Project File", true); if (file == null) return; projectFile = file; projectFolder = file.getParentFile(); SaveProject(); } public void SaveProject() { if (projectSubFolders == null) return; final Element root = new Element("Project"); root.setAttribute("name", getProjectName()); final Document doc = new Document(root); final Vector subFolders = projectSubFolders.getSubFolders(); for (Enumeration e = subFolders.elements(); e.hasMoreElements();) { final ProjectSubFolder folder = (ProjectSubFolder) e.nextElement(); final Element elem = folder.toXML(); root.addContent(elem); } XMLSupport.SaveXML(doc, projectFile.getAbsolutePath()); } public void LoadProject() { final File file = FileFolderUtils.GetFilePath("Load Project", "XML", "xml", "", "Project File", false); if (file == null) return; LoadProject(file); } public void LoadProject(final File file) { initProject(file); Document doc; try { doc = XMLSupport.LoadXML(file.getAbsolutePath()); } catch (IOException e) { Dialogs.showError("Unable to load " + file.toString() + ": " + e.getMessage()); return; } final Vector<ProjectSubFolder> folderList = new Vector<ProjectSubFolder>(30); final Vector<ProjectFile> prodList = new Vector<ProjectFile>(50); final Element root = doc.getRootElement(); final List children = root.getContent(); for (Object aChild : children) { if (aChild instanceof Element) { final Element child = (Element) aChild; if (child.getName().equals("subFolder")) { final Attribute attrib = child.getAttribute("name"); final ProjectSubFolder subFolder = projectSubFolders.addSubFolder(attrib.getValue()); subFolder.fromXML(child, folderList, prodList); } } } loadProducts(folderList, prodList); notifyEvent(false); showProjectsView(); } private static void loadProducts(final Vector<ProjectSubFolder> folderList, final Vector<ProjectFile> prodList) { final ProgressMonitorSwingWorker worker = new ProgressMonitorSwingWorker( SnapApp.getDefault().getMainFrame(), "Opening Project") { @Override protected Object doInBackground(com.bc.ceres.core.ProgressMonitor pm) throws Exception { pm.beginTask("Opening Project...", prodList.size()); try { for (int i = 0; i < prodList.size(); ++i) { final ProjectSubFolder subFolder = folderList.get(i); final ProjectFile projFile = prodList.get(i); final File prodFile = projFile.getFile(); if (ProductFunctions.isValidProduct(prodFile)) { subFolder.addFile(projFile); } pm.worked(1); } } finally { pm.done(); } return null; } }; worker.executeWithBlocking(); } }