needed for applet search
[jalview.git] / src / com / stevesoft / pat / Transformer.java
diff --git a/src/com/stevesoft/pat/Transformer.java b/src/com/stevesoft/pat/Transformer.java
new file mode 100755 (executable)
index 0000000..f65afb4
--- /dev/null
@@ -0,0 +1,155 @@
+//\r
+// This software is now distributed according to\r
+// the Lesser Gnu Public License.  Please see\r
+// http://www.gnu.org/copyleft/lesser.txt for\r
+// the details.\r
+//    -- Happy Computing!\r
+//\r
+package com.stevesoft.pat;\r
+\r
+import java.util.Vector;\r
+import com.stevesoft.pat.wrap.StringWrap;\r
+\r
+/** Replacement rule used by the Transformer.\r
+    @see com.stevesoft.pat.Transformer\r
+    */\r
+class TransRepRule extends ReplaceRule {\r
+    Transformer t;\r
+    TransRepRule(Transformer t) { this.t = t; }\r
+    public String toString1() { return ""; }\r
+    public Object clone1() { return new TransRepRule(t); }\r
+    public void apply(StringBufferLike sb,RegRes rr) {\r
+        // get the ReplaceRule of the Regex that matched.\r
+        next = t.tp.ra[t.tp.pn].getReplaceRule();\r
+    }\r
+}\r
+\r
+/** Sometimes you want to replace a whole bunch of things\r
+  that might occur within a single line of text.  One efficient\r
+  way to do this, both in terms of performance and programming\r
+  ease, is with Transformer. The Transformer contains an array\r
+  of Regex's and uses the Regex that matches earliest within the\r
+  text to do the replacing, if two Regex's match at the same\r
+  time it uses the one put in the Transformer first.\r
+  <p>\r
+  This feature can be used to prevent transformations from\r
+  occurring in certain regions. For example, if I add the rule\r
+  s'//.*'$&' and then add the\r
+  rule s/hello/goodbye/ the Transformer will replace "hello"\r
+  with "goodbye" except when it occurs inside a double-slash\r
+  style of comment.   The transformation on the comment goes first,\r
+  does nothing, and precludes transformation on the same region\r
+  of text as the s/hello/goodbye/ rule.\r
+  <p>\r
+  So far, at least, this class does not have the capability of\r
+  turning into a giant robot :-)\r
+  */\r
+public class Transformer {\r
+    TransPat tp;\r
+    Regex rp = new Regex();\r
+    boolean auto_optimize;\r
+\r
+    /** Get a replacer to that works with the current Regex.\r
+     @see com.stevesoft.pat.Replacer\r
+     */\r
+    public Replacer getReplacer() { return rp.getReplacer(); }\r
+\r
+    /** Instantiate a new Transformer object. */\r
+    public Transformer(boolean auto) {\r
+        auto_optimize = auto;\r
+        tp = new TransPat();\r
+        rp.setReplaceRule(new TransRepRule(this));\r
+        rp.thePattern = tp;\r
+    }\r
+\r
+    /** Add a new Regex to the set of Regex's. */\r
+    public void add(Regex r) {\r
+        if(auto_optimize) r.optimize();\r
+        tp.ra[tp.ra_len++] = r;\r
+        if(tp.ra.length==tp.ra_len) {\r
+            Regex[] ra2 = new Regex[tp.ra_len+10];\r
+            for(int i=0;i<tp.ra_len;i++)\r
+                ra2[i] = tp.ra[i];\r
+            tp.ra = ra2;\r
+        }\r
+        rp.numSubs_ = r.numSubs_ > rp.numSubs_ ? r.numSubs_ : rp.numSubs_;\r
+    }\r
+\r
+    /** Returns the number of Regex's in this Transformer. */\r
+    public int patterns() { return tp.ra_len; }\r
+\r
+    /** Get the Regex at position i in this Transformer. */\r
+    public Regex getRegexAt(int i) {\r
+        if(i >= tp.ra_len)\r
+            throw new ArrayIndexOutOfBoundsException("i="+i+">="+patterns());\r
+        if(i < 0)\r
+            throw new ArrayIndexOutOfBoundsException("i="+i+"< 0");\r
+        return tp.ra[i];\r
+    }\r
+    /** Set the Regex at position i in this Transformer. */\r
+    public void setRegexAt(Regex rx,int i) {\r
+        if(i >= tp.ra_len)\r
+            throw new ArrayIndexOutOfBoundsException("i="+i+">="+patterns());\r
+        if(i < 0)\r
+            throw new ArrayIndexOutOfBoundsException("i="+i+"< 0");\r
+        tp.ra[i] = rx;\r
+    }\r
+\r
+    /** Add a new Regex by calling Regex.perlCode\r
+        @see com.stevesoft.pat.Regex#perlCode(java.lang.String)\r
+        */\r
+    public void add(String rs) {\r
+        Regex r = Regex.perlCode(rs);\r
+        if(r == null) throw new NullPointerException("bad pattern to Regex.perlCode: "+rs);\r
+        add(r);\r
+    }\r
+    /** Add an array of Strings (which will be converted to\r
+        Regex's via the Regex.perlCode method.\r
+        @see com.stevesoft.pat.Regex#perlCode(java.lang.String)\r
+        */\r
+    public void add(String[] array) {\r
+        for(int i=0;i<array.length;i++)\r
+            add(array[i]);\r
+    }\r
+    /** Replace all matches in the current String. */\r
+    public String replaceAll(String s) {\r
+        return dorep(s,0,s.length());\r
+    }\r
+    public StringLike replaceAll(StringLike s) {\r
+        return dorep(s,0,s.length());\r
+    }\r
+    /** Replace all matching patterns beginning at position start. */\r
+    public String replaceAllFrom(String s,int start) {\r
+        return dorep(s,start,s.length());\r
+    }\r
+    /** Replace all matching patterns beginning between the positions\r
+        start and end inclusive. */\r
+    public String replaceAllRegion(String s,int start,int end) {\r
+        return dorep(s,start,end);\r
+    }\r
+\r
+    Replacer repr = new Replacer();\r
+    final StringLike dorep(StringLike s,int start,int end) {\r
+        StringLike tfmd = repr.replaceAllRegion(s,rp,start,end);\r
+        tp.lastMatchedTo = repr.lastMatchedTo;\r
+        return tfmd;\r
+    }\r
+    final String dorep(String s,int start,int end) {\r
+        return dorep(new StringWrap(s),start,end).toString();\r
+    }\r
+\r
+    /** Replace the first matching pattern in String s. */\r
+    public String replaceFirst(String s) {\r
+        return dorep(s,0,s.length());\r
+    }\r
+    /** Replace the first matching pattern after position start in\r
+        String s. */\r
+    public String replaceFirstFrom(String s,int start) {\r
+        return dorep(s,start,s.length());\r
+    }\r
+    /** Replace the first matching pattern that begins between\r
+        start and end inclusive. */\r
+    public String replaceFirstRegion(String s,int start,int end) {\r
+        return dorep(s,start,end);\r
+    }\r
+}\r