Package org.gocha.text.regex

Source Code of org.gocha.text.regex.Regex

/*******************************************************************************
gocha.org-lib-java Библеотека общего назначения
(с) Камнев Георгий Павлович 2009 GPLv2

Данная программа является свободным программным обеспечением. Вы вправе
распространять ее и/или модифицировать в соответствии с условиями версии 2
либо по вашему выбору с условиями более поздней версии
Стандартной Общественной Лицензии GNU, опубликованной Free Software Foundation.

Мы распространяем данную программу в надежде на то, что она будет вам полезной,
однако НЕ ПРЕДОСТАВЛЯЕМ НА НЕЕ НИКАКИХ ГАРАНТИЙ,
в том числе ГАРАНТИИ ТОВАРНОГО СОСТОЯНИЯ ПРИ ПРОДАЖЕ
и ПРИГОДНОСТИ ДЛЯ ИСПОЛЬЗОВАНИЯ В КОНКРЕТНЫХ ЦЕЛЯХ.
Для получения более подробной информации ознакомьтесь
со Стандартной Общественной Лицензией GNU.

Вместе с данной программой вы должны были получить экземпляр
Стандартной Общественной Лицензии GNU.
Если вы его не получили, сообщите об этом в Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*******************************************************************************/

package org.gocha.text.regex;

