JAL-3778 moving Java logging to Platform.
[jalview.git] / src / jalview / bin / Jalview.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.bin;
22
23 import jalview.api.AlignFrameI;
24 import jalview.api.AlignViewportI;
25 import jalview.api.JalviewApp;
26 import jalview.api.StructureSelectionManagerProvider;
27 import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
28 import jalview.datamodel.ColumnSelection;
29 import jalview.datamodel.HiddenColumns;
30 import jalview.datamodel.PDBEntry;
31 import jalview.datamodel.SequenceGroup;
32 import jalview.datamodel.SequenceI;
33 import jalview.ext.so.SequenceOntology;
34 import jalview.gui.AlignFrame;
35 import jalview.gui.AlignViewport;
36 import jalview.gui.AlignmentPanel;
37 import jalview.gui.CalculationChooser;
38 import jalview.gui.Desktop;
39 import jalview.gui.Preferences;
40 import jalview.gui.PromptUserConfig;
41 import jalview.gui.StructureViewer;
42 import jalview.io.AppletFormatAdapter;
43 import jalview.io.BioJsHTMLOutput;
44 import jalview.io.DataSourceType;
45 import jalview.io.FileFormat;
46 import jalview.io.FileFormatException;
47 import jalview.io.FileFormatI;
48 import jalview.io.FileFormats;
49 import jalview.io.FileLoader;
50 import jalview.io.HtmlSvgOutput;
51 import jalview.io.IdentifyFile;
52 import jalview.io.NewickFile;
53 import jalview.io.gff.SequenceOntologyFactory;
54 import jalview.javascript.JSFunctionExec;
55 import jalview.javascript.MouseOverStructureListener;
56 import jalview.renderer.seqfeatures.FeatureRenderer;
57 import jalview.schemes.ColourSchemeI;
58 import jalview.schemes.ColourSchemeProperty;
59 import jalview.structure.SelectionSource;
60 import jalview.structure.VamsasSource;
61 import jalview.util.MessageManager;
62 import jalview.util.Platform;
63 import jalview.ws.jws2.Jws2Discoverer;
64
65 import java.applet.AppletContext;
66 import java.io.BufferedReader;
67 import java.io.File;
68 import java.io.FileOutputStream;
69 import java.io.IOException;
70 import java.io.InputStreamReader;
71 import java.io.OutputStreamWriter;
72 import java.io.PrintWriter;
73 import java.net.MalformedURLException;
74 import java.net.URI;
75 import java.net.URISyntaxException;
76 import java.net.URL;
77 import java.security.AllPermission;
78 import java.security.CodeSource;
79 import java.security.PermissionCollection;
80 import java.security.Permissions;
81 import java.security.Policy;
82 import java.util.HashMap;
83 import java.util.Hashtable;
84 import java.util.Map;
85 import java.util.Vector;
86
87 import javax.swing.LookAndFeel;
88 import javax.swing.UIManager;
89
90 import groovy.lang.Binding;
91 import groovy.util.GroovyScriptEngine;
92 import netscape.javascript.JSObject;
93
94 /**
95  * Main class for Jalview Application <br>
96  * <br>
97  * start with: java -classpath "$PATH_TO_LIB$/*:$PATH_TO_CLASSES$" \
98  * jalview.bin.Jalview
99  * 
100  * or on Windows: java -classpath "$PATH_TO_LIB$/*;$PATH_TO_CLASSES$" \
101  * jalview.bin.Jalview jalview.bin.Jalview
102  * 
103  * (ensure -classpath arg is quoted to avoid shell expansion of '*' and do not
104  * embellish '*' to e.g. '*.jar')
105  * 
106  * @author $author$
107  * @version $Revision$
108  */
109 public class Jalview implements ApplicationSingletonI, JalviewJSApi
110 {
111
112   public static Jalview getInstance()
113   {
114     return (Jalview) ApplicationSingletonProvider
115             .getInstance(Jalview.class);
116   }
117
118   private Jalview()
119   {
120   }
121
122   static
123   {
124     Platform.getURLCommandArguments();
125   }
126
127   private boolean headless;
128
129   public static boolean isHeadlessMode()
130   {
131     return getInstance().headless;
132   }
133
134   private Desktop desktop;
135
136   private AlignFrame currentAlignFrame;
137
138   public boolean isJavaAppletTag;
139
140   public String appletResourcePath;
141
142   JalviewAppLoader appLoader;
143
144   protected JSFunctionExec jsFunctionExec;
145
146   private boolean noCalculation, noMenuBar, noStatus;
147
148   public boolean getStartCalculations()
149   {
150     return !noCalculation;
151   }
152
153   public boolean getAllowMenuBar()
154   {
155     return !noMenuBar;
156   }
157
158   public boolean getShowStatus()
159   {
160     return !noStatus;
161   }
162
163
164   public static AlignFrame getCurrentAlignFrame()
165   {
166     return getInstance().currentAlignFrame;
167   }
168
169   public static void setCurrentAlignFrame(AlignFrame currentAlignFrame)
170   {
171     getInstance().currentAlignFrame = currentAlignFrame;
172   }
173
174   static
175   {
176     if (!Platform.isJS())
177     /**
178      * Java only
179      * 
180      * @j2sIgnore
181      */
182     {
183       // grab all the rights we can for the JVM
184       Policy.setPolicy(new Policy()
185       {
186         @Override
187         public PermissionCollection getPermissions(CodeSource codesource)
188         {
189           Permissions perms = new Permissions();
190           perms.add(new AllPermission());
191           return (perms);
192         }
193
194         @Override
195         public void refresh()
196         {
197         }
198       });
199     }
200   }
201
202   /**
203    * keep track of feature fetching tasks.
204    * 
205    * @author JimP
206    * 
207    */
208   class FeatureFetcher
209   {
210     /*
211      * TODO: generalise to track all jalview events to orchestrate batch
212      * processing events.
213      */
214
215     private int queued = 0;
216
217     private int running = 0;
218
219     public FeatureFetcher()
220     {
221
222     }
223
224     public void addFetcher(final AlignFrame af,
225             final Vector<String> dasSources)
226     {
227       final long id = System.currentTimeMillis();
228       queued++;
229       final FeatureFetcher us = this;
230       new Thread(new Runnable()
231       {
232
233         @Override
234         public void run()
235         {
236           synchronized (us)
237           {
238             queued--;
239             running++;
240           }
241
242           af.setProgressBar(MessageManager
243                   .getString("status.das_features_being_retrived"), id);
244           af.featureSettings_actionPerformed(null);
245           af.setProgressBar(null, id);
246           synchronized (us)
247           {
248             running--;
249           }
250         }
251       }).start();
252     }
253
254     public synchronized boolean allFinished()
255     {
256       return queued == 0 && running == 0;
257     }
258
259   }
260
261   /**
262    * main class for Jalview application
263    * 
264    * @param args
265    *          open <em>filename</em>
266    */
267   public static void main(String[] args)
268   {
269     // Platform.startJavaLogging();
270     getInstance().doMain(args);
271   }
272
273
274   @SuppressWarnings("unused")
275   /**
276    * @param args
277    */
278   void doMain(String[] args)
279   {
280
281     boolean isJS = Platform.isJS();
282     if (!isJS)
283     {
284       System.setSecurityManager(null);
285     }
286
287     System.out
288             .println("Java version: " + System.getProperty("java.version"));
289     System.out.println(System.getProperty("os.arch") + " "
290             + System.getProperty("os.name") + " "
291             + System.getProperty("os.version"));
292
293     ArgsParser aparser = new ArgsParser(args);
294
295     String usrPropsFile = aparser.getValue(ArgsParser.PROPS);
296     Cache.loadProperties(usrPropsFile);
297     if (isJS)
298     {
299       isJavaAppletTag = aparser.isApplet();
300       if (isJavaAppletTag)
301       {
302         Preferences.setAppletDefaults();
303         Cache.loadProperties(usrPropsFile); // again, because we
304         // might be changing defaults here?
305       }
306       System.out.println(
307               "<Applet> found: " + aparser.getValue("Info.j2sAppletID"));
308       appletResourcePath = aparser.getValue("Info.resourcePath");
309     }
310     else
311     /**
312      * Java only
313      * 
314      * @j2sIgnore
315      */
316     {
317       if (usrPropsFile != null)
318       {
319         System.out.println(
320                 "CMD [-props " + usrPropsFile + "] executed successfully!");
321       }
322
323       if (aparser.contains("help") || aparser.contains("h"))
324       {
325         showUsage();
326         System.exit(0);
327       }
328       if (aparser.contains(ArgsParser.NODISPLAY)
329               || aparser.contains(ArgsParser.NOGUI)
330               || aparser.contains(ArgsParser.HEADLESS)
331               || "true".equals(System.getProperty("java.awt.headless")))
332       {
333         headless = true;
334       }
335
336       // anything else!
337
338       final String jabawsUrl = aparser.getValue(ArgsParser.JABAWS);
339       if (jabawsUrl != null)
340       {
341         try
342         {
343           Jws2Discoverer.getInstance().setPreferredUrl(jabawsUrl);
344           System.out.println(
345                   "CMD [-jabaws " + jabawsUrl + "] executed successfully!");
346         } catch (MalformedURLException e)
347         {
348           System.err.println(
349                   "Invalid jabaws parameter: " + jabawsUrl + " ignored");
350         }
351       }
352
353     }
354     // check for property setting
355     String defs = aparser.getValue(ArgsParser.SETPROP);
356     while (defs != null)
357     {
358       int p = defs.indexOf('=');
359       if (p == -1)
360       {
361         System.err.println("Ignoring invalid setprop argument : " + defs);
362       }
363       else
364       {
365         System.out.println("Executing setprop argument: " + defs);
366         if (isJS)
367         {
368           Cache.setProperty(defs.substring(0, p), defs.substring(p + 1));
369         }
370       }
371       defs = aparser.getValue(ArgsParser.SETPROP);
372     }
373     System.setProperty("http.agent",
374             "Jalview Desktop/" + Cache.getDefault("VERSION", "Unknown"));
375     try
376     {
377       Cache.initLogger();
378     } catch (NoClassDefFoundError error)
379     {
380       error.printStackTrace();
381       System.out.println("\nEssential logging libraries not found."
382               + "\nUse: java -classpath \"$PATH_TO_LIB$/*:$PATH_TO_CLASSES$\" jalview.bin.Jalview");
383       System.exit(0);
384     }
385
386     desktop = null;
387
388     try
389     {
390       UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
391     } catch (Exception ex)
392     {
393       System.err.println("Unexpected Look and Feel Exception");
394       ex.printStackTrace();
395     }
396     if (Platform.isAMacAndNotJS())
397     {
398
399       LookAndFeel lookAndFeel = ch.randelshofer.quaqua.QuaquaManager
400               .getLookAndFeel();
401       System.setProperty("com.apple.mrj.application.apple.menu.about.name",
402               "Jalview");
403       System.setProperty("apple.laf.useScreenMenuBar", "true");
404       if (lookAndFeel != null)
405       {
406         try
407         {
408           UIManager.setLookAndFeel(lookAndFeel);
409         } catch (Throwable e)
410         {
411           System.err.println(
412                   "Failed to set QuaQua look and feel: " + e.toString());
413         }
414       }
415       if (lookAndFeel == null
416               || !(lookAndFeel.getClass().isAssignableFrom(
417                       UIManager.getLookAndFeel().getClass()))
418               || !UIManager.getLookAndFeel().getClass().toString()
419                       .toLowerCase().contains("quaqua"))
420       {
421         try
422         {
423           System.err.println(
424                   "Quaqua LaF not available on this plaform. Using VAqua(4).\nSee https://issues.jalview.org/browse/JAL-2976");
425           UIManager.setLookAndFeel("org.violetlib.aqua.AquaLookAndFeel");
426         } catch (Throwable e)
427         {
428           System.err.println(
429                   "Failed to reset look and feel: " + e.toString());
430         }
431       }
432     }
433
434     /*
435      * configure 'full' SO model if preferences say to, 
436      * else use the default (SO Lite)
437      */
438     if (Cache.getDefault(Preferences.USE_FULL_SO, false))
439     {
440       SequenceOntologyFactory.setSequenceOntology(new SequenceOntology());
441     }
442
443     if (!headless)
444     {
445       desktop = Desktop.getInstance();
446       desktop.setInBatchMode(true); // indicate we are starting up
447       desktop.setVisible(true);
448
449       if (!isJS)
450       /**
451        * Java only
452        * 
453        * @j2sIgnore
454        */
455       {
456         desktop.startServiceDiscovery();
457         if (!aparser.contains(ArgsParser.NOUSAGESTATS))
458         {
459           startUsageStats(desktop);
460         }
461         else
462         {
463           System.err.println("CMD [-nousagestats] executed successfully!");
464         }
465
466         if (!aparser.contains(ArgsParser.NOQUESTIONNAIRE))
467         {
468           String url = aparser.getValue(ArgsParser.QUESTIONNAIRE);
469           if (url != null)
470           {
471             // Start the desktop questionnaire prompter with the specified
472             // questionnaire
473             Cache.log.debug("Starting questionnaire url at " + url);
474             desktop.checkForQuestionnaire(url);
475             System.out.println("CMD questionnaire[-" + url
476                     + "] executed successfully!");
477           }
478           else
479           {
480             if (Cache.getProperty(Preferences.NOQUESTIONNAIRES) == null)
481             {
482               // Start the desktop questionnaire prompter with the specified
483               // questionnaire
484               // String defurl =
485               // "http://anaplog.compbio.dundee.ac.uk/cgi-bin/questionnaire.pl";
486               // //
487               String defurl = "http://www.jalview.org/cgi-bin/questionnaire.pl";
488               Cache.log.debug(
489                       "Starting questionnaire with default url: " + defurl);
490               desktop.checkForQuestionnaire(defurl);
491             }
492           }
493         }
494         else
495         {
496           System.err
497                   .println("CMD [-noquestionnaire] executed successfully!");
498         }
499
500         if (!aparser.contains(ArgsParser.NONEWS))
501         {
502           desktop.checkForNews();
503         }
504
505         BioJsHTMLOutput.updateBioJS();
506       }
507     }
508
509     parseArguments(aparser, true);
510   }
511
512   /**
513    * Allow an outside entity to initiate the second half of argument parsing
514    * (only).
515    * 
516    * @param args
517    * @return null is good
518    */
519   @Override
520   public Object parseArguments(String[] args)
521   {
522
523     try
524     {
525       ArgsParser aparser = new ArgsParser(args);
526       return parseArguments(aparser, false);
527     } catch (Throwable t)
528     {
529       return t;
530     }
531   }
532
533   /**
534    * 
535    * @param aparser
536    * @param isStartup
537    * @return
538    */
539   private Object parseArguments(ArgsParser aparser, boolean isStartup)
540   {
541     boolean isJS = Platform.isJS();
542
543     Desktop desktop = (headless ? null : Desktop.getInstance());
544     // script to execute after all loading is
545     // completed one way or another
546     // extract groovy argument and execute if necessary
547     String groovyscript = (isJS ? null
548             : aparser.getValue(ArgsParser.GROOVY, true));
549     String file = aparser.getValue(ArgsParser.OPEN, true);
550     // BH this here to allow split frame; not working as of 5/17/2019
551     String file2 = aparser.getValue(ArgsParser.OPEN2, true);
552     String fileFormat = (isJavaAppletTag
553             ? aparser.getAppletValue("format", null)
554             : null);
555     FileFormatI format = null;
556     DataSourceType protocol = null;
557
558     if (file == null && desktop == null)
559     {
560       System.out.println("No files to open!");
561       System.exit(1);
562     }
563     boolean haveImport = checkStartVamas(aparser);
564     // Finally, deal with the remaining input data.
565     long progress = -1;
566     if (file == null && isJavaAppletTag)
567     {
568       // Maybe the sequences are added as parameters
569       StringBuffer data = new StringBuffer("PASTE");
570       int i = 1;
571       while ((file = aparser.getAppletValue("sequence" + i, null)) != null)
572       {
573         data.append(file.toString() + "\n");
574         i++;
575       }
576       if (data.length() > 5)
577       {
578         file = data.toString();
579       }
580     }
581
582     String data;
583
584     if (file != null)
585     {
586
587       if (!headless)
588       {
589         desktop.setProgressBar(
590                 MessageManager
591                         .getString("status.processing_commandline_args"),
592                 progress = System.currentTimeMillis());
593       }
594
595       if (!isJS)
596       /**
597        * ignore in JavaScript -- can't just check file existence - could load
598        * it?
599        * 
600        * @j2sIgnore
601        */
602       {
603         if (!file.startsWith("http://") && !file.startsWith("https://"))
604         // BH 2019 added https check for Java
605         {
606           if (!(new File(file)).exists())
607           {
608             System.out.println("Can't find " + file);
609             if (headless)
610             {
611               System.exit(1);
612             }
613           }
614         }
615       }
616
617       protocol = AppletFormatAdapter.checkProtocol(file);
618
619       try
620       {
621         format = (isJavaAppletTag && fileFormat != null
622                 ? FileFormats.getInstance().forName(fileFormat)
623                 : null);
624         if (format == null)
625         {
626           format = new IdentifyFile().identify(file, protocol);
627         }
628       } catch (FileFormatException e1)
629       {
630         // TODO ?
631       }
632
633       if (aparser.contains(ArgsParser.SHOWOVERVIEW))
634       {
635         jalview.bin.Cache.setPropertyNoSave(Preferences.SHOW_OVERVIEW,
636                 "true");
637
638         System.out.println("CMD [showoverview] executed successfully!");
639       }
640
641       if (aparser.contains(ArgsParser.NOMENUBAR))
642       {
643         noMenuBar = true;
644         System.out.println("CMD [nomenu] executed successfully!");
645       }
646
647       if (aparser.contains(ArgsParser.NOSTATUS))
648       {
649         noStatus = true;
650         System.out.println("CMD [nostatus] executed successfully!");
651       }
652
653       if (aparser.contains(ArgsParser.NOCALCULATION))
654       {
655         noCalculation = true;
656         System.out.println("CMD [nocalculation] executed successfully!");
657       }
658
659       AlignFrame af = new FileLoader(!headless).loadFileWaitTillLoaded(file,
660               protocol, format);
661       if (af == null)
662       {
663         System.out.println("error");
664       }
665       else
666       {
667         System.out
668                 .println("CMD [-open " + file + "] executed successfully!");
669         if (file2 != null)
670         {
671           protocol = AppletFormatAdapter.checkProtocol(file2);
672           try
673           {
674             format = new IdentifyFile().identify(file2, protocol);
675           } catch (FileFormatException e1)
676           {
677             // TODO ?
678           }
679           AlignFrame af2 = new FileLoader(!headless)
680                   .loadFileWaitTillLoaded(file2, protocol, format);
681           if (af2 == null)
682           {
683             System.out.println("error");
684           }
685           else
686           {
687             AlignViewport.openLinkedAlignmentAs(af,
688                     af.getViewport().getAlignment(),
689                     af2.getViewport().getAlignment(), "",
690                     AlignViewport.SPLIT_FRAME);
691             System.out.println(
692                     "CMD [-open2 " + file2 + "] executed successfully!");
693           }
694         }
695
696         setCurrentAlignFrame(af);
697
698         // TODO: file2 How to implement file2 for the applet spit screen?
699
700         data = aparser.getValue(ArgsParser.COLOUR, true);
701         if (data != null)
702         {
703           data.replaceAll("%20", " ");
704
705           ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
706                   af.getViewport(), af.getViewport().getAlignment(), data);
707
708           if (cs != null)
709           {
710             System.out.println(
711                     "CMD [-color " + data + "] executed successfully!");
712           }
713           af.changeColour(cs);
714         }
715
716         // Must maintain ability to use the groups flag
717         data = aparser.getValue(ArgsParser.GROUPS, true);
718         if (data != null)
719         {
720           af.parseFeaturesFile(data,
721                   AppletFormatAdapter.checkProtocol(data));
722           // System.out.println("Added " + data);
723           System.out.println(
724                   "CMD groups[-" + data + "]  executed successfully!");
725         }
726         data = aparser.getValue(ArgsParser.FEATURES, true);
727         if (data != null)
728         {
729           af.parseFeaturesFile(data,
730                   AppletFormatAdapter.checkProtocol(data));
731           // System.out.println("Added " + data);
732           System.out.println(
733                   "CMD [-features " + data + "]  executed successfully!");
734         }
735
736         data = aparser.getValue(ArgsParser.ANNOTATIONS, true);
737         if (data != null)
738         {
739           af.loadJalviewDataFile(data, null, null, null);
740           // System.out.println("Added " + data);
741           System.out.println(
742                   "CMD [-annotations " + data + "] executed successfully!");
743         }
744         // set or clear the sortbytree flag.
745         if (aparser.contains(ArgsParser.SORTBYTREE))
746         {
747           af.getViewport().setSortByTree(true);
748           if (af.getViewport().getSortByTree())
749           {
750             System.out.println("CMD [-sortbytree] executed successfully!");
751           }
752         }
753         
754         boolean doUpdateAnnotation = false;
755         
756
757         if (aparser.contains(ArgsParser.NOANNOTATION)
758                 || aparser.contains(ArgsParser.NOANNOTATION2))
759         {
760           af.getViewport().setShowAnnotation(false);
761           if (!af.getViewport().isShowAnnotation())
762           {
763             doUpdateAnnotation = true;
764             System.out.println("CMD no-annotation executed successfully!");
765           }
766         }
767         if (aparser.contains(ArgsParser.NOSORTBYTREE))
768         {
769           af.getViewport().setSortByTree(false);
770           if (!af.getViewport().getSortByTree())
771           {
772             doUpdateAnnotation = true;
773             System.out
774                     .println("CMD [-nosortbytree] executed successfully!");
775           }
776         }
777         if (doUpdateAnnotation)
778         { // BH 2019.07.24
779           af.setMenusForViewport();
780           af.alignPanel.updateLayout();
781         }
782         data = aparser.getValue(ArgsParser.TREE, true);
783         if (data != null)
784         {
785           try
786           {
787             System.out.println(
788                     "CMD [-tree " + data + "] executed successfully!");
789             NewickFile nf = new NewickFile(data,
790                     AppletFormatAdapter.checkProtocol(data));
791             af.getViewport()
792                     .setCurrentTree(af.showNewickTree(nf, data).getTree());
793           } catch (IOException ex)
794           {
795             System.err.println("Couldn't add tree " + data);
796             ex.printStackTrace(System.err);
797           }
798         }
799         // TODO - load PDB structure(s) to alignment JAL-629
800         // (associate with identical sequence in alignment, or a specified
801         // sequence)
802         if (isJavaAppletTag)
803         {
804           loadAppletParams(aparser, af);
805         }
806         else if (!isJS)
807         /**
808          * Java only
809          * 
810          * @j2sIgnore
811          */
812         {
813           if (groovyscript != null)
814           {
815             // Execute the groovy script after we've done all the rendering
816             // stuff
817             // and before any images or figures are generated.
818             System.out.println("Executing script " + groovyscript);
819             executeGroovyScript(groovyscript, af);
820             System.out.println("CMD groovy[" + groovyscript
821                     + "] executed successfully!");
822             groovyscript = null;
823           }
824           checkOutputFile(aparser, af, format);
825           while (aparser.getSize() > 0)
826           {
827             System.out.println("Unknown arg: " + aparser.nextValue());
828           }
829         }
830       }
831     }
832     AlignFrame startUpAlframe = null;
833     // We'll only open the default file if the desktop is visible.
834     // And the user
835     // ////////////////////
836
837     if (!isJS && !headless && file == null && !haveImport
838             && jalview.bin.Cache.getDefault("SHOW_STARTUP_FILE", true))
839     /**
840      * Java only
841      * 
842      * @j2sIgnore
843      */
844     {
845       file = jalview.bin.Cache.getDefault("STARTUP_FILE",
846               jalview.bin.Cache.getDefault("www.jalview.org",
847                       "http://www.jalview.org")
848                       + "/examples/exampleFile_2_7.jar");
849       if (file.equals(
850               "http://www.jalview.org/examples/exampleFile_2_3.jar"))
851       {
852         // hardwire upgrade of the startup file
853         file.replace("_2_3.jar", "_2_7.jar");
854         // and remove the stale setting
855         jalview.bin.Cache.removeProperty("STARTUP_FILE");
856       }
857
858       protocol = DataSourceType.FILE;
859
860       if (file.indexOf("http:") > -1)
861       {
862         protocol = DataSourceType.URL;
863       }
864
865       if (file.endsWith(".jar"))
866       {
867         format = FileFormat.Jalview;
868       }
869       else
870       {
871         try
872         {
873           format = new IdentifyFile().identify(file, protocol);
874         } catch (FileFormatException e)
875         {
876           // TODO what?
877         }
878       }
879
880       startUpAlframe = new FileLoader(!headless)
881               .loadFileWaitTillLoaded(file, protocol, format);
882       // extract groovy arguments before anything else.
883     }
884
885     // Once all other stuff is done, execute any groovy scripts (in order)
886     if (groovyscript != null)
887     {
888       if (Cache.groovyJarsPresent())
889       {
890         System.out.println("Executing script " + groovyscript);
891         executeGroovyScript(groovyscript, startUpAlframe);
892       }
893       else
894       {
895         System.err.println(
896                 "Sorry. Groovy Support is not available, so ignoring the provided groovy script "
897                         + groovyscript);
898       }
899     }
900     // and finally, turn off batch mode indicator - if the desktop still exists
901     if (desktop != null)
902     {
903       if (progress != -1)
904       {
905         desktop.setProgressBar(null, progress);
906       }
907       desktop.setInBatchMode(false);
908     }
909
910     return null;
911   }
912
913   private boolean checkStartVamas(ArgsParser aparser)
914   {
915     String vamsasImport = aparser.getValue(ArgsParser.VDOC);
916     String vamsasSession = aparser.getValue(ArgsParser.VSESS);
917     if (vamsasImport == null && vamsasSession == null)
918     {
919       return false;
920     }
921     if (desktop == null || headless)
922     {
923       System.out.println(
924               "Headless vamsas sessions not yet supported. Sorry.");
925       System.exit(1);
926     }
927     boolean haveImport = (vamsasImport != null);
928     if (haveImport)
929     {
930       // if we have a file, start a new session and import it.
931       boolean inSession = false;
932       try
933       {
934         DataSourceType viprotocol = AppletFormatAdapter
935                 .checkProtocol(vamsasImport);
936         if (viprotocol == DataSourceType.FILE)
937         {
938           inSession = desktop.vamsasImport(new File(vamsasImport));
939         }
940         else if (viprotocol == DataSourceType.URL)
941         {
942           inSession = desktop.vamsasImport(new URL(vamsasImport));
943         }
944
945       } catch (Exception e)
946       {
947         System.err.println("Exeption when importing " + vamsasImport
948                 + " as a vamsas document.");
949         e.printStackTrace();
950       }
951       if (!inSession)
952       {
953         System.err.println("Failed to import " + vamsasImport
954                 + " as a vamsas document.");
955       }
956       else
957       {
958         System.out.println("Imported Successfully into new session "
959                 + desktop.getVamsasApplication().getCurrentSession());
960       }
961     }
962     if (vamsasSession != null)
963     {
964       if (vamsasImport != null)
965       {
966         // close the newly imported session and import the Jalview specific
967         // remnants into the new session later on.
968         desktop.vamsasStop_actionPerformed(null);
969       }
970       // now join the new session
971       try
972       {
973         if (desktop.joinVamsasSession(vamsasSession))
974         {
975           System.out.println(
976                   "Successfully joined vamsas session " + vamsasSession);
977         }
978         else
979         {
980           System.err.println("WARNING: Failed to join vamsas session "
981                   + vamsasSession);
982         }
983       } catch (Exception e)
984       {
985         System.err.println(
986                 "ERROR: Failed to join vamsas session " + vamsasSession);
987         e.printStackTrace();
988       }
989       if (vamsasImport != null)
990       {
991         // the Jalview specific remnants can now be imported into the new
992         // session at the user's leisure.
993         Cache.log.info(
994                 "Skipping Push for import of data into existing vamsas session.");
995         // TODO:
996         // enable
997         // this
998         // when
999         // debugged
1000         // desktop.getVamsasApplication().push_update();
1001       }
1002     }
1003     return haveImport;
1004   }
1005
1006   private void checkOutputFile(ArgsParser aparser, AlignFrame af,
1007           FileFormatI format)
1008   {
1009     String imageName = "unnamed.png";
1010     while (aparser.getSize() > 1)
1011     {
1012       // PNG filename
1013       // SVG filename
1014       // HTML filename
1015       // biojsmsa filename
1016       String outputFormat = aparser.nextValue();
1017       String file = aparser.nextValue();
1018       if (outputFormat.equalsIgnoreCase("png"))
1019       {
1020         af.createPNG(new File(file));
1021         imageName = (new File(file)).getName();
1022         System.out.println("Creating PNG image: " + file);
1023         continue;
1024       }
1025       else if (outputFormat.equalsIgnoreCase("svg"))
1026       {
1027         File imageFile = new File(file);
1028         imageName = imageFile.getName();
1029         af.createSVG(imageFile);
1030         System.out.println("Creating SVG image: " + file);
1031         continue;
1032       }
1033       else if (outputFormat.equalsIgnoreCase("html"))
1034       {
1035         File imageFile = new File(file);
1036         imageName = imageFile.getName();
1037         HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
1038         htmlSVG.exportHTML(file);
1039
1040         System.out.println("Creating HTML image: " + file);
1041         continue;
1042       }
1043       else if (outputFormat.equalsIgnoreCase("biojsmsa"))
1044       {
1045         if (file == null)
1046         {
1047           System.err.println("The output html file must not be null");
1048           return;
1049         }
1050         try
1051         {
1052           BioJsHTMLOutput.refreshVersionInfo(
1053                   BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
1054         } catch (URISyntaxException e)
1055         {
1056           e.printStackTrace();
1057         }
1058         BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
1059         bjs.exportHTML(file);
1060         System.out.println("Creating BioJS MSA Viwer HTML file: " + file);
1061         continue;
1062       }
1063       else if (outputFormat.equalsIgnoreCase("imgMap"))
1064       {
1065         af.createImageMap(new File(file), imageName);
1066         System.out.println("Creating image map: " + file);
1067         continue;
1068       }
1069       else if (outputFormat.equalsIgnoreCase("eps"))
1070       {
1071         File outputFile = new File(file);
1072         System.out.println(
1073                 "Creating EPS file: " + outputFile.getAbsolutePath());
1074         af.createEPS(outputFile);
1075         continue;
1076       }
1077
1078       af.saveAlignment(file, format);
1079       if (af.isSaveAlignmentSuccessful())
1080       {
1081         System.out.println(
1082                 "Written alignment in " + format + " format to " + file);
1083       }
1084       else
1085       {
1086         System.out.println("Error writing file " + file + " in " + format
1087                 + " format!!");
1088       }
1089
1090     }
1091   }
1092
1093   private static void showUsage()
1094   {
1095     System.out.println(
1096             "Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
1097                     + "-nodisplay\tRun Jalview without User Interface.\n"
1098                     + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
1099                     + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
1100                     + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
1101                     + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
1102                     + "-features FILE\tUse the given file to mark features on the alignment.\n"
1103                     + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
1104                     + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
1105                     + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
1106                     + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
1107                     + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
1108                     + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
1109                     + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
1110                     + "-json FILE\tCreate alignment file FILE in JSON format.\n"
1111                     + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
1112                     + "-png FILE\tCreate PNG image FILE from alignment.\n"
1113                     + "-svg FILE\tCreate SVG image FILE from alignment.\n"
1114                     + "-html FILE\tCreate HTML file from alignment.\n"
1115                     + "-biojsMSA FILE\tCreate BioJS MSA Viewer HTML file from alignment.\n"
1116                     + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
1117                     + "-eps FILE\tCreate EPS file FILE from alignment.\n"
1118                     + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
1119                     + "-noquestionnaire\tTurn off questionnaire check.\n"
1120                     + "-nonews\tTurn off check for Jalview news.\n"
1121                     + "-nousagestats\tTurn off google analytics tracking for this session.\n"
1122                     + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
1123                     // +
1124                     // "-setprop PROPERTY=VALUE\tSet the given Jalview property,
1125                     // after all other properties files have been read\n\t
1126                     // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
1127                     // passed in correctly)"
1128                     + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
1129                     + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
1130                     // +
1131                     // "-vdoc vamsas-document\tImport vamsas document into new
1132                     // session or join existing session with same URN\n"
1133                     // + "-vses vamsas-session\tJoin session with given URN\n"
1134                     + "-groovy FILE\tExecute groovy script in FILE, after all other arguments have been processed (if FILE is the text 'STDIN' then the file will be read from STDIN)\n"
1135                     + "\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n");
1136   }
1137
1138   private static void startUsageStats(final Desktop desktop)
1139   {
1140     /**
1141      * start a User Config prompt asking if we can log usage statistics.
1142      */
1143     PromptUserConfig prompter = new PromptUserConfig(
1144             Desktop.getDesktopPane(), "USAGESTATS",
1145             "Jalview Usage Statistics",
1146             "Do you want to help make Jalview better by enabling "
1147                     + "the collection of usage statistics with Google Analytics ?"
1148                     + "\n\n(you can enable or disable usage tracking in the preferences)",
1149             new Runnable()
1150             {
1151               @Override
1152               public void run()
1153               {
1154                 Cache.log.debug(
1155                         "Initialising googletracker for usage stats.");
1156                 Cache.initGoogleTracker();
1157                 Cache.log.debug("Tracking enabled.");
1158               }
1159             }, new Runnable()
1160             {
1161               @Override
1162               public void run()
1163               {
1164                 Cache.log.debug("Not enabling Google Tracking.");
1165               }
1166             }, null, true);
1167     desktop.addDialogThread(prompter);
1168   }
1169
1170   /**
1171    * Locate the given string as a file and pass it to the groovy interpreter.
1172    * 
1173    * @param groovyscript
1174    *          the script to execute
1175    * @param jalviewContext
1176    *          the Jalview Desktop object passed in to the groovy binding as the
1177    *          'Jalview' object.
1178    */
1179   private void executeGroovyScript(String groovyscript, AlignFrame af)
1180   {
1181     /**
1182      * for scripts contained in files
1183      */
1184     File tfile = null;
1185     /**
1186      * script's URI
1187      */
1188     URL sfile = null;
1189     if (groovyscript.trim().equals("STDIN"))
1190     {
1191       // read from stdin into a tempfile and execute it
1192       try
1193       {
1194         tfile = File.createTempFile("jalview", "groovy");
1195         PrintWriter outfile = new PrintWriter(
1196                 new OutputStreamWriter(new FileOutputStream(tfile)));
1197         BufferedReader br = new BufferedReader(
1198                 new InputStreamReader(System.in));
1199         String line = null;
1200         while ((line = br.readLine()) != null)
1201         {
1202           outfile.write(line + "\n");
1203         }
1204         br.close();
1205         outfile.flush();
1206         outfile.close();
1207
1208       } catch (Exception ex)
1209       {
1210         System.err.println("Failed to read from STDIN into tempfile "
1211                 + ((tfile == null) ? "(tempfile wasn't created)"
1212                         : tfile.toString()));
1213         ex.printStackTrace();
1214         return;
1215       }
1216       try
1217       {
1218         sfile = tfile.toURI().toURL();
1219       } catch (Exception x)
1220       {
1221         System.err.println(
1222                 "Unexpected Malformed URL Exception for temporary file created from STDIN: "
1223                         + tfile.toURI());
1224         x.printStackTrace();
1225         return;
1226       }
1227     }
1228     else
1229     {
1230       try
1231       {
1232         sfile = new URI(groovyscript).toURL();
1233       } catch (Exception x)
1234       {
1235         tfile = new File(groovyscript);
1236         if (!tfile.exists())
1237         {
1238           System.err.println("File '" + groovyscript + "' does not exist.");
1239           return;
1240         }
1241         if (!tfile.canRead())
1242         {
1243           System.err.println("File '" + groovyscript + "' cannot be read.");
1244           return;
1245         }
1246         if (tfile.length() < 1)
1247         {
1248           System.err.println("File '" + groovyscript + "' is empty.");
1249           return;
1250         }
1251         try
1252         {
1253           sfile = tfile.getAbsoluteFile().toURI().toURL();
1254         } catch (Exception ex)
1255         {
1256           System.err.println("Failed to create a file URL for "
1257                   + tfile.getAbsoluteFile());
1258           return;
1259         }
1260       }
1261     }
1262     try
1263     {
1264       Map<String, Object> vbinding = new HashMap<>();
1265       vbinding.put("Jalview", this);
1266       if (af != null)
1267       {
1268         vbinding.put("currentAlFrame", af);
1269       }
1270       Binding gbinding = new Binding(vbinding);
1271       GroovyScriptEngine gse = new GroovyScriptEngine(new URL[] { sfile });
1272       gse.run(sfile.toString(), gbinding);
1273       if ("STDIN".equals(groovyscript))
1274       {
1275         // delete temp file that we made -
1276         // only if it was successfully executed
1277         tfile.delete();
1278       }
1279     } catch (Exception e)
1280     {
1281       System.err.println("Exception Whilst trying to execute file " + sfile
1282               + " as a groovy script.");
1283       e.printStackTrace(System.err);
1284
1285     }
1286   }
1287
1288   public AlignFrame[] getAlignFrames()
1289   {
1290     return desktop == null ? new AlignFrame[] { getCurrentAlignFrame() }
1291             : Desktop.getAlignFrames();
1292
1293   }
1294
1295   /**
1296    * Quit method delegates to Desktop.quit - unless running in headless mode
1297    * when it just ends the JVM
1298    */
1299   public void quit()
1300   {
1301     if (jsFunctionExec != null)
1302     {
1303       jsFunctionExec.tidyUp();
1304       jsFunctionExec = null;
1305     }
1306
1307     if (desktop != null)
1308     {
1309       desktop.quit();
1310     }
1311     else
1312     {
1313       System.exit(0);
1314     }
1315   }
1316
1317   /**
1318    * Get the SwingJS applet ID and combine that with the frameType
1319    * 
1320    * @param frameType
1321    *          "alignment", "desktop", etc., or null
1322    * @return
1323    */
1324   public static String getAppID(String frameType)
1325   {
1326     String id = Cache.getProperty("Info.j2sAppletID");
1327     if (id == null)
1328     {
1329       id = "jalview";
1330     }
1331     return id + (frameType == null ? "" : "-" + frameType);
1332   }
1333
1334   /**
1335    * Handle all JalviewLite applet parameters
1336    * 
1337    * @param aparser
1338    * @param af
1339    */
1340   private void loadAppletParams(ArgsParser aparser, AlignFrame af)
1341   {
1342     JalviewApp app = new JalviewApp()
1343     {
1344
1345       // TODO BH 2019
1346       //
1347       // These are methods that are in JalviewLite that various classes call
1348       // but are not in JalviewLiteJsApi. Or, even if they are, other classes
1349       // call
1350       // them to JalviewLite directly. Some may not be necessary, but they have
1351       // to
1352       // be at least mentioned here, or the classes calling them should
1353       // reference
1354       // JalviewLite itself.
1355
1356       private boolean alignPDBStructures; // From JalviewLite; not implemented
1357
1358       private Hashtable<String, Hashtable<String, String[]>> jsmessages;
1359
1360       private Hashtable<String, int[]> jshashes;
1361
1362       @Override
1363       public String getParameter(String name)
1364       {
1365         return aparser.getAppletValue(name, null);
1366       }
1367
1368       @Override
1369       public boolean getDefaultParameter(String name, boolean def)
1370       {
1371         String stn;
1372         return ((stn = getParameter(name)) == null ? def
1373                 : "true".equalsIgnoreCase(stn));
1374       }
1375
1376       /**
1377        * Get the applet-like document base even though this is an application.
1378        */
1379       @Override
1380       public URL getDocumentBase()
1381       {
1382         return Platform.getDocumentBase();
1383       }
1384
1385       /**
1386        * Get the applet-like code base even though this is an application.
1387        */
1388       @Override
1389       public URL getCodeBase()
1390       {
1391         return Platform.getCodeBase();
1392       }
1393
1394       @Override
1395       public AlignViewportI getViewport()
1396       {
1397         return af.getViewport();
1398       }
1399
1400       /**
1401        * features
1402        * 
1403        */
1404       @Override
1405       public boolean parseFeaturesFile(String filename,
1406               DataSourceType protocol)
1407       {
1408         return af.parseFeaturesFile(filename, protocol);
1409       }
1410
1411       /**
1412        * scorefile
1413        * 
1414        */
1415       @Override
1416       public boolean loadScoreFile(String sScoreFile) throws IOException
1417       {
1418         af.loadJalviewDataFile(sScoreFile, null, null, null);
1419         return true;
1420       }
1421
1422       /**
1423        * annotations, jpredfile, jnetfile
1424        * 
1425        */
1426       @Override
1427       public void updateForAnnotations()
1428       {
1429         af.updateForAnnotations();
1430       }
1431
1432       @Override
1433       public void loadTree(NewickFile fin, String treeFile)
1434               throws IOException
1435       {
1436         // n/a -- already done by standard Jalview command line processing
1437       }
1438
1439       @Override
1440       public void setAlignPdbStructures(boolean defaultParameter)
1441       {
1442         alignPDBStructures = true;
1443       }
1444
1445       @Override
1446       public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
1447               String[] chains, DataSourceType protocol)
1448       {
1449         StructureViewer.launchStructureViewer(af.alignPanel, pdb, seqs);
1450       }
1451
1452       @Override
1453       public void setFeatureGroupState(String[] groups, boolean state)
1454       {
1455         af.setFeatureGroupState(groups, state);
1456       }
1457
1458       @Override
1459       public void alignedStructureView(PDBEntry[] pdb, SequenceI[][] seqs,
1460               String[][] chains, String[] protocols)
1461       {
1462         System.err.println(
1463                 "Jalview applet interface alignedStructureView not implemented");
1464       }
1465
1466       @Override
1467       public void newFeatureSettings()
1468       {
1469         System.err.println(
1470                 "Jalview applet interface newFeatureSettings not implemented");
1471       }
1472
1473       private Vector<Runnable> jsExecQueue;
1474
1475       @Override
1476       public Vector<Runnable> getJsExecQueue(JSFunctionExec exec)
1477       {
1478         jsFunctionExec = exec;
1479         return (jsExecQueue == null ? (jsExecQueue = new Vector<>())
1480                 : jsExecQueue);
1481       }
1482
1483       @Override
1484       public AppletContext getAppletContext()
1485       {
1486         // TODO Auto-generated method stub
1487         return null;
1488       }
1489
1490       @Override
1491       public boolean isJsfallbackEnabled()
1492       {
1493         // TODO Auto-generated method stub
1494         return false;
1495       }
1496
1497       @Override
1498       public JSObject getJSObject()
1499       {
1500         // TODO Auto-generated method stub
1501         return null;
1502       }
1503
1504       @Override
1505       public StructureSelectionManagerProvider getStructureSelectionManagerProvider()
1506       {
1507         // TODO Q: what exactly is this? BH
1508         return null;
1509       }
1510
1511       @Override
1512       public void updateColoursFromMouseOver(Object source,
1513               MouseOverStructureListener mouseOverStructureListener)
1514       {
1515         // TODO Auto-generated method stub
1516
1517       }
1518
1519       @Override
1520       public Object[] getSelectionForListener(SequenceGroup seqsel,
1521               ColumnSelection colsel, HiddenColumns hidden,
1522               SelectionSource source, Object alignFrame)
1523       {
1524         return appLoader.getSelectionForListener(getCurrentAlignFrame(),
1525                 seqsel, colsel, hidden, source, alignFrame);
1526       }
1527
1528       @Override
1529       public String arrayToSeparatorList(String[] array)
1530       {
1531         return appLoader.arrayToSeparatorList(array);
1532       }
1533
1534       @Override
1535       public Hashtable<String, int[]> getJSHashes()
1536       {
1537         return (jshashes == null ? (jshashes = new Hashtable<>())
1538                 : jshashes);
1539       }
1540
1541       @Override
1542       public Hashtable<String, Hashtable<String, String[]>> getJSMessages()
1543       {
1544         return (jsmessages == null ? (jsmessages = new Hashtable<>())
1545                 : jsmessages);
1546       }
1547
1548       @Override
1549       public Object getFrameForSource(VamsasSource source)
1550       {
1551         if (source != null)
1552         {
1553           AlignFrame af;
1554           if (source instanceof jalview.gui.AlignViewport
1555                   && source == (af = getCurrentAlignFrame()).getViewport())
1556           {
1557             // should be valid if it just generated an event!
1558             return af;
1559           }
1560           // TODO: ensure that if '_af' is specified along with a handler
1561           // function, then only events from that alignFrame are sent to that
1562           // function
1563         }
1564         return null;
1565       }
1566
1567       @Override
1568       public FeatureRenderer getNewFeatureRenderer(AlignViewportI vp)
1569       {
1570         return new jalview.gui.FeatureRenderer((AlignmentPanel) vp);
1571       }
1572
1573     };
1574
1575     appLoader = new JalviewAppLoader(true);
1576     appLoader.load(app);
1577   }
1578
1579   /**
1580    * 
1581    * @see jalview.bin.JalviewLiteJsApi#getSelectedSequences()
1582    */
1583   @Override
1584   public String getSelectedSequences()
1585   {
1586     return getSelectedSequencesFrom(getCurrentAlignFrame());
1587   }
1588
1589   /**
1590    * 
1591    * @see jalview.bin.JalviewLiteJsApi#getSelectedSequences(java.lang.String)
1592    */
1593   @Override
1594   public String getSelectedSequences(String sep)
1595   {
1596     return getSelectedSequencesFrom(getCurrentAlignFrame(), sep);
1597   }
1598
1599   /**
1600    * 
1601    * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
1602    *      .AlignFrame)
1603    */
1604   @Override
1605   public String getSelectedSequencesFrom(AlignFrameI alf)
1606   {
1607     return getSelectedSequencesFrom(alf, null);
1608   }
1609
1610   /**
1611    * 
1612    * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
1613    *      .AlignFrame, java.lang.String)
1614    */
1615   @Override
1616   public String getSelectedSequencesFrom(AlignFrameI alf, String sep)
1617   {
1618     return appLoader.getSelectedSequencesFrom(alf, sep);
1619   }
1620
1621   /**
1622    * 
1623    * @see jalview.bin.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
1624    *      .AlignFrame, java.lang.String)
1625    */
1626   @Override
1627   public void highlight(String sequenceId, String position,
1628           String alignedPosition)
1629   {
1630     highlightIn(getCurrentAlignFrame(), sequenceId, position,
1631             alignedPosition);
1632   }
1633
1634   @Override
1635   public void highlightIn(AlignFrameI alf, String sequenceId,
1636           String position, String alignedPosition)
1637   {
1638     appLoader.highlightIn(alf, sequenceId, position, alignedPosition);
1639   }
1640
1641   @Override
1642   public void select(String sequenceIds, String columns)
1643   {
1644     selectIn(getCurrentAlignFrame(), sequenceIds, columns, null);
1645   }
1646
1647   @Override
1648   public void select(String sequenceIds, String columns, String sep)
1649   {
1650     selectIn(getCurrentAlignFrame(), sequenceIds, columns, sep);
1651   }
1652
1653   @Override
1654   public void selectIn(AlignFrameI alf, String sequenceIds, String columns)
1655   {
1656     selectIn(alf, sequenceIds, columns, null);
1657   }
1658
1659   @Override
1660   public void selectIn(AlignFrameI alf, String sequenceIds, String columns,
1661           String sep)
1662   {
1663     appLoader.selectIn(alf, sequenceIds, columns, sep);
1664   }
1665
1666   @Override
1667   public String getSelectedSequencesAsAlignment(String format,
1668           String suffix)
1669   {
1670     return getSelectedSequencesAsAlignmentFrom(getCurrentAlignFrame(),
1671             format, suffix);
1672   }
1673
1674   @Override
1675   public String getSelectedSequencesAsAlignmentFrom(AlignFrameI alf,
1676           String format, String sep)
1677   {
1678     return appLoader.getSelectedSequencesAsAlignmentFrom(alf, format, sep);
1679   }
1680
1681   @Override
1682   public String getAlignmentOrder()
1683   {
1684     return getAlignmentFrom(getCurrentAlignFrame(), null);
1685   }
1686
1687   @Override
1688   public String getAlignmentOrderFrom(AlignFrameI alf)
1689   {
1690     return getAlignmentFrom(alf, null);
1691   }
1692
1693   @Override
1694   public String getAlignmentOrderFrom(AlignFrameI alf, String sep)
1695   {
1696     return appLoader.getAlignmentOrderFrom(alf, sep);
1697   }
1698
1699   @Override
1700   public String orderBy(String order, String undoName)
1701   {
1702     return orderBy(order, undoName, null);
1703   }
1704
1705   @Override
1706   public String orderBy(String order, String undoName, String sep)
1707   {
1708     return orderAlignmentBy(getCurrentAlignFrame(), order, undoName, sep);
1709   }
1710
1711   @Override
1712   public String orderAlignmentBy(AlignFrameI alf, String order,
1713           String undoName, String sep)
1714   {
1715     return appLoader.orderAlignmentBy(alf, order, undoName, sep);
1716   }
1717
1718   @Override
1719   public String getAlignment(String format)
1720   {
1721     return getAlignmentFrom(null, format, null);
1722   }
1723
1724   @Override
1725   public String getAlignmentFrom(AlignFrameI alf, String format)
1726   {
1727     return getAlignmentFrom(alf, format, null);
1728   }
1729
1730   @Override
1731   public String getAlignment(String format, String suffix)
1732   {
1733     return getAlignmentFrom(getCurrentAlignFrame(), format, suffix);
1734   }
1735
1736   @Override
1737   public String getAlignmentFrom(AlignFrameI alf, String format,
1738           String suffix)
1739   {
1740     return appLoader.getAlignmentFrom(alf, format, suffix);
1741   }
1742
1743   @Override
1744   public void loadAnnotation(String annotation)
1745   {
1746     loadAnnotationFrom(getCurrentAlignFrame(), annotation);
1747   }
1748
1749   @Override
1750   public void loadAnnotationFrom(AlignFrameI alf, String annotation)
1751   {
1752     appLoader.loadAnnotationFrom(alf, annotation);
1753   }
1754
1755   @Override
1756   public void loadFeatures(String features, boolean autoenabledisplay)
1757   {
1758     loadFeaturesFrom(currentAlignFrame, features, autoenabledisplay);
1759   }
1760
1761   @Override
1762   public boolean loadFeaturesFrom(AlignFrameI alf, String features,
1763           boolean autoenabledisplay)
1764   {
1765     return appLoader.loadFeaturesFrom(alf, features, autoenabledisplay);
1766   }
1767
1768   @Override
1769   public String getFeatures(String format)
1770   {
1771     return getFeaturesFrom(getCurrentAlignFrame(), format);
1772   }
1773
1774   @Override
1775   public String getFeaturesFrom(AlignFrameI alf, String format)
1776   {
1777     return appLoader.getFeaturesFrom(alf, format);
1778   }
1779
1780   @Override
1781   public String getAnnotation()
1782   {
1783     return getAnnotationFrom(getCurrentAlignFrame());
1784   }
1785
1786   @Override
1787   public String getAnnotationFrom(AlignFrameI alf)
1788   {
1789     return appLoader.getAnnotationFrom(alf);
1790   }
1791
1792   @Override
1793   public AlignFrameI newView()
1794   {
1795     return newViewFrom(getCurrentAlignFrame(), null);
1796   }
1797
1798   @Override
1799   public AlignFrameI newView(String name)
1800   {
1801     return newViewFrom(getCurrentAlignFrame(), name);
1802   }
1803
1804   @Override
1805   public AlignFrameI newViewFrom(AlignFrameI alf)
1806   {
1807     return newViewFrom(alf, null);
1808   }
1809
1810   @Override
1811   public AlignFrameI newViewFrom(AlignFrameI alf, String name)
1812   {
1813     return appLoader.newViewFrom(alf, name);
1814   }
1815
1816   @Override
1817   public AlignFrameI loadAlignment(String text, String title)
1818   {
1819     return appLoader.loadAlignment(text, AlignFrame.DEFAULT_WIDTH,
1820             AlignFrame.DEFAULT_HEIGHT, title);
1821   }
1822
1823   @Override
1824   public boolean addPdbFile(AlignFrameI alFrame, String sequenceId,
1825           String pdbEntryString, String pdbFile)
1826   {
1827     return appLoader.addPdbFile(alFrame, sequenceId, pdbEntryString,
1828             pdbFile);
1829   }
1830
1831   @Override
1832   public void scrollViewToIn(AlignFrameI alf, String topRow,
1833           String leftHandColumn)
1834   {
1835     appLoader.scrollViewToIn(alf, topRow, leftHandColumn);
1836   }
1837
1838   @Override
1839   public void scrollViewToRowIn(AlignFrameI alf, String topRow)
1840   {
1841     appLoader.scrollViewToRowIn(alf, topRow);
1842   }
1843
1844   @Override
1845   public void scrollViewToColumnIn(AlignFrameI alf, String leftHandColumn)
1846   {
1847     appLoader.scrollViewToColumnIn(alf, leftHandColumn);
1848   }
1849
1850   @Override
1851   public String getFeatureGroups()
1852   {
1853     return getFeatureGroupsOn(getCurrentAlignFrame());
1854   }
1855
1856   @Override
1857   public String getFeatureGroupsOn(AlignFrameI alf)
1858   {
1859     return appLoader.getFeatureGroupsOn(alf);
1860   }
1861
1862   @Override
1863   public String getFeatureGroupsOfState(boolean visible)
1864   {
1865     return getFeatureGroupsOfStateOn(getCurrentAlignFrame(), visible);
1866   }
1867
1868   @Override
1869   public String getFeatureGroupsOfStateOn(AlignFrameI alf, boolean visible)
1870   {
1871     return appLoader.getFeatureGroupsOfStateOn(alf, visible);
1872   }
1873
1874   @Override
1875   public void setFeatureGroupStateOn(AlignFrameI alf, String groups,
1876           boolean state)
1877   {
1878     setFeatureGroupStateOn(alf, groups, state);
1879   }
1880
1881   @Override
1882   public void setFeatureGroupState(String groups, boolean state)
1883   {
1884     appLoader.setFeatureGroupStateOn(getCurrentAlignFrame(), groups, state);
1885   }
1886
1887   @Override
1888   public String getSeparator()
1889   {
1890     return appLoader.getSeparator();
1891   }
1892
1893   @Override
1894   public void setSeparator(String separator)
1895   {
1896     appLoader.setSeparator(separator);
1897   }
1898
1899   @Override
1900   public String getJsMessage(String messageclass, String viewId)
1901   {
1902     // see http://www.jalview.org/examples/jalviewLiteJs.html
1903     return null;
1904   }
1905
1906   /**
1907    * Open a new Tree panel on the desktop statically. Params are standard (not
1908    * set by Groovy). No dialog is opened.
1909    * 
1910    * @param af
1911    * @param treeType
1912    * @param modelName
1913    * @return null, or the string "label.you_need_at_least_n_sequences" if number
1914    *         of sequences selected is inappropriate
1915    */
1916   @Override
1917   public Object openTreePanel(AlignFrame af, String treeType,
1918           String modelName)
1919   {
1920     return CalculationChooser.openTreePanel(af, treeType, modelName, null);
1921   }
1922
1923   /**
1924    * public static method for JalviewJS API to open a PCAPanel without
1925    * necessarily using a dialog.
1926    * 
1927    * @param af
1928    * @param modelName
1929    * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
1930    *         if number of sequences selected is inappropriate
1931    */
1932   @Override
1933   public Object openPcaPanel(AlignFrame af, String modelName)
1934   {
1935     return CalculationChooser.openPcaPanel(af, modelName, null);
1936   }
1937
1938   @Override
1939   public String getSelectedSequencesAsAlignment(String format,
1940           boolean suffix)
1941   {
1942     return getSelectedSequencesAsAlignmentFrom(getCurrentAlignFrame(),
1943             format, suffix);
1944   }
1945
1946   @Override
1947   public String getSelectedSequencesAsAlignmentFrom(AlignFrameI alf,
1948           String format, boolean suffix)
1949   {
1950     return appLoader.getSelectedSequencesAsAlignmentFrom(alf, format,
1951             "" + suffix);
1952   }
1953
1954   @Override
1955   public String arrayToSeparatorList(String[] array)
1956   {
1957     return appLoader.arrayToSeparatorList(array);
1958   }
1959
1960   @Override
1961   public String[] separatorListToArray(String list)
1962   {
1963     return appLoader.separatorListToArray(list);
1964   }
1965
1966   //// probably not needed in JalviewJS -- From when Jmol and Jalview did not
1967   //// have a direct connection?
1968
1969   @Override
1970   public void setMouseoverListener(String listener)
1971   {
1972     // TODO Auto-generated method stub
1973
1974   }
1975
1976   @Override
1977   public void setMouseoverListener(AlignFrameI af, String listener)
1978   {
1979     // TODO Auto-generated method stub
1980
1981   }
1982
1983   @Override
1984   public void setSelectionListener(String listener)
1985   {
1986     // TODO Auto-generated method stub
1987
1988   }
1989
1990   @Override
1991   public void setSelectionListener(AlignFrameI af, String listener)
1992   {
1993     // TODO Auto-generated method stub
1994
1995   }
1996
1997   @Override
1998   public void setStructureListener(String listener, String modelSet)
1999   {
2000     // TODO Auto-generated method stub
2001
2002   }
2003
2004   @Override
2005   public void removeJavascriptListener(AlignFrameI af, String listener)
2006   {
2007     // TODO Auto-generated method stub
2008
2009   }
2010
2011   @Override
2012   public void mouseOverStructure(String pdbResNum, String chain,
2013           String pdbfile)
2014   {
2015     // TODO Auto-generated method stub
2016
2017   }
2018
2019
2020 }