diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6f89c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ \ No newline at end of file diff --git a/README.md b/README.md index 9ccf741..76c107f 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,77 @@ Dicoogle Plugin - Sample ------------------------ +======================== +This is a Dicoogle plugin to serve as an example. Those that are interested in developing a new +plugin may use this one as a template. -Where should I start? ------------------------ +Getting Started +--------------- +### Installing and running Dicoogle -Run Dicoogle ---------------- 1. Go to http://www.dicoogle.com/?page_id=67 -2. Download the version of Dicoogle -3. Run the Dicoogle with: sh Dicoogle.sh or Dicoogle.bat. -4. Is it running? You're ok! +2. Download version 2 (or later) of Dicoogle +3. Extract your contents to its own directory (e.g. "~/dicoogle" or "C:\dicoogle", depending on the platform). +4. Run Dicoogle with: sh Dicoogle.sh (OSX / Linux) or Dicoogle.bat (Windows). +5. You should see your web browser opening the Dicoogle user interface. Is it running? You're ok! + +### Downloading and building the plugin + +Maven is required in order to build the project. An IDE with Maven support such as Netbeans may also help. + +1. Clone the git repository at https://github.com/bioinformatics-ua/dicooglePluginSample.git +2. Go to the project's base directory in a command line and run `mvn install`. Alternatively, open + the Maven project of the plugin with your IDE, then force it to build your project. -Use your own plugin --------------------- +3. If the building task is successful, you will have a new jar with dependencies in the target + folder (target/dicoogle-plugin-sample-2.0-jar-with-dependencies.jar). -You should use Netbeans to compile the project and maven is necessary. Then, the first class to look is RSIPluginSet. It is the place where the magic starts. +### Developing your own plugin based on this sample -You can compile and run in the command line: +The first class to look into is RSIPluginSet. It is the main entry point for everything else. +Once modified to suit your needs, build the plugin again and re-deploy it to Dicoogle (see below). -1. https://github.com/bioinformatics-ua/dicooglePluginSample.git -2. cd dicooglePluginSample -3. ```$ mvn install``` -4. copy target/dicooglePluginRestSample-1.0-SNAPSHOT-jar-with-dependencies.jar to the folder Plugins inside Dicoogle project. -5. Run Dicoogle with: sh Dicoogle.sh or Dicoogle.bat. +### Using your plugin +1. Copy your plugin's package with dependencies (target/dicoogle-plugin-sample-2.0-jar-with-dependencies.jar) + to the "Plugins" folder inside the root folder of Dicoogle. +2. Run Dicoogle. The plugin will be automatically included. -Available plugins ------------------------ -- RSIIndex -- RSIStorage -- RSIQuery -- RSIWebService -- RSIJettyPlugin -- Sample HTML5 content and consuming web service: helps to build a web app +Available content +----------------- + +- _RSIIndexer_ : a sample indexer, only logs the DIM contents of files +- _RSIStorage_ : a sample storage service, keeps files in memory buffers +- _RSIQuery_ : a sample query provider, returns random data on request +- _RSIJettyPlugin_ : a sample plugin for providing web services, holds `RSIWebService` +- _RSIWebService_ : a sample web service in the form of a servlet, serves a web page and a few other services +- _RSIRestPlugin_ : a sample Restlet server resource, provides dummy data +- Sample HTML5 content and consuming web service: helps you to build a web app Web service plugin sample and Web App: --------------------------- +-------------------------------------- -To test the webservice plugin, you should go to Services and Enable Dicoogle Web Services. +To test the webservice plugin, you may open your browser and navigate to these URLs: -- http://127.0.0.1:8080/sample/hello?uid=1111 -- http://127.0.0.1:8080/dashboardSample -- http://127.0.0.1:6060/rsitest (restlet) +- `http://localhost:8080/sample/hello?uid=1111` +- `http://localhost:8080/dashboardSample` +- `http://localhost:8080/ext/rsi-test` (restlet) +You may also use the built-in Dicoogle services for testing other plugins: +- GET `http://localhost:8080/search?query=test&provider=RSI` to test the query provider +- POST `http://localhost:8080/management/tasks/index?plugin=RSI&uri=` to test the indexer Platforms ----------------- +---------- + +Dicoogle has been tested in: - Windows - Linux - Mac OS X -More information: http://bioinformatics-ua.github.io/dicoogle/ - - +For more information, please visit http://www.dicoogle.com diff --git a/pom.xml b/pom.xml index 6e5ed60..e92c20b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,16 +1,28 @@ 4.0.0 - pt.ieeta.dicoogle.plugin.demo - dicooglePluginRestSample - 1.0-SNAPSHOT + pt.ua.dicoogle.demo + dicoogle-plugin-sample + dicoogle-plugin-sample + 2.0.0 jar + + + UTF-8 + + + 2.0.0 + + + 9.0.3.v20130506 + + - - - - src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/html5/ - + + + + src/main/resources/html5/ + @@ -19,20 +31,20 @@ maven-compiler-plugin 2.3.2 + 1.7 1.7 - - maven-assembly-plugin jar-with-dependencies - @@ -45,8 +57,27 @@ - - + + com.mycila + license-maven-plugin + 2.4 + +
./short-license.txt
+ + **/*.java + + + **/package-info.java + +
+ + + + check + + + +
@@ -55,30 +86,59 @@ Public online Restlet repository http://maven.restlet.org - + + mavencentral + http://repo1.maven.org/maven2/ + + true + + + + dcm4che + http://www.dcm4che.org/maven2/ + + true + + + + + mi + http://bioinformatics.ua.pt/maven/content/repositories/mi + + false + + + + + mi-snapshots + http://bioinformatics.ua.pt/maven/content/repositories/mi-snapshots + + true + + + + + sourceforge-releases + Sourceforge Releases + https://oss.sonatype.org/content/repositories/sourceforge-releases + + - - pt.ua.ieeta - dicoogle-sdk - 2.0-SNAPSHOT - org.restlet.jse org.restlet.ext.json 2.1.2 - - org.eclipse.jetty - jetty-webapp - 9.0.3.v20130506 - + pt.ua.ieeta + dicoogle-sdk + ${dicoogle.version} + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + - - UTF-8 - 1.7 - 1.7 - - dicooglePluginSample
\ No newline at end of file diff --git a/short-license.txt b/short-license.txt new file mode 100644 index 0000000..23158a0 --- /dev/null +++ b/short-license.txt @@ -0,0 +1,16 @@ +Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + +This file is part of Dicoogle/${project.name}. + +Dicoogle/${project.name} is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Dicoogle/${project.name} 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Dicoogle. If not, see . diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/JsonWebService.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/JsonWebService.java index a9998d7..82a3de7 100644 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/JsonWebService.java +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/JsonWebService.java @@ -1,3 +1,21 @@ +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . + */ package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/MemoryDICOMDB.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/MemoryDICOMDB.java index 7fdfe2a..242cb31 100644 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/MemoryDICOMDB.java +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/MemoryDICOMDB.java @@ -1,21 +1,43 @@ +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . + */ package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; import java.util.ArrayList; import java.util.List; -/** +/** An in-memory DICOM storage. * - * @author Luís A. Bastião Silva - + * @author Luís A. Bastião Silva + * @author Eduardo Pinho */ public class MemoryDICOMDB { - private List patientNames = null; - private List studies = null; - private List series = null; - private List sopInstanceUIDs = null; + private final List patientNames; + private final List studies; + private final List series; + private final List sopInstanceUIDs; public MemoryDICOMDB () { + patientNames = new ArrayList<>(); + studies = new ArrayList<>(); + series = new ArrayList<>(); sopInstanceUIDs = new ArrayList<>(); } diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIIndex.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIIndexer.java similarity index 54% rename from src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIIndex.java rename to src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIIndexer.java index 56d8c05..83b84ee 100644 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIIndex.java +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIIndexer.java @@ -1,13 +1,32 @@ +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . + */ package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; import java.io.BufferedInputStream; import java.io.IOException; -import java.io.InputStream; import java.net.URI; import org.dcm4che2.data.DicomObject; import org.dcm4che2.data.Tag; import org.dcm4che2.io.DicomInputStream; import org.dcm4che2.io.StopTagInputHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import pt.ua.dicoogle.sdk.IndexerInterface; import pt.ua.dicoogle.sdk.StorageInputStream; import pt.ua.dicoogle.sdk.datastructs.Report; @@ -15,50 +34,50 @@ import pt.ua.dicoogle.sdk.task.ProgressCallable; import pt.ua.dicoogle.sdk.task.Task; -/** +/** Example of an indexer plugin. * * @author Luís A. Bastião Silva - + * @author Eduardo Pinho */ -public class RSIIndex implements IndexerInterface{ - - - private MemoryDICOMDB memoryDicomDB = null; +public class RSIIndexer implements IndexerInterface{ + private static final Logger logger = LoggerFactory.getLogger(RSIIndexer.class); - - public RSIIndex(MemoryDICOMDB memoryDicomDB) + private boolean enabled; + private final MemoryDICOMDB memoryDicomDB; + private ConfigurationHolder settings; + + public RSIIndexer(MemoryDICOMDB memoryDicomDB) { this.memoryDicomDB = memoryDicomDB; + this.enabled = true; } - + private Report indexURI(StorageInputStream storage) throws IOException { - BufferedInputStream bufferedStream = null; - DicomInputStream dicomStream = null; - try (InputStream fileStream = storage.getInputStream()) { - bufferedStream = new BufferedInputStream(fileStream); - dicomStream = new DicomInputStream(bufferedStream); + + try (DicomInputStream dicomStream = + new DicomInputStream( + new BufferedInputStream( + storage.getInputStream()))) { //dicomStream.setFileSize(file.length()); dicomStream.setHandler(new StopTagInputHandler(Tag.PixelData)); DicomObject dicomObject = dicomStream.readDicomObject(); - String SOPInstanceUID = dicomObject.getString(Tag.SOPInstanceUID); String PatientName = dicomObject.getString(Tag.PatientName); - System.err.println("SOP Instance UID: "+SOPInstanceUID); - System.err.println("PatientName: "+PatientName); - - - } - catch(Exception e ) - { + String StudyInstanceUID = dicomObject.getString(Tag.StudyInstanceUID); + String SeriesInstanceUID = dicomObject.getString(Tag.SeriesInstanceUID); + String SOPInstanceUID = dicomObject.getString(Tag.SOPInstanceUID); + + this.memoryDicomDB.add(PatientName, StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID); + + // use slf4j for logging purposes: + logger.info("SOP Instance UID: {}", SOPInstanceUID); + logger.info("PatientName: {}", PatientName); + } catch(Exception e) { + logger.warn("Failed to index \"{}\"", storage.getURI(), e); System.err.println("indexURI: Do whatever you want."); } - finally{ - if (bufferedStream!=null) - bufferedStream.close(); - } - - // Do whatever you want - // System.out.println("Size: "+ storage.getSize()); // Works with new SDK (1.0) + return new Report(); } @@ -77,11 +96,9 @@ public Report call() throws Exception { try { r = indexURI(file); - } - catch (Exception e) - { - System.err.println("ProgressCallable: Do whatever you want."); + catch (Exception e) { + logger.warn("Indexation of \"{}\" failed", file.getURI(), e); } progress = 1.0f; @@ -107,23 +124,16 @@ public Task index(final Iterable files) { public Report call() throws Exception { Report r = new Report(); - try - { - for (StorageInputStream f : files) - { + try { + for (StorageInputStream f : files) { r = indexURI(f); } - } - catch (Exception e) - { - e.printStackTrace(); - System.err.println("ProgressCallable (iterator): Do whatever you want."); + } catch (Exception e) { + logger.warn("Indexation failed", e); } progress = 1.0f; - // Wait for it, solve the problem. :D - // This is not async (for real) return r; } @@ -139,47 +149,50 @@ public float getProgress() { public boolean unindex(URI uri) { // Not implemented return false; - } - - @Override - public boolean handles(URI uri) { - // Not implemented - return true; - - } - - + /** This method is used to retrieve the unique name of the indexer. + * + * @return a fixed name for the indexer + */ @Override public String getName() { - return "RSIStorageTest"; + return "RSI"; } @Override public boolean enable() { + this.enabled = true; return true; } @Override public boolean disable() { + this.enabled = false; return true; } @Override public boolean isEnabled() { - // FAKE value, implement by yourself. - return true; + return this.enabled; } @Override public void setSettings(ConfigurationHolder settings) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + this.settings = settings; + // use settings here } @Override public ConfigurationHolder getSettings() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return this.settings; + } + + @Override + public boolean handles(URI path) { + // State here whether this indexer can index the file at the given path. + // If not sure, simply return true and let the indexation procedures find out. + return true; } } diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIJettyPlugin.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIJettyPlugin.java index d2af404..8985159 100644 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIJettyPlugin.java +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIJettyPlugin.java @@ -1,86 +1,108 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . */ package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; -import java.io.File; import java.net.URL; +import javax.servlet.http.HttpServlet; import org.eclipse.jetty.server.handler.HandlerList; -import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.webapp.WebAppContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import pt.ua.dicoogle.sdk.JettyPluginInterface; import pt.ua.dicoogle.sdk.core.DicooglePlatformInterface; import pt.ua.dicoogle.sdk.core.PlatformCommunicatorInterface; import pt.ua.dicoogle.sdk.settings.ConfigurationHolder; -/** +/** Example of a Jetty Servlet plugin. * * @author Luís A. Bastião Silva - */ public class RSIJettyPlugin implements JettyPluginInterface, PlatformCommunicatorInterface { - + private static final Logger logger = LoggerFactory.getLogger(RSIJettyPlugin.class); + + private boolean enabled; private ConfigurationHolder settings; - private DicooglePlatformInterface pluginController; - + private DicooglePlatformInterface platform; + private final RSIJettyWebService webService; + public RSIJettyPlugin() { - super(); - new RSIJettyWebService(); + this.webService = new RSIJettyWebService(); + this.enabled = true; } + @Override public void setPlatformProxy(DicooglePlatformInterface pi) { - this.pluginController = pi; - RSIJettyWebService.setPlugin(this); - - System.out.println("PluginController was set:" + pi); + this.platform = pi; + // since web service is not a plugin interface, the platform interface must be provided manually + this.webService.setPlatformProxy(pi); } + @Override public String getName() { - return "RSIJetty"; + return "RSI"; } + @Override public boolean enable() { - // TODO Auto-generated method stub + this.enabled = true; return true; } + @Override public boolean disable() { - // TODO Auto-generated method stub - return false; + this.enabled = false; + return true; } + @Override public boolean isEnabled() { - // TODO Auto-generated method stub - return true; + return this.enabled; } + @Override public void setSettings(ConfigurationHolder settings) { - // TODO Auto-generated method stub this.settings = settings; + // use settings here } + @Override public ConfigurationHolder getSettings() { - // TODO Auto-generated method stub return settings; } + @Override public HandlerList getJettyHandlers() { ServletContextHandler handler = new ServletContextHandler(); handler.setContextPath("/sample"); - handler.addServlet(new ServletHolder(new RSIJettyWebService()), "/hello"); + handler.addServlet(new ServletHolder(this.webService), "/hello"); /* TODO: Change here if you want - * For deploymennt stage you can point for a directory in your machine, - * such as: file:///Users/bastiao/myHtml5Files - * */ + * During the development stage you can point to a directory in your machine, + * such as: file:///Users/bastiao/myHtml5Files + */ URL url = RSIJettyPlugin.class.getResource("/WEBAPP"); - System.out.println(url); + logger.debug("Retrieving web app from \"{}\"", url); String directoryToServeAssets = url.toString(); final WebAppContext webpages = new WebAppContext(directoryToServeAssets, "/dashboardSample"); @@ -97,8 +119,4 @@ public HandlerList getJettyHandlers() { return l; } - public DicooglePlatformInterface getPluginController() { - return pluginController; - } - } diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIJettyWebService.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIJettyWebService.java index 94ac97c..89dd12b 100644 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIJettyWebService.java +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIJettyWebService.java @@ -1,38 +1,50 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . */ - package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.concurrent.ExecutionException; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import pt.ua.dicoogle.sdk.core.DicooglePlatformInterface; +import pt.ua.dicoogle.sdk.core.PlatformCommunicatorInterface; import pt.ua.dicoogle.sdk.datastructs.SearchResult; import pt.ua.dicoogle.sdk.task.Task; -/** +/** Sample Jetty servlet-based web service. * * @author Luís A. Bastião Silva - */ -public class RSIJettyWebService extends HttpServlet { - +public class RSIJettyWebService extends HttpServlet implements PlatformCommunicatorInterface { + private static final Logger logger = LoggerFactory.getLogger(RSIJettyWebService.class); - private static RSIJettyPlugin plugin; - + private DicooglePlatformInterface platform; public RSIJettyWebService() { } - @Override protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException { @@ -42,7 +54,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse response) response.sendError(402, "No UID"); return; } - HashMap extraFields = new HashMap(); + HashMap extraFields = new HashMap<>(); //attaches the required extrafields extraFields.put("PatientName", "PatientName"); @@ -54,32 +66,26 @@ protected void doGet(HttpServletRequest req, HttpServletResponse response) extraFields.put("StudyInstanceUID", "StudyInstanceUID"); extraFields.put("Thumbnail", "Thumbnail"); extraFields.put("SOPInstanceUID", "SOPInstanceUID"); - // Kind of filtering: //Task> result = RSIPluginSet.coreDicoogle.query("lucene", "StudyInstanceUID:234567", extraFields); // Return all: - Task> result = RSIPluginSet.coreDicoogle.query("lucene", "*:*", extraFields); + Task> result = this.platform.query("lucene", "*:*", extraFields); try { Iterable rr = result.get(); - - } catch (InterruptedException ex) { - Logger.getLogger(RSIJettyWebService.class.getName()).log(Level.SEVERE, null, ex); - } catch (ExecutionException ex) { - Logger.getLogger(RSIJettyWebService.class.getName()).log(Level.SEVERE, null, ex); + } catch (InterruptedException | ExecutionException ex) { + logger.warn("Operation failed", ex); } - - response.setContentType("text/json;charset=utf-8"); PrintWriter out=response.getWriter(); out.print("{\"action\":\"test\"}"); } - - public static void setPlugin(RSIJettyPlugin plugin) { - RSIJettyWebService.plugin = plugin; + @Override + public void setPlatformProxy(DicooglePlatformInterface core) { + this.platform = core; } } diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIPluginSet.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIPluginSet.java index f18b618..4f69cb6 100644 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIPluginSet.java +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIPluginSet.java @@ -1,119 +1,134 @@ +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . + */ package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; +import java.util.Collections; import net.xeoh.plugins.base.annotations.PluginImplementation; import org.restlet.resource.ServerResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import pt.ua.dicoogle.sdk.GraphicalInterface; import pt.ua.dicoogle.sdk.IndexerInterface; import pt.ua.dicoogle.sdk.JettyPluginInterface; import pt.ua.dicoogle.sdk.PluginSet; import pt.ua.dicoogle.sdk.QueryInterface; import pt.ua.dicoogle.sdk.StorageInterface; -import pt.ua.dicoogle.sdk.core.DicooglePlatformInterface; -import pt.ua.dicoogle.sdk.core.PlatformCommunicatorInterface; import pt.ua.dicoogle.sdk.settings.ConfigurationHolder; -/** +/** The main plugin set. + * + * This is the entry point for all plugins. * * @author Luís A. Bastião Silva - + * @author Eduardo Pinho */ @PluginImplementation -public class RSIPluginSet implements PluginSet, PlatformCommunicatorInterface{ - - List RSIStorageList; - List RSIIndexerList; - List RSIQueryList; - List RSIwebservices; - List RSIJettyWebServices; +public class RSIPluginSet implements PluginSet { + // use slf4j for logging purposes + private static final Logger logger = LoggerFactory.getLogger(RSIPluginSet.class); - /* if you need to handle storage, you also should add it here */ + // We will list each of our plugins as an attribute to the plugin set + private final RSIIndexer indexer; + private final RSIQuery query; + private final RSIWebResource web; + private final RSIJettyPlugin jettyWeb; + private final RSIStorage storage; - private MemoryDICOMDB memoryDicomDB = new MemoryDICOMDB(); + // Additional resources may be added here. + private final MemoryDICOMDB memoryDicomDB = new MemoryDICOMDB(); + private ConfigurationHolder settings; public RSIPluginSet() throws IOException { - System.err.println("Initializing RSI Plugin Set"); - - RSIIndexerList = new ArrayList<>(); - RSIStorageList = new ArrayList<>(); - RSIQueryList = new ArrayList<>(); - RSIwebservices = new ArrayList<>(); - RSIJettyWebServices = new ArrayList<>(); - - RSIwebservices.add(new RSIWebService()); - RSIwebservices.add(new JsonWebService()); - RSIIndexerList.add(new RSIIndex(memoryDicomDB)); - RSIJettyWebServices.add(new RSIJettyPlugin()); - RSIQueryList.add(new RSIQuery(memoryDicomDB)); - RSIStorageList.add(new RSIStorage()); - - - /* More plugins should be added here */ - - System.err.println("Completed Init of RSI Plugin Set"); - } - public static DicooglePlatformInterface coreDicoogle; - @Override - public void setPlatformProxy(DicooglePlatformInterface core) { - // You can acess the core. It may be useful to do interaction between - // other external plugins. - - coreDicoogle = core; - - + logger.info("Initializing RSI Plugin Set"); + + // construct all plugins here + this.indexer = new RSIIndexer(memoryDicomDB); + this.jettyWeb = new RSIJettyPlugin(); + this.query = new RSIQuery(memoryDicomDB); + this.storage = new RSIStorage(); + this.web = new RSIWebResource(); + logger.info("RSI Plugin Set is ready"); } - + @Override - public List getIndexPlugins() { - return RSIIndexerList; + public Collection getIndexPlugins() { + /* Since we only have one indexer, we can return a singleton. For more than + * one plugin, Arrays.asList(...) is a nice alternative. If there are no + * plugins of this type in the set, simply return an empty set or list. + * + * This cast in the argument is needed (only in versions prior to Java 8), + * otherwise the return type cannot be resolved properly. + */ + return Collections.singleton((IndexerInterface) this.indexer); } - @Override - public List getQueryPlugins() { - return RSIQueryList; + public Collection getQueryPlugins() { + return Collections.singleton((QueryInterface) this.query); } + /** This method is used to retrieve a name for identifying the plugin set. Keep it as a constant value. + * + * @return a unique name for the plugin set + */ @Override - public String getName(){return "RSI Plugin Set";} + public String getName() { + return "RSI"; + } @Override - public List getRestPlugins() { - return RSIwebservices; + public Collection getRestPlugins() { + return Collections.singleton((ServerResource) this.web); } @Override - public List getJettyPlugins() { - return RSIJettyWebServices; + public Collection getJettyPlugins() { + return Collections.singleton((JettyPluginInterface) this.jettyWeb); } @Override public void shutdown() { - } @Override public Collection getStoragePlugins() { - return RSIStorageList ; + return Collections.singleton((StorageInterface) this.storage); } @Override public void setSettings(ConfigurationHolder xmlSettings) { - //throw new UnsupportedOperationException("Not supported yet."); + this.settings = xmlSettings; } @Override public ConfigurationHolder getSettings() { - throw new UnsupportedOperationException("Not supported yet."); + return this.settings; } @Override public Collection getGraphicalPlugins() { - return new ArrayList() ; + // Graphical plugins are deprecated. Do not use or provide any. + return Collections.EMPTY_LIST; } } \ No newline at end of file diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIQuery.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIQuery.java index e1afe4f..5355421 100644 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIQuery.java +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIQuery.java @@ -1,36 +1,56 @@ +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . + */ package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; +import java.io.File; import java.net.URI; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.UUID; -import java.util.logging.Level; -import java.util.logging.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import pt.ua.dicoogle.sdk.QueryInterface; import pt.ua.dicoogle.sdk.datastructs.SearchResult; import pt.ua.dicoogle.sdk.settings.ConfigurationHolder; -/** +/** Example of a query provider. * * @author Luís A. Bastião Silva - */ public class RSIQuery implements QueryInterface { + private static final Logger logger = LoggerFactory.getLogger(RSIQuery.class); + private boolean enabled; + private ConfigurationHolder settings; + private final MemoryDICOMDB memoryDicomDB; - private MemoryDICOMDB memoryDicomDB = null; - - public RSIQuery(MemoryDICOMDB memoryDicomDB) - { + public RSIQuery(MemoryDICOMDB memoryDicomDB) { this.memoryDicomDB = memoryDicomDB; + this.enabled = true; } private SearchResult generateSearchResult() { - HashMap map = new HashMap(); + HashMap map = new HashMap<>(); map.put("PatientID",UUID.randomUUID().toString() ); map.put("PatientName",UUID.randomUUID().toString() ); map.put("SOPInstanceUID",UUID.randomUUID().toString() ); @@ -40,14 +60,8 @@ private SearchResult generateSearchResult() map.put("StudyDate","20150120"); map.put("SeriesDate","20150120"); - SearchResult r = null; - try { - r = new SearchResult(new URI("file:///1"+UUID.randomUUID().toString() ), 1, map); - } catch (URISyntaxException ex) { - Logger.getLogger(RSIQuery.class.getName()).log(Level.SEVERE, null, ex); - } - - + SearchResult r = new SearchResult( + URI.create("file:" + File.separatorChar + UUID.randomUUID().toString() ), 1, map); return r; } @@ -55,46 +69,47 @@ private SearchResult generateSearchResult() @Override public Iterable query(String query, Object... parameters) { - List results = new ArrayList(); + List results = new ArrayList<>(); results.add(generateSearchResult()); results.add(generateSearchResult()); results.add(generateSearchResult()); results.add(generateSearchResult()); results.add(generateSearchResult()); - return results; - } @Override public String getName() { - return "RSIQUery"; + return "RSI"; } @Override public boolean enable() { + this.enabled = true; return true; } @Override public boolean disable() { + this.enabled = false; return true; } @Override public boolean isEnabled() { - return true; + return this.enabled; } @Override public void setSettings(ConfigurationHolder settings) { - + this.settings = settings; + // use settings here } @Override public ConfigurationHolder getSettings() { - return null; + return this.settings; } } diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIStorage.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIStorage.java index bace682..15d08ce 100644 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIStorage.java +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIStorage.java @@ -1,30 +1,53 @@ +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . + */ package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import org.dcm4che2.data.DicomObject; import org.dcm4che2.io.DicomInputStream; import pt.ua.dicoogle.sdk.StorageInputStream; import pt.ua.dicoogle.sdk.StorageInterface; import pt.ua.dicoogle.sdk.settings.ConfigurationHolder; -import java.io.*; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.UUID; -import java.util.logging.Level; -import java.util.logging.Logger; import org.dcm4che2.io.DicomOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -/** +/** Example of a storage plugin. * * @author Luís A. Bastião Silva - */ public class RSIStorage implements StorageInterface { - Map mem = new HashMap(); + private static final Logger logger = LoggerFactory.getLogger(RSIStorage.class); + + private final Map mem = new HashMap<>(); + private boolean enabled = true; + private ConfigurationHolder settings; @Override public String getScheme() { @@ -44,7 +67,7 @@ public Iterable at(final URI location) { @Override public Iterator iterator() { - Collection c2 = new ArrayList(); + Collection c2 = new ArrayList<>(); StorageInputStream s = new StorageInputStream() { @Override @@ -54,14 +77,14 @@ public URI getURI() { @Override public InputStream getInputStream() throws IOException { - ByteArrayOutputStream bos = mem.get(location); + ByteArrayOutputStream bos = mem.get(location.toString()); ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray()); return bin; } @Override public long getSize() throws IOException { - return 0 ; + return mem.get(location.toString()).size(); } }; c2.add(s); @@ -78,24 +101,17 @@ public URI store(DicomObject dicomObject) { try { dos.writeDicomFile(dicomObject); } catch (IOException ex) { - Logger.getLogger(RSIStorage.class.getName()).log(Level.SEVERE, null, ex); + logger.warn("Failed to store object", ex); } bos.toByteArray(); - URI uri = null; - try { - uri = new URI("mem://" + UUID.randomUUID().toString()); - } catch (URISyntaxException ex) { - Logger.getLogger(RSIStorage.class.getName()).log(Level.SEVERE, null, ex); - } + URI uri = URI.create("mem://" + UUID.randomUUID().toString()); mem.put(uri.toString(), bos); - return uri; } @Override public URI store(DicomInputStream inputStream) throws IOException { - DicomObject obj = inputStream.readDicomObject(); return store(obj); @@ -103,7 +119,7 @@ public URI store(DicomInputStream inputStream) throws IOException { @Override public void remove(URI location) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + this.mem.remove(location.toString()); } @Override @@ -113,27 +129,30 @@ public String getName() { @Override public boolean enable() { + this.enabled = true; return true; } @Override public boolean disable() { + this.enabled = false; return true; } @Override public boolean isEnabled() { - return true; + return this.enabled; } @Override public void setSettings(ConfigurationHolder settings) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + this.settings = settings; + // use settings here } @Override public ConfigurationHolder getSettings() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return this.settings; } } diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIWebResource.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIWebResource.java new file mode 100644 index 0000000..8d2360a --- /dev/null +++ b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIWebResource.java @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ + * + * This file is part of Dicoogle/dicoogle-plugin-sample. + * + * Dicoogle/dicoogle-plugin-sample is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dicoogle/dicoogle-plugin-sample 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dicoogle. If not, see . + */ + +package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; + +import org.restlet.data.MediaType; +import org.restlet.representation.Representation; +import org.restlet.representation.StringRepresentation; +import org.restlet.resource.Get; +import org.restlet.resource.ServerResource; + +/** Example of a Restlet-based server resource plugin. + * + * @author Luís A. Bastião Silva - + */ +public class RSIWebResource extends ServerResource { + + @Get + public Representation test(){ + StringRepresentation sr = new StringRepresentation("{\"name\":\"rsi\"}"); + + sr.setMediaType(MediaType.APPLICATION_JSON); + + return sr; + } + + // You can handle all crud operations. More information in the Restlet documentation. + + @Override + public String toString(){ + return "rsi-test"; + } + +} diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIWebService.java b/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIWebService.java deleted file mode 100644 index 115ed87..0000000 --- a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/RSIWebService.java +++ /dev/null @@ -1,33 +0,0 @@ - -package pt.ieeta.dicoogle.plugin.demo.dicooglepluginsample; - -import org.restlet.data.MediaType; -import org.restlet.representation.Representation; -import org.restlet.representation.StringRepresentation; -import org.restlet.resource.Get; -import org.restlet.resource.ServerResource; - -/** - * - * @author Luís A. Bastião Silva - - */ -public class RSIWebService extends ServerResource { - - - @Get - public Representation test(){ - StringRepresentation sr = new StringRepresentation("{\"name\":\"rsi\"}"); - - sr.setMediaType(MediaType.APPLICATION_JSON); - - return sr; - } - - // You can handle all crud operations. Please, read the restlet documentation - - - // http://localhost:8080/ext/rsidemo - @Override - public String toString(){return "rsidemo";} - -} diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/html5/WEBAPP/index.html b/src/main/resources/html5/WEBAPP/index.html similarity index 100% rename from src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/html5/WEBAPP/index.html rename to src/main/resources/html5/WEBAPP/index.html diff --git a/src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/html5/WEBAPP/webservicesWrapper.js b/src/main/resources/html5/WEBAPP/webservicesWrapper.js similarity index 100% rename from src/main/java/pt/ieeta/dicoogle/plugin/demo/dicooglepluginsample/html5/WEBAPP/webservicesWrapper.js rename to src/main/resources/html5/WEBAPP/webservicesWrapper.js