Details
diff --git a/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java b/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
index f7bf292..632da11 100644
--- a/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
+++ b/api/src/main/java/com/ning/billing/util/tag/ControlTagType.java
@@ -19,21 +19,27 @@ package com.ning.billing.util.tag;
import java.util.UUID;
public enum ControlTagType {
- AUTO_PAY_OFF("Suspends payments until removed.", true, false),
- AUTO_INVOICING_OFF("Suspends invoicing until removed.", false, true),
- OVERDUE_ENFORCEMENT_OFF("Suspends overdue enforcement behaviour until removed.", false, false),
- WRITTEN_OFF("Indicated that an invoice is written off. No billing or payment effect.", false, false);
+ AUTO_PAY_OFF(new UUID(0, 1), "Suspends payments until removed.", true, false),
+ AUTO_INVOICING_OFF(new UUID(0, 2), "Suspends invoicing until removed.", false, true),
+ OVERDUE_ENFORCEMENT_OFF(new UUID(0, 3), "Suspends overdue enforcement behaviour until removed.", false, false),
+ WRITTEN_OFF(new UUID(0, 4), "Indicated that an invoice is written off. No billing or payment effect.", false, false);
+ private final UUID id;
private final String description;
private final boolean autoPaymentOff;
private final boolean autoInvoicingOff;
- ControlTagType(final String description, final boolean autoPaymentOff, final boolean autoInvoicingOff) {
+ ControlTagType(final UUID id, final String description, final boolean autoPaymentOff, final boolean autoInvoicingOff) {
+ this.id = id;
this.description = description;
this.autoPaymentOff = autoPaymentOff;
this.autoInvoicingOff = autoInvoicingOff;
}
+ public UUID getId() {
+ return id;
+ }
+
public String getDescription() {
return this.description;
}
@@ -65,7 +71,7 @@ public enum ControlTagType {
@Override
public UUID getId() {
- return null;
+ return id;
}
};
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/RepairEntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/RepairEntitlementDao.java
index ed9cf13..069a325 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/RepairEntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/RepairEntitlementDao.java
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
@@ -16,6 +16,7 @@
package com.ning.billing.entitlement.engine.dao;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -26,6 +27,8 @@ import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
import com.ning.billing.entitlement.api.SubscriptionFactory;
import com.ning.billing.entitlement.api.migration.AccountMigrationData;
import com.ning.billing.entitlement.api.timeline.RepairEntitlementLifecycleDao;
@@ -43,27 +46,69 @@ public class RepairEntitlementDao implements EntitlementDao, RepairEntitlementLi
private final ThreadLocal<Map<UUID, SubscriptionRepairEvent>> preThreadsInRepairSubscriptions = new ThreadLocal<Map<UUID, SubscriptionRepairEvent>>();
+
+ private final static class EntitlementEventWithOrderingId {
+
+ private final EntitlementEvent event;
+ private final long orderingId;
+
+ public EntitlementEventWithOrderingId(EntitlementEvent event, long orderingId) {
+ this.event = event;
+ this.orderingId = orderingId;
+ }
+
+ public EntitlementEvent getEvent() {
+ return event;
+ }
+ public long getOrderingId() {
+ return orderingId;
+ }
+
+ }
+
private static final class SubscriptionRepairEvent {
- private final Set<EntitlementEvent> events;
+
+ private final Set<EntitlementEventWithOrderingId> events;
+ private long curOrderingId;
public SubscriptionRepairEvent(final List<EntitlementEvent> initialEvents) {
- events = new TreeSet<EntitlementEvent>(new Comparator<EntitlementEvent>() {
+ this.events = new TreeSet<EntitlementEventWithOrderingId>(new Comparator<EntitlementEventWithOrderingId>() {
@Override
- public int compare(final EntitlementEvent o1, final EntitlementEvent o2) {
- return o1.compareTo(o2);
+ public int compare(final EntitlementEventWithOrderingId o1, final EntitlementEventWithOrderingId o2) {
+ int result = o1.getEvent().getEffectiveDate().compareTo(o2.getEvent().getEffectiveDate());
+ if (result == 0) {
+ if (o1.getOrderingId() < o2.getOrderingId()) {
+ return -1;
+ } else if (o1.getOrderingId() > o2.getOrderingId()) {
+ return 1;
+ } else {
+ throw new RuntimeException("Repair entitlement events should not have the same orderingId");
+ }
+ }
+ return result;
}
});
+
+ this.curOrderingId = 0;
+
if (initialEvents != null) {
- events.addAll(initialEvents);
+ addEvents(initialEvents);
}
}
- public Set<EntitlementEvent> getEvents() {
- return events;
+ public List<EntitlementEvent> getEvents() {
+ return new ArrayList<EntitlementEvent>(Collections2.transform(events, new Function<EntitlementEventWithOrderingId, EntitlementEvent>() {
+ @Override
+ public EntitlementEvent apply(EntitlementEventWithOrderingId in) {
+ return in.getEvent();
+ }
+ }));
}
public void addEvents(final List<EntitlementEvent> newEvents) {
- events.addAll(newEvents);
+ for (EntitlementEvent cur : newEvents) {
+ events.add(new EntitlementEventWithOrderingId(cur, curOrderingId++));
+ }
}
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/timeline/TestRepairBP.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/timeline/TestRepairBP.java
index de7a40d..6ff4c51 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/timeline/TestRepairBP.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/timeline/TestRepairBP.java
@@ -122,8 +122,7 @@ public class TestRepairBP extends TestApiBaseRepair {
assertListenerStatus();
}
- //TODO MDW: Temporary disable need to look at this with Stephane
- @Test(groups = "slow", enabled = false)
+ @Test(groups = "slow")
public void testBPRepairWithCancellationOnstart() throws Exception {
final String baseProduct = "Shotgun";
final DateTime startDate = clock.getUTCNow();
diff --git a/util/src/main/java/com/ning/billing/util/dao/AuditedCollectionDaoBase.java b/util/src/main/java/com/ning/billing/util/dao/AuditedCollectionDaoBase.java
index f129496..e01e6a9 100644
--- a/util/src/main/java/com/ning/billing/util/dao/AuditedCollectionDaoBase.java
+++ b/util/src/main/java/com/ning/billing/util/dao/AuditedCollectionDaoBase.java
@@ -16,6 +16,7 @@
package com.ning.billing.util.dao;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -112,7 +113,7 @@ public abstract class AuditedCollectionDaoBase<T extends Entity, V> implements A
// Find all pairs <entity id, record id> (including those that are about to be deleted) for this parent object
final List<Mapper<UUID, Long>> recordIds = dao.getRecordIds(objectId.toString(), objectType);
// Flip the map to look up the record id associated with an entity id
- final Map<UUID, Long> recordIdMap = convertToHistoryMap(recordIds);
+ final Map<UUID, Long> recordIdMap = convertToHistoryMap(recordIds, objectType);
// Perform the deletes
if (objsToRemove.size() != 0) {
@@ -169,7 +170,12 @@ public abstract class AuditedCollectionDaoBase<T extends Entity, V> implements A
for (final T entity : entities) {
final UUID id = entity.getId();
- histories.add(new EntityHistory<T>(id, recordIds.get(id), entity, changeType));
+
+ final Long recordId = recordIds.get(id);
+ if (recordId == null) {
+ throw new IllegalStateException("recordId for object " + entity.getClass() + " is null ");
+ }
+ histories.add(new EntityHistory<T>(id, recordId, entity, changeType));
}
return histories;
@@ -187,9 +193,16 @@ public abstract class AuditedCollectionDaoBase<T extends Entity, V> implements A
return audits;
}
- protected Map<UUID, Long> convertToHistoryMap(final List<Mapper<UUID, Long>> recordIds) {
+ protected Map<UUID, Long> convertToHistoryMap(final List<Mapper<UUID, Long>> recordIds, final ObjectType objectType) {
final Map<UUID, Long> recordIdMap = new HashMap<UUID, Long>();
for (final Mapper<UUID, Long> recordId : recordIds) {
+ if (recordId.getKey() == null) {
+ throw new IllegalStateException("UUID for object " + objectType + " is null for recordId " + recordId.getValue());
+ }
+ if (recordId.getValue() == null) {
+ throw new IllegalStateException("recordId for object " + objectType + " is null for UUID " + recordId.getKey());
+ }
+
recordIdMap.put(recordId.getKey(), recordId.getValue());
}
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
index 67410ee..d990f7e 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/AuditedTagDao.java
@@ -83,7 +83,7 @@ public class AuditedTagDao extends AuditedCollectionDaoBase<Tag, Tag> implements
// Gather the tag ids for this object id
final List<Mapper<UUID, Long>> recordIds = tagSqlDao.getRecordIds(objectId.toString(), objectType);
- final Map<UUID, Long> recordIdMap = convertToHistoryMap(recordIds);
+ final Map<UUID, Long> recordIdMap = convertToHistoryMap(recordIds, objectType);
// Update the history table
final List<EntityHistory<Tag>> entityHistories = convertToHistory(tagList, recordIdMap, ChangeType.INSERT);
@@ -131,7 +131,7 @@ public class AuditedTagDao extends AuditedCollectionDaoBase<Tag, Tag> implements
// Before the deletion, gather the tag ids for this object id
final List<Mapper<UUID, Long>> recordIds = tagSqlDao.getRecordIds(objectId.toString(), objectType);
- final Map<UUID, Long> recordIdMap = convertToHistoryMap(recordIds);
+ final Map<UUID, Long> recordIdMap = convertToHistoryMap(recordIds, objectType);
// Delete the tag
tagSqlDao.deleteFromTransaction(objectId.toString(), objectType, tagList, context);
@@ -163,6 +163,7 @@ public class AuditedTagDao extends AuditedCollectionDaoBase<Tag, Tag> implements
}
});
} catch (TransactionFailedException exception) {
+
if (exception.getCause() instanceof TagDefinitionApiException) {
throw (TagApiException) exception.getCause();
} else {