Merge branch 'features/sequenceFeatureRefactor' into develop
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 23 Mar 2015 10:00:41 +0000 (10:00 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 23 Mar 2015 10:00:41 +0000 (10:00 +0000)
Conflicts:
src/jalview/analysis/AlignmentSorter.java
src/jalview/analysis/Dna.java
src/jalview/bin/JalviewLite.java
src/jalview/gui/PopupMenu.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
test/jalview/datamodel/SequenceTest.java
and minor unit test refactoring

32 files changed:
src/jalview/analysis/AlignmentSorter.java
src/jalview/analysis/AlignmentUtils.java
src/jalview/analysis/Dna.java
src/jalview/bin/JalviewLite.java
src/jalview/controller/AlignViewController.java
src/jalview/ext/paradise/Annotate3D.java
src/jalview/ext/rbvi/chimera/ChimeraCommands.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/IdPanel.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/SequenceFetcher.java
src/jalview/io/BioJsHTMLOutput.java
src/jalview/io/SequenceAnnotationReport.java
src/jalview/io/StockholmFile.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/util/ParseHtmlBodyAndLinks.java
src/jalview/util/StringUtils.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/ws/rest/InputType.java
src/jalview/ws/rest/RestServiceDescription.java
test/jalview/analysis/CrossRefTest.java [moved from src/jalview/analysis/CrossRefTest.java with 100% similarity]
test/jalview/datamodel/SequenceTest.java
test/jalview/ext/paradise/TestAnnotate3D.java
test/jalview/util/MappingUtilsTest.java
test/jalview/util/StringUtilsTest.java
test/jalview/ws/jabaws/JpredJabaStructExportImport.java
test/jalview/ws/jabaws/RNAStructExportImport.java
test/jalview/ws/rest/ShmmrRSBSService.java
test/jalview/ws/seqfetcher/DbRefFetcherTest.java

index 7721a98..2fad332 100755 (executable)
@@ -780,10 +780,6 @@ public class AlignmentSorter
     for (int i = 0; i < seqs.length; i++)
     {
       SequenceFeature[] sf = seqs[i].getSequenceFeatures();
-      if (sf == null && seqs[i].getDatasetSequence() != null)
-      {
-        sf = seqs[i].getDatasetSequence().getSequenceFeatures();
-      }
       if (sf == null)
       {
         sf = new SequenceFeature[0];
index 4576881..9202c0d 100644 (file)
@@ -453,8 +453,8 @@ public class AlignmentUtils
               || !(aaRes == translated.charAt(0)))
       {
         // debug
-        System.out.println(("Mismatch at " + i + "/" + aaResidue + ": "
-                + codon + "(" + translated + ") != " + aaRes));
+        // System.out.println(("Mismatch at " + i + "/" + aaResidue + ": "
+        // + codon + "(" + translated + ") != " + aaRes));
         return false;
       }
     }
index a785073..ab606f7 100644 (file)
@@ -781,8 +781,7 @@ public class Dna
           MapList map, Map<String, Object> featureTypes,
           Map<String, Boolean> featureGroups)
   {
-    SequenceFeature[] sfs = (dna.getDatasetSequence() != null ? dna
-            .getDatasetSequence() : dna).getSequenceFeatures();
+    SequenceFeature[] sfs = dna.getSequenceFeatures();
     Boolean fgstate;
     DBRefEntry[] dnarefs = DBRefUtils.selectRefs(dna.getDBRef(),
             DBRefSource.DNACODINGDBS);
index d812de6..c0a8d73 100644 (file)
@@ -1808,12 +1808,6 @@ public class JalviewLite extends Applet implements
       return file;
     }
 
