/*
* $Id: AnyPattern.java,v 1.30 2002/09/16 08:05:02 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.core;
import anvil.core.runtime.AnyFunction;
import anvil.script.Context;
import anvil.script.Function;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Vector;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.MatchResult;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.apache.oro.text.regex.Perl5Substitution;
import org.apache.oro.text.regex.StringSubstitution;
import org.apache.oro.text.regex.Substitution;
import org.apache.oro.text.regex.Util;
/// @class pattern
/// Pattern represents compiled regular expression.
/**
* class AnyPattern
*
* @author Jani Lehtim�ki
*/
public class AnyPattern extends Any
{
/// @constructor pattern
/// Creates regular expression.
/// @synopsis pattern(string pattern)
/// @synopsis pattern(string pattern, string flags)
/// @param pattern Pattern string
/// @param flags String containing zero or more of
/// <b>M</b>ultiline, <b>I</b>gnore case, e<b>X</b>tended
/// @throws MalformedPattern If pattern is invalid
public static final Object[] newInstance = { null, "pattern", "*flags", "" };
public static final Any newInstance(Context context, String pattern, String flags)
{
try {
return new AnyPattern(ObjectPool.createPattern(pattern, flags));
} catch (MalformedPatternException e) {
throw context.MalformedPattern(e.getMessage());
}
}
protected Pattern _pattern;
public static final Any create(String pattern, String flags)
{
try {
return new AnyPattern(ObjectPool.createPattern(pattern, flags));
} catch (MalformedPatternException e) {
return Any.UNDEFINED;
}
}
public AnyPattern(Pattern pattern)
{
_pattern = pattern;
}
public int typeOf()
{
return IS_PATTERN;
}
public boolean isPattern()
{
return true;
}
public final anvil.script.ClassType classOf() {
return __class__;
}
public boolean toBoolean()
{
return true;
}
public String getPattern()
{
return _pattern.getPattern();
}
public String getFlags()
{
StringBuffer buffer = new StringBuffer();
int options = _pattern.getOptions();
if ((options & Perl5Compiler.CASE_INSENSITIVE_MASK) != 0) {
buffer.append('i');
}
if ((options & Perl5Compiler.MULTILINE_MASK) != 0) {
buffer.append('m');
}
if ((options & Perl5Compiler.EXTENDED_MASK) != 0) {
buffer.append('x');
}
return buffer.toString();
}
public String toString()
{
String pattern = _pattern.getPattern();
StringBuffer buffer = new StringBuffer(pattern.length() + 5);
buffer.append('/');
buffer.append(pattern);
buffer.append('/');
buffer.append(getFlags());
return buffer.toString();
}
public Writer toAnvil(Writer writer) throws IOException
{
writer.write('/');
writer.write(_pattern.getPattern());
writer.write('/');
writer.write(getFlags());
return writer;
}
public Writer toJava(Writer writer) throws IOException
{
writer.write("anvil.core.AnyPattern.create(\"");
writer.write(anvil.util.Conversions.escape(_pattern.getPattern(), true));
writer.write("\", \"");
writer.write(getFlags());
writer.write('\"');
writer.write(')');
return writer;
}
public anvil.codec.Code toCode(anvil.codec.Code code)
{
anvil.codec.ConstantPool pool = code.getPool();
code.astring(_pattern.getPattern());
code.astring(getFlags());
code.invokestatic(code.getPool().addMethodRef("anvil/core/AnyPattern",
"create", "(Ljava/lang/String;Ljava/lang/String;)Lanvil/core/Any;"));
return code;
}
public Object toObject()
{
return _pattern;
}
public Pattern toPattern()
{
return _pattern;
}
public int hashCode()
{
return _pattern.hashCode();
}
public boolean equals(Object obj)
{
if (this == obj) {
return true;
}
if (obj instanceof AnyPattern) {
return _pattern.equals(((AnyPattern)obj)._pattern);
}
return false;
}
public int compare(Any other)
{
Pattern pattern = other.toPattern();
return _pattern.getPattern().compareTo(pattern.toString());
}
public void serialize(Serializer serializer) throws IOException
{
if (serializer.register(this)) {
return;
}
String s = _pattern.getPattern();
serializer.write('p');
int options = _pattern.getOptions();
if ((options & Perl5Compiler.CASE_INSENSITIVE_MASK) != 0) {
serializer.write('i');
}
if ((options & Perl5Compiler.MULTILINE_MASK) != 0) {
serializer.write('m');
}
if ((options & Perl5Compiler.EXTENDED_MASK) != 0) {
serializer.write('x');
}
serializer.write(':');
serializer.write(s.length());
serializer.write(':');
serializer.writeUTF16(s);
}
public static final Any unserialize(Unserializer unserializer)
throws UnserializationException
{
StringBuffer flags = new StringBuffer(3);
out: while(true) {
int ch = unserializer.get();
switch(ch) {
case ':':
break out;
case (byte)'i':
flags.append('i');
break;
case (byte)'m':
flags.append('m');
break;
case (byte)'x':
flags.append('x');
break;
}
}
String image = unserializer.getUTF16String();
Any pattern = Any.NULL;
try {
pattern = new AnyPattern(ObjectPool.createPattern(image, flags.toString()));
} catch (MalformedPatternException e) {
throw unserializer.getContext().CorruptedSerialization(e.getMessage());
}
unserializer.register(pattern);
return pattern;
}
public Any execute(Context context, Any[] parameters)
{
if (parameters.length > 0) {
return execute(context, parameters[0]);
}
return FALSE;
}
public Any execute(Context context)
{
return FALSE;
}
public Any execute(Context context, Any param1)
{
Perl5Matcher matcher = new Perl5Matcher();
return matcher.contains(param1.toString(), _pattern) ? TRUE : FALSE;
}
public Any execute(Context context, Any param1, Any param2)
{
return execute(context, param1);
}
public Any execute(Context context, Any param1, Any param2, Any param3)
{
return execute(context, param1);
}
public Any execute(Context context, Any param1, Any param2, Any param3, Any param4)
{
return execute(context, param1);
}
/********* Exposed methods ************/
private Any doMatch(Context context, String string, Any matches_, boolean isMatch)
{
Array array = null;
AnyList list = null;
if (matches_ != null) {
array = matches_.toArray();
if (matches_ instanceof AnyList) {
list = (AnyList)matches_;
}
}
Perl5Matcher matcher = new Perl5Matcher();
if (isMatch ? matcher.matches(string, _pattern)
: matcher.contains(string, _pattern))
{
if (array != null) {
MatchResult match = matcher.getMatch();
array.clear();
int n = match.groups();
for(int i=0; i<n; i++) {
array.append(Any.create(match.group(i)));
}
return array;
} else if (list != null) {
MatchResult match = matcher.getMatch();
list.clear();
int n = match.groups();
for(int i=0; i<n; i++) {
list.append(Any.create(match.group(i)));
}
return list;
}
return TRUE;
} else {
return FALSE;
}
}
/// @method matches
/// Checks is given string matches this pattern
/// @synopsis object matches(string text)
/// @synopsis object matches(string text, list matches)
/// @synopsis object matches(string text, array matches)
/// @returns Matches or boolean
public static final Object[] p_matches = new Object[] { null, "str", "*matches", null };
public Any m_matches(Context context, String str, Any matches)
{
return doMatch(context, str, matches, true);
}
/// @method contains
/// Checks is given string (partially) matches this pattern
/// @synopsis object contains(string text)
/// @synopsis object contains(string text, list matches)
/// @synopsis object contains(string text, array matches)
/// @returns Matches or boolean
public static final Object[] p_contains = new Object[] { null, "str", "*matches", null };
public Any m_contains(Context context, String str, Any matches)
{
return doMatch(context, str, matches, false);
}
/// @method split
/// Splits given text to pieces according to this pattern.
/// @synopsis array split(string text)
public static final Object[] p_split = new Object[] { "text" };
public Any m_split(String string)
{
Perl5Matcher matcher = new Perl5Matcher();
Vector parts = Util.split(matcher, _pattern, string);
Array array = new Array();
int n = parts.size();
for(int i=0; i<n; i++) {
array.append(Any.create(parts.elementAt(i).toString()));
}
return array;
}
private Any doSubstitute(Context context, String string, Any replacement, int substFlags)
{
Substitution substitution;
if (replacement.isString()) {
String s = replacement.toString();
if (s.indexOf('$') != -1) {
substitution = new Perl5Substitution(s);
} else {
substitution = new StringSubstitution(s);
}
} else {
substitution = new AnyUtils.FunctionSubstitute(context, replacement);
}
Perl5Matcher matcher = new Perl5Matcher();
return Any.create(Util.substitute(matcher, _pattern, substitution, string, substFlags));
}
/// @method substitute
/// Substitutes regions from string matching this pattern with
/// given substitution.
/// @synopsis string substitute(string text, string substition)
/// @synopsis string substitute(string text, function substituter)
/// @synopsis string substitute(string text, string substition, int amount)
/// @synopsis string substitute(string text, function substituter, int amount)
/// @param Amount of occurences to subsitutute, if omitted all occurences
/// are replaced
public static final Object[] p_substitute = new Object[] { null, "str", "substitution", "*amount", null };
public Any m_substitute(Context context, String text, Any substitution, Any amount)
{
int flags;
if (amount != null) {
flags = amount.toInt();
} else {
flags = Util.SUBSTITUTE_ALL;
}
return doSubstitute(context, text, substitution, flags);
}
/// @method substituteFirst
/// Substitutes first region from string matching this pattern.
/// @synopsis string substituteFirst(string text, string substition)
/// @synopsis string substituteFirst(string text, function substituter)
public static final Object[] p_substituteFirst = new Object[] { null, "str", "substitution" };
public Any m_substituteFirst(Context context, String text, Any substitution)
{
return doSubstitute(context, text, substitution, 1);
}
/// @method find
/// Finds all occurences from given string matching this pattern.
/// @synopsis enumeration find(string text)
public static final Object[] p_find = new Object[] { "str" };
public Any m_find(String text)
{
return new AnyBindingEnumeration(
new AnyUtils.StringPatternMatcher(_pattern, text));
}
transient public static final anvil.script.compiler.NativeClass __class__ =
new anvil.script.compiler.NativeClass("pattern", AnyPattern.class,
//DOC{{
""+
" @class pattern\n" +
" Pattern represents compiled regular expression.\n" +
" @constructor pattern\n" +
" Creates regular expression.\n" +
" @synopsis pattern(string pattern)\n" +
" @synopsis pattern(string pattern, string flags)\n" +
" @param pattern Pattern string\n" +
" @param flags String containing zero or more of \n" +
" <b>M</b>ultiline, <b>I</b>gnore case, e<b>X</b>tended\n" +
" @throws MalformedPattern If pattern is invalid\n" +
" @method matches\n" +
" Checks is given string matches this pattern\n" +
" @synopsis object matches(string text)\n" +
" @synopsis object matches(string text, list matches)\n" +
" @synopsis object matches(string text, array matches)\n" +
" @returns Matches or boolean\n" +
" @method contains\n" +
" Checks is given string (partially) matches this pattern\n" +
" @synopsis object contains(string text)\n" +
" @synopsis object contains(string text, list matches)\n" +
" @synopsis object contains(string text, array matches)\n" +
" @returns Matches or boolean\n" +
" @method split\n" +
" Splits given text to pieces according to this pattern.\n" +
" @synopsis array split(string text)\n" +
" @method substitute\n" +
" Substitutes regions from string matching this pattern with\n" +
" given substitution.\n" +
" @synopsis string substitute(string text, string substition)\n" +
" @synopsis string substitute(string text, function substituter)\n" +
" @synopsis string substitute(string text, string substition, int amount)\n" +
" @synopsis string substitute(string text, function substituter, int amount)\n" +
" @param Amount of occurences to subsitutute, if omitted all occurences\n" +
" are replaced\n" +
" @method substituteFirst\n" +
" Substitutes first region from string matching this pattern.\n" +
" @synopsis string substituteFirst(string text, string substition)\n" +
" @synopsis string substituteFirst(string text, function substituter)\n" +
" @method find\n" +
" Finds all occurences from given string matching this pattern.\n" +
" @synopsis enumeration find(string text)\n"
//}}DOC
);
}