/*
 * Copyright 2006-2007 Queplix Corp.
 *
 * Licensed under the Queplix Public License, Version 1.1.1 (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.queplix.com/solutions/commercial-open-source/queplix-public-license/
 *
 * 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 com.queplix.core.modules.alert.utils;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.utils.cache.JBossCache;
import org.jboss.cache.CacheException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * Alert implementation of JBoss Cache.
 *
 * @author [ALB] Baranov Andrey
 * @version $Revision: 1.3 $ $Date: 2005/10/26 14:03:51 $
 */

public class JBossAlertCache
        extends JBossCache implements AlertCache {

    /**
     * Default constructor
     */
    public JBossAlertCache() {
        // Cache must be closed.
        close();
    }

    /*
     * No javadoc
     * @see AlertCache#init
     */
    public synchronized void init() {

        logger.INFO("Calling JBossAlertCache#init");

        if(isOpen()) {
            // .. already initialized
            throw new IllegalStateException("Cache already initialized!");
        }

        // Cache is initialized!
        open();

        // Load all data and put to the cache.
        Collection list = AlertPropertyFactory.getInstance().getAlertDAO()
                .loadAllAlertVO();
        if(list != null) {

            // Use <code>Cache#put(Map)</code> method!
            Map map = new TreeMap();
            for(Iterator it = list.iterator(); it.hasNext();) {
                AlertVO alertVO = (AlertVO) it.next();
                map.put(getAlertVOKey(alertVO), alertVO);
            }

            // Add TreeMap to the cache.
            put(map);
        }
    }

    /*
     * No javadoc
     * @see AlertCache#isInitialized
     */
    public boolean isInitialized() {
        // Use <code>open</code> flag.
        return isOpen();
    }

    /*
     * No javadoc
     * @see JBossCache#clear
     */
    public synchronized void clear() {

        logger.INFO("Calling JBossAlertCache#clear");

        try {
            // Remove entry locally
            cache._remove(cache.getCurrentTransaction(), getNodeName(), false);

        } catch (CacheException ex) {
            logger.ERROR(ex);

        } finally {
            // .. reset initialized flag -- close cache
            close();
        }
    }

    /*
     * No javadoc
     * @see AlertCache#put
     */
    public void put(AlertVO alertVO) {
        put(getAlertVOKey(alertVO), alertVO);
    }

    /*
     * No javadoc
     * @see JBossCache#headMap
     */
    public SortedMap headMap(Comparable toKey) {

        SortedSet keys = _keys();
        if(keys == null) {
            return null;
        }

        SortedSet foundKeys = keys.headSet(toKey);
        if(foundKeys != null && foundKeys.size() > 0) {
            SortedMap ret = new TreeMap();
            for(Iterator it = foundKeys.iterator(); it.hasNext();) {
                Object key = it.next();
                Object o = get(key);
                if(o != null) {
                    ret.put(key, o);
                }
            }
            return ret;
        } else {
            return null;
        }
    }

    /*
     * No javadoc
     * @see JBossCache#subMap
     */
    public SortedMap subMap(Comparable fromKey, Comparable toKey) {

        SortedSet keys = _keys();
        if(keys == null) {
            return null;
        }

        SortedSet foundKeys = keys.subSet(fromKey, toKey);
        if(foundKeys != null && foundKeys.size() > 0) {
            SortedMap ret = new TreeMap();
            for(Iterator it = foundKeys.iterator(); it.hasNext();) {
                Object key = it.next();
                Object o = get(key);
                if(o != null) {
                    ret.put(key, o);
                }
            }
            return ret;
        } else {
            return null;
        }
    }

    /*
     * No javadoc
     * @see JBossCache#tailMap
     */
    public SortedMap tailMap(Comparable fromKey) {

        SortedSet keys = _keys();
        if(keys == null) {
            return null;
        }

        SortedSet foundKeys = keys.tailSet(fromKey);
        if(foundKeys != null && foundKeys.size() > 0) {
            SortedMap ret = new TreeMap();
            for(Iterator it = foundKeys.iterator(); it.hasNext();) {
                Object key = it.next();
                Object o = get(key);
                if(o != null) {
                    ret.put(key, o);
                }
            }
            return ret;
        } else {
            return null;
        }
    }

    /*
     * No javadoc
     * @see JBossCache#toMap
     */
    public SortedMap toMap() {

        SortedSet keys = _keys();
        if(keys == null) {
            return null;
        }

        SortedMap ret = new TreeMap();
        for(Iterator it = keys.iterator(); it.hasNext();) {
            Object key = it.next();
            Object o = get(key);
            if(o != null) {
                ret.put(key, o);
            }
        }

        return ret;
    }

    /*
     * No javadoc
     * @see JBossCache#containsKey
     */
    public boolean containsKey(Object key) {
        Collection keys = keys();
        if(keys != null) {
            return keys.contains(key);
        } else {
            return false;
        }
    }

    /*
     * No javadoc
     * @see JBossCache#keys
     */
    public Collection keys() {
        try {
            return cache.getKeys(getNodeName());
        } catch (CacheException ex) {
            logger.ERROR(ex);
            throw new GenericSystemException(ex);
        }
    }

    /*
     * No javadoc
     * @see JBossCache#getLastKey
     */
    public Object getLastKey() {
        SortedSet keys = _keys();
        if(keys == null) {
            return null;
        }
        return keys.last();
    }

    /*
     * No javadoc
     * @see JBossCache#getFirstKey
     */
    public Object getFirstKey() {
        SortedSet keys = _keys();
        if(keys == null) {
            return null;
        }
        return keys.first();
    }

    /*
     * No javadoc
     * @see JBossCache#values
     */
    public Collection values() {
        SortedSet keys = _keys();
        if(keys == null) {
            return null;
        }

        List ret = new ArrayList(keys.size());
        for(Iterator it = keys.iterator(); it.hasNext();) {
            Object key = it.next();
            Object o = get(key);
            if(o != null) {
                ret.add(o);
            }
        }

        return ret;
    }

    /*
     * No javadoc
     * @see JBossCache#isEmpty
     */
    public boolean isEmpty() {
        Collection c = keys();
        return (c == null || c.isEmpty());
    }

    /*
     * No javadoc
     * @see Object#toString
     */
    public String toString() {
        return "AlertCache: open=" + isOpen() + "; keys=" + keys();
    }

    // ----------------------------------------------------- protected methods

    //
    // Get keys in sorted order.
    //

    protected SortedSet _keys() {
        Collection c = keys();
        if(c == null || c.isEmpty()) {
            return null;
        } else {
            return new TreeSet(c);
        }

    }

    //
    // AlertVO key getter. Used in cache.
    //
    protected Object getAlertVOKey(AlertVO alertVO) {
        return new Long(alertVO.getAlertID());
    }
}
