package org.cryptocoinpartners.bin;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import org.apache.commons.configuration.ConfigurationException;
import org.cryptocoinpartners.module.ApplicationInitializer;
import org.cryptocoinpartners.module.StaticInjectionModule;
import org.cryptocoinpartners.util.ConfigUtil;
import org.cryptocoinpartners.util.Injector;
import org.cryptocoinpartners.util.ReflectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.beust.jcommander.DynamicParameter;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.MissingCommandException;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
/**
* This is the only entry point required into the Cryptocoin Partners executable world. Depending on parameters passed,
* this will act as a ticker plant, a strategy backtester, or an online trading system, either paper trading or live.
*/
public class Main {
static final String DEFAULT_PROPERTIES_FILENAME = "cointrader.properties";
private static final Logger log = LoggerFactory.getLogger(Main.class);
final static ExecutorService service = Executors.newSingleThreadExecutor();
static class MainParams {
@SuppressWarnings("UnusedDeclaration")
@Parameter(names = { "h", "help", "-h", "-H", "-help", "--help" }, help = true, description = "Show this usage help")
boolean help;
@Parameter(names = { "-f", "-properties-file" }, description = "location of the cointrader.properties config file")
String propertiesFilename = DEFAULT_PROPERTIES_FILENAME;
@DynamicParameter(names = { "-D" }, description = "use the -D flag to set configuration properties \"-Ddb.username=dbuser\"")
Map<String, String> definitions = new HashMap<>();
}
static class MainParamsOnly extends MainParams {
@Parameter
List<String> everythingElseIgnored;
}
public static void main(String[] args) throws ConfigurationException, IllegalAccessException, InstantiationException {
// first, parse only the MainParams to get the properties file location and initialize ConfigUtil and rootInjector
MainParamsOnly mainParamsOnly = new MainParamsOnly();
Semaphore semaphore = new Semaphore(0);
JCommander parameterParser = new JCommander(mainParamsOnly);
parameterParser.setProgramName(Main.class.getName());
try {
parameterParser.parse();
} catch (Throwable t) {
log.error("Threw a Execption, full stack trace follows:", t);
t.printStackTrace();
System.exit(1);
}
ConfigUtil.init(mainParamsOnly.propertiesFilename, mainParamsOnly.definitions);
Injector rootInjector = Injector.root();
rootInjector.getInstance(ApplicationInitializer.class);
// context.getInjector().root().
rootInjector.createChildInjector(new StaticInjectionModule());
// rootInjector.getInstance(BookJpaDao.class);
// rootInjector.getInstance(BarJpaDao.class);
// rootInjector.getInstance(CurrencyJpaDao.class);
// rootInjector.getInstance(ExchangeJpaDao.class);
//rootInjector.getInstance(FillJpaDao.class);
//rootInjector.getInstance(ListingJpaDao.class);
// rootInjector.getInstance(MarketJpaDao.class);
// rootInjector.getInstance(MarketDataJpaDao.class);
// rootInjector.getInstance(OrderJpaDao.class);
//rootInjector.getInstance(PortfolioJpaDao.class);
// rootInjector.getInstance(PositionJpaDao.class);
// rootInjector.getInstance(PromptJpaDao.class);
// rootInjector.getInstance(TradeJpaDao.class);
//rootInjector.getInstance(TransactionJpaDao.class);
//rootInjector.getInstance(OrderUpdateJpaDao.class);
// now parse the full command line
MainParams mainParams = new MainParams();
parameterParser = new JCommander(mainParams);
// find the commands, register with the parameter parser, and put them into the commandLookup map
Map<String, RunMode> runModesByName = new HashMap<>();
Set<Class<? extends RunMode>> runModeClasses = ReflectionUtil.getSubtypesOf(RunMode.class);
for (Class<? extends RunMode> runModeClass : runModeClasses) {
if (Modifier.isAbstract(runModeClass.getModifiers()))
continue;
Parameters annotation = runModeClass.getAnnotation(Parameters.class);
if (annotation == null) {
System.err.println("The RunMode subclass " + runModeClass + " must have the com.beust.jcommander.Parameters annotation.");
System.exit(1);
}
// rootInjector.getInstance(ApplicationInitializer.class);
// new Binder
RunMode runMode = rootInjector.getInstance(runModeClass);
for (String commandName : annotation.commandNames())
runModesByName.put(commandName, runMode);
parameterParser.addCommand(runMode);
}
// now parse the commandline
try {
parameterParser.parse(args);
} catch (MissingCommandException e) {
System.err.println(e.getMessage());
parameterParser.usage();
System.exit(7002);
}
String commandName = parameterParser.getParsedCommand();
// find the runmode, if any
RunMode runMode = runModesByName.get(commandName);
if (runMode == null || mainParams.help) {
parameterParser.usage();
System.exit(7001);
}
// PersistUtil.init();
try {
runMode.run(semaphore);
semaphore.acquire(1);
} catch (Throwable t) {
log.error("Uncaught error while running " + runMode.getClass().getSimpleName(), t);
} finally {
// rootInjector.getInstance(EntityManagerFactory.class).close();
// PersistUtil.shutdown();
}
}
}