/*
 * AddressBooksimpl.java
 * Class to implement AddressBooks interface
 * in AddressBook API
 */

import addressbooklib.*;
import addressbooklib.Application;
import addressbooklib.Errors;
import java.io.*;
import java.util.Enumeration;
import java.util.Vector;
import com.ms.com.ComFailException;
import com.ms.com.IUnknown;
import com.ms.com.Variant;

/**
 * Implementation of AddressBooks dual interface
 * @Author Ken Bandes
 */
public class AddressBooksimpl 
    implements AddressBooks
{
    private static final String CLSID = 
        "4F9DFA96-32EF-11D1-B5AC-9E4A44000000";

    /**
     * constructor
     * @param application the Applicationimpl object
     */
    public AddressBooksimpl(Applicationimpl application)
    {
        this.application = application;
    }

    /**
     * implementation of addressbook.AddressBooks.getApplication
     * @return the Application
     */
    public Application getApplication()
    {
        return (Application) application;
    }

    /**
     * implementation of addressbook.AddressBooks.getParent
     * @return the parent object, which is the Application
     */
    public Application getParent()
    {
        return (Application) application;
    }

    /**
     * implementation of addressbook.AddressBooks.getCount
     * @return the number of open AddressBook objects
     */
    public int getCount()
    {
        return books.size();
    }

    /**
     * implementation of addressbook.AddressBooks.get_NewEnum
     * @return the IUnknown pointer to an object implementing
     * IEnumVARIANT
     */
    public IUnknown get_NewEnum()
    {
        return (IUnknown) getAutoEnum();
    }

    /**
     * implementation of addressbook.AddressBooks.Add
     * Create a new AddressBook
     * @param filename the name of the file to create
     * @return the newly-created AddressBook object
     */
    public AddressBook Add(String filename)
    {
        File file = new File(filename);
        if(file.exists())
        {
            throw new ComFailException(
                        Errors.E_FILEEXISTS,
                        filename + " already exists: can't create it");
        }
        AddressBookimpl book = new AddressBookimpl(this, file);
        books.addElement(book);
        return (AddressBook) book;
    }

    /**
     * implementation of addressbook.AddressBooks.Item
     * @param index index into the array of open AddressBook objects
     * @return the selected AddressBook object
     */
    public AddressBook Item(int index)
    {
        AddressBookimpl book;
        try
        {
            book = (AddressBookimpl) books.elementAt(index);
        }
        catch(ArrayIndexOutOfBoundsException ex)
        {
            throw new ComFailException(
                        Errors.E_OUTOFBOUNDS, 
                        "No Element At Position " + index);
        }
        return (AddressBook) book;
    }

    /**
     * implementation of addressbook.AddressBooks.getEnum
     * @return a DIEnum interface to provide a simple enumeration
     */
    public DIEnum getEnum()
    {
        return (DIEnum) getAutoEnum();
    }

    /**
     * open an AddressBook
     * implementation of addressbook.AddressBooks.Open
     * @param Name name of the AddressBook
     * @return the specified AddressBook object
     */
    public AddressBook Open(String filename)
    {
        File file = new File(filename);
        if(!file.exists())
            throw new ComFailException(
                        Errors.E_FILENOTFOUND,
                        filename + " Not Found");

        AddressBookimpl book;
        try
        {
            FileInputStream fis = new FileInputStream(file);
            ObjectInputStream ois = new ObjectInputStream(fis);
            book = (AddressBookimpl) ois.readObject();
            ois.close();
        }
        catch(IOException ex)
        {
            throw new ComFailException(
                        Errors.E_LOADFAILED,
                        "Error Occurred Loading " + 
                        file.getAbsolutePath());
        }
        catch(ClassNotFoundException ex)
        {
            throw new ComFailException(
                        Errors.E_LOADFAILED,
                        "Error Occurred Loading " + 
                        file.getAbsolutePath());
        }

        // set transient fields in new object
        book.setFile(file);
        book.setParent(this);

        return (AddressBook) book;
    }

    // package-accessible methods
    /**
     * Remove an AddressBook object from the collection<br>
     * called when the AddressBook closes
     * @param book the AddressBook object
     */
    void remove(AddressBookimpl book)
    {
        books.removeElement(book);
    }

    // private methods

    // get a COM enumeration object for this collection
    private AutoEnum getAutoEnum()
    {
        /* use an anonymous class to implement the Enumerable
         * interface required by AutoEnum's constructor
         */
        return new AutoEnum(new Enumerable() {
            // get an Enumeration on the collection
            public Enumeration elements()
            {
                return books.elements();
            }
        });
    }

    // private data:
    // the Application object for this API instance
    private Applicationimpl application;
    // the collection of open AddressBook objects
    private Vector books = new Vector();
}
