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.core;
020
021import java.io.BufferedWriter;
022import java.io.FileWriter;
023import java.io.IOException;
024import java.io.Serializable;
025import java.util.ArrayList;
026import java.util.HashMap;
027import java.util.Observable;
028import java.util.Observer;
029import org.slf4j.LoggerFactory;
030
031import pt.ua.dicoogle.plugins.PluginController;
032import pt.ua.dicoogle.rGUI.interfaces.controllers.ISearch;
033import pt.ua.dicoogle.rGUI.server.controllers.Search;
034import pt.ua.dicoogle.sdk.Utils.TaskRequest;
035import pt.ua.dicoogle.sdk.Utils.TaskRequestsConstants;
036import pt.ua.dicoogle.sdk.datastructs.SearchResult;
037import pt.ua.dicoogle.sdk.observables.ListObservableSearch;
038
039
040/**
041 * This class is used to export query results to .csv file format with the selected tags
042 *
043 * @author Samuel da Costa Campos <samuelcampos@ua.pt>
044 *
045 */
046public class ExportDataSupport extends Observable implements Observer, Serializable {
047    private String query;
048    private HashMap<String, Boolean> origin;
049    //private boolean network;
050    private boolean keywords;
051    private ArrayList<String> tags;
052    private String filePath;
053
054    private ListObservableSearch obsAux = null;
055
056    
057    public ExportDataSupport(String query, HashMap<String, Boolean> origin, boolean keywords, ArrayList<String> tags, String filePath) throws Exception
058    {
059        
060        //System.out.println("Plugins: " + origin);
061        
062        //System.out.println("Entenring...");
063        this.query = query;
064        this.origin = origin;
065        this.keywords = keywords;
066        this.tags = tags;
067        this.filePath = filePath;
068
069        if(!this.filePath.endsWith(".csv"))
070            this.filePath = this.filePath + ".csv";
071
072    }
073
074    public void InitiateExport(Observer obs) throws Exception
075    {
076        this.addObserver(obs);
077        //this.obsAux = obs;
078        //System.out.println("Count observables: "+this.countObservers());
079        //System.out.println("1 - initiateExport");
080        printFirstLine();
081        //System.out.println("2 - initiateExport");
082        //Result2Tree.getInstance().searchToExport(query, keywords, origin, tags, this);
083        ISearch search = new Search();
084        obsAux  = search.SearchToExport(query, keywords, origin, tags, this);
085        //System.out.println("3 - initiateExport"); 
086    }
087
088    /**
089     * Print the first line of the .csv file
090     *
091     * @throws IOException
092     * @throws InterruptedException
093     */
094    private void printFirstLine() throws IOException, InterruptedException{
095        StringBuffer st = new StringBuffer();
096        //System.out.println("Write the First Line");
097        for(String tag: tags)
098            st.append(tag).append(';');
099
100        st.append('\n');
101        //System.out.println("Count observables: "+this.countObservers());
102        printToFile(st);
103    }
104
105    private void printLines(ArrayList<SearchResult> results) throws InterruptedException, IOException{
106        //System.out.println("Count observables: "+this.countObservers());
107        StringBuffer st = new StringBuffer();
108        long i = 0 ; 
109        //System.out.println("Calling");
110        for(SearchResult result : results){
111            
112            //System.out.println("Export: " + i );
113            //System.out.println("Count observables: "+this.countObservers());
114            
115            HashMap<String, Object> extraFields = result.getExtraData();
116            
117            for(String tag: tags){
118                Object temp1 = extraFields.get(tag);
119                String temp = null;
120                if(temp1 instanceof String)
121                    temp = (String) temp1;
122                
123                if(temp == null)
124                {
125                    st.append(';');
126                }
127                else{
128                    temp = temp.replace("\n", "");
129                    temp = temp.replace(";", ",");
130                    st.append(temp).append(';');
131                }
132            }
133            st.append('\n');
134            if (i%1000==0)
135            {
136                BufferedWriter out = new BufferedWriter(new FileWriter(filePath, true));
137                out.write(st.toString());
138                out.close();
139                st = new StringBuffer();
140            }
141            i++;
142            
143        }
144        //System.out.println("Out of loop");
145        // Print last buffer (that is not yet printed)
146        printToFile(st);
147
148        // only intended to notify the observers of the fist time
149        //System.out.println("Calling observables: "+this.countObservers());
150        if(this.countObservers() > 0)
151        {
152            //System.out.println("Calling observables. There is one, at least.");
153            this.setChanged();
154            
155            if (obsAux!=null)
156            {
157                LoggerFactory.getLogger(ExportDataSupport.class).error("obsAux " + obsAux.isFinish() );
158                this.notifyObservers(obsAux.isFinish());
159            }
160            else
161            {
162                LoggerFactory.getLogger(ExportDataSupport.class).error("not obsAux " );
163                this.notifyObservers(false);
164            }
165            //this.deleteObservers();
166        }
167    }
168
169    private void printToFile(StringBuffer st) throws InterruptedException, IOException{
170        
171        BufferedWriter out = new BufferedWriter(new FileWriter(filePath, true));
172        out.write(st.toString());
173        out.close();
174
175    }
176
177    private int count = 0 ; 
178    
179    @Override
180    public synchronized  void update(Observable o, Object arg) {
181        count++ ;
182        
183        if (obsAux==null)
184        {
185
186            obsAux = ((ListObservableSearch) o);
187        }
188        LoggerFactory.getLogger(ExportDataSupport.class).error("Update @ obs");
189        ArrayList tmp = ((ListObservableSearch) o).getArray();
190        
191        if (tmp==null)
192        {
193            tmp = ((ListObservableSearch) obsAux).getArray();
194        }
195        
196        if (tmp==null)
197        {
198            LoggerFactory.getLogger(ExportDataSupport.class).error("Update is null, sending block signal");
199            PluginController.getInstance().addTask(new TaskRequest(TaskRequestsConstants.T_BLOCK_SIGNAL, null, null));
200            return;
201        }
202        
203        boolean finish = ((ListObservableSearch) obsAux).isFinish();
204        LoggerFactory.getLogger(ExportDataSupport.class).error("Finished @ " + finish);
205        if (finish)
206        {
207            // only intended to notify the observers of the fist time
208            if(this.countObservers() > 0)
209            {
210                this.setChanged();
211                this.notifyObservers((Boolean)finish);
212                obsAux = null;
213                this.deleteObservers();
214            }
215        }   
216        
217        if(tmp instanceof ArrayList) 
218        {
219            try
220            {
221                
222                ArrayList<SearchResult> results = (ArrayList<SearchResult>) tmp;
223                if (results.isEmpty())
224                {
225                    PluginController.getInstance().addTask(new TaskRequest(TaskRequestsConstants.T_BLOCK_SIGNAL, null, null));
226                    return;
227                }
228                LoggerFactory.getLogger(ExportDataSupport.class).error("Print lines");
229                printLines(results);
230                PluginController.getInstance().addTask(new TaskRequest(TaskRequestsConstants.T_BLOCK_SIGNAL, null, null));
231
232            } catch (Exception ex) 
233            {
234                LoggerFactory.getLogger(ExportDataSupport.class).error(ex.getMessage(), ex);
235            }
236        }
237    }
238}