import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.gocha.collection.Convertor;
import org.gocha.collection.Iterators;
import org.gocha.collection.NodesExtracter;
import org.gocha.collection.Predicate;
import org.gocha.collection.iterators.TreeWalk;
import org.gocha.collection.iterators.TreeWalkItreator;
import org.gocha.collection.iterators.TreeWalkType;
import org.gocha.files.FileUtil;
import org.gocha.text.TextUtil;
import org.gocha.xml.CustomAttributeSetter;
import org.gocha.xml.CustomChildrenParser;
import org.gocha.xml.XMLDecoder;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Регулярные выражения (РВ).
* В данной реализации основной формой описания РВ является XML.
* <h1>Формат регулярных выражений XML:</h1>
*
* РВ описываються тегами, часть тегов могут быть вложены друг в друга,
* ниже приводится таблица с описанием возможных тегов.
* <br />
* Типы данных в атрибутах:
* <ul>
* <li>
* Тип <b>string</b> - это тип соответствует строке с лбой последовательность символов
* </li>
*
* <li>
* <b>enum</b> - это одно значение из указаных в описании
* </li>
*
* <li>
* <b>int</b> - Указывает на цело число
* </li>
*
* <li>
* <b>bool</b> - Указывает на булево,
* так значение <b>истенно</b> может быть задно следующими выражениями:
* <b>true</b> , <b>on</b> , <b>1</b> , а значение <b>ложно</b> :
* <b>false</b> , <b>off</b> , <b>0</b>
* </li>
*
* </ul>
*
* <table border='0'>
* <tr style='font-weight:bold'>
* <td>Тег</td><td>Атрибут</td><td>Тип</td><td>Описание</td>
* </tr>
*
* <tr style='background-color:#C0D0FF'>
* <td valign="top">text</td><td></td><td valign="top">TextPattern</td>
* <td>Задает последовательность символов.<br/>Вложенные шаблоны не поддерживаются.</td>
* </tr>
*
* <tr>
* <td></td><td>name</td><td>string</td>
* <td>Имя шаблона</td>
* </tr>
*
* <tr>
* <td></td><td>text</td><td>string</td>
* <td>Искомый текст</td>
* </tr>
*
* <tr>
* <td></td><td>ignoreCase</td><td>bool</td>
* <td>Игнорировать регистр (по умолчанию off)</td>
* </tr>
*
* <tr>
* <td></td><td>invert</td><td>bool</td>
* <td>Сравнивать на не совпадение (по умолчанию off)</td>
* </tr>
*
* <tr style='background-color:#C0D0FF'>
* <td valign="top">char</td><td></td><td valign="top">CharGroupPattern</td>
* <td>Символ из символьных групп (цифра,буква...).<br/>Вложенные шаблоны не поддерживаются.</td>
* </tr>
*
* <tr>
* <td></td><td>name</td><td>string</td>
* <td>Имя шаблона</td>
* </tr>
*
* <tr>
* <td></td><td valign='top'>group</td><td valign='top'>enum</td>
* <td>
* Указывает на группу:
* <ul>
* <li>any - Любой символ</li>
* <li>whitespace - Пробельный символ</li>
* <li>uppercase - Символ в верхнем регистре</li>
* <li>spacechar - Пробельный символ</li>
* <li>lowercase - Символ в нижнем регистре</li>
* <li>letter - Буква</li>
* <li>digit - Цифра</li>
* <li>return - Символ возврата каретки - 0x0A, оно же \r</li>
* <li>nextline - Символ перевода строки - 0x0D, оно же \n</li>
* <li>tab - Символ табуляции</li>
* </ul>
* </td>
* </tr>
*
* <tr>
* <td></td><td>invert</td><td>bool</td>
* <td>Сравнивать на не совпадение (по умолчанию off)</td>
* </tr>
*
* <tr style='background-color:#C0D0FF'>
* <td valign="top">bound</td><td></td><td valign="top">TextBoundPattern</td>
* <td>Граница текста.<br/>Вложенные шаблоны не поддерживаются.</td>
* </tr>
*
* <tr>
* <td></td><td>name</td><td>string</td>
* <td>Имя шаблона</td>
* </tr>
*
* <tr>
* <td></td><td valign='top'>bound</td><td valign='top'>enum</td>
* <td>
* <ul>
* <li>word - Граница слова (буква и не буква)</li>
* <li>begin - Начала текста</li>
* <li>end - Конец текста</li>
* </ul>
* </td>
* </tr>
*
* <tr style='background-color:#C0D0FF'>
* <td>sequence</td><td></td><td>SequencePattern</td>
* <td>Последовательность шаблонов</td>
* </tr>
*
* <tr>
* <td></td><td>name</td><td>string</td>
* <td>Имя шаблона</td>
* </tr>
*
* <tr style='background-color:#C0D0FF'>
* <td>or</td><td></td><td>OrPattern</td>
* <td>Различные варианты шаблонов (один из указанных)</td>
* </tr>
*
* <tr>
* <td></td><td>name</td><td>string</td>
* <td>Имя шаблона</td>
* </tr>
*
* <tr style='background-color:#C0D0FF'>
* <td>and</td><td></td><td>AndPattern</td>
* <td>Различные варианты шаблонов (все из указанных)</td>
* </tr>
*
* <tr>
* <td></td><td>name</td><td>string</td>
* <td>Имя шаблона</td>
* </tr>
*
* <tr>
* <td></td><td>selectMax</td><td>bool</td>
* <td>Возвращать максимально длинное совпадение с текстом (по умолчанию on)</td>
* </tr>
*
* <tr>
* <td></td><td>delegateChain</td><td>bool</td>
* <td>Проверять внутри шаблонов на следующий шаблон за AND (по умолчанию on)</td>
* </tr>
*
* <tr style='background-color:#C0D0FF'>
* <td>repeat</td><td></td><td>RepeatPattern</td>
* <td>Повторения шаблона</td>
* </tr>
*
* <tr>
* <td></td><td>name</td><td>string</td>
* <td>Имя шаблона</td>
* </tr>
*
* <tr>
* <td></td><td>greedliy</td><td>bool</td>
* <td>"Жадный" алгоритм (по умолчанию on)</td>
* </tr>
*
* <tr>
* <td></td><td>compromise</td><td>bool</td>
* <td>Искать с учетом последующего шаблона после repeat (по умолчанию on)</td>
* </tr>
*
* <tr>
* <td></td><td>min</td><td>int</td>
* <td>Минимальное кол-во совпадений (-1, нет ограничения, по умолчанию)</td>
* </tr>
*
* <tr>
* <td></td><td>max</td><td>int</td>
* <td>Максимальное кол-во совпадений (-1, нет ограничения, по умолчанию)</td>
* </tr>
*
* </table>
*
* <h2>Пример описания числа:</h2>
* &lt;sequence name='num'&gt;<br />
* &lt;repeat name='sign' min='0' max='1' greedily='on'&gt;<br />
* &lt;text text='-' /&gt;<br />
* &lt;/repeat&gt;<br />
* &lt;repeat name='digit' min='1' max='-1' greedily='on'&gt;<br />
* &lt;char group='digit' /&gt;<br />
* &lt;/repeat&gt;<br />
* &lt;repeat min='0' max='1' greedily='on'&gt;<br />
* &lt;sequence&gt;<br />
* &lt;text name='fpoint' text='.' /&gt;<br />
* &lt;repeat name='digit' min='1' max='-1' greedily='on'&gt;<br />
* &lt;char group='digit' /&gt;<br />
* &lt;/repeat&gt;<br />
* &lt;/sequence&gt;<br />
* &lt;/repeat&gt;<br />
* &lt;/sequence&gt;<br />
*
* @author gocha
*/
public class Regex
{
    public Regex()
    {
    }

