Skip to content

Commit

Permalink
Improve StorageInterface, add method get (#660)
Browse files Browse the repository at this point in the history
* [sdk] Add default method StorageInterface#get

- specifically for retrieving a single item from storage,
  without deep file traversal or requiring any iterables
- default impl uses `at` underneath to implement it
- update code in core to use it where suitable
- also correct image servlet to only query for instances
  to DIM providers if specified

* [sdk] Improve StorageInterface documentation

- Fix example code in #at
- Clarify in #list that a trailing forward slash
  means that it's a directory

* Apply suggestions from code review
  • Loading branch information
Enet4 authored Aug 27, 2024
1 parent 7af44ec commit 169d3eb
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,17 @@ public void onReceive(Task<Iterable<SearchResult>> e) {
for (SearchResult r : itResults) {
if (uri == null)
uri = r.getURI();
System.out.println("URI: " + uri.toString());
}

if (uri != null) {
StorageInterface str = PluginController.getInstance().getStorageForSchema(uri);
if (str != null) {
Iterable<StorageInputStream> stream = str.at(uri);
for (StorageInputStream r : stream) {
StorageInputStream r = str.get(uri);
if (r != null) {
ret = r;

stopAllTaks();

latch.countDown();

return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,13 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
// get the image file by the URI
URI imgUri = new URI(uri);
StorageInterface storageInt = PluginController.getInstance().getStorageForSchema(imgUri);
Iterator<StorageInputStream> storages = storageInt.at(imgUri).iterator();
StorageInputStream storageItem = storageInt.get(imgUri);
// take the first valid storage
if (!storages.hasNext()) {
if (storageItem == null) {
ResponseUtil.sendError(response, 404, "No image file for supplied URI");
return;
}
imgFile = storages.next();
imgFile = storageItem;

} catch (URISyntaxException ex) {
ResponseUtil.sendError(response, 400, "Bad URI syntax");
Expand Down Expand Up @@ -220,7 +220,6 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S

private static StorageInputStream getFileFromSOPInstanceUID(String sopInstanceUID, List<String> providers)
throws IOException {
// TODO use only DIM sources?
JointQueryTask qt = new JointQueryTask() {
@Override
public void onCompletion() {}
Expand All @@ -229,24 +228,32 @@ public void onCompletion() {}
public void onReceive(Task<Iterable<SearchResult>> e) {}
};
try {
PluginController pc = PluginController.getInstance();
if (providers == null) {
providers = PluginController.getInstance().getQueryProvidersName(true);
// use only DIM sources
providers = ServerSettingsManager.getSettings().getArchiveSettings().getDIMProviders();
// exclude unknown query providers
providers.removeIf(pName -> pc.getQueryProviderByName(pName, true) == null);
if (providers.isEmpty()) {
// fallback to all query providers
providers = pc.getQueryProvidersName(true);
}
}
Iterator<SearchResult> it = PluginController.getInstance()
.query(qt, providers, "SOPInstanceUID:" + sopInstanceUID).get().iterator();
Iterator<SearchResult> it = pc
.query(qt, providers, "SOPInstanceUID:\"" + sopInstanceUID + '"').get().iterator();
if (!it.hasNext()) {
throw new IOException("No such image of SOPInstanceUID " + sopInstanceUID);
}
SearchResult res = it.next();
StorageInterface storage = PluginController.getInstance().getStorageForSchema(res.getURI());
StorageInterface storage = pc.getStorageForSchema(res.getURI());
if (storage == null) {
throw new IOException("Unsupported file scheme");
}
Iterator<StorageInputStream> store = storage.at(res.getURI()).iterator();
if (!store.hasNext()) {
StorageInputStream item = storage.get(res.getURI());
if (item == null) {
throw new IOException("No storage item found");
}
return store.next();
return item;
} catch (InterruptedException | ExecutionException ex) {
throw new IOException(ex);
}
Expand Down
53 changes: 47 additions & 6 deletions sdk/src/main/java/pt/ua/dicoogle/sdk/StorageInterface.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,57 @@ public default boolean handles(URI location) {
* This method is particularly nice for use in for-each loops.
*
* The provided scheme is not relevant at this point, but the developer must avoid calling this method
* with a path of a different schema.
*
* <pre>for(StorageInputStream dicomObj : storagePlugin.at("file://dataset/")){
* System.err.println(dicomObj.getURI());
* }</pre>
* with a path of a different scheme.
*
* <pre>
* URI uri = URI.create("file://dataset/");
* for (StorageInputStream dicomObj: storagePlugin.at(uri)) {
* System.err.println(dicomObj.getURI());
* }
* </pre>
*
* @param location the location to read
* @param parameters a variable list of extra parameters for the retrieve
* @param parameters a variable list of extra retrieval parameters
* @return an iterable of storage input streams
* @see StorageInputStream
*/
public Iterable<StorageInputStream> at(URI location, Object... parameters);

/**
* Obtains an item stored at the exact location specified.
*
* The provided scheme is not relevant at this point,
* but the developer must avoid calling this method
* with a path of a different scheme.
*
* <pre>
* URI uri = URI.create("file://dataset/CT/001.dcm");
* StorageInputStream item = storagePlugin.get(uri);
* if (item != null) {
* System.err.println("Item at " + dicomObj.getURI() + " is available");
* }
* </pre>
*
* The default implementation calls {@linkplain #at}
* and returns the first item if its URI matches the location requested.
* Implementations may wish to override this method for performance reasons.
*
* @param location the URI of the item to retrieve
* @param parameters a variable list of extra retrieval parameters
* @return a storage item if it was found, <code>null</code> otherwise
* @see StorageInputStream
*/
default public StorageInputStream get(URI location, Object... parameters) {
for (StorageInputStream sis : this.at(location, parameters)) {
if (Objects.equals(sis.getURI(), location)) {
return sis;
}
// don't try any further
break;
}
return null;
}

/**
* Stores a DICOM object into the storage.
*
Expand Down Expand Up @@ -104,6 +142,9 @@ public default boolean handles(URI location) {
* can yield intermediate URIs representing other directories rather than
* objects.
*
* Directories can be distinguished from regular files
* by the presence of a trailing forward slash in the URI.
*
* The provided scheme is not relevant at this point, but the developer
* must avoid calling this method with a path of a different scheme.
*
Expand Down

0 comments on commit 169d3eb

Please sign in to comment.