Skip to content

Robust IOPlugins #167

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>

<artifactId>scijava-common</artifactId>
<version>2.41.1-SNAPSHOT</version>
<version>3.0.0-SNAPSHOT</version>

<name>SciJava Common</name>
<description>SciJava Common is a shared library for SciJava software. It provides a plugin framework, with an extensible mechanism for service discovery, backed by its own annotation processor, so that plugins can be loaded dynamically. It is used by both ImageJ and SCIFIO.</description>
Expand Down
22 changes: 11 additions & 11 deletions src/main/java/org/scijava/io/AbstractIOPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,47 +40,47 @@
*
* @author Curtis Rueden
*/
public abstract class AbstractIOPlugin<D> extends AbstractHandlerPlugin<String>
implements IOPlugin<D>
public abstract class AbstractIOPlugin<D> extends
AbstractHandlerPlugin<Location> implements IOPlugin<D>
{

// -- IOPlugin methods --

@Override
public boolean supportsOpen(final String source) {
public boolean supportsOpen(final Location source) {
return false;
}

@Override
public boolean supportsSave(final String destination) {
public boolean supportsSave(final Location destination) {
return false;
}

@Override
public boolean supportsSave(final Object data, final String destination) {
public boolean supportsSave(final Object data, final Location destination) {
return supportsSave(destination) && getDataType().isInstance(data);
}

@Override
public D open(final String source) throws IOException {
public D open(final Location source) throws IOException {
throw new UnsupportedOperationException();
}

@Override
public void save(final D data, final String destination) throws IOException {
public void save(final D data, final Location destination) throws IOException {
throw new UnsupportedOperationException();
}

// -- Typed methods --

@Override
public boolean supports(final String descriptor) {
return supportsOpen(descriptor) || supportsSave(descriptor);
public boolean supports(final Location location) {
return supportsOpen(location) || supportsSave(location);
}

@Override
public Class<String> getType() {
return String.class;
public Class<Location> getType() {
return Location.class;
}

}
14 changes: 7 additions & 7 deletions src/main/java/org/scijava/io/DefaultIOService.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
*/
@Plugin(type = Service.class)
public final class DefaultIOService
extends AbstractHandlerService<String, IOPlugin<?>> implements IOService
extends AbstractHandlerService<Location, IOPlugin<?>> implements IOService
{

@Parameter
Expand All @@ -61,15 +61,15 @@ public final class DefaultIOService
// -- IOService methods --

@Override
public IOPlugin<?> getOpener(final String source) {
public IOPlugin<?> getOpener(final Location source) {
for (final IOPlugin<?> handler : getInstances()) {
if (handler.supportsOpen(source)) return handler;
}
return null;
}

@Override
public <D> IOPlugin<D> getSaver(final D data, final String destination) {
public <D> IOPlugin<D> getSaver(D data, Location destination) {
for (final IOPlugin<?> handler : getInstances()) {
if (handler.supportsSave(data, destination)) {
@SuppressWarnings("unchecked")
Expand All @@ -81,7 +81,7 @@ public <D> IOPlugin<D> getSaver(final D data, final String destination) {
}

@Override
public Object open(final String source) throws IOException {
public Object open(final Location source) throws IOException {
final IOPlugin<?> opener = getOpener(source);
if (opener == null) return null; // no appropriate IOPlugin

Expand All @@ -93,7 +93,7 @@ public Object open(final String source) throws IOException {
}

@Override
public void save(final Object data, final String destination)
public void save(final Object data, final Location destination)
throws IOException
{
final IOPlugin<Object> saver = getSaver(data, destination);
Expand All @@ -112,8 +112,8 @@ public Class<IOPlugin<?>> getPluginType() {
}

@Override
public Class<String> getType() {
return String.class;
public Class<Location> getType() {
return Location.class;
}

}
5 changes: 4 additions & 1 deletion src/main/java/org/scijava/io/DefaultRecentFileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,10 @@ public void initialize() {

@EventHandler
protected void onEvent(final IOEvent event) {
add(event.getDescriptor());
final Location loc = event.getLocation();
if (!(loc instanceof FileLocation)) return;
final FileLocation fileLoc = (FileLocation) loc;
add(fileLoc.getFile().getPath());
}

// -- Helper methods --
Expand Down
24 changes: 12 additions & 12 deletions src/main/java/org/scijava/io/IOPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,27 @@
* @see Plugin
* @see IOService
*/
public interface IOPlugin<D> extends HandlerPlugin<String> {
public interface IOPlugin<D> extends HandlerPlugin<Location> {

/** The type of data opened and/or saved by the plugin. */
Class<D> getDataType();

/** Checks whether the I/O plugin can open data from the given source. */
boolean supportsOpen(String source);
/** Checks whether the I/O plugin can open data from the given location. */
boolean supportsOpen(Location source);

/** Checks whether the I/O plugin can save data to the given destination. */
boolean supportsSave(String destination);
/** Checks whether the I/O plugin can save data to the given location. */
boolean supportsSave(Location destination);

/** Opens data from the given location. */
D open(Location source) throws IOException;

/**
* Checks whether the I/O plugin can save the given data to the specified
* destination.
* location.
*/
boolean supportsSave(Object data, String destination);

/** Opens data from the given source. */
D open(String source) throws IOException;
boolean supportsSave(Object data, Location destination);

/** Saves the given data to the specified destination. */
void save(D data, String destination) throws IOException;
/** Saves the given data to the specified location. */
void save(D data, Location destination) throws IOException;

}
31 changes: 13 additions & 18 deletions src/main/java/org/scijava/io/IOService.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,52 +43,47 @@
* @see DataHandleService
* @see Location
*/
public interface IOService extends HandlerService<String, IOPlugin<?>>,
public interface IOService extends HandlerService<Location, IOPlugin<?>>,
SciJavaService
{

/**
* Gets the most appropriate {@link IOPlugin} for opening data from the given
* source.
* location.
*/
IOPlugin<?> getOpener(String source);
IOPlugin<?> getOpener(Location source);

/**
* Gets the most appropriate {@link IOPlugin} for saving data to the given
* destination.
* location.
*/
<D> IOPlugin<D> getSaver(D data, String destination);
<D> IOPlugin<D> getSaver(D data, Location destination);

/**
* Loads data from the given source. For extensibility, the nature of the
* source is left intentionally general, but two common examples include file
* paths and URLs.
* Loads data from the given location.
* <p>
* The opener to use is automatically determined based on available
* {@link IOPlugin}s; see {@link #getOpener(String)}.
* {@link IOPlugin}s; see {@link #getOpener(Location)}.
* </p>
*
* @param source The source (e.g., file path) from which to data should be
* loaded.
* @param source The location from which to data should be loaded.
* @return An object representing the loaded data, or null if the source is
* not supported.
* @throws IOException if something goes wrong loading the data.
*/
Object open(String source) throws IOException;
Object open(Location source) throws IOException;

/**
* Saves data to the given destination. The nature of the destination is left
* intentionally general, but the most common example is a file path.
* Saves data to the given location.
* <p>
* The saver to use is automatically determined based on available
* {@link IOPlugin}s; see {@link #getSaver(Object, String)}.
* {@link IOPlugin}s; see {@link #getSaver(Object, Location)}.
* </p>
*
* @param data The data to be saved to the destination.
* @param destination The destination (e.g., file path) to which data should
* be saved.
* @param destination The destination location to which data should be saved.
* @throws IOException if something goes wrong saving the data.
*/
void save(Object data, String destination) throws IOException;
void save(Object data, Location destination) throws IOException;

}
3 changes: 2 additions & 1 deletion src/main/java/org/scijava/io/console/OpenArgument.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.scijava.console.AbstractConsoleArgument;
import org.scijava.console.ConsoleArgument;
import org.scijava.display.DisplayService;
import org.scijava.io.FileLocation;
import org.scijava.io.IOService;
import org.scijava.log.LogService;
import org.scijava.plugin.Parameter;
Expand Down Expand Up @@ -69,7 +70,7 @@ public void handle(final LinkedList<String> args) {
final String source = args.removeFirst();

try {
final Object o = ioService.open(source);
final Object o = ioService.open(new FileLocation(source));
displayService.createDisplay(o);
}
catch (IOException exc) {
Expand Down
15 changes: 5 additions & 10 deletions src/main/java/org/scijava/io/event/DataOpenedEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,17 @@

package org.scijava.io.event;

import org.scijava.io.Location;

/**
* An event indicating that data has been opened from a source.
* An event indicating that data has been opened from a location.
*
* @author Curtis Rueden
*/
public class DataOpenedEvent extends IOEvent {

public DataOpenedEvent(final String source, final Object data) {
super(source, data);
}

// -- DataOpenedEvent methods --

/** Gets the source from which data was opened. */
public String getSource() {
return getDescriptor();
public DataOpenedEvent(final Location location, final Object data) {
super(location, data);
}

}
11 changes: 3 additions & 8 deletions src/main/java/org/scijava/io/event/DataSavedEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,17 @@

package org.scijava.io.event;

import org.scijava.io.Location;

/**
* An event indicating that data has been saved to a destination.
*
* @author Curtis Rueden
*/
public class DataSavedEvent extends IOEvent {

public DataSavedEvent(final String destination, final Object data) {
public DataSavedEvent(final Location destination, final Object data) {
super(destination, data);
}

// -- DataSavedEvent methods --

/** Gets the destination to which data was saved. */
public String getDestination() {
return getDescriptor();
}

}
18 changes: 10 additions & 8 deletions src/main/java/org/scijava/io/event/IOEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
package org.scijava.io.event;

import org.scijava.event.SciJavaEvent;
import org.scijava.io.Location;

/**
* An event indicating that I/O (e.g., opening or saving) has occurred.
Expand All @@ -40,20 +41,20 @@
*/
public abstract class IOEvent extends SciJavaEvent {

/** The data descriptor (source or destination). */
private final String descriptor;
/** The data location (source or destination). */
private final Location location;

/** The data for which I/O took place. */
private final Object data;

public IOEvent(final String descriptor, final Object data) {
this.descriptor = descriptor;
public IOEvent(final Location location, final Object data) {
this.location = location;
this.data = data;
}

/** Gets the data descriptor (source or destination). */
public String getDescriptor() {
return descriptor;
/** Gets the data location (source or destination). */
public Location getLocation() {
return location;
}

/** Gets the data for which I/O took place. */
Expand All @@ -65,7 +66,8 @@ public Object getData() {

@Override
public String toString() {
return super.toString() + "\n\tdescriptor = " + data + "\n\tdata = " + data;
return super.toString() + "\n\tlocation = " + location + "\n\tdata = " +
data;
}

}
11 changes: 8 additions & 3 deletions src/main/java/org/scijava/script/io/ScriptIOPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
import java.io.IOException;

import org.scijava.io.AbstractIOPlugin;
import org.scijava.io.FileLocation;
import org.scijava.io.IOPlugin;
import org.scijava.io.Location;
import org.scijava.plugin.Parameter;
import org.scijava.plugin.Plugin;
import org.scijava.script.ScriptService;
Expand All @@ -59,13 +61,16 @@ public Class<String> getDataType() {
}

@Override
public boolean supportsOpen(final String source) {
public boolean supportsOpen(final Location source) {
if (scriptService == null) return false; // no service for opening scripts
return scriptService.canHandleFile(source);
// TODO: Update ScriptService to use Location instead of File.
if (!(source instanceof FileLocation)) return false;
final FileLocation loc = (FileLocation) source;
return scriptService.canHandleFile(loc.getFile());
}

@Override
public String open(final String source) throws IOException {
public String open(final Location source) throws IOException {
if (scriptService == null) return null; // no service for opening scripts
// TODO: Use the script service to open the file in the script editor.
return null;
Expand Down
Loading