/* Copyright (C) 2001, 2007 United States Government as represented by
the Administrator of the National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.layers.rpf.wizard;
import gov.nasa.worldwind.util.wizard.DefaultPanelDescriptor;
import gov.nasa.worldwind.util.wizard.Wizard;
import gov.nasa.worldwind.util.wizard.WizardModel;
import gov.nasa.worldwind.util.FileTree;
import gov.nasa.worldwind.util.Logging;
import gov.nasa.worldwind.formats.rpf.RPFFrameFilename;
import gov.nasa.worldwind.formats.rpf.RPFDataSeries;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.io.FileFilter;
import java.util.*;
/**
* @author dcollins
* @version $Id: FileSearchPanelDescriptor.java 4857 2008-03-29 01:11:08Z dcollins $
*/
public class FileSearchPanelDescriptor extends DefaultPanelDescriptor
{
private ProgressPanel panelComponent;
private PropertyEvents propertyEvents;
private Thread workerThread;
public static final String IDENTIFIER = "gov.nasa.worldwind.rpf.wizard.FileSearchPanel";
public FileSearchPanelDescriptor()
{
this.panelComponent = new ProgressPanel();
this.propertyEvents = new PropertyEvents();
this.panelComponent.addPropertyChangeListener(this.propertyEvents);
setPanelIdentifier(IDENTIFIER);
setPanelComponent(this.panelComponent);
}
public Object getBackPanelDescriptor()
{
return FileChooserPanelDescriptor.IDENTIFIER;
}
public Object getNextPanelDescriptor()
{
return DataChooserPanelDescriptor.IDENTIFIER;
}
public void registerPanel(Wizard wizard)
{
WizardModel oldWizardModel = getWizardModel();
if (oldWizardModel != null)
oldWizardModel.removePropertyChangeListener(this.propertyEvents);
super.registerPanel(wizard);
WizardModel newWizardModel = getWizardModel();
if (newWizardModel != null)
newWizardModel.addPropertyChangeListener(this.propertyEvents);
}
public void aboutToDisplayPanel()
{
this.panelComponent.setTitle(RPFWizardUtil.makeLarger("Searching for Imagery"));
this.panelComponent.setProgressDescription1(" ");
this.panelComponent.setProgressDescription2(" ");
this.panelComponent.getProgressBar().setIndeterminate(false);
WizardModel model = getWizardModel();
if (model != null)
{
File selectedFile = RPFWizardUtil.getSelectedFile(model);
if (selectedFile != null)
{
StringBuilder sb = new StringBuilder();
sb.append("<br>");
sb.append("Searching ");
sb.append("\'").append(selectedFile.getAbsolutePath()).append(File.separator).append("...\'");
sb.append("<br>");
this.panelComponent.setDescription(RPFWizardUtil.makeBold(sb.toString()));
}
}
}
public void displayingPanel()
{
WizardModel model = getWizardModel();
if (model != null && !RPFWizardUtil.isFileListCurrent(model))
{
this.panelComponent.getProgressBar().setIndeterminate(true);
startWorkerThread(new Runnable() {
public void run() {
refreshFileList();
WizardModel model = getWizardModel();
if (model != null)
RPFWizardUtil.setFileListCurrent(model, true);
moveToNextPanel();
}
});
}
}
public void aboutToHidePanel()
{
killWorkerThread();
}
private void moveToNextPanel()
{
Wizard wizard = getWizard();
Object nextPanel = getNextPanelDescriptor();
if (wizard != null && nextPanel != null)
{
wizard.setCurrentPanelDescriptor(nextPanel);
}
}
private void selectedFileChanged()
{
WizardModel model = getWizardModel();
if (model != null)
{
RPFWizardUtil.setFileListCurrent(model, false);
}
}
private class PropertyEvents implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent evt) {
if (evt != null && evt.getPropertyName() != null) {
String propertyName = evt.getPropertyName();
if (propertyName.equals(RPFWizardUtil.SELECTED_FILE)) {
selectedFileChanged();
}
}
}
}
private void refreshFileList()
{
WizardModel model = getWizardModel();
if (model != null)
{
// Disable the "<Back" and "Next>" buttons.
boolean backEnabled = model.isBackButtonEnabled();
boolean nextEnabled = model.isNextButtonEnabled();
model.setBackButtonEnabled(false);
model.setNextButtonEnabled(false);
// Search for any RPF files under the selected file.
File selectedFile = RPFWizardUtil.getSelectedFile(model);
FileFilter rpfFilter = new AcceptRPFFilter();
FileFilter updateUIFilter = new UpdateDescriptionFilter(rpfFilter, this.panelComponent);
List<File> fileList = searchSelectedFile(selectedFile, updateUIFilter);
RPFWizardUtil.setFileList(model, fileList);
// Create FileSets from the search results (if any).
List<FileSet> fileSetList = makeFileSetList(fileList);
if (fileSetList != null)
{
makeDefaultSelections(fileSetList);
makeTitles(fileSetList);
sortFileSetList(fileSetList);
}
RPFWizardUtil.setFileSetList(model, fileSetList);
// Restore the previous state of the "<Back" buttons.
model.setBackButtonEnabled(backEnabled);
model.setNextButtonEnabled(nextEnabled);
}
}
private static class UpdateDescriptionFilter implements FileFilter {
private FileFilter delegate;
private ProgressPanel panel;
private UpdateDescriptionFilter(FileFilter delegate, ProgressPanel panel) {
this.delegate = delegate;
this.panel = panel;
}
public boolean accept(File pathname) {
if (!Thread.interrupted()) {
if (this.panel != null && pathname != null) {
String oldDescription = this.panel.getProgressDescription2();
String newDescription = pathname.getParent();
if (newDescription != null ? !newDescription.equals(oldDescription) : oldDescription != null) {
this.panel.setProgressDescription1(newDescription);
}
}
return this.delegate != null && this.delegate.accept(pathname);
}
return false;
}
}
private List<File> searchSelectedFile(File fileToSearch, FileFilter fileFilter)
{
if (Thread.interrupted())
return null;
List<File> fileList;
try
{
FileTree fileTree = new FileTree(fileToSearch);
fileTree.setMode(FileTree.FILES_ONLY);
fileList = fileTree.asList(fileFilter);
}
catch (Throwable t)
{
String message = String.format("Exception while searching file: %s", fileToSearch);
Logging.logger().log(java.util.logging.Level.SEVERE, message, t);
fileList = null;
}
return fileList;
}
private static class AcceptRPFFilter implements FileFilter {
public boolean accept(File pathname) {
if (pathname != null && pathname.getName() != null) {
String filename = pathname.getName().toUpperCase();
return RPFFrameFilename.isFilename(filename);
}
return false;
}
}
private List<FileSet> makeFileSetList(List<File> fileList)
{
List<FileSet> result = null;
if (fileList != null)
{
Map<String, FileSet> map = new HashMap<String, FileSet>();
for (File file : fileList)
{
try
{
String filename = file.getName().toUpperCase();
RPFFrameFilename rpfFilename = RPFFrameFilename.parseFilename(filename);
String id = rpfFilename.getDataSeriesCode();
FileSet set = map.get(id);
if (set == null)
{
set = new FileSet();
set.setIdentifier(id);
set.setFiles(new LinkedList<File>());
map.put(id, set);
}
set.getFiles().add(file);
}
catch (Exception e)
{
e.printStackTrace();
}
}
result = new ArrayList<FileSet>(map.values());
}
return result;
}
private void makeDefaultSelections(List<FileSet> fileSetList)
{
// If only one FileSet is available, select it.
if (fileSetList != null
&& fileSetList.size() == 1
&& fileSetList.get(0) != null)
{
fileSetList.get(0).setSelected(true);
}
}
private void makeTitles(Iterable<FileSet> fileSetList)
{
if (fileSetList != null)
{
for (FileSet set : fileSetList)
makeTitle(set);
}
}
private void makeTitle(FileSet set)
{
if (set != null && set.getIdentifier() != null)
{
String id = set.getIdentifier();
RPFDataSeries ds;
try
{
ds = RPFDataSeries.dataSeriesFor(id);
}
catch (Exception e)
{
e.printStackTrace();
ds = null;
}
if (ds != null)
{
StringBuilder sb = new StringBuilder();
sb.append(ds.dataSeries);
sb.append(" (");
sb.append(ds.seriesCode);
sb.append(")");
set.setTitle(sb.toString());
}
}
}
private void sortFileSetList(List<FileSet> fileSetList)
{
Comparator<FileSet> comparator = new Comparator<FileSet>() {
public int compare(FileSet o1, FileSet o2) {
// Don't care about ordering in this case.
if (o1 == null || o2 == null)
return 0;
String id1 = o1.getIdentifier();
String id2 = o2.getIdentifier();
// Don't care about ordering in this case.
if (id1 == null || id2 == null)
return 0;
RPFDataSeries ds1, ds2;
try
{
ds1 = RPFDataSeries.dataSeriesFor(id1);
ds2 = RPFDataSeries.dataSeriesFor(id2);
}
catch (Exception e)
{
e.printStackTrace();
ds1 = ds2 = null;
}
// Sort on the order the data series appears in the NITFS specification table,
// or if the data series cannot be identified, sort alphabetically.
return (ds1 != null && ds2 != null) ? ds1.compareTo(ds2) : id1.compareTo(id2);
}
};
Collections.sort(fileSetList, comparator);
}
private void startWorkerThread(Runnable runnable)
{
killWorkerThread();
this.workerThread = new Thread(runnable);
this.workerThread.start();
}
private void killWorkerThread()
{
if (this.workerThread != null && this.workerThread.isAlive())
this.workerThread.interrupt();
this.workerThread = null;
}
}