killbill-memoizeit

util: make DefaultTagDefinitionDao transactional This

6/12/2012 10:22:43 PM

Details

diff --git a/api/src/main/java/com/ning/billing/util/api/TagUserApi.java b/api/src/main/java/com/ning/billing/util/api/TagUserApi.java
index 422221a..2be6d6d 100644
--- a/api/src/main/java/com/ning/billing/util/api/TagUserApi.java
+++ b/api/src/main/java/com/ning/billing/util/api/TagUserApi.java
@@ -25,51 +25,41 @@ import com.ning.billing.util.dao.ObjectType;
 import com.ning.billing.util.tag.Tag;
 import com.ning.billing.util.tag.TagDefinition;
 
-// TODO: add ability to create, update and remove tags
 public interface TagUserApi {
-    /***
-     *
+    /**
      * @return the list of all available tag definitions
      */
     public List<TagDefinition> getTagDefinitions();
 
-    /***
-     *
+    /**
      * @param definitionName Identifies the definition.
-     * @param description Describes the use of the definition.
-     * @param context The call context, for auditing purposes
+     * @param description    Describes the use of the definition.
+     * @param context        The call context, for auditing purposes
      * @return the newly created tag definition
      * @throws TagDefinitionApiException
      */
     public TagDefinition create(String definitionName, String description, CallContext context) throws TagDefinitionApiException;
 
-    /***
-     *
+    /**
      * @param definitionName Identifies the definition.
-     * @param context The call context, for auditing purposes
-     * @throws TagDefinitionApiException
-     */
-    public void deleteAllTagsForDefinition(String definitionName, CallContext context) throws TagDefinitionApiException;
-
-    /***
-     *
-     * @param definitionName Identifies the definition.
-     * @param context The call context, for auditing purposes
+     * @param context        The call context, for auditing purposes
      * @throws TagDefinitionApiException
      */
     public void deleteTagDefinition(String definitionName, CallContext context) throws TagDefinitionApiException;
 
-	/**
-	 *
-	 * @param name
-	 * @return the tag with this definition
+    /**
+     * @param name
+     * @return the tag with this definition
      * @throws TagDefinitionApiException
-	 */
-	public TagDefinition getTagDefinition(String name) throws TagDefinitionApiException;
+     */
+    public TagDefinition getTagDefinition(String name) throws TagDefinitionApiException;
 
     public void addTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context);
+
     public void addTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context);
+
     public void removeTags(UUID objectId, ObjectType objectType, List<TagDefinition> tagDefinitions, CallContext context);
+
     public void removeTag(UUID objectId, ObjectType objectType, TagDefinition tagDefinition, CallContext context);
 
     public Map<String, Tag> getTags(UUID objectId, ObjectType objectType);
diff --git a/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java b/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
index c3edd34..93de7f8 100644
--- a/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
+++ b/util/src/main/java/com/ning/billing/util/tag/api/DefaultTagUserApi.java
@@ -51,14 +51,8 @@ public class DefaultTagUserApi implements TagUserApi {
     }
 
     @Override
-    public void deleteAllTagsForDefinition(final String definitionName, final CallContext context)
-            throws TagDefinitionApiException {
-        tagDefinitionDao.deleteAllTagsForDefinition(definitionName, context);
-    }
-
-    @Override
     public void deleteTagDefinition(final String definitionName, final CallContext context) throws TagDefinitionApiException {
-        tagDefinitionDao.deleteAllTagsForDefinition(definitionName, context);
+        tagDefinitionDao.deleteTagDefinition(definitionName, context);
     }
 
     @Override
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
index afad118..049c42d 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
@@ -20,6 +20,9 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.skife.jdbi.v2.IDBI;
+import org.skife.jdbi.v2.Transaction;
+import org.skife.jdbi.v2.TransactionStatus;
+import org.skife.jdbi.v2.exceptions.TransactionFailedException;
 
 import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
