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.
005 *
006 * Dicoogle/dicoogle 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 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.server.web.dicom;
020
021import java.util.ArrayList;
022import java.util.HashMap;
023import java.util.Iterator;
024import java.util.List;
025import java.util.Map;
026import java.util.concurrent.ExecutionException;
027
028import org.apache.commons.collections.Buffer;
029import org.apache.commons.collections.BufferUtils;
030import org.apache.commons.collections.KeyValue;
031import org.apache.commons.collections.buffer.UnboundedFifoBuffer;
032import org.apache.commons.collections.keyvalue.DefaultKeyValue;
033
034import pt.ua.dicoogle.plugins.PluginController;
035import pt.ua.dicoogle.sdk.datastructs.SearchResult;
036import pt.ua.dicoogle.sdk.task.JointQueryTask;
037import pt.ua.dicoogle.sdk.task.Task;
038
039public class SearchHolder {
040
041        @SuppressWarnings("unused") //TODO: IMPLEMENT THIS
042        private static int maxNumberOfTasks = 3;
043        private Map<Integer, QueryHandler> tasks;
044        
045        public SearchHolder() {
046                tasks = new HashMap<Integer, SearchHolder.QueryHandler>();
047        }
048
049        public synchronized int registerNewQuery(List<String> providers, String query, Object searchParam){
050                QueryHandler task = new QueryHandler();
051                
052                task = (QueryHandler) PluginController.getInstance().query(task, providers, query, searchParam);
053                if(task == null)
054                        return -1;
055                
056                tasks.put(task.hashCode(), task);
057                return task.hashCode();
058        }
059        
060        public synchronized void removeQuery(int id){
061                tasks.remove(id);
062        }
063        
064        public  synchronized Iterable<KeyValue> retrieveQueryOutput(int id){
065                QueryHandler task = tasks.get(id);
066        
067                if(task == null)
068                        return null;
069                
070                return task;
071        }
072        
073        private class QueryHandler extends JointQueryTask implements Iterable<KeyValue>{
074
075                private StringBuffer buffer;    
076                private List<KeyValue> tempResults;
077                private List<InnerIterator> currentIterators;
078                
079                public QueryHandler() {
080                        super();
081                        buffer = new StringBuffer();
082                        currentIterators = new ArrayList<InnerIterator>();
083                        tempResults = new ArrayList<>();
084                }
085
086                @Override
087                public void onCompletion() {
088                        // TODO Auto-generated method stub
089                        System.out.println("Completed Query");
090                }
091
092                @Override
093                public void onReceive(Task<Iterable<SearchResult>> e) {
094                        // TODO Auto-generated method stub
095                        try {
096                                System.out.println("RECEIVED NEW ITERATION: ");
097                                
098                                Iterable<SearchResult> results = e.get();
099                                DefaultKeyValue keyValue = new DefaultKeyValue(e.getName(), results);
100                                
101                                appendResult(keyValue);
102                                
103                                /*for(SearchResult res : results ){
104                                        
105                                }*/     
106                        } catch (InterruptedException | ExecutionException e1) {
107                                // TODO Auto-generated catch block
108                                //e1.printStackTrace();
109                        }
110                        
111                        buffer.append("Received Query: "+e.getName());
112                }
113
114                @SuppressWarnings("unchecked")
115                private synchronized void appendResult(DefaultKeyValue keyValue) {
116                        tempResults.add(keyValue);
117                        
118                        for(InnerIterator it : currentIterators){
119                                it.resultBuffer.add(keyValue);                          
120                        }
121                }
122                
123                private synchronized InnerIterator createIterator(){
124                        InnerIterator it = new InnerIterator(tempResults);
125                        currentIterators.add(it);
126                        
127                        return it; 
128                }
129
130                @Override
131                public Iterator<KeyValue> iterator() {
132                        if(isDone() || isCancelled())
133                                return tempResults.iterator();
134                        
135                        return createIterator();
136                }
137                
138                private class InnerIterator implements Iterator<KeyValue>{
139
140                        private Buffer resultBuffer;
141                        
142                        @SuppressWarnings("unchecked")
143                        public InnerIterator(List<KeyValue> tempResults) {
144                                int size = tempResults.size();
145                                if(size <= 0)
146                                        size = 1;
147                                resultBuffer = BufferUtils.blockingBuffer( new UnboundedFifoBuffer(size) );
148                                resultBuffer.addAll(tempResults);
149                        }
150
151                        @Override
152                        public boolean hasNext() {
153                                if(!(isCancelled() || isDone()))
154                                        return true;
155                                
156                                return !resultBuffer.isEmpty();
157                        }
158
159                        @Override
160                        public KeyValue next() {
161                                return (KeyValue) resultBuffer.remove();
162                        }
163
164                        @Override
165                        public void remove() {                          
166                        }
167                        
168                }
169                
170        }
171
172        public boolean isDone(int id) {
173                QueryHandler task = tasks.get(id);
174                
175                if(task == null)
176                        return true;
177                
178                return task.isDone() || task.isCancelled();
179        }
180                
181}