package org.apache.maven.jxr.pacman;

/*
 * Copyright (c) 1998 The Java Apache Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. Every modification must be notified to the Java Apache Project
 *    and redistribution of the modified code without prior notification
 *    is not permitted in any form.
 *
 * 4. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the Java Apache Project
 *    (http://java.apache.org/)."
 *
 * 5. The names "Alexandria", "Apache Alexandria" and "Apache Alexandria
 *    Project" must not be used to endorse or promote products
 *    derived from this software without prior written permission.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the Java Apache Project
 *    (http://java.apache.org/)."
 *
 * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * License version 1.0
 *
 */

import java.util.*;
import java.io.*;

import org.apache.maven.jxr.util.*;
import org.apache.tools.ant.DirectoryScanner;

/**
 * Given a list of directories, parse them out and store them as rendered
 * packages, classes, imports, etc.
 */
public class PackageManager
{

    private Hashtable directories = new Hashtable();

    /**
     * All the packages that have been parsed
     */
    private Hashtable packages = new Hashtable();

    /**
     * The default Java package.
     */
    private PackageType defaultPackage = new PackageType();

    /**
     * Given the name of a package (Ex: org.apache.maven.util) obtain it from
     * the PackageManager
     */
    public PackageType getPackageType(String name)
    {

        //return the default package if the name is null.
        if (name == null)
        {
            return defaultPackage;
        }

        return (PackageType) this.packages.get(name);
    }

    /**
     * Add a package to the PackageManager
     */
    public void addPackageType(PackageType packageType)
    {
        this.packages.put(packageType.getName(), packageType);
    }

    /**
     * Get all of the packages in the PackageManager
     */
    public Enumeration getPackageTypes()
    {
       return packages.elements();
    }

    /**
     * Parse out all the directories on which this depends.
     */
    private void parse(String directory)
    {
        // Go through each directory and get the java source 
        // files for this dir.
        DirectoryScanner directoryScanner = new DirectoryScanner();
        File baseDir = new File(directory);
        directoryScanner.setBasedir(baseDir);
        String[] includes = { "**/*.java" };
        directoryScanner.setIncludes(includes);
        directoryScanner.scan();
        String[] files = directoryScanner.getIncludedFiles();

        for (int j = 0; j < files.length; ++j)
        {
            log("parsing... " + files[j]);

            //now parse out this file to get the packages/classname/etc
            try
            {
                String fileName = new File(baseDir,files[j]).getAbsolutePath();
                JavaFile jfi = FileManager.getInstance().getFile(fileName);

                // now that we have this parsed out blend its information
                // with the current package structure
                PackageType jp = this.getPackageType(jfi.getPackageType().getName());

                if (jp == null)
                {
                    this.addPackageType(jfi.getPackageType());
                    jp = jfi.getPackageType();
                }

                //add the current class to this global package.
                if (jfi.getClassType() != null &&
                    jfi.getClassType().getName() != null)
                {

                    jp.addClassType(jfi.getClassType());

                }

            }
            catch (IOException e)
            {
                e.printStackTrace();
            }

        }

    }

    /**
     * Description of the Method
     */
    public void process(String directory)
    {
        if (this.directories.get(directory) == null)
        {
            this.parse(directory);
            this.directories.put(directory, directory);
        }
    }

    /**
     * Description of the Method
     */
    public void process(String[] directories)
    {

        for (int i = 0; i < directories.length; ++i)
        {
            this.process(directories[i]);
        }

    }

    /**
     * Simple logging facility
     */
    public final static void log(String message)
    {
        System.out.println(" PackageManager -> " + message);
    }

    /**
     * Dump the package information to STDOUT. FOR DEBUG ONLY
     */
    public void dump()
    {

        log("Dumping out PackageManager structure");

        Enumeration pts = this.getPackageTypes();

        while (pts.hasMoreElements())
        {

            //get the current package and print it.
            PackageType current = (PackageType)pts.nextElement();

            log(current.getName());

            //get the classes under the package and print those too.
            Enumeration classes = current.getClassTypes();

            while (classes.hasMoreElements())
            {

                ClassType currentClass = (ClassType) classes.nextElement();

                log("\t" + currentClass.getName());

            }
        }
    }
}

