/*
 * JBoss, Home of Professional Open Source
 * Copyright 2007, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags.
 * See the copyright.txt in the distribution for a full listing
 * of individual contributors.
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License, v. 2.0.
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License,
 * v. 2.0 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 *
 * (C) 2007,
 * @author JBoss Inc.
 */
package org.jboss.txbridge.ba.compensation;

import org.apache.log4j.Logger;

import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * This component is responsible for ensuring that a proper Compensation Manager is provided
 * during execution of a service or a compensation action. It associates compensation managers
 * with proper threads of execution.
 *
 * @author Maciej P. Machulak (mmachulak@redhat.com)
 * @version 0.1
 */
public class CompensationManagerProvider
{
    private static Logger log = Logger.getLogger(CompensationManagerProvider.class);

    private static volatile CompensationManagerProvider cmp = null;

    private static ConcurrentMap<Long,CompensationManager> cmList;

    private CompensationManagerProvider()
    {
        cmList = new ConcurrentHashMap<Long,CompensationManager>();
    }

    /**
     * Returns the instance fo a compensation manager provider.
     *
     * @return the compensation manager.
     */
    public static CompensationManagerProvider getSingletonInstance()
    {
        log.info("getSingletonInstance()");
        if (cmp == null)
        {
            synchronized (CompensationManagerProvider.class)
            {
                if (cmp == null)
                {
                    log.info("Creating a new instance");
                    cmp = new CompensationManagerProvider();
                }
            }
        }
        return cmp;
    }

    /**
     * This method associates a compensation manager with a given thread of execution.
     *
     * @param thread is the thread for which the compensation manager should be associated.
     * @param cmp is the compensation manager, which should be associated.
     */
    public void associateCompensationManager(Long thread, CompensationManager cmp)
    {
        log.info("associateCompensationManager()");
        cmList.put(thread,cmp);
    }

    /**
     * This method returns the compensation manager object associated to a certain thread of execution.
     * If there is no compensation manager associated to a certain thread of execution then it means
     * the service is being executed outside the scope of the Business Activity and a dummy compensation
     * manager is simply returned.
     *
     * @param thread thread ID for which the compensation manager should be returned.
     * @return the CompensationManager object.
     */
    public CompensationManager getCompensationManager(Long thread)
    {
        log.info("getCompensationManager()");
        CompensationManager cm = cmList.get(thread);
        if (cm == null)
        {
            log.info("Returning a dummy compensation manager");
            cm = new DummyCompensationManager();
        }
        return cm;
    }

    /**
     * This method removes the association of a thread and a compensation manager.
     *
     * @param thread is the thread for which the associaction should be removed.
     */
    public void removeCompensationManager(Long thread)
    {
        log.info("removeCompensationManager()");
        cmList.remove(thread);
    }
}
