/*
 * 
 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * The contents of this file are subject to the Sun Community Source
 * License v3.0/Jini Technology Specific Attachment v 1.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://wwws.sun.com/software/jini/licensing/SCSL3_JiniTSA1.html.
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Reference Code is Jini Technology Core Platform code, v2.0. The
 * Developer of the Reference Code is Sun Microsystems, Inc.
 * 
 * Contributor(s): Sun Microsystems, Inc.
 * 
 * The contents of this file comply with the Jini Technology Core
 * Platform Compatibility Kit, v2.0A.
 * 
 * Tester(s): Sun Microsystems, Inc.
 * 
 * Test Platform(s):
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Solaris(TM)SPARC/x86
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Linux (Intel x86)
 * Java 2 SDK, Standard Edition, Version 1.4.2_03 for Windows (Intel Platform)
 * 
 */
package com.sun.jini.norm.event;

import com.sun.jini.thread.TaskManager;
import com.sun.jini.thread.WakeupManager;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

/**
 * Factory class for <code>EventType</code> objects.  All
 * <code>EventType</code> objects created by the same generator (or
 * associated with the same generator by a
 * <code>EventType.restoreTransientState<code> call) will use the same
 * thread pool to manage their event send threads.
 *
 * @author Sun Microsystems, Inc.
 * @see EventType 
 * @see EventType#restoreTransientState
 */
public class EventTypeGenerator implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * Next event ID.
     * @serial
     */
    private long nextEvID = 1;

    /**
     * Task manager used to send events
     */
    private transient TaskManager taskManager = new TaskManager();

    /**
     * Wakeup manager used by the event sending tasks to schedule 
     * retries.
     */
    private transient WakeupManager wakeupManager = 
	new WakeupManager(new WakeupManager.ThreadDesc(null, true));

    /**
     * Create a new <code>EventType</code> object.  The event ID for
     * this type will be generated by this call.
     *
     * @param monitor Object to callback when an event sending
     *        attempt fails with a definite exception and to 
     *        ensure that the lease on the event is still current.
     *        May not be <code>null</code>.
     * @return the new <code>EventType</code> object
     * @throws IOException if listener cannot be serialized 
     */
    public synchronized EventType newEventType(SendMonitor monitor)
	throws IOException
    {
	EventType rslt = new EventType(
	    this, monitor, nextEvID, null, null);
	// Do this afterward so we don't use up an ID if 
	// we can't create the new object
	nextEvID++;
	return rslt;
    }

    /**
     * Create a new <code>EventType</code> object specify the 
     * event id it should have.
     *
     * @param eventID  the event ID of this type
     * @param monitor  Object to callback when an event sending
     *        attempt fails with a definite exception and to 
     *        ensure that the lease on the event is still current.
     *        May not be <code>null</code>.
     * @return the new <code>EventType</code> object
     * @throws IOException if listener cannot be serialized 
     */
    public EventType newEventType(SendMonitor monitor, long eventID)
	throws IOException
    {
	return new EventType(this, monitor, eventID, null, null);
    }

    /**
     * Called by event types during transient state recovery to ensure
     * the generator knows about there event ID.
     * <p>
     * Note: this method is not synchronized.
     * @param evID event ID of recovered <code>EventType</code> object
     */
    void recoverEventID(long evID) {
	if (evID >= nextEvID)
	    nextEvID = evID + 1;
    }

    /**
     * Return the task manager that <code>EventType</code> objects created
     * by this generator should use to send their events.
     */
    TaskManager getTaskManager() {
	return taskManager;
    }

    /**
     * Return the wakeup manager that <code>EventType</code> objects created
     * by this generator should use to send their events.
     */
    WakeupManager getWakeupManager() {
	return wakeupManager;
    }

    /**
     * Terminate any independent treads started by event types
     * associated with this generator.
     */
    public void terminate() {
	taskManager.terminate();
	wakeupManager.stop();
	wakeupManager.cancelAll();
    }

    /**
     * Override <code>readObject</code> to create a <code>TaskManager</code> 
     * and a <code>WakeupManager</code>.
     * @see ObjectInputStream#defaultReadObject
     */
    private void readObject(ObjectInputStream in)
	throws IOException, ClassNotFoundException
    {
	// fill in the object from the stream 
	in.defaultReadObject();

	taskManager = new TaskManager();
	wakeupManager = 
	    new WakeupManager(new WakeupManager.ThreadDesc(null, true));    
    }
}