-    // public LoadingThread(String _file, JalviewLite _applet)
-    // {
-    // this._file = _file;
-    // applet = _applet;
-    // }
-
     public LoadingThread(String file, String file2, JalviewLite _applet)
     {
       this._file = file;
index 2d74590..972b6ab 100644 (file)
@@ -179,13 +179,7 @@ public class AlignViewController implements AlignViewControllerI
       int tfeat = 0;
       if (sq != null)
       {
-        SequenceI dsq = sq.getDatasetSequence();
-        while (dsq.getDatasetSequence() != null)
-        {
-          dsq = dsq.getDatasetSequence();
-        }
-        ;
-        SequenceFeature[] sf = dsq.getSequenceFeatures();
+        SequenceFeature[] sf = sq.getSequenceFeatures();
         if (sf != null)
         {
           int ist = sq.findIndex(sq.getStart());
index 68625bc..55c3c1d 100644 (file)
@@ -23,6 +23,7 @@ package jalview.ext.paradise;
 import jalview.util.MessageManager;
 import jalview.ws.HttpClientUtils;
 
+import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.Reader;
@@ -136,7 +137,8 @@ public class Annotate3D
     // return processJsonResponseFor(HttpClientUtils.doHttpUrlPost(twoDtoolsURL,
     // vals));
     ArrayList<Reader> readers = new ArrayList<Reader>();
-    readers.add(HttpClientUtils.doHttpUrlPost(twoDtoolsURL, vals, 0, 0));
+    final BufferedReader postResponse = HttpClientUtils.doHttpUrlPost(twoDtoolsURL, vals, 0, 0);
+    readers.add(postResponse);
     return readers.iterator();
 
   }
index fa1b7e2..148f252 100644 (file)
  */
 package jalview.ext.rbvi.chimera;
 
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
 import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.datamodel.AlignmentI;
@@ -30,13 +37,6 @@ import jalview.structure.StructureSelectionManager;
 import jalview.util.ColorUtils;
 import jalview.util.Comparison;
 
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
 /**
  * Routines for generating Chimera commands for Jalview/Chimera binding
  * 
@@ -121,6 +121,7 @@ public class ChimeraCommands
         final Map<String, List<int[]>> modelData = colourData.get(model);
         for (String chain : modelData.keySet())
         {
+          boolean hasChain = !"".equals(chain.trim());
           for (int[] range : modelData.get(chain))
           {
             if (!firstPositionForModel)
@@ -135,7 +136,10 @@ public class ChimeraCommands
             {
               sb.append(range[0]).append("-").append(range[1]);
             }
-            sb.append(".").append(chain);
+            if (hasChain)
+            {
+              sb.append(".").append(chain);
+            }
             firstPositionForModel = false;
           }
         }
index 0566ee0..beafa8c 100644 (file)
@@ -1326,8 +1326,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
           sy = s * av.getCharHeight() + scaleHeight;
 
           SequenceI seq = av.getAlignment().getSequenceAt(s);
-          SequenceFeature[] features = seq.getDatasetSequence()
-                  .getSequenceFeatures();
+          SequenceFeature[] features = seq.getSequenceFeatures();
           SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
           for (res = 0; res < alwidth; res++)
           {
index 91332b1..891aaf7 100755 (executable)
@@ -67,6 +67,8 @@ import javax.swing.ToolTipManager;
 public class AnnotationLabels extends JPanel implements MouseListener,
         MouseMotionListener, ActionListener
 {
+  private static final Pattern LEFT_ANGLE_BRACKET_PATTERN = Pattern.compile("<");
+
   String TOGGLE_LABELSCALE = MessageManager.getString("label.scale_label_to_column");
 
   String ADDNEW = MessageManager.getString("label.add_new_row");
@@ -460,7 +462,7 @@ public class AnnotationLabels extends JPanel implements MouseListener,
                 || (desc.substring(0, 6).toLowerCase().indexOf("<html>") < 0))
         {
           // clean the description ready for embedding in html
-          desc = new StringBuffer(Pattern.compile("<").matcher(desc)
+          desc = new StringBuffer(LEFT_ANGLE_BRACKET_PATTERN.matcher(desc)
                   .replaceAll("&lt;"));
           desc.insert(0, "<html>");
         }
index 9e876c4..918fc02 100644 (file)
@@ -429,15 +429,13 @@ public class FeatureSettings extends JPanel
     String group;
     for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
     {
-      if (af.getViewport().getAlignment().getSequenceAt(i)
-              .getDatasetSequence().getSequenceFeatures() == null)
+      tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
+              .getSequenceFeatures();
+      if (tmpfeatures == null)
       {
         continue;
       }
 
-      tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
-              .getDatasetSequence().getSequenceFeatures();
-
       int index = 0;
       while (index < tmpfeatures.length)
       {
@@ -547,7 +545,7 @@ public class FeatureSettings extends JPanel
     {
 
       tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
-              .getDatasetSequence().getSequenceFeatures();
+              .getSequenceFeatures();
       if (tmpfeatures == null)
       {
         continue;
index c21c27b..4ea35ca 100755 (executable)
@@ -323,8 +323,7 @@ public class IdPanel extends JPanel implements MouseListener,
       // build a new links menu based on the current links + any non-positional
       // features
       Vector nlinks = new Vector(Preferences.sequenceURLLinks);
-      SequenceFeature sf[] = sq == null ? null : sq.getDatasetSequence()
-              .getSequenceFeatures();
+      SequenceFeature sf[] = sq == null ? null : sq.getSequenceFeatures();
       for (int sl = 0; sf != null && sl < sf.length; sl++)
       {
         if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0)
index 2c95b7c..ad10f5e 100644 (file)
@@ -682,9 +682,9 @@ public class Jalview2XML
         }
       }
 
-      if (jdatasq.getSequenceFeatures() != null)
+      if (jds.getSequenceFeatures() != null)
       {
-        jalview.datamodel.SequenceFeature[] sf = jdatasq
+        jalview.datamodel.SequenceFeature[] sf = jds
                 .getSequenceFeatures();
         int index = 0;
         while (index < sf.length)
index 64e8d67..0000291 100644 (file)
  */
 package jalview.gui;
 
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JColorChooser;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPopupMenu;
+import javax.swing.JRadioButtonMenuItem;
+
 import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.analysis.Conservation;
@@ -58,29 +81,6 @@ import jalview.util.GroupUrlLink.UrlStringTooLongException;
 import jalview.util.MessageManager;
 import jalview.util.UrlLink;
 
-import java.awt.Color;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.Vector;
-
-import javax.swing.ButtonGroup;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JColorChooser;
-import javax.swing.JMenu;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPopupMenu;
-import javax.swing.JRadioButtonMenuItem;
-
 /**
  * DOCUMENT ME!
  * 
@@ -2023,7 +2023,7 @@ public class PopupMenu extends JPopupMenu
     }
     cap.setText("<html>" + contents.toString() + "</html>");
 
-    Desktop.instance.addInternalFrame(cap, MessageManager.formatMessage(
+    Desktop.addInternalFrame(cap, MessageManager.formatMessage(
             "label.sequence_details_for",
             (sequences.length == 1 ? new Object[]
             { sequences[0].getDisplayId(true) } : new Object[]
index 72a7167..06f4b0f 100755 (executable)
@@ -814,7 +814,7 @@ public class SequenceFetcher extends JPanel implements Runnable
         {
           for (SequenceI sq : alsqs)
           {
-            if ((sfs = (sq).getDatasetSequence().getSequenceFeatures()) != null)
+            if ((sfs = sq.getSequenceFeatures()) != null)
             {
               if (sfs.length > 0)
               {
index ad3b79f..d2c4a7f 100644 (file)
@@ -137,8 +137,7 @@ public class BioJsHTMLOutput
       seqPojo.setName(name.toString());
       seqPojo.setSeq(seq.getSequenceAsString());
 
-      SequenceFeature[] seqFeatures = seq.getDatasetSequence()
-              .getSequenceFeatures();
+      SequenceFeature[] seqFeatures = seq.getSequenceFeatures();
       if (seqFeatures != null)
       {
         ArrayList<BioJsFeaturePojo> bjsSeqFeatures = new ArrayList<BioJsFeaturePojo>();
index 610c03f..07cfa8b 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.io;
 
+
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
@@ -364,7 +365,7 @@ public class SequenceAnnotationReport
     }
 
     // ADD NON POSITIONAL SEQUENCE INFO
-    SequenceFeature[] features = ds.getSequenceFeatures();
+    SequenceFeature[] features = sequence.getSequenceFeatures();
     if (showNpFeats && features != null)
     {
       for (int i = 0; i < features.length; i++)
index e5e14ad..6490d28 100644 (file)
@@ -978,6 +978,7 @@ public class StockholmFile extends AlignFile
             {
               feature = ds.getSequenceFeatures()[0].type;
             }
+            // ?bug - feature may still have previous loop value
             String key = type2id(feature);
 
             if (key == null)
index fa91342..648f776 100644 (file)
@@ -20,28 +20,6 @@ public class FeatureRenderer extends
 
   boolean offscreenRender = false;
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param g
-   *          DOCUMENT ME!
-   * @param seq
-   *          DOCUMENT ME!
-   * @param sg
-   *          DOCUMENT ME!
-   * @param start
-   *          DOCUMENT ME!
-   * @param end
-   *          DOCUMENT ME!
-   * @param x1
-   *          DOCUMENT ME!
-   * @param y1
-   *          DOCUMENT ME!
-   * @param width
-   *          DOCUMENT ME!
-   * @param height
-   *          DOCUMENT ME!
-   */
   protected SequenceI lastSeq;
 
   char s;
@@ -99,7 +77,6 @@ public class FeatureRenderer extends
         charOffset = (av_charWidth - fm.charWidth(s)) / 2;
         g.drawString(String.valueOf(s), charOffset
                 + (av_charWidth * (i - start)), pady);
-
       }
     }
   }
