SearchCLI.java

package gov.usgs.earthquake.indexer;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.logging.Logger;

import gov.usgs.earthquake.product.ProductId;
import gov.usgs.util.XmlUtils;

/**
 * Command line interface for search socket.
 *
 * This class reads arguments from the command line that represent a
 * ProductIndexQuery. Then it connects to a configured socket, executes the
 * search, and outputs the response xml.
 */
public class SearchCLI {

	private static final Logger LOGGER = Logger.getLogger(SearchCLI.class
			.getName());

	/**
	 * Command-line argument definitions
	 */
	/** Argument for search method */
	public static String SEARCH_METHOD_ARGUMENT = "--searchMethod=";
	/** Argument for result type */
	public static String RESULT_TYPE_ARGUMENT = "--resultType=";
	/** Argument for event Source */
	public static String EVENT_SOURCE_ARGUMENT = "--eventSource=";
	/** Argument for event Source Code */
	public static String EVENT_SOURCE_CODE_ARGUMENT = "--eventSourceCode=";
	/** Argument for minimum Event Time */
	public static String MIN_EVENT_TIME_ARGUMENT = "--minEventTime=";
	/** Argument for maximum event time */
	public static String MAX_EVENT_TIME_ARGUMENT = "--maxEventTime=";
	/** Argument for minimum event latitude */
	public static String MIN_EVENT_LATITUDE_ARGUMENT = "--minEventLatitude=";
	/** Argument for minimum event longitude */
	public static String MIN_EVENT_LONGITUDE_ARGUMENT = "--minEventLongitude=";
	/** Argument for maximum event latitude */
	public static String MAX_EVENT_LATITUDE_ARGUMENT = "--maxEventLatitude=";
	/** Argument for maximum event longitude */
	public static String MAX_EVENT_LONGITUDE_ARGUMENT = "--maxEventLongitude=";
	/** Argument for minimum event depth */
	public static String MIN_EVENT_DEPTH_ARGUMENT = "--minEventDepth=";
	/** Argument for maximum event depth */
	public static String MAX_EVENT_DEPTH_ARGUMENT = "--maxEventDepth=";
	/** Argument for minimum event magnitude */
	public static String MIN_EVENT_MAGNITUDE_ARGUMENT = "--minEventMagnitude=";
	/** Argument for maximum event magnitude */
	public static String MAX_EVENT_MAGNITUDE_ARGUMENT = "--maxEventMagnitude=";
	/** Argument for product ID */
	public static String PRODUCT_ID_ARGUMENT = "--productId=";
	/** Argument for  minimum product update time */
	public static String MIN_PRODUCT_UPDATE_TIME_ARGUMENT = "--minProductUpdateTime=";
	/** Argument for maximum product update time */
	public static String MAX_PRODUCT_UPDATE_TIME_ARGUMENT = "--maxProductUpdateTime=";
	/** Argument for product source */
	public static String PRODUCT_SOURCE_ARGUMENT = "--productSource=";
	/** Argument for product type */
	public static String PRODUCT_TYPE_ARGUMENT = "--productType=";
	/** Argument for product verion */
	public static String PRODUCT_VERSION_ARGUMENT = "--productVersion=";
	/** Argument for product status */
	public static String PRODUCT_STATUS_ARGUMENT = "--productStatus=";

	/** Argument for search host */
	public static String SEARCH_HOST_ARGUMENT = "--searchHost=";
	/** Argument for search port */
	public static String SEARCH_PORT_ARGUMENT = "--searchPort=";

	/** Argument for file output */
	public static String FILE_OUTPUT_ARGUMENT = "--outputFile=";

	/**
	 * Default constructor, for configurable interface.
	 */
	public SearchCLI() {
	}

