/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.org
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */


package org.objectweb.jonas_tm;

import java.io.Serializable;
import javax.transaction.xa.Xid;

/**
 * Xid implementation for JTA
 * @author Philippe Durieux
 */
public class XidImpl implements Xid, Serializable {

    public static final int JONAS_FORMAT_ID = 0xBB14;
    private static int count = 1;

    /**
     * format id
     * @serial
     */
    private int formatId;

    /**
     * global transaction id
     * @serial
     */
    private byte[] gtrid;

    /**
     * branch qualifier
     * @serial
     */
    private byte[] bqual;

    // -------------------------------------------------------------------
    // Constructors
    // -------------------------------------------------------------------

    /**
     * Build an Xid for a local transaction
     */
    public XidImpl(String serverName, int ipAddr) {

	TraceTm.debugTm("XidImpl constructor: " + serverName + ":" + ipAddr);

	formatId = JONAS_FORMAT_ID;
	long uuid;
	synchronized(getClass()) {
	    uuid =  System.currentTimeMillis() * 1024 + count;
	    count++;
	}

	// compute gtrid
	// compute JOnAS gtrid
	String s = Long.toHexString(uuid) + "_" + Long.toHexString(ipAddr) + "_" + serverName;
	if (s.length() > Xid.MAXBQUALSIZE) {
	    s = s.substring(0, Xid.MAXBQUALSIZE);
	}
	gtrid = s.getBytes();

	// bqual is equal to gtrid in this constructor XXX
	bqual = s.getBytes();

	TraceTm.debugTm("new Xid = "+uuid);
    }

    /**
     * Build an Xid from an otid_t CORBA
     */
    public XidImpl(int fid, int bqualsz, byte[] tid) {

	TraceTm.debugTm("XidImpl constructor");

	// FormatId
	formatId = fid;

	// gtrid
	int gtridsz = tid.length - bqualsz;
	gtrid = new byte[gtridsz];
	System.arraycopy(tid, bqualsz, gtrid, 0, gtridsz);	

	// bqual
	bqual = new byte[bqualsz];
	System.arraycopy(tid, 0, bqual, 0, bqualsz);
    }

    // -------------------------------------------------------------------
    // Xid implementation
    // -------------------------------------------------------------------

    /**
     * Get the format id for that Xid
     */
    public int getFormatId() {
	return formatId;
    }

    /**
     * Get the Global Id for that Xid
     */
    public byte[] getGlobalTransactionId() {
	return gtrid;
    }

    /**
     * Get the Branch Qualifier for that Xid
     */
    public byte[] getBranchQualifier() {
	return bqual;
    }

    // -------------------------------------------------------------------
    // other methods
    // -------------------------------------------------------------------

    /**
     * String form
     */
    public String toString() {
	return new String(bqual) + new String(gtrid);
    }

    // -------------------------------------------------------------------
    // equals and hashCode
    // -------------------------------------------------------------------

    /**
     * return true if objects are identical
     */
    public boolean equals(Object obj2) {
	XidImpl xid2 = (XidImpl) obj2;

	if (formatId == xid2.getFormatId() && 
	    java.util.Arrays.equals(bqual, xid2.getBranchQualifier()) &&
	    java.util.Arrays.equals(gtrid, xid2.getGlobalTransactionId())) {
	    return true;
	} else {
	    return false;
	}
    }

    /**
     * return a hashcode value for this object
     */
    public int hashCode() {
	String bquals = new String (bqual);
	String gtrids = new String (gtrid);	
	return (gtrids + bquals).hashCode() % 100;
    }

}
