001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018
019package org.apache.commons.net.ftp.parser;
020
021import java.util.regex.MatchResult;
022import java.util.regex.Matcher;
023import java.util.regex.Pattern;
024import java.util.regex.PatternSyntaxException;
025
026import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
027
028/**
029 * This abstract class implements both the older FTPFileListParser and
030 * newer FTPFileEntryParser interfaces with default functionality.
031 * All the classes in the parser subpackage inherit from this.
032 *
033 * This is the base class for all regular expression based FTPFileEntryParser classes
034 *
035 * @author Steve Cohen <scohen@apache.org>
036 */
037public abstract class RegexFTPFileEntryParserImpl extends
038        FTPFileEntryParserImpl {
039    /**
040     * internal pattern the matcher tries to match, representing a file
041     * entry
042     */
043    private Pattern pattern = null;
044
045    /**
046     * internal match result used by the parser
047     */
048    private MatchResult result = null;
049
050    /**
051     * Internal PatternMatcher object used by the parser.  It has protected
052     * scope in case subclasses want to make use of it for their own purposes.
053     */
054    protected Matcher _matcher_ = null;
055
056    /**
057     * The constructor for a RegexFTPFileEntryParserImpl object.
058     *
059     * @param regex  The regular expression with which this object is
060     * initialized.
061     *
062     * @exception IllegalArgumentException
063     * Thrown if the regular expression is unparseable.  Should not be seen in
064     * normal conditions.  It it is seen, this is a sign that a subclass has
065     * been created with a bad regular expression.   Since the parser must be
066     * created before use, this means that any bad parser subclasses created
067     * from this will bomb very quickly,  leading to easy detection.
068     */
069
070    public RegexFTPFileEntryParserImpl(String regex) {
071        super();
072        setRegex(regex);
073    }
074
075    /**
076     * Convenience method delegates to the internal MatchResult's matches()
077     * method.
078     *
079     * @param s the String to be matched
080     * @return true if s matches this object's regular expression.
081     */
082
083    public boolean matches(String s) {
084        this.result = null;
085        _matcher_ = pattern.matcher(s);
086        if (_matcher_.matches()) {
087            this.result = _matcher_.toMatchResult();
088        }
089        return null != this.result;
090    }
091
092    /**
093     * Convenience method
094     *
095     * @return the number of groups() in the internal MatchResult.
096     */
097
098    public int getGroupCnt() {
099        if (this.result == null) {
100            return 0;
101        }
102        return this.result.groupCount();
103    }
104
105    /**
106     * Convenience method delegates to the internal MatchResult's group()
107     * method.
108     *
109     * @param matchnum match group number to be retrieved
110     *
111     * @return the content of the <code>matchnum'th</code> group of the internal
112     *         match or null if this method is called without a match having
113     *         been made.
114     */
115    public String group(int matchnum) {
116        if (this.result == null) {
117            return null;
118        }
119        return this.result.group(matchnum);
120    }
121
122    /**
123     * For debugging purposes - returns a string shows each match group by
124     * number.
125     *
126     * @return a string shows each match group by number.
127     */
128
129    public String getGroupsAsString() {
130        StringBuilder b = new StringBuilder();
131        for (int i = 1; i <= this.result.groupCount(); i++) {
132            b.append(i).append(") ").append(this.result.group(i)).append(
133                    System.getProperty("line.separator"));
134        }
135        return b.toString();
136    }
137
138    /**
139     * Alter the current regular expression being utilised for entry parsing
140     * and create a new {@link Pattern} instance.
141     * @param regex The new regular expression
142     * @return  true if the compiled pattern is not null
143     * @since 2.0
144     */
145    public boolean setRegex(String regex) {
146        try {
147            pattern = Pattern.compile(regex);
148        } catch (PatternSyntaxException pse) {
149            throw new IllegalArgumentException("Unparseable regex supplied: "
150                    + regex);
151        }
152        return (pattern != null);
153    }
154
155}