package org.marketcetera.orderloader;
import static org.marketcetera.orderloader.Messages.*;
import java.io.File;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.cli.*;
import org.marketcetera.client.ClientParameters;
import org.marketcetera.core.ApplicationContainer;
import org.marketcetera.core.ApplicationVersion;
import org.marketcetera.trade.BrokerID;
import org.marketcetera.util.except.I18NException;
import org.marketcetera.util.log.SLF4JLoggerProxy;
import org.marketcetera.util.misc.ClassVersion;
import org.springframework.context.Lifecycle;
/* $License$ */
/**
* The entry point for running the order loader as an application
*
* @author anshul@marketcetera.com
* @author <a href="mailto:colin@marketcetera.com">Colin DuPlantis</a>
* @version $Id: OrderLoaderMain.java 16841 2014-02-20 19:59:04Z colin $
* @since 1.0.0
*/
@ClassVersion("$Id: OrderLoaderMain.java 16841 2014-02-20 19:59:04Z colin $")
public class OrderLoaderMain
implements Lifecycle
{
/* (non-Javadoc)
* @see org.springframework.context.Lifecycle#isRunning()
*/
@Override
public boolean isRunning()
{
return running.get();
}
/* (non-Javadoc)
* @see org.springframework.context.Lifecycle#start()
*/
@Override
public void start()
{
run(getArgs());
running.set(true);
exit();
}
/* (non-Javadoc)
* @see org.springframework.context.Lifecycle#stop()
*/
@Override
public void stop()
{
running.set(false);
}
/**
* Get the clientUsername value.
*
* @return a <code>String</code> value
*/
public String getClientUsername()
{
return clientUsername;
}
/**
* Sets the clientUsername value.
*
* @param inClientUsername a <code>String</code> value
*/
public void setClientUsername(String inClientUsername)
{
clientUsername = inClientUsername;
}
/**
* Sets the clientPassword value.
*
* @param inClientPassword a <code>char[]</code> value
*/
public void setClientPassword(char[] inClientPassword)
{
clientPassword = inClientPassword;
}
/**
* Get the clientURL value.
*
* @return a <code>String</code> value
*/
public String getClientURL()
{
return clientURL;
}
/**
* Sets the clientURL value.
*
* @param inClientURL a <code>String</code> value
*/
public void setClientURL(String inClientURL)
{
clientURL = inClientURL;
}
/**
* Get the clientWsHost value.
*
* @return a <code>String</code> value
*/
public String getClientWsHost()
{
return clientWsHost;
}
/**
* Sets the clientWsHost value.
*
* @param inClientWsHost a <code>String</code> value
*/
public void setClientWsHost(String inClientWsHost)
{
clientWsHost = inClientWsHost;
}
/**
* Get the clientIdPrefix value.
*
* @return a <code>String</code> value
*/
public String getClientIdPrefix()
{
return clientIdPrefix;
}
/**
* Sets the clientIdPrefix value.
*
* @param inClientIdPrefix a <code>String</code> value
*/
public void setClientIdPrefix(String inClientIdPrefix)
{
clientIdPrefix = inClientIdPrefix;
}
/**
* Get the clientWsPort value.
*
* @return a <code>String</code> value
*/
public String getClientWsPort()
{
return clientWsPort;
}
/**
* Sets the clientWsPort value.
*
* @param inClientWsPort a <code>String</code> value
*/
public void setClientWsPort(String inClientWsPort)
{
clientWsPort = inClientWsPort;
}
/**
* Sets the stream on which all the messages should be printed.
*
* @param inMsgStream the message stream on which all the messages should
* be printed.
*/
protected void setMsgStream(PrintStream inMsgStream)
{
mMsgStream = inMsgStream;
}
/**
* Exits the current process with the supplied exit code.
*/
protected void exit()
{
ApplicationContainer.stopInstanceWaiting();
}
/**
*
*
*
* @return
*/
protected String[] getArgs()
{
return ApplicationContainer.getInstanceArguments();
}
/**
* Reads the orders from the supplied and sends them to the server.
*
* @throws Exception if there were errors.
*/
protected void doProcessing()
throws Exception
{
// create the order processor
ClientParameters parameters = new ClientParameters(clientUsername,
clientPassword,
clientURL,
clientWsHost,
Integer.parseInt(clientWsPort),
clientIdPrefix);
OrderProcessor processor = createProcessor(parameters);
// run the order loader and display the summary of results.
try {
displaySummary(new OrderLoader(mMode,
mBrokerID,
processor,
new File(mFilename)));
} finally {
processor.done();
}
}
/**
* Creates a processor given the parameters.
* <p>
* This method is an implementation artifact to aid unit testing.
*
* @param inParameters the parameters to connect to the server.
*
* @return the order processor that will send orders to the server.
*
* @throws Exception if there were errors creating the order processor.
*/
protected OrderProcessor createProcessor(ClientParameters inParameters)
throws Exception
{
return new ServerOrderProcessor(inParameters);
}
/**
* Displays the summary of results after the order loader is done processing.
*
* @param inLoader the order loader instance.
*/
protected void displaySummary(OrderLoader inLoader)
{
printMessage(LINE_SUMMARY.getText(inLoader.getNumLines(),
inLoader.getNumBlankLines(),
inLoader.getNumComments()));
printMessage(ORDER_SUMMARY.getText(inLoader.getNumSuccess(),
inLoader.getNumFailed()));
List<FailedOrderInfo> list = inLoader.getFailedOrders();
if(!list.isEmpty()) {
printMessage(FAILED_ORDERS.getText());
for(FailedOrderInfo info: list) {
printMessage(FAILED_ORDER.getText(info.getIndex(),
Arrays.toString(info.getRow()),
getExceptionMsg(info.getException())));
}
}
}
/**
* Prints the message to the output.
*
* @param inMessage the message to print.
*/
protected void printMessage(String inMessage)
{
mMsgStream.println(inMessage);
}
/**
* Prints the supplied exception's message to the output.
*
* @param inException the exception whose messages should be
* printed on the output.
*/
protected void printError(Exception inException)
{
printMessage(getExceptionMsg(inException));
SLF4JLoggerProxy.debug(this,
inException);
}
/**
* Gets the exception message from the supplied exception.
*
* @param inException the exception
*
* @return the message from the exception.
*/
protected String getExceptionMsg(Exception inException)
{
if(inException instanceof I18NException) {
return ((I18NException)inException).getLocalizedDetail();
} else {
return inException.getLocalizedMessage();
}
}
/**
* Runs the supplied instance given the arguments.
*
* @param inArgs the command line arguments to run.
*/
private void run(String[] inArgs)
{
printMessage(LOG_APP_COPYRIGHT.getText());
printMessage(LOG_APP_VERSION_BUILD.getText(ApplicationVersion.getVersion(),
ApplicationVersion.getBuildNumber()));
try {
execute(new GnuParser().parse(options(),
inArgs));
} catch (Exception e) {
printError(e);
usage();
}
}
/**
* Executes the given parsed command line.
*
* @param inLine a <code>CommandLine</code> value
* @throws Exception if an error occurs parsing the command line
*/
private void execute(CommandLine inLine)
throws Exception
{
if(inLine.hasOption(OPT_USERNAME)) {
clientUsername = inLine.getOptionValue(OPT_USERNAME);
}
if(inLine.hasOption(OPT_PASSWORD)) {
clientPassword = inLine.getOptionValue(OPT_PASSWORD).toCharArray();
}
if(inLine.hasOption(OPT_MODE)) {
mMode = inLine.getOptionValue(OPT_MODE);
}
if(inLine.hasOption(OPT_BROKER)) {
mBrokerID = new BrokerID(inLine.getOptionValue(OPT_BROKER));
}
if(inLine.getArgList().isEmpty()) {
throw new IllegalArgumentException(ERROR_MISSING_FILE.getText());
} else {
mFilename = String.valueOf(inLine.getArgList().remove(0));
}
if(!inLine.getArgList().isEmpty()) {
throw new IllegalArgumentException(ERROR_TOO_MANY_ARGUMENTS.getText());
}
doProcessing();
}
/**
* Constructs the command line options for the orderloader.
*
* @return an <code>Options</code> value
*/
@SuppressWarnings("static-access")
private static Options options()
{
Options opts = new Options();
opts.addOption(OptionBuilder.hasArg().withArgName(ARG_MODE_VALUE.getText()).withDescription(ARG_MODE_DESCRIPTION.getText()).isRequired(false).create(OPT_MODE));
opts.addOption(OptionBuilder.hasArg().withArgName(ARG_BROKER_VALUE.getText()).withDescription(ARG_BROKER_DESCRIPTION.getText()).isRequired(false).create(OPT_BROKER));
opts.addOption(OptionBuilder.hasArg().withArgName(ARG_USERNAME_VALUE.getText()).withDescription(ARG_USERNAME_DESCRIPTION.getText()).isRequired(false).create(OPT_USERNAME));
opts.addOption(OptionBuilder.hasArg().withArgName(ARG_PASSWORD_VALUE.getText()).withDescription(ARG_PASSWORD_DESCRIPTION.getText()).isRequired(false).create(OPT_PASSWORD));
return opts;
}
/**
* Prints the usage to the output.
*/
private void usage()
{
HelpFormatter formatter = new HelpFormatter();
PrintWriter pw = new PrintWriter(mMsgStream);
pw.append(ERROR_USAGE.getText());
pw.println();
formatter.printOptions(pw,
HelpFormatter.DEFAULT_WIDTH,
options,
HelpFormatter.DEFAULT_LEFT_PAD,
HelpFormatter.DEFAULT_DESC_PAD);
pw.println();
pw.flush();
exit();
}
/**
* options value contains all command line options
*/
private final Options options = options();
/**
* print stream used to render output
*/
private PrintStream mMsgStream = System.err;
/**
* FIX mode to use
*/
private String mMode;
/**
* broker ID to use
*/
private BrokerID mBrokerID;
/**
* filename to parse
*/
private String mFilename;
/**
*
*/
private static final String OPT_MODE = "m"; //$NON-NLS-1$
/**
*
*/
private static final String OPT_BROKER = "b"; //$NON-NLS-1$
/**
*
*/
private static final String OPT_USERNAME = "u"; //$NON-NLS-1$
/**
*
*/
private static final String OPT_PASSWORD = "p"; //$NON-NLS-1$
/**
* indicates if the order loader is running or not
*/
private final AtomicBoolean running = new AtomicBoolean(false);
private String clientUsername;
/**
*
*/
private char[] clientPassword;
/**
*
*/
private String clientURL;
/**
*
*/
private String clientWsHost;
/**
*
*/
private String clientIdPrefix;
/**
*
*/
private String clientWsPort;
}