@@ -164,7 +141,6 @@ public class FeatureRenderer extends
         charOffset = (av_charWidth - fm.charWidth(s)) / 2;
         g.drawString(String.valueOf(s), charOffset
                 + (av_charWidth * (i - start)), pady);
-
       }
     }
   }
@@ -188,29 +164,29 @@ public class FeatureRenderer extends
       return initialCol;
     }
 
-    SequenceFeature[] sf = seq.getSequenceFeatures();
+    SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
     if (seq != lastSeq)
     {
       lastSeq = seq;
-      sequenceFeatures = sf;
-      if (sequenceFeatures != null)
+      lastSequenceFeatures = sequenceFeatures;
+      if (lastSequenceFeatures != null)
       {
-        sfSize = sequenceFeatures.length;
+        sfSize = lastSequenceFeatures.length;
       }
     }
     else
     {
-      if (sequenceFeatures != sf)
+      if (lastSequenceFeatures != sequenceFeatures)
       {
-        sequenceFeatures = sf;
-        if (sequenceFeatures != null)
+        lastSequenceFeatures = sequenceFeatures;
+        if (lastSequenceFeatures != null)
         {
-          sfSize = sequenceFeatures.length;
+          sfSize = lastSequenceFeatures.length;
         }
       }
     }
 
-    if (sequenceFeatures == null || sfSize == 0)
+    if (lastSequenceFeatures == null || sfSize == 0)
     {
       return initialCol;
     }
@@ -254,7 +230,7 @@ public class FeatureRenderer extends
 
   }
 
-  private volatile SequenceFeature[] sequenceFeatures;
+  private volatile SequenceFeature[] lastSequenceFeatures;
 
   int sfSize;
 
@@ -267,8 +243,8 @@ public class FeatureRenderer extends
   public synchronized void drawSequence(Graphics g, final SequenceI seq,
           int start, int end, int y1)
   {
-    SequenceFeature[] sf = seq.getSequenceFeatures();
-    if (sf == null || sf.length == 0)
+    SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
+    if (sequenceFeatures == null || sequenceFeatures.length == 0)
     {
       return;
     }
@@ -281,10 +257,10 @@ public class FeatureRenderer extends
     updateFeatures();
 
     if (lastSeq == null || seq != lastSeq
- || sf != sequenceFeatures)
+            || sequenceFeatures != lastSequenceFeatures)
     {
       lastSeq = seq;
-      sequenceFeatures = sf;
+      lastSequenceFeatures = sequenceFeatures;
     }
 
     if (transparency != 1 && g != null)
@@ -300,7 +276,7 @@ public class FeatureRenderer extends
       epos = lastSeq.findPosition(end);
     }
 
