package org.ut.biolab.medsavant.client.cli; import gnu.getopt.Getopt; import gnu.getopt.LongOpt; import java.rmi.RemoteException; import java.sql.SQLException; import java.util.*; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.ut.biolab.medsavant.MedSavantClient; import org.ut.biolab.medsavant.client.api.Listener; import org.ut.biolab.medsavant.client.controller.SettingsController; import org.ut.biolab.medsavant.client.project.ProjectController; import org.ut.biolab.medsavant.client.reference.ReferenceController; import org.ut.biolab.medsavant.client.util.ClientNetworkUtils; import org.ut.biolab.medsavant.client.util.DownloadEvent; import org.ut.biolab.medsavant.client.view.login.LoginController; import org.ut.biolab.medsavant.client.view.login.LoginEvent; import org.ut.biolab.medsavant.shared.model.SessionExpiredException; import java.io.File; import java.util.concurrent.ExecutionException; public class Cli { /** Possible tasks that the CLI can handle */ private enum Task { NONE, UPLOAD_VCF } private Task task = Task.NONE; private String filename = null; private String project = null; private String email = null; private boolean phasing = false; private boolean geneAnnotation = false; private final String usage = "usage: java -jar medsavant-cli-*.jar -h host -p port -d dbname -u user -w password\n" + " [--upload_vcf filename --project name] [--email address] [--phasing] [--gene-annotation]"; public Cli(String args[]) { LongOpt[] longOpts = Cli.getLongOpts(); Getopt g = new Getopt("MedSavant", args, "h:p:d:u:w:", longOpts); int c; boolean startGui = true; while ((c = g.getopt()) != -1) { switch (c) { case 0: // handling longopts startGui = false; LongOpt l = longOpts[g.getLongind()]; if (l.getName().equals("help")) { System.out.println(usage); System.exit(0); } else if (l.getName().equals("upload-vcf")) { filename = g.getOptarg(); task = Task.UPLOAD_VCF; } else if (l.getName().equals("project")) { project = g.getOptarg(); } else if (l.getName().equals("email")) { email = g.getOptarg(); } else if (l.getName().equals("phasing")) { phasing = true; } else if (l.getName().equals("gene-annotation")) { geneAnnotation = true; } break; case 'h': String host = g.getOptarg(); SettingsController.getInstance().setServerAddress(g.getOptarg()); break; case 'p': int port = Integer.parseInt(g.getOptarg()); SettingsController.getInstance().setServerPort(port + ""); break; case 'd': String dbname = g.getOptarg(); SettingsController.getInstance().setDBName(dbname); break; case 'u': String username = g.getOptarg(); SettingsController.getInstance().setUsername(username); break; case 'w': String password = g.getOptarg(); SettingsController.getInstance().setPassword(password); break; case '?': System.out.println(usage); System.exit(1); default: System.out.println("getopt() returned " + c); } } // Validate presence of arguments required for some tasks. switch (task) { case UPLOAD_VCF: if (filename == null) { System.err.println(usage); System.exit(1); } if (project == null) { System.err.println(usage); System.exit(1); } break; case NONE: default: System.err.println(usage); System.exit(1); } try { Logger.getRootLogger().setLevel(Level.OFF); login(); processTasks(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } private static LongOpt[] getLongOpts() { List<LongOpt> longopts = new ArrayList<LongOpt>(); longopts.add(new LongOpt("upload-vcf", LongOpt.REQUIRED_ARGUMENT, null, 0)); longopts.add(new LongOpt("project", LongOpt.REQUIRED_ARGUMENT, null, 0)); longopts.add(new LongOpt("email", LongOpt.REQUIRED_ARGUMENT, null, 0)); longopts.add(new LongOpt("phasing", LongOpt.NO_ARGUMENT, null, 0)); longopts.add(new LongOpt("gene-annotation", LongOpt.NO_ARGUMENT, null, 0)); return longopts.toArray(new LongOpt[longopts.size()]); } private void login() throws Exception { // let's login final SettingsController settingsController = SettingsController.getInstance(); // This thread helps us make login synchronous, so we don't need to next the next step in the event handler. final Thread t = new Thread(new Runnable() { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(500); } catch (InterruptedException e) { break; } } } }); Listener<LoginEvent> loginEventListener = new Listener<LoginEvent>() { @Override public void handleEvent(LoginEvent event) { try { switch (event.getType()) { case LOGGED_IN: break; case LOGGED_OUT: case LOGIN_CANCELLED: case LOGIN_FAILED: throw event.getException(); } t.interrupt(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } }; LoginController.getInstance().addListener(loginEventListener); t.start(); LoginController.getInstance().login( settingsController.getUsername(), settingsController.getPassword(), settingsController.getDBName(), settingsController.getServerAddress(), settingsController.getServerPort()); // wait for the busy-waiting thread to exit t.join(); LoginController.getInstance().removeListener(loginEventListener); } private void processTasks() throws Exception { switch (task) { case UPLOAD_VCF: // so far so good. Let's upload! ProjectController.getInstance().setProject(project); int[] transferIDs = null; try { transferIDs = uploadVCFtoServer(filename); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); System.exit(1); } obtainDBLock(); processVCF(email, phasing, geneAnnotation, transferIDs); System.out.println("\nThe VCF file is now uploaded and processed. Exiting."); System.exit(0); case NONE: default: return; } } private int[] uploadVCFtoServer(String filename) throws ExecutionException, InterruptedException { int[] ids = new int[1]; File f = new File(filename); System.out.println("Copying " + filename + " to server."); ids[0] = ClientNetworkUtils.copyFileToServer(f, new Listener<DownloadEvent>() { @Override public void handleEvent(DownloadEvent event) { System.out.print("."); } }).get(); System.out.println("Done"); return ids; } private void obtainDBLock() { try { if (!getDBLockState()) { return; } System.out.println("Ongoing upload detected. Waiting for it to finish."); while (getDBLockState()) { Thread.sleep(3000); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } } /** * Return True if locked, False otherwise. */ private boolean getDBLockState() throws RemoteException, SessionExpiredException { return MedSavantClient.SettingsManager.isProjectLockedForChanges( LoginController.getSessionID(), ProjectController.getInstance().getCurrentProjectID()); } private void processVCF(String email, boolean phasing, boolean geneAnnotation, int[] transferIDs) throws Exception { System.out.println("Parsing and annotating VCF, this may take a while."); Thread t = new Thread(new Runnable() { @Override public void run() { int columns = 0; while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(3000); } catch (InterruptedException e) { break; } System.out.print('.'); columns++; if (columns >= 80) { System.out.print('\n'); columns = 0; } } System.out.println("Done!"); } }); t.start(); String sessionID = LoginController.getSessionID(); int projectID = ProjectController.getInstance().getCurrentProjectID(); MedSavantClient.VariantManager.uploadVariants( sessionID, transferIDs, projectID, ReferenceController.getInstance().getCurrentReferenceID(), new String[][]{}, ProjectController.getInstance().getContainsRefCalls(sessionID, projectID), email, true, geneAnnotation, phasing); t.interrupt(); } public static void main(String args[]) { Cli cli = new Cli(args); } }