    public static Pattern parseWildcard(String wildcard,boolean ignoreCase,char any,char anyRepeat,char escape)
    {
        if (wildcard == null) {
            throw new IllegalArgumentException("wildcard == null");
        }
        if( wildcard.length()<1 )
        {
            throw new IllegalArgumentException("wildcard.length() < 1");
        }

        SequencePattern seq = new SequencePattern();

        String buff = "";
        boolean escp = false;

        for( int i=0; i<wildcard.length(); i++ )
        {
            char c = wildcard.charAt(i);
            if( !escp )
            {
                if( c==any )
                {
                    if( buff.length()>0 )
                    {
                        TextPattern tm = new TextPattern(buff, ignoreCase);
                        seq.add(tm);
                        buff = "";
                    }
                    CharGroupPattern cg = new CharGroupPattern(CharGroupName.ANY);
                    seq.add(cg);
                }else if( c==anyRepeat )
                {
                    if( buff.length()>0 )
                    {
                        TextPattern tm = new TextPattern(buff, ignoreCase);
                        seq.add(tm);
                        buff = "";
                    }
                    CharGroupPattern cg = new CharGroupPattern(CharGroupName.ANY);

//                    OrPattern or = new OrPattern();

                    RepeatPattern rep = new RepeatPattern();
                    rep.setSubPattern(cg);
                    rep.setMin(0);
                    rep.setMax(-1);
                    rep.setGreedily(false);
                    rep.setCompromise(true);

                    seq.add(rep);
                }else if( c==escape )
                {
                    escp = true;
                }else{
                    buff += c;
                }
            }else{
                escp = false;
                buff += c;
            }
        }

        if( buff.length()>0 )
        {
            TextPattern tm = new TextPattern(buff, ignoreCase);
            seq.add(tm);
            buff = "";
        }

        TextBoundPattern endTextBound = new TextBoundPattern(TextBoundName.ENDTEXT);
        seq.add(endTextBound);

        return seq;
    }

    /**
     * Анализирует XML и возвращает шаблон регулярных выражений
     * @param xmlDocument Шаблон в формате XML
     * @return Шаблон регулярных выражений или null, если не получилось создать
     * @see Regex
     */
    public static Pattern parseXML(org.w3c.dom.Document xmlDocument)
    {
        if (xmlDocument == null) {
            throw new IllegalArgumentException("xmlDocument == null");
        }

        XMLDecoder decoder = new XMLDecoder();
        configureXMLDecoder(decoder);

        Object o = decoder.parse(xmlDocument);
        return (o instanceof Pattern) ? (Pattern)o : null;
    }

    /**
     * Анализирует XML и возвращает шаблон регулярных выражений
     * @param xml Шаблон в формате XML
     * @return Шаблон регулярных выражений или null, если не получилось создать
     * @see Regex
     */
    public static Pattern parseXML(org.w3c.dom.Node xml)
    {
        if (xml == null) {
            throw new IllegalArgumentException("xml == null");
        }

        XMLDecoder decoder = new XMLDecoder();
        configureXMLDecoder(decoder);

        Object o = decoder.parse(xml);
        return (o instanceof Pattern) ? (Pattern)o : null;
    }

    /**
     * Анализирует XML и возвращает шаблон регулярных выражений
     * @param xml Шаблон в формате XML
     * @return Шаблон регулярных выражений или null, если не получилось создать
     * @see Regex
     */
    public static Pattern parseXML(String xml) throws IOException, SAXException
    {
        if (xml == null) {           
            throw new IllegalArgumentException("xml == null");
        }

        XMLDecoder decoder = new XMLDecoder();
        configureXMLDecoder(decoder);

        Object o = decoder.parseXML(xml);
        return (o instanceof Pattern) ? (Pattern)o : null;
    }

