needed for applet search
[jalview.git] / src / com / stevesoft / pat / Replacer.java
diff --git a/src/com/stevesoft/pat/Replacer.java b/src/com/stevesoft/pat/Replacer.java
new file mode 100755 (executable)
index 0000000..c78a11d
--- /dev/null
@@ -0,0 +1,261 @@
+//\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.*;\r
+import com.stevesoft.pat.wrap.StringWrap;\r
+\r
+/** Internally used class. */\r
+class RegHolder {\r
+    Regex me = null;\r
+    RegHolder prev = null;\r
+}\r
+\r
+/** Internally used class.\r
+  * @see CodeRule\r
+  */\r
+class CodeVal {\r
+    int pos;\r
+    char code;\r
+    CodeVal(int p,char c) {\r
+        pos = p;\r
+        code = c;\r
+    }\r
+    public String toString() {\r
+        return "("+pos+","+code+")";\r
+    }\r
+}\r
+\r
+/**\r
+  To use this class, first use either the getReplacer() method from\r
+  Transformer or Regex.  You can then use replaceAll, replaceFirst,\r
+  etc. methods on the Replacer in the same way that you can from\r
+  either of those two classes.\r
+  <p>\r
+  The only potential difference between using the methods of\r
+  Replacer to do the replacing is that Replacer remembers changes\r
+  to the replacing object between calls to replaceAll, replaceFirst\r
+  etc.  For details, see the example file\r
+  <a href="http://javaregex.com/code/trans3.java.html">trans3.java</a>.\r
+  @see com.stevesoft.pat.Transformer\r
+  @see com.stevesoft.pat.Regex\r
+*/\r
+public class Replacer {\r
+    boolean first;\r
+\r
+    /** Instantiate a new Replacer. */\r
+    public Replacer() {}\r
+\r
+    public StringLike replaceFirstRegion(String s,Regex r,\r
+        int start,int end) {\r
+        return replaceFirstRegion(new StringWrap(s),r,start,end);\r
+    }\r
+    /** This method replaces the first occurence of the Regex in the\r
+        String starting with position pos\r
+        according to the Replacer rule of this object. */\r
+    public StringLike replaceFirstRegion(StringLike s,Regex r,\r
+        int start,int end) {\r
+        first = true;\r
+        rh.me = r;\r
+        rh.prev = null;\r
+        return dorep(s,start,end);\r
+    }\r
+    public StringLike replaceFirst(StringLike s) {\r
+        return replaceFirstRegion(s,0,s.length());\r
+    }\r
+    public StringLike replaceFirstFrom(StringLike s,int start) {\r
+        return replaceFirstRegion(s,start,s.length());\r
+    }\r
+    public StringLike replaceFirstRegion(StringLike s,int start,int end) {\r
+        first = true;\r
+        return dorep(s,start,end);\r
+    }\r
+\r
+    RegHolder rh = new RegHolder();\r
+\r
+    public StringLike replaceAllRegion(String s,Regex r,\r
+        int start, int end) {\r
+        return replaceAllRegion(new StringWrap(s),r,start,end);\r
+    }\r
+    /** This method replaces all occurences of the Regex in the\r
+        String starting with postition pos\r
+        according to the Replacer rule of this object. */\r
+    public StringLike replaceAllRegion(StringLike s,Regex r,\r
+        int start,int end) {\r
+        first = false;\r
+        // reset\r
+        rh.me = r;\r
+        rh.prev = null;\r
+        return dorep(s,start,end);\r
+    }\r
+    public StringLike replaceAll(StringLike s) {\r
+        return replaceAllRegion(s,0,s.length());\r
+    }\r
+    public StringLike replaceAllFrom(StringLike s,int start) {\r
+        return replaceAllRegion(s,start,s.length());\r
+    }\r
+    public StringLike replaceAllRegion(StringLike s,int start,int end) {\r
+        first = false;\r
+        return dorep(s,start,end);\r
+    }\r
+\r
+    public String replaceAll(String s) {\r
+        return replaceAllRegion(new StringWrap(s),0,s.length()).toString();\r
+    }\r
+    public String replaceAllFrom(String s,int start) {\r
+        return replaceAllRegion(new StringWrap(s),start,s.length()).toString();\r
+    }\r
+    public String replaceAllRegion(String s,int start,int end) {\r
+        first = false;\r
+        return dorep(new StringWrap(s),start,end).toString();\r
+    }\r
+\r
+    final public boolean isSpecial(ReplaceRule x) {\r
+        while(x != null) {\r
+            if(x instanceof SpecialRule\r
+                    || (x instanceof RuleHolder && ((RuleHolder)x).held instanceof SpecialRule))\r
+                return true;\r
+            x = x.next;\r
+        }\r
+        return false;\r
+    }\r
+    final public void apply1(RegRes rr) {\r
+        rr.charsMatched_++;\r
+        apply(rr,null);\r
+        rr.charsMatched_--;\r
+    }\r
+\r
+    final StringLike dorep(StringLike s,int start,int end) {\r
+        StringLike ret = s;\r
+        want_more_text = false;\r
+        lastMatchedTo = 0;\r
+        if(rh.me == null)\r
+            throw new NullPointerException("Replacer has null Regex pointer");\r
+        if(rh.me._search(s,start,end)) {\r
+            int rmn = rh.me.matchedTo();\r
+            if(rh.me.charsMatched()==0 && !isSpecial(rh.me.getReplaceRule())) {\r
+                apply1(rh.me);\r
+                rmn++;\r
+            }\r
+            apply(rh.me);\r
+            if(!first)\r
+                for(int i=rmn;\r
+                        !want_more_text && rh.me._search(s,i,end);i=rmn) {\r
+                    rmn = rh.me.matchedTo();\r
+                    if(rh.me.charsMatched()==0) {\r
+                        if(!isSpecial(rh.me.getReplaceRule()))\r
+                            apply1(rh.me);\r
+                        rmn++;\r
+                    }\r
+                    apply(rh.me);\r
+                }\r
+            ret = finish();\r
+            ret = ret == null ? s : ret;\r
+        }\r
+        return ret;\r
+    }\r
+\r
+    StringBufferLike sb = null;\r
+    StringLike src = null;\r
+    int pos = 0;\r
+    /** This method allows you to apply the results of several\r
+        matches in a sequence to modify a String of text.  Each\r
+        call in the sequence must operate on the same piece of\r
+        text and the matchedFrom() of each RegRes given to this\r
+        method must be greater in value than the preceeding\r
+        RegRes's matchedTo() value.\r
+        */\r
+    public void apply(RegRes r,ReplaceRule rp) {\r
+        if(rp==null ||(rp.next == null && rp instanceof AmpersandRule))\r
+            return;\r
+        if(r.didMatch()) {\r
+            if(src == null)\r
+                src = r.getStringLike();\r
+           if(sb == null)\r
+                sb = new StringBufferLike(src.newStringBufferLike());\r
+            int rmf = r.matchedFrom();\r
+            for(int ii=pos;ii<rmf;ii++)\r
+              sb.append(src.charAt(ii));\r
+\r
+            Vector v = new Vector();\r
+            for(ReplaceRule x=rp;x != null;x=x.next) {\r
+                x.apply(sb,r);\r
+                if(x instanceof SpecialRule) {\r
+                    if(x instanceof WantMoreTextReplaceRule\r
+                            && want_more_text_enable)\r
+                        want_more_text = true;\r
+                    else if(x instanceof PushRule) {\r
+                        RegHolder rh2 = new RegHolder();\r
+                        rh2.me = ( (PushRule)x ).NewRule;\r
+                        rh2.prev = rh;\r
+                        rh = rh2;\r
+                    } else if(x instanceof PopRule) {\r
+                        if(rh.prev != null)\r
+                            rh = rh.prev;\r
+                    } else if(x instanceof ChangeRule) {\r
+                        rh.me = ( (ChangeRule) x).NewRule;\r
+                    }\r
+                }\r
+            }\r
+            if(!want_more_text)\r
+                pos = r.matchedTo();\r
+        }\r
+    }\r
+    boolean want_more_text = false, want_more_text_enable = false;\r
+    public boolean WantMoreText() { return want_more_text; }\r
+    /** Another form of apply, it is the same as\r
+        apply(r,r.getReplaceRule()). */\r
+    public void apply(Regex r) { apply(r,r.getReplaceRule()); }\r
+\r
+    /** This finishes the replacement, appending the right() part of\r
+        the last RegRes given to substitute(RegRes).  After this method\r
+        is called, the Replace object is reset to perform another\r
+        substitution. If no RegRes objects with a true didMatch are\r
+        applied, this returns null. */\r
+    public StringLike finish() {\r
+        if(src==null)\r
+            return null;\r
+        //sb.append(src.substring(pos,src.length()));\r
+        int s_end = src.length();\r
+        for(int ii=pos;ii<s_end;ii++)\r
+          sb.append(src.charAt(ii));\r
+        src = null;\r
+        lastMatchedTo = pos;\r
+        pos = 0;\r
+        StringLike retstr = sb.toStringLike();\r
+        sb = null;\r
+        return retstr;\r
+    }\r
+    int lastMatchedTo = 0;\r
+    public Object clone() {\r
+        Replacer r = new Replacer();\r
+        r.first = first;\r
+        r.src = src;\r
+        r.sb = sb;\r
+        r.pos = pos;\r
+        r.lastMatchedTo = lastMatchedTo;\r
+        r.want_more_text = want_more_text;\r
+        r.want_more_text_enable = want_more_text_enable;\r
+        r.rh.me = rh.me;\r
+        r.rh.prev = rh.prev;\r
+        return r;\r
+    }\r
+    public int lastMatchedTo() { return lastMatchedTo; }\r
+    public Regex getRegex() {\r
+      return rh.me;\r
+    }\r
+    public void setSource(StringLike sl) {\r
+      src = sl;\r
+    }\r
+    public void setBuffer(StringBufferLike sbl) {\r
+      sb = sbl;\r
+    }\r
+    public void setPos(int pos) {\r
+      this.pos = pos;\r
+    }\r
+}\r