-    sfSize = sequenceFeatures.length;
+    sfSize = lastSequenceFeatures.length;
     String type;
     for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
     {
@@ -315,25 +291,24 @@ public class FeatureRenderer extends
       // current feature to render
       for (sfindex = 0; sfindex < sfSize; sfindex++)
       {
-        if (!sequenceFeatures[sfindex].type.equals(type))
+        final SequenceFeature sequenceFeature = lastSequenceFeatures[sfindex];
+        if (!sequenceFeature.type.equals(type))
         {
           continue;
         }
 
         if (featureGroups != null
-                && sequenceFeatures[sfindex].featureGroup != null
-                && sequenceFeatures[sfindex].featureGroup.length() != 0
-                && featureGroups
-                        .containsKey(sequenceFeatures[sfindex].featureGroup)
-                && !featureGroups
-                        .get(sequenceFeatures[sfindex].featureGroup)
+                && sequenceFeature.featureGroup != null
+                && sequenceFeature.featureGroup.length() != 0
+                && featureGroups.containsKey(sequenceFeature.featureGroup)
+                && !featureGroups.get(sequenceFeature.featureGroup)
                         .booleanValue())
         {
           continue;
         }
 
         if (!offscreenRender
-                && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex]
+                && (sequenceFeature.getBegin() > epos || sequenceFeature
                         .getEnd() < spos))
         {
           continue;
@@ -341,56 +316,51 @@ public class FeatureRenderer extends
 
         if (offscreenRender && offscreenImage == null)
         {
-          if (sequenceFeatures[sfindex].begin <= start
-                  && sequenceFeatures[sfindex].end >= start)
+          if (sequenceFeature.begin <= start
+                  && sequenceFeature.end >= start)
           {
             // this is passed out to the overview and other sequence renderers
             // (e.g. molecule viewer) to get displayed colour for rendered
             // sequence
-            currentColour = new Integer(
-                    getColour(sequenceFeatures[sfindex]).getRGB());
+            currentColour = new Integer(getColour(sequenceFeature).getRGB());
             // used to be retreived from av.featuresDisplayed
             // currentColour = av.featuresDisplayed
             // .get(sequenceFeatures[sfindex].type);
 
           }
         }
-        else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
+        else if (sequenceFeature.type.equals("disulfide bond"))
         {
-
-          renderFeature(g, seq,
-                  seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                  seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                  getColour(sequenceFeatures[sfindex])
+          renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1,
+                  seq.findIndex(sequenceFeature.begin) - 1,
+                  getColour(sequenceFeature)
                   // new Color(((Integer) av.featuresDisplayed
                   // .get(sequenceFeatures[sfindex].type)).intValue())
                   , start, end, y1);
-          renderFeature(g, seq,
-                  seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                  seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                  getColour(sequenceFeatures[sfindex])
+          renderFeature(g, seq, seq.findIndex(sequenceFeature.end) - 1,
+                  seq.findIndex(sequenceFeature.end) - 1,
+                  getColour(sequenceFeature)
                   // new Color(((Integer) av.featuresDisplayed
                   // .get(sequenceFeatures[sfindex].type)).intValue())
                   , start, end, y1);
 
         }
-        else if (showFeature(sequenceFeatures[sfindex]))
+        else if (showFeature(sequenceFeature))
         {
           if (av_isShowSeqFeatureHeight
-                  && sequenceFeatures[sfindex].score != Float.NaN)
+                  && sequenceFeature.score != Float.NaN)
           {
             renderScoreFeature(g, seq,
-                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                    getColour(sequenceFeatures[sfindex]), start, end, y1,
-                    normaliseScore(sequenceFeatures[sfindex]));
+                    seq.findIndex(sequenceFeature.begin) - 1,
+                    seq.findIndex(sequenceFeature.end) - 1,
+                    getColour(sequenceFeature), start, end, y1,
+                    normaliseScore(sequenceFeature));
           }
           else
           {
-            renderFeature(g, seq,
-                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                    getColour(sequenceFeatures[sfindex]), start, end, y1);
+            renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1,
+                    seq.findIndex(sequenceFeature.end) - 1,
+                    getColour(sequenceFeature), start, end, y1);
           }
         }
 
