All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fj.test.Cogen Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

The newest version!
package fj.test;

import fj.*;

import static fj.Function.curry;
import static fj.P.p;

import fj.data.*;

import static fj.data.Array.iterableArray;
import static fj.data.List.fromString;
import static fj.data.List.nil;

import static fj.test.Variant.variant;

import static java.lang.Double.doubleToRawLongBits;
import static java.lang.Float.floatToRawIntBits;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Properties;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
import java.util.WeakHashMap;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.SynchronousQueue;

/**
 * Transforms a type and a generator to produce a new generator. This function is used to generate
 * {@link Gen gen} functions.
 *
 * @version %build.number%
 */
public abstract class Cogen {
  /**
   * Transforms the given value and generator to a new generator with a high probability of being
   * independent.
   *
   * @param a The value to produce the generator from.
   * @param g The generator to produce the new generator from.
   * @return A new generator with a high probability of being independent.
   */
  public abstract  Gen cogen(A a, Gen g);


  /**
   * A curried version of {@link #cogen(Object, Gen)}.
   *
   * @param a The value to produce the generator from.
   * @return A curried version of {@link #cogen(Object, Gen)}.
   */
  public final  F, Gen> cogen(final A a) {
    return g -> cogen(a, g);
  }

  /**
   * Composes the given function with this cogen to produce a new cogen.
   *
   * @param f The function to compose.
   * @return A new cogen composed with the given function.
   */
  public final  Cogen compose(final F f) {
    return new Cogen() {
      public  Gen cogen(final B b, final Gen g) {
        return Cogen.this.cogen(f.f(b), g);
      }
    };
  }

  /**
   * Contra-maps this cogen using the given function.
   *
   * @param f The function to co-map with.
   * @return A contra-mapped cogen.
   */
  public final  Cogen contramap(final F f) {
    return new Cogen() {
      public  Gen cogen(final B b, final Gen g) {
        return Cogen.this.cogen(f.f(b), g);
      }
    };
  }

  /**
   * A cogen for a function.
   *
   * @param a A gen for the domain of the function.
   * @param c A cogen for the codomain of the function.
   * @return A cogen for a function.
   */
  public static  Cogen> cogenF(final Gen a, final Cogen c) {
    return new Cogen>() {
      public  Gen cogen(final F f, final Gen g) {
        return a.bind(a1 -> c.cogen(f.f(a1), g));
      }
    };
  }

  /**
   * A cogen for a function-2.
   *
   * @param aa A gen for part of the domain of the function.
   * @param ab A gen for part of the domain of the function.
   * @param c  A cogen for the codomain of the function.
   * @return A cogen for a function-2.
   */
  public static  Cogen> cogenF2(final Gen aa, final Gen ab,
                                                     final Cogen c) {
    return new Cogen>() {
      public  Gen cogen(final F2 f, final Gen g) {
        return cogenF(aa, cogenF(ab, c)).cogen(curry(f), g);
      }
    };
  }

  /**
   * A cogen for a function-3.
   *
   * @param aa A gen for part of the domain of the function.
   * @param ab A gen for part of the domain of the function.
   * @param ac A gen for part of the domain of the function.
   * @param c  A cogen for the codomain of the function.
   * @return A cogen for a function-3.
   */
  public static  Cogen> cogenF3(final Gen aa, final Gen ab,
                                                           final Gen ac, final Cogen c) {
    return new Cogen>() {
      public  Gen cogen(final F3 f, final Gen g) {
        return cogenF(aa, cogenF(ab, cogenF(ac, c))).cogen(curry(f), g);
      }
    };
  }

