Example usage for org.joda.time LocalDate compareTo

List of usage examples for org.joda.time LocalDate compareTo

Introduction

In this page you can find the example usage for org.joda.time LocalDate compareTo.

Prototype

public int compareTo(ReadablePartial partial) 

Source Link

Document

Compares this partial with another returning an integer indicating the order.

Usage

From source file:org.killbill.billing.entitlement.engine.core.DefaultEventsStream.java

License:Apache License

private void computeEntitlementEffectiveEndDate() {
    LocalDate result = null;/*from   w  ww .  j  ava 2 s.  c om*/
    BlockingState lastEntry;

    lastEntry = (!subscriptionEntitlementStates.isEmpty())
            ? subscriptionEntitlementStates.get(subscriptionEntitlementStates.size() - 1)
            : null;
    if (lastEntry != null && DefaultEntitlementApi.ENT_STATE_CANCELLED.equals(lastEntry.getStateName())) {
        result = new LocalDate(lastEntry.getEffectiveDate(), account.getTimeZone());
    }

    lastEntry = (!bundleEntitlementStates.isEmpty())
            ? bundleEntitlementStates.get(bundleEntitlementStates.size() - 1)
            : null;
    if (lastEntry != null && DefaultEntitlementApi.ENT_STATE_CANCELLED.equals(lastEntry.getStateName())) {
        final LocalDate localDate = new LocalDate(lastEntry.getEffectiveDate(), account.getTimeZone());
        result = ((result == null) || (localDate.compareTo(result) < 0)) ? localDate : result;
    }

    lastEntry = (!accountEntitlementStates.isEmpty())
            ? accountEntitlementStates.get(accountEntitlementStates.size() - 1)
            : null;
    if (lastEntry != null && DefaultEntitlementApi.ENT_STATE_CANCELLED.equals(lastEntry.getStateName())) {
        final LocalDate localDate = new LocalDate(lastEntry.getEffectiveDate(), account.getTimeZone());
        result = ((result == null) || (localDate.compareTo(result) < 0)) ? localDate : result;
    }

    entitlementEffectiveEndDate = result;
}

From source file:org.killbill.billing.invoice.generator.FixedAndRecurringInvoiceItemGenerator.java

License:Apache License

private List<InvoiceItem> processRecurringEvent(final UUID invoiceId, final UUID accountId,
        final BillingEvent thisEvent, @Nullable final BillingEvent nextEvent, final LocalDate targetDate,
        final Currency currency, final InvoiceItemGeneratorLogger invoiceItemGeneratorLogger,
        final BillingMode billingMode,
        final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDate,
        final InternalCallContext internalCallContext) throws InvoiceApiException {

    try {/*from  w ww.  ja  v  a 2 s .c om*/
        final List<InvoiceItem> items = new ArrayList<InvoiceItem>();

        // For FIXEDTERM phases we need to stop when the specified duration has been reached
        final LocalDate maxEndDate = thisEvent.getPlanPhase().getPhaseType() == PhaseType.FIXEDTERM
                ? thisEvent.getPlanPhase().getDuration().addToLocalDate(
                        internalCallContext.toLocalDate(thisEvent.getEffectiveDate()))
                : null;

        // Handle recurring items
        final BillingPeriod billingPeriod = thisEvent.getBillingPeriod();
        if (billingPeriod != BillingPeriod.NO_BILLING_PERIOD) {
            final LocalDate startDate = internalCallContext.toLocalDate(thisEvent.getEffectiveDate());

            if (!startDate.isAfter(targetDate)) {
                final LocalDate endDate = (nextEvent == null) ? null
                        : internalCallContext.toLocalDate(nextEvent.getEffectiveDate());

                final int billCycleDayLocal = thisEvent.getBillCycleDayLocal();

                final RecurringInvoiceItemDataWithNextBillingCycleDate itemDataWithNextBillingCycleDate;
                try {
                    itemDataWithNextBillingCycleDate = generateInvoiceItemData(startDate, endDate, targetDate,
                            billCycleDayLocal, billingPeriod, billingMode);
                } catch (final InvalidDateSequenceException e) {
                    throw new InvoiceApiException(ErrorCode.INVOICE_INVALID_DATE_SEQUENCE, startDate, endDate,
                            targetDate);
                }
                for (final RecurringInvoiceItemData itemDatum : itemDataWithNextBillingCycleDate
                        .getItemData()) {

                    // Stop if there a maxEndDate and we have reached it
                    if (maxEndDate != null && maxEndDate.compareTo(itemDatum.getEndDate()) < 0) {
                        break;
                    }
                    final BigDecimal rate = thisEvent
                            .getRecurringPrice(internalCallContext.toUTCDateTime(itemDatum.getStartDate()));
                    if (rate != null) {
                        final BigDecimal amount = KillBillMoney.of(itemDatum.getNumberOfCycles().multiply(rate),
                                currency);
                        final RecurringInvoiceItem recurringItem = new RecurringInvoiceItem(invoiceId,
                                accountId, thisEvent.getSubscription().getBundleId(),
                                thisEvent.getSubscription().getId(), thisEvent.getPlan().getName(),
                                thisEvent.getPlanPhase().getName(), itemDatum.getStartDate(),
                                itemDatum.getEndDate(), amount, rate, currency);
                        items.add(recurringItem);
                    }
                }
                updatePerSubscriptionNextNotificationDate(thisEvent.getSubscription().getId(),
                        itemDataWithNextBillingCycleDate.getNextBillingCycleDate(), items, billingMode,
                        perSubscriptionFutureNotificationDate);
            }
        }

        // For debugging purposes
        invoiceItemGeneratorLogger.append(thisEvent, items);

        return items;
    } catch (final CatalogApiException e) {
        throw new InvoiceApiException(e);
    }
}

