/*******************************************************************************
* Copyright (c) 2004, 2005 Actuate Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*  Actuate Corporation  - initial API and implementation
*******************************************************************************/ 

package org.eclipse.birt.data.oda.util;

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Locale;

/**
 * This class provides a cache-like functionality for storing of resource bundles. The class
 * maintains a linked list of such bundles whose keys are stored in a hashtable. This class
 * provides the mechanism to load a resource from the cache of stored bundles. If the desired
 * resource is not found in the cache, the same is loaded afresh and added into the cache,
 * provided the cache limit is not exceeded, in which case, the last resource is removed from
 * the cache and the new one is added in to the list for future use. This class also provides
 * a method to analyze the content of the cache using the locale provided. The method displays
 * messages like the maximum limit of cache, number of resources held under the cache, name of
 * the resources, display language/country of the resource, etc. On can also set the maximum
 * limit of the cache.
 *
 * @deprecated	As of BIRT 2.0, replaced by
 * 		{@link org.eclipse.datatools.connectivity.oda.util.ResourceCache 
 * 				org.eclipse.datatools.connectivity.oda.util.ResourceCache} .
 * 		<br>The BIRT ODA run-time framework has been migrated to the 
 * 		Eclipse Data Tools Platform (DTP) project.
 */
public final class ResourceCache
{
    /**
     *
     */
    private transient int m_iMaxBundles = 15;

    /**
     *
     */
    private transient Hashtable m_htRC = new Hashtable( 15 );

    /**
     *
     */
    private transient LinkedList m_llRC = new LinkedList( );

    /**
     *
     */
    private static transient ResourceCache sm_rc = null;

    /**
     * Singleton; cannot be instantiated
     */
    private ResourceCache( ) { }

    /**
     *
     * @return	ResourceCache
     */
    public synchronized static final ResourceCache instance( )
    {
        if( sm_rc == null )
        {
			sm_rc = new ResourceCache( );
		}
        return sm_rc;
    }

    /**
     *
     * @param      sFQClass
     * @param      lo
     * @return	   ResourceManager
     * @exception  IllegalArgumentException
     */
	public synchronized final ResourceManager getResources( String sFQClass, Locale lo ) throws IllegalArgumentException
	{
        if( lo == null )
        {
            lo = Locale.getDefault( );
        }

		RCKey k = new RCKey( sFQClass, lo );

        ResourceManager rm =( ResourceManager ) m_htRC.get( k );
        if( rm == null ) // IF DOESN'T EXIST IN CACHE,
        {
            if( m_htRC.size( ) >= m_iMaxBundles ) // IF CACHE SIZE HAS REACHED LIMIT, REMOVE LAST
            {
                RCKey kRemove =( RCKey ) m_llRC.removeLast( );
                if( kRemove != null )
                {
                    m_htRC.remove( kRemove );
                }
            }
            rm = ResourceManager.loadResources( sFQClass, lo );
            m_htRC.put( k, rm );
            m_llRC.addFirst( k ); // ALWAYS ADD TO TOP OF LIST
        }
        else if( m_htRC.size( ) > 1 ) // DON'T NEED TO RE-INSERT IF CACHE CONTAINS ONLY A SINGLE ELEMENT
        {
            m_llRC.remove( k );
            m_llRC.addFirst( k ); // ALWAYS ADD TO TOP OF LIST
        }

        return rm;
	}

    /**
     *
     */
    public final void flushCache( )
    {
        // TODO
    }

    /**
     *
     * @param      iMaxBundles
     */
    public final void setCacheSize( int iMaxBundles )
    {
        this.m_iMaxBundles = iMaxBundles;
    }


    /**
     *
    	     */
    private static final class RCKey
    {
        /**
         *
         */
        private transient String sResourceName = null;

        /**
         *
         */
        private transient Locale lo = null; // MUST STAY AS java.util.Locale;

        /**
         *
         * @param      sResourceName
         * @param      lo
         * @exception  IllegalArgumentException
         */
        RCKey( String sResourceName, Locale lo ) throws IllegalArgumentException
        {
            this.sResourceName = sResourceName;
            if( sResourceName == null )
            {
				throw new IllegalArgumentException( "ResourceCache : NULL value not allowed for a resource bundle name" );
			}
            if( lo == null )
            {
				lo = Locale.getDefault( );
			}
            this.lo = lo;
        }

        /**
         *
         * @return	int
         */
        public int hashCode( )
        {
            String s = toString( );
            int hc = 0 ;
            final int n = s.length( );
            for( int i = 0; i < n; i++ )
            {
				hc +=( s.charAt( i ) * 2 ) ;
			}
            return hc;
        }

        /**
         *
         * @param      o
         * @return	   boolean
         */
        public boolean equals( Object o )
        {
            if( o == null || !( o instanceof RCKey ) )
            {
				return false;
			}
            RCKey k =( RCKey ) o;
            return( k.sResourceName.equals( sResourceName ) && k.lo.toString( ).equals( lo.toString( ) ) );
        }

        /**
         *
         * @return		String
         */
        public String toString( ) { return sResourceName + " [" + lo.toString( ) + "] "; }
    }
}

