killbill-memoizeit

account: change semantics of the update call On update, populate

6/25/2012 6:25:52 PM

Details

diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index 022ada4..58a6904 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -20,6 +20,9 @@ import java.util.UUID;
 
 import org.joda.time.DateTimeZone;
 
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.util.entity.EntityBase;
@@ -99,17 +102,17 @@ public class DefaultAccount extends EntityBase implements Account {
 
     @Override
     public String getExternalKey() {
-        return externalKey;
+        return Strings.nullToEmpty(externalKey);
     }
 
     @Override
     public String getName() {
-        return name;
+        return Strings.nullToEmpty(name);
     }
 
     @Override
     public String getEmail() {
-        return email;
+        return Strings.nullToEmpty(email);
     }
 
     @Override
@@ -139,42 +142,42 @@ public class DefaultAccount extends EntityBase implements Account {
 
     @Override
     public String getLocale() {
-        return locale;
+        return Strings.nullToEmpty(locale);
     }
 
     @Override
     public String getAddress1() {
-        return address1;
+        return Strings.nullToEmpty(address1);
     }
 
     @Override
     public String getAddress2() {
-        return address2;
+        return Strings.nullToEmpty(address2);
     }
 
     @Override
     public String getCompanyName() {
-        return companyName;
+        return Strings.nullToEmpty(companyName);
     }
 
     @Override
     public String getCity() {
-        return city;
+        return Strings.nullToEmpty(city);
     }
 
     @Override
     public String getStateOrProvince() {
-        return stateOrProvince;
+        return Strings.nullToEmpty(stateOrProvince);
     }
 
     @Override
     public String getPostalCode() {
-        return postalCode;
+        return Strings.nullToEmpty(postalCode);
     }
 
     @Override
     public String getCountry() {
-        return country;
+        return Strings.nullToEmpty(country);
     }
 
     @Override
@@ -189,7 +192,7 @@ public class DefaultAccount extends EntityBase implements Account {
 
     @Override
     public String getPhone() {
-        return phone;
+        return Strings.nullToEmpty(phone);
     }
 
     @Override
@@ -198,6 +201,33 @@ public class DefaultAccount extends EntityBase implements Account {
     }
 
     @Override
+    public Account mergeWithDelegate(final Account delegate) {
+        final DefaultMutableAccountData accountData = new DefaultMutableAccountData(this);
+        accountData.setExternalKey(Objects.firstNonNull(externalKey, delegate.getExternalKey()));
+        accountData.setEmail(Objects.firstNonNull(email, delegate.getEmail()));
+        accountData.setName(Objects.firstNonNull(name, delegate.getName()));
+        accountData.setFirstNameLength(Objects.firstNonNull(firstNameLength, delegate.getFirstNameLength()));
+        accountData.setCurrency(Objects.firstNonNull(currency, delegate.getCurrency()));
+        accountData.setBillCycleDay(Objects.firstNonNull(billCycleDay, delegate.getBillCycleDay()));
+        accountData.setPaymentMethodId(Optional.<UUID>fromNullable(paymentMethodId)
+                                               .or(Optional.<UUID>fromNullable(delegate.getPaymentMethodId())).orNull());
+        accountData.setTimeZone(Objects.firstNonNull(timeZone, delegate.getTimeZone()));
+        accountData.setLocale(Objects.firstNonNull(locale, delegate.getLocale()));
+        accountData.setAddress1(Objects.firstNonNull(address1, delegate.getAddress1()));
+        accountData.setAddress2(Objects.firstNonNull(address2, delegate.getAddress2()));
+        accountData.setCompanyName(Objects.firstNonNull(companyName, delegate.getCompanyName()));
+        accountData.setCity(Objects.firstNonNull(city, delegate.getCity()));
+        accountData.setStateOrProvince(Objects.firstNonNull(stateOrProvince, delegate.getStateOrProvince()));
+        accountData.setCountry(Objects.firstNonNull(country, delegate.getCountry()));
+        accountData.setPostalCode(Objects.firstNonNull(postalCode, delegate.getPostalCode()));
+        accountData.setPhone(Objects.firstNonNull(phone, delegate.getPhone()));
+        accountData.setIsMigrated(Objects.firstNonNull(isMigrated, delegate.isMigrated()));
+        accountData.setIsMigrated(Objects.firstNonNull(isNotifiedForInvoices, delegate.isNotifiedForInvoices()));
+
+        return new DefaultAccount(delegate.getId(), accountData);
+    }
+
+    @Override
     public String toString() {
         return "DefaultAccount [externalKey=" + externalKey +
                 ", email=" + email +
diff --git a/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java b/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
index 8d4dca4..a232732 100644
--- a/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
+++ b/account/src/main/java/com/ning/billing/account/dao/AuditedAccountDao.java
@@ -89,14 +89,15 @@ public class AuditedAccountDao implements AccountDao {
                     if (currentAccount != null) {
                         throw new AccountApiException(ErrorCode.ACCOUNT_ALREADY_EXISTS, key);
                     }
+
                     transactionalDao.create(account, context);
 
-                    // insert history
+                    // Insert history
                     final Long recordId = accountSqlDao.getRecordId(account.getId().toString());
                     final EntityHistory<Account> history = new EntityHistory<Account>(account.getId(), recordId, account, ChangeType.INSERT);
                     accountSqlDao.insertHistoryFromTransaction(history, context);
 
-                    // insert audit
+                    // Insert audit
                     final Long historyRecordId = accountSqlDao.getHistoryRecordId(recordId);
                     final EntityAudit audit = new EntityAudit(TableName.ACCOUNT_HISTORY, historyRecordId, ChangeType.INSERT);
                     accountSqlDao.insertAuditFromTransaction(audit, context);
@@ -122,38 +123,41 @@ public class AuditedAccountDao implements AccountDao {
     }
 
     @Override
-    public void update(final Account account, final CallContext context) throws EntityPersistenceException {
+    public void update(final Account specifiedAccount, final CallContext context) throws EntityPersistenceException {
         try {
             accountSqlDao.inTransaction(new Transaction<Void, AccountSqlDao>() {
                 @Override
                 public Void inTransaction(final AccountSqlDao transactional, final TransactionStatus status) throws EntityPersistenceException, Bus.EventBusException {
-                    final String accountId = account.getId().toString();
-                    final Account currentAccount = transactional.getById(accountId);
+                    final UUID accountId = specifiedAccount.getId();
+                    final Account currentAccount = transactional.getById(accountId.toString());
                     if (currentAccount == null) {
                         throw new EntityPersistenceException(ErrorCode.ACCOUNT_DOES_NOT_EXIST_FOR_ID, accountId);
                     }
 
                     final String currentKey = currentAccount.getExternalKey();
-                    if (!currentKey.equals(account.getExternalKey())) {
+                    if (!currentKey.equals(specifiedAccount.getExternalKey())) {
                         throw new EntityPersistenceException(ErrorCode.ACCOUNT_CANNOT_CHANGE_EXTERNAL_KEY, currentKey);
                     }
 
+                    // Set unspecified (null) fields to their current values
+                    final Account account = specifiedAccount.mergeWithDelegate(currentAccount);
+
                     transactional.update(account, context);
 
-                    final Long recordId = accountSqlDao.getRecordId(account.getId().toString());
-                    final EntityHistory<Account> history = new EntityHistory<Account>(account.getId(), recordId, account, ChangeType.INSERT);
+                    final Long recordId = accountSqlDao.getRecordId(accountId.toString());
+                    final EntityHistory<Account> history = new EntityHistory<Account>(accountId, recordId, account, ChangeType.INSERT);
                     accountSqlDao.insertHistoryFromTransaction(history, context);
 
                     final Long historyRecordId = accountSqlDao.getHistoryRecordId(recordId);
                     final EntityAudit audit = new EntityAudit(TableName.ACCOUNT_HISTORY, historyRecordId, ChangeType.INSERT);
                     accountSqlDao.insertAuditFromTransaction(audit, context);
 
-                    final AccountChangeEvent changeEvent = new DefaultAccountChangeEvent(account.getId(), context.getUserToken(), currentAccount, account);
+                    final AccountChangeEvent changeEvent = new DefaultAccountChangeEvent(accountId, context.getUserToken(), currentAccount, account);
                     if (changeEvent.hasChanges()) {
                         try {
                             eventBus.postFromTransaction(changeEvent, transactional);
                         } catch (EventBusException e) {
-                            log.warn("Failed to post account change event for account " + account.getId(), e);
+                            log.warn("Failed to post account change event for account " + accountId, e);
                         }
                     }
                     return null;
diff --git a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
index e56bf58..f92db6a 100644
--- a/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
+++ b/account/src/main/resources/com/ning/billing/account/dao/AccountSqlDao.sql.stg
@@ -138,4 +138,4 @@ insertAuditFromTransaction() ::= <<
 test() ::= <<
     SELECT 1 FROM accounts;
 >>
-;
\ No newline at end of file
+;
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
index 4c9205c..54f9302 100644
--- a/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
+++ b/account/src/test/java/com/ning/billing/account/dao/TestAccountDao.java
@@ -345,40 +345,6 @@ public class TestAccountDao extends AccountDaoTestBase {
         assertEquals(savedAccount.getPhone(), phone);
     }
 
-    @Test
-    public void testRemovingContactInformation() throws Exception {
-        final UUID accountId = UUID.randomUUID();
-
-        final DefaultAccount account = new DefaultAccount(accountId, "extKey654321", "myemail654321@glam.com",
-                                                          "John Smith", 4, Currency.USD, 15, null,
-                                                          DateTimeZone.forID("America/Cambridge_Bay"), "EN-CA",
-                                                          "123 address 1", "456 address 2", null, "Cambridge Bay",
-                                                          "Nunavut", "Canada", "X0B 0C0", "18001112222",
-                                                          false, false);
-        accountDao.create(account, context);
-
-        final DefaultAccount updatedAccount = new DefaultAccount(accountId, "extKey654321", "myemail654321@glam.com",
-                                                                 "John Smith", 4, Currency.USD, 15, null,
-                                                                 DateTimeZone.forID("America/Cambridge_Bay"), "EN-CA",
-                                                                 null, null, null, null, null, null, null, null,
-                                                                 false, false);
-
-        accountDao.update(updatedAccount, context);
-
-        final Account savedAccount = accountDao.getById(accountId);
-
-        assertNotNull(savedAccount);
-        assertEquals(savedAccount.getId(), accountId);
-        assertEquals(savedAccount.getAddress1(), null);
-        assertEquals(savedAccount.getAddress2(), null);
-        assertEquals(savedAccount.getCompanyName(), null);
-        assertEquals(savedAccount.getCity(), null);
-        assertEquals(savedAccount.getStateOrProvince(), null);
-        assertEquals(savedAccount.getCity(), null);
-        assertEquals(savedAccount.getPostalCode(), null);
-        assertEquals(savedAccount.getPhone(), null);
-    }
-
     @Test(expectedExceptions = EntityPersistenceException.class)
     public void testExternalKeyCannotBeUpdated() throws Exception {
         final UUID accountId = UUID.randomUUID();
diff --git a/api/src/main/java/com/ning/billing/account/api/Account.java b/api/src/main/java/com/ning/billing/account/api/Account.java
index 076afd7..dd6804a 100644
--- a/api/src/main/java/com/ning/billing/account/api/Account.java
+++ b/api/src/main/java/com/ning/billing/account/api/Account.java
@@ -21,4 +21,6 @@ import com.ning.billing.util.entity.UpdatableEntity;
 
 public interface Account extends AccountData, UpdatableEntity, Blockable {
     public MutableAccountData toMutableAccountData();
+
+    public Account mergeWithDelegate(final Account delegate);
 }
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java
index 207825c..38820bf 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java
@@ -148,4 +148,9 @@ public class BlockingAccount implements Account {
     public boolean isNotifiedForInvoices() {
         return account.isNotifiedForInvoices();
     }
+
+    @Override
+    public Account mergeWithDelegate(final Account delegate) {
+        return account.mergeWithDelegate(delegate);
+    }
 }
diff --git a/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java b/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
index 2255d5f..f0547e6 100644
--- a/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
+++ b/util/src/test/java/com/ning/billing/mock/MockAccountBuilder.java
@@ -303,6 +303,11 @@ public class MockAccountBuilder {
             public MutableAccountData toMutableAccountData() {
                 throw new UnsupportedOperationException();
             }
+
+            @Override
+            public Account mergeWithDelegate(final Account delegate) {
+                throw new UnsupportedOperationException();
+            }
         };
     }
 }