3 import java.awt.EventQueue;
4 //import java.applet.AppletContext;
5 import java.io.IOException;
7 import java.util.ArrayList;
8 import java.util.Hashtable;
10 import java.util.StringTokenizer;
11 import java.util.Vector;
13 import jalview.bin.ArgsParser;
14 import jalview.bin.Jalview;
15 import jalview.bin.JalviewJSApi;
16 import jalview.datamodel.Alignment;
17 import jalview.datamodel.AlignmentI;
18 import jalview.datamodel.AlignmentOrder;
19 import jalview.datamodel.ColumnSelection;
20 import jalview.datamodel.HiddenColumns;
21 import jalview.datamodel.PDBEntry;
22 import jalview.datamodel.Sequence;
23 import jalview.datamodel.SequenceGroup;
24 import jalview.datamodel.SequenceI;
25 import jalview.gui.AlignFrame;
26 import jalview.gui.AlignViewport;
27 import jalview.gui.AlignmentPanel;
28 import jalview.gui.CalculationChooser;
29 import jalview.gui.Desktop;
30 import jalview.gui.StructureViewer;
31 import jalview.io.AnnotationFile;
32 import jalview.io.AppletFormatAdapter;
33 import jalview.io.DataSourceType;
34 import jalview.io.FeaturesFile;
35 import jalview.io.FileFormat;
36 import jalview.io.FileFormatI;
37 import jalview.io.FileFormats;
38 import jalview.io.IdentifyFile;
39 import jalview.io.JPredFile;
40 import jalview.io.JnetAnnotationMaker;
41 import jalview.io.NewickFile;
42 import jalview.renderer.seqfeatures.FeatureRenderer;
43 import jalview.structure.SelectionListener;
44 import jalview.structure.SelectionSource;
45 import jalview.structure.StructureSelectionManager;
46 import jalview.structure.VamsasSource;
47 import jalview.util.HttpUtils;
48 import jalview.util.MessageManager;
49 import jalview.util.Platform;
51 //import netscape.javascript.JSObject;
54 * Basically the JalviewLite application, but without JalviewLite
59 public class JalviewJSApp implements JalviewJSApi
61 private ArgsParser aparser;
63 private boolean debug;
65 private String[] ret = new String[1];
67 private String separator = "\u00AC"; // JalviewLite note: the default used to
68 // be '|', but many sequence IDS include
72 public JalviewJSApp(ArgsParser aparser)
74 this.aparser = aparser;
75 Platform.setAppClass(this);
79 public void load(AlignFrame af)
81 String sep = (String) getAppletParameter("separator", true);
90 throw new Error(MessageManager
91 .getString("error.invalid_separator_parameter"));
105 // These are methods that are in JalviewLite that various classes call
106 // but are not in JalviewLiteJsApi. Or, even if they are, other classes
108 // them to JalviewLite directly. Some may not be necessary, but they have
110 // be at least mentioned here, or the classes calling them should
112 // JalviewLite itself.
114 // private boolean alignPDBStructures; // From JalviewLite; not implemented
116 private Hashtable<String, Hashtable<String, String[]>> jsmessages;
118 private Hashtable<String, int[]> jshashes;
121 public String getParameter(String name)
123 return (String) getAppletParameter(name, true);
127 public Object getAppletParameter(String name, boolean asString)
129 return aparser.getAppletValue(name, null, asString);
133 * Get the applet-like code base even though this is an application.
137 public URL getCodeBase()
139 return Platform.getCodeBase();
143 * Get the applet-like document base even though this is an application.
147 public URL getDocumentBase()
149 return Platform.getDocumentBase();
153 public Object getFrameForSource(VamsasSource source)
158 if (source instanceof jalview.gui.AlignViewport
159 && source == (af = Jalview.getCurrentAlignFrame())
162 // should be valid if it just generated an event!
165 // TODO: ensure that if '_af' is specified along with a handler
166 // function, then only events from that alignFrame are sent to that
173 public Hashtable<String, int[]> getJSHashes()
175 return (jshashes == null ? (jshashes = new Hashtable<>()) : jshashes);
179 public Hashtable<String, Hashtable<String, String[]>> getJSMessages()
181 return (jsmessages == null ? (jsmessages = new Hashtable<>())
186 public Object getJSObject()
188 return Jalview.getInstance();
192 public FeatureRenderer getNewFeatureRenderer(AlignViewportI vp)
194 return new jalview.gui.FeatureRenderer((AlignmentPanel) vp);
198 public Object[] getSelectionForListener(SequenceGroup seqsel,
199 ColumnSelection colsel, HiddenColumns hidden,
200 SelectionSource source, Object alignFrame)
202 return getSelectionForListener(null, seqsel, colsel, hidden, source,
212 public boolean loadScoreFile(String sScoreFile) throws IOException
214 return loadScoreFile(null, sScoreFile);
217 public boolean loadScoreFile(AlignFrame af, String sScoreFile) throws IOException
219 (af == null ? Jalview.getCurrentAlignFrame() : af).loadJalviewDataFile(sScoreFile, null, null, null);
223 public void loadTree(AlignFrame af, NewickFile nf, String treeFile) throws IOException
226 af = Jalview.getCurrentAlignFrame();
228 .setCurrentTree(af.showNewickTree(nf, treeFile).getTree());
232 public void newFeatureSettings()
235 "Jalview applet interface newFeatureSettings not implemented");
240 // public void setAlignPdbStructures(boolean defaultParameter)
242 // alignPDBStructures = true;
247 public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
248 String[] chains, DataSourceType protocol)
250 newStructureView(null, pdb, seqs, chains, protocol);
254 public void newStructureView(AlignFrame af, PDBEntry pdb,
255 SequenceI[] seqs, String[] chains, DataSourceType protocol)
257 StructureViewer.launchStructureViewer(
258 (af == null ? Jalview.getCurrentAlignFrame() : af).alignPanel,
269 public boolean parseFeaturesFile(String filename, DataSourceType protocol)
271 return parseFeaturesFile(null, filename, protocol);
274 public boolean parseFeaturesFile(AlignFrame af, String filename, DataSourceType protocol)
276 return af.parseFeaturesFile(filename, protocol);
280 public void setFeatureGroupState(String[] groups, boolean state)
282 setFeatureGroupState(null, groups, state);
285 public void setFeatureGroupState(AlignFrame af, String[] groups, boolean state) {
286 (af == null ? Jalview.getCurrentAlignFrame() : af).setFeatureGroupState(groups, state);
289 * annotations, jpredfile, jnetfile
294 public void updateForAnnotations()
296 updateForAnnotations(null);
299 public void updateForAnnotations(AlignFrame af)
301 (af == null ? Jalview.getCurrentAlignFrame() : af).updateForAnnotations();
305 public boolean addPdbFile(AlignFrame alf, String sequenceId,
306 String pdbEntryString, String pdbFile)
310 alf = Jalview.getCurrentAlignFrame();
312 SequenceI toaddpdb = alf.getViewport().getAlignment()
313 .findName(sequenceId);
314 boolean needtoadd = false;
315 if (toaddpdb != null)
317 Vector<PDBEntry> pdbe = toaddpdb.getAllPDBEntries();
318 PDBEntry pdbentry = null;
319 if (pdbe != null && pdbe.size() > 0)
321 for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)
323 pdbentry = pdbe.elementAt(pe);
324 if (!pdbentry.getId().equals(pdbEntryString)
325 && !pdbentry.getFile().equals(pdbFile))
335 if (pdbentry == null)
337 pdbentry = new PDBEntry();
338 pdbentry.setId(pdbEntryString);
339 pdbentry.setFile(pdbFile);
340 needtoadd = true; // add this new entry to sequence.
342 // resolve data source
343 // TODO: this code should be a refactored to an io package
344 DataSourceType protocol = AppletFormatAdapter.resolveProtocol(pdbFile,
346 if (protocol == null)
352 pdbentry.setProperty("protocol", protocol);
353 toaddpdb.addPDBId(pdbentry);
354 alf.alignPanel.getStructureSelectionManager()
355 .registerPDBEntry(pdbentry);
362 public String arrayToSeparatorList(String[] array)
364 return arrayToSeparatorList(array, separator);
368 * concatenate the list with separator
372 * @return concatenated string
374 public static String arrayToSeparatorList(String[] list, String separator)
376 // TODO use StringUtils version
377 StringBuffer v = new StringBuffer();
378 if (list != null && list.length > 0)
380 for (int i = 0, iSize = list.length; i < iSize; i++)
394 // .println("Returning '" + separator + "' separated List:\n");
395 // System.err.println(v);
401 // System.err.println(
402 // "Returning empty '" + separator + "' separated List\n");
404 return "" + separator;
408 public String getAlignment(String format)
410 return getAlignmentFrom(null, format, null);
414 public String getAlignment(String format, String suffix)
416 return getAlignmentFrom(Jalview.getCurrentAlignFrame(), format, suffix);
420 public String getAlignmentFrom(AlignFrame alf, String format)
422 return getAlignmentFrom(alf, format, null);
426 public String getAlignmentFrom(AlignFrame alf, String format,
433 alf = Jalview.getCurrentAlignFrame();
435 boolean seqlimits = (suffix == null
436 || suffix.equalsIgnoreCase("true"));
438 FileFormatI theFormat = FileFormats.getInstance().forName(format);
439 String reply = new AppletFormatAdapter().formatSequences(theFormat,
440 alf.getViewport().getAlignment(), seqlimits);
442 } catch (IllegalArgumentException ex)
444 ex.printStackTrace();
445 return "Error retrieving alignment, possibly invalid format specifier: "
451 public String getAlignmentOrder()
453 return getAlignmentFrom(Jalview.getCurrentAlignFrame(), null);
457 public String getAlignmentOrderFrom(AlignFrame alf)
459 return getAlignmentFrom(alf, null);
463 public String getAlignmentOrderFrom(AlignFrame alf, String sep)
467 alf = Jalview.getCurrentAlignFrame();
469 AlignmentI alorder = alf.getViewport().getAlignment();
470 String[] order = new String[alorder.getHeight()];
471 for (int i = 0; i < order.length; i++)
473 order[i] = alorder.getSequenceAt(i).getName();
475 return arrayToSeparatorList(order, sep);
479 public String getAnnotation()
481 return getAnnotationFrom(null);
485 public String getAnnotationFrom(AlignFrame alf)
489 alf = Jalview.getCurrentAlignFrame();
491 String annotation = new AnnotationFile()
492 .printAnnotationsForView(alf.getViewport());
497 public String getFeatureGroups()
499 return getFeatureGroupsOn(null);
503 public String getFeatureGroupsOfState(boolean visible)
505 return getFeatureGroupsOfStateOn(null, visible);
509 public String getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)
513 alf = Jalview.getCurrentAlignFrame();
515 return arrayToSeparatorList(alf.getFeatureGroupsOfState(visible));
519 public String getFeatureGroupsOn(AlignFrame alf)
523 alf = Jalview.getCurrentAlignFrame();
525 return arrayToSeparatorList(alf.getFeatureGroups());
529 public String getFeatures(String format)
531 return getFeaturesFrom(null, format);
535 * JavaScript interface to print the alignment frame
539 * "jalview" or "gff" with or without ";includeComplement" or
540 * ";includeNonpositional"; default with no ";" is
541 * ";includeNonpositional"
545 public String getFeaturesFrom(AlignFrame alf, String format)
549 alf = Jalview.getCurrentAlignFrame();
552 FeaturesFile formatter = new FeaturesFile();
553 format = format.toLowerCase();
554 if (format.indexOf(";") < 0)
555 format += ";includenonpositional";
556 boolean nonpos = format.indexOf(";includenonpositional") > 0;
557 boolean compl = format.indexOf(";includecomplement") >= 0;
558 if (format.startsWith("jalview"))
560 features = formatter.printJalviewFormat(
561 alf.getViewport().getAlignment().getSequencesArray(),
562 alf.alignPanel.getFeatureRenderer(), nonpos, compl);
566 features = formatter.printGffFormat(
567 alf.getViewport().getAlignment().getSequencesArray(),
568 alf.alignPanel.getFeatureRenderer(), nonpos, compl);
571 if (features == null)
580 public String getJsMessage(String messageclass, String viewId)
582 // TODO Auto-generated method stub
587 * read sequence1...sequenceN as a raw alignment
592 public String getPastedSequence(JalviewJSApp jalviewApp)
594 StringBuffer data = new StringBuffer("PASTE");
597 while ((file = (String) getAppletParameter("sequence" + i,
600 data.append(file.toString() + "\n");
603 if (data.length() > 5)
605 file = data.toString();
612 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences()
615 public String getSelectedSequences()
617 return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame());
622 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences(java.lang.String)
625 public String getSelectedSequences(String sep)
627 return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame(), sep);
631 public String getSelectedSequencesAsAlignment(String format,
634 return getSelectedSequencesAsAlignmentFrom(null, format, suffix);
638 public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
639 String format, String suffix)
644 alf = Jalview.getCurrentAlignFrame();
647 boolean seqlimits = (suffix == null || suffix.equalsIgnoreCase("true"));
650 AlignViewport vp = alf.getViewport();
651 FileFormatI theFormat = FileFormats.getInstance().forName(format);
652 if (vp.getSelectionGroup() != null)
654 // JBPNote: getSelectionAsNewSequence behaviour has changed - this
655 // method now returns a full copy of sequence data
656 // TODO consider using getSequenceSelection instead here
657 String reply = new AppletFormatAdapter().formatSequences(theFormat,
658 new Alignment(vp.getSelectionAsNewSequence()), seqlimits);
661 } catch (IllegalArgumentException ex)
663 ex.printStackTrace();
664 return "Error retrieving alignment, possibly invalid format specifier: "
672 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
676 public String getSelectedSequencesFrom(AlignFrame alf)
678 return getSelectedSequencesFrom(alf, null);
682 public String getSelectedSequencesFrom(AlignFrame alf, String sep)
686 alf = Jalview.getCurrentAlignFrame();
688 StringBuffer result = new StringBuffer("");
689 if (sep == null || sep.length() == 0)
691 sep = separator; // "+0x00AC;
693 AlignViewport v = alf.getViewport();
694 if (v.getSelectionGroup() != null)
696 SequenceI[] seqs = v.getSelectionGroup()
697 .getSequencesInOrder(v.getAlignment());
699 for (int i = 0; i < seqs.length; i++)
701 result.append(seqs[i].getName());
706 return result.toString();
709 public Object[] getSelectionForListener(AlignFrame alf,
710 SequenceGroup seqsel, ColumnSelection colsel,
711 HiddenColumns hidden, SelectionSource source, Object alignFrame)
715 alf = Jalview.getCurrentAlignFrame();
717 // System.err.println("Testing selection event relay to
718 // jsfunction:"+_listener);
720 AlignFrame src = (AlignFrame) alignFrame;
723 if (source instanceof AlignViewport && alf.getViewport() == source)
725 // should be valid if it just generated an event!
730 String[] seqs = new String[] {};
731 String[] cols = new String[] {};
732 int strt = 0, end = (src == null) ? -1
733 : src.alignPanel.av.getAlignment().getWidth();
734 if (seqsel != null && seqsel.getSize() > 0)
736 seqs = new String[seqsel.getSize()];
737 for (int i = 0; i < seqs.length; i++)
739 seqs[i] = seqsel.getSequenceAt(i).getName();
741 if (strt < seqsel.getStartRes())
743 strt = seqsel.getStartRes();
745 if (end == -1 || end > seqsel.getEndRes())
747 end = seqsel.getEndRes();
750 if (colsel != null && !colsel.isEmpty())
754 end = colsel.getMax() + 1;
756 cols = new String[colsel.getSelected().size()];
757 for (int i = 0; i < cols.length; i++)
759 cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
764 if (seqsel != null && seqsel.getSize() > 0)
766 // send a valid range, otherwise we send the empty selection
767 cols = new String[2];
768 cols[0] = "" + (1 + strt) + "-" + (1 + end);
771 return new Object[] { src, setid, arrayToSeparatorList(seqs),
772 arrayToSeparatorList(cols) };
776 public String getSeparator()
783 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
784 * .AlignFrame, java.lang.String)
787 public void highlight(String sequenceId, String position,
788 String alignedPosition)
790 highlightIn(null, sequenceId, position, alignedPosition);
794 public void highlightIn(AlignFrame alf, final String sequenceId,
795 final String position, final String alignedPosition)
799 alf = Jalview.getCurrentAlignFrame();
801 // TODO: could try to highlight in all alignments if alf==null
802 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
803 alf.getViewport().getAlignment().getSequencesArray());
804 final SequenceI sq = matcher.findIdMatch(sequenceId);
810 apos = Integer.valueOf(position).intValue();
812 } catch (NumberFormatException ex)
816 final int pos = apos;
817 // use vamsas listener to broadcast to all listeners in scope
818 if (alignedPosition != null && (alignedPosition.trim().length() == 0
819 || alignedPosition.toLowerCase().indexOf("false") > -1))
821 java.awt.EventQueue.invokeLater(new Runnable()
826 StructureSelectionManager
827 .getStructureSelectionManager(Desktop.getInstance())
828 .mouseOverVamsasSequence(sq, sq.findIndex(pos), null);
834 java.awt.EventQueue.invokeLater(new Runnable()
839 StructureSelectionManager
840 .getStructureSelectionManager(Desktop.getInstance())
841 .mouseOverVamsasSequence(sq, pos, null);
848 public AlignFrame loadAlignment(String text, int width, int height,
851 AlignmentI al = null;
855 FileFormatI format = new IdentifyFile().identify(text,
856 DataSourceType.PASTE);
857 al = new AppletFormatAdapter().readFile(text, DataSourceType.PASTE,
859 if (al.getHeight() > 0)
861 return new AlignFrame(al, width, height, title);
863 } catch (IOException ex)
865 ex.printStackTrace();
870 // public void setMouseoverListener(String listener)
872 // appLoader.setMouseoverListener(listener);
876 // public void setMouseoverListener(AlignFrame af, String listener)
882 public AlignFrame loadAlignment(String text, String title)
884 return loadAlignment(text, AlignFrame.DEFAULT_WIDTH,
885 AlignFrame.DEFAULT_HEIGHT, title);
889 public void loadAnnotation(String annotation)
891 loadAnnotationFrom(null, annotation);
895 public void loadAnnotationFrom(AlignFrame alf, String annotation)
899 alf = Jalview.getCurrentAlignFrame();
901 if (new AnnotationFile().annotateAlignmentView(alf.getViewport(),
902 annotation, DataSourceType.PASTE))
904 alf.alignPanel.fontChanged();
905 alf.alignPanel.setScrollValues(0, 0);
909 alf.parseFeaturesFile(annotation, DataSourceType.PASTE);
914 * Load annotations if specified by parameter. Returns true if loaded, else
921 protected boolean loadAnnotations(AlignFrame af)
923 boolean result = false;
924 String param = (String) getAppletParameter("annotations", true);
928 DataSourceType protocol = resolveFileProtocol(ret);
930 if (new AnnotationFile().annotateAlignmentView(af.getViewport(), param,
933 updateForAnnotations();
939 .println("Annotations were not added from annotation file '"
949 * Load features file and view settings as specified by parameters. Returns
950 * true if features were loaded, else false.
956 protected boolean loadFeatures(AlignFrame af)
958 boolean result = false;
959 // ///////////////////////////
960 // modify display of features
961 // we do this before any features have been loaded, ensuring any hidden
962 // groups are hidden when features first displayed
964 // hide specific groups
966 String param = (String) getAppletParameter("hidefeaturegroups", true);
969 setFeatureGroupState(af, separatorListToArray(param, separator), false);
970 // setFeatureGroupStateOn(newAlignFrame, param, false);
972 // show specific groups
973 param = (String) getAppletParameter("showfeaturegroups", true);
976 setFeatureGroupState(af, separatorListToArray(param, separator), true);
977 // setFeatureGroupStateOn(newAlignFrame, param, true);
979 // and now load features
980 param = (String) getAppletParameter("features", true);
984 DataSourceType protocol = resolveFileProtocol(ret);
986 result = parseFeaturesFile(af, ret[0], protocol);
989 param = (String) getAppletParameter("showFeatureSettings", true);
990 if (param != null && param.equalsIgnoreCase("true"))
992 newFeatureSettings();
998 public void loadFeatures(String features, boolean autoenabledisplay)
1000 loadFeaturesFrom(null, features, autoenabledisplay);
1004 public boolean loadFeaturesFrom(AlignFrame alf, String features,
1005 boolean autoenabledisplay)
1009 alf = Jalview.getCurrentAlignFrame();
1011 boolean ret = alf.parseFeaturesFile(features, DataSourceType.PASTE);
1016 if (autoenabledisplay)
1018 alf.getViewport().setShowSequenceFeatures(true);
1019 // this next was for a checkbox in JalviewLite
1020 // ((AlignFrame) alf).getViewport().sequenceFeatures.setState(true);
1026 * Load in a Jnetfile if specified by parameter. Returns true if loaded, else
1032 protected boolean loadJnetFile(AlignFrame af)
1034 boolean result = false;
1035 String param = (String) getAppletParameter("jnetfile", true);
1038 // jnet became jpred around 2016
1039 param = (String) getAppletParameter("jpredfile", true);
1046 DataSourceType protocol = resolveFileProtocol(ret);
1047 JPredFile predictions = new JPredFile(ret[0], protocol);
1048 JnetAnnotationMaker.add_annotation(predictions,
1049 af.getViewport().getAlignment(), 0, false);
1050 // false == do not add sequence profile from concise output
1051 af.getViewport().getAlignment().setupJPredAlignment();
1052 updateForAnnotations();
1054 } catch (Exception ex)
1056 ex.printStackTrace();
1063 * Load PDBFiles if any specified by parameter(s). Returns true if loaded,
1066 * @param loaderFrame
1069 protected boolean loadPdbFiles(AlignFrame af)
1071 boolean result = false;
1073 * <param name="alignpdbfiles" value="false/true"/> Undocumented for 2.6 -
1074 * related to JAL-434
1077 // not supported (as for JalviewLite)
1078 // boolean doAlign = false;//"true".equalsIgnoreCase("" +
1079 // getAppletParameter("alignpdbfiles", false));
1080 // setAlignPdbStructures(doAlign);
1082 * <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B
1085 * <param name="PDBfile2" value="1gaq.txt A=SEQA B=SEQB C=SEQB">
1087 * <param name="PDBfile3" value="1q0o Q45135_9MICO">
1090 // Accumulate pdbs here if they are heading for the same view (if
1091 // alignPdbStructures is true)
1092 // ArrayList<Object[]> pdbs = new ArrayList<>();
1093 // create a lazy matcher if we're asked to
1094 boolean relaxed = "true".equalsIgnoreCase(
1095 "" + getAppletParameter("relaxedidmatch", false));
1096 jalview.analysis.SequenceIdMatcher matcher = relaxed
1097 ? new jalview.analysis.SequenceIdMatcher(
1098 af.getViewport().getAlignment().getSequencesArray())
1101 int pdbFileCount = 0;
1105 if (pdbFileCount > 0)
1107 param = (String) getAppletParameter("PDBFILE" + pdbFileCount, true);
1111 param = (String) getAppletParameter("PDBFILE", true);
1116 PDBEntry pdb = new PDBEntry();
1119 SequenceI[] seqs = null;
1120 String[] chains = null;
1122 StringTokenizer st = new StringTokenizer(param, " ");
1124 if (st.countTokens() < 2)
1126 String sequence = (String) getAppletParameter("PDBSEQ", true);
1127 if (sequence != null)
1129 seqs = new SequenceI[] { matcher == null
1130 ? (Sequence) af.getViewport().getAlignment()
1132 : matcher.findIdMatch(sequence) };
1138 param = st.nextToken();
1139 List<SequenceI> tmp = new ArrayList<>();
1140 List<String> tmp2 = new ArrayList<>();
1142 while (st.hasMoreTokens())
1144 seqstring = st.nextToken();
1145 StringTokenizer st2 = new StringTokenizer(seqstring, "=");
1146 if (st2.countTokens() > 1)
1148 // This is the chain
1149 tmp2.add(st2.nextToken());
1150 seqstring = st2.nextToken();
1152 tmp.add(matcher == null
1153 ? (Sequence) af.getViewport().getAlignment()
1154 .findName(seqstring)
1155 : matcher.findIdMatch(seqstring));
1158 seqs = tmp.toArray(new SequenceI[tmp.size()]);
1159 if (tmp2.size() == tmp.size())
1161 chains = tmp2.toArray(new String[tmp2.size()]);
1166 DataSourceType protocol = resolveFileProtocol(ret);
1167 // TODO check JAL-357 for files in a jar (CLASSLOADER)
1168 pdb.setFile(ret[0]);
1172 for (int i = 0; i < seqs.length; i++)
1174 if (seqs[i] != null)
1176 ((Sequence) seqs[i]).addPDBId(pdb);
1177 StructureSelectionManager
1178 .getStructureSelectionManager(
1179 (StructureSelectionManagerProvider) this)
1180 .registerPDBEntry(pdb);
1186 // this may not really be a problem but we give a warning
1189 "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "
1197 // pdbs.add(new Object[] { pdb, seqs, chains, protocol });
1201 newStructureView(af, pdb, seqs, chains, protocol);
1207 } while (param != null || pdbFileCount < 10);
1209 // if (doAlign && pdbs.size() > 0)
1211 // SequenceI[][] seqs = new SequenceI[pdbs.size()][];
1212 // PDBEntry[] pdb = new PDBEntry[pdbs.size()];
1213 // String[][] chains = new String[pdbs.size()][];
1214 // String[] protocols = new String[pdbs.size()];
1215 // for (int pdbsi = 0, pdbsiSize = pdbs
1216 // .size(); pdbsi < pdbsiSize; pdbsi++)
1218 // Object[] o = pdbs.get(pdbsi);
1219 // pdb[pdbsi] = (PDBEntry) o[0];
1220 // seqs[pdbsi] = (SequenceI[]) o[1];
1221 // chains[pdbsi] = (String[]) o[2];
1222 // protocols[pdbsi] = (String) o[3];
1224 //// alignedStructureView(pdb, seqs, chains, protocols);
1231 * Load a score file if specified by parameter. Returns true if file was
1232 * loaded, else false.
1234 * @param loaderFrame
1236 protected boolean loadScoreFile()
1238 boolean result = false;
1239 String sScoreFile = (String) getAppletParameter("scoreFile", true);
1240 if (sScoreFile != null && !"".equals(sScoreFile))
1247 "Attempting to load T-COFFEE score file from the scoreFile parameter");
1249 result = loadScoreFile(sScoreFile);
1253 "Failed to parse T-COFFEE parameter as a valid score file ('"
1254 + sScoreFile + "')");
1256 } catch (Exception e)
1258 System.err.printf("Cannot read score file: '%s'. Cause: %s \n",
1259 sScoreFile, e.getMessage());
1266 * Load a tree for the alignment if specified by parameter. Returns true if a
1267 * tree was loaded, else false.
1271 protected boolean loadTree(AlignFrame af)
1273 boolean result = false;
1274 String treeFile = (String) getAppletParameter("tree", true);
1275 if (treeFile == null)
1277 treeFile = (String) getAppletParameter("treefile", true);
1280 if (treeFile != null)
1285 NewickFile fin = new NewickFile(treeFile, resolveFileProtocol(ret));
1288 if (fin.getTree() != null)
1290 loadTree(af, fin, ret[0]);
1294 System.out.println("Successfully imported tree.");
1302 "Tree parameter did not resolve to a valid tree.");
1305 } catch (Exception ex)
1307 ex.printStackTrace();
1314 * public static method for JalviewJS API to open a PCAPanel without
1315 * necessarily using a dialog.
1319 * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
1320 * if number of sequences selected is inappropriate
1323 public Object openPcaPanel(AlignFrame af, String modelName)
1327 af = Jalview.getCurrentAlignFrame();
1329 return CalculationChooser.openPcaPanel(af, modelName, null);
1333 * Open a new Tree panel on the desktop statically. Params are standard (not
1334 * set by Groovy). No dialog is opened.
1339 * @return null, or the string "label.you_need_at_least_n_sequences" if number
1340 * of sequences selected is inappropriate
1343 public Object openTreePanel(AlignFrame af, String treeType,
1348 af = Jalview.getCurrentAlignFrame();
1350 return CalculationChooser.openTreePanel(af, treeType, modelName, null);
1354 public String orderAlignmentBy(AlignFrame alf, String order,
1355 String undoName, String sep)
1357 if (sep == null || sep.length() == 0)
1361 String[] ids = separatorListToArray(order, sep);
1362 SequenceI[] sqs = null;
1363 if (ids != null && ids.length > 0)
1367 alf = Jalview.getCurrentAlignFrame();
1369 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
1370 alf.getViewport().getAlignment().getSequencesArray());
1372 sqs = new SequenceI[ids.length];
1373 for (int i = 0; i < ids.length; i++)
1375 if (ids[i].trim().length() == 0)
1379 SequenceI sq = matcher.findIdMatch(ids[i]);
1387 SequenceI[] sqq = new SequenceI[s];
1388 System.arraycopy(sqs, 0, sqq, 0, s);
1401 final AlignmentOrder aorder = new AlignmentOrder(sqs);
1403 if (undoName != null && undoName.trim().length() == 0)
1407 final String _undoName = undoName;
1408 // TODO: deal with synchronization here: cannot raise any events until after
1409 // this has returned.
1410 return alf.sortBy(aorder, _undoName) ? "true" : "";
1414 public String orderBy(String order, String undoName)
1416 return orderBy(order, undoName, null);
1420 public String orderBy(String order, String undoName, String sep)
1422 return orderAlignmentBy(Jalview.getCurrentAlignFrame(), order, undoName,
1427 * Allow an outside entity to initiate the second half of argument parsing
1431 * @return null is good
1434 public Object parseArguments(String[] args)
1439 Jalview.getInstance().parseArguments(new ArgsParser(args), false);
1441 } catch (Throwable t)
1448 public void removeSelectionListener(AlignFrame af, String listener)
1451 List<SelectionListener> listeners = Desktop
1452 .getStructureSelectionManager().getListeners();
1453 for (int i = listeners.size(); --i >= 0;)
1455 SelectionListener l = listeners.get(i);
1456 if (l instanceof JsSelectionListener
1457 && ((JsSelectionListener) l).isFor(af, listener))
1459 listeners.remove(i);
1466 public void scrollViewToColumnIn(final AlignFrame alf,
1467 final String leftHandColumn)
1469 java.awt.EventQueue.invokeLater(new Runnable()
1477 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1479 Integer.valueOf(leftHandColumn).intValue());
1481 } catch (Exception ex)
1484 "Couldn't parse integer arguments (leftHandColumn='"
1485 + leftHandColumn + "')");
1486 ex.printStackTrace();
1494 public void scrollViewToIn(final AlignFrame alf, final String topRow,
1495 final String leftHandColumn)
1498 java.awt.EventQueue.invokeLater(new Runnable()
1505 (alf == null ? Jalview.getCurrentAlignFrame() : alf).scrollTo(
1506 Integer.valueOf(topRow).intValue(),
1507 Integer.valueOf(leftHandColumn).intValue());
1509 } catch (Exception ex)
1511 System.err.println("Couldn't parse integer arguments (topRow='"
1512 + topRow + "' and leftHandColumn='" + leftHandColumn
1514 ex.printStackTrace();
1521 public void scrollViewToRowIn(final AlignFrame alf, final String topRow)
1525 java.awt.EventQueue.invokeLater(new Runnable()
1532 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1533 .scrollToRow(Integer.valueOf(topRow).intValue());
1535 } catch (Exception ex)
1537 System.err.println("Couldn't parse integer arguments (topRow='"
1539 ex.printStackTrace();
1547 public void select(String sequenceIds, String columns)
1549 selectIn(Jalview.getCurrentAlignFrame(), sequenceIds, columns, null);
1553 public void select(String sequenceIds, String columns, String sep)
1555 selectIn(null, sequenceIds, columns, sep);
1559 // public AlignFrame newView()
1561 // return newViewFrom(null, null);
1565 // public AlignFrame newView(String name)
1567 // return newViewFrom(null, name);
1571 // public AlignFrame newViewFrom(AlignFrame alf)
1573 // return newViewFrom(alf, null);
1577 // public AlignFrame newViewFrom(AlignFrame alf, String name)
1581 // alf = Jalview.getCurrentAlignFrame();
1583 // return appLoader.newViewFrom(alf, name);
1587 public void selectIn(AlignFrame alf, String sequenceIds, String columns)
1589 selectIn(alf, sequenceIds, columns, null);
1593 public void selectIn(AlignFrame af, String sequenceIds, String columns,
1596 AlignFrame alf = (af == null ? Jalview.getCurrentAlignFrame() : af);
1598 if (sep == null || sep.length() == 0)
1606 System.err.println("Selecting region using separator string '"
1611 String[] ids = separatorListToArray(sequenceIds, sep);
1612 String[] cols = separatorListToArray(columns, sep);
1613 final SequenceGroup sel = new SequenceGroup();
1614 final ColumnSelection csel = new ColumnSelection();
1615 AlignmentI al = alf.getViewport().getAlignment();
1616 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
1617 alf.getViewport().getAlignment().getSequencesArray());
1618 int start = 0, end = al.getWidth(), alw = al.getWidth();
1619 boolean seqsfound = true;
1620 if (ids != null && ids.length > 0)
1623 for (int i = 0; i < ids.length; i++)
1625 if (ids[i].trim().length() == 0)
1629 SequenceI sq = matcher.findIdMatch(ids[i]);
1633 sel.addSequence(sq, false);
1637 boolean inseqpos = false;
1638 if (cols != null && cols.length > 0)
1640 boolean seset = false;
1641 for (int i = 0; i < cols.length; i++)
1643 String cl = cols[i].trim();
1644 if (cl.length() == 0)
1649 if ((p = cl.indexOf("-")) > -1)
1651 int from = -1, to = -1;
1654 from = Integer.valueOf(cl.substring(0, p)).intValue();
1656 } catch (NumberFormatException ex)
1659 "ERROR: Couldn't parse first integer in range element column selection string '"
1660 + cl + "' - format is 'from-to'");
1665 to = Integer.valueOf(cl.substring(p + 1)).intValue();
1667 } catch (NumberFormatException ex)
1670 "ERROR: Couldn't parse second integer in range element column selection string '"
1671 + cl + "' - format is 'from-to'");
1674 if (from >= 0 && to >= 0)
1691 // comment to prevent range extension
1701 for (int r = from; r <= to; r++)
1703 if (r >= 0 && r < alw)
1710 System.err.println("Range '" + cl + "' deparsed as [" + from
1716 System.err.println("ERROR: Invalid Range '" + cl
1717 + "' deparsed as [" + from + "," + to + "]");
1725 r = Integer.valueOf(cl).intValue();
1727 } catch (NumberFormatException ex)
1729 if (cl.toLowerCase().equals("sequence"))
1731 // we are in the dataset sequence's coordinate frame.
1737 "ERROR: Couldn't parse integer from point selection element of column selection string '"
1742 if (r >= 0 && r <= alw)
1752 // comment to prevent range extension
1765 System.err.println("Point selection '" + cl
1766 + "' deparsed as [" + r + "]");
1771 System.err.println("ERROR: Invalid Point selection '" + cl
1772 + "' deparsed as [" + r + "]");
1779 // we only propagate the selection when it was the null selection, or the
1780 // given sequences were found in the alignment.
1781 if (inseqpos && sel.getSize() > 0)
1783 // assume first sequence provides reference frame ?
1784 SequenceI rs = sel.getSequenceAt(0);
1785 start = rs.findIndex(start);
1786 end = rs.findIndex(end);
1787 List<Integer> cs = new ArrayList<>(csel.getSelected());
1789 for (Integer selectedCol : cs)
1791 csel.addElement(rs.findIndex(selectedCol));
1794 sel.setStartRes(start);
1796 EventQueue.invokeLater(new Runnable()
1801 alf.select(sel, csel,
1802 alf.getCurrentView().getAlignment().getHiddenColumns());
1808 // public AlignFrame newViewFrom(AlignFrame alf, String name)
1810 // return (AlignFrame) alf.newView(name, true);
1814 public String[] separatorListToArray(String list)
1816 return separatorListToArray(list, separator);
1820 public void setFeatureGroupState(String groups, boolean state)
1821 { // JalviewLite API
1822 setFeatureGroupStateOn(null, groups, state);
1826 public void setFeatureGroupStateOn(final AlignFrame alf,
1827 final String groups, boolean state)
1830 java.awt.EventQueue.invokeLater(new Runnable()
1835 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1836 .setFeatureGroupState(
1837 separatorListToArray(groups, separator), state);
1843 public void setSelectionListener(AlignFrame af, String listener)
1845 Desktop.getStructureSelectionManager()
1846 .addSelectionListener(new JsSelectionListener(af, listener));
1850 public void setSelectionListener(String listener)
1852 Desktop.getStructureSelectionManager()
1853 .addSelectionListener(new JsSelectionListener(null, listener));
1857 public void setSeparator(String separator)
1859 this.separator = separator;
1863 public void showOverview()
1865 Jalview.getCurrentAlignFrame().overviewMenuItem_actionPerformed(null);
1869 * Allowing for a JavaScript function here.
1871 public void callInitCallback()
1873 Object initjscallback = getAppletParameter("oninit", false);
1874 if (initjscallback != null)
1878 doSendCallback(initjscallback, new Object[0]);
1879 } catch (Exception e)
1881 System.err.println("Exception when executing _oninit callback '"
1882 + initjscallback + "'.");
1883 e.printStackTrace();
1889 * Pass the provided array prepended with Jalview.this
1891 * Appropriated from org.jmol.appletjs.Jmol
1894 * a window function or "alert"
1896 * @return String return from the callback method.
1898 public String doSendCallback(Object callback, Object[] data)
1900 Jalview me = Jalview.getInstance();
1902 if (me != null && callback != null)
1909 * if (callback == "alert") { alert(data[0]); return ""; } var
1910 * o; if (typeof callback == "function") { o = callback; } else
1911 * { if (!callback)return; var tokens = callback.split("."); o
1912 * = window[tokens[0]]; for (var i = 1; i < tokens.length; i++)
1913 * o = o[tokens[i]]; } var a = [me]; for (var i = 0; i <
1914 * data.length; i++) a.push(data[i] ? data[i].booleanValue &&
1915 * (data[i] = data[i].booleanValue()) : data[i]); return
1916 * o.apply(null,a) } catch (e) { System.out.println(callback +
1917 * " failed " + e); }
1923 private DataSourceType resolveFileProtocol(String[] retPath)
1925 String path = retPath[0];
1929 if (path.startsWith("PASTE"))
1931 retPath[0] = path.substring(5);
1932 return DataSourceType.PASTE;
1938 if (path.indexOf("://") >= 0)
1940 return DataSourceType.URL;
1944 * try relative to document root
1946 URL documentBase = getDocumentBase();
1947 String withDocBase = resolveUrlForLocalOrAbsolute(path, documentBase);
1948 if (HttpUtils.isValidUrl(withDocBase))
1952 // System.err.println("Prepended document base '" + documentBase
1953 // + "' to make: '" + withDocBase + "'");
1955 retPath[0] = withDocBase;
1956 return DataSourceType.URL;
1960 * try relative to codebase (if different to document base)
1962 URL codeBase = getCodeBase();
1963 String withCodeBase = resolveUrlForLocalOrAbsolute(path, codeBase);
1964 if (!withCodeBase.equals(withDocBase)
1965 && HttpUtils.isValidUrl(withCodeBase))
1969 // System.err.println("Prepended codebase '" + codeBase
1970 // + "' to make: '" + withCodeBase + "'");
1972 retPath[0] = withCodeBase;
1973 return DataSourceType.URL;
1977 * try locating by classloader; try this last so files in the directory
1978 * are resolved using document base
1980 if (inArchive(getClass(), path))
1982 return DataSourceType.CLASSLOADER;
1988 * Discovers whether the given file is in the Applet Archive
1994 private static boolean inArchive(Class<?> c, String f)
1996 // This might throw a security exception in certain browsers
1997 // Netscape Communicator for instance.
2000 boolean rtn = (c.getResourceAsStream("/" + f) != null);
2002 } catch (Exception ex)
2004 System.out.println("Exception checking resources: " + f + " " + ex);
2010 * form a complete URL given a path to a resource and a reference location on
2014 * - an absolute path on the same server as localref or a document
2015 * located relative to localref
2017 * - a URL on the same server as url
2018 * @return a complete URL for the resource located by url
2020 public static String resolveUrlForLocalOrAbsolute(String targetPath,
2023 String resolvedPath = "";
2024 if (targetPath.startsWith("/"))
2026 String codebase = localref.toString();
2027 String localfile = localref.getFile();
2028 resolvedPath = codebase.substring(0,
2029 codebase.length() - localfile.length()) + targetPath;
2030 return resolvedPath;
2034 * get URL path and strip off any trailing file e.g.
2035 * www.jalview.org/examples/index.html#applets?a=b is trimmed to
2036 * www.jalview.org/examples/
2038 String urlPath = localref.toString();
2039 String directoryPath = urlPath;
2040 int lastSeparator = directoryPath.lastIndexOf("/");
2041 if (lastSeparator > 0)
2043 directoryPath = directoryPath.substring(0, lastSeparator + 1);
2046 if (targetPath.startsWith("/"))
2049 * construct absolute URL to a file on the server - this is not allowed?
2051 // String localfile = localref.getFile();
2052 // resolvedPath = urlPath.substring(0,
2053 // urlPath.length() - localfile.length())
2055 resolvedPath = directoryPath + targetPath.substring(1);
2059 resolvedPath = directoryPath + targetPath;
2063 // System.err.println(
2064 // "resolveUrlForLocalOrAbsolute returning " + resolvedPath);
2066 return resolvedPath;
2070 * parse the string into a list
2074 * @return elements separated by separator
2076 public static String[] separatorListToArray(String list, String separator)
2078 // TODO use StringUtils version (slightly different...)
2079 int seplen = separator.length();
2080 if (list == null || list.equals("") || list.equals(separator))
2084 Vector<String> jv = new Vector<>();
2086 while ((pos = list.indexOf(separator, cp)) > cp)
2088 jv.addElement(list.substring(cp, pos));
2091 if (cp < list.length())
2093 String c = list.substring(cp);
2094 if (!c.equals(separator))
2101 String[] v = new String[jv.size()];
2102 for (int i = 0; i < v.length; i++)
2104 v[i] = jv.elementAt(i);
2106 jv.removeAllElements();
2112 public class JsSelectionListener
2113 implements jalview.structure.SelectionListener
2120 public JsSelectionListener(AlignFrame af, String listener)
2123 _listener = listener;
2127 public void selection(SequenceGroup seqsel, ColumnSelection colsel,
2128 HiddenColumns hidden, SelectionSource source)
2130 // System.err.println("Testing selection event relay to
2131 // jsfunction:"+_listener);
2133 AlignFrame src = _af;
2136 if (source instanceof AlignViewport
2137 && Jalview.getCurrentAlignFrame().getViewport() == source)
2139 src = Jalview.getCurrentAlignFrame();
2144 String[] seqs = new String[] {};
2145 String[] cols = new String[] {};
2146 int strt = 0, end = (src == null) ? -1
2147 : src.alignPanel.av.getAlignment().getWidth();
2148 if (seqsel != null && seqsel.getSize() > 0)
2150 seqs = new String[seqsel.getSize()];
2151 for (int i = 0; i < seqs.length; i++)
2153 seqs[i] = seqsel.getSequenceAt(i).getName();
2155 if (strt < seqsel.getStartRes())
2157 strt = seqsel.getStartRes();
2159 if (end == -1 || end > seqsel.getEndRes())
2161 end = seqsel.getEndRes();
2164 if (colsel != null && !colsel.isEmpty())
2168 end = colsel.getMax() + 1;
2170 cols = new String[colsel.getSelected().size()];
2171 for (int i = 0; i < cols.length; i++)
2173 cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
2178 if (seqsel != null && seqsel.getSize() > 0)
2180 // send a valid range, otherwise we send the empty selection
2181 cols = new String[2];
2182 cols[0] = "" + (1 + strt) + "-" + (1 + end);
2188 doSendCallback(_listener,
2190 { src, setid, arrayToSeparatorList(seqs),
2191 arrayToSeparatorList(cols) });
2194 public boolean isFor(AlignFrame af, String listener)
2196 return _af == af && _listener.contentEquals(listener);
2202 public AlignViewportI getViewport()
2204 return Jalview.getCurrentAlignFrame().getViewport();