/*
 * Creado el 09-feb-04
 */
package es.ejie.frmk.infraestructura.poolCache;

import java.util.ConcurrentModificationException;
import java.util.Map;
import java.util.TimerTask;

import es.ejie.frmk.Q70Factoria;
import es.ejie.frmk.control.excepciones.Q70GestorDeExcepcionesServidor;
import es.ejie.frmk.infraestructura.traza.Q70TraceLevel;
import es.ejie.frmk.infraestructura.traza.Q70TrazaInterface;

/**
 * Clase que representa la caché. Es decir, un almacén de Q70ElementoCache y
 * una algoritmo de limpieza.
 * @version 1.0 Fecha: 09-feb-04 (Q70LimpiarCache)
 * @version 2.0 Fecha: 21-feb-06
 */
public class Q70Cache extends TimerTask{
	private Map cacheMap;
	private long tAcceso;
	private long tVida;
	
	/** 
	 * @param cMap Alamacén de Q70ElementoCache
	 * @param tAcceso Tiempo de inactividad de un elemento de la caché.
	 * @param tVida Tiempo de vida de un elemento de la caché.
	 */
	public Q70Cache(Map cMap, Long tAcceso, Long tVida){
		this.cacheMap = cMap;
		this.tAcceso = tAcceso.longValue();
		this.tVida = tVida.longValue();
	}

	/**
	 * Algoritmo de limpieza de la caché.
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		Q70TrazaInterface traza = Q70Factoria.getTraza();
		try {
			long ahora = System.currentTimeMillis();
			synchronized(cacheMap) {
				/** @version 2.0
				 * Si la cache está vacia que no siga el proceso de limpieza **/				
				if (cacheMap.size()>0) {			
					Object[] key = cacheMap.keySet().toArray();
					for(int i = 0; i < key.length; i++){                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
						Q70ElementoCache elementoCache = (Q70ElementoCache) cacheMap.get(key[i]);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
						if (elementoCache == null || elementoCache.hasExpired(ahora, tAcceso, tVida)) {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
							cacheMap.remove(key[i]);
							if (traza.isTraceActive()){
								traza.trace(Q70Constantes.ID_COMPONENTE, Q70TraceLevel.DEBUG,
								"El elemento con clave: "+key[i]+" ha sido borrado de la cache por la tarea de limpieza.");
							}
							Thread.yield();                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
						}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
					}
				}
			}
		} catch (ConcurrentModificationException e) {
			Q70GestorDeExcepcionesServidor.getSingleton().recogerThrowable(e);
			/** @version 1.0 **/
			//Q70GestorCache.getSingleton().reinitialize();
			/** @version 2.0 **/
			if (traza.isTraceActive()){
				traza.trace(Q70Constantes.ID_COMPONENTE, Q70TraceLevel.ERROR, "ERROR al modificar concurrentemente una caché en su proceso de limpieza. Se eliminarán todos sus elementos.");
			}
			cacheMap.clear();
		} catch (Exception e) {
			Q70GestorDeExcepcionesServidor.getSingleton().recogerThrowable(e);			
			if (traza.isTraceActive()){
				traza.trace(Q70Constantes.ID_COMPONENTE, Q70TraceLevel.ERROR, "ERROR en el proceso de limpieza de la caché.");
			}
		}
	}

	/**
	 * @return Returns the cacheMap.
	 */
	public Map getCacheMap() {
		return cacheMap;
	}

	/**
	 * @param cacheMap The cacheMap to set.
	 */
	public void setCacheMap(Map cacheMap) {
		this.cacheMap = cacheMap;
	}

	/**
	 * @return Returns the tAcceso.
	 */
	public long getTAcceso() {
		return tAcceso;
	}

	/**
	 * @param acceso The tAcceso to set.
	 */
	public void setTAcceso(long acceso) {
		tAcceso = acceso;
	}

	/**
	 * @return Returns the tVida.
	 */
	public long getTVida() {
		return tVida;
	}

	/**
	 * @param vida The tVida to set.
	 */
	public void setTVida(long vida) {
		tVida = vida;
	}
}
