001/**
002 * Copyright (C) 2014  Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/
003 *
004 * This file is part of Dicoogle/dicoogle-sdk.
005 *
006 * Dicoogle/dicoogle-sdk is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * Dicoogle/dicoogle-sdk is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with Dicoogle.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package pt.ua.dicoogle.sdk.task;
020
021import java.util.ArrayList;
022import java.util.List;
023import java.util.concurrent.ExecutionException;
024
025import pt.ua.dicoogle.sdk.datastructs.SearchResult;
026
027/**
028 * Advanced task which encompases multiple sub-tasks.
029 * 
030 * This class helps dicoogle to deal with multiple providers simultaneously.
031 * 
032 * @author Tiago Marques Godinho, tmgodinho@ua.pt
033 *
034 */
035public abstract class JointQueryTask {
036
037        private boolean cancelled;
038        private int numberOfCompletedTasks;
039        
040        private List<Task<Iterable<SearchResult>>> searchTasks;
041        
042        public JointQueryTask() {
043                this.searchTasks = new ArrayList<>();
044                this.numberOfCompletedTasks = 0;
045                this.cancelled = false;
046        }
047
048        public boolean addTask(final Task<Iterable<SearchResult>> e) {
049                //Add hook
050                e.onCompletion( new Runnable() {
051                        @Override
052                        public void run() {
053                                numberOfCompletedTasks++;
054                                onReceive(e);
055                                if(numberOfCompletedTasks == searchTasks.size())
056                                        onCompletion();
057                        }
058                } );
059                
060                return searchTasks.add(e);
061        }
062        
063        public abstract void onCompletion();
064
065        public abstract void onReceive(Task<Iterable<SearchResult>> e);
066        
067        public Iterable<SearchResult> get() throws InterruptedException, ExecutionException{
068                List<SearchResult> list = new ArrayList<>();
069                
070                for(Task<Iterable<SearchResult>> task : searchTasks){
071                        Iterable<SearchResult> res = task.get();
072                        for(SearchResult i : res)
073                                list.add(i);
074                }
075                return list;
076        }       
077
078        public float getProgress() {
079                if(isCancelled())
080                        return -1;
081                
082                if(isDone())
083                        return 1;
084                
085                return numberOfCompletedTasks / searchTasks.size();
086        }
087
088        public boolean isCancelled() {
089                return cancelled;
090        }
091
092        public boolean isDone() {
093                return numberOfCompletedTasks == searchTasks.size();
094        }
095
096        public boolean cancel(boolean mayInterruptIfRunning) {
097                boolean ret = true;
098                for(Task<Iterable<SearchResult>> t : searchTasks){
099                        if(!t.isCancelled())
100                                ret = t.cancel(mayInterruptIfRunning) && ret;
101                }
102                return ret;
103        }       
104}