/*
 * 
 * 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.
 * 
 */
package net.jini.core.transaction.server;

import net.jini.core.transaction.*;
import java.rmi.Remote;
import java.rmi.RemoteException;


/**
 * Class implementing the <code>Transaction</code> interface, for use with
 * transaction participants that implement the default transaction semantics.
 *
 * @author Sun Microsystems, Inc.
 *
 * @see net.jini.core.transaction.Transaction
 * @see NestableServerTransaction
 * @see TransactionManager
 * @see net.jini.core.transaction.TransactionFactory
 *
 * @since 1.0
 */
public class ServerTransaction implements Transaction, java.io.Serializable {
    static final long serialVersionUID = 4552277137549765374L;

    /**
     * The transaction manager.
     * @serial
     */
    public final TransactionManager mgr;
    /**
     * The transaction id.
     * @serial
     */
    public final long id;

    /**
     * Simple constructor.  Clients should not call this directly, but
     * should instead use <code>TransactionFactory</code>.
     *
     * @param mgr the manager for this transaction
     * @param id the transaction id
     */
    public ServerTransaction(TransactionManager mgr, long id) {
	this.mgr = mgr;
	this.id = id;
    }

    // inherit javadoc
    public int hashCode() {
        return (int) id ^ mgr.hashCode();
    }

    /**
     * Two instances are equal if they have the same transaction manager
     * and the same transaction id.
     */
    public boolean equals(Object other) {
        try {
            ServerTransaction t = (ServerTransaction) other;
            return (id == t.id && mgr.equals(t.mgr));
        } catch (ClassCastException e) {
            return false;
        }
    }

    // inherit javadoc
    public void commit()
	throws UnknownTransactionException, CannotCommitException,
	       RemoteException
    {
        mgr.commit(id);
    }

    // inherit javadoc
    public void commit(long waitFor)
        throws UnknownTransactionException, CannotCommitException,
	       TimeoutExpiredException, RemoteException
    {
	mgr.commit(id, waitFor);
    }

    // inherit javadoc
    public void abort()
	throws UnknownTransactionException, CannotAbortException,
	       RemoteException
    {
	mgr.abort(id);
    }

    // inherit javadoc
    public void abort(long waitFor)
	throws UnknownTransactionException, CannotAbortException,
	       TimeoutExpiredException, RemoteException
    {
        mgr.abort(id, waitFor);
    }

    /**
     * Join the transaction. The <code>crashCount</code> marks the state of
     * the storage used by the participant for transactions. If the
     * participant attempts to join a transaction more than once, the crash
     * counts must be the same. Each system crash or other event that
     * destroys the state of the participant's unprepared transaction storage
     * must cause the crash count to increase by at least one.
     *
     * @param part the participant joining the transaction
     * @param crashCount the participant's current crash count
     *
     * @throws UnknownTransactionException if the transaction 
     *         is unknown to the transaction manager, either 
     *         because the transaction ID is incorrect or because the 
     *         transaction is complete and its state has been 
     *         discarded by the manager.
     * @throws CannotJoinException if the transaction is known 
     *         to the manager but is no longer active.
     * @throws CrashCountException if the crash count provided 
     *         for the participant differs from the crash count 
     *         in a previous invocation of the same pairing of 
     *         participant and transaction
     * @throws RemoteException if there is a communication error
     */
    public void join(TransactionParticipant part, long crashCount)
        throws UnknownTransactionException, CannotJoinException,
	       CrashCountException, RemoteException
    {
        mgr.join(id, part, crashCount);
    }
 
    /**
     * Returns the current state of the transaction.  The returned
     * state can be any of the <code>TransactionConstants</code> values.
     *
     * @return an <code>int</code> representing the state of the transaction
     *
     * @throws UnknownTransactionException if the transaction 
     *         is unknown to the transaction manager, either 
     *         because the transaction ID is incorrect or because the 
     *         transaction is complete and its state has been 
     *         discarded by the manager.
     * @throws RemoteException if there is a communication error
     *
     * @see TransactionConstants
     */
    public int getState() throws UnknownTransactionException, RemoteException {
	return mgr.getState(id);
    }

    /**
     * Return true if the transaction has a parent, false if the transaction
     * is top level.
     *
     * @return true if the transaction has a parent, false if the transaction
     * is top level.
     */
    public boolean isNested() {
	return false;
    }

    // inherit javadoc
    public String toString() {
	return new String(
	    this.getClass().getName() +
	    " [manager=" + this.mgr +
	    ", id=" + this.id +
	    "]");
    }
}
