/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/UriTokenizer.java,v 1.8 2004/11/08 09:26:57 luetzkendorf Exp $
 * $Revision: 1.8 $
 * $Date: 2004/11/08 09:26:57 $
 *
 * ====================================================================
 *
 * Copyright 1999-2002 The Apache Software Foundation 
 *
 * 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 org.apache.slide.common;

import java.util.StringTokenizer;
import java.util.Vector;
import java.util.NoSuchElementException;

/**
 * Tokenizes a scope.
 * <p/>
 * This tokenizer derives from StringTokenizer and tokenizes an Uri.
 * This object is used for browsing down the main tree from the root
 * element during retrieval and create operations.
 * <p/>
 * Ex : the uri /foo/bar/bar.txt will be tokenized in the following tokens :
 * <li>/
 * <li>/foo
 * <li>/foo/bar
 * <li>/foo/bar/bar.txt
 *
 * @version $Revision: 1.8 $
 */
public final class UriTokenizer extends StringTokenizer {
    
    
    // ----------------------------------------------------------- Constructors
    
    
    /**
     * Constructor.
     *
     * @param namespace
     * @param uri
     */
    public UriTokenizer(SlideToken slideToken, Namespace namespace, String uri) {
        super(uri, "/");
        
        // We then build the scopes.
        uris = new Vector();
        
        this.slideToken = slideToken;
        this.namespace = namespace;
        
        uris.addElement("/");
        
        // We parse the token list and build the scope String objects.
        StringBuffer b = new StringBuffer(uri.length());
        while(super.hasMoreTokens()) {
            b.append("/").append(super.nextToken());
            uris.addElement(b.toString());
        }
        
        pos = 0;
    }
    
    
    /**
     * Constructor.
     *
     * @param namespace
     * @param uri
     */
    public UriTokenizer(Namespace namespace, String uri) {
        this(null, namespace, uri);
    }
    
    
    /**
     * Constructor.
     *
     * @param namespace
     * @param scope
     */
    public UriTokenizer(Namespace namespace, Scope scope) {
        this(null, namespace, scope.toString());
    }
    
    
    // ----------------------------------------------------- Instance Variables
    
    
    /**
     * Vector of all the scopes matched by the associated Uri.
     */
    Vector uris;
    
    
    /**
     * Position in the uri vector.
     */
    int pos;
    
    
    /**
     * Associated namespace.
     */
    Namespace namespace;
    
    SlideToken slideToken;
    
    
    // --------------------------------------------------------- Public Methods
    
    
    /**
     * Get the parent uri.
     *
     * @return Uri
     */
    public Uri getParentUri() {
        if (uris.size() < 1) {
            return null;
        } else {
            return namespace.getUri(slideToken, (String) uris.elementAt(uris.size() - 1));
        }
    }
    
    
    /**
     * True if the UriTokenizer contains additional scopes.
     *
     * @return boolean
     */
    public boolean hasMoreElements() {
        return uris.size() > pos;
    }
    
    
    /**
     * True if the UriTokenizer contains additional scopes.
     *
     * @return boolean
     */
    public boolean hasMoreTokens() {
    return hasMoreElements();
    }
    
    
    /**
     * Returns the next Uri as an Object.
     *
     * @return Object
     * @exception NoSuchElementException
     */
    public Object nextElement()
    throws NoSuchElementException {
    Object obj = null;
    try {
        if (!hasMoreElements()) {
        throw new NoSuchElementException();
        }
        obj = uris.elementAt(pos);
        pos = pos + 1;
    } catch (ArrayIndexOutOfBoundsException e) {
        // Should NEVER happen.
        e.printStackTrace();
    }
    return obj;
    }
    
    
    /**
     * Returns the next Uri as a String object.
     *
     * @return String
     * @exception NoSuchElementException
     */
    public String nextToken()
    throws NoSuchElementException {
    return (String) nextElement();
    }
    
    
    /**
     * Returns the next Uri as an Uri object.
     *
     * @return Uri
     * @exception NoSuchElementException
     */
    public Uri nextUri()
    throws NoSuchElementException {
    return namespace.getUri(slideToken, nextToken());
    }
    
    
    /**
     * Returns the next Uri as an Uri object.
     *
     * @param delim
     * @exception NoSuchElementException
     */
    public String nextToken(String delim)
    throws NoSuchElementException {
    return nextToken();
    }
    
}
