package umontreal.iro.lecuyer.rng;

import umontreal.iro.lecuyer.rng.RandomStream;
import umontreal.iro.lecuyer.rng.MRG32k3a;


/**
 * Represents a basic random stream factory that can constructs new
 * instances of a given {@link RandomStream} implementation via the
 * {@link #newInstance(()) newInstance} method.
 * The class name of the implementation to be used must be passed to
 * the constructor as a String, which must be the name of
 * a nullary constructor of a {@link RandomStream} object
 * (i.e., a constructor that has no parameters).
 * The streams are constructed by the factory by reflection from this
 * String. 
 * 
 */
public class BasicRandomStreamFactory implements RandomStreamFactory {
   private Class rsClass;


   /**
    * Constructs a new basic random stream factory with
    *  random stream class rsClass.
    *  The supplied class object must represent an implementation
    *  of {@link RandomStream} and must provide a nullary
    *  constructor.  For example, to construct a factory
    *  producing {@link MRG32k3a} random streams, this constructor
    *  must be called with MRG33k3a.class.
    * 
    * @param rsClass the random stream class being used.
    * 
    *    @exception NullPointerException if rsClass is null.
    * 
    *    @exception IllegalArgumentException if rsClass does
    *     not represent an implementation of {@link RandomStream}, or
    *     does not provide a nullary constructor.
    * 
    * 
    */
   public BasicRandomStreamFactory (Class rsClass) {
      checkRandomStreamClass (rsClass);
      this.rsClass = rsClass;
   }


   /**
    * Returns the random stream class associated with this
    *  object.
    * 
    * @return the associated random stream class.
    * 
    */
   public Class getRandomStreamClass() {
      return rsClass;
   }


   /**
    * Sets the associated random stream class to
    *  rsClass.
    *  The supplied class object must represent an implementation
    *  of {@link RandomStream} and must provide a nullary
    *  constructor.
    * 
    * @param rsClass the random stream class being used.
    * 
    *    @exception NullPointerException if rsClass is null.
    * 
    *    @exception IllegalArgumentException if rsClass does
    *     not represent an implementation of {@link RandomStream}, or
    *     does not provide a nullary constructor.
    * 
    * 
    */
   public void setRandomStreamClass (Class rsClass) {
      checkRandomStreamClass (rsClass);
      this.rsClass = rsClass;
   }


   private void checkRandomStreamClass (final Class rsClass) {
      if (!RandomStream.class.isAssignableFrom (rsClass))
         throw new IllegalArgumentException
            ("The random class must implement the RandomStream interface");
      try {
         rsClass.getConstructor (new Class[0]);
      }
      catch (NoSuchMethodException nme) {
         throw new IllegalArgumentException
            ("The random stream class " + rsClass.getName() + " does not have a " +
             "nullary public constructor.");
      }
   }

   public RandomStream newInstance() {
      try {
         return (RandomStream)rsClass.newInstance();
      }
      catch (IllegalAccessException iae) {
         throw new RandomStreamInstantiationException
            (this, "Cannot access constructor for random stream class " + rsClass.getName(),
             iae);
      }
      catch (InstantiationException ie) {
         throw new RandomStreamInstantiationException
            (this, "Cannot instantiate random stream class "
             + rsClass.getName(), ie);
      }
      catch (Exception e) {
         throw new RandomStreamInstantiationException
            (this, "Exception while calling the nullary constructor for random stream class "
             + rsClass.getName(), e);
      }
   }

   public String toString() {
      return "Basic random stream factory constructing streams of class " + rsClass.getName();
   }
}

 

Ads help maintain this website.