From 73f6ca49365fc7791a47570e9fad297d8145ba59 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Wed, 31 Jan 2018 16:22:01 +0000 Subject: [PATCH 1/1] JAL-852 clickable links in Alignment Properties report; alignmentProperties now Map --- resources/lang/Messages.properties | 1 - resources/lang/Messages_es.properties | 1 - src/jalview/appletgui/AlignFrame.java | 3 +- src/jalview/datamodel/Alignment.java | 15 +-- src/jalview/datamodel/AlignmentI.java | 3 +- src/jalview/gui/AlignFrame.java | 3 +- src/jalview/gui/Jalview2XML.java | 9 +- src/jalview/io/AlignFile.java | 34 ++++--- src/jalview/io/AlignmentProperties.java | 157 ++++++++++++++++++++----------- src/jalview/io/AnnotationFile.java | 11 +-- src/jalview/io/StockholmFile.java | 19 ++-- 11 files changed, 147 insertions(+), 109 deletions(-) diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 05f7a57..0056580 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -967,7 +967,6 @@ error.implementation_error_old_jalview_object_not_bound =IMPLEMENTATION ERROR: o error.implementation_error_vamsas_doc_class_should_bind_to_type = Implementation Error: Vamsas Document Class {0} should bind to a {1} (found a {2}) error.invalid_vamsas_rangetype_cannot_resolve_lists = Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice! error.implementation_error_maplist_is_null = Implementation error. MapList is null for initMapType. -error.implementation_error_cannot_have_null_alignment = Implementation error: Cannot have null alignment property key error.implementation_error_null_fileparse = Implementation error. Null FileParse in copy constructor error.implementation_error_cannot_map_alignment_sequences = IMPLEMENTATION ERROR: Cannot map an alignment of sequences from different datasets into a single alignment in the vamsas document. error.implementation_error_structure_selection_manager_null = Implementation error. Structure selection manager's context is 'null' diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index 1c62648..abc3612 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -892,7 +892,6 @@ error.implementation_error_old_jalview_object_not_bound =Error de implementaci error.implementation_error_vamsas_doc_class_should_bind_to_type = Error de implementación: la clase de documento VAMSAS {0} debe enlazar a {1} (pero se ha encontrado que lo está a {2}) error.invalid_vamsas_rangetype_cannot_resolve_lists = RangeType VAMSAS no válido - ¡no es posible resolver ambas listas de Pos y Seg con los valores elegidos! error.implementation_error_maplist_is_null = Error de implementación. MapList es nulo en initMapType. -error.implementation_error_cannot_have_null_alignment = Error de implementación: no es posible tener una clave nula en el alineamiento error.implementation_error_null_fileparse = Error de implementación. FileParse nulo en el construictor de copia error.implementation_error_cannot_map_alignment_sequences = Error de implementación: no es posible maper un alineamiento de secuencias desde distintos conjuntos de datos en un único alineamiento en el documento VAMSAS. error.implementation_error_structure_selection_manager_null = Error de implementación. El contexto structure selection manager's es nulo diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java index ef87671..37e9b11 100644 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@ -51,6 +51,7 @@ import jalview.datamodel.PDBEntry; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.io.AlignmentProperties; import jalview.io.AnnotationFile; import jalview.io.AppletFormatAdapter; import jalview.io.DataSourceType; @@ -1206,7 +1207,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, } else if (source == alProperties) { - StringBuffer contents = new jalview.io.AlignmentProperties( + StringBuilder contents = new AlignmentProperties( viewport.getAlignment()).formatAsString(); CutAndPasteTransfer cap = new CutAndPasteTransfer(false, this); cap.setText(contents.toString()); diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java index f268d37..1265923 100755 --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@ -31,8 +31,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; +import java.util.HashMap; import java.util.HashSet; -import java.util.Hashtable; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -65,7 +66,7 @@ public class Alignment implements AlignmentI HiddenColumns hiddenCols; - public Hashtable alignmentProperties; + public Map alignmentProperties; private List codonFrameList; @@ -1353,7 +1354,7 @@ public class Alignment implements AlignmentI { if (alignmentProperties == null) { - alignmentProperties = new Hashtable(); + alignmentProperties = new HashMap<>(); } alignmentProperties.put(key, value); @@ -1373,7 +1374,7 @@ public class Alignment implements AlignmentI } @Override - public Hashtable getProperties() + public Map getProperties() { return alignmentProperties; } @@ -1541,10 +1542,10 @@ public class Alignment implements AlignmentI { // we really can't do very much here - just try to concatenate strings // where property collisions occur. - Enumeration key = toappend.getProperties().keys(); - while (key.hasMoreElements()) + Iterator key = toappend.getProperties().keySet().iterator(); + while (key.hasNext()) { - Object k = key.nextElement(); + Object k = key.next(); Object ourval = this.getProperty(k); Object toapprop = toappend.getProperty(k); if (ourval != null) diff --git a/src/jalview/datamodel/AlignmentI.java b/src/jalview/datamodel/AlignmentI.java index 084b80e..757dad1 100755 --- a/src/jalview/datamodel/AlignmentI.java +++ b/src/jalview/datamodel/AlignmentI.java @@ -20,7 +20,6 @@ */ package jalview.datamodel; -import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; @@ -389,7 +388,7 @@ public interface AlignmentI extends AnnotatedCollectionI * * @return hashtable of alignment properties (or null if none are defined) */ - Hashtable getProperties(); + Map getProperties(); /** * add a reference to a frame of aligned codons for this alignment diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index da11536..bb81a4e 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -3221,7 +3221,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, public void alignmentProperties() { CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer(); - StringBuffer contents = new AlignmentProperties(viewport.getAlignment()) + StringBuilder contents = new AlignmentProperties( + viewport.getAlignment()) .formatAsHtml(); cap.setText("" + contents.toString() + ""); diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index 4a15024..26a11de 100644 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -768,13 +768,12 @@ public class Jalview2XML } if (jal.getProperties() != null) { - Enumeration en = jal.getProperties().keys(); - while (en.hasMoreElements()) + for (Entry prop : jal.getProperties().entrySet()) { - String key = en.nextElement().toString(); + String key = prop.getKey().toString(); SequenceSetProperties ssp = new SequenceSetProperties(); ssp.setKey(key); - ssp.setValue(jal.getProperties().get(key).toString()); + ssp.setValue(prop.getValue().toString()); vamsasSet.addSequenceSetProperties(ssp); } } @@ -5333,7 +5332,7 @@ public class Jalview2XML if (this.frefedSequence == null) { - frefedSequence = new Vector(); + frefedSequence = new Vector<>(); } viewportsAdded.clear(); diff --git a/src/jalview/io/AlignFile.java b/src/jalview/io/AlignFile.java index 2340283..22ffcae 100755 --- a/src/jalview/io/AlignFile.java +++ b/src/jalview/io/AlignFile.java @@ -25,13 +25,13 @@ import jalview.datamodel.AlignmentI; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; -import jalview.util.MessageManager; import java.io.IOException; import java.util.ArrayList; -import java.util.Enumeration; import java.util.Hashtable; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Vector; /** @@ -66,7 +66,7 @@ public abstract class AlignFile extends FileParse /** * Properties to be added to generated alignment object */ - private Hashtable properties; + private Map properties; long start; @@ -251,13 +251,11 @@ public abstract class AlignFile extends FileParse */ public void addProperties(AlignmentI al) { - if (properties != null && properties.size() > 0) + if (properties != null) { - Enumeration keys = properties.keys(); - Enumeration vals = properties.elements(); - while (keys.hasMoreElements()) + for (Entry prop : properties.entrySet()) { - al.setProperty(keys.nextElement(), vals.nextElement()); + al.setProperty(prop.getKey(), prop.getValue()); } } } @@ -272,12 +270,12 @@ public abstract class AlignFile extends FileParse * @param value * - non-null value */ - protected void setAlignmentProperty(Object key, Object value) + protected void setAlignmentProperty(String key, String value) { if (key == null) { - throw new Error(MessageManager.getString( - "error.implementation_error_cannot_have_null_alignment")); + throw new Error( + "Implementation error: Cannot have null alignment property key."); } if (value == null) { @@ -285,12 +283,12 @@ public abstract class AlignFile extends FileParse } if (properties == null) { - properties = new Hashtable(); + properties = new Hashtable<>(); } properties.put(key, value); } - protected Object getAlignmentProperty(Object key) + protected String getAlignmentProperty(String key) { if (properties != null && key != null) { @@ -304,9 +302,9 @@ public abstract class AlignFile extends FileParse */ protected void initData() { - seqs = new Vector(); - annotations = new Vector(); - seqGroups = new ArrayList(); + seqs = new Vector<>(); + annotations = new Vector<>(); + seqGroups = new ArrayList<>(); parseCalled = false; } @@ -319,7 +317,7 @@ public abstract class AlignFile extends FileParse @Override public void setSeqs(SequenceI[] s) { - seqs = new Vector(); + seqs = new Vector<>(); for (int i = 0; i < s.length; i++) { @@ -390,7 +388,7 @@ public abstract class AlignFile extends FileParse { if (newickStrings == null) { - newickStrings = new Vector(); + newickStrings = new Vector<>(); } newickStrings.addElement(new String[] { treeName, newickString }); } diff --git a/src/jalview/io/AlignmentProperties.java b/src/jalview/io/AlignmentProperties.java index 6a7d1c1..c1d6129 100644 --- a/src/jalview/io/AlignmentProperties.java +++ b/src/jalview/io/AlignmentProperties.java @@ -20,13 +20,11 @@ */ package jalview.io; -import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentI; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Enumeration; -import java.util.Hashtable; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Map; /** * Render associated attributes of an alignment. The heart of this code was @@ -37,6 +35,8 @@ import java.util.Hashtable; */ public class AlignmentProperties { + private static final String BR_TAG = "
"; + private static final String NEWLINE = System.getProperty("line.separator"); AlignmentI alignment; public AlignmentProperties(AlignmentI alignment) @@ -47,12 +47,12 @@ public class AlignmentProperties /** * render the alignment's properties report as text or an HTML fragment * - * @param pw * @param html */ - protected void writeProperties(PrintWriter pw, boolean html) + protected StringBuilder writeProperties(boolean html) { - final String nl = html ? "
" : System.getProperty("line.separator"); + StringBuilder sb = new StringBuilder(256); + final String nl = html ? BR_TAG : NEWLINE; float avg = 0; int min = Integer.MAX_VALUE, max = 0; for (int i = 0; i < alignment.getHeight(); i++) @@ -70,77 +70,122 @@ public class AlignmentProperties } } avg = avg / alignment.getHeight(); - pw.print(nl); - pw.print("Sequences: " + alignment.getHeight()); - pw.print(nl); - pw.print("Minimum Sequence Length: " + min); - pw.print(nl); - pw.print("Maximum Sequence Length: " + max); - pw.print(nl); - pw.print("Average Length: " + (int) avg); + sb.append(nl); + sb.append("Sequences: " + alignment.getHeight()); + sb.append(nl); + sb.append("Minimum Sequence Length: " + min); + sb.append(nl); + sb.append("Maximum Sequence Length: " + max); + sb.append(nl); + sb.append("Average Length: " + (int) avg); - if (((Alignment) alignment).alignmentProperties != null) + Map props = alignment.getProperties(); + if (props != null && !props.isEmpty()) { - pw.print(nl); - pw.print(nl); + sb.append(nl); + sb.append(nl); if (html) { - pw.print(""); + sb.append("
"); } - Hashtable props = ((Alignment) alignment).alignmentProperties; - Enumeration en = props.keys(); - while (en.hasMoreElements()) + + /* + * sort keys alphabetically for ease of reading the output + */ + Object[] keys = props.keySet().toArray(new Object[props.size()]); + Arrays.sort(keys, new Comparator() { - String key = en.nextElement().toString(); - String vals = props.get(key).toString(); - if (html) + @Override + public int compare(Object o1, Object o2) { - // wrap the text in the table - StringBuffer val = new StringBuffer(); - int pos = 0, npos; - do - { - npos = vals.indexOf("\n", pos); - if (npos == -1) - { - val.append(vals.substring(pos)); - } - else - { - val.append(vals.substring(pos, npos)); - val.append("
"); - } - pos = npos + 1; - } while (npos != -1); - pw.print("
"); + return String.CASE_INSENSITIVE_ORDER.compare(o1.toString(), + o2.toString()); } - else + }); + for (Object key : keys) + { + String value = props.get(key).toString(); + if (html) { - pw.print(nl + key + "\t" + vals); + value = value.replaceAll("\\R", value); // Java 8 newline matcher + value = formatHrefs(value); } + appendRow(sb, key.toString(), value, html); } if (html) { - pw.print("
" + key + "" + val + "
"); + sb.append(""); } } + return sb; } /** - * generate a report as plain text + * Helper method to change any token starting with http into an html href * + * @param value * @return */ - public StringBuffer formatAsString() + private String formatHrefs(String value) + { + if (!value.contains("http")) + { + return value; + } + + StringBuilder sb = new StringBuilder(value.length() * 3); + String[] tokens = value.split("\\s"); + boolean found = false; + boolean first = true; + for (String token : tokens) + { + if (token.startsWith("http")) + { + token = "" + token + ""; + found = true; + } + if (!first) + { + sb.append(" "); + } + sb.append(token); + first = false; + } + return found ? sb.toString() : value; + } + + /** + * A helper method to add one key-value row, optionally in HTML table entry + * format + * + * @param sb + * @param key + * @param value + * @param html + */ + private void appendRow(StringBuilder sb, String key, String value, + boolean html) { - return formatReport(false); + if (html) + { + sb.append("").append(key).append("").append(value) + .append(""); + } + else + { + sb.append(html ? BR_TAG : NEWLINE).append(key).append("\t") + .append(value); + } } - protected StringBuffer formatReport(boolean html) + /** + * generate a report as plain text + * + * @return + */ + public StringBuilder formatAsString() { - StringWriter content = new StringWriter(); - writeProperties(new PrintWriter(content), html); - return content.getBuffer(); + return writeProperties(false); } /** @@ -148,9 +193,9 @@ public class AlignmentProperties * * @return */ - public StringBuffer formatAsHtml() + public StringBuilder formatAsHtml() { - return formatReport(true); + return writeProperties(true); } } diff --git a/src/jalview/io/AnnotationFile.java b/src/jalview/io/AnnotationFile.java index 00476d6..c6b4bc7 100755 --- a/src/jalview/io/AnnotationFile.java +++ b/src/jalview/io/AnnotationFile.java @@ -141,8 +141,8 @@ public class AnnotationFile * @return annotation file */ public String printAnnotations(AlignmentAnnotation[] annotations, - List list, Hashtable properties, HiddenColumns cs, - AlignmentI al, ViewDef view) + List list, Map properties, + HiddenColumns cs, AlignmentI al, ViewDef view) { if (view != null) { @@ -446,14 +446,13 @@ public class AnnotationFile text.append(newline); text.append(newline); text.append("ALIGNMENT"); - Enumeration en = properties.keys(); - while (en.hasMoreElements()) + for (Object ko : properties.keySet()) { - String key = en.nextElement().toString(); + String key = ko.toString(); text.append("\t"); text.append(key); text.append("="); - text.append(properties.get(key)); + text.append(properties.get(ko)); } // TODO: output alignment visualization settings here if required // iterate through one or more views, defining, marking columns and rows diff --git a/src/jalview/io/StockholmFile.java b/src/jalview/io/StockholmFile.java index f5b5177..654d593 100644 --- a/src/jalview/io/StockholmFile.java +++ b/src/jalview/io/StockholmFile.java @@ -46,6 +46,7 @@ import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Vector; import com.stevesoft.pat.Regex; @@ -197,7 +198,7 @@ public class StockholmFile extends AlignFile String version; // String id; Hashtable seqAnn = new Hashtable(); // Sequence related annotations - LinkedHashMap seqs = new LinkedHashMap(); + LinkedHashMap seqs = new LinkedHashMap<>(); Regex p, r, rend, s, x; // Temporary line for processing RNA annotation // String RNAannot = ""; @@ -658,7 +659,7 @@ public class StockholmFile extends AlignFile strucAnn = new Hashtable(); } - Vector newStruc = new Vector(); + Vector newStruc = new Vector<>(); parseAnnotationRow(newStruc, type, ns); for (AlignmentAnnotation alan : newStruc) { @@ -710,7 +711,7 @@ public class StockholmFile extends AlignFile private void guessDatabaseFor(Sequence seqO, String dbr, String dbsource) { DBRefEntry dbrf = null; - List dbrs = new ArrayList(); + List dbrs = new ArrayList<>(); String seqdb = "Unknown", sdbac = "" + dbr; int st = -1, en = -1, p; if ((st = sdbac.indexOf("/")) > -1) @@ -961,15 +962,11 @@ public class StockholmFile extends AlignFile // output database type if (al.getProperties() != null) { - if (!al.getProperties().isEmpty()) + for (Entry prop : al.getProperties().entrySet()) { - Enumeration key = al.getProperties().keys(); - Enumeration val = al.getProperties().elements(); - while (key.hasMoreElements()) - { - out.append("#=GF " + key.nextElement() + " " + val.nextElement()); - out.append(newline); - } + out.append("#=GF " + prop.getKey().toString() + " " + + prop.getValue().toString()); + out.append(newline); } } -- 1.7.10.2