package org.codefx.libfx.collection.transform; import java.util.Map; import java.util.Objects; import java.util.function.Function; /** * Builder for {@link TransformingMap}s. * <p> * A builder can be obtained by calling {@link #forTypes(Class, Class, Class, Class) forTypes} or * {@link #forTypesUnknown()}. The building method TODO can only be called after transformations from inner to outer * keys and values and vice versa have been set. * * @param <IK> * the inner key type of the created transforming map, i.e. the type of the keys contained in the * wrapped/inner map * @param <OK> * the outer key type of the created transforming map, i.e. the type of keys appearing to be in this map * @param <IV> * the inner value type of the created transforming map, i.e. the type of the values contained in the * wrapped/inner map * @param <OV> * the outer value type of the created transforming map, i.e. the type of values appearing to be in this map */ public class TransformingMapBuilder<IK, OK, IV, OV> { // #begin FIELDS private final Class<? super OK> outerKeyTypeToken; private final Class<? super IK> innerKeyTypeToken; private Function<? super IK, ? extends OK> transformToOuterKey; private Function<? super OK, ? extends IK> transformToInnerKey; private final Class<? super OV> outerValueTypeToken; private final Class<? super IV> innerValueTypeToken; private Function<? super IV, ? extends OV> transformToOuterValue; private Function<? super OV, ? extends IV> transformToInnerValue; // #end FIELDS // #begin CONSTRUCTION private TransformingMapBuilder( Class<? super IK> innerKeyTypeToken, Class<? super OK> outerKeyTypeToken, Class<? super IV> innerValueTypeToken, Class<? super OV> outerValueTypeToken) { Objects.requireNonNull(innerKeyTypeToken, "The argument 'innerKeyTypeToken' must not be null."); Objects.requireNonNull(outerKeyTypeToken, "The argument 'outerKeyTypeToken' must not be null."); Objects.requireNonNull(innerValueTypeToken, "The argument 'innerValueTypeToken' must not be null."); Objects.requireNonNull(outerValueTypeToken, "The argument 'outerValueTypeToken' must not be null."); this.innerKeyTypeToken = innerKeyTypeToken; this.outerKeyTypeToken = outerKeyTypeToken; this.innerValueTypeToken = innerValueTypeToken; this.outerValueTypeToken = outerValueTypeToken; } /** * Returns a new builder for the specified inner and outer key and value types. * * @param <IK> * the inner key type of the created transforming map, i.e. the type of the keys contained in the * wrapped/inner map * @param <OK> * the outer key type of the created transforming map, i.e. the type of keys appearing to be in this map * @param <IV> * the inner value type of the created transforming map, i.e. the type of the values contained in the * wrapped/inner map * @param <OV> * the outer value type of the created transforming map, i.e. the type of values appearing to be in this * map * @param innerKeyTypeToken * the token for the inner key type * @param outerKeyTypeToken * the token for the outer key type * @param innerValueTypeToken * the token for the inner value type * @param outerValueTypeToken * the token for the outer value type * @return a new builder */ public static <IK, OK, IV, OV> TransformingMapBuilder<IK, OK, IV, OV> forTypes( Class<? super IK> innerKeyTypeToken, Class<? super OK> outerKeyTypeToken, Class<? super IV> innerValueTypeToken, Class<? super OV> outerValueTypeToken) { return new TransformingMapBuilder<>( innerKeyTypeToken, outerKeyTypeToken, innerValueTypeToken, outerValueTypeToken); } /** * Returns a new builder for unknown inner and outer key and value types. * <p> * This is equivalent to calling {@link #forTypes(Class, Class, Class, Class) forTypes(Object.class, Object.class, * Object.class, Object.class)}. To obtain a builder for {@code <IK, OK, IV, OV>} you will have to call * {@code TransformingMapBuilder.<IK, OK, IV, OV> forTypesUnknown()}. * * @param <IK> * the inner key type of the created transforming map, i.e. the type of the keys contained in the * wrapped/inner map * @param <OK> * the outer key type of the created transforming map, i.e. the type of keys appearing to be in this map * @param <IV> * the inner value type of the created transforming map, i.e. the type of the values contained in the * wrapped/inner map * @param <OV> * the outer value type of the created transforming map, i.e. the type of values appearing to be in this * map * @return a new builder */ public static <IK, OK, IV, OV> TransformingMapBuilder<IK, OK, IV, OV> forTypesUnknown() { return forTypes(Object.class, Object.class, Object.class, Object.class); } // #end CONSTRUCTION // #begin SET FIELDS /** * Sets the transformation from inner to outer keys which will be used by the created map. * * @param transformToOuterKey * transforms inner to outer keys * @return this builder */ public TransformingMapBuilder<IK, OK, IV, OV> toOuterKey(Function<? super IK, ? extends OK> transformToOuterKey) { Objects.requireNonNull(transformToOuterKey, "The argument 'transformToOuterKey' must not be null."); this.transformToOuterKey = transformToOuterKey; return this; } /** * Sets the transformation from outer to inner keys which will be used by the created map. * * @param transformToInnerKey * transforms outer to inner keys * @return this builder */ public TransformingMapBuilder<IK, OK, IV, OV> toInnerKey(Function<? super OK, ? extends IK> transformToInnerKey) { Objects.requireNonNull(transformToInnerKey, "The argument 'transformToInnerKey' must not be null."); this.transformToInnerKey = transformToInnerKey; return this; } /** * Sets the transformation from inner to outer values which will be used by the created map. * * @param transformToOuterValue * transforms inner to outer values * @return this builder */ public TransformingMapBuilder<IK, OK, IV, OV> toOuterValue(Function<? super IV, ? extends OV> transformToOuterValue) { Objects.requireNonNull(transformToOuterValue, "The argument 'transformToOuterValue' must not be null."); this.transformToOuterValue = transformToOuterValue; return this; } /** * Sets the transformation from outer to inner values which will be used by the created map. * * @param transformToInnerValue * transforms outer to inner values * @return this builder */ public TransformingMapBuilder<IK, OK, IV, OV> toInnerValue(Function<? super OV, ? extends IV> transformToInnerValue) { Objects.requireNonNull(transformToInnerValue, "The argument 'transformToInnerValue' must not be null."); this.transformToInnerValue = transformToInnerValue; return this; } // #end SET FIELDS // #begin BUILD /** * Creates a {@link TransformingMap} which transforms/decorates the specified map. * * @param map * the map to transform; will be the inner map of the returned transformation * @return a new {@link TransformingMap} */ public TransformingMap<IK, OK, IV, OV> transformMap(Map<IK, IV> map) { return new TransformingMap<>(map, innerKeyTypeToken, outerKeyTypeToken, transformToOuterKey, transformToInnerKey, innerValueTypeToken, outerValueTypeToken, transformToOuterValue, transformToInnerValue); } // #end BUILD }