/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2009 France Telecom R&D
 * Copyright (C) 2012 Bull S.A.S.
 * Contact: jonas-team@ow2.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 (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.jndi.checker.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import org.ow2.jonas.jndi.checker.api.IResourceChecker;
import org.ow2.jonas.jndi.checker.api.IResourceCheckerInfo;
import org.ow2.jonas.jndi.checker.api.IResourceCheckerManager;

/**
 * Manager of all the resources that need to be checked.
 * This kind of interceptors are called
 */
public class ResourceCheckerManager implements IResourceCheckerManager {

    /**
     * Build a new Resource checker manager by using a thread local providing a list of enlisted resources.
     */
    private static ThreadLocal<Stack<List<IResourceChecker>>> resourcesThread = new ThreadLocal<Stack<List<IResourceChecker>>>() {
        protected Stack<List<IResourceChecker>> initialValue() {
            Stack<List<IResourceChecker>> stack = new Stack<List<IResourceChecker>>();
            List<IResourceChecker> list = new ArrayList<IResourceChecker>();
            stack.push(list);
            return stack;
        }
    };

    /**
     * Push a new list on the stack.
     */
    public void push() {
        resourcesThread.get().push(new ArrayList<IResourceChecker>());
    }

    /**
     * Pop the list on the stacK.
     */
    public void pop() {
        resourcesThread.get().pop();
    }

    /**
     * Enlist a new resource.
     * @param resource the given resource that can be checked.
     */
    public void enlistResource(final IResourceChecker resource) {
        if (!getResourcesInternal().contains(resource)) {
            getResourcesInternal().add(resource);
        }
    }

    /**
     * Delist a resource.
     * @param resource the given resource.
     */
    public void delistResource(final IResourceChecker resource) {
        getResourcesInternal().remove(resource);
    }

    /**
     * Delist all resources that are enlisted.
     */
    public void delistAll() {
        getResourcesInternal().clear();
    }

    /**
     * Call detect method on each enlisted resource.
     * @param resourceCheckerInfo some data for the resource checker
     */
    public void detect(final IResourceCheckerInfo resourceCheckerInfo) {
        List<IResourceChecker> resourceCheckers = getResources();
        for (IResourceChecker resourceChecker : resourceCheckers) {
            resourceChecker.detect(resourceCheckerInfo);
        }
    }

    /**
     * This method has to be used only when the real list reference is required.
     * @return list of resources enlisted on the current thread.
     */
    private List<IResourceChecker> getResourcesInternal() {
        return resourcesThread.get().peek();
    }

    /**
     * This method returns a copy of the internal resources list.
     * @return list of resources enlisted on the current thread.
     */
    public List<IResourceChecker> getResources() {
        return new ArrayList<IResourceChecker>(getResourcesInternal());
    }
}