    private static void configureXMLDecoder(XMLDecoder decoder)
    {
        decoder.putAttributeSetter(CharGroupPattern.class, "group", charGroup);
        decoder.putAttributeSetter(TextBoundPattern.class, "type", boundsAttr);

        decoder.putChildrenParser(RepeatPattern.class, repeatParser(decoder));

        decoder.getTagMap().put("char", CharGroupPattern.class);
        decoder.getTagMap().put("or", OrPattern.class);
        decoder.getTagMap().put("repeat", RepeatPattern.class);
        decoder.getTagMap().put("sequence", SequencePattern.class);
        decoder.getTagMap().put("text", TextPattern.class);
        decoder.getTagMap().put("bound", TextBoundPattern.class);
        decoder.getTagMap().put("and", AndPattern.class);
    }

    /**
     * Анализирует XML заданный в ресурсе и возвращает шаблон регулярных выражений
     * @param resourceName Имя ресурса
     * @return Шаблон регулярных выражений или null, если не получилось создать
     * @see Regex
     */
    public static Pattern parseXMLResource(String resourceName) throws IOException, SAXException
    {
        return parseXMLResource(resourceName, null);
    }

    /**
     * Анализирует XML заданный в ресурсе и возвращает шаблон регулярных выражений
     * @param resourceName Имя ресурса
     * @param cs Кодировка ресурса
     * @return Шаблон регулярных выражений или null, если не получилось создать
     * @see Regex
     */
    public static Pattern parseXMLResource(String resourceName, Charset cs) throws IOException, SAXException
    {
        if (resourceName == null) {
            throw new IllegalArgumentException("resourceName == null");
        }
        if (cs==null) cs = FileUtil.UTF8();
        URL res = Regex.class.getResource(resourceName);
        if( res==null )return null;
        return parseXML( FileUtil.readAllText(res, cs) );
    }

    private static CustomAttributeSetter boundsAttr = new CustomAttributeSetter() {
        @Override
        public void set(Object obj, String attribute, String value) {
            if( !(obj instanceof TextBoundPattern) )return;
            if( attribute==null || value==null )return;
           
            if( attribute.equalsIgnoreCase("name") )
            {
                ((TextBoundPattern)obj).setName(value);
            }

            if( attribute.equalsIgnoreCase("type") )
            {
                if( value.equalsIgnoreCase("word") )
                {
                    ((TextBoundPattern)obj).setTextBoundName(TextBoundName.WORDBREAK);
                }else if( value.equalsIgnoreCase("begin") ){
                    ((TextBoundPattern)obj).setTextBoundName(TextBoundName.BEGINTEXT);
                }else if(
                        value.equalsIgnoreCase("end") ||
                        value.equalsIgnoreCase("eof")
                        ){
                    ((TextBoundPattern)obj).setTextBoundName(TextBoundName.ENDTEXT);
                }
            }
        }
    };

    private static CustomChildrenParser repeatParser(XMLDecoder decoder)
    {
        final XMLDecoder fdecoder = decoder;

        return new CustomChildrenParser() {
            @Override
            public void parse(Object parentObject, Node parentNode) {
                if( parentObject==null || !(parentObject instanceof RepeatPattern) )return;
                if( parentNode==null )return;
                if( !parentNode.hasChildNodes() )return;

                NodeList nl = parentNode.getChildNodes();
                int count = nl.getLength();
    //            int parsed = 0;

                for( int i=0; i<count; i++ )
                {
                    Node n = nl.item(i);
                    if( n==null || !(n instanceof Element) )continue;

                    Object obj = fdecoder.parse(n);
                    if( obj==null )continue;
                    if( obj instanceof Pattern )
                    {
                        ((RepeatPattern)parentObject).setSubPattern((Pattern)obj);
                        break;
                    }
                }
            }
        };
    }