index 19726b9..7aec22d 100644 (file)
@@ -32,6 +32,8 @@ import java.util.regex.Pattern;
  */
 public class ParseHtmlBodyAndLinks
 {
+  private static final Pattern LEFT_ANGLE_BRACKET_PATTERN = Pattern.compile("<");
+
   String orig = null;
 
   public String getOrig()
@@ -153,7 +155,7 @@ public class ParseHtmlBodyAndLinks
     {
       // instead of parsing the html into plaintext
       // clean the description ready for embedding in html
-      sb = new StringBuffer(Pattern.compile("<").matcher(description)
+      sb = new StringBuffer(LEFT_ANGLE_BRACKET_PATTERN.matcher(description)
               .replaceAll("&lt;"));
 
     }
index 0544864..1325ce5 100644 (file)
@@ -1,8 +1,15 @@
 package jalview.util;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
 
 public class StringUtils
 {
+  private static final Pattern DELIMITERS_PATTERN = Pattern.compile(".*='[^']*(?!')");
+
+  private static final boolean DEBUG = false;
 
   /**
    * Returns a new character array, after inserting characters into the given
@@ -103,4 +110,124 @@ public class StringUtils
     String[] st = input.split(token);
     return st[st.length - 1];
   }
+
+  /**
+   * Parses the input string into components separated by the delimiter. Unlike
+   * String.split(), this method will ignore occurrences of the delimiter which
+   * are nested within single quotes in name-value pair values, e.g. a='b,c'.
+   * 
+   * @param input
+   * @param delimiter
+   * @return elements separated by separator
+   */
+  public static String[] separatorListToArray(String input, String delimiter)
+  {
+    int seplen = delimiter.length();
+    if (input == null || input.equals("") || input.equals(delimiter))
+    {
+      return null;
+    }
+    List<String> jv = new ArrayList<String>();
+    int cp = 0, pos, escape;
+    boolean wasescaped = false, wasquoted = false;
+    String lstitem = null;
+    while ((pos = input.indexOf(delimiter, cp)) >= cp)
+    {
+      escape = (pos > 0 && input.charAt(pos - 1) == '\\') ? -1 : 0;
+      if (wasescaped || wasquoted)
+      {
+        // append to previous pos
+        jv.set(jv.size() - 1,
+                lstitem = lstitem + delimiter
+                        + input.substring(cp, pos + escape));
+      }
+      else
+      {
+        jv.add(lstitem = input.substring(cp, pos + escape));
+      }
+      cp = pos + seplen;
+      wasescaped = escape == -1;
+      // last separator may be in an unmatched quote
+      wasquoted = DELIMITERS_PATTERN.matcher(lstitem).matches();
+    }
+    if (cp < input.length())
+    {
+      String c = input.substring(cp);
+      if (wasescaped || wasquoted)
+      {
+        // append final separator
+        jv.set(jv.size() - 1, lstitem + delimiter + c);
+      }
+      else
+      {
+        if (!c.equals(delimiter))
+        {
+          jv.add(c);
+        }
+      }
+    }
+    if (jv.size() > 0)
+    {
+      String[] v = jv.toArray(new String[jv.size()]);
+      jv.clear();
+      if (DEBUG)
+      {
+        System.err.println("Array from '" + delimiter
+                + "' separated List:\n" + v.length);
+        for (int i = 0; i < v.length; i++)
+        {
+          System.err.println("item " + i + " '" + v[i] + "'");
+        }
+      }
+      return v;
+    }
+    if (DEBUG)
+    {
+      System.err.println("Empty Array from '" + delimiter
+              + "' separated List");
+    }
+    return null;
+  }
+
+  /**
+   * Returns a string which contains the list elements delimited by the
+   * separator. Null items are ignored. If the input is null or has length zero,
+   * a single delimiter is returned.
+   * 
+   * @param list
+   * @param separator
+   * @return concatenated string
+   */
+  public static String arrayToSeparatorList(String[] list, String separator)
+  {
+    StringBuffer v = new StringBuffer();
+    if (list != null && list.length > 0)
+    {
+      for (int i = 0, iSize = list.length; i < iSize; i++)
+      {
+        if (list[i] != null)
+        {
+          if (v.length() > 0)
+          {
+            v.append(separator);
+          }
+          // TODO - escape any separator values in list[i]
+          v.append(list[i]);
+        }
+      }
+      if (DEBUG)
+      {
+        System.err.println("Returning '" + separator
+                + "' separated List:\n");
+        System.err.println(v);
+      }
+      return v.toString();
+    }
+    if (DEBUG)
+    {
+      System.err.println("Returning empty '" + separator
+              + "' separated List\n");
+    }
+    return "" + separator;
+  }
 }
index 8c2f0da..674f3d1 100644 (file)
@@ -247,12 +247,6 @@ public abstract class FeatureRendererModel implements
     ArrayList<SequenceFeature> tmp = new ArrayList<SequenceFeature>();
     SequenceFeature[] features = sequence.getSequenceFeatures();
 
-    while (features == null && sequence.getDatasetSequence() != null)
-    {
-      sequence = sequence.getDatasetSequence();
-      features = sequence.getSequenceFeatures();
-    }
-
     if (features != null)
     {
       for (int i = 0; i < features.length; i++)
index 91fce18..8741ddc 100644 (file)
@@ -46,6 +46,8 @@ import org.apache.http.entity.mime.content.StringBody;
  */
 public abstract class InputType
 {
+  private static final Pattern URL_PATTERN = Pattern.compile("^([^=]+)=?'?([^']*)?'?");
+
   /**
    * not used yet
    */
@@ -209,7 +211,7 @@ public abstract class InputType
     boolean valid = true;
     for (String tok : tokenstring)
     {
-      Matcher mtch = Pattern.compile("^([^=]+)=?'?([^']*)?'?").matcher(tok);
+      Matcher mtch = URL_PATTERN.matcher(tok);
       if (mtch.find())
       {
         try
index bbe131d..5b910c4 100644 (file)
  */
 package jalview.ws.rest;
 
-import jalview.datamodel.SequenceI;
-import jalview.io.packed.DataProvider.JvDataType;
-import jalview.ws.rest.params.Alignment;
-import jalview.ws.rest.params.AnnotationFile;
-import jalview.ws.rest.params.SeqGroupIndexVector;
-
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -37,8 +31,17 @@ import java.util.StringTokenizer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import jalview.datamodel.SequenceI;
+import jalview.io.packed.DataProvider.JvDataType;
+import jalview.util.StringUtils;
+import jalview.ws.rest.params.Alignment;
+import jalview.ws.rest.params.AnnotationFile;
+import jalview.ws.rest.params.SeqGroupIndexVector;
+
 public class RestServiceDescription
 {
+  private static final Pattern PARAM_ENCODED_URL_PATTERN = Pattern.compile("([?&])([A-Za-z0-9_]+)=\\$([^$]+)\\$");
+
   /**
    * create a new rest service description ready to be configured
    */
@@ -358,126 +361,6 @@ public class RestServiceDescription
     return invalidMessage == null;
   }
 
-  private static boolean debug = false;
-
-  /**
-   * parse the string into a list
-   * 
-   * @param list
-   * @param separator
-   * @return elements separated by separator
-   */
-  public static String[] separatorListToArray(String list, String separator)
-  {
-    int seplen = separator.length();
-    if (list == null || list.equals("") || list.equals(separator))
-    {
-      return null;
-    }
-    java.util.ArrayList<String> jv = new ArrayList<String>();
-    int cp = 0, pos, escape;
-    boolean wasescaped = false, wasquoted = false;
-    String lstitem = null;
-    while ((pos = list.indexOf(separator, cp)) >= cp)
-    {
-
-      escape = (pos > 0 && list.charAt(pos - 1) == '\\') ? -1 : 0;
-      if (wasescaped || wasquoted)
-      {
-        // append to previous pos
-        jv.set(jv.size() - 1,
-                lstitem = lstitem + separator
-                        + list.substring(cp, pos + escape));
-      }
-      else
-      {
-        jv.add(lstitem = list.substring(cp, pos + escape));
-      }
-      cp = pos + seplen;
-      wasescaped = escape == -1;
-      // last separator may be in an unmatched quote
-      wasquoted = (java.util.regex.Pattern.matches(".*='[^']*(?!')",
-              lstitem));
-    }
-    if (cp < list.length())
-    {
-      String c = list.substring(cp);
-      if (wasescaped || wasquoted)
-      {
-        // append final separator
-        jv.set(jv.size() - 1, lstitem + separator + c);
-      }
-      else
-      {
-        if (!c.equals(separator))
-        {
-          jv.add(c);
-        }
-      }
-    }
-    if (jv.size() > 0)
-    {
-      String[] v = jv.toArray(new String[jv.size()]);
-      jv.clear();
-      if (debug)
-      {
-        System.err.println("Array from '" + separator
-                + "' separated List:\n" + v.length);
-        for (int i = 0; i < v.length; i++)
-        {
-          System.err.println("item " + i + " '" + v[i] + "'");
-        }
-      }
-      return v;
-    }
-    if (debug)
-    {
-      System.err.println("Empty Array from '" + separator
-              + "' separated List");
-    }
-    return null;
-  }
-
-  /**
-   * concatenate the list with separator
-   * 
-   * @param list
-   * @param separator
-   * @return concatenated string
-   */
-  public static String arrayToSeparatorList(String[] list, String separator)
-  {
-    StringBuffer v = new StringBuffer();
-    if (list != null && list.length > 0)
-    {
-      for (int i = 0, iSize = list.length; i < iSize; i++)
-      {
-        if (list[i] != null)
-        {
-          if (v.length() > 0)
-          {
-            v.append(separator);
-          }
-          // TODO - escape any separator values in list[i]
-          v.append(list[i]);
-        }
-      }
-      if (debug)
-      {
-        System.err.println("Returning '" + separator
-                + "' separated List:\n");
-        System.err.println(v);
-      }
-      return v.toString();
-    }
-    if (debug)
-    {
-      System.err.println("Returning empty '" + separator
-              + "' separated List\n");
-    }
-    return "" + separator;
-  }
-
   /**
    * parse a string containing a list of service properties and configure the
    * service description
@@ -489,7 +372,7 @@ public class RestServiceDescription
   private boolean configureFromServiceInputProperties(String propList,
           StringBuffer warnings)
   {
-    String[] props = separatorListToArray(propList, ",");
+    String[] props = StringUtils.separatorListToArray(propList, ",");
     if (props == null)
     {
       return true;
@@ -607,7 +490,7 @@ public class RestServiceDescription
     ;
     vls.add(new String("gapCharacter='" + gapCharacter + "'"));
     vls.add(new String("returns='" + _genOutputFormatString() + "'"));
-    return arrayToSeparatorList(vls.toArray(new String[0]), ",");
+    return StringUtils.arrayToSeparatorList(vls.toArray(new String[0]), ",");
   }
 
   public String toString()
@@ -650,7 +533,7 @@ public class RestServiceDescription
   public boolean configureFromEncodedString(String encoding,
           StringBuffer warnings)
   {
-    String[] list = separatorListToArray(encoding, "|");
+    String[] list = StringUtils.separatorListToArray(encoding, "|");
 
     int nextpos = parseServiceList(list, warnings, 0);
     if (nextpos > 0)
@@ -751,7 +634,7 @@ public class RestServiceDescription
             url.append("$");
             url.append(param.getValue().getURLtokenPrefix());
             url.append(":");
-            url.append(arrayToSeparatorList(vals.toArray(new String[0]),
+            url.append(StringUtils.arrayToSeparatorList(vals.toArray(new String[0]),
                     ","));
             url.append("$");
           }
@@ -778,7 +661,7 @@ public class RestServiceDescription
     boolean valid = true;
     int lastp = 0;
     String url = new String();
-    Matcher prms = Pattern.compile("([?&])([A-Za-z0-9_]+)=\\$([^$]+)\\$")
+    Matcher prms = PARAM_ENCODED_URL_PATTERN
             .matcher(ipurl);
     Map<String, InputType> iparams = new Hashtable<String, InputType>();
     InputType jinput;
@@ -844,7 +727,7 @@ public class RestServiceDescription
         if (iprm.equalsIgnoreCase(jinput.getURLtokenPrefix()))
         {
           ArrayList<String> al = new ArrayList<String>();
-          for (String prprm : separatorListToArray(iprmparams, ","))
+          for (String prprm : StringUtils.separatorListToArray(iprmparams, ","))
           {
             // hack to ensure that strings like "sep=','" containing unescaped
             // commas as values are concatenated
@@ -995,7 +878,7 @@ public class RestServiceDescription
   public static List<RestServiceDescription> parseDescriptions(
           String services) throws Exception
   {
-    String[] list = separatorListToArray(services, "|");
+    String[] list = StringUtils.separatorListToArray(services, "|");
     List<RestServiceDescription> svcparsed = new ArrayList<RestServiceDescription>();
     int p = 0, lastp = 0;
     StringBuffer warnings = new StringBuffer();
index 1ef1d07..857ee84 100644 (file)
@@ -247,7 +247,6 @@ public class SequenceTest
     assertEquals("zABCDEF", seq.getSequenceAsString());
     seq.insertCharAt(2, 2, 'x');
     assertEquals("zAxxBCDEF", seq.getSequenceAsString());
-    
     // for static method see StringUtilsTest
   }
 
index 6085e03..3365c52 100644 (file)
 package jalview.ext.paradise;
 
 import static org.junit.Assert.assertTrue;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.SequenceI;
-import jalview.io.FastaFile;
-import jalview.io.FormatAdapter;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -35,9 +31,13 @@ import org.junit.Assert;
 import org.junit.Test;
 
 import MCview.PDBfile;
-
 import compbio.util.FileUtil;
 
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.io.FastaFile;
+import jalview.io.FormatAdapter;
+
 public class TestAnnotate3D
 {
 
@@ -124,11 +124,12 @@ public class TestAnnotate3D
         sb.append(line + "\n");
       }
       assertTrue("No data returned by Annotate3D", sb.length() > 0);
-      AlignmentI al = new FormatAdapter().readFile(sb.toString(),
+      final String lines = sb.toString();
+      AlignmentI al = new FormatAdapter().readFile(lines,
               FormatAdapter.PASTE, "RNAML");
       if (al == null || al.getHeight() == 0)
       {
-        System.out.println(sb.toString());
+        System.out.println(lines);
       }
       assertTrue("No alignment returned.", al != null);
       assertTrue("No sequences in returned alignment.", al.getHeight() > 0);
@@ -141,7 +142,8 @@ public class TestAnnotate3D
             String sq_ = new String(sq.getSequence()).toLowerCase();
             for (SequenceI _struseq : pdbf.getSeqsAsArray())
             {
-              if (new String(_struseq.getSequence()).toLowerCase().equals(
+              final String lowerCase = new String(_struseq.getSequence()).toLowerCase();
+              if (lowerCase.equals(
                       sq_))
               {
                 struseq = _struseq;
index f1ea01c..f32e7ff 100644 (file)
@@ -344,30 +344,6 @@ public class MappingUtilsTest
   }
 
   /**
-   * Test mapping a column selection including hidden columns
-   * 
-   * @throws IOException
-   */
-  @Test
-  public void testMapColumnSelection_hiddenColumns() throws IOException
-  {
-    setupMappedAlignments();
-
-    ColumnSelection colsel = new ColumnSelection();
-  
-    /*
-     * Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
-     * in dna respectively, overall 0-4
-     */
-    colsel.addElement(0);
-    ColumnSelection cs = MappingUtils.mapColumnSelection(colsel,
-            proteinView, dnaView);
-    assertEquals("[0, 1, 2, 3, 4]", cs.getSelected().toString());
-
-    fail("write me");
-  }
-
-  /**
    * Test mapping a column selection in dna to its protein equivalent
    * 
    * @throws IOException
index 22a4130..6930e40 100644 (file)
@@ -68,4 +68,42 @@ public class StringUtilsTest
     assertEquals("file1.dat", StringUtils.getLastToken(
             "file://localhost:8080/data/examples/file1.dat", "/"));
   }
+
+  @Test
+  public void testSeparatorListToArray()
+  {
+    String[] result = StringUtils.separatorListToArray(
+            "foo=',',min='foo',max='1,2,3',fa=','", ",");
+    assertEquals("[foo=',', min='foo', max='1,2,3', fa=',']",
+            Arrays.toString(result));
+    /*
+     * Comma nested in '' is not treated as delimiter; tokens are not trimmed
+     */
+    result = StringUtils.separatorListToArray("minsize='2', sep=','", ",");
+    assertEquals("[minsize='2',  sep=',']", Arrays.toString(result));
+    
+    /*
+     * String delimited by | containing a quoted | (should not be treated as
+     * delimiter)
+     */
+    assertEquals("[abc='|'d, ef, g]", Arrays.toString(StringUtils
+            .separatorListToArray("abc='|'d|ef|g", "|")));
+  }
+
+  @Test
+  public void testArrayToSeparatorList()
+  {
+    assertEquals("*", StringUtils.arrayToSeparatorList(null, "*"));
+    assertEquals("*", StringUtils.arrayToSeparatorList(new String[]
+    {}, "*"));
+    assertEquals("a*bc*cde", StringUtils.arrayToSeparatorList(new String[]
+    { "a", "bc", "cde" }, "*"));
+    assertEquals("a*cde", StringUtils.arrayToSeparatorList(new String[]
+    { "a", null, "cde" }, "*"));
+    assertEquals("a**cde", StringUtils.arrayToSeparatorList(new String[]
+    { "a", "", "cde" }, "*"));
+    // delimiter within token is not (yet) escaped
+    assertEquals("a*b*c*cde", StringUtils.arrayToSeparatorList(new String[]
+    { "a", "b*c", "cde" }, "*"));
+  }
 }
index cf98e33..c522bc3 100644 (file)
@@ -23,17 +23,6 @@ package jalview.ws.jabaws;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import jalview.datamodel.AlignmentI;
-import jalview.gui.Jalview2XML;
-import jalview.io.AnnotationFile;
-import jalview.io.FormatAdapter;
-import jalview.io.StockholmFileTest;
-import jalview.ws.jws2.JPred301Client;
-import jalview.ws.jws2.JabaParamStore;
-import jalview.ws.jws2.Jws2Discoverer;
-import jalview.ws.jws2.SequenceAnnotationWSClient;
-import jalview.ws.jws2.jabaws2.Jws2Instance;
-import jalview.ws.params.AutoCalcSetting;
 
 import java.awt.Component;
 import java.util.ArrayList;
@@ -49,6 +38,18 @@ import org.junit.Test;
 import compbio.metadata.Argument;
 import compbio.metadata.WrongParameterException;
 
+import jalview.datamodel.AlignmentI;
+import jalview.gui.Jalview2XML;
+import jalview.io.AnnotationFile;
+import jalview.io.FormatAdapter;
+import jalview.io.StockholmFileTest;
+import jalview.ws.jws2.JPred301Client;
+import jalview.ws.jws2.JabaParamStore;
+import jalview.ws.jws2.Jws2Discoverer;
+import jalview.ws.jws2.SequenceAnnotationWSClient;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.AutoCalcSetting;
+
 public class JpredJabaStructExportImport
 {
   public static String testseqs = "examples/uniref50.fa";
@@ -81,7 +82,7 @@ public class JpredJabaStructExportImport
 
     if (jpredws == null)
     {
-      System.exit(0);
+      fail("jpredws is null");
     }
 
     jalview.io.FileLoader fl = new jalview.io.FileLoader(false);
index c052b0b..36b3196 100644 (file)
@@ -23,16 +23,6 @@ package jalview.ws.jabaws;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import jalview.datamodel.AlignmentI;
-import jalview.gui.Jalview2XML;
-import jalview.io.AnnotationFile;
-import jalview.io.FormatAdapter;
-import jalview.io.StockholmFileTest;
-import jalview.ws.jws2.Jws2Discoverer;
-import jalview.ws.jws2.RNAalifoldClient;
-import jalview.ws.jws2.SequenceAnnotationWSClient;
-import jalview.ws.jws2.jabaws2.Jws2Instance;
-import jalview.ws.params.AutoCalcSetting;
 
 import java.awt.Component;
 import java.util.ArrayList;
@@ -47,6 +37,17 @@ import org.junit.Test;
 
 import compbio.metadata.WrongParameterException;
 
+import jalview.datamodel.AlignmentI;
+import jalview.gui.Jalview2XML;
+import jalview.io.AnnotationFile;
+import jalview.io.FormatAdapter;
+import jalview.io.StockholmFileTest;
+import jalview.ws.jws2.Jws2Discoverer;
+import jalview.ws.jws2.RNAalifoldClient;
+import jalview.ws.jws2.SequenceAnnotationWSClient;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.AutoCalcSetting;
+
 public class RNAStructExportImport
 {
   public static String testseqs = "examples/unfolded_RF00031.aln";
@@ -79,7 +80,7 @@ public class RNAStructExportImport
 
     if (rnaalifoldws == null)
     {
-      System.exit(0);
+      fail("no web service");
     }
 
     jalview.io.FileLoader fl = new jalview.io.FileLoader(false);
index 5fc215c..c4430ad 100644 (file)
  */
 package jalview.ws.rest;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.List;
 import java.util.Map;
 
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.AlignmentView;
-import jalview.gui.AlignFrame;
-import jalview.io.FileParse;
-import jalview.ws.rest.InputType;
-import jalview.ws.rest.params.SeqGroupIndexVector;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
 import org.junit.Test;
 
+import jalview.gui.AlignFrame;
+import jalview.util.StringUtils;
+
 /**
  * @author jimp
  * 
@@ -48,20 +38,6 @@ public class ShmmrRSBSService
 {
 
   @Test
-  public void testSeparatorListToArrayForRestServiceDescriptions()
-  {
-    assertTrue(
-            "separatorListToArray is faulty.",
-            RestServiceDescription.separatorListToArray(
-                    "foo=',',min='foo',max='1,2,3',fa=','", ",").length == 4);
-    assertTrue("separatorListToArray is faulty.",
-            RestServiceDescription.separatorListToArray(
-                    "minsize='2', sep=','", ",").length != 2); // probably
-                                                               // should come as
-                                                               // 2
-  }
-
-  @Test
   public void testShmmrService()
   {
 
index f58ead5..7540edf 100644 (file)
@@ -23,12 +23,6 @@ package jalview.ws.seqfetcher;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import jalview.analysis.CrossRef;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.DBRefEntry;
-import jalview.datamodel.DBRefSource;
-import jalview.util.DBRefUtils;
-import jalview.ws.SequenceFetcher;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -37,6 +31,13 @@ import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import jalview.analysis.CrossRef;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
+import jalview.util.DBRefUtils;
+import jalview.ws.SequenceFetcher;
+
 /**
  * @author jimp
  *