@@ -32,7 +35,7 @@ import com.ning.billing.util.tag.TagDefinition;
 import com.ning.billing.util.tag.api.user.TagEventBuilder;
 
 public class DefaultTagDefinitionDao implements TagDefinitionDao {
-    private final TagDefinitionSqlDao dao;
+    private final TagDefinitionSqlDao tagDefinitionSqlDao;
     private final TagEventBuilder tagEventBuilder;
     private final Bus bus;
 
@@ -40,16 +43,16 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
     public DefaultTagDefinitionDao(final IDBI dbi, final TagEventBuilder tagEventBuilder, final Bus bus) {
         this.tagEventBuilder = tagEventBuilder;
         this.bus = bus;
-        this.dao = dbi.onDemand(TagDefinitionSqlDao.class);
+        this.tagDefinitionSqlDao = dbi.onDemand(TagDefinitionSqlDao.class);
     }
 
     @Override
     public List<TagDefinition> getTagDefinitions() {
-        // get user definitions from the database
+        // Get user definitions from the database
         final List<TagDefinition> definitionList = new ArrayList<TagDefinition>();
-        definitionList.addAll(dao.get());
+        definitionList.addAll(tagDefinitionSqlDao.get());
 
-        // add control tag definitions
+        // Add control tag definitions
         for (final ControlTagType controlTag : ControlTagType.values()) {
             definitionList.add(new DefaultTagDefinition(controlTag.toString(), controlTag.getDescription(), true));
         }
@@ -59,31 +62,47 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
 
     @Override
     public TagDefinition getByName(final String definitionName) {
-        // add control tag definitions
+        // Add control tag definitions
         for (final ControlTagType controlTag : ControlTagType.values()) {
             if (definitionName.equals(controlTag.name())) {
                 return new DefaultTagDefinition(controlTag.toString(), controlTag.getDescription(), true);
             }
         }
-        return dao.getByName(definitionName);
+
+        return tagDefinitionSqlDao.getByName(definitionName);
     }
 
     @Override
     public TagDefinition create(final String definitionName, final String description,
                                 final CallContext context) throws TagDefinitionApiException {
+        // Make sure a control tag with this name don't already exist
         if (isControlTagName(definitionName)) {
             throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_CONFLICTS_WITH_CONTROL_TAG, definitionName);
         }
 
-        final TagDefinition existingDefinition = dao.getByName(definitionName);
-
-        if (existingDefinition != null) {
-            throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_ALREADY_EXISTS, definitionName);
+        try {
+            return tagDefinitionSqlDao.inTransaction(new Transaction<TagDefinition, TagDefinitionSqlDao>() {
+                @Override
+                public TagDefinition inTransaction(final TagDefinitionSqlDao transactional, final TransactionStatus status) throws Exception {
+                    // Make sure the tag definition doesn't exist already
+                    final TagDefinition existingDefinition = tagDefinitionSqlDao.getByName(definitionName);
+                    if (existingDefinition != null) {
+                        throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_ALREADY_EXISTS, definitionName);
+                    }
+
+                    final TagDefinition definition = new DefaultTagDefinition(definitionName, description, false);
+                    tagDefinitionSqlDao.create(definition, context);
+
+                    return definition;
+                }
+            });
+        } catch (TransactionFailedException exception) {
+            if (exception.getCause() instanceof TagDefinitionApiException) {
+                throw (TagDefinitionApiException) exception.getCause();
+            } else {
+                throw exception;
+            }
         }
-
-        final TagDefinition definition = new DefaultTagDefinition(definitionName, description, false);
-        dao.create(definition, context);
-        return definition;
     }
 
     private boolean isControlTagName(final String definitionName) {
@@ -97,27 +116,33 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
     }
 
     @Override
-    public void deleteAllTagsForDefinition(final String definitionName, final CallContext context) throws TagDefinitionApiException {
-        final TagDefinition existingDefinition = dao.getByName(definitionName);
-        if (existingDefinition == null) {
-            throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_DOES_NOT_EXIST, definitionName);
-        }
-
-        dao.deleteAllTagsForDefinition(definitionName, context);
-    }
-
-    @Override
     public void deleteTagDefinition(final String definitionName, final CallContext context) throws TagDefinitionApiException {
-        if (dao.tagDefinitionUsageCount(definitionName) > 0) {
-            throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_IN_USE, definitionName);
-        }
-
-        final TagDefinition existingDefinition = dao.getByName(definitionName);
-
-        if (existingDefinition == null) {
-            throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_DOES_NOT_EXIST, definitionName);
+        try {
+            tagDefinitionSqlDao.inTransaction(new Transaction<Void, TagDefinitionSqlDao>() {
+                @Override
+                public Void inTransaction(final TagDefinitionSqlDao transactional, final TransactionStatus status) throws Exception {
+                    // Make sure the tag definition exists
+                    final TagDefinition existingDefinition = tagDefinitionSqlDao.getByName(definitionName);
+                    if (existingDefinition == null) {
+                        throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_DOES_NOT_EXIST, definitionName);
+                    }
+
+                    // Make sure it is not used currently
+                    if (tagDefinitionSqlDao.tagDefinitionUsageCount(definitionName) > 0) {
+                        throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_IN_USE, definitionName);
+                    }
+
+                    tagDefinitionSqlDao.deleteTagDefinition(definitionName, context);
+
+                    return null;
+                }
+            });
+        } catch (TransactionFailedException exception) {
+            if (exception.getCause() instanceof TagDefinitionApiException) {
+                throw (TagDefinitionApiException) exception.getCause();
+            } else {
+                throw exception;
+            }
         }
