MapReader.java

/*
 * GovWay - A customizable API Gateway 
 * https://govway.org
 * 
 * Copyright (c) 2005-2024 Link.it srl (https://link.it). 
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3, as published by
 * the Free Software Foundation.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */


package org.openspcoop2.utils.resources;

import java.util.Collection;
import java.util.Enumeration;
import java.util.Map;

import org.apache.commons.collections.FastHashMap;
import org.apache.commons.collections.iterators.IteratorEnumeration;

/**
 * HashMapReader
 *
 * @author Poli Andrea (apoli@link.it)
 * @author $Author$
 * @version $Rev$, $Date$
 */
public class MapReader<K,V> {

	protected Map<K, V> javaMap;
	protected boolean readCallsNotSynchronized = false;
	protected FastHashMap fastMap;
	
	public MapReader(Map<K, V> map, boolean readCallsNotSynchronized){
		this.readCallsNotSynchronized = readCallsNotSynchronized;
		if(this.readCallsNotSynchronized){
			
			// NOTE: This class is not cross-platform. 
			// Using it may cause unexpected failures on some architectures. 
			// It suffers from the same problems as the double-checked locking idiom. 
			// In particular, the instruction that clones the internal collection and the instruction that sets the internal reference to the clone 
			// can be executed or perceived out-of-order. 
			// This means that any read operation might fail unexpectedly, 
			// as it may be reading the state of the internal collection before the internal collection is fully formed. 
			// For more information on the double-checked locking idiom, see the Double-Checked Locking Idiom Is Broken Declaration.
			// http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/index.html
			// http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
			
			// In pratica non effettuare mai delle PUT dopo aver creato l'oggetto.
			// Usare solo in lettura.
			// Questo garantisce che non si presenta il problema sopra descritto
			
			this.fastMap = new FastHashMap(map);
			this.fastMap.setFast(true);
			/**Enumeration<?> keys = this.javaProperties.keys();
			while (keys.hasMoreElements()) {
				Object key = (Object) keys.nextElement();
				this.fastProperties.put(key, properties.get(key));
			}*/
		}
		else{
			this.javaMap = map;
		}
	}
	
	public V get(K key) {
		return this.getValue(key);
	}
	
	@SuppressWarnings("unchecked")
	public V getValue(K key) {
		Object o = null;
		if(this.readCallsNotSynchronized){
			o = this.fastMap.get(key);
		}else{
			o = this.javaMap.get(key);
		}
		if(o==null){
			return null;
		}
		else{
			return (V) o;
		}
	}
	
	@SuppressWarnings("unchecked")
	public java.util.Enumeration<K> keys(){
		if(this.readCallsNotSynchronized){
			return (new IteratorEnumeration(this.fastMap.keySet().iterator()));
		}else{
			return (new IteratorEnumeration(this.javaMap.keySet().iterator()));
		}
	}
	
	@SuppressWarnings("unchecked")
	public Collection<V> values(){
		if(this.readCallsNotSynchronized){
			return this.fastMap.values();
		}else{
			return this.javaMap.values();
		}
	}
	
	@SuppressWarnings("unchecked")
	public Enumeration<V> elements(){
		return new IteratorEnumeration(this.values().iterator());
	}
	
	public boolean containsKey(K key){
		if(this.readCallsNotSynchronized){
			return this.fastMap.containsKey(key);
		}else{
			return this.javaMap.containsKey(key);
		}
	}
	
	public int size(){
		if(this.readCallsNotSynchronized){
			return this.fastMap.size();
		}else{
			return this.javaMap.size();
		}
	}
}