/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.cocoon.matching.helpers;

import java.util.HashMap;

/**
 * This class is an utility class that perform wilcard-patterns matching and
 * isolation.
 *
 * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
 *         (Apache Software Foundation)
 * @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
 * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
 * @version CVS $Id$
 * @deprecated renamed to WildcardHelper
 */
public class WildcardURIMatcher {

    /** The int representing '*' in the pattern <code>int []</code>. */
    protected static final int MATCH_FILE = -1;
    /** The int representing '**' in the pattern <code>int []</code>. */
    protected static final int MATCH_PATH = -2;
    /** The int representing begin in the pattern <code>int []</code>. */
    protected static final int MATCH_BEGIN = -4;
    /** The int representing end in pattern <code>int []</code>. */
    protected static final int MATCH_THEEND = -5;
    /** The int value that terminates the pattern <code>int []</code>. */
    protected static final int MATCH_END = -3;

    /**
     * match a pattern agains a string and isolates wildcard replacement into a
     * <code>Stack</code>.
     */
    public static boolean match (HashMap map, String data,
            int[] expr) throws NullPointerException {
        if (map == null)
            throw new NullPointerException ("No map provided");
        if (data == null)
            throw new NullPointerException ("No data provided");
        if (expr == null)
            throw new NullPointerException ("No pattern expression provided");


        char buff[] = data.toCharArray();
        // Allocate the result buffer
        char rslt[] = new char[expr.length + buff.length];


        // The previous and current position of the expression character
        // (MATCH_*)
        int charpos = 0;

        // The position in the expression, input, translation and result arrays
        int exprpos = 0;
        int buffpos = 0;
        int rsltpos = 0;
        int offset = -1;

        // The matching count
        int mcount = 0;

        // We want the complete data be in {0}
        map.put(Integer.toString(mcount),data);

        // First check for MATCH_BEGIN
        boolean matchBegin = false;
        if (expr[charpos] == MATCH_BEGIN) {
            matchBegin = true;
            exprpos = ++charpos;
        }

        // Search the fist expression character (except MATCH_BEGIN - already skipped)
        while (expr[charpos] >= 0)
            charpos++;

        // The expression charater (MATCH_*)
        int exprchr = expr[charpos];

        while (true) {
            // Check if the data in the expression array before the current
            // expression character matches the data in the input buffer
            if (matchBegin) {
                if (!matchArray(expr, exprpos, charpos, buff, buffpos))
                    return (false);
                matchBegin = false;
            } else {
                offset = indexOfArray (expr, exprpos, charpos, buff,
                        buffpos);
                if (offset < 0)
                    return (false);
            }

            // Check for MATCH_BEGIN
            if (matchBegin) {
                if (offset != 0)
                    return (false);
                matchBegin = false;
            }

            // Advance buffpos
            buffpos += (charpos - exprpos);

            // Check for END's
            if (exprchr == MATCH_END) {
                if (rsltpos > 0)
                    map.put(Integer.toString(++mcount),new String(rslt, 0, rsltpos));
                // Don't care about rest of input buffer
                return (true);
            } else if (exprchr == MATCH_THEEND) {
                if (rsltpos > 0)
                    map.put (Integer.toString(++mcount),new String(rslt, 0, rsltpos));
                // Check that we reach buffer's end
                return (buffpos == buff.length);
            }

            // Search the next expression character
            exprpos = ++charpos;
            while (expr[charpos] >= 0)
                charpos++;
            int prevchr = exprchr;
            exprchr = expr[charpos];

            // We have here prevchr == * or **.
            offset = (prevchr == MATCH_FILE) ?
                    indexOfArray (expr, exprpos, charpos, buff, buffpos) :
                    lastIndexOfArray (expr, exprpos, charpos, buff,
                    buffpos);

            if (offset < 0)
                return (false);

            // Copy the data from the source buffer into the result buffer
            // to substitute the expression character
            if (prevchr == MATCH_PATH) {
                while (buffpos < offset)
                    rslt[rsltpos++] = buff[buffpos++];
            } else {
                // Matching file, don't copy '/'
                while (buffpos < offset) {
                    if (buff[buffpos] == '/')
                        return (false);
                    rslt[rsltpos++] = buff[buffpos++];
                }
            }

            map.put(Integer.toString(++mcount),new String (rslt, 0, rsltpos));
            rsltpos = 0;
        }
    }

