Skip to content
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

Use Location in the I/O API #395

Merged
merged 6 commits into from
Aug 13, 2020
Merged
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 @@ -5,7 +5,7 @@
<parent>
<groupId>org.scijava</groupId>
<artifactId>pom-scijava</artifactId>
<version>28.0.0</version>
<version>29.2.1</version>
<relativePath />
</parent>

Expand Down
51 changes: 48 additions & 3 deletions src/main/java/org/scijava/io/AbstractIOPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,60 @@

package org.scijava.io;

import org.scijava.io.location.Location;
import org.scijava.io.location.LocationService;
import org.scijava.plugin.AbstractHandlerPlugin;
import org.scijava.plugin.Parameter;

import java.io.IOException;
import java.net.URISyntaxException;

/**
* Abstract base class for {@link IOPlugin}s.
*
* @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>
{
// NB: No implementation needed.

@Parameter
private LocationService locationService;

@Override
public boolean supportsOpen(final String source) {
try {
return supportsOpen(locationService.resolve(source));
} catch (URISyntaxException e) {
return false;
}
}

@Override
public boolean supportsSave(final String destination) {
try {
return supportsSave(locationService.resolve(destination));
} catch (URISyntaxException e) {
return false;
}
}

@Override
public void save(final D data, final String destination) throws IOException {
try {
save(data, locationService.resolve(destination));
} catch (URISyntaxException e) {
throw new IOException(e);
}
}

@Override
public D open(final String destination) throws IOException {
try {
return open(locationService.resolve(destination));
} catch (URISyntaxException e) {
throw new IOException(e);
}
}

}
30 changes: 27 additions & 3 deletions src/main/java/org/scijava/io/DefaultIOService.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@
package org.scijava.io;

import java.io.IOException;
import java.net.URISyntaxException;

import org.scijava.event.EventService;
import org.scijava.io.event.DataOpenedEvent;
import org.scijava.io.event.DataSavedEvent;
import org.scijava.io.location.Location;
import org.scijava.io.location.LocationService;
import org.scijava.log.LogService;
import org.scijava.plugin.AbstractHandlerService;
import org.scijava.plugin.Parameter;
Expand All @@ -47,7 +50,7 @@
*/
@Plugin(type = Service.class)
public final class DefaultIOService
extends AbstractHandlerService<String, IOPlugin<?>> implements IOService
extends AbstractHandlerService<Location, IOPlugin<?>> implements IOService
{

@Parameter
Expand All @@ -56,10 +59,31 @@ public final class DefaultIOService
@Parameter
private EventService eventService;

// -- IOService methods --
@Parameter
private LocationService locationService;

@Override
public Object open(final String source) throws IOException {
try {
return open(locationService.resolve(source));
} catch (URISyntaxException e) {
throw new IOException(e);
}
}

@Override
public void save(final Object data, final String destination)
throws IOException
{
try {
save(data, locationService.resolve(destination));
} catch (URISyntaxException e) {
throw new IOException(e);
}
}

@Override
public Object open(final Location source) throws IOException {
final IOPlugin<?> opener = getOpener(source);
if (opener == null) {
log.error("No opener IOPlugin found for " + source + ".");
Expand All @@ -77,7 +101,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 Down
7 changes: 6 additions & 1 deletion src/main/java/org/scijava/io/DefaultRecentFileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
import org.scijava.event.EventHandler;
import org.scijava.event.EventService;
import org.scijava.io.event.IOEvent;
import org.scijava.io.location.FileLocation;
import org.scijava.io.location.Location;
import org.scijava.menu.MenuConstants;
import org.scijava.module.ModuleInfo;
import org.scijava.module.ModuleService;
Expand Down Expand Up @@ -181,7 +183,10 @@ public void dispose() {

@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
34 changes: 29 additions & 5 deletions src/main/java/org/scijava/io/IOPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

import java.io.IOException;

import org.scijava.io.location.FileLocation;
import org.scijava.io.location.Location;
import org.scijava.plugin.HandlerPlugin;
import org.scijava.plugin.Plugin;

Expand All @@ -48,52 +50,74 @@
* @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. */
@SuppressWarnings("unused")
default boolean supportsOpen(final String source) {
return supportsOpen(new FileLocation(source));
}

/** Checks whether the I/O plugin can open data from the given location. */
default boolean supportsOpen(Location source) {
return false;
}

/** Checks whether the I/O plugin can save data to the given destination. */
@SuppressWarnings("unused")
default boolean supportsSave(final String destination) {
return supportsSave(new FileLocation(destination));
}

/** Checks whether the I/O plugin can save data to the given location. */
default boolean supportsSave(Location destination) {
return false;
}

/**
* Checks whether the I/O plugin can save the given data to the specified
* destination.
* location.
*/
default boolean supportsSave(final Object data, final String destination) {
return supportsSave(destination) && getDataType().isInstance(data);
}

default boolean supportsSave(Object data, Location destination) {
return supportsSave(destination) && getDataType().isInstance(data);
}

/** Opens data from the given source. */
@SuppressWarnings("unused")
default D open(final String source) throws IOException {
throw new UnsupportedOperationException();
}

/** Opens data from the given location. */
default D open(Location source) throws IOException {
throw new UnsupportedOperationException();
}
/** Saves the given data to the specified destination. */
@SuppressWarnings("unused")
default void save(final D data, final String destination) throws IOException {
save(data, new FileLocation(destination));
}

/** Saves the given data to the specified location. */
default void save(D data, Location destination) throws IOException {
throw new UnsupportedOperationException();
}

// -- Typed methods --

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

@Override
default Class<String> getType() {
return String.class;
default Class<Location> getType() {
return Location.class;
}
}
63 changes: 56 additions & 7 deletions src/main/java/org/scijava/io/IOService.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

import java.io.IOException;

import org.scijava.io.location.FileLocation;
import org.scijava.io.location.Location;
import org.scijava.plugin.HandlerService;
import org.scijava.service.SciJavaService;

Expand All @@ -39,15 +41,23 @@
*
* @author Curtis Rueden
*/
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.
*/
default IOPlugin<?> getOpener(final String source) {
return getOpener(new FileLocation(source));
}

/**
* Gets the most appropriate {@link IOPlugin} for opening data from the given
* location.
*/
default IOPlugin<?> getOpener(Location source) {
for (final IOPlugin<?> handler : getInstances()) {
if (handler.supportsOpen(source)) return handler;
}
Expand All @@ -56,9 +66,17 @@ default IOPlugin<?> getOpener(final String source) {

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

/**
* Gets the most appropriate {@link IOPlugin} for saving data to the given
* location.
*/
default <D> IOPlugin<D> getSaver(D data, Location destination) {
for (final IOPlugin<?> handler : getInstances()) {
if (handler.supportsSave(data, destination)) {
@SuppressWarnings("unchecked")
Expand All @@ -77,7 +95,7 @@ default <D> IOPlugin<D> getSaver(final D data, final String destination) {
* The opener to use is automatically determined based on available
* {@link IOPlugin}s; see {@link #getOpener(String)}.
* </p>
*
*
* @param source The source (e.g., file path) from which to data should be
* loaded.
* @return An object representing the loaded data, or null if the source is
Expand All @@ -86,21 +104,52 @@ default <D> IOPlugin<D> getSaver(final D data, final String destination) {
*/
Object open(String source) throws IOException;

/**
* Loads data from the given location.
* <p>
* The opener to use is automatically determined based on available
* {@link IOPlugin}s; see {@link #getOpener(Location)}.
* </p>
*
* @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.
*/
default Object open(Location source) throws IOException {
throw new UnsupportedOperationException();
}

/**
* Saves data to the given destination. The nature of the destination is left
* intentionally general, but the most common example is a file path.
* <p>
* The saver to use is automatically determined based on available
* {@link IOPlugin}s; see {@link #getSaver(Object, String)}.
* </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.
* @throws IOException if something goes wrong saving the data.
*/
void save(Object data, String destination) throws IOException;

/**
* Saves data to the given location.
* <p>
* The saver to use is automatically determined based on available
* {@link IOPlugin}s; see {@link #getSaver(Object, Location)}.
* </p>
*
* @param data The data to be saved to the destination.
* @param destination The destination location to which data should be saved.
* @throws IOException if something goes wrong saving the data.
*/
default void save(Object data, Location destination) throws IOException {
throw new UnsupportedOperationException();
}

// -- HandlerService methods --

@Override
Expand All @@ -110,7 +159,7 @@ default Class<IOPlugin<?>> getPluginType() {
}

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