imported patch factory JDK-8193209-branch
authorjlaskey
Wed, 07 Aug 2019 15:35:55 -0300
branchJDK-8193209-branch
changeset 57671 6a4be8bf8990
parent 57547 56cbdc3ea079
child 57684 7cb325557832
imported patch factory
src/java.base/share/classes/java/util/Random.java
src/java.base/share/classes/java/util/random/RandomGenerator.java
src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java
--- a/src/java.base/share/classes/java/util/Random.java	Fri Jul 26 15:37:05 2019 -0300
+++ b/src/java.base/share/classes/java/util/Random.java	Wed Aug 07 15:35:55 2019 -0300
@@ -31,18 +31,13 @@
 import java.math.BigInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.DoubleConsumer;
-import java.util.function.Function;
 import java.util.function.IntConsumer;
 import java.util.function.LongConsumer;
-import java.util.Objects;
 import java.util.random.RandomGenerator;
 import java.util.random.RandomSupport;
 import java.util.random.RandomSupport.AbstractSpliteratorGenerator;
 import java.util.random.RandomSupport.RandomSpliterator;
-import java.util.ServiceLoader;
-import java.util.ServiceLoader.Provider;
 import java.util.Spliterator;
-import java.util.stream.Collectors;
 
 /**
  * An instance of this class is used to generate a stream of
@@ -501,47 +496,6 @@
     }
 
     /**
-     * Creates a new random number generator that uses the random number generator algorithm
-     * specified by name. The seed of the random number generator to a value very likely to be
-     * distinct from any other invocation.
-     *
-     * @param name  name of random number generator algorithm to use.
-     *
-     * @return an instance of random number generator.
-     *
-     * @throws IllegalArgumentException if {@code name} is an unknown random number generator
-     *
-     * @since 14
-     */
-    public static RandomGenerator byName(String name) throws IllegalArgumentException {
-        Objects.requireNonNull(name);
-        Map<String, Provider<RandomGenerator>> rngs = getGeneratorMap();
-        Provider<RandomGenerator> provider = rngs.get(name.toUpperCase());
-        if (provider == null) {
-            throw new IllegalArgumentException(name + " is an unknown random number generator");
-        }
-        return provider.get();
-    }
-
-    private static Map<String, Provider<RandomGenerator>> rngMap;
-
-    private static Map<String, Provider<RandomGenerator>> getGeneratorMap() {
-        if (rngMap == null) {
-            synchronized (Random.class) {
-                if (rngMap == null) {
-                    rngMap = ServiceLoader
-                            .load(RandomGenerator.class)
-                            .stream()
-                            .filter(p -> !p.type().isInterface())
-                            .collect(Collectors.toMap(p -> p.type().getSimpleName().toUpperCase(),
-                                    Function.identity()));
-                }
-            }
-        }
-        return rngMap;
-    }
-
-    /**
      * Serializable fields for Random.
      *
      * @serialField    seed long
--- a/src/java.base/share/classes/java/util/random/RandomGenerator.java	Fri Jul 26 15:37:05 2019 -0300
+++ b/src/java.base/share/classes/java/util/random/RandomGenerator.java	Wed Aug 07 15:35:55 2019 -0300
@@ -26,11 +26,11 @@
 package java.util.random;
 
 import java.math.BigInteger;
+import java.util.Objects;
 import java.util.stream.DoubleStream;
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
 import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
 
 /**
  * The {@link RandomGenerator} interface is designed to provide a common protocol for objects
@@ -90,6 +90,122 @@
 public interface RandomGenerator {
 
     /**
+     * Supported randpm number Algorithms.
+     */
+    public enum Algorithm {
+        /**
+         * L32X64MixRandom algorithm
+         */
+        L32X64MixRandom("L32X64MixRandom"),
+        /**
+         * L64X1024MixRandom algorithm
+         */
+        L64X1024MixRandom("L64X1024MixRandom"),
+        /**
+         * L64X1024Random algorithm
+         */
+        L64X1024Random("L64X1024Random"),
+        /**
+         * L64X128MixRandom algorithm
+         */
+        L64X128MixRandom("L64X128MixRandom"),
+        /**
+         * L64X128Random algorithm
+         */
+        L64X128Random("L64X128Random"),
+        /**
+         * L64X256MixRandom algorithm
+         */
+        L64X256MixRandom("L64X256MixRandom"),
+        /**
+         * L64X256Random algorithm
+         */
+        L64X256Random("L64X256Random"),
+        /**
+         * L128X256MixRandom algorithm
+         */
+        L128X256MixRandom("L128X256MixRandom"),
+        /**
+         * MRG32k3a algorithm
+         */
+        MRG32k3a("MRG32k3a"),
+        /**
+         * Xoroshiro128Plus algorithm
+         */
+        Xoroshiro128Plus("Xoroshiro128Plus"),
+        /**
+         * Xoroshiro128StarStar algorithm
+         */
+        Xoroshiro128StarStar("Xoroshiro128StarStar"),
+        /**
+         * Xoshiro256StarStar algorithm
+         */
+        Xoshiro256StarStar("Xoshiro256StarStar");
+
+        private String name;
+
+        Algorithm(String name) {
+            this.name = name;
+        }
+
+        public String toString() {
+            return name;
+        }
+    }
+
+    /**
+     * Returns an instance of {@link RandomGenerator} that utilizes the
+     * {@code name} algorithm.
+     *
+     * @param name  Name of random number generator algorithm
+     *
+     * @return An instance of {@link RandomGenerator}
+     */
+    public static RandomGenerator of(String name) {
+        Objects.requireNonNull(name);
+        return RandomGeneratorFactory.of(name, RandomGenerator.class);
+    }
+
+    /**
+     * Returns an instance of {@link RandomGenerator} that utilizes the
+     * specified {@code algorithm}.
+     *
+     * @param algorithm  Random number generator algorithm
+     *
+     * @return An instance of {@link RandomGenerator}
+     */
+    public static RandomGenerator of(Algorithm algorithm) {
+        Objects.requireNonNull(algorithm);
+        return RandomGeneratorFactory.of(algorithm.toString(), RandomGenerator.class);
+    }
+
+    /**
+     * Returns a {@link RandomGeneratorFactory} that can produce instances
+     * of {@link RandomGenerator} that utilizes the {@code name} algorithm.
+     *
+     * @param name  Name of random number generator algorithm
+     *
+     * @return Factory of {@link RandomGenerator}
+     */
+    public static RandomGeneratorFactory<RandomGenerator> factoryOf(String name) {
+        Objects.requireNonNull(name);
+        return RandomGeneratorFactory.factoryOf(name, RandomGenerator.class);
+    }
+
+    /**
+     * Returns a {@link RandomGeneratorFactory} that can produce instances
+     * of {@link RandomGenerator} that utilizes the specified {@code algorithm}.
+     *
+     * @param algorithm  Random number generator algorithm
+     *
+     * @return Factory of {@link RandomGenerator}
+     */
+    public static RandomGeneratorFactory<RandomGenerator> factoryOf(Algorithm algorithm) {
+        Objects.requireNonNull(algorithm);
+        return RandomGeneratorFactory.factoryOf(algorithm.toString(), RandomGenerator.class);
+    }
+
+    /**
      * Returns an effectively unlimited stream of pseudorandomly chosen
      * {@code double} values.
      *
@@ -672,6 +788,59 @@
      * @since 14
      */
     public interface StreamableGenerator extends RandomGenerator {
+
+        /**
+         * Returns an instance of {@link StreamableGenerator} that utilizes the
+         * {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return An instance of {@link StreamableGenerator}
+         */
+        public static StreamableGenerator of(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.of(name, StreamableGenerator.class);
+        }
+
+        /**
+         * Returns an instance of {@link StreamableGenerator} that utilizes the
+         * specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return An instance of {@link StreamableGenerator}
+         */
+        public static StreamableGenerator of(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.of(algorithm.toString(), StreamableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link StreamableGenerator} that utilizes the {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return Factory of {@link StreamableGenerator}
+         */
+        public static RandomGeneratorFactory<StreamableGenerator> factoryOf(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.factoryOf(name, StreamableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link StreamableGenerator} that utilizes the specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return Factory of {@link StreamableGenerator}
+         */
+        public static RandomGeneratorFactory<StreamableGenerator> factoryOf(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.factoryOf(algorithm.toString(), StreamableGenerator.class);
+        }
+
         /**
          * Returns an effectively unlimited stream of objects, each of
          * which implements the {@link RandomGenerator} interface.  Ideally the
@@ -748,6 +917,58 @@
     public interface SplittableGenerator extends StreamableGenerator {
 
         /**
+         * Returns an instance of {@link SplittableGenerator} that utilizes the
+         * {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return An instance of {@link SplittableGenerator}
+         */
+        public static SplittableGenerator of(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.of(name, SplittableGenerator.class);
+        }
+
+        /**
+         * Returns an instance of {@link SplittableGenerator} that utilizes the
+         * specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return An instance of {@link SplittableGenerator}
+         */
+        public static SplittableGenerator of(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.of(algorithm.toString(), SplittableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link SplittableGenerator} that utilizes the {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return Factory of {@link SplittableGenerator}
+         */
+        public static RandomGeneratorFactory<SplittableGenerator> factoryOf(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.factoryOf(name, SplittableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link SplittableGenerator} that utilizes the specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return Factory of {@link SplittableGenerator}
+         */
+        public static RandomGeneratorFactory<SplittableGenerator> factoryOf(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.factoryOf(algorithm.toString(), SplittableGenerator.class);
+        }
+
+        /**
          * Returns a new pseudorandom number generator, split off from
          * this one, that implements the {@link RandomGenerator} and {@link SplittableGenerator}
          * interfaces.
@@ -910,6 +1131,59 @@
      * @since 14
      */
     public interface JumpableGenerator extends StreamableGenerator {
+
+        /**
+         * Returns an instance of {@link JumpableGenerator} that utilizes the
+         * {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return An instance of {@link JumpableGenerator}
+         */
+        public static JumpableGenerator of(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.of(name, JumpableGenerator.class);
+        }
+
+        /**
+         * Returns an instance of {@link JumpableGenerator} that utilizes the
+         * specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return An instance of {@link JumpableGenerator}
+         */
+        public static JumpableGenerator of(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.of(algorithm.toString(), JumpableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link JumpableGenerator} that utilizes the {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return Factory of {@link JumpableGenerator}
+         */
+        public static RandomGeneratorFactory<JumpableGenerator> factoryOf(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.factoryOf(name, JumpableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link JumpableGenerator} that utilizes the specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return Factory of {@link JumpableGenerator}
+         */
+        public static RandomGeneratorFactory<JumpableGenerator> factoryOf(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.factoryOf(algorithm.toString(), JumpableGenerator.class);
+        }
+
         /**
          * Returns a new generator whose internal state is an exact copy of this generator (therefore
          * their future behavior should be identical if subjected to the same series of operations).
@@ -1046,6 +1320,59 @@
      * @since 14
      */
     public interface LeapableGenerator extends JumpableGenerator {
+
+        /**
+         * Returns an instance of {@link LeapableGenerator} that utilizes the
+         * {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return An instance of {@link LeapableGenerator}
+         */
+        public static LeapableGenerator of(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.of(name, LeapableGenerator.class);
+        }
+
+        /**
+         * Returns an instance of {@link LeapableGenerator} that utilizes the
+         * specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return An instance of {@link LeapableGenerator}
+         */
+        public static LeapableGenerator of(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.of(algorithm.toString(), LeapableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link LeapableGenerator} that utilizes the {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return Factory of {@link LeapableGenerator}
+         */
+        public static RandomGeneratorFactory<LeapableGenerator> factoryOf(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.factoryOf(name, LeapableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link LeapableGenerator} that utilizes the specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return Factory of {@link LeapableGenerator}
+         */
+        public static RandomGeneratorFactory<LeapableGenerator> factoryOf(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.factoryOf(algorithm.toString(), LeapableGenerator.class);
+        }
+
         /**
          * Returns a new generator whose internal state is an exact copy of this generator (therefore
          * their future behavior should be identical if subjected to the same series of operations).
@@ -1155,6 +1482,59 @@
      * @since 14
      */
     public interface ArbitrarilyJumpableGenerator extends LeapableGenerator {
+
+        /**
+         * Returns an instance of {@link ArbitrarilyJumpableGenerator} that utilizes the
+         * {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return An instance of {@link ArbitrarilyJumpableGenerator}
+         */
+        public static ArbitrarilyJumpableGenerator of(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.of(name, ArbitrarilyJumpableGenerator.class);
+        }
+
+        /**
+         * Returns an instance of {@link ArbitrarilyJumpableGenerator} that utilizes the
+         * specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return An instance of {@link ArbitrarilyJumpableGenerator}
+         */
+        public static ArbitrarilyJumpableGenerator of(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.of(algorithm.toString(), ArbitrarilyJumpableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link ArbitrarilyJumpableGenerator} that utilizes the {@code name} algorithm.
+         *
+         * @param name  Name of random number generator algorithm
+         *
+         * @return Factory of {@link ArbitrarilyJumpableGenerator}
+         */
+        public static RandomGeneratorFactory<ArbitrarilyJumpableGenerator> factoryOf(String name) {
+            Objects.requireNonNull(name);
+            return RandomGeneratorFactory.factoryOf(name, ArbitrarilyJumpableGenerator.class);
+        }
+
+        /**
+         * Returns a {@link RandomGeneratorFactory} that can produce instances
+         * of {@link ArbitrarilyJumpableGenerator} that utilizes the specified {@code algorithm}.
+         *
+         * @param algorithm  Random number generator algorithm
+         *
+         * @return Factory of {@link ArbitrarilyJumpableGenerator}
+         */
+        public static RandomGeneratorFactory<ArbitrarilyJumpableGenerator> factoryOf(Algorithm algorithm) {
+            Objects.requireNonNull(algorithm);
+            return RandomGeneratorFactory.factoryOf(algorithm.toString(), ArbitrarilyJumpableGenerator.class);
+        }
+
         /**
          * Returns a new generator whose internal state is an exact copy of this generator (therefore
          * their future behavior should be identical if subjected to the same series of operations).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java	Wed Aug 07 15:35:55 2019 -0300
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2016, 2019, 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.random;
+
+import java.util.function.Function;
+import java.util.Map;
+import java.util.Objects;
+import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+/**
+ * This is a factory class for generating random number generators of a specific
+ * catagory and algorithm.
+ */
+public class RandomGeneratorFactory<T> {
+    /**
+     * Instance provider class of random number algorithm.
+     */
+    private final Provider<T> provider;
+
+    /**
+     * Map of provider classes.
+     */
+    private static Map<String, Provider<RandomGenerator>> providerMap;
+
+    /**
+     * Private constructor.
+     *
+     * @param provider  Provider class to wrap.
+     */
+    private RandomGeneratorFactory(Provider<T> provider) {
+        this.provider = provider;
+    }
+
+    /**
+     * Returns the provider map, lazily constructing map on first call.
+     *
+     * @return Map of provider classes.
+     */
+    private static Map<String, Provider<RandomGenerator>> getProviderMap() {
+        if (providerMap == null) {
+            synchronized (RandomGeneratorFactory.class) {
+                if (providerMap == null) {
+                    providerMap =
+                        ServiceLoader
+                            .load(RandomGenerator.class)
+                            .stream()
+                            .filter(p -> !p.type().isInterface())
+                            .collect(Collectors.toMap(p -> p.type().getSimpleName().toUpperCase(),
+                                    Function.identity()));
+                }
+            }
+        }
+        return providerMap;
+    }
+
+    private static Provider<RandomGenerator> findProvider(String name, Class<? extends RandomGenerator> category)
+            throws IllegalArgumentException {
+        Map<String, Provider<RandomGenerator>> pm = getProviderMap();
+        Provider<RandomGenerator> provider = pm.get(name.toUpperCase());
+        if (provider == null || provider.type().isAssignableFrom(category)) {
+            throw new IllegalArgumentException(name + " is an unknown random number generator");
+        }
+        return provider;
+    }
+
+    /**
+     * Returns a {@link RandomGenerator} that utilizes the {@code name} algorithm.
+     *
+     * @param name  Name of random number algorithm to use
+     * @param category Sub-interface of {@link RandomGenerator} to type check
+     * @param <T> Sub-interface of {@link RandomGenerator} to produce
+     * @return An instance of {@link RandomGenerator}
+     * @throws IllegalArgumentException when either the name or category is null
+     */
+    static <T> T of(String name, Class<? extends RandomGenerator> category)
+            throws IllegalArgumentException {
+        @SuppressWarnings("unchecked")
+        T uncheckedRandomGenerator = (T)findProvider(name, category).get();
+        return uncheckedRandomGenerator;
+    }
+
+    /**
+     * Returns a {@link RandomGeneratorFactory} that will produce instances
+     * of {@link RandomGenerator} that utilizes the {@code name} algorithm.
+     *
+     * @param name  Name of random number algorithm to use
+     * @param category Sub-interface of {@link RandomGenerator} to type check
+     * @param <T> Sub-interface of {@link RandomGenerator} to produce
+     * @return Factory of {@link RandomGenerator}
+     * @throws IllegalArgumentException when either the name or category is null
+     */
+    static <T> RandomGeneratorFactory<T> factoryOf(String name, Class<? extends RandomGenerator> category)
+            throws IllegalArgumentException {
+        @SuppressWarnings("unchecked")
+        Provider<T> uncheckedProvider = (Provider<T>)findProvider(name, category);
+        return new RandomGeneratorFactory<T>(uncheckedProvider);
+    }
+
+    /**
+     * Create an instance of {@link RandomGenerator}.
+     *
+     * @return Instance of {@link RandomGenerator}.
+     */
+    public T create() {
+        return provider.get();
+    }
+}
+
+