/**
* DataCleaner (community edition)
* Copyright (C) 2014 Neopost - Customer Information Management
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.datacleaner.widgets;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.filechooser.FileFilter;
import org.apache.metamodel.util.Resource;
import org.datacleaner.util.DCDocumentListener;
import org.datacleaner.util.ExtensionFilter;
import org.datacleaner.util.WidgetFactory;
import org.datacleaner.util.convert.ResourceConverter.ResourceTypeHandler;
import org.jdesktop.swingx.JXTextField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
/**
* Generic {@link ResourceTypePresenter} that uses a simple text field to
* represent any {@link Resource} as per it's {@link ResourceTypeHandler}'s
* capability to create and parse paths.
*/
public class TextFieldResourceTypePresenter implements ResourceTypePresenter<Resource> {
private static final Logger logger = LoggerFactory.getLogger(TextFieldResourceTypePresenter.class);
private final ResourceTypeHandler<?> _resourceTypeHandler;
private final JXTextField _pathTextField;
private final List<Listener> _listeners = new ArrayList<>();
private final List<FileFilter> _fileFilters = new ArrayList<>();
public TextFieldResourceTypePresenter(final ResourceTypeHandler<?> resourceTypeHandler) {
_resourceTypeHandler = resourceTypeHandler;
_pathTextField = WidgetFactory.createTextField("Path");
_pathTextField.getDocument().addDocumentListener(new DCDocumentListener() {
@Override
protected void onChange(final DocumentEvent event) {
onPathChanged();
}
});
}
protected static void handleResourceCandidate(final Resource resource,
final ResourceTypePresenter<?> resourceTypePresenter, final List<ResourceTypePresenter.Listener> listeners,
final List<FileFilter> fileFilters) {
if (resource == null) {
// do nothing
notifyListeners(null, resourceTypePresenter, listeners);
return;
}
if (!fileFilters.isEmpty()) {
final FileFilter selectedFileFilter = fileFilters.get(0);
if (selectedFileFilter instanceof ExtensionFilter) {
final ExtensionFilter extensionFilter = (ExtensionFilter) selectedFileFilter;
if (!extensionFilter.accept(resource)) {
// TODO: do something?
}
}
}
// do this in a swing worker to avoid blocking the UI since it
// will often time require I/O which may take time
final SwingWorker<Resource, Void> worker = new SwingWorker<Resource, Void>() {
@Override
protected Resource doInBackground() throws Exception {
if (!resource.isExists()) {
return null;
}
return resource;
}
@Override
protected void done() {
Resource resource;
try {
resource = get();
} catch (final Exception e) {
resource = null;
}
notifyListeners(resource, resourceTypePresenter, listeners);
}
};
worker.execute();
}
private static void notifyListeners(final Resource resource, final ResourceTypePresenter<?> resourceTypePresenter,
final List<ResourceTypePresenter.Listener> listeners) {
for (final ResourceTypePresenter.Listener resourceSelectionListener : listeners) {
resourceSelectionListener.onResourceSelected(resourceTypePresenter, resource);
}
}
private void onPathChanged() {
final Resource resource;
final String path = _pathTextField.getText();
if (Strings.isNullOrEmpty(path)) {
resource = null;
} else {
resource = getResource();
}
handleResourceCandidate(resource, this, _listeners, _fileFilters);
}
@Override
public JComponent getWidget() {
return _pathTextField;
}
@Override
public Resource getResource() {
final String path = _pathTextField.getText();
try {
return _resourceTypeHandler.parsePath(path);
} catch (final Exception e) {
logger.debug("Failed to parse path '{}', returning null", path, e);
return null;
}
}
@Override
public void setResource(final Resource resource) {
final String path = _resourceTypeHandler.createPath(resource);
_pathTextField.setText(path);
}
@Override
public void addListener(final Listener listener) {
_listeners.add(listener);
}
@Override
public void removeListener(final Listener listener) {
_listeners.remove(listener);
}
@Override
public void addChoosableFileFilter(final FileFilter fileFilter) {
_fileFilters.add(fileFilter);
}
@Override
public void removeChoosableFileFilter(final FileFilter fileFilter) {
_fileFilters.remove(fileFilter);
}
@Override
public void setSelectedFileFilter(final FileFilter fileFilter) {
_fileFilters.remove(fileFilter);
_fileFilters.add(0, fileFilter);
}
}