/*
 * @(#)Package.java        1.12 98/06/29
 *
 * Copyright 1995-1998 by Sun Microsystems, Inc.,
 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Sun Microsystems, Inc. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Sun.
 */

package com.novell.utility.java;

import java.util.Enumeration;
import java.io.File;
import java.io.IOException;

/**
 * This class is used to represent the classes in a package.
 */
public
class Package {
    /**
     * The path which we use to locate source files.
     */
    ClassPath sourcePath;

    /**
     * The path which we use to locate class (binary) files.
     */
    ClassPath binaryPath;

    /**
     * The path name of the package.
     */
    String pkg;

    /**
     * Create a package given a class path, and package name.
     */
    public Package(ClassPath path, Identifier pkg) throws IOException {
        this(path, path, pkg);
    }

    /**
     * Create a package given a source path, binary path, and package
     * name.
     */
    public Package(ClassPath sourcePath,
                   ClassPath binaryPath,
                   Identifier pkg)
    throws IOException {
        if (pkg.isInner())
            pkg = Identifier.lookup(pkg.getQualifier(), pkg.getFlatName());
        this.sourcePath = sourcePath;
        this.binaryPath = binaryPath;
        this.pkg = pkg.toString().replace('.', File.separatorChar);
    }

    /**
     * Check if a class is defined in this package.
     * (If it is an inner class name, it is assumed to exist
     * only if its binary file exists.  This is somewhat pessimistic.)
     */
    public boolean classExists(Identifier className) {
        return getBinaryFile(className) != null ||
                !className.isInner() &&
               getSourceFile(className) != null;
    }

    /**
     * Check if the package exists
     */
    public boolean exists() {
        // Look for the directory on our binary path.
        ClassFile dir = binaryPath.getDirectory(pkg);
        if (dir != null && dir.isDirectory()) {
            return true;
        }

        if (sourcePath != binaryPath) {
            // Look for the directory on our source path.
            dir = sourcePath.getDirectory(pkg);
            if (dir != null && dir.isDirectory()) {
                return true;
            }
        }

        /* Accomodate ZIP files without CEN entries for directories
         * (packages): look on class path for at least one binary
         * file or one source file with the right package prefix
         */
        String prefix = pkg + File.separator;

        return binaryPath.getFiles(prefix, ".class").hasMoreElements()
            || sourcePath.getFiles(prefix, ".java").hasMoreElements();
    }

    private String makeName(String fileName) {
        return pkg.equals("") ? fileName : pkg + File.separator + fileName;
    }

    /**
     * Get the .class file of a class
     */
    public ClassFile getBinaryFile(Identifier className) {
        className = Type.mangleInnerType(className);
        String fileName = className.toString() + ".class";
        return binaryPath.getFile(makeName(fileName));
    }

    /**
     * Get the .java file of a class
     */
    public ClassFile getSourceFile(Identifier className) {
        // The source file of an inner class is that of its outer class.
        className = className.getTopName();
        String fileName = className.toString() + ".java";
        return sourcePath.getFile(makeName(fileName));
    }

    public ClassFile getSourceFile(String fileName) {
        if (fileName.endsWith(".java")) {
            return sourcePath.getFile(makeName(fileName));
        }
        return null;
    }

    public Enumeration getSourceFiles() {
        return sourcePath.getFiles(pkg, ".java");
    }

    public Enumeration getBinaryFiles() {
        return binaryPath.getFiles(pkg, ".class");
    }

    public String toString() {
        if (pkg.equals("")) {
            return "unnamed package";
        }
        return "package " + pkg;
    }
}