    private static CustomAttributeSetter charGroup = new CustomAttributeSetter() {
        @Override
        public void set(Object obj, String attribute, String value) {
            if( !(obj instanceof CharGroupPattern) )return;
            if( attribute==null || value==null )return;

            if( attribute.equalsIgnoreCase("name") )
            {
                ((CharGroupPattern)obj).setName(value);
            }

            if( attribute.equalsIgnoreCase("group") )
            {
                if( value.equalsIgnoreCase("any") )
                {
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.ANY);
                }else if( value.equalsIgnoreCase("WHITESPACE") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.WHITESPACE);
                }else if( value.equalsIgnoreCase("UPPERCASE") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.UPPERCASE);
                }else if( value.equalsIgnoreCase("SPACECHAR") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.SPACECHAR);
                }else if( value.equalsIgnoreCase("LOWERCASE") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.LOWERCASE);
                }else if( value.equalsIgnoreCase("LETTER") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.LETTER);
                }else if( value.equalsIgnoreCase("DIGIT") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.DIGIT);
                }else if( value.equalsIgnoreCase("RETURN") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.RETURN);
                }else if( value.equalsIgnoreCase("NEXTLINE") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.NEXTLINE);
                }else if( value.equalsIgnoreCase("TAB") ){
                    ((CharGroupPattern)obj).setCharGroup(CharGroupName.TAB);
                }
            }
        }
    };

    public final static NodesExtracter<Matcher,Matcher> matchExtracter = new NodesExtracter<Matcher, Matcher>()
    {
        @Override
        public Iterable<Matcher> extract(Matcher from)
        {
            return from.getChildrenMatchers();
        }
    };

    public final static Convertor<TreeWalk<Matcher>,Matcher> treeWalkConvertor = new Convertor<TreeWalk<Matcher>, Matcher>()
    {
        @Override
        public Matcher convert(TreeWalk<Matcher> from)
        {
            return from.currentNode();
        }
    };

    public static Iterable<TreeWalk<Matcher>> walkTree(Matcher root)
    {
        if (root == null) {
            throw new IllegalArgumentException("root == null");
        }
        Iterable<TreeWalk<Matcher>> itr = TreeWalkItreator.<Matcher>createIterable(root, matchExtracter);
        return itr;
    }

    public static Iterable<Matcher> walkMatchers(Matcher root)
    {
        if (root == null) {
            throw new IllegalArgumentException("root == null");
        }
        Iterable<TreeWalk<Matcher>> itr = walkTree(root);
        Iterable<Matcher> converted = Iterators.<TreeWalk<Matcher>,Matcher>convert(itr, treeWalkConvertor);
        return converted;
    }

    public static String getMatcherName(Matcher m)
    {
        if( m==null )return null;

        Pattern p = m.getPattern();
        String n = p!=null ? p.name() : null;
        return n;
    }

    public static Matcher getFirstNamedMatcher(Matcher root, String name)
    {
        if (root == null) {
            throw new IllegalArgumentException("root == null");
        }

        if (name == null) {
            throw new IllegalArgumentException("name == null");
        }

        for( Matcher m : walkMatchers(root) )
        {
            String mn = getMatcherName(m);
            if( mn==null )continue;
            if( mn.equals(name) )return m;
        }

        return null;
    }

    public static Iterable<Matcher> getMatchers(Matcher root, Predicate<Matcher> matcherPredicate)
    {
        if (root == null) {
            throw new IllegalArgumentException("root == null");
        }
        if (matcherPredicate == null) {
            throw new IllegalArgumentException("matcherPredicate == null");
        }

        ArrayList<Matcher> result = new ArrayList<Matcher>();

        for( Matcher m : walkMatchers(root) )
        {
            if( m==null )continue;
            if( matcherPredicate.validate(m) )
            {
                result.add(m);
            }
        }

        return result;
    }

    public static Iterable<Matcher> getNamedMatchers(Matcher root, String name)
    {
        if (root == null) {
            throw new IllegalArgumentException("root == null");
        }
        if (name == null) {
            throw new IllegalArgumentException("name == null");
        }

        ArrayList<Matcher> result = new ArrayList<Matcher>();

        for( Matcher m : walkMatchers(root) )
        {
            String mn = getMatcherName(m);
            if( mn==null )continue;
            if( mn.equals(name) )
            {
                result.add(m);
            }
        }

        return result;
    }

    public static Map<String,List<Matcher>> getNamedMatchersMap(Matcher root)
    {
        if (root == null) {
            throw new IllegalArgumentException("root == null");
        }

        Map<String,List<Matcher>> result = new TreeMap<String, List<Matcher>>();

        for( Matcher m : walkMatchers(root) )
        {
            if( m==null )continue;

            String name = getMatcherName(m);
            if( name==null )continue;

            List<Matcher> l = null;
            if( result.containsKey(name) )
            {
                l = result.get(name);
            }
            if( l==null )
            {
                l = new ArrayList<Matcher>();
                result.put(name, l);
            }
            l.add(m);
        }

        return result;
    }

    public static String getNamedMatchersString(Matcher root, String name, String delimiter)
    {
        if (name == null) {
            throw new IllegalArgumentException("name == null");
        }

        StringBuilder sb = new StringBuilder();

        int co = -1;
        for( Matcher m : getNamedMatchers(root, name) )
        {
            if( m==null )continue;
            if( !m.isMatched() )continue;

            String mtext = m.getMatchedText();
            if( mtext==null )continue;

            co++;
            if( co>0 && delimiter!=null )sb.append(delimiter);
            sb.append(mtext);
        }

        return sb.toString();
    }

    public static Predicate<Matcher> matcherNameWildcard(String mask,boolean ignoreCase,char any,char anyRepeat,char escape)
    {
        if (mask == null) {
            throw new IllegalArgumentException("mask == null");
        }

        final Pattern ptrn = parseWildcard(mask, ignoreCase, any, anyRepeat, escape);

        if( ptrn==null )
            throw new IllegalArgumentException(
                    "can't create pattern of wildcard = "+ TextUtil.encodeStringConstant(mask));

        return new Predicate<Matcher>()
        {
            @Override
            public boolean validate(Matcher value)
            {
                if( value==null )return false;
                Pattern p = value.getPattern();
                String n = p==null ? null : p.name();
                if( n==null )return false;
                Matcher m = ptrn.match(n, 0);
                return m==null ? false : m.isMatched();
            }
        };
    }

    public static Predicate<Matcher> matcherNameWildcard(String mask,boolean ignoreCase)
    {
        if (mask == null) {
            throw new IllegalArgumentException("mask == null");
        }

        return matcherNameWildcard(mask, ignoreCase, '?', '*', '\\');
    }

    public static Predicate<Matcher> matcherNameWildcard(String mask)
    {
        if (mask == null) {
            throw new IllegalArgumentException("mask == null");
        }

        return matcherNameWildcard(mask, true, '?', '*', '\\');
    }

    private static NodesExtracter<Matcher,Matcher> resultView = new NodesExtracter<Matcher,Matcher>() {
        @Override
        public Iterable<Matcher> extract(Matcher from)
        {
            return from.getChildrenMatchers();
        }
    };

    public static void print(Matcher m)
    {
        if (m == null) {
            throw new IllegalArgumentException("m == null");
        }

        Iterable<TreeWalk<Matcher>> itr =
        TreeWalkItreator.<Matcher>createIterable(m, resultView,TreeWalkType.ByBranchForward);

        for( TreeWalk<Matcher> twm : itr )
        {
            print(twm);
        }
    }

    public static void print(TreeWalk<Matcher> twm)
    {
        if (twm == null) {
            throw new IllegalArgumentException("twm == null");
        }

        Matcher m = twm.currentNode();
        int l = twm.currentLevel();
        if( l<0 )l=0;
        String spacer = "";
        for( int i=0; i<l; i++ )
        {
            spacer += "....";
        }

        Matcher sm = m;
        Pattern ptrn = sm.getPattern();

        String name = ptrn.name();

        name = name != null ?
            " name="+TextUtil.encodeStringConstant(name)
            : null;

        Class ptrnCls = ptrn.getClass();
        String sptrn = ptrnCls.getSimpleName();
        if( sptrn==null )sptrn = ptrnCls.getName();

        String matchedText = null;
        if( m.isMatched() ){
            String begin = " begin="+sm.getBegin();
            String mtext = " matched="+TextUtil.encodeStringConstant(sm.getMatchedText());
            matchedText = begin+mtext;
        }else{
            matchedText = " not matched";
        }

        System.out.println(spacer+sptrn+(name==null ? "" : name)+matchedText);
    }
}
TOP

Related Classes of org.gocha.text.regex.Regex

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.