/*
* Copyright 2008 Folke Behrens (fb at toxis. com)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.horaz.client.util;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.google.gwt.core.client.JavaScriptObject;
/**
* Wrapper for the RegExp JavaScript object. Can be passed as parameter to JSNI
* methods. Almost all of its methods get inlined. No extra weight.
* <p>
* RegExp literals like /abc/ are not possible. For this we need a Generator
* that can except parameters which is currently not possible with GWT.
*
* @author Folke Behrens (fb at toxis. com)
* @version 1.0
*/
/*
* Please leave the JSNI opening tag "/*-{" on its own line to workaround a bug
* in Eclipse' formatter.
*/
public final class RegExp extends JavaScriptObject {
/**
* Wraps the result of any RegExp operation which is either an object or an
* array of strings. Use the accessor methods, or use the iterator, or
* <code>cast()</code> it to JsArrayString to access the matched strings.
*/
public static final class Result extends JavaScriptObject {
public class IterableIterator implements Iterable<String>, Iterator<String> {
private int index = 0;
@Override
public boolean hasNext() {
return index < length();
}
@Override
public Iterator<String> iterator() {
return this;
}
@Override
public String next() {
if (index == length())
throw new NoSuchElementException();
assert index < length() : index + " > " + length();
return get(index++);
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
protected Result() {
}
/**
* Depending on the global ('g') flag this either returns a 0-indexed match
* or 1-indexed submatch.
*
* @param num
* @return match (0-based index) or submatch (1-based index)
*/
public native String get(int num)
/*-{
return this[num];
}-*/;
/**
* @return The index of the match. Always <code>0</code> in global matching
* mode.
*/
public native int index()
/*-{
return this.index || 0;
}-*/;
/**
* @return The input string. Always <code>null</code> in global matching
* mode.
*/
public native String input()
/*-{
return this.input || null;
}-*/;
/**
* Returns an Iterator which is also Iterable and can be used in foreach
* loops. This is because JavaScriptObject cannot implement interfaces. :-(
*/
public IterableIterator iterator() {
return new IterableIterator();
}
/**
* @return the number of matches.
*/
public native int length()
/*-{
return this.length;
}-*/;
/**
* @return the matched string.
*/
public native String match()
/*-{
return this[0];
}-*/;
public String[] toArray() {
return toArray(new String[length()]);
}
/**
* Copies the matches into <code>stringArray</code>.
*
* @param stringArray
* @return stringArray
*/
public String[] toArray(String[] stringArray) {
for (int i = 0; i < length(); ++i) {
stringArray[i] = this.get(i);
}
return stringArray;
}
}
/**
* Factory method for RegExp object.
*
* @param pattern
* @return the newly created RegExp object
*/
public static native RegExp create(String pattern)
/*-{
return new RegExp(pattern);
}-*/;
/**
* Factory method for RegExp object.
*
* @param pattern
* @param flags Any combination of <code>'g'</code>, <code>'m'</code>, and
* <code>'i'</code>, and some browser-specific flags like
* <code>'y'</code>.
* @return the newly created RegExp object
*/
public static native RegExp create(String pattern, String flags)
/*-{
return new RegExp(pattern, flags);
}-*/;
protected RegExp() {
}
/**
* @param str
* @return result
*/
public native Result exec(String str)
/*-{
return this.exec(str);
}-*/;
/**
* @return the index following the end of the last match
*/
public native int getLastIndex()
/*-{
return this.lastIndex || 0;
}-*/;
/**
* @return the pattern without surrounding quotes or slashes
*/
public native String getSource()
/*-{
return this.source || null;
}-*/;
/**
* @return true if 'g' flag is set.
*/
public native boolean isGlobal()
/*-{
return this.global || false;
}-*/;
/**
* @return true if 'i' flag is set.
*/
public native boolean isIgnoringCase()
/*-{
return this.ignoreCase || false;
}-*/;
/**
* @return true if 'm' flag is set.
*/
public native boolean isMultiline()
/*-{
return this.multiline || false;
}-*/;
/**
* @return true if 'y' flag is set. This is currently only supported by
* Firefox 3.
*/
public native boolean isSticky()
/*-{
return this.sticky || false;
}-*/;
/**
* @param str
* @return result
*/
public native Result match(String str)
/*-{
return str.match(this);
}-*/;
/**
* @param str
* @param replacement
* @return result
*/
public native String replace(String str, String replacement)
/*-{
return str.replace(this, replacement);
}-*/;
/**
* @param str
* @return the index of the match inside <code>str</code>. Otherwise, it
* returns -1.
*/
public native int search(String str)
/*-{
return str.search(this);
}-*/;
/**
* @param lastIndex
*/
public native void setLastIndex(int lastIndex)
/*-{
this.lastIndex = lastIndex;
}-*/;
/**
* @param str
* @return result
*/
public native Result split(String str)
/*-{
return str.split(this);
}-*/;
/**
* This split() is different from java.lang.String.split(). The limit is
* applies after the complete string is split.
*
* @param str
* @param limit
* @return result
*/
public native Result split(String str, int limit)
/*-{
return str.split(this, limit);
}-*/;
/**
* This method tests if a string matches the specified pattern.
*
* @param str the string to be tested
* @return true if <code>text</code> matches the pattern.
*/
public native boolean test(String str)
/*-{
return this.test(str);
}-*/;
}