Formatting
[jalview.git] / src / com / stevesoft / pat / Replacer.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 /** Internally used class. */\r
13 class RegHolder\r
14 {\r
15   Regex me = null;\r
16   RegHolder prev = null;\r
17 }\r
18 \r
19 /** Internally used class.\r
20  * @see CodeRule\r
21  */\r
22 class CodeVal\r
23 {\r
24   int pos;\r
25   char code;\r
26   CodeVal(int p, char c)\r
27   {\r
28     pos = p;\r
29     code = c;\r
30   }\r
31 \r
32   public String toString()\r
33   {\r
34     return "(" + pos + "," + code + ")";\r
35   }\r
36 }\r
37 \r
38 /**\r
39   To use this class, first use either the getReplacer() method from\r
40   Transformer or Regex.  You can then use replaceAll, replaceFirst,\r
41   etc. methods on the Replacer in the same way that you can from\r
42   either of those two classes.\r
43   <p>\r
44   The only potential difference between using the methods of\r
45   Replacer to do the replacing is that Replacer remembers changes\r
46   to the replacing object between calls to replaceAll, replaceFirst\r
47   etc.  For details, see the example file\r
48   <a href="http://javaregex.com/code/trans3.java.html">trans3.java</a>.\r
49   @see com.stevesoft.pat.Transformer\r
50   @see com.stevesoft.pat.Regex\r
51  */\r
52 public class Replacer\r
53 {\r
54   boolean first;\r
55 \r
56   /** Instantiate a new Replacer. */\r
57   public Replacer()\r
58   {}\r
59 \r
60   public StringLike replaceFirstRegion(String s, Regex r,\r
61                                        int start, int end)\r
62   {\r
63     return replaceFirstRegion(new StringWrap(s), r, start, end);\r
64   }\r
65 \r
66   /** This method replaces the first occurence of the Regex in the\r
67       String starting with position pos\r
68       according to the Replacer rule of this object. */\r
69   public StringLike replaceFirstRegion(StringLike s, Regex r,\r
70                                        int start, int end)\r
71   {\r
72     first = true;\r
73     rh.me = r;\r
74     rh.prev = null;\r
75     return dorep(s, start, end);\r
76   }\r
77 \r
78   public StringLike replaceFirst(StringLike s)\r
79   {\r
80     return replaceFirstRegion(s, 0, s.length());\r
81   }\r
82 \r
83   public StringLike replaceFirstFrom(StringLike s, int start)\r
84   {\r
85     return replaceFirstRegion(s, start, s.length());\r
86   }\r
87 \r
88   public StringLike replaceFirstRegion(StringLike s, int start, int end)\r
89   {\r
90     first = true;\r
91     return dorep(s, start, end);\r
92   }\r
93 \r
94   RegHolder rh = new RegHolder();\r
95 \r
96   public StringLike replaceAllRegion(String s, Regex r,\r
97                                      int start, int end)\r
98   {\r
99     return replaceAllRegion(new StringWrap(s), r, start, end);\r
100   }\r
101 \r
102   /** This method replaces all occurences of the Regex in the\r
103       String starting with postition pos\r
104       according to the Replacer rule of this object. */\r
105   public StringLike replaceAllRegion(StringLike s, Regex r,\r
106                                      int start, int end)\r
107   {\r
108     first = false;\r
109     // reset\r
110     rh.me = r;\r
111     rh.prev = null;\r
112     return dorep(s, start, end);\r
113   }\r
114 \r
115   public StringLike replaceAll(StringLike s)\r
116   {\r
117     return replaceAllRegion(s, 0, s.length());\r
118   }\r
119 \r
120   public StringLike replaceAllFrom(StringLike s, int start)\r
121   {\r
122     return replaceAllRegion(s, start, s.length());\r
123   }\r
124 \r
125   public StringLike replaceAllRegion(StringLike s, int start, int end)\r
126   {\r
127     first = false;\r
128     return dorep(s, start, end);\r
129   }\r
130 \r
131   public String replaceAll(String s)\r
132   {\r
133     return replaceAllRegion(new StringWrap(s), 0, s.length()).toString();\r
134   }\r
135 \r
136   public String replaceAllFrom(String s, int start)\r
137   {\r
138     return replaceAllRegion(new StringWrap(s), start, s.length()).toString();\r
139   }\r
140 \r
141   public String replaceAllRegion(String s, int start, int end)\r
142   {\r
143     first = false;\r
144     return dorep(new StringWrap(s), start, end).toString();\r
145   }\r
146 \r
147   final public boolean isSpecial(ReplaceRule x)\r
148   {\r
149     while (x != null)\r
150     {\r
151       if (x instanceof SpecialRule\r
152           ||\r
153           (x instanceof RuleHolder && ( (RuleHolder) x).held instanceof SpecialRule))\r
154       {\r
155         return true;\r
156       }\r
157       x = x.next;\r
158     }\r
159     return false;\r
160   }\r
161 \r
162   final public void apply1(RegRes rr)\r
163   {\r
164     rr.charsMatched_++;\r
165     apply(rr, null);\r
166     rr.charsMatched_--;\r
167   }\r
168 \r
169   final StringLike dorep(StringLike s, int start, int end)\r
170   {\r
171     StringLike ret = s;\r
172     want_more_text = false;\r
173     lastMatchedTo = 0;\r
174     if (rh.me == null)\r
175     {\r
176       throw new NullPointerException("Replacer has null Regex pointer");\r
177     }\r
178     if (rh.me._search(s, start, end))\r
179     {\r
180       int rmn = rh.me.matchedTo();\r
181       if (rh.me.charsMatched() == 0 && !isSpecial(rh.me.getReplaceRule()))\r
182       {\r
183         apply1(rh.me);\r
184         rmn++;\r
185       }\r
186       apply(rh.me);\r
187       if (!first)\r
188       {\r
189         for (int i = rmn;\r
190              !want_more_text && rh.me._search(s, i, end); i = rmn)\r
191         {\r
192           rmn = rh.me.matchedTo();\r
193           if (rh.me.charsMatched() == 0)\r
194           {\r
195             if (!isSpecial(rh.me.getReplaceRule()))\r
196             {\r
197               apply1(rh.me);\r
198             }\r
199             rmn++;\r
200           }\r
201           apply(rh.me);\r
202         }\r
203       }\r
204       ret = finish();\r
205       ret = ret == null ? s : ret;\r
206     }\r
207     return ret;\r
208   }\r
209 \r
210   StringBufferLike sb = null;\r
211   StringLike src = null;\r
212   int pos = 0;\r
213   /** This method allows you to apply the results of several\r
214       matches in a sequence to modify a String of text.  Each\r
215       call in the sequence must operate on the same piece of\r
216       text and the matchedFrom() of each RegRes given to this\r
217       method must be greater in value than the preceeding\r
218       RegRes's matchedTo() value.\r
219    */\r
220   public void apply(RegRes r, ReplaceRule rp)\r
221   {\r
222     if (rp == null || (rp.next == null && rp instanceof AmpersandRule))\r
223     {\r
224       return;\r
225     }\r
226     if (r.didMatch())\r
227     {\r
228       if (src == null)\r
229       {\r
230         src = r.getStringLike();\r
231       }\r
232       if (sb == null)\r
233       {\r
234         sb = new StringBufferLike(src.newStringBufferLike());\r
235       }\r
236       int rmf = r.matchedFrom();\r
237       for (int ii = pos; ii < rmf; ii++)\r
238       {\r
239         sb.append(src.charAt(ii));\r
240       }\r
241 \r
242       for (ReplaceRule x = rp; x != null; x = x.next)\r
243       {\r
244         x.apply(sb, r);\r
245         if (x instanceof SpecialRule)\r
246         {\r
247           if (x instanceof WantMoreTextReplaceRule\r
248               && want_more_text_enable)\r
249           {\r
250             want_more_text = true;\r
251           }\r
252           else if (x instanceof PushRule)\r
253           {\r
254             RegHolder rh2 = new RegHolder();\r
255             rh2.me = ( (PushRule) x).NewRule;\r
256             rh2.prev = rh;\r
257             rh = rh2;\r
258           }\r
259           else if (x instanceof PopRule)\r
260           {\r
261             if (rh.prev != null)\r
262             {\r
263               rh = rh.prev;\r
264             }\r
265           }\r
266           else if (x instanceof ChangeRule)\r
267           {\r
268             rh.me = ( (ChangeRule) x).NewRule;\r
269           }\r
270         }\r
271       }\r
272       if (!want_more_text)\r
273       {\r
274         pos = r.matchedTo();\r
275       }\r
276     }\r
277   }\r
278 \r
279   boolean want_more_text = false, want_more_text_enable = false;\r
280   public boolean WantMoreText()\r
281   {\r
282     return want_more_text;\r
283   }\r
284 \r
285   /** Another form of apply, it is the same as\r
286       apply(r,r.getReplaceRule()). */\r
287   public void apply(Regex r)\r
288   {\r
289     apply(r, r.getReplaceRule());\r
290   }\r
291 \r
292   /** This finishes the replacement, appending the right() part of\r
293       the last RegRes given to substitute(RegRes).  After this method\r
294       is called, the Replace object is reset to perform another\r
295       substitution. If no RegRes objects with a true didMatch are\r
296       applied, this returns null. */\r
297   public StringLike finish()\r
298   {\r
299     if (src == null)\r
300     {\r
301       return null;\r
302     }\r
303     //sb.append(src.substring(pos,src.length()));\r
304     int s_end = src.length();\r
305     for (int ii = pos; ii < s_end; ii++)\r
306     {\r
307       sb.append(src.charAt(ii));\r
308     }\r
309     src = null;\r
310     lastMatchedTo = pos;\r
311     pos = 0;\r
312     StringLike retstr = sb.toStringLike();\r
313     sb = null;\r
314     return retstr;\r
315   }\r
316 \r
317   int lastMatchedTo = 0;\r
318   public Object clone()\r
319   {\r
320     Replacer r = new Replacer();\r
321     r.first = first;\r
322     r.src = src;\r
323     r.sb = sb;\r
324     r.pos = pos;\r
325     r.lastMatchedTo = lastMatchedTo;\r
326     r.want_more_text = want_more_text;\r
327     r.want_more_text_enable = want_more_text_enable;\r
328     r.rh.me = rh.me;\r
329     r.rh.prev = rh.prev;\r
330     return r;\r
331   }\r
332 \r
333   public int lastMatchedTo()\r
334   {\r
335     return lastMatchedTo;\r
336   }\r
337 \r
338   public Regex getRegex()\r
339   {\r
340     return rh.me;\r
341   }\r
342 \r
343   public void setSource(StringLike sl)\r
344   {\r
345     src = sl;\r
346   }\r
347 \r
348   public void setBuffer(StringBufferLike sbl)\r
349   {\r
350     sb = sbl;\r
351   }\r
352 \r
353   public void setPos(int pos)\r
354   {\r
355     this.pos = pos;\r
356   }\r
357 }\r