  /**
   * A cogen for a function-4.
   *
   * @param aa A gen for part of the domain of the function.
   * @param ab A gen for part of the domain of the function.
   * @param ac A gen for part of the domain of the function.
   * @param ad A gen for part of the domain of the function.
   * @param c  A cogen for the codomain of the function.
   * @return A cogen for a function-4.
   */
  public static  Cogen> cogenF4(final Gen aa, final Gen ab,
                                                                 final Gen ac, final Gen ad,
                                                                 final Cogen c) {
    return new Cogen>() {
      public  Gen cogen(final F4 f, final Gen g) {
        return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, c)))).cogen(curry(f), g);
      }
    };
  }

  /**
   * A cogen for a function-5.
   *
   * @param aa A gen for part of the domain of the function.
   * @param ab A gen for part of the domain of the function.
   * @param ac A gen for part of the domain of the function.
   * @param ad A gen for part of the domain of the function.
   * @param ae A gen for part of the domain of the function.
   * @param c  A cogen for the codomain of the function.
   * @return A cogen for a function-5.
   */
  public static  Cogen> cogenF5(final Gen aa,
                                                                         final Gen ab,
                                                                         final Gen ac,
                                                                         final Gen ad,
                                                                         final Gen ae,
                                                                         final Cogen c) {
    return new Cogen>() {
      public  Gen cogen(final F5 f, final Gen g) {
        return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, cogenF(ae, c))))).cogen(curry(f), g);
      }
    };
  }

  /**
   * A cogen for a function-6.
   *
   * @param aa A gen for part of the domain of the function.
   * @param ab A gen for part of the domain of the function.
   * @param ac A gen for part of the domain of the function.
   * @param ad A gen for part of the domain of the function.
   * @param ae A gen for part of the domain of the function.
   * @param af A gen for part of the domain of the function.
   * @param c  A cogen for the codomain of the function.
   * @return A cogen for a function-6.
   */
  public static  Cogen> cogenF6(final Gen aa,
                                                                               final Gen ab,
                                                                               final Gen ac,
                                                                               final Gen ad,
                                                                               final Gen ae,
                                                                               final Gen af,
                                                                               final Cogen c) {
    return new Cogen>() {
      public  Gen cogen(final F6 f, final Gen g) {
        return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, cogenF(ae, cogenF(af, c)))))).cogen(curry(f), g);
      }
    };
  }

  /**
   * A cogen for a function-7.
   *
   * @param aa A gen for part of the domain of the function.
   * @param ab A gen for part of the domain of the function.
   * @param ac A gen for part of the domain of the function.
   * @param ad A gen for part of the domain of the function.
   * @param ae A gen for part of the domain of the function.
   * @param af A gen for part of the domain of the function.
   * @param ag A gen for part of the domain of the function.
   * @param c  A cogen for the codomain of the function.
   * @return A cogen for a function-7.
   */
  public static  Cogen> cogenF7(final Gen aa,
                                                                                     final Gen ab,
                                                                                     final Gen ac,
                                                                                     final Gen ad,
                                                                                     final Gen ae,
                                                                                     final Gen af,
                                                                                     final Gen ag,
                                                                                     final Cogen c) {
    return new Cogen>() {
      public  Gen cogen(final F7 f, final Gen g) {
        return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, cogenF(ae, cogenF(af, cogenF(ag, c)))))))
            .cogen(curry(f), g);
      }
    };
  }

  /**
   * A cogen for a function-8.
   *
   * @param aa A gen for part of the domain of the function.
   * @param ab A gen for part of the domain of the function.
   * @param ac A gen for part of the domain of the function.
   * @param ad A gen for part of the domain of the function.
   * @param ae A gen for part of the domain of the function.
   * @param af A gen for part of the domain of the function.
   * @param ag A gen for part of the domain of the function.
   * @param ah A gen for part of the domain of the function.
   * @param c  A cogen for the codomain of the function.
   * @return A cogen for a function-8.
   */
  public static  Cogen> cogenF8(final Gen aa,
                                                                                           final Gen ab,
                                                                                           final Gen ac,
                                                                                           final Gen ad,
                                                                                           final Gen ae,
                                                                                           final Gen af,
                                                                                           final Gen ag,
                                                                                           final Gen ah,
                                                                                           final Cogen c) {
    return new Cogen>() {
      public  Gen cogen(final F8 f, final Gen g) {
        return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, cogenF(ae, cogenF(af, cogenF(ag, cogenF(ah, c))))))))
            .cogen(curry(f), g);
      }
    };
  }

  /**
   * A cogen for booleans.
   */
  public static final Cogen cogenBoolean = new Cogen() {
    public  Gen cogen(final Boolean b, final Gen g) {
      return variant(b ? 0 : 1, g);
    }
  };

  /**
   * A cogen for integers.
   */
  public static final Cogen cogenInteger = new Cogen() {
    public  Gen cogen(final Integer i, final Gen g) {
      return variant(i >= 0 ? 2 * i : -2 * i + 1, g);
    }
  };

  /**
   * A cogen for bytes.
   */
  public static final Cogen cogenByte = new Cogen() {
    public  Gen cogen(final Byte b, final Gen g) {
      return variant(b >= 0 ? 2 * b : -2 * b + 1, g);
    }
  };

  /**
   * A cogen for shorts.
   */
  public static final Cogen cogenShort = new Cogen() {
    public  Gen cogen(final Short s, final Gen g) {
      return variant(s >= 0 ? 2 * s : -2 * s + 1, g);
    }
  };

  /**
   * A cogen for longs.
   */
  public static final Cogen cogenLong = new Cogen() {
    public  Gen cogen(final Long l, final Gen g) {
      return variant(l >= 0L ? 2L * l : -2L * l + 1L, g);
    }
  };

  /**
   * A cogen for characters.
   */
  public static final Cogen cogenCharacter = new Cogen() {
    public  Gen cogen(final Character c, final Gen g) {
      return variant(c << 1, g);
    }
  };

  /**
   * A cogen for floats.
   */
  public static final Cogen cogenFloat = new Cogen() {
    public  Gen cogen(final Float f, final Gen g) {
      return cogenInteger.cogen(floatToRawIntBits(f), g);
    }
  };

  /**
   * A cogen for doubles.
   */
  public static final Cogen cogenDouble = new Cogen() {
    public  Gen cogen(final Double d, final Gen g) {
      return cogenLong.cogen(doubleToRawLongBits(d), g);
    }
  };

  /**
   * A cogen for the optional value.
   *
   * @param ca A cogen for the type of the optional value.
   * @return A cogen for the optional value.
   */
  public static  Cogen> cogenOption(final Cogen ca) {
    return new Cogen>() {
      public  Gen cogen(final Option o, final Gen g) {
        return o.isNone() ? variant(0, g) : variant(1, ca.cogen(o.some(), g));
      }
    };
  }

  /**
   * A cogen for the disjoint union.
   *
   * @param ca A cogen for one side of the disjoint union.
   * @param cb A cogen for one side of the disjoint union.
   * @return A cogen for the disjoint union.
   */
  public static  Cogen> cogenEither(final Cogen ca, final Cogen cb) {
    return new Cogen>() {
      public  Gen cogen(final Either e, final Gen g) {
        return e.isLeft() ?
            variant(0, ca.cogen(e.left().value(), g)) :
            variant(1, cb.cogen(e.right().value(), g));
      }
    };
  }

  /**
   * A cogen for lists.
   *
   * @param ca A cogen for the elements of the list.
   * @return A cogen for lists.
   */
  public static  Cogen> cogenList(final Cogen ca) {
    return new Cogen>() {
      public  Gen cogen(final List as, final Gen g) {
        return as.isEmpty() ?
            variant(0, g) :
            variant(1, ca.cogen(as.head(), cogen(as.tail(), g)));
      }
    };
  }

  /**
   * A cogen for strings.
   */
  public static final Cogen cogenString = new Cogen() {
    public  Gen cogen(final String s, final Gen g) {
      return cogenList(cogenCharacter).cogen(fromString(s), g);
    }
  };

  /**
   * A cogen for string buffers.
   */
  public static final Cogen cogenStringBuffer = new Cogen() {
    public  Gen cogen(final StringBuffer s, final Gen g) {
      return cogenString.cogen(s.toString(), g);
    }
  };

  /**
   * A cogen for string builders.
   */
  public static final Cogen cogenStringBuilder = new Cogen() {
    public  Gen cogen(final StringBuilder s, final Gen g) {
      return cogenString.cogen(s.toString(), g);
    }
  };

  /**
   * A cogen for streams.
   *
   * @param ca A cogen for the elements of the stream.
   * @return A cogen for streams.
   */
  public static  Cogen> cogenStream(final Cogen ca) {
    return new Cogen>() {
      public  Gen cogen(final Stream as, final Gen g) {
        return as.isEmpty() ?
            variant(0, g) :
            variant(1, ca.cogen(as.head(), cogen(as.tail()._1(), g)));
      }
    };
  }

  /**
   * A cogen for the provided LcgRng
   * @return A cogen for the provided LcgRng.
   */
  public static Cogen cogenLcgRng() {
    return new Cogen() {
      @Override
      public  Gen cogen(LcgRng rng, Gen g) {
        long i = rng.getSeed();
        return variant(i >= 0 ? 2 * i : -2 * i + 1, g);
      }
    };
  }

  /**
   * A cogen for state.
   */
  public static  Cogen> cogenState(Gen as, F2 f) {
    return new Cogen>() {
      @Override
      public  Gen cogen(State s1, Gen g) {
        return as.bind(r -> {
          P2 p = s1.run(r);
          return variant(f.f(p._1(), p._2()), g);
        });
      }
    };
  }

  /**
   * A cogen for arrays.
   *
   * @param ca A cogen for the elements of the array.
   * @return A cogen for arrays.
   */
  public static  Cogen> cogenArray(final Cogen ca) {
    return new Cogen>() {
      public  Gen cogen(final Array as, final Gen g) {
        return cogenList(ca).cogen(as.toList(), g);
      }
    };
  }

  /**
   * A cogen for throwables.
   *
   * @param cs A cogen for the throwable message.
   * @return A cogen for throwables.
   */
  public static Cogen cogenThrowable(final Cogen cs) {
    return cs.contramap(Throwable::getMessage);
  }

  /**
   * A cogen for throwables.
   */
  public static final Cogen cogenThrowable =
      cogenThrowable(cogenString);

  // BEGIN java.util

  /**
   * A cogen for array lists.
   *
   * @param ca A cogen for the elements of the array list.
   * @return A cogen for array lists.
   */
  public static  Cogen> cogenArrayList(final Cogen ca) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final ArrayList as, final Gen g) {
        return cogenArray(ca).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for bit sets.
   */
  public static final Cogen cogenBitSet = new Cogen() {
    public  Gen cogen(final BitSet s, final Gen g) {
      List x = nil();

      for (int i = 0; i < s.size(); i++) {
        x = x.snoc(s.get(i));
      }

      return cogenList(cogenBoolean).cogen(x, g);
    }
  };

  /**
   * A cogen for calendars.
   */
  public static final Cogen cogenCalendar = new Cogen() {
    public  Gen cogen(final Calendar c, final Gen g) {
      return cogenLong.cogen(c.getTime().getTime(), g);
    }
  };

  /**
   * A cogen for dates.
   */
  public static final Cogen cogenDate = new Cogen() {
    public  Gen cogen(final Date d, final Gen g) {
      return cogenLong.cogen(d.getTime(), g);
    }
  };

  /**
   * A cogen for enum maps.
   *
   * @param ck A cogen for the map keys.
   * @param cv A cogen for the map values.
   * @return A cogen for enum maps.
   */
  public static , V> Cogen> cogenEnumMap(final Cogen ck,
                                                                         final Cogen cv) {
    return new Cogen>() {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      public  Gen cogen(final EnumMap m, final Gen g) {
        return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g);
      }
    };
  }

  /**
   * A cogen for enum sets.
   *
   * @param c A cogen for the elements of the enum set.
   * @return A cogen for enum sets.
   */
  public static > Cogen> cogenEnumSet(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final EnumSet as, final Gen g) {
        return cogenHashSet(c).cogen(new HashSet<>(as), g);
      }
    };
  }

  /**
   * A cogen for gregorian calendars.
   */
  public static final Cogen cogenGregorianCalendar = new Cogen() {
    public  Gen cogen(final GregorianCalendar c, final Gen g) {
      return cogenLong.cogen(c.getTime().getTime(), g);
    }
  };

  /**
   * A cogen for hash maps.
   *
   * @param ck A cogen for the map keys.
   * @param cv A cogen for the map values.
   * @return A cogen for hash maps.
   */
  public static  Cogen> cogenHashMap(final Cogen ck, final Cogen cv) {
    return new Cogen>() {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      public  Gen cogen(final HashMap m, final Gen g) {
        return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g);
      }
    };
  }

  /**
   * A cogen for hash sets.
   *
   * @param c A cogen for the elements of the hash set.
   * @return A cogen for hash sets.
   */
  public static  Cogen> cogenHashSet(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final HashSet as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for hash tables.
   *
   * @param ck A cogen for the map keys.
   * @param cv A cogen for the map values.
   * @return A cogen for hash tables.
   */
  public static  Cogen> cogenHashtable(final Cogen ck, final Cogen cv) {
    return new Cogen>() {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      public  Gen cogen(final Hashtable h, final Gen g) {
        List> x = nil();

        for (final Map.Entry entry : h.entrySet()) {
          x = x.snoc(p(entry.getKey(), entry.getValue()));
        }

        return cogenList(cogenP2(ck, cv)).cogen(x, g);
      }
    };
  }

  /**
   * A cogen for identity hash maps.
   *
   * @param ck A cogen for the map keys.
   * @param cv A cogen for the map values.
   * @return A cogen for identity hash maps.
   */
  public static  Cogen> cogenIdentityHashMap(final Cogen ck,
                                                                         final Cogen cv) {
    return new Cogen>() {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      public  Gen cogen(final IdentityHashMap m, final Gen g) {
        return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g);
      }
    };
  }

  /**
   * A cogen for linked hash maps.
   *
   * @param ck A cogen for the map keys.
   * @param cv A cogen for the map values.
   * @return A cogen for linked hash maps.
   */
  public static  Cogen> cogenLinkedHashMap(final Cogen ck,
                                                                     final Cogen cv) {
    return new Cogen>() {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      public  Gen cogen(final LinkedHashMap m, final Gen g) {
        return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g);
      }
    };
  }

  /**
   * A cogen for linked hash sets.
   *
   * @param c A cogen for the elements of the linked hash set.
   * @return A cogen for linked hash sets.
   */
  public static  Cogen> cogenLinkedHashSet(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final LinkedHashSet as, final Gen g) {
        return cogenHashSet(c).cogen(new HashSet<>(as), g);
      }
    };
  }

  /**
   * A cogen for linked lists.
   *
   * @param c A cogen for the elements of the linked list.
   * @return A cogen for linked lists.
   */
  public static  Cogen> cogenLinkedList(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final LinkedList as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for priority queues.
   *
   * @param c A cogen for the elements of the priority queue.
   * @return A cogen for priority queues.
   */
  public static  Cogen> cogenPriorityQueue(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final PriorityQueue as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for properties.
   */
  public static final Cogen cogenProperties = new Cogen() {
    @SuppressWarnings("UseOfObsoleteCollectionType")
    public  Gen cogen(final Properties p, final Gen g) {
      final Hashtable t = new Hashtable<>();

      for (final Object s : p.keySet()) {
        t.put((String) s, p.getProperty((String) s));
      }

      return cogenHashtable(cogenString, cogenString).cogen(t, g);
    }
  };

  /**
   * A cogen for stacks.
   *
   * @param c A cogen for the elements of the stack.
   * @return A cogen for stacks.
   */
  public static  Cogen> cogenStack(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final Stack as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for tree maps.
   *
   * @param ck A cogen for the map keys.
   * @param cv A cogen for the map values.
   * @return A cogen for tree maps.
   */
  public static  Cogen> cogenTreeMap(final Cogen ck, final Cogen cv) {
    return new Cogen>() {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      public  Gen cogen(final TreeMap m, final Gen g) {
        return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g);
      }
    };
  }

  /**
   * A cogen for tree sets.
   *
   * @param c A cogen for the elements of the tree set.
   * @return A cogen for tree sets.
   */
  public static  Cogen> cogenTreeSet(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final TreeSet as, final Gen g) {
        return cogenHashSet(c).cogen(new HashSet<>(as), g);
      }
    };
  }

  /**
   * A cogen for vectors.
   *
   * @param c A cogen for the elements of the vector.
   * @return A cogen for vectors.
   */
  public static  Cogen> cogenVector(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings({"unchecked", "UseOfObsoleteCollectionType"})
      public  Gen cogen(final Vector as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for weak hash maps.
   *
   * @param ck A cogen for the map keys.
   * @param cv A cogen for the map values.
   * @return A cogen for weak hash maps.
   */
  public static  Cogen> cogenWeakHashMap(final Cogen ck,
                                                                 final Cogen cv) {
    return new Cogen>() {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      public  Gen cogen(final WeakHashMap m, final Gen g) {
        return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g);
      }
    };
  }

  // END java.util

  // BEGIN java.util.concurrent

  /**
   * A cogen for array blocking queues.
   *
   * @param c A cogen for the elements of the array blocking queue.
   * @return A cogen for array blocking queues.
   */
  public static  Cogen> cogenArrayBlockingQueue(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final ArrayBlockingQueue as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for concurrent hash maps.
   *
   * @param ck A cogen for the map keys.
   * @param cv A cogen for the map values.
   * @return A cogen for concurrent hash maps.
   */
  public static  Cogen> cogenConcurrentHashMap(final Cogen ck,
                                                                             final Cogen cv) {
    return new Cogen>() {
      @SuppressWarnings("UseOfObsoleteCollectionType")
      public  Gen cogen(final ConcurrentHashMap m, final Gen g) {
        return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g);
      }
    };
  }

  /**
   * A cogen for concurrent linked queues.
   *
   * @param c A cogen for the elements of the concurrent linked queue.
   * @return A cogen for concurrent linked queues.
   */
  public static  Cogen> cogenConcurrentLinkedQueue(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final ConcurrentLinkedQueue as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for copy-on-write array lists.
   *
   * @param c A cogen for the elements of the copy-on-write array list.
   * @return A cogen for copy-on-write array lists.
   */
  public static  Cogen> cogenCopyOnWriteArrayList(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final CopyOnWriteArrayList as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for copy-on-write array sets.
   *
   * @param c A cogen for the elements of the copy-on-write array set.
   * @return A cogen for copy-on-write array sets.
   */
  public static  Cogen> cogenCopyOnWriteArraySet(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final CopyOnWriteArraySet as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for delay queues.
   *
   * @param c A cogen for the elements of the delay queue.
   * @return A cogen for delay queues.
   */
  public static  Cogen> cogenDelayQueue(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final DelayQueue as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for linked blocking queues.
   *
   * @param c A cogen for the elements of the linked blocking queue.
   * @return A cogen for linked blocking queues.
   */
  public static  Cogen> cogenLinkedBlockingQueue(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final LinkedBlockingQueue as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for priority blocking queues.
   *
   * @param c A cogen for the elements of the priority blocking queue.
   * @return A cogen for priority blocking queues.
   */
  public static  Cogen> cogenPriorityBlockingQueue(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final PriorityBlockingQueue as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  /**
   * A cogen for synchronous queues.
   *
   * @param c A cogen for the elements of the synchronous queue.
   * @return A cogen for synchronous queues.
   */
  public static  Cogen> cogenSynchronousQueue(final Cogen c) {
    return new Cogen>() {
      @SuppressWarnings("unchecked")
      public  Gen cogen(final SynchronousQueue as, final Gen g) {
        return cogenArray(c).cogen(iterableArray(as), g);
      }
    };
  }

  // END java.util.concurrent

  // BEGIN java.sql

  public static final Cogen cogenSQLDate = new Cogen() {
    public  Gen cogen(final java.sql.Date d, final Gen g) {
      return cogenLong.cogen(d.getTime(), g);
    }
  };

  public static final Cogen cogenTimestamp = new Cogen() {
    public  Gen cogen(final Timestamp t, final Gen g) {
      return cogenLong.cogen(t.getTime(), g);
    }
  };

  public static final Cogen Cogen> cogenP1(final Cogen ca) {
    return new Cogen>() {
      public  Gen cogen(final P1 p, final Gen g) {
        return ca.cogen(p._1(), g);
      }
    };
  }

  /**
   * A cogen for product-2 values.
   *
   * @param ca A cogen for one of the types over which the product-2 is defined.
   * @param cb A cogen for one of the types over which the product-2 is defined.
   * @return A cogen for product-2 values.
   */
  public static  Cogen> cogenP2(final Cogen ca, final Cogen cb) {
    return new Cogen>() {
      public  Gen cogen(final P2 p, final Gen g) {
        return ca.cogen(p._1(), cb.cogen(p._2(), g));
      }
    };
  }

  /**
   * A cogen for product-3 values.
   *
   * @param ca A cogen for one of the types over which the product-3 is defined.
   * @param cb A cogen for one of the types over which the product-3 is defined.
   * @param cc A cogen for one of the types over which the product-3 is defined.
   * @return A cogen for product-3 values.
   */
  public static  Cogen> cogenP3(final Cogen ca, final Cogen cb,
                                                     final Cogen cc) {
    return new Cogen>() {
      public  Gen cogen(final P3 p, final Gen g) {
        return ca.cogen(p._1(), cb.cogen(p._2(), cc.cogen(p._3(), g)));
      }
    };
  }

  /**
   * A cogen for product-4 values.
   *
   * @param ca A cogen for one of the types over which the product-4 is defined.
   * @param cb A cogen for one of the types over which the product-4 is defined.
   * @param cc A cogen for one of the types over which the product-4 is defined.
   * @param cd A cogen for one of the types over which the product-4 is defined.
   * @return A cogen for product-4 values.
   */
  public static  Cogen> cogenP4(final Cogen ca, final Cogen cb,
                                                           final Cogen cc, final Cogen cd) {
    return new Cogen>() {
      public  Gen cogen(final P4 p, final Gen g) {
        return ca.cogen(p._1(), cb.cogen(p._2(), cc.cogen(p._3(), cd.cogen(p._4(), g))));
      }
    };
  }

  /**
   * A cogen for product-5 values.
   *
   * @param ca A cogen for one of the types over which the product-5 is defined.
   * @param cb A cogen for one of the types over which the product-5 is defined.
   * @param cc A cogen for one of the types over which the product-5 is defined.
   * @param cd A cogen for one of the types over which the product-5 is defined.
   * @param ce A cogen for one of the types over which the product-5 is defined.
   * @return A cogen for product-5 values.
   */
  public static  Cogen> cogenP5(final Cogen ca, final Cogen cb,
                                                                 final Cogen cc, final Cogen cd,
                                                                 final Cogen ce) {
    return new Cogen>() {
      public  Gen cogen(final P5 p, final Gen g) {
        return ca.cogen(p._1(),
            cb.cogen(p._2(), cc.cogen(p._3(), cd.cogen(p._4(), ce.cogen(p._5(), g)))));
      }
    };
  }

  /**
   * A cogen for product-6 values.
   *
   * @param ca A cogen for one of the types over which the product-6 is defined.
   * @param cb A cogen for one of the types over which the product-6 is defined.
   * @param cc A cogen for one of the types over which the product-6 is defined.
   * @param cd A cogen for one of the types over which the product-6 is defined.
   * @param ce A cogen for one of the types over which the product-6 is defined.
   * @param cf A cogen for one of the types over which the product-6 is defined.
   * @return A cogen for product-6 values.
   */
  public static  Cogen> cogenP6(final Cogen ca,
                                                                         final Cogen cb,
                                                                         final Cogen cc,
                                                                         final Cogen cd,
                                                                         final Cogen ce,
                                                                         final Cogen cf) {
    return new Cogen>() {
      public  Gen cogen(final P6 p, final Gen g) {
        return ca.cogen(p._1(), cb.cogen(p._2(),
            cc.cogen(p._3(), cd.cogen(p._4(), ce.cogen(p._5(), cf.cogen(p._6(), g))))));
      }
    };
  }

  /**
   * A cogen for product-7 values.
   *
   * @param ca A cogen for one of the types over which the product-7 is defined.
   * @param cb A cogen for one of the types over which the product-7 is defined.
   * @param cc A cogen for one of the types over which the product-7 is defined.
   * @param cd A cogen for one of the types over which the product-7 is defined.
   * @param ce A cogen for one of the types over which the product-7 is defined.
   * @param cf A cogen for one of the types over which the product-7 is defined.
   * @param cg A cogen for one of the types over which the product-7 is defined.
   * @return A cogen for product-7 values.
   */
  public static  Cogen> cogenP7(final Cogen ca,
                                                                               final Cogen cb,
                                                                               final Cogen cc,
                                                                               final Cogen cd,
                                                                               final Cogen ce,
                                                                               final Cogen cf,
                                                                               final Cogen cg) {
    return new Cogen>() {
      public  Gen cogen(final P7 p, final Gen g) {
        return ca.cogen(p._1(), cb.cogen(p._2(), cc.cogen(p._3(),
            cd.cogen(p._4(), ce.cogen(p._5(), cf.cogen(p._6(), cg.cogen(p._7(), g)))))));
      }
    };
  }

  /**
   * A cogen for product-8 values.
   *
   * @param ca A cogen for one of the types over which the product-8 is defined.
   * @param cb A cogen for one of the types over which the product-8 is defined.
   * @param cc A cogen for one of the types over which the product-8 is defined.
   * @param cd A cogen for one of the types over which the product-8 is defined.
   * @param ce A cogen for one of the types over which the product-8 is defined.
   * @param cf A cogen for one of the types over which the product-8 is defined.
   * @param cg A cogen for one of the types over which the product-8 is defined.
   * @param ch A cogen for one of the types over which the product-8 is defined.
   * @return A cogen for product-8 values.
   */
  public static  Cogen> cogenP8(final Cogen ca,
                                                                                     final Cogen cb,
                                                                                     final Cogen cc,
                                                                                     final Cogen cd,
                                                                                     final Cogen ce,
                                                                                     final Cogen cf,
                                                                                     final Cogen cg,
                                                                                     final Cogen ch) {
    return new Cogen>() {
      public  Gen cogen(final P8 p, final Gen g) {
        return ca.cogen(p._1(), cb.cogen(p._2(), cc.cogen(p._3(), cd.cogen(p._4(),
            ce.cogen(p._5(), cf.cogen(p._6(), cg.cogen(p._7(), ch.cogen(p._8(), g))))))));
      }
    };
  }
}