private static ArrayList getProductElements(Collection qtys, final Collection rates) {
private static ArrayList getProductElements(Schedule qtys, final Schedule rates) {
  private static ArrayList getProductElements(Collection qtys, final Collection rates) {    // if one of the schedules has no matching elements, return an empty OrderedSet.    if (qtys.isEmpty() || rates.isEmpty()) {      return emptySet;    }    // make a new orderedset to hold the new quantityschedulelelements    final Schedule result = new ScheduleImpl();        Thunk qt = new Thunk() {        public void apply(Object o) {          final QuantityScheduleElement qse = (QuantityScheduleElement) o;          final long qse_s = qse.getStartTime();          final long qse_e = qse.getEndTime();          final double q = qse.getQuantity();          Thunk rt = new Thunk() {              public void apply(Object ro) {                RateScheduleElement rse = (RateScheduleElement) ro;                long rse_s = rse.getStartTime();                long rse_e = rse.getEndTime();                if (rse_s < qse_e && rse_e >qse_s) {                  // find the boundaries                  long s = (qse_s>rse_s)?qse_s:rse_s;                  long e = (qse_e<rse_e)?qse_e:rse_e;                                    result.add(newQSE(s,e,q*rse.getRate()));                }              }            };          Collectors.apply(rt, rates);        }      };    Collectors.apply(qt, qtys);    return new ArrayList(result);  }