--- /dev/null 2011-08-08 08:40:49.685541141 -0700
+++ new/src/share/classes/java/util/functions/Mappers.java 2011-08-09 10:55:26.000000000 -0700
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.util.functions;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Static utility methods pertaining to {@code Mapper} instances.
+ *
+ *
All of the returned mappers are serializable if provided serializable
+ * parameters.
+ */
+public final class Mappers {
+
+ /**
+ * A mapper which who's {@code map} method returns the provided
+ * input.
+ */
+ public static final Mapper IDENTITY = #{Object t -> t};
+
+ /**
+ * A mapper which performs a mapping from an object to it's
+ * string representation.
+ */
+ public static final Mapper STRING = #{Object t -> String.valueOf(t)};
+
+ /**
+ * singleton utils
+ */
+ private Mappers() {
+ throw new AssertionError("No instances!");
+ }
+
+ /**
+ * Returns a mapper which who's {@code map} method returns the provided
+ * input. Useful when a Mapper is required and {@code } and {@code }
+ * are the same type.
+ */
+ public static Mapper identity() {
+ return (Mapper) IDENTITY;
+ }
+
+// /**
+// * Returns a mapper which who's {@code map} method returns a clone of the
+// * provided input.
+// */
+// public static Mapper cloneOf() {
+// return
+//
+// #{T t -> try {
+// return t.clone();
+// } catch (CloneNotSupportedException ex) {
+// throw new UndeclaredThrowableException(ex);
+// }
+// };
+// }
+//
+ /**
+ * Returns a mapper which performs a mapping from {@code } to it's
+ * string representation.
+ *
+ * @param Type of input values
+ * @return a mapper which performs a mapping from {@code } to it's
+ * string representation
+ */
+ public static Mapper string() {
+ return (Mapper) STRING;
+ }
+
+ /**
+ * Returns a mapper which performs a mapping from {@code } to {@code }
+ * followed by a mapping from {@code } to {@code }.
+ *
+ * @param Type for input values
+ * @param Type for intermediate mapped values. May be the same type as
+ * {@code }.
+ * @param Type for final mapped values. May be the same type as
+ * {@code }.
+ * @param first Initial mapping from {@code } to {@code }.
+ * @param second additional mapping from {@code } to {@code }.
+ */
+ public static Mapper chain(
+ Mapper super T, ? extends U> first,
+ Mapper super U, ? extends V> second) {
+ Objects.requireNonNull(first);
+ Objects.requireNonNull(second);
+
+ return #{T t -> second.map(first.map(t))};
+ }
+
+ /**
+ * Returns a constant output regardless of input.
+ *
+ * @param constant The value to be returned by the {@code map} method.
+ * @return a mapper who's {@code map} method provides a constant result.
+ */
+ public static Mapper constant(U constant) {
+ return #{ T t -> constant };
+ }
+
+ /**
+ * A mapper that substitutes a single input value with a specified
+ * replacement. Input values are compared using {@code equals()}.
+ *
+ * @param The type of values.
+ * @param subOut The input value to be substituted out.
+ * @param subIn The replacement value for matching inputs.
+ * @return a mapper that substitutes a single input value with a specified
+ * replacement.
+ */
+ public static Mapper substitute(T subOut, T subIn) {
+ return #{ T t -> Objects.equals(subOut,t) ? subIn : t};
+ }
+
+ /**
+ * Returns a new instance of {@code } constructed with provided
+ * {@code }.
+ *
+ * @param Type of input values to mapping
+ * @param Type of output values from mapping
+ * @param clazzT The {@code Class} which defines objects of type {@code }
+ * @param clazzU The {@code Class} which defines objects of type {@code }
+ * @return a mapper which creates instances of {@code } using {@code }
+ * as the constructor parameter.
+ * @throws NoSuchMethodException when {@code } has no constructor which
+ * takes a {@code } as a parameter.
+ */
+ public static Mapper instantiate(final Class extends T> clazzT, final Class extends U> clazzU) {
+ Objects.requireNonNull(clazzT);
+ Objects.requireNonNull(clazzU);
+
+ final Constructor extends U> constructor;
+ try {
+ constructor = clazzU.getConstructor(clazzT);
+ } catch(NoSuchMethodException noConstructor) {
+ throw new IllegalArgumentException("no constructor for ()", noConstructor);
+ }
+
+ return #{T t ->
+ try {
+ return constructor.newInstance(t);
+ } catch (ReflectiveOperationException ex) {
+ // XXX mduigou argument for exception transparency?
+ throw new UndeclaredThrowableException(ex);
+ }
+ };
+ }
+
+ /**
+ * Map according to the provided mapping. The map is expected to contain
+ * all possible values of {@code }. A copy is not made
+ * of the map and care should be taken to avoid changes to the map during
+ * operation may produce results which violate the {@code map} method
+ * contract.
+ *
+ * @param input type to mapping operation
+ * @param output type from mapping operation
+ * @param map provides the mappings from {@code } to {@code }
+ * @throws IllegalArgumentException for all values of {@code } not
+ * present in the map
+ */
+ public static Mapper forMap(final Map super T, ? extends U> map) {
+ Objects.requireNonNull(map);
+
+ return #{T t -> if (map.containsKey(t)) {
+ return map.get(t);
+ }
+
+ throw new IllegalArgumentException("unmappable : " + t);
+ };
+ }
+
+ /**
+ * Map according to the provided mapping. The provided default value is
+ * returned for all {@code } keys not found in the map. A copy is
+ * not made of the map and care should be taken to avoid
+ * changes to the map during operation may produce results which violate the
+ * {@coe map} method contract.
+ *
+ * @param input type to map
+ * @param output type from mapping
+ * @param map provides the mappings from {@code } to {@code }
+ * @param defaultValue the value returned by {@code map} method for
+ * {code } values not contained in the provided map
+ */
+ public static Mapper forMap(final Map super T, ? extends U> map, final U defaultValue) {
+ Objects.requireNonNull(map);
+
+ if(map.isEmpty()) {
+ return constant(defaultValue);
+ }
+
+ return #{T t -> map.containsKey(t) ? map.get(t) : defaultValue};
+ }
+
+ /**
+ * Map according to the provided predicate. Two output values are provided
+ * {@code forTrue} is returned if the predicate returns {@code true}
+ * otherwise the {@code forFalse} value is returned.
+ *
+ * @param input type to map
+ * @param output type from mapping
+ * @param predicate decides which value {@code map} method should return
+ * @param forTrue value to be returned for {@code true} predicate results
+ * @param forFalse value to be returned for {@code false} predicate results
+ * @return a Mapper who's {@code map} method provides results according to
+ * the provided predicate.
+ */
+ public static Mapper forPredicate(Predicate super T> predicate, U forTrue, U forFalse) {
+ Objects.requireNonNull(predicate);
+
+ return #{T t -> predicate.eval(t) ? forTrue : forFalse};
+ }
+}