001/* 002 * Copyright c 2018 Rusi Popov, MDA Tools.net All rights reserved. 003 * 004 * This program and the accompanying materials are made available under the terms of the 005 * Eclipse Public License v2.0 which accompanies this distribution, and is available at 006 * http://www.eclipse.org/legal/epl-v20.html 007 */ 008package net.mdatools.modelant.core.util.map; 009 010import java.util.Collection; 011import java.util.HashMap; 012import java.util.HashSet; 013import java.util.Map; 014import java.util.Set; 015 016/** 017 * This class is a composite Map implementation, so that when creating a 018 * new map form another, this implementation does not copy the original, 019 * but any access is delegated to the wrapped one. 020 * @author Rusi Popov (popovr@mdatools.net) 021 */ 022public class CompositeMap<K,V> implements Map<K,V> { 023 024 private final Map<K,V> wrapped; 025 026 /** 027 * Any local changes 028 */ 029 private final Map<K,V> local = new HashMap<>(); 030 031 /** 032 * 033 */ 034 public CompositeMap(Map<K,V> wrapped) { 035 this.wrapped = wrapped; 036 } 037 038 /** 039 * @see java.util.Map#clear() 040 */ 041 public void clear() { 042 wrapped.clear(); 043 local.clear(); 044 } 045 046 /** 047 * @see java.util.Map#containsKey(java.lang.Object) 048 */ 049 public boolean containsKey(Object key) { 050 return local.containsKey( key ) || wrapped.containsKey( key ); 051 } 052 053 /** 054 * @see java.util.Map#containsValue(java.lang.Object) 055 */ 056 public boolean containsValue(Object value) { 057 return local.containsValue( value ) || wrapped.containsValue( value ); 058 } 059 060 /** 061 * @see java.util.Map#get(java.lang.Object) 062 */ 063 public V get(Object key) { 064 V result; 065 066 if ( local.containsKey( key ) ) { // handles key-to-null local bindings 067 result = local.get( key ); 068 } else { 069 result = wrapped.get( key ); 070 } 071 return result; 072 } 073 074 /** 075 * @see java.util.Map#entrySet() 076 */ 077 public Set entrySet() { 078 Set result = new HashSet(); 079 result.addAll( wrapped.entrySet() ); 080 result.addAll( local.entrySet() ); 081 return result; 082 } 083 084 /** 085 * @see java.util.Map#keySet() 086 */ 087 public Set keySet() { 088 Set result = new HashSet(); 089 result.addAll( wrapped.keySet() ); 090 result.addAll( local.keySet() ); 091 return result; 092 } 093 094 /** 095 * @see java.util.Map#values() 096 */ 097 public Collection values() { 098 Set result = new HashSet(); 099 result.addAll( wrapped.values() ); 100 result.addAll( local.values() ); 101 return result; 102 } 103 104 /** 105 * @see java.util.Map#isEmpty() 106 */ 107 public boolean isEmpty() { 108 return local.isEmpty() && wrapped.isEmpty(); 109 } 110 111 /** 112 * @see java.util.Map#put(java.lang.Object, java.lang.Object) 113 */ 114 public V put(K key, V value) { 115 return local.put( key, value ); 116 } 117 118 /** 119 * @see java.util.Map#putAll(java.util.Map) 120 */ 121 public void putAll(Map m) { 122 local.putAll( m ); 123 } 124 125 /** 126 * @see java.util.Map#remove(java.lang.Object) 127 */ 128 public V remove(Object key) { 129 V result; 130 131 if ( local.containsKey( key )) { 132 result = local.remove( key ); 133 } else { 134 result = wrapped.remove( key ); 135 } 136 return result; 137 } 138 139 /** 140 * @see java.util.Map#size() 141 */ 142 public int size() { 143 return local.size() + wrapped.size(); 144 } 145 146 /** 147 * @see java.lang.Object#toString() 148 */ 149 public String toString() { 150 Map local; 151 152 local = new HashMap(this); 153 return local.toString(); 154 } 155}