From source file:org.killbill.billing.invoice.generator.FixedAndRecurringInvoiceItemGenerator.java

License:Apache License

private void updatePerSubscriptionNextNotificationDate(final UUID subscriptionId,
        final LocalDate nextBillingCycleDate, final List<InvoiceItem> newProposedItems,
        final BillingMode billingMode,
        final Map<UUID, SubscriptionFutureNotificationDates> perSubscriptionFutureNotificationDates) {

    LocalDate nextNotificationDate = null;
    switch (billingMode) {
    case IN_ADVANCE:
        for (final InvoiceItem item : newProposedItems) {
            if ((item.getEndDate() != null)
                    && (item.getAmount() == null || item.getAmount().compareTo(BigDecimal.ZERO) >= 0)) {
                if (nextNotificationDate == null) {
                    nextNotificationDate = item.getEndDate();
                } else {
                    nextNotificationDate = nextNotificationDate.compareTo(item.getEndDate()) > 0
                            ? nextNotificationDate
                            : item.getEndDate();
                }//from w w  w .  j av  a2  s.  c o m
            }
        }
        break;
    case IN_ARREAR:
        nextNotificationDate = nextBillingCycleDate;
        break;
    default:
        throw new IllegalStateException("Unrecognized billing mode " + billingMode);
    }

    if (nextNotificationDate != null) {
        SubscriptionFutureNotificationDates subscriptionFutureNotificationDates = perSubscriptionFutureNotificationDates
                .get(subscriptionId);
        if (subscriptionFutureNotificationDates == null) {
            subscriptionFutureNotificationDates = new SubscriptionFutureNotificationDates(billingMode);
            perSubscriptionFutureNotificationDates.put(subscriptionId, subscriptionFutureNotificationDates);
        }
        subscriptionFutureNotificationDates.updateNextRecurringDateIfRequired(nextNotificationDate);

    }
}

From source file:org.killbill.billing.invoice.generator.FixedAndRecurringInvoiceItemGenerator.java

License:Apache License