	/**
	 * Entry point into search. Called by Main when the --search argument is
	 * used.
	 *
	 * @param args
	 *            command line arguments.
	 * @throws Exception if error occurs
	 */
	public static void main(final String[] args) throws Exception {
		String outputFilePath = null;
		SearchMethod type = null;
		InetAddress host = InetAddress.getByName("localhost");
		int port = Integer.parseInt(SearchServerSocket.DEFAULT_SEARCH_PORT);
		ProductIndexQuery query = new ProductIndexQuery();
		// Alternate result types are currently not supported.
		query.setResultType(ProductIndexQuery.RESULT_TYPE_CURRENT);
		for (String arg : args) {
			if (arg.startsWith(SEARCH_METHOD_ARGUMENT)) {
				type = SearchMethod.fromXmlMethodName(arg.replace(
						SEARCH_METHOD_ARGUMENT, ""));
				if (type == null) {
					LOGGER.severe("Undefined search method received: '"
							+ arg.replace(SEARCH_METHOD_ARGUMENT, "")
							+ "'. Search could not be processed.");
					throw new Exception();
				}
				/*
				 * Alternate result types are currently not supported. } else if
				 * (arg.startsWith(RESULT_TYPE_ARGUMENT)) { String resultType =
				 * arg.replace(RESULT_TYPE_ARGUMENT, ""); if
				 * (resultType.toLowerCase() == "current")
				 * query.setResultType(ProductIndexQuery.RESULT_TYPE_CURRENT);
				 * else if (resultType.toLowerCase() == "superseded")
				 * query.setResultType
				 * (ProductIndexQuery.RESULT_TYPE_SUPERSEDED); else if
				 * (resultType.toLowerCase() == "all")
				 * query.setResultType(ProductIndexQuery.RESULT_TYPE_ALL);
				 */
			} else if (arg.startsWith(EVENT_SOURCE_ARGUMENT)) {
				query.setEventSource(arg.replace(EVENT_SOURCE_ARGUMENT, ""));
			} else if (arg.startsWith(EVENT_SOURCE_CODE_ARGUMENT)) {
				query.setEventSourceCode(arg.replace(
						EVENT_SOURCE_CODE_ARGUMENT, ""));
			} else if (arg.startsWith(MIN_EVENT_TIME_ARGUMENT)) {
				query.setMinEventTime(XmlUtils.getDate(arg.replace(
						MIN_EVENT_TIME_ARGUMENT, "")));
			} else if (arg.startsWith(MAX_EVENT_TIME_ARGUMENT)) {
				query.setMaxEventTime(XmlUtils.getDate(arg.replace(
						MAX_EVENT_TIME_ARGUMENT, "")));
			} else if (arg.startsWith(MIN_EVENT_LATITUDE_ARGUMENT)) {
				query.setMinEventLatitude(new BigDecimal(arg.replace(
						MIN_EVENT_LATITUDE_ARGUMENT, "")));
			} else if (arg.startsWith(MIN_EVENT_LONGITUDE_ARGUMENT)) {
				query.setMinEventLongitude(new BigDecimal(arg.replace(
						MIN_EVENT_LONGITUDE_ARGUMENT, "")));
			} else if (arg.startsWith(MIN_EVENT_DEPTH_ARGUMENT)) {
				query.setMinEventDepth(new BigDecimal(arg.replace(
						MIN_EVENT_DEPTH_ARGUMENT, "")));
			} else if (arg.startsWith(MAX_EVENT_LATITUDE_ARGUMENT)) {
				query.setMaxEventLatitude(new BigDecimal(arg.replace(
						MAX_EVENT_LATITUDE_ARGUMENT, "")));
			} else if (arg.startsWith(MAX_EVENT_LONGITUDE_ARGUMENT)) {
				query.setMaxEventLongitude(new BigDecimal(arg.replace(
						MAX_EVENT_LONGITUDE_ARGUMENT, "")));
			} else if (arg.startsWith(MAX_EVENT_DEPTH_ARGUMENT)) {
				query.setMaxEventDepth(new BigDecimal(arg.replace(
						MAX_EVENT_DEPTH_ARGUMENT, "")));
			} else if (arg.startsWith(MIN_EVENT_MAGNITUDE_ARGUMENT)) {
				query.setMinEventMagnitude(new BigDecimal(arg.replace(
						MIN_EVENT_MAGNITUDE_ARGUMENT, "")));
			} else if (arg.startsWith(MAX_EVENT_MAGNITUDE_ARGUMENT)) {
				query.setMaxEventMagnitude(new BigDecimal(arg.replace(
						MAX_EVENT_MAGNITUDE_ARGUMENT, "")));
			} else if (arg.startsWith(PRODUCT_ID_ARGUMENT)) {
				query.getProductIds().add(
						ProductId.parse(arg.replace(PRODUCT_ID_ARGUMENT, "")));
			} else if (arg.startsWith(PRODUCT_SOURCE_ARGUMENT)) {
				query.setProductSource(arg.replace(PRODUCT_SOURCE_ARGUMENT, ""));
			} else if (arg.startsWith(PRODUCT_STATUS_ARGUMENT)) {
				query.setProductStatus(arg.replace(PRODUCT_STATUS_ARGUMENT, ""));
			} else if (arg.startsWith(PRODUCT_TYPE_ARGUMENT)) {
				query.setProductType(arg.replace(PRODUCT_TYPE_ARGUMENT, ""));
			} else if (arg.startsWith(PRODUCT_VERSION_ARGUMENT)) {
				query.setProductVersion(arg.replace(PRODUCT_VERSION_ARGUMENT,
						""));
			} else if (arg.startsWith(SEARCH_HOST_ARGUMENT)) {
				host = InetAddress.getByName(arg.replace(SEARCH_HOST_ARGUMENT,
						""));
			} else if (arg.startsWith(SEARCH_PORT_ARGUMENT)) {
				port = Integer.parseInt(arg.replace(SEARCH_PORT_ARGUMENT, ""));
			} else if (arg.startsWith(FILE_OUTPUT_ARGUMENT)) {
				outputFilePath = arg.replace(FILE_OUTPUT_ARGUMENT, "");
			}
		}
		SearchRequest request = new SearchRequest();
		if (type == null) {
			LOGGER.severe("No search type was provided.");
		}
		OutputStream stream;
		if (outputFilePath != null) {
			stream = new FileOutputStream(FILE_OUTPUT_ARGUMENT);
		} else {
			stream = System.out;
		}
		request.addQuery(SearchQuery.getSearchQuery(type, query));

		SearchSocket socket = new SearchSocket(host, port);
		socket.search(request, stream);
	}

