001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.openide.util;
042:
043: import java.util.*;
044:
045: /** Implementation of translate regular expression methods.
046: * Works on 1.3 though we could use 1.4's java.util.regex - this is faster anyway.
047: * @author Jaroslav Tulach
048: */
049: final class RE13 implements Utilities.RE {
050: /** root of the match automata */
051: private Object[] root;
052:
053: /** list of strings to convert to */
054: private String[] results;
055:
056: /** Parses line of text to two parts: the key and the rest
057: */
058: public String[] readPair(String line) {
059: int indx = line.indexOf('#');
060:
061: if (indx != -1) {
062: line = line.substring(0, indx).trim();
063: }
064:
065: indx = line.indexOf('=');
066:
067: if (indx == -1) {
068: indx = line.indexOf(' ');
069: }
070:
071: if (indx == -1) {
072: return null;
073: }
074:
075: return new String[] { line.substring(0, indx).trim(),
076: line.substring(indx + 1).trim() };
077: }
078:
079: public String convert(String pattern) {
080: Object[] item = root;
081: int resIndex = -1;
082: int resLength = 0;
083:
084: int lenOfPattern = 0;
085: int indx = 0;
086: ALL: for (;;) {
087: if (item.length == 0) {
088: break;
089: }
090:
091: // update the result if this item represents a result
092: Object last = item[item.length - 1];
093:
094: if (last instanceof Integer) {
095: // remember the number
096: resIndex = ((Integer) last).intValue();
097: resLength += lenOfPattern;
098: lenOfPattern = 0;
099: }
100:
101: if (indx >= pattern.length()) {
102: // no next text to compare, stop the search
103: break;
104: }
105:
106: char f = pattern.charAt(indx++);
107:
108: // find next suitable item
109: for (int i = 0; i < item.length; i++) {
110: if (item[i] instanceof String
111: && (((String) item[i]).charAt(0) == f)) {
112: // we have found the branch to possibly follow, now check
113: String s = (String) item[i];
114:
115: for (int j = 1; j < s.length(); j++, indx++) {
116: if ((pattern.length() <= indx)
117: || (pattern.charAt(indx) != s.charAt(j))) {
118: // well this is not the right path and there is
119: // no better => evaluate in this node
120: break ALL;
121: }
122: }
123:
124: // ok, correct convert path
125: item = (Object[]) item[i + 1];
126: lenOfPattern += s.length();
127:
128: continue ALL;
129: }
130: }
131:
132: // no suitable continuation found, if this is end tree item
133: // do convertion
134: break;
135: }
136:
137: if (resIndex != -1) {
138: // do the conversion
139: return results[resIndex] + pattern.substring(resLength);
140: } else {
141: // no conversion
142: return pattern;
143: }
144: }
145:
146: /** Data structure to needed to store the */
147: public void init(String[] original, String[] newversion) {
148: ArrayList<Object> root = new ArrayList<Object>();
149:
150: for (int i = 0; i < original.length; i++) {
151: placeString(root, original[i], i);
152: }
153:
154: this .root = compress(root);
155: this .results = newversion;
156: }
157:
158: /** Places a string to the graph of other strings.
159: * @param item list to add the string to
160: * @param s string to place there
161: * @param indx index to put at the end node
162: */
163: private static void placeString(List<Object> item, String s,
164: int indx) {
165: if (s.length() == 0) {
166: item.add(new Integer(indx));
167:
168: return;
169: }
170:
171: char f = s.charAt(0);
172:
173: ListIterator<Object> it = item.listIterator();
174:
175: while (it.hasNext()) {
176: Object o = it.next();
177:
178: if (o instanceof String) {
179: // could be also Integer or array
180: String pref = (String) o;
181:
182: if (f == pref.charAt(0)) {
183: // find the first difference
184: for (int i = 1; i < pref.length(); i++) {
185: if ((i >= s.length())
186: || (s.charAt(i) != pref.charAt(i))) {
187: // split in the i-th index
188: it.set(pref.substring(0, i));
189:
190: // next is the list or null
191: List listForPref = (List) it.next();
192:
193: ArrayList<Object> switchList = new ArrayList<Object>();
194: it.set(switchList);
195:
196: switchList.add(pref.substring(i));
197: switchList.add(listForPref);
198:
199: if (i >= s.length()) {
200: switchList.add(new Integer(indx));
201: } else {
202: ArrayList<Object> terminalList = new ArrayList<Object>();
203: terminalList.add(new Integer(indx));
204:
205: switchList.add(s.substring(i));
206: switchList.add(terminalList);
207: }
208:
209: return;
210: }
211: }
212:
213: //
214: // the new string is longer than the existing recursive add
215: //
216: List<Object> switchList = nextList(it);
217: placeString(switchList, s.substring(pref.length()),
218: indx);
219:
220: return;
221: }
222: }
223: }
224:
225: //
226: // ok new prefix in this item
227: //
228: ArrayList<Object> id = new ArrayList<Object>();
229: id.add(new Integer(indx));
230:
231: item.add(s);
232: item.add(id);
233: }
234:
235: @SuppressWarnings("unchecked")
236: private static List<Object> nextList(final ListIterator<Object> it) {
237: List<Object> switchList = (List<Object>) it.next();
238: return switchList;
239: }
240:
241: /** Compress tree of Lists into tree of Objects.
242: */
243: private static Object[] compress(List item) {
244: Object[] arr = new Object[item.size()];
245:
246: Integer last = null;
247:
248: Iterator it = item.iterator();
249: int i = 0;
250:
251: while (it.hasNext()) {
252: Object o = it.next();
253:
254: if (o instanceof Integer) {
255: if (last != null) {
256: throw new IllegalStateException();
257: }
258:
259: last = (Integer) o;
260:
261: continue;
262: }
263:
264: if (o instanceof String) {
265: arr[i++] = ((String) o).intern();
266:
267: continue;
268: }
269:
270: if (o instanceof List) {
271: arr[i++] = compress((List) o);
272:
273: continue;
274: }
275:
276: throw new IllegalStateException();
277: }
278:
279: if (last != null) {
280: // assigned integer to this object
281: arr[arr.length - 1] = last;
282: }
283:
284: return arr;
285: }
286: }
|