@VisibleForTesting
void safetyBounds(final Iterable<InvoiceItem> resultingItems,
        final Multimap<UUID, LocalDate> createdItemsPerDayPerSubscription,
        final InternalTenantContext internalCallContext) throws InvoiceApiException {
    // Trigger an exception if we detect the creation of similar items for a given subscription
    // See https://github.com/killbill/killbill/issues/664
    if (config.isSanitySafetyBoundEnabled(internalCallContext)) {
        final Map<UUID, Multimap<LocalDate, InvoiceItem>> fixedItemsPerDateAndSubscription = new HashMap<UUID, Multimap<LocalDate, InvoiceItem>>();
        final Map<UUID, Multimap<Range<LocalDate>, InvoiceItem>> recurringItemsPerServicePeriodAndSubscription = new HashMap<UUID, Multimap<Range<LocalDate>, InvoiceItem>>();
        for (final InvoiceItem resultingItem : resultingItems) {
            if (resultingItem.getInvoiceItemType() == InvoiceItemType.FIXED) {
                if (fixedItemsPerDateAndSubscription.get(resultingItem.getSubscriptionId()) == null) {
                    fixedItemsPerDateAndSubscription.put(resultingItem.getSubscriptionId(),
                            LinkedListMultimap.<LocalDate, InvoiceItem>create());
                }/*w ww  .  jav  a2s  .  co  m*/
                fixedItemsPerDateAndSubscription.get(resultingItem.getSubscriptionId())
                        .put(resultingItem.getStartDate(), resultingItem);

                final Collection<InvoiceItem> resultingInvoiceItems = fixedItemsPerDateAndSubscription
                        .get(resultingItem.getSubscriptionId()).get(resultingItem.getStartDate());
                if (resultingInvoiceItems.size() > 1) {
                    throw new InvoiceApiException(ErrorCode.UNEXPECTED_ERROR, String.format(
                            "SAFETY BOUND TRIGGERED Multiple FIXED items for subscriptionId='%s', startDate='%s', resultingItems=%s",
                            resultingItem.getSubscriptionId(), resultingItem.getStartDate(),
                            resultingInvoiceItems));
                }
            } else if (resultingItem.getInvoiceItemType() == InvoiceItemType.RECURRING) {
                if (recurringItemsPerServicePeriodAndSubscription
                        .get(resultingItem.getSubscriptionId()) == null) {
                    recurringItemsPerServicePeriodAndSubscription.put(resultingItem.getSubscriptionId(),
                            LinkedListMultimap.<Range<LocalDate>, InvoiceItem>create());
                }
                final Range<LocalDate> interval = Range.<LocalDate>closedOpen(resultingItem.getStartDate(),
                        resultingItem.getEndDate());
                recurringItemsPerServicePeriodAndSubscription.get(resultingItem.getSubscriptionId())
                        .put(interval, resultingItem);

                final Collection<InvoiceItem> resultingInvoiceItems = recurringItemsPerServicePeriodAndSubscription
                        .get(resultingItem.getSubscriptionId()).get(interval);
                if (resultingInvoiceItems.size() > 1) {
                    throw new InvoiceApiException(ErrorCode.UNEXPECTED_ERROR, String.format(
                            "SAFETY BOUND TRIGGERED Multiple RECURRING items for subscriptionId='%s', startDate='%s', endDate='%s', resultingItems=%s",
                            resultingItem.getSubscriptionId(), resultingItem.getStartDate(),
                            resultingItem.getEndDate(), resultingInvoiceItems));
                }
            }
        }
    }

    // Trigger an exception if we create too many invoice items for a subscription on a given day
    if (config.getMaxDailyNumberOfItemsSafetyBound(internalCallContext) == -1) {
        // Safety bound disabled
        return;
    }

    for (final InvoiceItem invoiceItem : resultingItems) {
        if (invoiceItem.getSubscriptionId() != null) {
            final LocalDate resultingItemCreationDay = trackInvoiceItemCreatedDay(invoiceItem,
                    createdItemsPerDayPerSubscription, internalCallContext);

            final Collection<LocalDate> creationDaysForSubscription = createdItemsPerDayPerSubscription
                    .get(invoiceItem.getSubscriptionId());
            int i = 0;
            for (final LocalDate creationDayForSubscription : creationDaysForSubscription) {
                if (creationDayForSubscription.compareTo(resultingItemCreationDay) == 0) {
                    i++;
                    if (i > config.getMaxDailyNumberOfItemsSafetyBound(internalCallContext)) {
                        // Proposed items have already been logged
                        throw new InvoiceApiException(ErrorCode.UNEXPECTED_ERROR,
                                String.format("SAFETY BOUND TRIGGERED subscriptionId='%s', resultingItem=%s",
                                        invoiceItem.getSubscriptionId(), invoiceItem));
                    }

                }
            }
        }
    }
}

From source file:org.killbill.billing.invoice.InvoiceDispatcher.java

License:Apache License

@VisibleForTesting
FutureAccountNotifications createNextFutureNotificationDate(final Iterable<InvoiceItemModelDao> invoiceItems,
        final BillingEventSet billingEvents, final DateAndTimeZoneContext dateAndTimeZoneContext,
        final InternalCallContext context) {

    final Map<UUID, List<SubscriptionNotification>> result = new HashMap<UUID, List<SubscriptionNotification>>();

    final Map<String, LocalDate> perSubscriptionUsage = new HashMap<String, LocalDate>();

    // For each subscription that has a positive (amount) recurring item, create the date
    // at which we should be called back for next invoice.
    ////from  www .j a v a2s. c om
    for (final InvoiceItemModelDao item : invoiceItems) {

        List<SubscriptionNotification> perSubscriptionCallback = result.get(item.getSubscriptionId());
        if (perSubscriptionCallback == null
                && (item.getType() == InvoiceItemType.RECURRING || item.getType() == InvoiceItemType.USAGE)) {
            perSubscriptionCallback = new ArrayList<SubscriptionNotification>();
            result.put(item.getSubscriptionId(), perSubscriptionCallback);
        }

        switch (item.getType()) {
        case RECURRING:
            if ((item.getEndDate() != null)
                    && (item.getAmount() == null || item.getAmount().compareTo(BigDecimal.ZERO) >= 0)) {
                perSubscriptionCallback.add(new SubscriptionNotification(
                        dateAndTimeZoneContext.computeUTCDateTimeFromLocalDate(item.getEndDate()), true));
            }
            break;

        case USAGE:
            final String key = item.getSubscriptionId().toString() + ":" + item.getUsageName();
            final LocalDate perSubscriptionUsageRecurringDate = perSubscriptionUsage.get(key);
            if (perSubscriptionUsageRecurringDate == null
                    || perSubscriptionUsageRecurringDate.compareTo(item.getEndDate()) < 0) {
                perSubscriptionUsage.put(key, item.getEndDate());
            }
            break;

        default:
            // Ignore
        }
    }

    for (final String key : perSubscriptionUsage.keySet()) {
        final String[] parts = key.split(":");
        final UUID subscriptionId = UUID.fromString(parts[0]);

        final List<SubscriptionNotification> perSubscriptionCallback = result.get(subscriptionId);
        final String usageName = parts[1];
        final LocalDate endDate = perSubscriptionUsage.get(key);

        final DateTime subscriptionUsageCallbackDate = getNextUsageBillingDate(subscriptionId, usageName,
                endDate, dateAndTimeZoneContext, billingEvents);
        perSubscriptionCallback.add(new SubscriptionNotification(subscriptionUsageCallbackDate, true));
    }

    // If dryRunNotification is enabled we also need to fetch the upcoming PHASE dates (we add SubscriptionNotification with isForInvoiceNotificationTrigger = false)
    final boolean isInvoiceNotificationEnabled = invoiceConfig.getDryRunNotificationSchedule().getMillis() > 0;
    if (isInvoiceNotificationEnabled) {
        final Map<UUID, DateTime> upcomingPhasesForSubscriptions = subscriptionApi
                .getNextFutureEventForSubscriptions(SubscriptionBaseTransitionType.PHASE, context);
        for (UUID cur : upcomingPhasesForSubscriptions.keySet()) {
            final DateTime curDate = upcomingPhasesForSubscriptions.get(cur);
            List<SubscriptionNotification> resultValue = result.get(cur);
            if (resultValue == null) {
                resultValue = new ArrayList<SubscriptionNotification>();
            }
            resultValue.add(new SubscriptionNotification(curDate, false));
            result.put(cur, resultValue);
        }
    }
    return new FutureAccountNotifications(dateAndTimeZoneContext, result);
}

From source file:org.killbill.billing.invoice.notification.DefaultNextBillingDatePoster.java

License:Apache License

