public int calculateMaxUsesForItemCriteria(OfferItemCriteria itemCriteria, Offer promotion) {
    int numberOfTargets = 0;
    int numberOfUsesForThisItemCriteria = 9999;

    if (candidateTargets != null && itemCriteria != null) {
      for (PromotableOrderItem potentialTarget : candidateTargets) {
        numberOfTargets += potentialTarget.getQuantityAvailableToBeUsedAsTarget(promotion);
      }
      numberOfUsesForThisItemCriteria = numberOfTargets / itemCriteria.getQuantity();
    }

    return numberOfUsesForThisItemCriteria;
  }
  protected void applyItemQualifiersAndTargets(
      PromotableCandidateItemOffer itemOffer, PromotableOrder order) {
    Offer promotion = itemOffer.getOffer();
    OrderItemPriceComparator priceComparator =
        new OrderItemPriceComparator(promotion.getApplyDiscountToSalePrice());
    boolean matchFound = false;
    do {
      matchFound = false;
      int totalQualifiersNeeded = 0;
      for (OfferItemCriteria itemCriteria : itemOffer.getCandidateQualifiersMap().keySet()) {
        totalQualifiersNeeded += itemCriteria.getQuantity();
      }
      int receiveQtyNeeded = promotion.getTargetItemCriteria().getQuantity();

      checkAll:
      {
        for (OfferItemCriteria itemCriteria : itemOffer.getCandidateQualifiersMap().keySet()) {
          List<PromotableOrderItem> chargeableItems =
              itemOffer.getCandidateQualifiersMap().get(itemCriteria);

          // Sort the items so that the highest priced ones are at the top
          Collections.sort(chargeableItems, priceComparator);
          // Calculate the number of qualifiers needed that will not receive the promotion.
          // These will be reserved first before the target is assigned.
          int qualifierQtyNeeded = itemCriteria.getQuantity();

          for (PromotableOrderItem chargeableItem : chargeableItems) {

            // Mark Qualifiers
            if (qualifierQtyNeeded > 0) {
              int itemQtyAvailableToBeUsedAsQualifier =
                  chargeableItem.getQuantityAvailableToBeUsedAsQualifier(promotion);
              if (itemQtyAvailableToBeUsedAsQualifier > 0) {
                int qtyToMarkAsQualifier =
                    Math.min(qualifierQtyNeeded, itemQtyAvailableToBeUsedAsQualifier);
                qualifierQtyNeeded -= qtyToMarkAsQualifier;
                chargeableItem.addPromotionQualifier(itemOffer, itemCriteria, qtyToMarkAsQualifier);
              }
            }

            if (qualifierQtyNeeded == 0) {
              totalQualifiersNeeded -= itemCriteria.getQuantity();
              break;
            }
          }
          if (qualifierQtyNeeded != 0) {
            break checkAll;
          }
        }
        checkTargets:
        {
          List<PromotableOrderItem> chargeableItems = itemOffer.getCandidateTargets();
          Collections.sort(chargeableItems, priceComparator);
          for (PromotableOrderItem chargeableItem : chargeableItems) {
            // Mark Targets
            if (receiveQtyNeeded > 0) {
              int itemQtyAvailableToBeUsedAsTarget =
                  chargeableItem.getQuantityAvailableToBeUsedAsTarget(promotion);
              if (itemQtyAvailableToBeUsedAsTarget > 0) {
                if (promotion.getMaxUses() == 0 || itemOffer.getUses() < promotion.getMaxUses()) {
                  int qtyToMarkAsTarget =
                      Math.min(receiveQtyNeeded, itemQtyAvailableToBeUsedAsTarget);
                  receiveQtyNeeded -= qtyToMarkAsTarget;
                  // atLeastOneCriteriaMatched = true;
                  chargeableItem.addPromotionDiscount(
                      itemOffer, itemOffer.getOffer().getTargetItemCriteria(), qtyToMarkAsTarget);
                }
              }
            }

            if (receiveQtyNeeded == 0) {
              break checkTargets;
            }
          }
        }
      }
      boolean criteriaMatched = true;
      if (receiveQtyNeeded != 0 || totalQualifiersNeeded != 0) {
        // This ItemCriteria did not match.  Therefore, we need to clear all non-finalized
        // quantities.
        for (OfferItemCriteria itemCriteria : itemOffer.getCandidateQualifiersMap().keySet()) {
          List<PromotableOrderItem> chargeableItems =
              itemOffer.getCandidateQualifiersMap().get(itemCriteria);
          clearAllNonFinalizedQuantities(chargeableItems);
        }
        clearAllNonFinalizedQuantities(itemOffer.getCandidateTargets());
        criteriaMatched = false;
      }

      if (criteriaMatched) {
        matchFound = true;
        finalizeQuantities(order.getDiscountableDiscreteOrderItems());
      }
      // This promotion may be able to be applied multiple times if there is enough
      // product quantity in the order. Continue to loop through the order until
      // there are no more matches
    } while (matchFound);

    if (order.getSplitItems().size() == 0) {
      initializeSplitItems(order, order.getDiscountableDiscreteOrderItems());
    }
    List<PromotableOrderItem> allSplitItems = order.getAllSplitItems();
    for (PromotableOrderItem chargeableItem : allSplitItems) {
      if (itemOffer.getCandidateTargets().contains(chargeableItem)) {
        List<PromotableOrderItem> splitItems = chargeableItem.split();
        if (splitItems != null && splitItems.size() > 0) {
          // Remove this item from the list
          List<PromotableOrderItem> temp = order.searchSplitItems(chargeableItem);
          if (!CollectionUtils.isEmpty(temp)) {
            temp.remove(chargeableItem);
            temp.addAll(splitItems);
          }
        }
      }
    }
  }