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