	/**
	 * CLI Usage
	 * @return string of usage
	 */
	public static String getUsage() {
		StringBuffer buf = new StringBuffer();

		buf.append("Product Index Search Interface:\n");
		buf.append("--search : Command is using the search interface\n");
		buf.append(SEARCH_METHOD_ARGUMENT + "METHOD : Any one of ");
		SearchMethod[] methods = SearchMethod.values();
		for (int i = 0; i < methods.length; i++) {
			buf.append("'" + methods[i].getXmlMethodName() + "'");
			if (i < methods.length - 1) {
				buf.append(", ");
			} else {
				buf.append("\n");
			}
		}
		buf.append("[" + EVENT_SOURCE_ARGUMENT
				+ "SOURCE] : Filter results by event source network.\n");
		buf.append("[" + EVENT_SOURCE_CODE_ARGUMENT
				+ "CODE] : Filter results by event source network code.\n");
		buf.append("["
				+ MIN_EVENT_TIME_ARGUMENT
				+ "XML_FORMATTED_TIME] : Filter results by start of time window.\n");
		buf.append("["
				+ MAX_EVENT_TIME_ARGUMENT
				+ "XML_FORMATTED_TIME] : Filter results by end of time window.\n");
		buf.append("[" + MIN_EVENT_LATITUDE_ARGUMENT
				+ "LATITUDE] : Filter results by Southern boundary.\n");
		buf.append("[" + MAX_EVENT_LATITUDE_ARGUMENT
				+ "LATITUDE] : Filter results by Northern boundary.\n");
		buf.append("[" + MIN_EVENT_LONGITUDE_ARGUMENT
				+ "LONGITUDE] : Filter results by Western boundary.\n");
		buf.append("[" + MAX_EVENT_LONGITUDE_ARGUMENT
				+ "LONGITUDE] : Filter results by Eastern boundary.\n");
		buf.append("[" + MIN_EVENT_DEPTH_ARGUMENT
				+ "DEPTH] : Filter results by minimum depth in km.\n");
		buf.append("[" + MAX_EVENT_DEPTH_ARGUMENT
				+ "DEPTH] : Filter results by maximum depth in km.\n");
		buf.append("[" + MIN_EVENT_MAGNITUDE_ARGUMENT
				+ "MAGNITUDE] : Filter results by minimum magnitude.\n");
		buf.append("[" + MAX_EVENT_MAGNITUDE_ARGUMENT
				+ "MAGNITUDE] : Filter results by maximum magnitude.\n");
		buf.append("["
				+ PRODUCT_ID_ARGUMENT
				+ "PRODUCT_ID] : Filter by product ID. Each time this appears the new ID is added.\n");
		buf.append("[" + PRODUCT_SOURCE_ARGUMENT
				+ "SOURCE] : Filter results by product source.\n");
		buf.append("[" + PRODUCT_STATUS_ARGUMENT
				+ "STATUS] : Filter results by product status.\n");
		buf.append("[" + PRODUCT_TYPE_ARGUMENT
				+ "TYPE] : Filter results by product type.\n");
		buf.append("[" + PRODUCT_VERSION_ARGUMENT
				+ "VERSION] : Filter results by product version.\n");
		buf.append("["
				+ SEARCH_HOST_ARGUMENT
				+ "HOST] : The Product Index host to receive this query. Default is localhost.");
		buf.append("["
				+ SEARCH_PORT_ARGUMENT
				+ "PORT] : The port on which to execute this query. Default is "
				+ SearchServerSocket.DEFAULT_SEARCH_PORT + ".\n");
		buf.append("["
				+ FILE_OUTPUT_ARGUMENT
				+ "FILE] : The file to write output to. If this is not included, output will be directed over stdout.");

		return buf.toString();
	}

}