All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.staccatocommons.lang.MapBuilder Maven / Gradle / Ivy

/**
 *  Copyright (c) 2011, The Staccato-Commons Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; version 3 of the License.
 *
 *  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 Lesser General Public License for more details.
 */

package net.sf.staccatocommons.lang;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;

import net.sf.staccatocommons.defs.Applicable;
import net.sf.staccatocommons.defs.function.Function;
import net.sf.staccatocommons.lang.builder.Builder;
import net.sf.staccatocommons.lang.builder.BuilderAlreadyUsedException;
import net.sf.staccatocommons.lang.function.AbstractFunction;
import net.sf.staccatocommons.lang.function.Functions;
import net.sf.staccatocommons.restrictions.Constant;
import net.sf.staccatocommons.restrictions.check.NonNull;
import net.sf.staccatocommons.restrictions.value.Unmodifiable;

/**
 * A {@link Builder} for {@link Map}s. With the exception of
 * {@link #from(Map, Applicable)}, all factory methods of {@link MapBuilder}
 * grant to return builders that build {@link Unmodifiable} maps
 * 
 * @author fbulgarelli
 * 
 * @param 
 * @param 
 * @param 
 */
public class MapBuilder> implements Builder {

  private M map;
  private Applicable wrapperFunction;

  /**
   * 
   * Creates a new {@link MapBuilder}
   * 
   * @param map
   *          the map to build. Non null
   */
  public MapBuilder(@NonNull M map, @NonNull Applicable wrapperFunction) {
    this.map = map;
    this.wrapperFunction = wrapperFunction;
  }

  /**
   * Adds a key-value pair to the map
   * 
   * @param key
   * @param value
   * @return this {@link MapBuilder}
   */
  @NonNull
  public MapBuilder with(K key, V value) {
    map.put(key, value);
    return this;
  }

  /**
   * Adds an entry to the map
   * 
   * @param entry
   *          the entry to add. Non null
   * 
   * @return this {@link MapBuilder}
   */
  @NonNull
  public MapBuilder with(@NonNull Entry entry) {
    map.put(entry.getKey(), entry.getValue());
    return this;
  }

  /**
   * Sets the wrapper function, that is, the {@link Applicable} to apply to the
   * resulting map before returning it through {@link #build()}.
   * 
   * By default, maps are wrapped with unmodifiable wrappers, but this behavior
   * can be changed through this method.
   * 
   * @param wrapperFunction
   * @return this
   */
  @NonNull
  public MapBuilder withWrapper(@NonNull Applicable wrapperFunction) {
    this.wrapperFunction = wrapperFunction;
    return this;
  }

  /**
   * Disables wrapping, which means that a built map will be returned just as it
   * was created.
   * 
   * As a consequence, the map returned by {@link #build()} will be modifiable.
   * 
   * @return this
   */
  @NonNull
  public MapBuilder unwrap() {
    return withWrapper(Functions. identity());
  }

  @NonNull
  public M build() {
    M map = this.map;
    this.map = null;
    if (map == null)
      throw new BuilderAlreadyUsedException();
    return wrapperFunction.apply(map);
  }

  /**
   * Creates a new {@link MapBuilder} that uses the given map instance, and
   * using {@link #toUnmodifiableMap()} as postprocessor. The map built by the
   * returned {@link Builder} grants to be {@link Unmodifiable}
   * 
   * @param 
   * @param 
   * @param map
   * @return a new {@link MapBuilder} that builds unmodifiable views of the
   *         given map
   */
  @NonNull
  public static  MapBuilder> from(@NonNull Map map) {
    return from(map, MapBuilder. toUnmodifiableMap());
  }

  /**
   * Creates a new {@link MapBuilder} using a {@link HashMap} as map
   * implementation and the first key and value. The map built by the returned
   * {@link Builder} grants to be {@link Unmodifiable}
   * 
   * @param 
   *          type of key
   * @param 
   *          type of value
   * @param key
   * @param value
   * @return a new {@link MapBuilder}
   */
  @NonNull
  public static  MapBuilder> mapWith(K key, V value) {
    return from(new HashMap()).with(key, value);
  }

  /**
   * Creates a new {@link MapBuilder} using a {@link LinkedHashMap} as map
   * implementation and the first key and value. The map built by the returned
   * {@link Builder} grants to be {@link Unmodifiable}
   * 
   * @param 
   *          type of key
   * @param 
   *          type of value
   * @param key
   * @param value
   * @return a new {@link MapBuilder}
   */
  @NonNull
  public static  MapBuilder> linkedMapWith(K key, V value) {
    return from(new LinkedHashMap()).with(key, value);
  }

  /**
   * Creates a new {@link MapBuilder} using a {@link TreeMap} as map
   * implementation and the first key and value. The map built by the returned
   * {@link Builder} grants to be {@link Unmodifiable}
   * 
   * @param 
   *          type of key
   * @param 
   *          type of value
   * @param key
   * @param value
   * @return a new {@link MapBuilder}
   */
  @NonNull
  public static  MapBuilder> treeMapWith(K key, V value) {
    return from(new TreeMap(), MapBuilder. toUnmodifiableSortedMap()).with(key, value);
  }

  /**
   * Creates a new {@link MapBuilder} using the given map instance and
   * wrapperFunction that would be applied to the built map before being
   * returned. If no wrapping is required, pass {@link Functions#identity()}
   * 
   * @param 
   *          type of key
   * @param 
   *          type of value
   * @param 
   *          type of {@link Map}
   * @param map
   *          the map to build
   * @param wrapperFunction
   *          the {@link Applicable} to be applied to the given map before
   *          returning it. If the {@link Applicable} returns a different map
   *          instead of modifying it, then that map is returned.
   * @return a new {@link MapBuilder}
   */
  @NonNull
  private static > MapBuilder from(@NonNull M map, Applicable wrapperFunction) {
    return new MapBuilder(map, wrapperFunction);
  }

  /**
   * A constant function that returns an unmodifiable view of its map argument
   * 
   * @param 
   * @param 
   * @return a constant {@link Function}
   */
  @Constant
  public static  Function, Map> toUnmodifiableMap() {
    return new AbstractFunction, Map>() {
      public Map apply(Map arg) {
        return Collections.unmodifiableMap(arg);
      }
    };
  }

  /**
   * A constant function that returns an unmodifiable view of its sortedmap
   * argument
   * 
   * @param 
   * @param 
   * @return a constant {@link Function}
   */
  @Constant
  public static  Function, SortedMap> toUnmodifiableSortedMap() {
    return new AbstractFunction, SortedMap>() {
      public SortedMap apply(SortedMap arg) {
        return Collections.unmodifiableSortedMap(arg);
      }
    };
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy