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-ext.
005 *
006 * Dicoogle/dicoogle-sdk-ext 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-ext 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.p2p.Messages.Handlers;
020
021import java.io.ByteArrayInputStream;
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027import java.util.Observable;
028import java.util.Observer;
029import org.slf4j.LoggerFactory;
030import org.dom4j.Document;
031import org.dom4j.DocumentException;
032import org.dom4j.Element;
033import org.dom4j.io.SAXReader;
034import pt.ua.dicoogle.sdk.NetworkPluginAdapter;
035import pt.ua.dicoogle.sdk.Utils.TaskRequest;
036import pt.ua.dicoogle.sdk.Utils.TaskRequestsConstants;
037import pt.ua.dicoogle.sdk.datastructs.SearchResult;
038import pt.ua.dicoogle.sdk.p2p.Messages.Builders.MessageBuilder;
039import pt.ua.dicoogle.sdk.p2p.Messages.MessageFields;
040import pt.ua.dicoogle.sdk.p2p.Messages.MessageI;
041import pt.ua.dicoogle.sdk.p2p.Messages.MessageXML;
042
043/**
044 *
045 * @author Carlos Ferreira
046 * @author Pedro Bento
047 */
048public class QueryHandler implements MessageHandler, Observer
049{
050
051    private int maxResultsPerMessage;
052    //private ListObservable<TaskRequest> tasks;
053    private NetworkPluginAdapter plugin;
054
055    public QueryHandler(int maxResultsPerMessage, NetworkPluginAdapter plugin)
056    {
057        this.plugin = plugin;
058        this.maxResultsPerMessage = maxResultsPerMessage;
059    }
060
061    public void handleMessage(MessageI message, String sender)
062    {
063        if (!MessageXML.class.isInstance(message))
064        {
065            return;
066        }
067
068        byte[] msg = (byte[]) message.getMessage();
069
070        SAXReader saxReader = new SAXReader();
071
072        Document document = null;
073        try
074        {
075            document = saxReader.read(new ByteArrayInputStream(msg));
076        } catch (DocumentException ex)
077        {
078            ex.printStackTrace(System.out);
079        }
080
081        /**
082         * Reading the message XML, getting the necessary fields.
083         */
084        Element root = document.getRootElement();
085        String query;
086        Element queryNumber = root.element(MessageFields.QUERY_NUMBER);
087        List<String> extra = new ArrayList();
088        Element queryE = root.element(MessageFields.QUERY);
089        /**
090         * If the message has not the query element, then it is an invalid message
091         * ignore it.
092         */
093        if (queryE == null)
094        {
095            return;
096        }
097        query = queryE.getText();
098        List<Element> extrafields = root.elements(MessageFields.EXTRAFIELD);
099        if (extrafields == null)
100        {
101            extrafields = new ArrayList();
102        }
103        for (Element extrafield : extrafields)
104        {
105            extra.add(extrafield.getText());
106        }
107
108        /**
109         * Local search.
110         */
111        Map<Integer, Object> parameters = new HashMap<Integer, Object>();
112        parameters.put(TaskRequestsConstants.P_QUERY, query);
113        parameters.put(TaskRequestsConstants.P_EXTRAFIELDS, extra);
114        parameters.put(TaskRequestsConstants.P_REQUESTER_ADDRESS, sender);
115        parameters.put(TaskRequestsConstants.P_QUERY_NUMBER, queryNumber.getText());
116
117        TaskRequest task = new TaskRequest(TaskRequestsConstants.T_QUERY_LOCALLY,
118                this.plugin.getName(), parameters);
119        task.addObserver(this);
120
121        this.plugin.getTaskRequestsList().addTask(task);
122
123
124        // ArrayList<SearchResult> resultsAll = IndexEngine.getInstance().search(query, extra);
125        //
126    }
127
128    public void update(Observable o, Object arg)
129    {
130
131        if (!TaskRequest.class.isInstance(o))
132        {
133            return;
134        }
135
136        TaskRequest task = (TaskRequest) o;
137
138
139        Map<Integer, Object> res = task.getResults();
140        Object SR = res.get(TaskRequestsConstants.R_SEARCH_RESULTS);
141        if ((SR == null) || (!ArrayList.class.isInstance(SR)))
142        {
143            return;
144        }
145
146        ArrayList<SearchResult> resultsAll = (ArrayList<SearchResult>) SR;
147        List<SearchResult> results;
148        /**
149         * Build of the response for the query
150         */
151        MessageBuilder builder = new MessageBuilder();
152        MessageI newMessage = null;
153        for (int i = 0; i < resultsAll.size(); i += maxResultsPerMessage)
154        {
155            int size = maxResultsPerMessage;
156            if (i + maxResultsPerMessage > resultsAll.size())
157            {
158                size = resultsAll.size() - i;
159            }
160
161            results = resultsAll.subList(i, i + size);
162            try
163            {
164                newMessage = builder.buildQueryResponse(results, (String) task.getParameters().get(TaskRequestsConstants.P_QUERY_NUMBER), this.plugin.getName());
165            } catch (IOException ex)
166            {
167                LoggerFactory.getLogger(QueryHandler.class).error(ex.getMessage(), ex);
168            }
169
170            /**
171             * Sending the response
172             */
173            if (newMessage != null)
174            {
175                
176                this.plugin.send(newMessage, (String) task.getParameters().get(TaskRequestsConstants.P_REQUESTER_ADDRESS));
177            }
178        }
179    }
180}