001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy 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 * Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.search; 020 021import icy.network.NetworkUtil; 022import icy.network.URLUtil; 023import icy.network.WebInterface; 024import icy.system.IcyExceptionHandler; 025import icy.system.thread.ThreadUtil; 026import icy.util.StringUtil; 027import icy.util.XMLUtil; 028 029import java.net.URLEncoder; 030 031import org.w3c.dom.Document; 032 033/** 034 * The OnlineSearchResultProducer is the basic class for {@link SearchResult} producer from online 035 * results.<br> 036 * It does use a single static instance to do the online search then dispatch XML result the 037 * overriding class. 038 * 039 * @author Stephane Dallongeville 040 * @see SearchResultProducer 041 */ 042public abstract class OnlineSearchResultProducer extends SearchResultProducer 043{ 044 /** 045 * @deprecated Use {@link WebInterface#doSearch(String, String)} instead 046 */ 047 @Deprecated 048 protected static final String SEARCH_URL = NetworkUtil.WEBSITE_URL + "search/search.php?search="; 049 050 public static final long REQUEST_INTERVAL = 250; 051 public static final long MAXIMUM_SEARCH_TIME = 5000; 052 053 @Override 054 public void doSearch(String text, SearchResultConsumer consumer) 055 { 056 // nothing to do here 057 if (StringUtil.isEmpty(text)) 058 return; 059 060 final long startTime = System.currentTimeMillis(); 061 062 // wait interval elapsed before sending request (avoid website request spam) 063 while ((System.currentTimeMillis() - startTime) < REQUEST_INTERVAL) 064 { 065 ThreadUtil.sleep(10); 066 // abort 067 if (hasWaitingSearch()) 068 return; 069 } 070 071 int retry = 0; 072 073 Document document = null; 074 // let's 5 tries to get the result 075 while (((System.currentTimeMillis() - startTime) < MAXIMUM_SEARCH_TIME) && (document == null) && (retry < 5)) 076 { 077 try 078 { 079 // do the search request 080 document = doSearchRequest(text); 081 } 082 catch (Exception e) 083 { 084 IcyExceptionHandler.showErrorMessage(e, false); 085 } 086 087 // abort 088 if (hasWaitingSearch()) 089 return; 090 091 // error ? --> wait a bit before retry 092 if (document == null) 093 ThreadUtil.sleep(100); 094 095 retry++; 096 } 097 098 // can't get result from website or another search done --> abort 099 if (hasWaitingSearch() || (document == null)) 100 return; 101 102 doSearch(document, text, consumer); 103 } 104 105 /** 106 * Default implementation for the search request, override it if needed 107 * 108 * @throws Exception 109 */ 110 protected Document doSearchRequest(String text) throws Exception 111 { 112 // send request to website and get result 113 return XMLUtil.loadDocument(URLUtil.getURL(SEARCH_URL + URLEncoder.encode(text, "UTF-8")), true); 114 115 // by default we use the default WEB interface search 116 // TODO: uncomment when ready 117 // return WebInterface.doSearch(text); 118 } 119 120 /** 121 * @deprecated Use {@link #doSearch(Document, String, SearchResultConsumer)} instead 122 */ 123 @Deprecated 124 public void doSearch(Document doc, String[] words, SearchResultConsumer consumer) 125 { 126 // default implementation, does nothing... 127 } 128 129 public void doSearch(Document doc, String text, SearchResultConsumer consumer) 130 { 131 // by default this implementation use separated word search for backward compatibility 132 doSearch(doc, text.split(" "), consumer); 133 } 134}