001: /**
002: * This file defines a class which implements the search
003: * and replace functionallity for a text.
004: * @author Dmytro Podalyuk, Matthias Buechler
005: */package org.columba.core.util;
006:
007: import java.util.regex.*;
008:
009: public class FindReplace {
010:
011: private Matcher m;
012: private Pattern p;
013: private boolean isFound; // is true if the last search was successful
014: private int lastfoundposition; // a position of the word after the last search ivokation; -1 if nothing found
015: private int lastreplaceposition; // a position of the word after the last replace ivokation; -1 if nothing was replaced
016:
017: private StringBuffer sb = null; //intern variable which is used for text replace purposes
018:
019: private String pattern; // text which we are looking for, or want to replace
020: private String replaceWith; // replaced text which we want to have
021: private String source; // text where we make a search
022: private boolean casesensitive; // search/replace is case sensitive
023: private boolean matchwholeword; // search/replace matches whole words only
024: private boolean backwards; // search/replace works backwards on the text
025:
026: private boolean processing = false; // false if search/replace is currently working
027:
028: public FindReplace() { // constructor for the class
029: pattern = new String();
030: source = new String();
031: replaceWith = new String();
032: casesensitive = false;
033: matchwholeword = false;
034: backwards = false;
035:
036: isFound = false;
037: lastreplaceposition = lastfoundposition = -1;
038:
039: m = null;
040: p = null;
041: }
042:
043: public FindReplace(String source, String pattern) { // some other version of the constructor
044: this .pattern = pattern;
045: this .source = source;
046: this .replaceWith = new String();
047:
048: casesensitive = false;
049: matchwholeword = false;
050: backwards = false;
051:
052: isFound = false;
053: lastreplaceposition = lastfoundposition = -1;
054: m = null;
055: p = null;
056: }
057:
058: public FindReplace(String source, String pattern, String replaceWith) { // some other version of the constructor
059: this .pattern = pattern;
060: this .source = source;
061: this .replaceWith = replaceWith;
062: casesensitive = false;
063: matchwholeword = false;
064: backwards = false;
065:
066: isFound = false;
067: lastreplaceposition = lastfoundposition = -1;
068: m = null;
069: p = null;
070: }
071:
072: public void setSource(String source) {
073: this .source = source;
074: }
075:
076: public String getSource() {
077: return this .source;
078: }
079:
080: public void setPattern(String pattern) {
081: this .pattern = pattern;
082: }
083:
084: public String getPattern() {
085: return this .pattern;
086: }
087:
088: public void setReplaceWith(String replaceWith) {
089: this .replaceWith = replaceWith;
090: }
091:
092: public String getReplaceWith() {
093: return this .replaceWith;
094: }
095:
096: public void setCaseSensitive(boolean state) {
097: this .casesensitive = state;
098: }
099:
100: public boolean getCaseSensitive() {
101: return this .casesensitive;
102: }
103:
104: public void setMatchWholeWord(boolean state) {
105: this .matchwholeword = state;
106: }
107:
108: public boolean getMatchWholeWord() {
109: return this .matchwholeword;
110: }
111:
112: public void setBackwards(boolean state) {
113: this .backwards = state;
114: if (state && isFound) {
115: lastfoundposition = source.length() - lastfoundposition;
116: //if (lastreplaceposition != -1) lastreplaceposition = source.length() - lastreplaceposition;
117: }
118:
119: }
120:
121: public boolean getBackwards() {
122: return this .backwards;
123: }
124:
125: // need to be called before search/replace to set up all the states we need
126: private void begin() {
127: if (!processing) {
128: String source = this .source;
129: String pattern = this .pattern;
130:
131: // find backwards
132: if (backwards) {
133: source = new StringBuffer(source).reverse().toString();
134: pattern = new StringBuffer(pattern).reverse()
135: .toString();
136: replaceWith = new StringBuffer(replaceWith).reverse()
137: .toString();
138: }
139:
140: // match whole word
141: if (matchwholeword) {
142: // create pattern
143: pattern = "\\b" + pattern + "\\b";
144: }
145:
146: if (!casesensitive)
147: p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
148: else
149: p = Pattern.compile(pattern);
150:
151: m = p.matcher(source);
152: processing = true;
153: }
154: }
155:
156: // need to be called after search/replace to make some changes in the states
157: private void end() {
158: if (processing) {
159: if (isFound) {
160: if (backwards) {
161: lastfoundposition = source.length() - m.end();
162: //lastreplaceposition = lastfoundposition;
163:
164: replaceWith = new StringBuffer(replaceWith)
165: .reverse().toString();
166:
167: if (sb != null) {
168: source = sb.reverse().toString();
169: sb = null;
170: } else
171: source = new StringBuffer(m.toString())
172: .reverse().toString();
173:
174: } else {
175: lastfoundposition = m.start();
176: //lastreplaceposition = lastfoundposition; //+ replaceWith.length();
177:
178: if (sb != null) {
179: source = sb.toString();
180: sb = null;
181: } else
182: source = m.toString();
183: }
184:
185: } else
186: lastfoundposition = -1;
187: processing = false;
188: }
189: }
190:
191: // the implementation of the search function. It returns always the position of the FIRST found word.
192: public int find() {
193: begin();
194: isFound = m.find(0);
195: end();
196: return lastfoundposition;
197: }
198:
199: // the implementation of the search next function. It returns always the position of the NEXT found word.
200: public int findnext() {
201: // end of text was reached -> begin at the start
202: begin();
203: if (!isFound)
204: find();
205: else
206: isFound = m.find(backwards ? lastfoundposition
207: : lastfoundposition + 1);
208: end();
209: lastreplaceposition = -1;
210: return lastfoundposition;
211: }
212:
213: // the implementation of the replace function. It returns always the position of the NEXT replaced word.
214: public int replace() {
215: begin();
216: //if (lastfoundposition == -1 || lastreplaceposition == -1) {lastreplaceposition = lastfoundposition = 0;}
217:
218: if (lastfoundposition == -1)
219: lastfoundposition = 0;
220:
221: if (lastreplaceposition == -1 && backwards) {
222: lastreplaceposition = lastfoundposition - pattern.length();
223: if (lastreplaceposition < 0)
224: lastreplaceposition = 0;
225: }
226:
227: if (lastreplaceposition == -1 && !backwards)
228: lastreplaceposition = lastfoundposition;
229: if (lastreplaceposition == -2 && backwards)
230: lastreplaceposition = lastfoundposition;
231: if (lastreplaceposition == -2 && !backwards)
232: lastreplaceposition = lastfoundposition
233: + replaceWith.length();
234:
235: isFound = m.find(lastreplaceposition);
236: if (isFound) {
237: sb = new StringBuffer();
238:
239: m.appendReplacement(sb, replaceWith);
240: m.appendTail(sb);
241: lastreplaceposition = -2;
242: } else
243: lastreplaceposition = -1;
244:
245: end();
246: return lastfoundposition;
247: }
248:
249: // the implementation of the replace all function.
250: public void replaceAll() {
251: begin();
252: String source = m.replaceAll(replaceWith);
253: if (source != null)
254: if (backwards)
255: this .source = new StringBuffer(source).reverse()
256: .toString();
257: else
258: this .source = source;
259: isFound = false;
260: end();
261: }
262: }
|