// get all non-discontinued virtuals, see if all variant ProductAssocs are expired, if discontinue
EntityCondition condition = new EntityConditionList(UtilMisc.toList(
new EntityExpr("isVirtual", EntityOperator.EQUALS, "Y"),
new EntityExpr(new EntityExpr("salesDiscontinuationDate", EntityOperator.EQUALS, null), EntityOperator.OR, new EntityExpr("salesDiscontinuationDate", EntityOperator.GREATER_THAN_EQUAL_TO, nowTimestamp))
), EntityOperator.AND);
EntityListIterator eli = delegator.findListIteratorByCondition("Product", condition, null, null);
GenericValue product = null;
int numSoFar = 0;
while ((product = (GenericValue) eli.next()) != null) {
List passocList = delegator.findByAnd("ProductAssoc", UtilMisc.toMap("productId", product.get("productId"), "productAssocTypeId", "PRODUCT_VARIANT"));
passocList = EntityUtil.filterByDate(passocList, nowTimestamp);