package com.limegroup.gnutella.gui.search;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.StringTokenizer;
import java.util.Map;
import java.util.HashMap;
import com.limegroup.gnutella.MediaType;
import com.limegroup.gnutella.gui.GUIMediator;
import com.limegroup.gnutella.util.IpPort;
/**
* Simple struct-like class containing information about a search.
*/
public class SearchInformation {
/** Constants used to serialize the search information to Map. */
/** Key in map which holds property {@link #type}. */
private static final String MAP_TYPE = "type";
/** Key in map which holds property {@link #query}. */
private static final String MAP_QUERY = "query";
/** Key in map which holds property {@link #xml}. */
private static final String MAP_XML = "xml";
/** Key in map which holds property {@link #media}. */
private static final String MAP_MEDIA = "media";
/** Key in map which holds property {@link #title}. */
private static final String MAP_TITLE = "title";
/**
* A keyword search.
*/
public static final int KEYWORD = 0;
/**
* A what is new search.
*/
public static final int WHATS_NEW = 1;
/**
* A browse host search.
*/
public static final int BROWSE_HOST = 2;
/**
* The string to use to describe a what's new search.
*/
public static final String WHATS_NEW_DESC =
GUIMediator.getStringResource("SEARCH_WHATS_NEW_SMALL");
/**
* The kind of search this is.
*/
private final int type;
/**
* The simple query string.
*/
private final String query;
/**
* The XML string.
*/
private final String xml;
/**
* The MediaType of the search.
*/
private final MediaType media;
/**
* The title of this search as it is displayed to the user.
*/
private final String title;
/**
* Private constructor -- use factory methods instead.
* @param title can be <code>null</code>, then the query is used.
*/
private SearchInformation(int type, String query, String xml,
MediaType media, String title) {
if(media == null)
throw new NullPointerException("null media");
if(query == null)
throw new NullPointerException("null query");
this.type = type;
this.query = query.trim();
this.xml = xml;
this.media = media;
this.title = title != null ? title : query;
}
private SearchInformation(int type, String query, String xml,
MediaType media) {
this(type, query, xml, media, null);
}
/**
* Creates a new keyword, but state is loaded from Map generated
* by {@link toMap()}.
* @param map The map with storred state.
* @see toMap()
* @see fromMap(Map)
*/
private SearchInformation(Map map) {
Integer type = (Integer) map.get(MAP_TYPE);
if ( type == null )
throw new NullPointerException("null type");
this.type = type.intValue();
query = (String) map.get(MAP_QUERY);
xml = (String) map.get(MAP_XML);
media = (MediaType) map.get(MAP_MEDIA);
title = (String) map.get(MAP_TITLE);
if(media == null)
throw new NullPointerException("null media");
if(query == null)
throw new NullPointerException("null query");
}
/**
* Creates a keyword search.
*/
public static SearchInformation createKeywordSearch(String query,
String xml,
MediaType media) {
return new SearchInformation(KEYWORD, query, xml, media);
}
/**
* Creates a keyword search with a title different from the query string.
* @param query
* @param xml
* @param media
* @param title
* @return
*/
public static SearchInformation createTitledKeyWordSearch(String query,
String xml, MediaType media, String title) {
return new SearchInformation(KEYWORD, query, xml, media, title);
}
/**
* Creates a what's new search.
*/
public static SearchInformation createWhatsNewSearch(String name, MediaType type){
return new SearchInformation(WHATS_NEW,
WHATS_NEW_DESC + " - " + name, null, type);
}
/**
* Create's a browse host search.
*/
public static SearchInformation createBrowseHostSearch(String desc) {
return new SearchInformation(BROWSE_HOST, desc, null,
MediaType.getAnyTypeMediaType());
}
/**
* Retrieves the basic query of the search.
*/
public String getQuery() {
return query;
}
/**
* Retrieves the XML portion of the search.
*/
public String getXML() {
return xml;
}
/**
* Retrieves the MediaType of the search.
*/
public MediaType getMediaType() {
return media;
}
public String getTitle() {
return title;
}
/**
* Gets the IP/Port if this is a browse-host.
*/
IpPort getIpPort() {
if(!isBrowseHostSearch())
throw new IllegalStateException();
StringTokenizer st = new StringTokenizer(getQuery(), ":");
String host = null;
int port = 6346;
if (st.hasMoreTokens())
host = st.nextToken();
if (st.hasMoreTokens()) {
try {
port = Integer.parseInt(st.nextToken());
} catch(NumberFormatException ignored) {}
}
InetAddress addr = null;
try {
addr = InetAddress.getByName(host);
} catch(UnknownHostException ignored) {}
final String _host = host;
final int _port = port;
final InetAddress _addr = addr;
return new IpPort() {
public InetAddress getInetAddress() { return _addr; }
public String getAddress() { return _host; }
public int getPort() { return _port; }
};
}
/**
* Determines whether or not this is an XML search.
*/
public boolean isXMLSearch() {
return xml != null && !xml.equals("");
}
/**
* Determines if this is a keyword search.
*/
public boolean isKeywordSearch() {
return type == KEYWORD;
}
/**
* Determines if this is a what's new search.
*/
public boolean isWhatsNewSearch() {
return type == WHATS_NEW;
}
/**
* Determines if this is a browse host search.
*/
public boolean isBrowseHostSearch() {
return type == BROWSE_HOST;
}
/**
* Converts state storred in the object into map. In this way, state
* can be storred in classes unawre of this class existance.
* @return A map which holds parameters of the class.
* @see fromMap()
* @see SearchInformation(Map)
*/
public Map toMap() {
Map map = new HashMap();
map.put(MAP_TYPE, new Integer(type));
map.put(MAP_QUERY, query);
map.put(MAP_XML, xml);
map.put(MAP_MEDIA, media);
map.put(MAP_TITLE, title);
return map;
}
/**
* Creates a new keyword, but state is loaded from map generated
* by {@link toMap()}.
* @param map The map with storred state.
* @see toMap()
* @see SearchInformation(Map)
*/
public static SearchInformation createFromMap(Map map) {
return new SearchInformation(map);
}
}