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 String j2sAppletID;
65 private boolean debug;
67 private String[] ret = new String[1];
69 private String separator = "\u00AC"; // JalviewLite note: the default used to
70 // be '|', but many sequence IDS include
73 public JalviewJSApp(ArgsParser aparser)
75 this.aparser = aparser;
76 this.j2sAppletID = (String) aparser.getAppletValue("j2sAppletID",
78 Platform.setAppClass(this);
82 public void load(AlignFrame af)
84 String sep = (String) getAppletParameter("separator", true);
93 throw new Error(MessageManager
94 .getString("error.invalid_separator_parameter"));
106 public String getAppID(String frameType)
108 return j2sAppletID + (frameType == null ? "" : "-" + frameType);
113 // These are methods that are in JalviewLite that various classes call
114 // but are not in JalviewLiteJsApi. Or, even if they are, other classes
116 // them to JalviewLite directly. Some may not be necessary, but they have
118 // be at least mentioned here, or the classes calling them should
120 // JalviewLite itself.
122 // private boolean alignPDBStructures; // From JalviewLite; not implemented
124 private Hashtable<String, Hashtable<String, String[]>> jsmessages;
126 private Hashtable<String, int[]> jshashes;
129 public String getParameter(String name)
131 return (String) getAppletParameter(name, true);
135 public Object getAppletParameter(String name, boolean asString)
137 return aparser.getAppletValue(name, null, asString);
141 * Get the applet-like code base even though this is an application.
145 public URL getCodeBase()
147 return Platform.getCodeBase();
151 * Get the applet-like document base even though this is an application.
155 public URL getDocumentBase()
157 return Platform.getDocumentBase();
161 public Object getFrameForSource(VamsasSource source)
166 if (source instanceof jalview.gui.AlignViewport
167 && source == (af = Jalview.getCurrentAlignFrame())
170 // should be valid if it just generated an event!
173 // TODO: ensure that if '_af' is specified along with a handler
174 // function, then only events from that alignFrame are sent to that
181 public Hashtable<String, int[]> getJSHashes()
183 return (jshashes == null ? (jshashes = new Hashtable<>()) : jshashes);
187 public Hashtable<String, Hashtable<String, String[]>> getJSMessages()
189 return (jsmessages == null ? (jsmessages = new Hashtable<>())
194 public Object getJSObject()
196 return Jalview.getInstance();
200 public FeatureRenderer getNewFeatureRenderer(AlignViewportI vp)
202 return new jalview.gui.FeatureRenderer((AlignmentPanel) vp);
206 public Object[] getSelectionForListener(SequenceGroup seqsel,
207 ColumnSelection colsel, HiddenColumns hidden,
208 SelectionSource source, Object alignFrame)
210 return getSelectionForListener(null, seqsel, colsel, hidden, source,
220 public boolean loadScoreFile(String sScoreFile) throws IOException
222 return loadScoreFile(null, sScoreFile);
225 public boolean loadScoreFile(AlignFrame af, String sScoreFile) throws IOException
227 (af == null ? Jalview.getCurrentAlignFrame() : af).loadJalviewDataFile(sScoreFile, null, null, null);
231 public void loadTree(AlignFrame af, NewickFile nf, String treeFile) throws IOException
234 af = Jalview.getCurrentAlignFrame();
236 .setCurrentTree(af.showNewickTree(nf, treeFile).getTree());
240 public void newFeatureSettings()
243 "Jalview applet interface newFeatureSettings not implemented");
248 // public void setAlignPdbStructures(boolean defaultParameter)
250 // alignPDBStructures = true;
255 public void newStructureView(PDBEntry pdb, SequenceI[] seqs,
256 String[] chains, DataSourceType protocol)
258 newStructureView(null, pdb, seqs, chains, protocol);
262 public void newStructureView(AlignFrame af, PDBEntry pdb,
263 SequenceI[] seqs, String[] chains, DataSourceType protocol)
265 StructureViewer.launchStructureViewer(
266 (af == null ? Jalview.getCurrentAlignFrame() : af).alignPanel,
277 public boolean parseFeaturesFile(String filename, DataSourceType protocol)
279 return parseFeaturesFile(null, filename, protocol);
282 public boolean parseFeaturesFile(AlignFrame af, String filename, DataSourceType protocol)
284 return af.parseFeaturesFile(filename, protocol);
288 public void setFeatureGroupState(String[] groups, boolean state)
290 setFeatureGroupState(null, groups, state);
293 public void setFeatureGroupState(AlignFrame af, String[] groups, boolean state) {
294 (af == null ? Jalview.getCurrentAlignFrame() : af).setFeatureGroupState(groups, state);
297 * annotations, jpredfile, jnetfile
302 public void updateForAnnotations()
304 updateForAnnotations(null);
307 public void updateForAnnotations(AlignFrame af)
309 (af == null ? Jalview.getCurrentAlignFrame() : af).updateForAnnotations();
313 public boolean addPdbFile(AlignFrame alf, String sequenceId,
314 String pdbEntryString, String pdbFile)
318 alf = Jalview.getCurrentAlignFrame();
320 SequenceI toaddpdb = alf.getViewport().getAlignment()
321 .findName(sequenceId);
322 boolean needtoadd = false;
323 if (toaddpdb != null)
325 Vector<PDBEntry> pdbe = toaddpdb.getAllPDBEntries();
326 PDBEntry pdbentry = null;
327 if (pdbe != null && pdbe.size() > 0)
329 for (int pe = 0, peSize = pdbe.size(); pe < peSize; pe++)
331 pdbentry = pdbe.elementAt(pe);
332 if (!pdbentry.getId().equals(pdbEntryString)
333 && !pdbentry.getFile().equals(pdbFile))
343 if (pdbentry == null)
345 pdbentry = new PDBEntry();
346 pdbentry.setId(pdbEntryString);
347 pdbentry.setFile(pdbFile);
348 needtoadd = true; // add this new entry to sequence.
350 // resolve data source
351 // TODO: this code should be a refactored to an io package
352 DataSourceType protocol = AppletFormatAdapter.resolveProtocol(pdbFile,
354 if (protocol == null)
360 pdbentry.setProperty("protocol", protocol);
361 toaddpdb.addPDBId(pdbentry);
362 alf.alignPanel.getStructureSelectionManager()
363 .registerPDBEntry(pdbentry);
370 public String arrayToSeparatorList(String[] array)
372 return arrayToSeparatorList(array, separator);
376 * concatenate the list with separator
380 * @return concatenated string
382 public static String arrayToSeparatorList(String[] list, String separator)
384 // TODO use StringUtils version
385 StringBuffer v = new StringBuffer();
386 if (list != null && list.length > 0)
388 for (int i = 0, iSize = list.length; i < iSize; i++)
402 // .println("Returning '" + separator + "' separated List:\n");
403 // System.err.println(v);
409 // System.err.println(
410 // "Returning empty '" + separator + "' separated List\n");
412 return "" + separator;
416 public String getAlignment(String format)
418 return getAlignmentFrom(null, format, null);
422 public String getAlignment(String format, String suffix)
424 return getAlignmentFrom(Jalview.getCurrentAlignFrame(), format, suffix);
428 public String getAlignmentFrom(AlignFrame alf, String format)
430 return getAlignmentFrom(alf, format, null);
434 public String getAlignmentFrom(AlignFrame alf, String format,
441 alf = Jalview.getCurrentAlignFrame();
443 boolean seqlimits = (suffix == null
444 || suffix.equalsIgnoreCase("true"));
446 FileFormatI theFormat = FileFormats.getInstance().forName(format);
447 String reply = new AppletFormatAdapter().formatSequences(theFormat,
448 alf.getViewport().getAlignment(), seqlimits);
450 } catch (IllegalArgumentException ex)
452 ex.printStackTrace();
453 return "Error retrieving alignment, possibly invalid format specifier: "
459 public String getAlignmentOrder()
461 return getAlignmentFrom(Jalview.getCurrentAlignFrame(), null);
465 public String getAlignmentOrderFrom(AlignFrame alf)
467 return getAlignmentFrom(alf, null);
471 public String getAlignmentOrderFrom(AlignFrame alf, String sep)
475 alf = Jalview.getCurrentAlignFrame();
477 AlignmentI alorder = alf.getViewport().getAlignment();
478 String[] order = new String[alorder.getHeight()];
479 for (int i = 0; i < order.length; i++)
481 order[i] = alorder.getSequenceAt(i).getName();
483 return arrayToSeparatorList(order, sep);
487 public String getAnnotation()
489 return getAnnotationFrom(null);
493 public String getAnnotationFrom(AlignFrame alf)
497 alf = Jalview.getCurrentAlignFrame();
499 String annotation = new AnnotationFile()
500 .printAnnotationsForView(alf.getViewport());
505 public String getFeatureGroups()
507 return getFeatureGroupsOn(null);
511 public String getFeatureGroupsOfState(boolean visible)
513 return getFeatureGroupsOfStateOn(null, visible);
517 public String getFeatureGroupsOfStateOn(AlignFrame alf, boolean visible)
521 alf = Jalview.getCurrentAlignFrame();
523 return arrayToSeparatorList(alf.getFeatureGroupsOfState(visible));
527 public String getFeatureGroupsOn(AlignFrame alf)
531 alf = Jalview.getCurrentAlignFrame();
533 return arrayToSeparatorList(alf.getFeatureGroups());
537 public String getFeatures(String format)
539 return getFeaturesFrom(null, format);
543 * JavaScript interface to print the alignment frame
547 * "jalview" or "gff" with or without ";includeComplement" or
548 * ";includeNonpositional"; default with no ";" is
549 * ";includeNonpositional"
553 public String getFeaturesFrom(AlignFrame alf, String format)
557 alf = Jalview.getCurrentAlignFrame();
560 FeaturesFile formatter = new FeaturesFile();
561 format = format.toLowerCase();
562 if (format.indexOf(";") < 0)
563 format += ";includenonpositional";
564 boolean nonpos = format.indexOf(";includenonpositional") > 0;
565 boolean compl = format.indexOf(";includecomplement") >= 0;
566 if (format.startsWith("jalview"))
568 features = formatter.printJalviewFormat(
569 alf.getViewport().getAlignment().getSequencesArray(),
570 alf.alignPanel.getFeatureRenderer(), nonpos, compl);
574 features = formatter.printGffFormat(
575 alf.getViewport().getAlignment().getSequencesArray(),
576 alf.alignPanel.getFeatureRenderer(), nonpos, compl);
579 if (features == null)
588 public String getJsMessage(String messageclass, String viewId)
590 // TODO Auto-generated method stub
595 * read sequence1...sequenceN as a raw alignment
600 public String getPastedSequence(JalviewJSApp jalviewApp)
602 StringBuffer data = new StringBuffer("PASTE");
605 while ((file = (String) getAppletParameter("sequence" + i,
608 data.append(file.toString() + "\n");
611 if (data.length() > 5)
613 file = data.toString();
620 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences()
623 public String getSelectedSequences()
625 return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame());
630 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequences(java.lang.String)
633 public String getSelectedSequences(String sep)
635 return getSelectedSequencesFrom(Jalview.getCurrentAlignFrame(), sep);
639 public String getSelectedSequencesAsAlignment(String format,
642 return getSelectedSequencesAsAlignmentFrom(null, format, suffix);
646 public String getSelectedSequencesAsAlignmentFrom(AlignFrame alf,
647 String format, String suffix)
652 alf = Jalview.getCurrentAlignFrame();
655 boolean seqlimits = (suffix == null || suffix.equalsIgnoreCase("true"));
658 AlignViewport vp = alf.getViewport();
659 FileFormatI theFormat = FileFormats.getInstance().forName(format);
660 if (vp.getSelectionGroup() != null)
662 // JBPNote: getSelectionAsNewSequence behaviour has changed - this
663 // method now returns a full copy of sequence data
664 // TODO consider using getSequenceSelection instead here
665 String reply = new AppletFormatAdapter().formatSequences(theFormat,
666 new Alignment(vp.getSelectionAsNewSequence()), seqlimits);
669 } catch (IllegalArgumentException ex)
671 ex.printStackTrace();
672 return "Error retrieving alignment, possibly invalid format specifier: "
680 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
684 public String getSelectedSequencesFrom(AlignFrame alf)
686 return getSelectedSequencesFrom(alf, null);
690 public String getSelectedSequencesFrom(AlignFrame alf, String sep)
694 alf = Jalview.getCurrentAlignFrame();
696 StringBuffer result = new StringBuffer("");
697 if (sep == null || sep.length() == 0)
699 sep = separator; // "+0x00AC;
701 AlignViewport v = alf.getViewport();
702 if (v.getSelectionGroup() != null)
704 SequenceI[] seqs = v.getSelectionGroup()
705 .getSequencesInOrder(v.getAlignment());
707 for (int i = 0; i < seqs.length; i++)
709 result.append(seqs[i].getName());
714 return result.toString();
717 public Object[] getSelectionForListener(AlignFrame alf,
718 SequenceGroup seqsel, ColumnSelection colsel,
719 HiddenColumns hidden, SelectionSource source, Object alignFrame)
723 alf = Jalview.getCurrentAlignFrame();
725 // System.err.println("Testing selection event relay to
726 // jsfunction:"+_listener);
728 AlignFrame src = (AlignFrame) alignFrame;
731 if (source instanceof AlignViewport && alf.getViewport() == source)
733 // should be valid if it just generated an event!
738 String[] seqs = new String[] {};
739 String[] cols = new String[] {};
740 int strt = 0, end = (src == null) ? -1
741 : src.alignPanel.av.getAlignment().getWidth();
742 if (seqsel != null && seqsel.getSize() > 0)
744 seqs = new String[seqsel.getSize()];
745 for (int i = 0; i < seqs.length; i++)
747 seqs[i] = seqsel.getSequenceAt(i).getName();
749 if (strt < seqsel.getStartRes())
751 strt = seqsel.getStartRes();
753 if (end == -1 || end > seqsel.getEndRes())
755 end = seqsel.getEndRes();
758 if (colsel != null && !colsel.isEmpty())
762 end = colsel.getMax() + 1;
764 cols = new String[colsel.getSelected().size()];
765 for (int i = 0; i < cols.length; i++)
767 cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
772 if (seqsel != null && seqsel.getSize() > 0)
774 // send a valid range, otherwise we send the empty selection
775 cols = new String[2];
776 cols[0] = "" + (1 + strt) + "-" + (1 + end);
779 return new Object[] { src, setid, arrayToSeparatorList(seqs),
780 arrayToSeparatorList(cols) };
784 public String getSeparator()
791 * @see jalview.appletgui.js.JalviewLiteJsApi#getSelectedSequencesFrom(jalview.appletgui
792 * .AlignFrame, java.lang.String)
795 public void highlight(String sequenceId, String position,
796 String alignedPosition)
798 highlightIn(null, sequenceId, position, alignedPosition);
802 public void highlightIn(AlignFrame alf, final String sequenceId,
803 final String position, final String alignedPosition)
807 alf = Jalview.getCurrentAlignFrame();
809 // TODO: could try to highlight in all alignments if alf==null
810 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
811 alf.getViewport().getAlignment().getSequencesArray());
812 final SequenceI sq = matcher.findIdMatch(sequenceId);
818 apos = Integer.valueOf(position).intValue();
820 } catch (NumberFormatException ex)
824 final int pos = apos;
825 // use vamsas listener to broadcast to all listeners in scope
826 if (alignedPosition != null && (alignedPosition.trim().length() == 0
827 || alignedPosition.toLowerCase().indexOf("false") > -1))
829 java.awt.EventQueue.invokeLater(new Runnable()
834 StructureSelectionManager
835 .getStructureSelectionManager(Desktop.getInstance())
836 .mouseOverVamsasSequence(sq, sq.findIndex(pos), null);
842 java.awt.EventQueue.invokeLater(new Runnable()
847 StructureSelectionManager
848 .getStructureSelectionManager(Desktop.getInstance())
849 .mouseOverVamsasSequence(sq, pos, null);
856 public AlignFrame loadAlignment(String text, int width, int height,
859 AlignmentI al = null;
863 FileFormatI format = new IdentifyFile().identify(text,
864 DataSourceType.PASTE);
865 al = new AppletFormatAdapter().readFile(text, DataSourceType.PASTE,
867 if (al.getHeight() > 0)
869 return new AlignFrame(al, width, height, title);
871 } catch (IOException ex)
873 ex.printStackTrace();
878 // public void setMouseoverListener(String listener)
880 // appLoader.setMouseoverListener(listener);
884 // public void setMouseoverListener(AlignFrame af, String listener)
890 public AlignFrame loadAlignment(String text, String title)
892 return loadAlignment(text, AlignFrame.DEFAULT_WIDTH,
893 AlignFrame.DEFAULT_HEIGHT, title);
897 public void loadAnnotation(String annotation)
899 loadAnnotationFrom(null, annotation);
903 public void loadAnnotationFrom(AlignFrame alf, String annotation)
907 alf = Jalview.getCurrentAlignFrame();
909 if (new AnnotationFile().annotateAlignmentView(alf.getViewport(),
910 annotation, DataSourceType.PASTE))
912 alf.alignPanel.fontChanged();
913 alf.alignPanel.setScrollValues(0, 0);
917 alf.parseFeaturesFile(annotation, DataSourceType.PASTE);
922 * Load annotations if specified by parameter. Returns true if loaded, else
929 protected boolean loadAnnotations(AlignFrame af)
931 boolean result = false;
932 String param = (String) getAppletParameter("annotations", true);
936 DataSourceType protocol = resolveFileProtocol(ret);
938 if (new AnnotationFile().annotateAlignmentView(af.getViewport(), param,
941 updateForAnnotations();
947 .println("Annotations were not added from annotation file '"
957 * Load features file and view settings as specified by parameters. Returns
958 * true if features were loaded, else false.
964 protected boolean loadFeatures(AlignFrame af)
966 boolean result = false;
967 // ///////////////////////////
968 // modify display of features
969 // we do this before any features have been loaded, ensuring any hidden
970 // groups are hidden when features first displayed
972 // hide specific groups
974 String param = (String) getAppletParameter("hidefeaturegroups", true);
977 setFeatureGroupState(af, separatorListToArray(param, separator), false);
978 // setFeatureGroupStateOn(newAlignFrame, param, false);
980 // show specific groups
981 param = (String) getAppletParameter("showfeaturegroups", true);
984 setFeatureGroupState(af, separatorListToArray(param, separator), true);
985 // setFeatureGroupStateOn(newAlignFrame, param, true);
987 // and now load features
988 param = (String) getAppletParameter("features", true);
992 DataSourceType protocol = resolveFileProtocol(ret);
994 result = parseFeaturesFile(af, ret[0], protocol);
997 param = (String) getAppletParameter("showFeatureSettings", true);
998 if (param != null && param.equalsIgnoreCase("true"))
1000 newFeatureSettings();
1006 public void loadFeatures(String features, boolean autoenabledisplay)
1008 loadFeaturesFrom(null, features, autoenabledisplay);
1012 public boolean loadFeaturesFrom(AlignFrame alf, String features,
1013 boolean autoenabledisplay)
1017 alf = Jalview.getCurrentAlignFrame();
1019 boolean ret = alf.parseFeaturesFile(features, DataSourceType.PASTE);
1024 if (autoenabledisplay)
1026 alf.getViewport().setShowSequenceFeatures(true);
1027 // this next was for a checkbox in JalviewLite
1028 // ((AlignFrame) alf).getViewport().sequenceFeatures.setState(true);
1034 * Load in a Jnetfile if specified by parameter. Returns true if loaded, else
1040 protected boolean loadJnetFile(AlignFrame af)
1042 boolean result = false;
1043 String param = (String) getAppletParameter("jnetfile", true);
1046 // jnet became jpred around 2016
1047 param = (String) getAppletParameter("jpredfile", true);
1054 DataSourceType protocol = resolveFileProtocol(ret);
1055 JPredFile predictions = new JPredFile(ret[0], protocol);
1056 JnetAnnotationMaker.add_annotation(predictions,
1057 af.getViewport().getAlignment(), 0, false);
1058 // false == do not add sequence profile from concise output
1059 af.getViewport().getAlignment().setupJPredAlignment();
1060 updateForAnnotations();
1062 } catch (Exception ex)
1064 ex.printStackTrace();
1071 * Load PDBFiles if any specified by parameter(s). Returns true if loaded,
1074 * @param loaderFrame
1077 protected boolean loadPdbFiles(AlignFrame af)
1079 boolean result = false;
1081 * <param name="alignpdbfiles" value="false/true"/> Undocumented for 2.6 -
1082 * related to JAL-434
1085 // not supported (as for JalviewLite)
1086 // boolean doAlign = false;//"true".equalsIgnoreCase("" +
1087 // getAppletParameter("alignpdbfiles", false));
1088 // setAlignPdbStructures(doAlign);
1090 * <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B
1093 * <param name="PDBfile2" value="1gaq.txt A=SEQA B=SEQB C=SEQB">
1095 * <param name="PDBfile3" value="1q0o Q45135_9MICO">
1098 // Accumulate pdbs here if they are heading for the same view (if
1099 // alignPdbStructures is true)
1100 // ArrayList<Object[]> pdbs = new ArrayList<>();
1101 // create a lazy matcher if we're asked to
1102 boolean relaxed = "true".equalsIgnoreCase(
1103 "" + getAppletParameter("relaxedidmatch", false));
1104 jalview.analysis.SequenceIdMatcher matcher = relaxed
1105 ? new jalview.analysis.SequenceIdMatcher(
1106 af.getViewport().getAlignment().getSequencesArray())
1109 int pdbFileCount = 0;
1113 if (pdbFileCount > 0)
1115 param = (String) getAppletParameter("PDBFILE" + pdbFileCount, true);
1119 param = (String) getAppletParameter("PDBFILE", true);
1124 PDBEntry pdb = new PDBEntry();
1127 SequenceI[] seqs = null;
1128 String[] chains = null;
1130 StringTokenizer st = new StringTokenizer(param, " ");
1132 if (st.countTokens() < 2)
1134 String sequence = (String) getAppletParameter("PDBSEQ", true);
1135 if (sequence != null)
1137 seqs = new SequenceI[] { matcher == null
1138 ? (Sequence) af.getViewport().getAlignment()
1140 : matcher.findIdMatch(sequence) };
1146 param = st.nextToken();
1147 List<SequenceI> tmp = new ArrayList<>();
1148 List<String> tmp2 = new ArrayList<>();
1150 while (st.hasMoreTokens())
1152 seqstring = st.nextToken();
1153 StringTokenizer st2 = new StringTokenizer(seqstring, "=");
1154 if (st2.countTokens() > 1)
1156 // This is the chain
1157 tmp2.add(st2.nextToken());
1158 seqstring = st2.nextToken();
1160 tmp.add(matcher == null
1161 ? (Sequence) af.getViewport().getAlignment()
1162 .findName(seqstring)
1163 : matcher.findIdMatch(seqstring));
1166 seqs = tmp.toArray(new SequenceI[tmp.size()]);
1167 if (tmp2.size() == tmp.size())
1169 chains = tmp2.toArray(new String[tmp2.size()]);
1174 DataSourceType protocol = resolveFileProtocol(ret);
1175 // TODO check JAL-357 for files in a jar (CLASSLOADER)
1176 pdb.setFile(ret[0]);
1180 for (int i = 0; i < seqs.length; i++)
1182 if (seqs[i] != null)
1184 ((Sequence) seqs[i]).addPDBId(pdb);
1185 StructureSelectionManager
1186 .getStructureSelectionManager(
1187 (StructureSelectionManagerProvider) this)
1188 .registerPDBEntry(pdb);
1194 // this may not really be a problem but we give a warning
1197 "Warning: Possible input parsing error: Null sequence for attachment of PDB (sequence "
1205 // pdbs.add(new Object[] { pdb, seqs, chains, protocol });
1209 newStructureView(af, pdb, seqs, chains, protocol);
1215 } while (param != null || pdbFileCount < 10);
1217 // if (doAlign && pdbs.size() > 0)
1219 // SequenceI[][] seqs = new SequenceI[pdbs.size()][];
1220 // PDBEntry[] pdb = new PDBEntry[pdbs.size()];
1221 // String[][] chains = new String[pdbs.size()][];
1222 // String[] protocols = new String[pdbs.size()];
1223 // for (int pdbsi = 0, pdbsiSize = pdbs
1224 // .size(); pdbsi < pdbsiSize; pdbsi++)
1226 // Object[] o = pdbs.get(pdbsi);
1227 // pdb[pdbsi] = (PDBEntry) o[0];
1228 // seqs[pdbsi] = (SequenceI[]) o[1];
1229 // chains[pdbsi] = (String[]) o[2];
1230 // protocols[pdbsi] = (String) o[3];
1232 //// alignedStructureView(pdb, seqs, chains, protocols);
1239 * Load a score file if specified by parameter. Returns true if file was
1240 * loaded, else false.
1242 * @param loaderFrame
1244 protected boolean loadScoreFile()
1246 boolean result = false;
1247 String sScoreFile = (String) getAppletParameter("scoreFile", true);
1248 if (sScoreFile != null && !"".equals(sScoreFile))
1255 "Attempting to load T-COFFEE score file from the scoreFile parameter");
1257 result = loadScoreFile(sScoreFile);
1261 "Failed to parse T-COFFEE parameter as a valid score file ('"
1262 + sScoreFile + "')");
1264 } catch (Exception e)
1266 System.err.printf("Cannot read score file: '%s'. Cause: %s \n",
1267 sScoreFile, e.getMessage());
1274 * Load a tree for the alignment if specified by parameter. Returns true if a
1275 * tree was loaded, else false.
1279 protected boolean loadTree(AlignFrame af)
1281 boolean result = false;
1282 String treeFile = (String) getAppletParameter("tree", true);
1283 if (treeFile == null)
1285 treeFile = (String) getAppletParameter("treefile", true);
1288 if (treeFile != null)
1293 NewickFile fin = new NewickFile(treeFile, resolveFileProtocol(ret));
1296 if (fin.getTree() != null)
1298 loadTree(af, fin, ret[0]);
1302 System.out.println("Successfully imported tree.");
1310 "Tree parameter did not resolve to a valid tree.");
1313 } catch (Exception ex)
1315 ex.printStackTrace();
1322 * public static method for JalviewJS API to open a PCAPanel without
1323 * necessarily using a dialog.
1327 * @return the PCAPanel, or the string "label.you_need_at_least_n_sequences"
1328 * if number of sequences selected is inappropriate
1331 public Object openPcaPanel(AlignFrame af, String modelName)
1335 af = Jalview.getCurrentAlignFrame();
1337 return CalculationChooser.openPcaPanel(af, modelName, null);
1341 * Open a new Tree panel on the desktop statically. Params are standard (not
1342 * set by Groovy). No dialog is opened.
1347 * @return null, or the string "label.you_need_at_least_n_sequences" if number
1348 * of sequences selected is inappropriate
1351 public Object openTreePanel(AlignFrame af, String treeType,
1356 af = Jalview.getCurrentAlignFrame();
1358 return CalculationChooser.openTreePanel(af, treeType, modelName, null);
1362 public String orderAlignmentBy(AlignFrame alf, String order,
1363 String undoName, String sep)
1365 if (sep == null || sep.length() == 0)
1369 String[] ids = separatorListToArray(order, sep);
1370 SequenceI[] sqs = null;
1371 if (ids != null && ids.length > 0)
1375 alf = Jalview.getCurrentAlignFrame();
1377 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
1378 alf.getViewport().getAlignment().getSequencesArray());
1380 sqs = new SequenceI[ids.length];
1381 for (int i = 0; i < ids.length; i++)
1383 if (ids[i].trim().length() == 0)
1387 SequenceI sq = matcher.findIdMatch(ids[i]);
1395 SequenceI[] sqq = new SequenceI[s];
1396 System.arraycopy(sqs, 0, sqq, 0, s);
1409 final AlignmentOrder aorder = new AlignmentOrder(sqs);
1411 if (undoName != null && undoName.trim().length() == 0)
1415 final String _undoName = undoName;
1416 // TODO: deal with synchronization here: cannot raise any events until after
1417 // this has returned.
1418 return alf.sortBy(aorder, _undoName) ? "true" : "";
1422 public String orderBy(String order, String undoName)
1424 return orderBy(order, undoName, null);
1428 public String orderBy(String order, String undoName, String sep)
1430 return orderAlignmentBy(Jalview.getCurrentAlignFrame(), order, undoName,
1435 * Allow an outside entity to initiate the second half of argument parsing
1439 * @return null is good
1442 public Object parseArguments(String[] args)
1447 Jalview.getInstance().parseArguments(new ArgsParser(args), false);
1449 } catch (Throwable t)
1456 public void removeSelectionListener(AlignFrame af, String listener)
1459 List<SelectionListener> listeners = Desktop
1460 .getStructureSelectionManager().getListeners();
1461 for (int i = listeners.size(); --i >= 0;)
1463 SelectionListener l = listeners.get(i);
1464 if (l instanceof JsSelectionListener
1465 && ((JsSelectionListener) l).isFor(af, listener))
1467 listeners.remove(i);
1474 public void scrollViewToColumnIn(final AlignFrame alf,
1475 final String leftHandColumn)
1477 java.awt.EventQueue.invokeLater(new Runnable()
1485 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1487 Integer.valueOf(leftHandColumn).intValue());
1489 } catch (Exception ex)
1492 "Couldn't parse integer arguments (leftHandColumn='"
1493 + leftHandColumn + "')");
1494 ex.printStackTrace();
1502 public void scrollViewToIn(final AlignFrame alf, final String topRow,
1503 final String leftHandColumn)
1506 java.awt.EventQueue.invokeLater(new Runnable()
1513 (alf == null ? Jalview.getCurrentAlignFrame() : alf).scrollTo(
1514 Integer.valueOf(topRow).intValue(),
1515 Integer.valueOf(leftHandColumn).intValue());
1517 } catch (Exception ex)
1519 System.err.println("Couldn't parse integer arguments (topRow='"
1520 + topRow + "' and leftHandColumn='" + leftHandColumn
1522 ex.printStackTrace();
1529 public void scrollViewToRowIn(final AlignFrame alf, final String topRow)
1533 java.awt.EventQueue.invokeLater(new Runnable()
1540 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1541 .scrollToRow(Integer.valueOf(topRow).intValue());
1543 } catch (Exception ex)
1545 System.err.println("Couldn't parse integer arguments (topRow='"
1547 ex.printStackTrace();
1555 public void select(String sequenceIds, String columns)
1557 selectIn(Jalview.getCurrentAlignFrame(), sequenceIds, columns, null);
1561 public void select(String sequenceIds, String columns, String sep)
1563 selectIn(null, sequenceIds, columns, sep);
1567 // public AlignFrame newView()
1569 // return newViewFrom(null, null);
1573 // public AlignFrame newView(String name)
1575 // return newViewFrom(null, name);
1579 // public AlignFrame newViewFrom(AlignFrame alf)
1581 // return newViewFrom(alf, null);
1585 // public AlignFrame newViewFrom(AlignFrame alf, String name)
1589 // alf = Jalview.getCurrentAlignFrame();
1591 // return appLoader.newViewFrom(alf, name);
1595 public void selectIn(AlignFrame alf, String sequenceIds, String columns)
1597 selectIn(alf, sequenceIds, columns, null);
1601 public void selectIn(AlignFrame af, String sequenceIds, String columns,
1604 AlignFrame alf = (af == null ? Jalview.getCurrentAlignFrame() : af);
1606 if (sep == null || sep.length() == 0)
1614 System.err.println("Selecting region using separator string '"
1619 String[] ids = separatorListToArray(sequenceIds, sep);
1620 String[] cols = separatorListToArray(columns, sep);
1621 final SequenceGroup sel = new SequenceGroup();
1622 final ColumnSelection csel = new ColumnSelection();
1623 AlignmentI al = alf.getViewport().getAlignment();
1624 jalview.analysis.SequenceIdMatcher matcher = new jalview.analysis.SequenceIdMatcher(
1625 alf.getViewport().getAlignment().getSequencesArray());
1626 int start = 0, end = al.getWidth(), alw = al.getWidth();
1627 boolean seqsfound = true;
1628 if (ids != null && ids.length > 0)
1631 for (int i = 0; i < ids.length; i++)
1633 if (ids[i].trim().length() == 0)
1637 SequenceI sq = matcher.findIdMatch(ids[i]);
1641 sel.addSequence(sq, false);
1645 boolean inseqpos = false;
1646 if (cols != null && cols.length > 0)
1648 boolean seset = false;
1649 for (int i = 0; i < cols.length; i++)
1651 String cl = cols[i].trim();
1652 if (cl.length() == 0)
1657 if ((p = cl.indexOf("-")) > -1)
1659 int from = -1, to = -1;
1662 from = Integer.valueOf(cl.substring(0, p)).intValue();
1664 } catch (NumberFormatException ex)
1667 "ERROR: Couldn't parse first integer in range element column selection string '"
1668 + cl + "' - format is 'from-to'");
1673 to = Integer.valueOf(cl.substring(p + 1)).intValue();
1675 } catch (NumberFormatException ex)
1678 "ERROR: Couldn't parse second integer in range element column selection string '"
1679 + cl + "' - format is 'from-to'");
1682 if (from >= 0 && to >= 0)
1699 // comment to prevent range extension
1709 for (int r = from; r <= to; r++)
1711 if (r >= 0 && r < alw)
1718 System.err.println("Range '" + cl + "' deparsed as [" + from
1724 System.err.println("ERROR: Invalid Range '" + cl
1725 + "' deparsed as [" + from + "," + to + "]");
1733 r = Integer.valueOf(cl).intValue();
1735 } catch (NumberFormatException ex)
1737 if (cl.toLowerCase().equals("sequence"))
1739 // we are in the dataset sequence's coordinate frame.
1745 "ERROR: Couldn't parse integer from point selection element of column selection string '"
1750 if (r >= 0 && r <= alw)
1760 // comment to prevent range extension
1773 System.err.println("Point selection '" + cl
1774 + "' deparsed as [" + r + "]");
1779 System.err.println("ERROR: Invalid Point selection '" + cl
1780 + "' deparsed as [" + r + "]");
1787 // we only propagate the selection when it was the null selection, or the
1788 // given sequences were found in the alignment.
1789 if (inseqpos && sel.getSize() > 0)
1791 // assume first sequence provides reference frame ?
1792 SequenceI rs = sel.getSequenceAt(0);
1793 start = rs.findIndex(start);
1794 end = rs.findIndex(end);
1795 List<Integer> cs = new ArrayList<>(csel.getSelected());
1797 for (Integer selectedCol : cs)
1799 csel.addElement(rs.findIndex(selectedCol));
1802 sel.setStartRes(start);
1804 EventQueue.invokeLater(new Runnable()
1809 alf.select(sel, csel,
1810 alf.getCurrentView().getAlignment().getHiddenColumns());
1816 // public AlignFrame newViewFrom(AlignFrame alf, String name)
1818 // return (AlignFrame) alf.newView(name, true);
1822 public String[] separatorListToArray(String list)
1824 return separatorListToArray(list, separator);
1828 public void setFeatureGroupState(String groups, boolean state)
1829 { // JalviewLite API
1830 setFeatureGroupStateOn(null, groups, state);
1834 public void setFeatureGroupStateOn(final AlignFrame alf,
1835 final String groups, boolean state)
1838 java.awt.EventQueue.invokeLater(new Runnable()
1843 (alf == null ? Jalview.getCurrentAlignFrame() : alf)
1844 .setFeatureGroupState(
1845 separatorListToArray(groups, separator), state);
1851 public void setSelectionListener(AlignFrame af, String listener)
1853 Desktop.getStructureSelectionManager()
1854 .addSelectionListener(new JsSelectionListener(af, listener));
1858 public void setSelectionListener(String listener)
1860 Desktop.getStructureSelectionManager()
1861 .addSelectionListener(new JsSelectionListener(null, listener));
1865 public void setSeparator(String separator)
1867 this.separator = separator;
1871 public void showOverview()
1873 Jalview.getCurrentAlignFrame().overviewMenuItem_actionPerformed(null);
1877 * Allowing for a JavaScript function here.
1879 public void callInitCallback()
1881 Object initjscallback = getAppletParameter("oninit", false);
1882 if (initjscallback != null)
1886 doSendCallback(initjscallback, new Object[0]);
1887 } catch (Exception e)
1889 System.err.println("Exception when executing _oninit callback '"
1890 + initjscallback + "'.");
1891 e.printStackTrace();
1897 * Pass the provided array prepended with Jalview.this
1899 * Appropriated from org.jmol.appletjs.Jmol
1902 * a window function or "alert"
1904 * @return String return from the callback method.
1906 public String doSendCallback(Object callback, Object[] data)
1908 Jalview me = Jalview.getInstance();
1910 if (me != null && callback != null)
1917 * if (callback == "alert") { alert(data[0]); return ""; } var
1918 * o; if (typeof callback == "function") { o = callback; } else
1919 * { if (!callback)return; var tokens = callback.split("."); o
1920 * = window[tokens[0]]; for (var i = 1; i < tokens.length; i++)
1921 * o = o[tokens[i]]; } var a = [me]; for (var i = 0; i <
1922 * data.length; i++) a.push(data[i] ? data[i].booleanValue &&
1923 * (data[i] = data[i].booleanValue()) : data[i]); return
1924 * o.apply(null,a) } catch (e) { System.out.println(callback +
1925 * " failed " + e); }
1931 private DataSourceType resolveFileProtocol(String[] retPath)
1933 String path = retPath[0];
1937 if (path.startsWith("PASTE"))
1939 retPath[0] = path.substring(5);
1940 return DataSourceType.PASTE;
1946 if (path.indexOf("://") >= 0)
1948 return DataSourceType.URL;
1952 * try relative to document root
1954 URL documentBase = getDocumentBase();
1955 String withDocBase = resolveUrlForLocalOrAbsolute(path, documentBase);
1956 if (HttpUtils.isValidUrl(withDocBase))
1960 // System.err.println("Prepended document base '" + documentBase
1961 // + "' to make: '" + withDocBase + "'");
1963 retPath[0] = withDocBase;
1964 return DataSourceType.URL;
1968 * try relative to codebase (if different to document base)
1970 URL codeBase = getCodeBase();
1971 String withCodeBase = resolveUrlForLocalOrAbsolute(path, codeBase);
1972 if (!withCodeBase.equals(withDocBase)
1973 && HttpUtils.isValidUrl(withCodeBase))
1977 // System.err.println("Prepended codebase '" + codeBase
1978 // + "' to make: '" + withCodeBase + "'");
1980 retPath[0] = withCodeBase;
1981 return DataSourceType.URL;
1985 * try locating by classloader; try this last so files in the directory
1986 * are resolved using document base
1988 if (inArchive(getClass(), path))
1990 return DataSourceType.CLASSLOADER;
1996 * Discovers whether the given file is in the Applet Archive
2002 private static boolean inArchive(Class<?> c, String f)
2004 // This might throw a security exception in certain browsers
2005 // Netscape Communicator for instance.
2008 boolean rtn = (c.getResourceAsStream("/" + f) != null);
2010 } catch (Exception ex)
2012 System.out.println("Exception checking resources: " + f + " " + ex);
2018 * form a complete URL given a path to a resource and a reference location on
2022 * - an absolute path on the same server as localref or a document
2023 * located relative to localref
2025 * - a URL on the same server as url
2026 * @return a complete URL for the resource located by url
2028 public static String resolveUrlForLocalOrAbsolute(String targetPath,
2031 String resolvedPath = "";
2032 if (targetPath.startsWith("/"))
2034 String codebase = localref.toString();
2035 String localfile = localref.getFile();
2036 resolvedPath = codebase.substring(0,
2037 codebase.length() - localfile.length()) + targetPath;
2038 return resolvedPath;
2042 * get URL path and strip off any trailing file e.g.
2043 * www.jalview.org/examples/index.html#applets?a=b is trimmed to
2044 * www.jalview.org/examples/
2046 String urlPath = localref.toString();
2047 String directoryPath = urlPath;
2048 int lastSeparator = directoryPath.lastIndexOf("/");
2049 if (lastSeparator > 0)
2051 directoryPath = directoryPath.substring(0, lastSeparator + 1);
2054 if (targetPath.startsWith("/"))
2057 * construct absolute URL to a file on the server - this is not allowed?
2059 // String localfile = localref.getFile();
2060 // resolvedPath = urlPath.substring(0,
2061 // urlPath.length() - localfile.length())
2063 resolvedPath = directoryPath + targetPath.substring(1);
2067 resolvedPath = directoryPath + targetPath;
2071 // System.err.println(
2072 // "resolveUrlForLocalOrAbsolute returning " + resolvedPath);
2074 return resolvedPath;
2078 * parse the string into a list
2082 * @return elements separated by separator
2084 public static String[] separatorListToArray(String list, String separator)
2086 // TODO use StringUtils version (slightly different...)
2087 int seplen = separator.length();
2088 if (list == null || list.equals("") || list.equals(separator))
2092 Vector<String> jv = new Vector<>();
2094 while ((pos = list.indexOf(separator, cp)) > cp)
2096 jv.addElement(list.substring(cp, pos));
2099 if (cp < list.length())
2101 String c = list.substring(cp);
2102 if (!c.equals(separator))
2109 String[] v = new String[jv.size()];
2110 for (int i = 0; i < v.length; i++)
2112 v[i] = jv.elementAt(i);
2114 jv.removeAllElements();
2120 public class JsSelectionListener
2121 implements jalview.structure.SelectionListener
2128 public JsSelectionListener(AlignFrame af, String listener)
2131 _listener = listener;
2135 public void selection(SequenceGroup seqsel, ColumnSelection colsel,
2136 HiddenColumns hidden, SelectionSource source)
2138 // System.err.println("Testing selection event relay to
2139 // jsfunction:"+_listener);
2141 AlignFrame src = _af;
2144 if (source instanceof AlignViewport
2145 && Jalview.getCurrentAlignFrame().getViewport() == source)
2147 src = Jalview.getCurrentAlignFrame();
2152 String[] seqs = new String[] {};
2153 String[] cols = new String[] {};
2154 int strt = 0, end = (src == null) ? -1
2155 : src.alignPanel.av.getAlignment().getWidth();
2156 if (seqsel != null && seqsel.getSize() > 0)
2158 seqs = new String[seqsel.getSize()];
2159 for (int i = 0; i < seqs.length; i++)
2161 seqs[i] = seqsel.getSequenceAt(i).getName();
2163 if (strt < seqsel.getStartRes())
2165 strt = seqsel.getStartRes();
2167 if (end == -1 || end > seqsel.getEndRes())
2169 end = seqsel.getEndRes();
2172 if (colsel != null && !colsel.isEmpty())
2176 end = colsel.getMax() + 1;
2178 cols = new String[colsel.getSelected().size()];
2179 for (int i = 0; i < cols.length; i++)
2181 cols[i] = "" + (1 + colsel.getSelected().get(i).intValue());
2186 if (seqsel != null && seqsel.getSize() > 0)
2188 // send a valid range, otherwise we send the empty selection
2189 cols = new String[2];
2190 cols[0] = "" + (1 + strt) + "-" + (1 + end);
2196 Jalview jalview = Jalview.getInstance();
2197 jalview.doSendCallback(_listener,
2199 { src, setid, jalview.arrayToSeparatorList(seqs),
2200 jalview.arrayToSeparatorList(cols) });
2203 public boolean isFor(AlignFrame af, String listener)
2205 return _af == af && _listener.contentEquals(listener);
2211 public AlignViewportI getViewport()
2213 return Jalview.getCurrentAlignFrame().getViewport();