001/* 002 * ============================================================================ 003 * Copyright © 2002-20123 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * Licensed to the public under the agreements of the GNU Lesser General Public 007 * License, version 3.0 (the "License"). You may obtain a copy of the License at 008 * 009 * http://www.gnu.org/licenses/lgpl.html 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package org.tquadrat.foundation.util.internal; 019 020import static java.util.Collections.emptySet; 021import static org.apiguardian.api.API.Status.INTERNAL; 022import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 023 024import java.util.Collection; 025import java.util.Map; 026import java.util.Set; 027import java.util.function.Consumer; 028import java.util.function.Supplier; 029 030import org.apiguardian.api.API; 031import org.tquadrat.foundation.annotation.ClassVersion; 032import org.tquadrat.foundation.lang.Lazy; 033import org.tquadrat.foundation.util.LazyMap; 034 035/** 036 * The implementation for 037 * {@link LazyMap}. 038 * 039 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 040 * @version $Id: LazyMapImpl.java 1060 2023-09-24 19:21:40Z tquadrat $ 041 * @since 0.0.5 042 * 043 * @param <K> The type of keys maintained by this map 044 * @param <V> The type of mapped values 045 * 046 * @UMLGraph.link 047 */ 048@ClassVersion( sourceVersion = "$Id: LazyMapImpl.java 1060 2023-09-24 19:21:40Z tquadrat $" ) 049@API( status = INTERNAL, since = "0.0.5" ) 050public sealed class LazyMapImpl<K,V> implements LazyMap<K,V> 051 permits LazySortedMapImpl 052{ 053 /*------------*\ 054 ====** Attributes **======================================================= 055 \*------------*/ 056 /** 057 * The holder for the real map. 058 */ 059 private final Lazy<? extends Map<K,V>> m_Holder; 060 061 /** 062 * The flag that indicates whether the provided supplier will put values 063 * to the list on initialisation. 064 */ 065 private final boolean m_SupplierPopulates; 066 067 /*--------------*\ 068 ====** Constructors **===================================================== 069 \*--------------*/ 070 /** 071 * Creates a new {@code LazyMapImpl} instance. 072 * 073 * @param doPopulate {@code true} if the provided supplier will put 074 * values to the map on initialisation, {@code false} if it will 075 * create an empty map. 076 * @param supplier The supplier that initialises the internal map for 077 * this instance when it is first needed. 078 */ 079 public LazyMapImpl( final boolean doPopulate, final Supplier<? extends Map<K,V>> supplier ) 080 { 081 m_SupplierPopulates = doPopulate; 082 m_Holder = Lazy.use( supplier ); 083 } // LazyMapImpl() 084 085 /** 086 * Creates a new {@code LazyMapImpl} instance that is initialised with the 087 * given value. 088 * 089 * @param value The initialisation value. 090 */ 091 public LazyMapImpl( final Map<K,V> value ) 092 { 093 m_SupplierPopulates = true; 094 m_Holder = Lazy.of( value ); 095 } // LazyMapImpl() 096 097 /*---------*\ 098 ====** Methods **========================================================== 099 \*---------*/ 100 /** 101 * {@inheritDoc} 102 */ 103 @Override 104 public final void clear() 105 { 106 if( m_SupplierPopulates ) init(); 107 m_Holder.ifPresent( Map::clear ); 108 } // clear() 109 110 /** 111 * {@inheritDoc} 112 */ 113 @Override 114 public final boolean containsKey( final Object key ) 115 { 116 @SuppressWarnings( "unlikely-arg-type" ) 117 final var retValue = (m_Holder.isPresent() || m_SupplierPopulates) && m_Holder.get().containsKey( key ); 118 119 //---* Done *---------------------------------------------------------- 120 return retValue; 121 } // containsKey() 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override 127 public final boolean containsValue( final Object value ) 128 { 129 @SuppressWarnings( "unlikely-arg-type" ) 130 final var retValue = (m_Holder.isPresent() || m_SupplierPopulates) && m_Holder.get().containsValue( value ); 131 132 //---* Done *---------------------------------------------------------- 133 return retValue; 134 } // containsValue() 135 136 /** 137 * {@inheritDoc} 138 */ 139 @Override 140 public final Set<Entry<K,V>> entrySet() 141 { 142 if( m_SupplierPopulates ) init(); 143 final var retValue = m_Holder.map( Map::entrySet ).orElse( emptySet() ); 144 145 //---* Done *---------------------------------------------------------- 146 return retValue; 147 } // entrySet() 148 149 /** 150 * {@inheritDoc} 151 */ 152 @Override 153 public final boolean equals( final Object o ) 154 { 155 var retValue = o == this; 156 if( !retValue && (o instanceof final Map<?,?> other) ) 157 { 158 /* 159 * Collections are equal if their contents is equal. Refer to the 160 * respective Javadoc for equals(). 161 */ 162 if( isPresent() || m_SupplierPopulates ) 163 { 164 retValue = m_Holder.get().equals( other ); 165 } 166 else 167 { 168 retValue = other.isEmpty(); 169 } 170 } 171 172 //---* Done *---------------------------------------------------------- 173 return retValue; 174 } // equals() 175 176 /** 177 * {@inheritDoc} 178 */ 179 @Override 180 public final V get( final Object key ) 181 { 182 if( m_SupplierPopulates ) init(); 183 @SuppressWarnings( "unlikely-arg-type" ) 184 final var retValue = m_Holder.map( map -> map.get( key ) ).orElse( null ); 185 186 //---* Done *---------------------------------------------------------- 187 return retValue; 188 } // get() 189 190 /** 191 * {@inheritDoc} 192 */ 193 @Override 194 public final int hashCode() { return m_Holder.hashCode(); } 195 196 /** 197 * Gives access to the internal 198 * {@link Lazy} 199 * instance for derived classes. 200 * 201 * @return A reference to 202 * {@link #m_Holder}. 203 */ 204 /* 205 * Not final, because it will be overridden by LazySortedMap. 206 */ 207 protected Lazy<? extends Map<K,V>> holder() { return m_Holder; } 208 209 /** 210 * {@inheritDoc} 211 */ 212 @Override 213 public void ifPresent( final Consumer<? super Map<K,V>> consumer ) 214 { 215 //noinspection FunctionalExpressionCanBeFolded 216 m_Holder.ifPresent( requireNonNullArgument( consumer, "consumer" )::accept ); 217 } // ifPresent() 218 219 /** 220 * {@inheritDoc} 221 */ 222 @Override 223 public final void init() { m_Holder.get(); } 224 225 /** 226 * {@inheritDoc} 227 */ 228 @Override 229 public final boolean isEmpty() 230 { 231 final var retValue = (!m_Holder.isPresent() && !m_SupplierPopulates) || m_Holder.get().isEmpty(); 232 233 //---* Done *---------------------------------------------------------- 234 return retValue; 235 } // isEmpty() 236 237 /** 238 * {@inheritDoc} 239 */ 240 @Override 241 public final boolean isPresent() { return m_Holder.isPresent(); } 242 243 /** 244 * {@inheritDoc} 245 */ 246 @Override 247 public final Set<K> keySet() 248 { 249 if( m_SupplierPopulates ) init(); 250 final var retValue = m_Holder.map( Map::keySet ).orElse( emptySet() ); 251 252 //---* Done *---------------------------------------------------------- 253 return retValue; 254 } // keySet() 255 256 /** 257 * {@inheritDoc} 258 */ 259 @Override 260 public final V put( final K key, final V value ) 261 { 262 final var retValue = m_Holder.get().put( key, value ); 263 264 //---* Done *---------------------------------------------------------- 265 return retValue; 266 } // put() 267 268 /** 269 * {@inheritDoc} 270 */ 271 @Override 272 public final void putAll( final Map<? extends K,? extends V> map ) { m_Holder.get().putAll( map ); } 273 274 /** 275 * {@inheritDoc} 276 */ 277 @Override 278 public final V remove( final Object key ) 279 { 280 if( m_SupplierPopulates ) init(); 281 @SuppressWarnings( "unlikely-arg-type" ) 282 final var retValue = m_Holder.map( map -> map.remove( key ) ).orElse( null ); 283 284 //---* Done *---------------------------------------------------------- 285 return retValue; 286 } // remove() 287 288 /** 289 * {@inheritDoc} 290 */ 291 @Override 292 public final int size() 293 { 294 final var retValue = m_Holder.isPresent() || m_SupplierPopulates ? m_Holder.get().size() : 0; 295 296 //---* Done *---------------------------------------------------------- 297 return retValue; 298 } // size() 299 300 /** 301 * {@inheritDoc} 302 */ 303 @Override 304 public final String toString() 305 { 306 final var retValue = m_Holder.isPresent() || m_SupplierPopulates ? m_Holder.getAsString() : "[Not initialized]"; 307 308 //---* Done *---------------------------------------------------------- 309 return retValue; 310 } // toString() 311 312 /** 313 * {@inheritDoc} 314 */ 315 @Override 316 public final Collection<V> values() 317 { 318 if( m_SupplierPopulates ) init(); 319 final var retValue = m_Holder.map( Map::values ).orElse( emptySet() ); 320 321 //---* Done *---------------------------------------------------------- 322 return retValue; 323 } // values() 324} 325// class LazyMapImpl 326 327/* 328 * End of File 329 */