private void insertNextBillingFromTransactionInternal(
        final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final UUID accountId,
        final UUID subscriptionId, final Boolean isDryRunForInvoiceNotification,
        final DateTime futureNotificationTime, final DateTime targetDate,
        final DateAndTimeZoneContext accountDateAndTimeZoneContext,
        final InternalCallContext internalCallContext) {
    final NotificationQueue nextBillingQueue;
    try {/*from   w ww  .  j ava2s  .c o  m*/
        nextBillingQueue = notificationQueueService.getNotificationQueue(
                DefaultInvoiceService.INVOICE_SERVICE_NAME,
                DefaultNextBillingDateNotifier.NEXT_BILLING_DATE_NOTIFIER_QUEUE);

        // If we see existing notification for the same date (and isDryRunForInvoiceNotification mode), we don't insert a new notification
        final List<NotificationEventWithMetadata<NextBillingDateNotificationKey>> futureNotifications = nextBillingQueue
                .getFutureNotificationFromTransactionForSearchKeys(internalCallContext.getAccountRecordId(),
                        internalCallContext.getTenantRecordId(),
                        entitySqlDaoWrapperFactory.getHandle().getConnection());
        final NotificationEventWithMetadata<NextBillingDateNotificationKey> existingFutureNotificationWithSameDate = Iterables
                .tryFind(futureNotifications,
                        new Predicate<NotificationEventWithMetadata<NextBillingDateNotificationKey>>() {
                            @Override
                            public boolean apply(
                                    final NotificationEventWithMetadata<NextBillingDateNotificationKey> input) {
                                final boolean isEventDryRunForNotifications = input.getEvent()
                                        .isDryRunForInvoiceNotification() != null
                                                ? input.getEvent().isDryRunForInvoiceNotification()
                                                : false;

                                final LocalDate notificationEffectiveLocaleDate = new LocalDate(
                                        futureNotificationTime,
                                        accountDateAndTimeZoneContext.getAccountTimeZone());
                                final LocalDate eventEffectiveLocaleDate = new LocalDate(
                                        input.getEffectiveDate(),
                                        accountDateAndTimeZoneContext.getAccountTimeZone());

                                return notificationEffectiveLocaleDate.compareTo(eventEffectiveLocaleDate) == 0
                                        && ((isDryRunForInvoiceNotification && isEventDryRunForNotifications)
                                                || (!isDryRunForInvoiceNotification
                                                        && !isEventDryRunForNotifications));
                            }
                        })
                .orNull();

        if (existingFutureNotificationWithSameDate == null) {
            log.info("Queuing next billing date notification at {} for subscriptionId {}",
                    futureNotificationTime.toString(), subscriptionId.toString());

            nextBillingQueue.recordFutureNotificationFromTransaction(
                    entitySqlDaoWrapperFactory.getHandle().getConnection(), futureNotificationTime,
                    new NextBillingDateNotificationKey(subscriptionId, targetDate,
                            isDryRunForInvoiceNotification),
                    internalCallContext.getUserToken(), internalCallContext.getAccountRecordId(),
                    internalCallContext.getTenantRecordId());
        } else if (log.isDebugEnabled()) {
            log.debug(
                    "*********************   SKIPPING Queuing next billing date notification at {} for subscriptionId {} *******************",
                    futureNotificationTime.toString(), subscriptionId.toString());
        }

    } catch (final NoSuchNotificationQueue e) {
        log.error("Attempting to put items on a non-existent queue (NextBillingDateNotifier).", e);
    } catch (final IOException e) {
        log.error("Failed to serialize notificationKey for subscriptionId {}", subscriptionId);
    }
}

From source file:org.killbill.billing.invoice.notification.ParentInvoiceCommitmentPoster.java

License:Apache License

public void insertParentInvoiceFromTransactionInternal(
        final EntitySqlDaoWrapperFactory entitySqlDaoWrapperFactory, final UUID invoiceId,
        final DateTime futureNotificationTime, final InternalCallContext internalCallContext) {
    final NotificationQueue commitInvoiceQueue;
    try {//from   www .ja  v  a2 s . co m
        commitInvoiceQueue = notificationQueueService.getNotificationQueue(
                DefaultInvoiceService.INVOICE_SERVICE_NAME,
                ParentInvoiceCommitmentNotifier.PARENT_INVOICE_COMMITMENT_NOTIFIER_QUEUE);

        // If we see existing notification for the same date we don't insert a new notification
        final Iterable<NotificationEventWithMetadata<ParentInvoiceCommitmentNotificationKey>> futureNotifications = commitInvoiceQueue
                .getFutureNotificationFromTransactionForSearchKeys(internalCallContext.getAccountRecordId(),
                        internalCallContext.getTenantRecordId(),
                        entitySqlDaoWrapperFactory.getHandle().getConnection());

        boolean existingFutureNotificationWithSameDate = false;
        for (final NotificationEventWithMetadata<ParentInvoiceCommitmentNotificationKey> input : futureNotifications) {
            final LocalDate notificationEffectiveLocaleDate = internalCallContext
                    .toLocalDate(futureNotificationTime);
            final LocalDate eventEffectiveLocaleDate = internalCallContext
                    .toLocalDate(input.getEffectiveDate());

            if (notificationEffectiveLocaleDate.compareTo(eventEffectiveLocaleDate) == 0) {
                existingFutureNotificationWithSameDate = true;
            }
            // Go through all results to close the connection
        }

        if (!existingFutureNotificationWithSameDate) {
            log.info("Queuing parent invoice commitment notification at {} for invoiceId {}",
                    futureNotificationTime.toString(), invoiceId.toString());

            commitInvoiceQueue.recordFutureNotificationFromTransaction(
                    entitySqlDaoWrapperFactory.getHandle().getConnection(), futureNotificationTime,
                    new ParentInvoiceCommitmentNotificationKey(invoiceId), internalCallContext.getUserToken(),
                    internalCallContext.getAccountRecordId(), internalCallContext.getTenantRecordId());
        } else if (log.isDebugEnabled()) {
            log.debug(
                    "*********************   SKIPPING Queuing parent invoice commitment notification at {} for invoiceId {} *******************",
                    futureNotificationTime.toString(), invoiceId.toString());
        }

    } catch (final NoSuchNotificationQueue e) {
        log.error("Attempting to put items on a non-existent queue (ParentInvoiceCommitmentNotifier).", e);
    } catch (final IOException e) {
        log.error("Failed to serialize notificationKey for invoiceId {}", invoiceId);
    }
}

