/*
 * $Header: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/UriPath.java,v 1.9 2005/01/03 15:43:26 luetzkendorf Exp $
 * $Revision: 1.9 $
 * $Date: 2005/01/03 15:43:26 $
 *
 * ====================================================================
 *
 * 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;

/**
 * An URI path.
 *
 * @version $Revision: 1.9 $
 */
public final class UriPath {
    
    private String[] tokens;
    
    private UriPath() {
    }
    
    private UriPath(String[] tokens) {
        this.tokens = tokens;
    }
    
    public UriPath(String uri) {
        StringTokenizer t = new StringTokenizer( uri, "/" );
        this.tokens = new String[t.countTokens()];
        for (int i = 0; t.hasMoreTokens(); i++) {
            tokens[i] = t.nextToken();
        }
    }
    
    public String[] tokens() {
        return tokens;
    }
    
    public String lastSegment() {
        return tokens.length > 0
            ? tokens[ tokens.length - 1 ]
            : null;
    }
    
    public UriPath parent() {
        if (this.tokens.length == 0) {
            return null;
        }
        return subUriPath(0, tokens.length - 1);
    }
    
    public UriPath child( String segment ) {
        String[] ctokens = new String[tokens.length + 1];
        for (int i = 0; i < tokens.length; i++) {
            ctokens[i] = tokens[i];
        }
        ctokens[tokens.length] = segment;
        return new UriPath(ctokens);
    }
    
    public UriPath subUriPath(int start, int end) {
        UriPath result = new UriPath();
        result.tokens = new String[end - start];
        System.arraycopy(tokens, start, result.tokens, 0, result.tokens.length);
        return result;
    }
    
    public String subUriPathString(int start, int end) {
        if (end > start) {
            StringBuffer b = new StringBuffer(tokens.length * 20);
            for (int i = start; i < end; i++) {
                b.append("/").append(tokens[i]);
            }
            return b.toString();
        } else {
            return "/";
        }
    }
    
    /**
     * Tests whether a given uri is a child of this uri path.
     * @param child uri of the possible child
     * @return <code>true</code> if <code>child</code> is a child of this path
     */
    public boolean isParentOf(String child) {
        StringTokenizer tokenizer = new StringTokenizer(child, "/");
        
        for(int i = 0; i < this.tokens.length && tokenizer.hasMoreTokens();i++) {
            String t = tokenizer.nextToken();
            if (!t.equals(this.tokens[i])) {
                return false;
            }
        }
        // there must be exactly one more token 
        if (tokenizer.hasMoreTokens()) {
            tokenizer.nextToken();
            return !tokenizer.hasMoreTokens();
        } else {
            return false;
        }
    }
    
    public boolean equals(Object o) {
        boolean result = false;
        if (o instanceof UriPath) {
            UriPath other = (UriPath)o;
            if (other.tokens.length == this.tokens.length) {
                result = true;
                for (int i = 0; i < this.tokens.length; i++) {
                    if (!other.tokens[i].equals(this.tokens[i])) {
                        result = false;
                        break;
                    }
                }
            }
        }
        return result;
    }
    
    public int hashCode() {
        if (tokens.length > 0) {
            return tokens[tokens.length - 1].hashCode();
        }
        else {
            return 0;
        }
    }
    
    public String toString() {
        if (tokens.length > 0) {
            StringBuffer b = new StringBuffer();
            for (int i = 0; i < tokens.length; i++) {
                b.append("/").append(tokens[i]);
            }
            return b.toString();
        }
        else {
            return "/";
        }
    }
    
    public static int segmentCount(String uri) {
        return new StringTokenizer(uri, "/").countTokens();
    }
    
    public static String getParentUri(String uri) {
        if ("/".equals(uri)) return null;
        
        int lastSlashPos = uri.endsWith("/") ? 
                uri.lastIndexOf('/', uri.length()-2) : uri.lastIndexOf('/');
        if (lastSlashPos == -1) {
            throw new RuntimeException("Can't create parent uri for: " + uri);
        }
        if (lastSlashPos == 0) {
            return "/";
        }
        
        return uri.substring(0, lastSlashPos);
    }
    
    public static String getLastSegment(String uri) {
        if ("/".equals(uri)) return "";
        
        int lastSlashPos = uri.endsWith("/") ? 
                uri.lastIndexOf('/', uri.length()-2) : uri.lastIndexOf('/');
        if (lastSlashPos == -1) {
            return uri;
        }
        
        return uri.endsWith("/") 
                ? uri.substring(lastSlashPos+1, uri.length()-1)
                : uri.substring(lastSlashPos+1);
    }
    
    public static void main(String[] args) {
        System.out.println(getParentUri("/"));
        System.out.println(getParentUri("/abc"));
        System.out.println(getParentUri("/abc/"));
        System.out.println(getParentUri("/abc/def"));
        System.out.println(getParentUri("/abc/def/"));
        System.out.println(getLastSegment("/"));
        System.out.println(getLastSegment("/abc"));
        System.out.println(getLastSegment("/abc/"));
        System.out.println(getLastSegment("/abc/def"));
        System.out.println(getLastSegment("/abc/def/"));
    }
}
