/* * Copyright 2013 Cameron Beccario * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.nullschool.grains; import net.nullschool.collect.IterableMap; import java.util.*; /** * 2013-03-24<p/> * * A GrainBuilder is a mutable {@link IterableMap iterable map} of String to Object that contains permanent keys, * i.e., keys that cannot be disassociated from the map. GrainBuilders permit {@code null} values but disallow * {@code null} keys. A GrainBuilder is the mutable analog to a {@link Grain} and makes no guarantees for thread * safety.<p/> * * The set of permanent keys, called the "basis", differs depending on the builder implementation, and each basis key * may restrict the type of values it can be associated with. This is roughly analogous to how instances of a class * share the same set of fields, and each field stores values only of a particular type. Attempts to disassociate a * basis key or associate it with {@code null} results in the key becoming associated with its <i>default value</i>. * Generally, a key's default value is {@code null} if its type restriction is a reference type, otherwise {@code 0} * for primitive types. However, some builder implementations may (optionally) specify a non-null/non-zero default * value for a key.<p/> * * A builder can associate and disassociate non-basis keys, just like a normal map. To differentiate them from the * basis, these keys are called "extensions". Extension keys may also (optionally) restrict their associated * values.<p/> * * The {@link #keySet}, {@link #values}, {@link #entrySet}, and {@link #iterator} methods present the <i>union</i> * of the basis and extensions. There is no guaranteed iteration order.<p/> * * Builders are intended to simplify the construction of immutable grains. Instances of a builder can be created * by calling the {@link Grain#newBuilder} or {@link GrainFactory#getNewBuilder} methods. The {@link #build} method * constructs a new grain from the builder's current set of entries.<p/> * * @author Cameron Beccario */ public interface GrainBuilder extends IterableMap<String, Object> { /** * {@inheritDoc}<p/> * * This method interprets a {@code null} value to represent the <i>default value</i> of the key. Generally, a * key's default value is {@code null} if its type restriction is a reference type, otherwise {@code 0} for * primitive types. However, some keys may have a non-null/non-zero default value. For example, if a key's * default value is <i>42</i>, then invoking this method with a {@code null} value will associate that key with * <i>42</i>. * * @param key the key to associate. * @param value the value to be associated with the key. * @throws NullPointerException if the key is null. * @throws ClassCastException if the value is of a type not suitable for this builder. * @throws IllegalArgumentException if some property of the value is not suitable for this builder. */ Object put(String key, Object value); /** * {@inheritDoc}<p/> * * @param map mappings to be stored in this builder. * @throws NullPointerException if the map is null, or any key is null. * @throws ClassCastException if any value is of a type not suitable for this builder. * @throws IllegalArgumentException if some property of any value in the map is not suitable for this builder. */ void putAll(Map<? extends String, ?> map); /** * Removes the mapping for a key if it exists.<p/> * * NOTE: This method violates the Map contract if invoked with a basis key. Rather than remove the key, this * method associates it with its <i>default value</i>. * * @param key the key to de-associate. * @throws NullPointerException if the key is null. * @throws ClassCastException if the key is not a String. */ Object remove(Object key); /** * Removes all extension mappings from this builder and resets all basis keys to their <i>default values</i>.<p/> * * NOTE: This method violates the Map contract if this builder contains basis keys. Basis keys are permanent, * so the builder will not be empty after this method returns. */ void clear(); /** * {@inheritDoc}<p/> * * NOTE: This method violates the Map contract if basis keys are removed from the resulting set. Rather than * remove the key, the key will become associated with its <i>default value</i>. */ Set<String> keySet(); /** * {@inheritDoc}<p/> * * NOTE: This method violates the Map contract if a value associated with a basis key is removed from the * resulting collection. Rather than remove the association, the key will become associated with its <i>default * value</i>. */ Collection<Object> values(); /** * {@inheritDoc}<p/> * * The entries in the resulting set can be used to assign values in this builder using the {@link Entry#setValue} * method. However, {@code null} is interpreted to represent the <i>default value</i> of the key. See * {@link #put}.<p/> * * NOTE: This method violates the Map contract if an entry for a basis key is removed from the resulting set. * Rather than remove the association, the key will become associated with its <i>default value</i>. */ Set<Entry<String, Object>> entrySet(); /** * Constructs a Grain instance from this builder's current state. This method may be invoked multiple times. * * @return a grain instance. * @throws IllegalArgumentException if some property of this builder is not suitable for the grain being * constructed. */ Grain build(); /** * {@inheritDoc} */ boolean equals(Object obj); /** * {@inheritDoc} */ int hashCode(); }