From source file:org.killbill.billing.invoice.tree.Item.java

License:Apache License

public InvoiceItem toProratedInvoiceItem(final LocalDate newStartDate, final LocalDate newEndDate) {

    int nbTotalDays = Days.daysBetween(startDate, endDate).getDays();
    final boolean prorated = !(newStartDate.compareTo(startDate) == 0 && newEndDate.compareTo(endDate) == 0);

    // Pro-ration is built by using the startDate, endDate and amount of this item instead of using the rate and a potential full period.
    final BigDecimal positiveAmount = prorated ? InvoiceDateUtils
            .calculateProrationBetweenDates(newStartDate, newEndDate, nbTotalDays).multiply(amount) : amount;

    if (action == ItemAction.ADD) {
        return new RecurringInvoiceItem(id, createdDate, invoiceId, accountId, bundleId, subscriptionId,
                planName, phaseName, newStartDate, newEndDate, KillBillMoney.of(positiveAmount, currency), rate,
                currency);/*  ww  w  . j a  v a2  s  .  com*/
    } else {
        // We first compute the maximum amount after adjustment and that sets the amount limit of how much can be repaired.
        final BigDecimal maxAvailableAmountAfterAdj = amount.subtract(adjustedAmount);
        final BigDecimal maxAvailableAmountForRepair = maxAvailableAmountAfterAdj
                .subtract(currentRepairedAmount);
        final BigDecimal positiveAmountForRepair = positiveAmount.compareTo(maxAvailableAmountForRepair) <= 0
                ? positiveAmount
                : maxAvailableAmountForRepair;
        return positiveAmountForRepair.compareTo(BigDecimal.ZERO) > 0
                ? new RepairAdjInvoiceItem(targetInvoiceId, accountId, newStartDate, newEndDate,
                        KillBillMoney.of(positiveAmountForRepair.negate(), currency), currency, linkedId)
                : null;
    }
}

From source file:org.killbill.billing.invoice.tree.NodeInterval.java

License:Apache License

/**
 * Build the tree by calling the callback on the last node in the tree or remaining part with no children.
 *
 * @param callback the callback which perform the build logic.
 * @return whether or not the parent NodeInterval should ignore the period covered by the child (NodeInterval)
 *///from w  ww  .  j  a v a 2s  .c o  m
public void build(final BuildNodeCallback callback) {

    Preconditions.checkNotNull(callback);

    if (leftChild == null) {
        callback.onLastNode(this);
        return;
    }

    LocalDate curDate = start;
    NodeInterval curChild = leftChild;
    while (curChild != null) {
        if (curChild.getStart().compareTo(curDate) > 0) {
            callback.onMissingInterval(this, curDate, curChild.getStart());
        }
        curChild.build(callback);
        // Note that skip to child endDate, meaning that we always consider the child [start end]
        curDate = curChild.getEnd();
        curChild = curChild.getRightSibling();
    }

    // Finally if there is a hole at the end, we build the missing piece from ourselves
    if (curDate.compareTo(end) < 0) {
        callback.onMissingInterval(this, curDate, end);
    }
    return;
}

From source file:org.killbill.billing.invoice.tree.NodeInterval.java

License:Apache License

@JsonIgnore
public boolean isPartitionedByChildren() {

    if (leftChild == null) {
        return false;
    }/* www  .j a  va 2s.c  om*/

    LocalDate curDate = start;
    NodeInterval curChild = leftChild;
    while (curChild != null) {
        if (curChild.getStart().compareTo(curDate) > 0) {
            return false;
        }
        curDate = curChild.getEnd();
        curChild = curChild.getRightSibling();
    }
    return (curDate.compareTo(end) == 0);
}