    /**
      * Get the offset of a part of an int array within a char array.
      * <br>
      * This method return the index in d of the first occurrence after dpos of
      * that part of array specified by r, starting at rpos and terminating at
      * rend.
      *
      * @param r The array containing the data that need to be matched in d.
      * @param rpos The index of the first character in r to look for.
      * @param rend The index of the last character in r to look for plus 1.
      * @param d The array of char that should contain a part of r.
      * @param dpos The starting offset in d for the matching.
      * @return The offset in d of the part of r matched in d or -1 if that was
      *         not found.
      */
    protected static int indexOfArray (int r[], int rpos, int rend,
            char d[], int dpos) {
        // Check if pos and len are legal
        if (rend < rpos)
            throw new IllegalArgumentException ("rend < rpos");
        // If we need to match a zero length string return current dpos
        if (rend == rpos)
            return (d.length); //?? dpos?
        // If we need to match a 1 char length string do it simply
        if ((rend - rpos) == 1) {
            // Search for the specified character
            for (int x = dpos; x < d.length; x++)
                if (r[rpos] == d[x])
                    return (x);
        }
        // Main string matching loop. It gets executed if the characters to
        // match are less then the characters left in the d buffer
        while ((dpos + rend - rpos) <= d.length) {
            // Set current startpoint in d
            int y = dpos;
            // Check every character in d for equity. If the string is matched
            // return dpos
            for (int x = rpos; x <= rend; x++) {
                if (x == rend)
                    return (dpos);
                if (r[x] != d[y++])
                    break;
            }
            // Increase dpos to search for the same string at next offset
            dpos++;
        }
        // The remaining chars in d buffer were not enough or the string
        // wasn't matched
        return (-1);
    }

    /**
      * Get the offset of a last occurance of an int array within a char array.
      * <br>
      * This method return the index in d of the last occurrence after dpos of
      * that part of array specified by r, starting at rpos and terminating at
      * rend.
      *
      * @param r The array containing the data that need to be matched in d.
      * @param rpos The index of the first character in r to look for.
      * @param rend The index of the last character in r to look for plus 1.
      * @param d The array of char that should contain a part of r.
      * @param dpos The starting offset in d for the matching.
      * @return The offset in d of the last part of r matched in d or -1 if that was
      *         not found.
      */
    protected static int lastIndexOfArray (int r[], int rpos, int rend,
            char d[], int dpos) {
        // Check if pos and len are legal
        if (rend < rpos)
            throw new IllegalArgumentException ("rend < rpos");
        // If we need to match a zero length string return current dpos
        if (rend == rpos)
            return (d.length); //?? dpos?

        // If we need to match a 1 char length string do it simply
        if ((rend - rpos) == 1) {
            // Search for the specified character
            for (int x = d.length - 1; x > dpos; x--)
                if (r[rpos] == d[x])
                    return (x);
        }

        // Main string matching loop. It gets executed if the characters to
        // match are less then the characters left in the d buffer
        int l = d.length - (rend - rpos);
        while (l >= dpos) {
            // Set current startpoint in d
            int y = l;
            // Check every character in d for equity. If the string is matched
            // return dpos
            for (int x = rpos; x <= rend; x++) {
                if (x == rend)
                    return (l);
                if (r[x] != d[y++])
                    break;
            }
            // Decrease l to search for the same string at next offset
            l--;
        }
        // The remaining chars in d buffer were not enough or the string
        // wasn't matched
        return (-1);
    }

    /**
      * Matches elements of array r from rpos to rend with array d, starting from dpos.
      * <br>
      * This method return true if elements of array r from rpos to rend
      * equals elements of array d starting from dpos to dpos+(rend-rpos).
      *
      * @param r The array containing the data that need to be matched in d.
      * @param rpos The index of the first character in r to look for.
      * @param d The array of char that should start from a part of r.
      * @param dpos The starting offset in d for the matching.
      * @return true if array d starts from portion of array r.
      */
    protected static boolean matchArray (int r[], int rpos, int rend,
            char d[], int dpos) {
        if (d.length - dpos < rend - rpos)
            return (false);
        for (int i = rpos; i < rend; i++)
            if (r[i] != d[dpos++])
                return (false);
        return (true);
    }
}
