Formatting
[jalview.git] / src / com / stevesoft / pat / Transformer.java
1 //\r
2 // This software is now distributed according to\r
3 // the Lesser Gnu Public License.  Please see\r
4 // http://www.gnu.org/copyleft/lesser.txt for\r
5 // the details.\r
6 //    -- Happy Computing!\r
7 //\r
8 package com.stevesoft.pat;\r
9 \r
10 import com.stevesoft.pat.wrap.*;\r
11 \r
12 /** Replacement rule used by the Transformer.\r
13     @see com.stevesoft.pat.Transformer\r
14  */\r
15 class TransRepRule\r
16     extends ReplaceRule\r
17 {\r
18   Transformer t;\r
19   TransRepRule(Transformer t)\r
20   {\r
21     this.t = t;\r
22   }\r
23 \r
24   public String toString1()\r
25   {\r
26     return "";\r
27   }\r
28 \r
29   public Object clone1()\r
30   {\r
31     return new TransRepRule(t);\r
32   }\r
33 \r
34   public void apply(StringBufferLike sb, RegRes rr)\r
35   {\r
36     // get the ReplaceRule of the Regex that matched.\r
37     next = t.tp.ra[t.tp.pn].getReplaceRule();\r
38   }\r
39 }\r
40 \r
41 /** Sometimes you want to replace a whole bunch of things\r
42   that might occur within a single line of text.  One efficient\r
43   way to do this, both in terms of performance and programming\r
44   ease, is with Transformer. The Transformer contains an array\r
45   of Regex's and uses the Regex that matches earliest within the\r
46   text to do the replacing, if two Regex's match at the same\r
47   time it uses the one put in the Transformer first.\r
48   <p>\r
49   This feature can be used to prevent transformations from\r
50   occurring in certain regions. For example, if I add the rule\r
51   s'//.*'$&' and then add the\r
52   rule s/hello/goodbye/ the Transformer will replace "hello"\r
53   with "goodbye" except when it occurs inside a double-slash\r
54   style of comment.   The transformation on the comment goes first,\r
55   does nothing, and precludes transformation on the same region\r
56   of text as the s/hello/goodbye/ rule.\r
57   <p>\r
58   So far, at least, this class does not have the capability of\r
59   turning into a giant robot :-)\r
60  */\r
61 public class Transformer\r
62 {\r
63   TransPat tp;\r
64   Regex rp = new Regex();\r
65   boolean auto_optimize;\r
66 \r
67   /** Get a replacer to that works with the current Regex.\r
68    @see com.stevesoft.pat.Replacer\r
69    */\r
70   public Replacer getReplacer()\r
71   {\r
72     return rp.getReplacer();\r
73   }\r
74 \r
75   /** Instantiate a new Transformer object. */\r
76   public Transformer(boolean auto)\r
77   {\r
78     auto_optimize = auto;\r
79     tp = new TransPat();\r
80     rp.setReplaceRule(new TransRepRule(this));\r
81     rp.thePattern = tp;\r
82   }\r
83 \r
84   /** Add a new Regex to the set of Regex's. */\r
85   public void add(Regex r)\r
86   {\r
87     if (auto_optimize)\r
88     {\r
89       r.optimize();\r
90     }\r
91     tp.ra[tp.ra_len++] = r;\r
92     if (tp.ra.length == tp.ra_len)\r
93     {\r
94       Regex[] ra2 = new Regex[tp.ra_len + 10];\r
95       for (int i = 0; i < tp.ra_len; i++)\r
96       {\r
97         ra2[i] = tp.ra[i];\r
98       }\r
99       tp.ra = ra2;\r
100     }\r
101     rp.numSubs_ = r.numSubs_ > rp.numSubs_ ? r.numSubs_ : rp.numSubs_;\r
102   }\r
103 \r
104   /** Returns the number of Regex's in this Transformer. */\r
105   public int patterns()\r
106   {\r
107     return tp.ra_len;\r
108   }\r
109 \r
110   /** Get the Regex at position i in this Transformer. */\r
111   public Regex getRegexAt(int i)\r
112   {\r
113     if (i >= tp.ra_len)\r
114     {\r
115       throw new ArrayIndexOutOfBoundsException("i=" + i + ">=" + patterns());\r
116     }\r
117     if (i < 0)\r
118     {\r
119       throw new ArrayIndexOutOfBoundsException("i=" + i + "< 0");\r
120     }\r
121     return tp.ra[i];\r
122   }\r
123 \r
124   /** Set the Regex at position i in this Transformer. */\r
125   public void setRegexAt(Regex rx, int i)\r
126   {\r
127     if (i >= tp.ra_len)\r
128     {\r
129       throw new ArrayIndexOutOfBoundsException("i=" + i + ">=" + patterns());\r
130     }\r
131     if (i < 0)\r
132     {\r
133       throw new ArrayIndexOutOfBoundsException("i=" + i + "< 0");\r
134     }\r
135     tp.ra[i] = rx;\r
136   }\r
137 \r
138   /** Add a new Regex by calling Regex.perlCode\r
139       @see com.stevesoft.pat.Regex#perlCode(java.lang.String)\r
140    */\r
141   public void add(String rs)\r
142   {\r
143     Regex r = Regex.perlCode(rs);\r
144     if (r == null)\r
145     {\r
146       throw new NullPointerException("bad pattern to Regex.perlCode: " + rs);\r
147     }\r
148     add(r);\r
149   }\r
150 \r
151   /** Add an array of Strings (which will be converted to\r
152       Regex's via the Regex.perlCode method.\r
153       @see com.stevesoft.pat.Regex#perlCode(java.lang.String)\r
154    */\r
155   public void add(String[] array)\r
156   {\r
157     for (int i = 0; i < array.length; i++)\r
158     {\r
159       add(array[i]);\r
160     }\r
161   }\r
162 \r
163   /** Replace all matches in the current String. */\r
164   public String replaceAll(String s)\r
165   {\r
166     return dorep(s, 0, s.length());\r
167   }\r
168 \r
169   public StringLike replaceAll(StringLike s)\r
170   {\r
171     return dorep(s, 0, s.length());\r
172   }\r
173 \r
174   /** Replace all matching patterns beginning at position start. */\r
175   public String replaceAllFrom(String s, int start)\r
176   {\r
177     return dorep(s, start, s.length());\r
178   }\r
179 \r
180   /** Replace all matching patterns beginning between the positions\r
181       start and end inclusive. */\r
182   public String replaceAllRegion(String s, int start, int end)\r
183   {\r
184     return dorep(s, start, end);\r
185   }\r
186 \r
187   Replacer repr = new Replacer();\r
188   final StringLike dorep(StringLike s, int start, int end)\r
189   {\r
190     StringLike tfmd = repr.replaceAllRegion(s, rp, start, end);\r
191     tp.lastMatchedTo = repr.lastMatchedTo;\r
192     return tfmd;\r
193   }\r
194 \r
195   final String dorep(String s, int start, int end)\r
196   {\r
197     return dorep(new StringWrap(s), start, end).toString();\r
198   }\r
199 \r
200   /** Replace the first matching pattern in String s. */\r
201   public String replaceFirst(String s)\r
202   {\r
203     return dorep(s, 0, s.length());\r
204   }\r
205 \r
206   /** Replace the first matching pattern after position start in\r
207       String s. */\r
208   public String replaceFirstFrom(String s, int start)\r
209   {\r
210     return dorep(s, start, s.length());\r
211   }\r
212 \r
213   /** Replace the first matching pattern that begins between\r
214       start and end inclusive. */\r
215   public String replaceFirstRegion(String s, int start, int end)\r
216   {\r
217     return dorep(s, start, end);\r
218   }\r
219 }\r