3 import java.awt.EventQueue;
4 //import java.applet.AppletContext;
5 import java.io.IOException;
7 import java.util.ArrayList;
9 import java.util.StringTokenizer;
10 import java.util.Vector;
12 import jalview.bin.ArgsParser;
13 import jalview.bin.Jalview;
14 import jalview.bin.JalviewJSApi;
15 import jalview.datamodel.Alignment;
16 import jalview.datamodel.AlignmentI;
17 import jalview.datamodel.AlignmentOrder;
18 import jalview.datamodel.ColumnSelection;
19 import jalview.datamodel.HiddenColumns;
20 import jalview.datamodel.PDBEntry;
21 import jalview.datamodel.Sequence;
22 import jalview.datamodel.SequenceGroup;
23 import jalview.datamodel.SequenceI;
24 import jalview.gui.AlignFrame;
25 import jalview.gui.AlignViewport;
26 import jalview.gui.CalculationChooser;
27 import jalview.gui.Desktop;
28 import jalview.gui.StructureViewer;
29 import jalview.io.AnnotationFile;
30 import jalview.io.AppletFormatAdapter;
31 import jalview.io.DataSourceType;
32 import jalview.io.FeaturesFile;
33 import jalview.io.FileFormat;
34 import jalview.io.FileFormatI;
35 import jalview.io.FileFormats;
36 import jalview.io.IdentifyFile;
37 import jalview.io.JPredFile;
38 import jalview.io.JnetAnnotationMaker;
39 import jalview.io.NewickFile;
40 import jalview.structure.SelectionListener;
41 import jalview.structure.SelectionSource;
42 import jalview.structure.StructureSelectionManager;
43 import jalview.structure.VamsasSource;
44 import jalview.util.HttpUtils;
45 import jalview.util.MessageManager;
46 import jalview.util.Platform;
48 //import netscape.javascript.JSObject;
51 * Basically the JalviewLite application, but without JalviewLite
56 public class JalviewJSApp implements JalviewJSApi
58 private ArgsParser aparser;
60 private boolean debug;
62 private String[] ret = new String[1];
64 private String separator = "\u00AC"; // JalviewLite note: the default used to
65 // be '|', but many sequence IDS include
69 * We maintain a pointer to the jalview instance here, because only with that do we have a direct
70 * connection from the JavaScript "applet" object to the proper instance of Jalview in case there
71 * are multiple applets on a page.
73 private Jalview jalview;
76 public JalviewJSApp(Jalview jalview, ArgsParser aparser)
78 this.jalview = jalview;
79 this.aparser = aparser;
80 Platform.setAppClass(this);
84 public void load(AlignFrame af)
86 String sep = (String) getAppletParameter("separator", true);
95 throw new Error(MessageManager
96 .getString("error.invalid_separator_parameter"));
110 // These are methods that are in JalviewLite that various classes call
111 // but are not in JalviewLiteJsApi. Or, even if they are, other classes
113 // them to JalviewLite directly. Some may not be necessary, but they have
115 // be at least mentioned here, or the classes calling them should
117 // JalviewLite itself.
119 // private boolean alignPDBStructures; // From JalviewLite; not implemented
123 public String getParameter(String name)
125 return (String) getAppletParameter(name, true);
129 public Object getAppletParameter(String name, boolean asString)
131 return aparser.getAppletValue(name, null, asString);
135 * Get the applet-like code base even though this is an application.
139 public URL getCodeBase()
141 return Platform.getCodeBase();
145 * Get the applet-like document base even though this is an application.
149 public URL getDocumentBase()
151 return Platform.getDocumentBase();
155 public Object getFrameForSource(VamsasSource source)
160 if (source instanceof jalview.gui.AlignViewport
161 && source == (af = Jalview.getCurrentAlignFrame())
164 // should be valid if it just generated an event!
167 // TODO: ensure that if '_af' is specified along with a handler
168 // function, then only events from that alignFrame are sent to that
175 public Object[] getSelectionForListener(SequenceGroup seqsel,
176 ColumnSelection colsel, HiddenColumns hidden,
177 SelectionSource source, Object alignFrame)
179 return getSelectionForListener(null, seqsel, colsel, hidden, source,
189 public boolean loadScoreFile(String sScoreFile) throws IOException
191 return loadScoreFile(null, sScoreFile);
194 public boolean loadScoreFile(AlignFrame af, String sScoreFile) throws IOException
196 (af == null ? Jalview.getCurrentAlignFrame() : af).loadJalviewDataFile(sScoreFile, null, null, null);
200 public void loadTree(AlignFrame af, NewickFile nf, String treeFile) throws IOException
203 af = Jalview.getCurrentAlignFrame();
205 .setCurrentTree(af.showNewickTree(nf, treeFile).getTree());
209 public void newFeatureSettings()
212 "Jalview applet interface newFeatureSettings not implemented");
217 // public void setAlignPdbStructures(boolean defaultParameter)
219 // alignPDBStructures = true;
224 public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
225 String[] chains, DataSourceType protocol)
227 newStructureView(null, pdb, seqs, chains, protocol);
232 * @j2sAlias showStructure
235 public void showStructure(AlignFrame af, String pdbID, String fileType) {
237 af = Jalview.getCurrentAlignFrame();
239 SequenceI[] seqs = null;
241 seqs = af.getViewport().getSequenceSelection();
242 if (seqs.length == 0)
243 seqs = af.getViewport().getAlignment().getSequencesArray();
244 for (int i = 0; i < seqs.length; i++) {
245 Vector<PDBEntry> list = seqs[i].getAllPDBEntries();
246 if (list.size() > 0) {
255 pe = new PDBEntry(pdbID, null, fileType);
256 List<SequenceI> list = af.getViewport().getAlignment().getSequences();
257 List<SequenceI> tmp = new ArrayList<SequenceI>();
258 for (int i = 0; i < list.size(); i++) {
259 SequenceI seq = list.get(i);
260 if (seq.getPDBEntry(pdbID) != null) {
264 seqs = tmp.toArray(new SequenceI[tmp.size()]);
265 af.alignPanel.selectSequences(tmp);
267 StructureViewer.launchStructureViewer(
272 public void newStructureView(AlignFrame af, PDBEntry pdb,
273 SequenceI[] seqs, String[] chains, DataSourceType protocol)
275 StructureViewer.launchStructureViewer(
276 (af == null ? Jalview.getCurrentAlignFrame() : af).alignPanel,
287 public boolean parseFeaturesFile(String filename, DataSourceType protocol)
289 return parseFeaturesFile(null, filename, protocol);
293 * @j2sAlias parseFeatureFile
300 public boolean parseFeaturesFile(AlignFrame af, String filename, DataSourceType protocol)
302 return (af == null ? Jalview.getCurrentAlignFrame() : af).parseFeaturesFile(filename, protocol);
306 * annotations, jpredfile, jnetfile
311 public void updateForAnnotations()
313 updateForAnnotations(null);
316 public void updateForAnnotations(AlignFrame af)
318 (af == null ? Jalview.getCurrentAlignFrame() : af).updateForAnnotations();
322 public boolean addPdbFile(AlignFrame alf, String sequenceId, String pdbId,
327 alf = Jalview.getCurrentAlignFrame();
329 SequenceI seq = alf.getViewport().getAlignment().findName(sequenceId);
332 Vector<PDBEntry> pdbe = seq.getAllPDBEntries();
333 PDBEntry pdbentry = null;
334 if (pdbe != null && pdbe.size() > 0)
336 for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)
338 pdbentry = pdbe.elementAt(pe);
339 if (!pdbentry.getId().equals(pdbId)
340 || pdbFile != null && !pdbentry.getFile().equals(pdbFile))
346 if (pdbentry == null)
348 pdbentry = new PDBEntry(pdbId, null, pdbFile);
351 DataSourceType protocol = AppletFormatAdapter
352 .resolveProtocol(pdbFile, FileFormat.PDB);
353 if (protocol == null)
355 pdbentry.setProperty("protocol", protocol);
357 seq.addPDBId(pdbentry);
358 alf.alignPanel.getStructureSelectionManager()
359 .registerPDBEntry(pdbentry);
366 // public String arrayToSeparatorList(String[] array)
368 // return arrayToSeparatorList(array, separator);
372 // * concatenate the list with separator
375 // * @param separator
376 // * @return concatenated string
378 // public static String arrayToSeparatorList(String[] list, String separator)
380 // // TODO use StringUtils version
381 // StringBuffer v = new StringBuffer();
382 // if (list != null && list.length > 0)
384 // for (int i = 0, iSize = list.length; i < iSize; i++)
386 // if (list[i] != null)
390 // v.append(separator);
392 // v.append(list[i]);
398 // // .println("Returning '" + separator + "' separated List:\n");
399 // // System.err.println(v);
401 // return v.toString();
405 // // System.err.println(
406 // // "Returning empty '" + separator + "' separated List\n");
408 // return "" + separator;
412 public String getAlignment(String format)
414 return getAlignmentFrom(null, format, null);
418 * suffix string "true"/"false" (default true)
419 * passed to AlnFile class controls whether /START-END is added to
423 public String getAlignment(String format, String suffix)
425 return getAlignmentFrom(Jalview.getCurrentAlignFrame(), format, suffix);
429 public String getAlignmentFrom(AlignFrame alf, String format)
431 return getAlignmentFrom(alf, format, null);
435 public String getAlignmentFrom(AlignFrame alf, String format,
442 alf = Jalview.getCurrentAlignFrame();
444 boolean seqlimits = (suffix == null
445 || suffix.equalsIgnoreCase("true"));
447 FileFormatI theFormat = FileFormats.getInstance().forName(format);
448 String reply = new AppletFormatAdapter().formatSequences(theFormat,
449 alf.getViewport().getAlignment(), seqlimits);
451 } catch (IllegalArgumentException ex)
453 ex.printStackTrace();
454 return "Error retrieving alignment, possibly invalid format specifier: "
460 public String getAlignmentOrder()
462 return getAlignmentFrom(Jalview.getCurrentAlignFrame(), null);
466 public String[] getAlignmentOrderFrom(AlignFrame alf)
470 alf = Jalview.getCurrentAlignFrame();
472 AlignmentI alorder = alf.getViewport().getAlignment();
473 String[] order = new String[alorder.getHeight()];
474 for (int i = 0; i < order.length; i++)
476 order[i] = alorder.getSequenceAt(i).getName();
478 return order;// arrayToSeparatorList(order, sep);
482 public String getAnnotation()
484 return getAnnotationFrom(null);
488 public String getAnnotationFrom(AlignFrame alf)
492 alf = Jalview.getCurrentAlignFrame();
494 String annotation = new AnnotationFile()
495 .printAnnotationsForView(alf.getViewport());
500 public String[] getFeatureGroups()
502 return getFeatureGroupsOn(null);
506 public String[] getFeatureGroupsOfState(boolean visible)
508 return getFeatureGroupsOfStateOn(null, visible);
512 public String[] getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)
516 alf = Jalview.getCurrentAlignFrame();
518 return alf.getFeatureGroupsOfState(visible);
522 public String[] getFeatureGroupsOn(AlignFrame alf)
526 alf = Jalview.getCurrentAlignFrame();
528 return alf.getFeatureGroups();
532 public String getFeatures(String format)
534 return getFeaturesFrom(null, format);
538 * JavaScript interface to print the alignment frame
542 * "jalview" or "gff" with or without ";includeComplement" or
543 * ";includeNonpositional"; default with no ";" is
544 * ";includeNonpositional"
548 public String getFeaturesFrom(AlignFrame alf, String format)
552 alf = Jalview.getCurrentAlignFrame();
555 FeaturesFile formatter = new FeaturesFile();
556 format = format.toLowerCase();
557 if (format.indexOf(";") < 0)
558 format += ";includenonpositional";
559 boolean nonpos = format.indexOf(";includenonpositional") > 0;
560 boolean compl = format.indexOf(";includecomplement") >= 0;
561 if (format.startsWith("jalview"))
563 features = formatter.printJalviewFormat(
564 alf.getViewport().getAlignment().getSequencesArray(),
565 alf.alignPanel.getFeatureRenderer(), nonpos, compl);
569 features = formatter.printGffFormat(
570 alf.getViewport().getAlignment().getSequencesArray(),
571 alf.alignPanel.getFeatureRenderer(), nonpos, compl);
574 if (features == null)
583 * read sequence1...sequenceN as a raw alignment
588 public String getPastedSequence(JalviewJSApp jalviewApp)
590 StringBuffer data = new StringBuffer("PASTE");
593 while ((file = (String) getAppletParameter("sequence" + i,
596 data.append(file.toString() + "\n");
599 if (data.length() > 5)
601 file = data.toString();
608 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences()
611 public SequenceI[] getSelectedSequences()
613 return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame());
618 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences(java.lang.String)
621 public SequenceI[] getSelectedSequences(String sep)
623 return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame(), sep);
627 public String getSelectedSequencesAsAlignment(String format,
630 return getSelectedSequencesAsAlignmentFrom(null, format, suffix);
634 public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
635 String format, String suffix)
640 alf = Jalview.getCurrentAlignFrame();
643 boolean seqlimits = (suffix == null || suffix.equalsIgnoreCase("true"));
646 AlignViewport vp = alf.getViewport();
647 FileFormatI theFormat = FileFormats.getInstance().forName(format);
648 if (vp.getSelectionGroup() != null)
650 // JBPNote: getSelectionAsNewSequence behaviour has changed - this
651 // method now returns a full copy of sequence data
652 // TODO consider using getSequenceSelection instead here
653 String reply = new AppletFormatAdapter().formatSequences(theFormat,
654 new Alignment(vp.getSelectionAsNewSequence()), seqlimits);
657 } catch (IllegalArgumentException ex)
659 ex.printStackTrace();
660 return "Error retrieving alignment, possibly invalid format specifier: "
668 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
672 public SequenceI[] getSelectedSequencesFrom(AlignFrame alf)
674 return getSelectedSequencesFrom(alf, null);
678 public SequenceI[] getSelectedSequencesFrom(AlignFrame alf, String sep)
682 alf = Jalview.getCurrentAlignFrame();
684 AlignViewport v = alf.getViewport();
685 if (v.getSelectionGroup() != null)
687 return v.getSelectionGroup()
688 .getSequencesInOrder(v.getAlignment());
694 public Object[] getSelectionForListener(AlignFrame alf,
695 SequenceGroup seqsel, ColumnSelection colsel,
696 HiddenColumns hidden, SelectionSource source, Object alignFrame)
700 alf = Jalview.getCurrentAlignFrame();
702 // System.err.println("Testing selection event relay to
703 // jsfunction:"+_listener);
705 AlignFrame src = (AlignFrame) alignFrame;
708 if (source instanceof AlignViewport && alf.getViewport() == source)
710 // should be valid if it just generated an event!
715 String[] seqs = new String[] {};
716 String[] cols = new String[] {};
717 int strt = 0, end = (src == null) ? -1
718 : src.alignPanel.av.getAlignment().getWidth();
719 if (seqsel != null && seqsel.getSize() > 0)
721 seqs = new String[seqsel.getSize()];
722 for (int i = 0; i < seqs.length; i++)
724 seqs[i] = seqsel.getSequenceAt(i).getName();
726 if (strt < seqsel.getStartRes())
728 strt = seqsel.getStartRes();
730 if (end == -1 || end > seqsel.getEndRes())
732 end = seqsel.getEndRes();
735 if (colsel != null && !colsel.isEmpty())
739 end = colsel.getMax() + 1;
741 cols = new String[colsel.getSelected().size()];
742 for (int i = 0; i < cols.length; i++)
744 cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
749 if (seqsel != null && seqsel.getSize() > 0)
751 // send a valid range, otherwise we send the empty selection
752 cols = new String[2];
753 cols[0] = "" + (1 + strt) + "-" + (1 + end);
756 return new Object[] { src, setid, seqs, cols };
761 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
762 * .AlignFrame, java.lang.String)
765 public void highlight(String sequenceId, String position,
766 String alignedPosition)
768 highlightIn(null, sequenceId, position, alignedPosition);
772 public void highlightIn(AlignFrame alf, final String sequenceId,
773 final String position, final String alignedPosition)
777 alf = Jalview.getCurrentAlignFrame();
779 // TODO: could try to highlight in all alignments if alf==null
780 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
781 alf.getViewport().getAlignment().getSequencesArray());
782 final SequenceI sq = matcher.findIdMatch(sequenceId);
788 apos = Integer.valueOf(position).intValue();
790 } catch (NumberFormatException ex)
794 final int pos = apos;
795 // use vamsas listener to broadcast to all listeners in scope
796 if (alignedPosition != null && (alignedPosition.trim().length() == 0
797 || alignedPosition.toLowerCase().indexOf("false") > -1))
799 java.awt.EventQueue.invokeLater(new Runnable()
804 StructureSelectionManager
805 .getStructureSelectionManager(Desktop.getInstance())
806 .mouseOverVamsasSequence(sq, sq.findIndex(pos), null);
812 java.awt.EventQueue.invokeLater(new Runnable()
817 StructureSelectionManager
818 .getStructureSelectionManager(Desktop.getInstance())
819 .mouseOverVamsasSequence(sq, pos, null);
826 public AlignFrame loadAlignment(String text, int width, int height,
829 AlignmentI al = null;
833 FileFormatI format = new IdentifyFile().identify(text,
834 DataSourceType.PASTE);
835 al = new AppletFormatAdapter().readFile(text, DataSourceType.PASTE,
837 if (al.getHeight() > 0)
839 return new AlignFrame(al, width, height, title);
841 } catch (IOException ex)
843 ex.printStackTrace();
848 // public void setMouseoverListener(String listener)
850 // appLoader.setMouseoverListener(listener);
854 // public void setMouseoverListener(AlignFrame af, String listener)
860 public AlignFrame loadAlignment(String text, String title)
862 return loadAlignment(text, AlignFrame.DEFAULT_WIDTH,
863 AlignFrame.DEFAULT_HEIGHT, title);
867 public void loadAnnotation(String annotation)
869 loadAnnotationFrom(null, annotation);
873 public void loadAnnotationFrom(AlignFrame alf, String annotation)
877 alf = Jalview.getCurrentAlignFrame();
879 if (new AnnotationFile().annotateAlignmentView(alf.getViewport(),
880 annotation, DataSourceType.PASTE))
882 alf.alignPanel.fontChanged();
883 alf.alignPanel.setScrollValues(0, 0);
887 alf.parseFeaturesFile(annotation, DataSourceType.PASTE);
892 * Load annotations if specified by parameter. Returns true if loaded, else
899 protected boolean loadAnnotations(AlignFrame af)
901 boolean result = false;
902 String param = (String) getAppletParameter("annotations", true);
906 DataSourceType protocol = resolveFileProtocol(ret);
908 if (new AnnotationFile().annotateAlignmentView(af.getViewport(), param,
911 updateForAnnotations();
917 .println("Annotations were not added from annotation file '"
927 * Load features file and view settings as specified by parameters. Returns
928 * true if features were loaded, else false.
934 protected boolean loadFeatures(AlignFrame af)
936 boolean result = false;
937 // ///////////////////////////
938 // modify display of features
939 // we do this before any features have been loaded, ensuring any hidden
940 // groups are hidden when features first displayed
942 // hide specific groups
944 String param = (String) getAppletParameter("hidefeaturegroups", true);
947 setFeatureGroupState(af, separatorListToArray(param, separator), false);
948 // setFeatureGroupStateOn(newAlignFrame, param, false);
950 // show specific groups
951 param = (String) getAppletParameter("showfeaturegroups", true);
954 setFeatureGroupState(af, separatorListToArray(param, separator), true);
955 // setFeatureGroupStateOn(newAlignFrame, param, true);
957 // and now load features
958 param = (String) getAppletParameter("features", true);
962 DataSourceType protocol = resolveFileProtocol(ret);
964 result = parseFeaturesFile(af, ret[0], protocol);
967 param = (String) getAppletParameter("showFeatureSettings", true);
968 if (param != null && param.equalsIgnoreCase("true"))
970 newFeatureSettings();
976 public void loadFeatures(String features, boolean autoenabledisplay)
978 loadFeaturesFrom(null, features, autoenabledisplay);
982 public boolean loadFeaturesFrom(AlignFrame alf, String features,
983 boolean autoenabledisplay)
987 alf = Jalview.getCurrentAlignFrame();
989 boolean ret = alf.parseFeaturesFile(features, DataSourceType.PASTE);
994 if (autoenabledisplay)
996 alf.getViewport().setShowSequenceFeatures(true);
997 // this next was for a checkbox in JalviewLite
998 // ((AlignFrame) alf).getViewport().sequenceFeatures.setState(true);
1004 * Load in a Jnetfile if specified by parameter. Returns true if loaded, else
1010 protected boolean loadJnetFile(AlignFrame af)
1012 boolean result = false;
1013 String param = (String) getAppletParameter("jnetfile", true);
1016 // jnet became jpred around 2016
1017 param = (String) getAppletParameter("jpredfile", true);
1024 DataSourceType protocol = resolveFileProtocol(ret);
1025 JPredFile predictions = new JPredFile(ret[0], protocol);
1026 JnetAnnotationMaker.add_annotation(predictions,
1027 af.getViewport().getAlignment(), 0, false);
1028 // false == do not add sequence profile from concise output
1029 af.getViewport().getAlignment().setupJPredAlignment();
1030 updateForAnnotations();
1032 } catch (Exception ex)
1034 ex.printStackTrace();
1041 * Load PDBFiles if any specified by parameter(s). Returns true if loaded,
1044 * @param loaderFrame
1047 protected boolean loadPdbFiles(AlignFrame af)
1049 boolean result = false;
1051 * <param name="alignpdbfiles" value="false/true"/> Undocumented for 2.6 -
1052 * related to JAL-434
1055 // not supported (as for JalviewLite)
1056 // boolean doAlign = false;//"true".equalsIgnoreCase("" +
1057 // getAppletParameter("alignpdbfiles", false));
1058 // setAlignPdbStructures(doAlign);
1060 * <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B
1063 * <param name="PDBfile2" value="1gaq.txt A=SEQA B=SEQB C=SEQB">
1065 * <param name="PDBfile3" value="1q0o Q45135_9MICO">
1068 // Accumulate pdbs here if they are heading for the same view (if
1069 // alignPdbStructures is true)
1070 // ArrayList<Object[]> pdbs = new ArrayList<>();
1071 // create a lazy matcher if we're asked to
1072 boolean relaxed = "true".equalsIgnoreCase(
1073 "" + getAppletParameter("relaxedidmatch", false));
1074 jalview.analysis.SequenceIdMatcher matcher = relaxed
1075 ? new jalview.analysis.SequenceIdMatcher(
1076 af.getViewport().getAlignment().getSequencesArray())
1079 int pdbFileCount = 0;
1083 if (pdbFileCount > 0)
1085 param = (String) getAppletParameter("PDBFILE" + pdbFileCount, true);
1089 param = (String) getAppletParameter("PDBFILE", true);
1094 PDBEntry pdb = new PDBEntry();
1097 SequenceI[] seqs = null;
1098 String[] chains = null;
1100 StringTokenizer st = new StringTokenizer(param, " ");
1102 if (st.countTokens() < 2)
1104 String sequence = (String) getAppletParameter("PDBSEQ", true);
1105 if (sequence != null)
1107 seqs = new SequenceI[] { matcher == null
1108 ? (Sequence) af.getViewport().getAlignment()
1110 : matcher.findIdMatch(sequence) };
1116 param = st.nextToken();
1117 List<SequenceI> tmp = new ArrayList<>();
1118 List<String> tmp2 = new ArrayList<>();
1120 while (st.hasMoreTokens())
1122 seqstring = st.nextToken();
1123 StringTokenizer st2 = new StringTokenizer(seqstring, "=");
1124 if (st2.countTokens() > 1)
1126 // This is the chain
1127 tmp2.add(st2.nextToken());
1128 seqstring = st2.nextToken();
1130 tmp.add(matcher == null
1131 ? (Sequence) af.getViewport().getAlignment()
1132 .findName(seqstring)
1133 : matcher.findIdMatch(seqstring));
1136 seqs = tmp.toArray(new SequenceI[tmp.size()]);
1137 if (tmp2.size() == tmp.size())
1139 chains = tmp2.toArray(new String[tmp2.size()]);
1144 DataSourceType protocol = resolveFileProtocol(ret);
1145 // TODO check JAL-357 for files in a jar (CLASSLOADER)
1146 pdb.setFile(ret[0]);
1150 for (int i = 0; i < seqs.length; i++)
1152 if (seqs[i] != null)
1154 ((Sequence) seqs[i]).addPDBId(pdb);
1155 StructureSelectionManager
1156 .getStructureSelectionManager(
1157 (StructureSelectionManagerProvider) this)
1158 .registerPDBEntry(pdb);
1164 // this may not really be a problem but we give a warning
1167 "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "
1175 // pdbs.add(new Object[] { pdb, seqs, chains, protocol });
1179 newStructureView(af, pdb, seqs, chains, protocol);
1185 } while (param != null || pdbFileCount < 10);
1187 // if (doAlign && pdbs.size() > 0)
1189 // SequenceI[][] seqs = new SequenceI[pdbs.size()][];
1190 // PDBEntry[] pdb = new PDBEntry[pdbs.size()];
1191 // String[][] chains = new String[pdbs.size()][];
1192 // String[] protocols = new String[pdbs.size()];
1193 // for (int pdbsi = 0, pdbsiSize = pdbs
1194 // .size(); pdbsi < pdbsiSize; pdbsi++)
1196 // Object[] o = pdbs.get(pdbsi);
1197 // pdb[pdbsi] = (PDBEntry) o[0];
1198 // seqs[pdbsi] = (SequenceI[]) o[1];
1199 // chains[pdbsi] = (String[]) o[2];
1200 // protocols[pdbsi] = (String) o[3];
1202 //// alignedStructureView(pdb, seqs, chains, protocols);
1209 * Load a score file if specified by parameter. Returns true if file was
1210 * loaded, else false.
1212 * @param loaderFrame
1214 protected boolean loadScoreFile()
1216 boolean result = false;
1217 String sScoreFile = (String) getAppletParameter("scoreFile", true);
1218 if (sScoreFile != null && !"".equals(sScoreFile))
1225 "Attempting to load T-COFFEE score file from the scoreFile parameter");
1227 result = loadScoreFile(sScoreFile);
1231 "Failed to parse T-COFFEE parameter as a valid score file ('"
1232 + sScoreFile + "')");
1234 } catch (Exception e)
1236 System.err.printf("Cannot read score file: '%s'. Cause: %s \n",
1237 sScoreFile, e.getMessage());
1244 * Load a tree for the alignment if specified by parameter. Returns true if a
1245 * tree was loaded, else false.
1249 protected boolean loadTree(AlignFrame af)
1251 boolean result = false;
1252 String treeFile = (String) getAppletParameter("tree", true);
1253 if (treeFile == null)
1255 treeFile = (String) getAppletParameter("treefile", true);
1258 if (treeFile != null)
1263 NewickFile fin = new NewickFile(treeFile, resolveFileProtocol(ret));
1266 if (fin.getTree() != null)
1268 loadTree(af, fin, ret[0]);
1272 System.out.println("Successfully imported tree.");
1280 "Tree parameter did not resolve to a valid tree.");
1283 } catch (Exception ex)
1285 ex.printStackTrace();
1292 * @j2sAlias openPcaPanel
1294 * public static method for JalviewJS API to open a PCAPanel without
1295 * necessarily using a dialog.
1299 * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
1300 * if number of sequences selected is inappropriate
1303 public Object openPcaPanel(AlignFrame af, String modelName)
1307 af = Jalview.getCurrentAlignFrame();
1309 return CalculationChooser.openPcaPanel(af, modelName, null);
1313 * @j2sAlias openTreePanel
1315 * Open a new Tree panel on the desktop statically. Params are standard (not
1316 * set by Groovy). No dialog is opened.
1321 * @return null, or the string "label.you_need_at_least_n_sequences" if number
1322 * of sequences selected is inappropriate
1325 public Object openTreePanel(AlignFrame af, String treeType,
1330 af = Jalview.getCurrentAlignFrame();
1332 return CalculationChooser.openTreePanel(af, treeType, modelName, null);
1337 public String orderBy(String[] ids, String undoName)
1339 return orderAlignmentBy(null, ids, undoName);
1343 public String orderAlignmentBy(AlignFrame alf, String[] ids,
1347 alf = Jalview.getCurrentAlignFrame();
1348 SequenceI[] sqs = null;
1349 if (ids != null && ids.length > 0)
1351 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
1352 alf.getViewport().getAlignment().getSequencesArray());
1354 sqs = new SequenceI[ids.length];
1355 for (int i = 0; i < ids.length; i++)
1357 if (ids[i].trim().length() == 0)
1361 SequenceI sq = matcher.findIdMatch(ids[i]);
1369 SequenceI[] sqq = new SequenceI[s];
1370 System.arraycopy(sqs, 0, sqq, 0, s);
1383 final AlignmentOrder aorder = new AlignmentOrder(sqs);
1385 if (undoName != null && undoName.trim().length() == 0)
1389 final String _undoName = undoName;
1390 // TODO: deal with synchronization here: cannot raise any events until after
1391 // this has returned.
1392 return alf.sortBy(aorder, _undoName) ? "true" : "";
1396 * Allow an outside entity to initiate the second half of argument parsing
1400 * @return null is good
1403 public Object parseArguments(String[] args)
1408 jalview.parseArguments(new ArgsParser(args), false);
1410 } catch (Throwable t)
1417 public void removeSelectionListener(AlignFrame af, String listener)
1420 List<SelectionListener> listeners = Desktop
1421 .getStructureSelectionManager().getListeners();
1422 for (int i = listeners.size(); --i >= 0;)
1424 SelectionListener l = listeners.get(i);
1425 if (l instanceof JsSelectionListener
1426 && ((JsSelectionListener) l).isFor(af, listener))
1428 listeners.remove(i);
1435 public void scrollViewToColumnIn(final AlignFrame alf,
1436 final String leftHandColumn)
1438 java.awt.EventQueue.invokeLater(new Runnable()
1446 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1448 Integer.valueOf(leftHandColumn).intValue());
1450 } catch (Exception ex)
1453 "Couldn't parse integer arguments (leftHandColumn='"
1454 + leftHandColumn + "')");
1455 ex.printStackTrace();
1463 public void scrollViewToIn(final AlignFrame alf, final String topRow,
1464 final String leftHandColumn)
1467 java.awt.EventQueue.invokeLater(new Runnable()
1474 (alf == null ? Jalview.getCurrentAlignFrame() : alf).scrollTo(
1475 Integer.valueOf(topRow).intValue(),
1476 Integer.valueOf(leftHandColumn).intValue());
1478 } catch (Exception ex)
1480 System.err.println("Couldn't parse integer arguments (topRow='"
1481 + topRow + "' and leftHandColumn='" + leftHandColumn
1483 ex.printStackTrace();
1490 public void scrollViewToRowIn(final AlignFrame alf, final String topRow)
1494 java.awt.EventQueue.invokeLater(new Runnable()
1501 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1502 .scrollToRow(Integer.valueOf(topRow).intValue());
1504 } catch (Exception ex)
1506 System.err.println("Couldn't parse integer arguments (topRow='"
1508 ex.printStackTrace();
1516 public void select(String sequenceIds, String columns)
1518 selectIn(Jalview.getCurrentAlignFrame(), sequenceIds, columns, null);
1522 public void select(String sequenceIds, String columns, String sep)
1524 selectIn(null, sequenceIds, columns, sep);
1528 // public AlignFrame newView()
1530 // return newViewFrom(null, null);
1534 // public AlignFrame newView(String name)
1536 // return newViewFrom(null, name);
1540 // public AlignFrame newViewFrom(AlignFrame alf)
1542 // return newViewFrom(alf, null);
1546 // public AlignFrame newViewFrom(AlignFrame alf, String name)
1550 // alf = Jalview.getCurrentAlignFrame();
1552 // return appLoader.newViewFrom(alf, name);
1556 public void selectIn(AlignFrame alf, String sequenceIds, String columns)
1558 selectIn(alf, sequenceIds, columns, null);
1562 public void selectIn(AlignFrame af, String sequenceIds, String columns,
1565 AlignFrame alf = (af == null ? Jalview.getCurrentAlignFrame() : af);
1567 if (sep == null || sep.length() == 0)
1575 System.err.println("Selecting region using separator string '"
1580 String[] ids = separatorListToArray(sequenceIds, sep);
1581 String[] cols = separatorListToArray(columns, sep);
1582 final SequenceGroup sel = new SequenceGroup();
1583 final ColumnSelection csel = new ColumnSelection();
1584 AlignmentI al = alf.getViewport().getAlignment();
1585 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
1586 alf.getViewport().getAlignment().getSequencesArray());
1587 int start = 0, end = al.getWidth(), alw = al.getWidth();
1588 boolean seqsfound = true;
1589 if (ids != null && ids.length > 0)
1592 for (int i = 0; i < ids.length; i++)
1594 if (ids[i].trim().length() == 0)
1598 SequenceI sq = matcher.findIdMatch(ids[i]);
1602 sel.addSequence(sq, false);
1606 boolean inseqpos = false;
1607 if (cols != null && cols.length > 0)
1609 boolean seset = false;
1610 for (int i = 0; i < cols.length; i++)
1612 String cl = cols[i].trim();
1613 if (cl.length() == 0)
1618 if ((p = cl.indexOf("-")) > -1)
1620 int from = -1, to = -1;
1623 from = Integer.valueOf(cl.substring(0, p)).intValue();
1625 } catch (NumberFormatException ex)
1628 "ERROR: Couldn't parse first integer in range element column selection string '"
1629 + cl + "' - format is 'from-to'");
1634 to = Integer.valueOf(cl.substring(p + 1)).intValue();
1636 } catch (NumberFormatException ex)
1639 "ERROR: Couldn't parse second integer in range element column selection string '"
1640 + cl + "' - format is 'from-to'");
1643 if (from >= 0 && to >= 0)
1660 // comment to prevent range extension
1670 for (int r = from; r <= to; r++)
1672 if (r >= 0 && r < alw)
1679 System.err.println("Range '" + cl + "' deparsed as [" + from
1685 System.err.println("ERROR: Invalid Range '" + cl
1686 + "' deparsed as [" + from + "," + to + "]");
1694 r = Integer.valueOf(cl).intValue();
1696 } catch (NumberFormatException ex)
1698 if (cl.toLowerCase().equals("sequence"))
1700 // we are in the dataset sequence's coordinate frame.
1706 "ERROR: Couldn't parse integer from point selection element of column selection string '"
1711 if (r >= 0 && r <= alw)
1721 // comment to prevent range extension
1734 System.err.println("Point selection '" + cl
1735 + "' deparsed as [" + r + "]");
1740 System.err.println("ERROR: Invalid Point selection '" + cl
1741 + "' deparsed as [" + r + "]");
1748 // we only propagate the selection when it was the null selection, or the
1749 // given sequences were found in the alignment.
1750 if (inseqpos && sel.getSize() > 0)
1752 // assume first sequence provides reference frame ?
1753 SequenceI rs = sel.getSequenceAt(0);
1754 start = rs.findIndex(start);
1755 end = rs.findIndex(end);
1756 List<Integer> cs = new ArrayList<>(csel.getSelected());
1758 for (Integer selectedCol : cs)
1760 csel.addElement(rs.findIndex(selectedCol));
1763 sel.setStartRes(start);
1765 EventQueue.invokeLater(new Runnable()
1770 alf.select(sel, csel,
1771 alf.getCurrentView().getAlignment().getHiddenColumns());
1778 public void setFeatureGroupState(String[] groups, boolean state)
1780 setFeatureGroupState(null, groups, state);
1784 public void setFeatureGroupState(String groups, boolean state)
1785 { // JalviewLite API
1786 setFeatureGroupStateOn(null, groups, state);
1790 public void setFeatureGroupStateOn(final AlignFrame alf,
1791 final String groups, boolean state)
1793 setFeatureGroupState(alf, separatorListToArray(groups, separator), state);
1794 // java.awt.EventQueue.invokeLater(new Runnable()
1797 // public void run()
1799 // (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1800 // .setFeatureGroupState(
1801 // separatorListToArray(groups, separator), state);
1806 public void setFeatureGroupState(AlignFrame af, String[] groups, boolean state) {
1807 (af == null ? Jalview.getCurrentAlignFrame() : af).setFeatureGroupState(groups, state);
1812 public void setSelectionListener(AlignFrame af, String listener)
1814 Desktop.getStructureSelectionManager()
1815 .addSelectionListener(new JsSelectionListener(af, listener));
1819 public void setSelectionListener(String listener)
1821 Desktop.getStructureSelectionManager()
1822 .addSelectionListener(new JsSelectionListener(null, listener));
1826 public void showOverview()
1828 Jalview.getCurrentAlignFrame().overviewMenuItem_actionPerformed(null);
1832 * Allowing for a JavaScript function here.
1834 public void callInitCallback()
1836 Object initjscallback = getAppletParameter("oninit", false);
1837 if (initjscallback != null)
1841 doSendCallback(initjscallback, new Object[0]);
1842 } catch (Exception e)
1844 System.err.println("Exception when executing _oninit callback '"
1845 + initjscallback + "'.");
1846 e.printStackTrace();
1852 * Pass the provided array prepended with Jalview.this
1854 * Appropriated from org.jmol.appletjs.Jmol
1857 * a window function or "alert"
1859 * @return String return from the callback method.
1861 public String doSendCallback(Object callback, Object[] data)
1863 Jalview me = jalview;
1865 if (me != null && callback != null)
1872 * if (callback == "alert") { alert(data[0]); return ""; } var
1873 * o; if (typeof callback == "function") { o = callback; } else
1874 * { if (!callback)return; var tokens = callback.split("."); o
1875 * = window[tokens[0]]; for (var i = 1; i < tokens.length; i++)
1876 * o = o[tokens[i]]; } var a = [me]; for (var i = 0; i <
1877 * data.length; i++) a.push(data[i] ? data[i].booleanValue &&
1878 * (data[i] = data[i].booleanValue()) : data[i]); return
1879 * o.apply(null,a) } catch (e) { System.out.println(callback +
1880 * " failed " + e); }
1886 private DataSourceType resolveFileProtocol(String[] retPath)
1888 String path = retPath[0];
1892 if (path.startsWith("PASTE"))
1894 retPath[0] = path.substring(5);
1895 return DataSourceType.PASTE;
1901 if (path.indexOf("://") >= 0)
1903 return DataSourceType.URL;
1907 * try relative to document root
1909 URL documentBase = getDocumentBase();
1910 String withDocBase = resolveUrlForLocalOrAbsolute(path, documentBase);
1911 if (HttpUtils.isValidUrl(withDocBase))
1915 // System.err.println("Prepended document base '" + documentBase
1916 // + "' to make: '" + withDocBase + "'");
1918 retPath[0] = withDocBase;
1919 return DataSourceType.URL;
1923 * try relative to codebase (if different to document base)
1925 URL codeBase = getCodeBase();
1926 String withCodeBase = resolveUrlForLocalOrAbsolute(path, codeBase);
1927 if (!withCodeBase.equals(withDocBase)
1928 && HttpUtils.isValidUrl(withCodeBase))
1932 // System.err.println("Prepended codebase '" + codeBase
1933 // + "' to make: '" + withCodeBase + "'");
1935 retPath[0] = withCodeBase;
1936 return DataSourceType.URL;
1940 * try locating by classloader; try this last so files in the directory
1941 * are resolved using document base
1943 if (inArchive(getClass(), path))
1945 return DataSourceType.CLASSLOADER;
1951 * Discovers whether the given file is in the Applet Archive
1957 private static boolean inArchive(Class<?> c, String f)
1959 // This might throw a security exception in certain browsers
1960 // Netscape Communicator for instance.
1963 boolean rtn = (c.getResourceAsStream("/" + f) != null);
1965 } catch (Exception ex)
1967 System.out.println("Exception checking resources: " + f + " " + ex);
1973 * form a complete URL given a path to a resource and a reference location on
1977 * - an absolute path on the same server as localref or a document
1978 * located relative to localref
1980 * - a URL on the same server as url
1981 * @return a complete URL for the resource located by url
1983 public static String resolveUrlForLocalOrAbsolute(String targetPath,
1986 String resolvedPath = "";
1987 if (targetPath.startsWith("/"))
1989 String codebase = localref.toString();
1990 String localfile = localref.getFile();
1991 resolvedPath = codebase.substring(0,
1992 codebase.length() - localfile.length()) + targetPath;
1993 return resolvedPath;
1997 * get URL path and strip off any trailing file e.g.
1998 * www.jalview.org/examples/index.html#applets?a=b is trimmed to
1999 * www.jalview.org/examples/
2001 String urlPath = localref.toString();
2002 String directoryPath = urlPath;
2003 int lastSeparator = directoryPath.lastIndexOf("/");
2004 if (lastSeparator > 0)
2006 directoryPath = directoryPath.substring(0, lastSeparator + 1);
2009 if (targetPath.startsWith("/"))
2012 * construct absolute URL to a file on the server - this is not allowed?
2014 // String localfile = localref.getFile();
2015 // resolvedPath = urlPath.substring(0,
2016 // urlPath.length() - localfile.length())
2018 resolvedPath = directoryPath + targetPath.substring(1);
2022 resolvedPath = directoryPath + targetPath;
2026 // System.err.println(
2027 // "resolveUrlForLocalOrAbsolute returning " + resolvedPath);
2029 return resolvedPath;
2033 * parse the string into a list
2037 * @return elements separated by separator
2039 public static String[] separatorListToArray(String list, String separator)
2041 // TODO use StringUtils version (slightly different...)
2042 int seplen = separator.length();
2043 if (list == null || list.equals("") || list.equals(separator))
2047 Vector<String> jv = new Vector<>();
2049 while ((pos = list.indexOf(separator, cp)) > cp)
2051 jv.addElement(list.substring(cp, pos));
2054 if (cp < list.length())
2056 String c = list.substring(cp);
2057 if (!c.equals(separator))
2064 String[] v = new String[jv.size()];
2065 for (int i = 0; i < v.length; i++)
2067 v[i] = jv.elementAt(i);
2069 jv.removeAllElements();
2075 public class JsSelectionListener
2076 implements jalview.structure.SelectionListener
2083 public JsSelectionListener(AlignFrame af, String listener)
2086 _listener = listener;
2090 public void selection(SequenceGroup seqsel, ColumnSelection colsel,
2091 HiddenColumns hidden, SelectionSource source)
2093 // System.err.println("Testing selection event relay to
2094 // jsfunction:"+_listener);
2096 AlignFrame src = _af;
2099 if (source instanceof AlignViewport
2100 && Jalview.getCurrentAlignFrame().getViewport() == source)
2102 src = Jalview.getCurrentAlignFrame();
2107 String[] seqs = new String[] {};
2108 String[] cols = new String[] {};
2109 int strt = 0, end = (src == null) ? -1
2110 : src.alignPanel.av.getAlignment().getWidth();
2111 if (seqsel != null && seqsel.getSize() > 0)
2113 seqs = new String[seqsel.getSize()];
2114 for (int i = 0; i < seqs.length; i++)
2116 seqs[i] = seqsel.getSequenceAt(i).getName();
2118 if (strt < seqsel.getStartRes())
2120 strt = seqsel.getStartRes();
2122 if (end == -1 || end > seqsel.getEndRes())
2124 end = seqsel.getEndRes();
2127 if (colsel != null && !colsel.isEmpty())
2131 end = colsel.getMax() + 1;
2133 cols = new String[colsel.getSelected().size()];
2134 for (int i = 0; i < cols.length; i++)
2136 cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
2141 if (seqsel != null && seqsel.getSize() > 0)
2143 // send a valid range, otherwise we send the empty selection
2144 cols = new String[1];
2145 cols[0] = "" + (1 + strt) + "-" + (1 + end);
2151 doSendCallback(_listener,
2153 { src, setid, seqs, cols });
2156 public boolean isFor(AlignFrame af, String listener)
2158 return _af == af && _listener.contentEquals(listener);
2164 public AlignViewportI getViewport()
2166 return Jalview.getCurrentAlignFrame().getViewport();