/*
 * 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.utils.cache;

import com.queplix.core.error.GenericSystemException;
import com.queplix.core.utils.StringHelper;
import com.queplix.core.utils.log.AbstractLogger;
import com.queplix.core.utils.log.Log;
import org.jboss.cache.CacheException;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * <p>JBoss cache implementation of com.queplix.core.utils.cache.Cache</p>
 *
 * @author [ALB] Baranov Andrey
 * @version 1.0
 */

public class JBossCache
        extends AbstractCache {

    /**
     * 'Node' property name
     */
    public static final String NODE_PROPERTY = "node";

    // Logger.
    protected AbstractLogger logger = Log.getLog(getClass());

    // JBoss Tree Cache Wrapper.
    protected JBossCacheWrapper cache;

    // Node name.
    private String nodeName;

    /*
     * No javadoc
     * @see AbstractCache#setProperties
     */
    public void setProperties(Properties prop) {

        super.setProperties(prop);

        // Initialization.
        nodeName = (String) getProperty(NODE_PROPERTY);
        cache = JBossCacheManager.getInstance().get();

        if(StringHelper.isEmpty(nodeName)) {
            throw new NullPointerException(
                    "Cannot find property: " + NODE_PROPERTY +
                            " in " + prop);
        }

        if(logger.getLogger().isInfoEnabled()) {
            logger.INFO("JBossCache#setProperties():");
            logger.INFO(toString());
        }
    }

    /*
     * No javadoc
     * @see Cache#get
     */
    public Object get(Object key) {
        try {
            return cache.get(getNodeName(), key);
        } catch (CacheException ex) {
            logger.ERROR(ex);
            throw new GenericSystemException(ex);
        }
    }

    /*
     * No javadoc
     * @see Cache#headMap
     */
    public SortedMap headMap(Comparable toKey) {
        throw new UnsupportedOperationException();
    }

    /*
     * No javadoc
     * @see Cache#subMap
     */
    public SortedMap subMap(Comparable fromKey, Comparable toKey) {
        throw new UnsupportedOperationException();
    }

    /*
     * No javadoc
     * @see Cache#tailMap
     */
    public SortedMap tailMap(Comparable fromKey) {
        throw new UnsupportedOperationException();
    }

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

        Collection 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 Cache#containsKey
     */
    public boolean containsKey(Object key) {
        return cache.exists(getNodeName(), key);
    }

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

    /*
     * No javadoc
     * @see Cache#getLastKey
     */
    public Object getLastKey() {
        throw new UnsupportedOperationException();
    }

    /*
     * No javadoc
     * @see Cache#getFirstKey
     */
    public Object getFirstKey() {
        throw new UnsupportedOperationException();
    }

    /*
     * No javadoc
     * @see Cache#values
     */
    public Collection values() {
        throw new UnsupportedOperationException();
    }

    /*
     * No javadoc
     * @see Cache#put(Object, Object)
     */
    public void put(Object key, Object o) {
        if(!isOpen()) {
            throw new IllegalStateException("Cache closed");
        }

        try {
            cache.put(getNodeName(), key, o);
        } catch (CacheException ex) {
            logger.ERROR(ex);
            throw new GenericSystemException(ex);
        }
    }

    /*
     * No javadoc
     * @see Cache#put(Map)
     */
    public void put(Map _map) {
        if(!isOpen()) {
            throw new IllegalStateException("Cache closed");
        }

        try {
            cache.put(getNodeName(), _map);
        } catch (CacheException ex) {
            logger.ERROR(ex);
            throw new GenericSystemException(ex);
        }
    }

    /*
     * No javadoc
     * @see Cache#remove
     */
    public void remove(Object key) {
        if(!isOpen()) {
            throw new IllegalStateException("Cache closed");
        }

        try {
            cache.remove(getNodeName(), key);
        } catch (CacheException ex) {
            logger.ERROR(ex);
            throw new GenericSystemException(ex);
        }
    }

    /*
     * No javadoc
     * @see Cache#clear
     */
    public void clear() {
        try {
            cache.remove(getNodeName());
        } catch (CacheException ex) {
            logger.ERROR(ex);
            throw new GenericSystemException(ex);
        }
    }

    /*
     * No javadoc
     * @see Cache#isEmpty
     */
    public boolean isEmpty() {
        Collection keys = keys();
        return keys == null ? true:keys.isEmpty();
    }

    /*
     * No javadoc
     * @see Object#toString
     */
    public String toString() {
        return
                "JBossCache: node name=" + nodeName +
                        "; open=" + isOpen() + "; tree cache:\n" + cache;
    }

    /**
     * Node Name getter.
     *
     * @return String or NULL
     */
    protected String getNodeName() {
        return nodeName;
    }
}
