View Javadoc

1   package cz.cuni.amis.utils.maps;
2   
3   import java.util.Collections;
4   import java.util.HashMap;
5   import java.util.Map;
6   
7   /**
8    * Map containing other maps. Whenever a map under some key is requested and does not exists,
9    * the HashMapMap automatically creates new one.
10   * <p><p>
11   * The implementation is unsynchronized, created maps are synchronized (just iteration over the inner-map must
12   * be synchronized by the user as described in Java(tm) documentation).
13   * 
14   * @author Jimmy
15   *
16   * @param <PRIMARY_KEY>
17   * @param <SECONDARY_KEY>
18   * @param <ITEM>
19   */
20  public abstract class LazyMapMap<PRIMARY_KEY, SECONDARY_KEY, ITEM> extends HashMap<PRIMARY_KEY, Map<SECONDARY_KEY, ITEM>> {
21  	
22  	public LazyMapMap() {
23  	}
24  	
25  	/**
26       * Creates value for given key.
27       * @param key
28       * @return
29       */
30      protected abstract ITEM create(SECONDARY_KEY key);
31  
32  	/**
33  	 * The get method ensures that the requested map under primaryKey always exists!
34  	 * 
35  	 * @param primaryKey must be instance of PRIMARY_KEY
36  	 */
37  	@Override
38  	public Map<SECONDARY_KEY, ITEM> get(Object primaryKey) {
39  		Map<SECONDARY_KEY, ITEM> map = super.get(primaryKey);
40  		if (map != null) return map;
41  		map = Collections.synchronizedMap(new LazyMap<SECONDARY_KEY, ITEM>(){
42  			@Override
43  			protected ITEM create(SECONDARY_KEY key) {
44  				return LazyMapMap.this.create(key);
45  			}
46  		});
47  		super.put((PRIMARY_KEY)primaryKey, map);
48  		return map;
49  	}
50  	
51  	/**
52  	 * Returns an item under primary and secondary key if exists (otherwise a null is returned).
53  	 * @param primaryKey
54  	 * @param secondaryKey
55  	 * @return
56  	 */
57  	public ITEM get(PRIMARY_KEY primaryKey, SECONDARY_KEY secondaryKey) {
58  		return get(primaryKey).get(secondaryKey);
59  	}
60  	
61  	/**
62  	 * Inserts an item under primary and then secondary key.
63  	 * @param primaryKey
64  	 * @param secondaryKey
65  	 * @param item
66  	 */
67  	public void put(PRIMARY_KEY primaryKey, SECONDARY_KEY secondaryKey, ITEM item) {
68  		get(primaryKey).put(secondaryKey, item);
69  	}
70  	
71  	/**
72  	 * Remove returns the removed item, if item was non-existent, it returns empty map. 
73  	 * @param primaryKey
74  	 * @return
75  	 */
76  	@Override
77  	public Map<SECONDARY_KEY, ITEM> remove(Object primaryKey) {
78  		Map<SECONDARY_KEY, ITEM> map = super.remove(primaryKey);
79  		if (map != null) return map;
80  		return Collections.synchronizedMap(new LazyMap<SECONDARY_KEY, ITEM>(){
81  			@Override
82  			protected ITEM create(SECONDARY_KEY key) {
83  				return LazyMapMap.this.create(key);
84  			}
85  		});
86  	}
87  
88  	/**
89  	 * Removes an item from the map.
90  	 * @param primaryKey
91  	 * @param secondaryKey
92  	 * @return
93  	 */
94  	public ITEM remove(PRIMARY_KEY primaryKey, SECONDARY_KEY secondaryKey) {
95  		return get(primaryKey).remove(secondaryKey);
96  	}
97  
98  }