/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.command;

import java.util.Arrays;

import javax.transaction.xa.Xid;

import org.apache.activemq.util.HexSupport;


/**
 * @openwire:marshaller code="112"
 * @version $Revision: 1.6 $
 */
public class XATransactionId extends TransactionId implements Xid {
    
    public static final byte DATA_STRUCTURE_TYPE=CommandTypes.ACTIVEMQ_XA_TRANSACTION_ID;

    private int formatId;
    private byte[] branchQualifier;
    private byte[] globalTransactionId;
    
    private transient int hash;
    
    public XATransactionId() {        
    }
    
    public XATransactionId(Xid xid) {
        this.formatId = xid.getFormatId();
        this.globalTransactionId = xid.getGlobalTransactionId();
        this.branchQualifier = xid.getBranchQualifier();
    }
    
    public byte getDataStructureType() {
        return DATA_STRUCTURE_TYPE;
    }
        
    public String getTransactionKey() {
        return "XID:"+formatId+":"+HexSupport.toHexFromBytes(globalTransactionId)+":"+HexSupport.toHexFromBytes(branchQualifier);
    }

    public String toString() {
        return getTransactionKey();
    }
    
    public boolean isXATransaction() {
        return true;
    }

    public boolean isLocalTransaction() {
        return false;
    }

    /**
     * @openwire:property version=1
     */
    public int getFormatId() {
        return formatId;
    }

    /**
     * @openwire:property version=1
     */
    public byte[] getGlobalTransactionId() {
        return globalTransactionId;
    }

    /**
     * @openwire:property version=1
     */
    public byte[] getBranchQualifier() {
        return branchQualifier;
    }

    public void setBranchQualifier(byte[] branchQualifier) {
        this.branchQualifier = branchQualifier;
        this.hash=0;
    }

    public void setFormatId(int formatId) {
        this.formatId = formatId;
        this.hash=0;
    }

    public void setGlobalTransactionId(byte[] globalTransactionId) {
        this.globalTransactionId = globalTransactionId;
        this.hash=0;
    }

    public int hashCode() {
        if( hash==0 ) {
            hash = formatId;
            hash = hash(globalTransactionId, hash);
            hash = hash(branchQualifier, hash);
            if (hash == 0) {
                hash = 0xaceace;
            }
        }
        return hash;
    }

    private static int hash(byte[] bytes, int hash) {
        for (int i = 0, size = bytes.length; i < size; i++) {
            hash ^= bytes[i] << ((i % 4) * 8);
        }
        return hash;
    }
    
    public boolean equals(Object o) {
        if( o==null || o.getClass()!=XATransactionId.class )
            return false;
        XATransactionId xid = (XATransactionId)o;
        return xid.formatId==formatId && Arrays.equals(xid.globalTransactionId,globalTransactionId)
               && Arrays.equals(xid.branchQualifier, branchQualifier);
    }
    
}

@@ -858,17 +858,16 @@
 Arrays;%0A
-%0A
 import j
@@ -891,17 +891,16 @@
 xa.Xid;%0A
-%0A
 import o
@@ -1074,17 +1074,28 @@
 ents Xid
- 
+, Comparable
 %7B%0A    %0A 
@@ -1319,24 +1319,69 @@
 t int hash;%0A
+    private transient String transactionKey;%0A
     %0A    pub
@@ -1736,24 +1736,37 @@
 %0A    public 
+synchronized 
 String getTr
@@ -1779,17 +1779,16 @@
 ionKey()
- 
 %7B%0A      
@@ -1789,23 +1789,69 @@
         
-return 
+if(transactionKey==null)%7B%0A            transactionKey=
 %22XID:%22+f
@@ -1908,24 +1908,45 @@
 ctionId)+%22:%22
+%0A                    
 +HexSupport.
@@ -1974,24 +1974,65 @@
 Qualifier);%0A
+        %7D%0A        return transactionKey;%0A
     %7D%0A%0A    p
@@ -3872,20 +3872,268 @@
 fier);%0A    %7D
+%0A%0A    public int compareTo(Object o)%7B%0A        if( o==null %7C%7C o.getClass()!=XATransactionId.class )%0A            return -1;%0A        XATransactionId xid = (XATransactionId)o;%0A        return getTransactionKey().compareTo(xid.getTransactionKey());%0A    %7D
 %0A    %0A%7D%0A

implement Comparable (well, badly)