-
-        dao.deleteTagDefinition(definitionName, context);
     }
 }
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionDao.java
index cc10c93..ae645ea 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionDao.java
@@ -29,7 +29,5 @@ public interface TagDefinitionDao {
 
     public TagDefinition create(String definitionName, String description, CallContext context) throws TagDefinitionApiException;
 
-    public void deleteAllTagsForDefinition(String definitionName, CallContext context) throws TagDefinitionApiException;
-
     public void deleteTagDefinition(String definitionName, CallContext context) throws TagDefinitionApiException;
 }
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
index 8524c53..4a7dd1c 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
@@ -34,6 +34,7 @@ import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
 import org.skife.jdbi.v2.sqlobject.SqlQuery;
 import org.skife.jdbi.v2.sqlobject.SqlUpdate;
 import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
 import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
 import org.skife.jdbi.v2.tweak.ResultSetMapper;
 
@@ -45,7 +46,7 @@ import com.ning.billing.util.tag.TagDefinition;
 
 @ExternalizedSqlViaStringTemplate3
 @RegisterMapper(TagDefinitionSqlDao.TagDefinitionMapper.class)
-public interface TagDefinitionSqlDao extends EntitySqlDao<TagDefinition> {
+public interface TagDefinitionSqlDao extends EntitySqlDao<TagDefinition>, Transactional<TagDefinitionSqlDao> {
     @Override
     @SqlUpdate
     public void create(@TagDefinitionBinder final TagDefinition entity, @CallContextBinder final CallContext context);
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDefinitionDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDefinitionDao.java
index 2d36936..d7a3e63 100644
--- a/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDefinitionDao.java
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/MockTagDefinitionDao.java
@@ -49,11 +49,6 @@ public class MockTagDefinitionDao implements TagDefinitionDao {
     }
 
     @Override
-    public void deleteAllTagsForDefinition(final String definitionName, final CallContext context) throws TagDefinitionApiException {
-        tags.remove(definitionName);
-    }
-
-    @Override
     public void deleteTagDefinition(final String definitionName, final CallContext context) throws TagDefinitionApiException {
         tags.remove(definitionName);
     }
diff --git a/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java b/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
index bea5065..8dcd638 100644
--- a/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
+++ b/util/src/test/java/com/ning/billing/util/tag/TestTagStore.java
@@ -285,7 +285,7 @@ public class TestTagStore {
     }
 
     @Test(groups = "slow")
-    public void testDeleteAllTagsForDefinitionInUse() {
+    public void testDeleteTagBeforeDeleteTagDefinition() {
         final String definitionName = "TestTag1234567";
         try {
             tagDefinitionDao.create(definitionName, "Some test tag", context);
@@ -306,58 +306,9 @@ public class TestTagStore {
         final Map<String, Tag> tagMap = tagDao.loadEntities(objectId, ObjectType.ACCOUNT);
         assertEquals(tagMap.size(), 1);
 
-        try {
-            tagDefinitionDao.deleteAllTagsForDefinition(definitionName, context);
-        } catch (TagDefinitionApiException e) {
-            fail("Could not delete tagStore for tag definition", e);
-        }
-
-        try {
-            tagDefinitionDao.deleteTagDefinition(definitionName, context);
-        } catch (TagDefinitionApiException e) {
-            fail("Could not delete tag definition", e);
-        }
-    }
-
-    @Test(groups = "slow")
-    public void testDeleteAllTagsForDefinitionNotInUse() {
-        final String definitionName = "TestTag4321";
-        try {
-            tagDefinitionDao.create(definitionName, "Some test tag", context);
-        } catch (TagDefinitionApiException e) {
-            fail("Could not create tag definition", e);
-        }
-
-        final TagDefinition tagDefinition = tagDefinitionDao.getByName(definitionName);
-        assertNotNull(tagDefinition);
-
-        try {
-            tagDefinitionDao.deleteAllTagsForDefinition(definitionName, context);
-        } catch (TagDefinitionApiException e) {
-            fail("Could not delete tagStore for tag definition", e);
-        }
-
-        try {
-            tagDefinitionDao.deleteTagDefinition(definitionName, context);
-        } catch (TagDefinitionApiException e) {
-            fail("Could not delete tag definition", e);
-        }
-    }
-
-    @Test(groups = "slow", expectedExceptions = TagDefinitionApiException.class)
-    public void testDeleteAllTagsForDefinitionWithWrongName() throws TagDefinitionApiException {
-        final String definitionName = "TestTag654321";
-        final String wrongDefinitionName = "TestTag564321";
-        try {
-            tagDefinitionDao.create(definitionName, "Some test tag", context);
-        } catch (TagDefinitionApiException e) {
-            fail("Could not create tag definition", e);
-        }
-
-        final TagDefinition tagDefinition = tagDefinitionDao.getByName(definitionName);
-        assertNotNull(tagDefinition);
-
-        tagDefinitionDao.deleteAllTagsForDefinition(wrongDefinitionName, context);
+        tagDao.deleteTag(objectId, ObjectType.ACCOUNT, tagDefinition, context);
+        final Map<String, Tag> tagMapAfterDeletion = tagDao.loadEntities(objectId, ObjectType.ACCOUNT);
+        assertEquals(tagMapAfterDeletion.size(), 0);
 
         try {
             tagDefinitionDao.deleteTagDefinition(definitionName, context);