javadoc and introduction of dasserver and fetchdas command line arguments.
[jalview.git] / src / jalview / bin / Jalview.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.bin;
20
21 import java.io.IOException;
22 import java.util.*;
23
24 import javax.swing.*;
25
26 import jalview.gui.*;
27 import jalview.io.AppletFormatAdapter;
28
29 /**
30  * Main class for Jalview Application <br>
31  * <br>
32  * start with java -Djava.ext.dirs=$PATH_TO_LIB$ jalview.bin.Jalview
33  * 
34  * @author $author$
35  * @version $Revision$
36  */
37 public class Jalview
38 {
39
40   /**
41    * main class for Jalview application
42    * 
43    * @param args
44    *                open <em>filename</em>
45    */
46   public static void main(String[] args)
47   {
48     System.out.println("Java version: "
49             + System.getProperty("java.version"));
50     System.out.println(System.getProperty("os.arch") + " "
51             + System.getProperty("os.name") + " "
52             + System.getProperty("os.version"));
53
54     ArgsParser aparser = new ArgsParser(args);
55     boolean headless = false;
56
57     if (aparser.contains("help") || aparser.contains("h"))
58     {
59       System.out
60               .println("Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
61                       + "-nodisplay\tRun Jalview without User Interface.\n"
62                       + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
63                       + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
64                       + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
65                       + "-features FILE\tUse the given file to mark features on the alignment.\n"
66                       + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
67                       + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
68                       + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
69                       + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
70                       + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
71                       + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
72                       + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
73                       + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
74                       + "-png FILE\tCreate PNG image FILE from alignment.\n"
75                       + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
76                       + "-eps FILE\tCreate EPS file FILE from alignment."
77                       + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires."
78                       + "-noquestionnaire\tTurn off questionnaire check."
79                       + "-dasserver nickname=URL\tAdd and enable a das server with given nickname (alphanumeric or underscores only) for retrieval of features for all alignments."
80                       + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them."
81                       + "\n\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n");
82       System.exit(0);
83     }
84
85     Cache.loadProperties(aparser.getValue("props")); // must do this before
86     // anything else!
87
88     if (aparser.contains("nodisplay"))
89     {
90       System.setProperty("java.awt.headless", "true");
91     }
92     if (System.getProperty("java.awt.headless") != null
93             && System.getProperty("java.awt.headless").equals("true"))
94     {
95       headless = true;
96     }
97
98     try
99     {
100       Cache.initLogger();
101     } catch (java.lang.NoClassDefFoundError error)
102     {
103       error.printStackTrace();
104       System.out
105               .println("\nEssential logging libraries not found."
106                       + "\nUse: java -Djava.ext.dirs=$PATH_TO_LIB$ jalview.bin.Jalview");
107       System.exit(0);
108     }
109
110     Desktop desktop = null;
111
112     try
113     {
114       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()
115       // UIManager.getCrossPlatformLookAndFeelClassName()
116               // "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"
117               // "javax.swing.plaf.metal.MetalLookAndFeel"
118               // "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"
119               // "com.sun.java.swing.plaf.motif.MotifLookAndFeel"
120
121               );
122     } catch (Exception ex)
123     {
124     }
125     if (!headless)
126     {
127       desktop = new Desktop();
128       desktop.setVisible(true);
129       desktop.discoverer.start();
130       if (!aparser.contains("noquestionnaire"))
131       {
132         String url = aparser.getValue("questionnaire");
133         if (url != null)
134         {
135           // Start the desktop questionnaire prompter with the specified
136           // questionnaire
137           Cache.log.debug("Starting questionnaire url at " + url);
138           desktop.checkForQuestionnaire(url);
139         }
140         else
141         {
142           if (Cache.getProperty("NOQUESTIONNAIRES") == null)
143           {
144             // Start the desktop questionnaire prompter with the specified
145             // questionnaire
146             // String defurl =
147             // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
148             // //
149             String defurl = "http://www.jalview.org/cgi-bin/questionnaire.pl";
150             Cache.log.debug("Starting questionnaire with default url: "
151                     + defurl);
152             desktop.checkForQuestionnaire(defurl);
153
154           }
155         }
156       }
157     }
158
159     String file = null, protocol = null, format = null, data = null;
160     jalview.io.FileLoader fileLoader = new jalview.io.FileLoader();
161     Vector getFeatures = null; // vector of das source nicknames to fetch features from
162     // loading is done.
163     file = aparser.getValue("open");
164
165     if (file == null && desktop == null)
166     {
167       System.out.println("No files to open!");
168       System.exit(1);
169     }
170
171     if (file != null)
172     {
173       System.out.println("Opening file: " + file);
174
175       if (!file.startsWith("http://"))
176       {
177         if (!(new java.io.File(file)).exists())
178         {
179           System.out.println("Can't find " + file);
180           if (headless)
181           {
182             System.exit(1);
183           }
184         }
185       }
186
187       protocol = checkProtocol(file);
188
189       format = new jalview.io.IdentifyFile().Identify(file, protocol);
190
191       AlignFrame af = fileLoader.LoadFileWaitTillLoaded(file, protocol,
192               format);
193
194       if (af == null)
195       {
196         System.out.println("error");
197         return;
198       }
199
200       data = aparser.getValue("colour");
201       if (data != null)
202       {
203         data.replaceAll("%20", " ");
204
205         jalview.schemes.ColourSchemeI cs = jalview.schemes.ColourSchemeProperty
206                 .getColour(af.getViewport().getAlignment(), data);
207
208         if (cs == null)
209         {
210           jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(
211                   "white");
212           ucs.parseAppletParameter(data);
213           cs = ucs;
214         }
215
216         System.out.println("colour is " + data);
217         af.changeColour(cs);
218       }
219
220       // Must maintain ability to use the groups flag
221       data = aparser.getValue("groups");
222       if (data != null)
223       {
224         af.parseFeaturesFile(data, checkProtocol(data));
225         System.out.println("Added " + data);
226       }
227       data = aparser.getValue("features");
228       if (data != null)
229       {
230         af.parseFeaturesFile(data, checkProtocol(data));
231         System.out.println("Added " + data);
232       }
233
234       data = aparser.getValue("annotations");
235       if (data != null)
236       {
237         af.loadJalviewDataFile(data);
238         System.out.println("Added " + data);
239       }
240       data = aparser.getValue("tree");
241       if (data != null)
242       {
243         jalview.io.NewickFile fin = null;
244         try
245         {
246           fin = new jalview.io.NewickFile(data, checkProtocol(data));
247           if (fin != null)
248           {
249             af.getViewport().setCurrentTree(
250                     af.ShowNewickTree(fin, data).getTree());
251             System.out.println("Added tree " + data);
252           }
253         } catch (IOException ex)
254         {
255           System.err.println("Couldn't add tree " + data);
256           ex.printStackTrace(System.err);
257         }
258       }
259       getFeatures = checkDasArguments(aparser);
260       if (af != null && getFeatures!=null)
261       {
262         startFeatureFetching(getFeatures); 
263         // need to block until fetching is complete.
264         while (af.operationInProgress())
265         {
266           // wait around until fetching is finished.
267           try {
268             Thread.sleep(10);
269           } catch (Exception e)
270           {
271             
272           }
273         }
274       }
275       String imageName = "unnamed.png";
276       while (aparser.getSize() > 1)
277       {
278         format = aparser.nextValue();
279         file = aparser.nextValue();
280
281         if (format.equalsIgnoreCase("png"))
282         {
283           af.createPNG(new java.io.File(file));
284           imageName = (new java.io.File(file)).getName();
285           System.out.println("Creating PNG image: " + file);
286           continue;
287         }
288         else if (format.equalsIgnoreCase("imgMap"))
289         {
290           af.createImageMap(new java.io.File(file), imageName);
291           System.out.println("Creating image map: " + file);
292           continue;
293         }
294         else if (format.equalsIgnoreCase("eps"))
295         {
296           System.out.println("Creating EPS file: " + file);
297           af.createEPS(new java.io.File(file));
298           continue;
299         }
300
301         if (af.saveAlignment(file, format))
302         {
303           System.out.println("Written alignment in " + format
304                   + " format to " + file);
305         }
306         else
307         {
308           System.out.println("Error writing file " + file + " in " + format
309                   + " format!!");
310         }
311
312       }
313
314       while (aparser.getSize() > 0)
315       {
316         System.out.println("Unknown arg: " + aparser.nextValue());
317       }
318     }
319     AlignFrame startUpAlframe = null;
320     // We'll only open the default file if the desktop is visible.
321     // And the user
322     // ////////////////////
323     if (!headless && file == null
324             && jalview.bin.Cache.getDefault("SHOW_STARTUP_FILE", true))
325     {
326       file = jalview.bin.Cache.getDefault("STARTUP_FILE",
327               "http://www.jalview.org/examples/exampleFile_2_3.jar");
328
329       protocol = "File";
330
331       if (file.indexOf("http:") > -1)
332       {
333         protocol = "URL";
334       }
335
336       if (file.endsWith(".jar"))
337       {
338         format = "Jalview";
339       }
340       else
341       {
342         format = new jalview.io.IdentifyFile().Identify(file, protocol);
343       }
344
345       startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
346               format);
347       getFeatures = checkDasArguments(aparser);
348     }
349     // Once all loading is done. Retrieve features.
350     if (getFeatures!=null)
351     {
352       if (startUpAlframe!=null)
353       {
354         startFeatureFetching(getFeatures);
355       }
356     }
357   }
358   /**
359    * Check commandline for any das server definitions or any fetchfrom switches
360    * @return vector of DAS source nicknames to retrieve from
361    */
362   private static Vector checkDasArguments(ArgsParser aparser)
363   {
364     Vector source=null;
365     String data;
366     String locsources = Cache.getProperty(Cache.DAS_LOCAL_SOURCE);
367     while ((data = aparser.getValue("dasserver"))!=null)
368     {
369       String nickname = null;
370       String url = null;
371       int pos = data.indexOf('=');
372       if (pos > 0)
373       {
374         nickname = data.substring(0, pos);
375       }
376       url = data.substring(pos + 1);
377       if (url != null && url.startsWith("http:"))
378       {
379         if (nickname == null)
380         {
381           nickname = url;
382         }
383         if (locsources==null)
384         {
385           locsources="";
386         } else {
387           locsources+="\t";
388         }
389         locsources=locsources+nickname+"|"+url;
390         System.err
391                 .println("NOTE! dasserver parameter not yet really supported (got args of "
392                         + nickname + "|" + url);
393         if (source==null)
394         {
395           source = new Vector();
396         }
397         source.addElement(nickname);
398       }
399     } // loop until no more server entries are found.
400     if (locsources!=null && locsources.indexOf('|')>-1)
401     {
402       Cache.log.debug("Setting local source list in properties file to:\n"+locsources);
403       Cache.setProperty(Cache.DAS_LOCAL_SOURCE, locsources);
404     }
405     while ((data = aparser.getValue("fetchfrom"))!=null)
406     {
407       System.out.println("adding source '"+data+"'");
408       if (source==null)
409       {
410         source = new Vector();
411       }
412       source.addElement(data);
413     }
414     return source;
415   }
416   /**
417    * start a feature fetcher for every alignment frame
418    * @param dasSources
419    */
420   private static void startFeatureFetching(final Vector dasSources)
421   {
422     AlignFrame afs[] = Desktop.getAlignframes();
423     if (afs==null || afs.length==0)
424     {
425       return;
426     }
427     for (int i = 0; i<afs.length; i++)
428     {
429       final AlignFrame af = afs[i];
430       SwingUtilities.invokeLater(new Runnable() {
431
432         public void run()
433         { 
434           af.featureSettings_actionPerformed(null);
435           af.featureSettings.fetchDasFeatures(dasSources);
436         }
437       });
438     }
439   }
440
441   private static String checkProtocol(String file)
442   {
443     String protocol = jalview.io.FormatAdapter.FILE;
444
445     if (file.indexOf("http:") > -1 || file.indexOf("file:") > -1)
446     {
447       protocol = jalview.io.FormatAdapter.URL;
448     }
449     return protocol;
450   }
451 }
452
453 /**
454  * Notes: this argParser does not distinguish between parameter switches,
455  * parameter values and argument text. If an argument happens to be identical
456  * to a parameter, it will be taken as such (even though it didn't have a '-' prefixing it).
457  * 
458  * @author Andrew Waterhouse and JBP documented.
459  *
460  */
461 class ArgsParser
462 {
463   Vector vargs = null;
464
465   public ArgsParser(String[] args)
466   {
467     vargs = new Vector();
468     for (int i = 0; i < args.length; i++)
469     {
470       String arg = args[i].trim();
471       if (arg.charAt(0) == '-')
472       {
473         arg = arg.substring(1);
474       }
475       vargs.addElement(arg);
476     }
477   }
478   /**
479    * check for and remove first occurence of arg+parameter in arglist.
480    * @param arg
481    * @return return the argument following the given arg if arg was in list.
482    */
483   public String getValue(String arg)
484   {
485     int index = vargs.indexOf(arg);
486     String ret = null;
487     if (index != -1)
488     {
489       ret = vargs.elementAt(index + 1).toString();
490       vargs.removeElementAt(index);
491       vargs.removeElementAt(index);
492     }
493     return ret;
494   }
495   /**
496    * check for and remove first occurence of arg in arglist.
497    * @param arg
498    * @return true if arg was present in argslist.
499    */
500   public boolean contains(String arg)
501   {
502     if (vargs.contains(arg))
503     {
504       vargs.removeElement(arg);
505       return true;
506     }
507     else
508     {
509       return false;
510     }
511   }
512
513   public String nextValue()
514   {
515     return vargs.remove(0).toString();
516   }
517
518   public int getSize()
519   {
520     return vargs.size();
521   }
522
523 }