Details
diff --git a/api/src/main/java/com/ning/billing/util/api/AuditUserApi.java b/api/src/main/java/com/ning/billing/util/api/AuditUserApi.java
new file mode 100644
index 0000000..1770335
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/api/AuditUserApi.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.api;
+
+import java.util.List;
+import java.util.UUID;
+
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.dao.ObjectType;
+
+public interface AuditUserApi {
+
+ /**
+ * Get all the audit entries for a given object
+ *
+ * @param objectId the object id
+ * @param objectType the type of object
+ * @return all audit entries for that object
+ */
+ public List<AuditLog> getAuditLogs(final UUID objectId, final ObjectType objectType);
+}
diff --git a/api/src/main/java/com/ning/billing/util/audit/AuditLog.java b/api/src/main/java/com/ning/billing/util/audit/AuditLog.java
new file mode 100644
index 0000000..be89e7f
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/util/audit/AuditLog.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.util.ChangeType;
+
+public interface AuditLog {
+
+ /**
+ * Get the type of change for this log entry
+ *
+ * @return the ChangeType
+ */
+ public ChangeType getChangeType();
+
+ /**
+ * Get the name of the requestor
+ *
+ * @return the requestor user name
+ */
+ public String getUserName();
+
+ /**
+ * Get the time when this change was effective
+ *
+ * @return the created date of this log entry
+ */
+ public DateTime getCreatedDate();
+
+ /**
+ * Get the reason code for this change
+ *
+ * @return the reason code
+ */
+ public String getReasonCode();
+
+ /**
+ * Get the user token of this change requestor
+ *
+ * @return the user token
+ */
+ public String getUserToken();
+
+ /**
+ * Get the comment for this change
+ *
+ * @return the comment
+ */
+ public String getComment();
+}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AuditLogJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AuditLogJson.java
new file mode 100644
index 0000000..333a7d4
--- /dev/null
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AuditLogJson.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.jaxrs.json;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.util.audit.AuditLog;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class AuditLogJson {
+
+ private final String changeType;
+ private final DateTime changeDate;
+ private final String changedBy;
+ private final String reasonCode;
+ private final String comments;
+ private final String userToken;
+
+ @JsonCreator
+ public AuditLogJson(@JsonProperty("changeType") final String changeType,
+ @JsonProperty("changeDate") final DateTime changeDate,
+ @JsonProperty("changedBy") final String changedBy,
+ @JsonProperty("reasonCode") final String reasonCode,
+ @JsonProperty("comments") final String comments,
+ @JsonProperty("userToken") final String userToken) {
+ this.changeType = changeType;
+ this.changeDate = changeDate;
+ this.changedBy = changedBy;
+ this.reasonCode = reasonCode;
+ this.comments = comments;
+ this.userToken = userToken;
+ }
+
+ public AuditLogJson(final AuditLog auditLog) {
+ this(auditLog.getChangeType().toString(), auditLog.getCreatedDate(), auditLog.getUserName(), auditLog.getReasonCode(),
+ auditLog.getComment(), auditLog.getUserToken());
+ }
+
+ public String getChangeType() {
+ return changeType;
+ }
+
+ public DateTime getChangeDate() {
+ return changeDate;
+ }
+
+ public String getChangedBy() {
+ return changedBy;
+ }
+
+ public String getReasonCode() {
+ return reasonCode;
+ }
+
+ public String getComments() {
+ return comments;
+ }
+
+ public String getUserToken() {
+ return userToken;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("AuditLogJson");
+ sb.append("{changeType='").append(changeType).append('\'');
+ sb.append(", changeDate=").append(changeDate);
+ sb.append(", changedBy=").append(changedBy);
+ sb.append(", reasonCode='").append(reasonCode).append('\'');
+ sb.append(", comments='").append(comments).append('\'');
+ sb.append(", userToken='").append(userToken).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final AuditLogJson that = (AuditLogJson) o;
+
+ if (changeDate != null ? changeDate.compareTo(that.changeDate) != 0 : that.changeDate != null) {
+ return false;
+ }
+ if (changeType != null ? !changeType.equals(that.changeType) : that.changeType != null) {
+ return false;
+ }
+ if (changedBy != null ? !changedBy.equals(that.changedBy) : that.changedBy != null) {
+ return false;
+ }
+ if (comments != null ? !comments.equals(that.comments) : that.comments != null) {
+ return false;
+ }
+ if (reasonCode != null ? !reasonCode.equals(that.reasonCode) : that.reasonCode != null) {
+ return false;
+ }
+ if (userToken != null ? !userToken.equals(that.userToken) : that.userToken != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = changeType != null ? changeType.hashCode() : 0;
+ result = 31 * result + (changeDate != null ? changeDate.hashCode() : 0);
+ result = 31 * result + (changedBy != null ? changedBy.hashCode() : 0);
+ result = 31 * result + (reasonCode != null ? reasonCode.hashCode() : 0);
+ result = 31 * result + (comments != null ? comments.hashCode() : 0);
+ result = 31 * result + (userToken != null ? userToken.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java
new file mode 100644
index 0000000..3c7e31c
--- /dev/null
+++ b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.jaxrs.json;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.jaxrs.JaxrsTestSuite;
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.DefaultAuditLog;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContext;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.clock.DefaultClock;
+import com.ning.billing.util.dao.EntityAudit;
+import com.ning.billing.util.dao.TableName;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.joda.JodaModule;
+
+public class TestAuditLogJson extends JaxrsTestSuite {
+
+ private static final ObjectMapper mapper = new ObjectMapper();
+
+ private final Clock clock = new DefaultClock();
+
+ static {
+ mapper.registerModule(new JodaModule());
+ mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ }
+
+ @Test(groups = "fast")
+ public void testJson() throws Exception {
+ final String changeType = UUID.randomUUID().toString();
+ final DateTime changeDate = clock.getUTCNow();
+ final String changedBy = UUID.randomUUID().toString();
+ final String reasonCode = UUID.randomUUID().toString();
+ final String comments = UUID.randomUUID().toString();
+ final String userToken = UUID.randomUUID().toString();
+
+ final AuditLogJson auditLogJson = new AuditLogJson(changeType, changeDate, changedBy, reasonCode, comments, userToken);
+ Assert.assertEquals(auditLogJson.getChangeType(), changeType);
+ Assert.assertEquals(auditLogJson.getChangeDate(), changeDate);
+ Assert.assertEquals(auditLogJson.getChangedBy(), changedBy);
+ Assert.assertEquals(auditLogJson.getReasonCode(), reasonCode);
+ Assert.assertEquals(auditLogJson.getComments(), comments);
+ Assert.assertEquals(auditLogJson.getUserToken(), userToken);
+
+ final String asJson = mapper.writeValueAsString(auditLogJson);
+ Assert.assertEquals(asJson, "{\"changeType\":\"" + auditLogJson.getChangeType() + "\"," +
+ "\"changeDate\":\"" + auditLogJson.getChangeDate().toDateTimeISO().toString() + "\"," +
+ "\"changedBy\":\"" + auditLogJson.getChangedBy() + "\"," +
+ "\"reasonCode\":\"" + auditLogJson.getReasonCode() + "\"," +
+ "\"comments\":\"" + auditLogJson.getComments() + "\"," +
+ "\"userToken\":\"" + auditLogJson.getUserToken() + "\"}");
+
+ final AuditLogJson fromJson = mapper.readValue(asJson, AuditLogJson.class);
+ Assert.assertEquals(fromJson, auditLogJson);
+ }
+
+ @Test(groups = "fast")
+ public void testConstructor() throws Exception {
+ final TableName tableName = TableName.ACCOUNT_EMAIL_HISTORY;
+ final long recordId = Long.MAX_VALUE;
+ final ChangeType changeType = ChangeType.DELETE;
+ final EntityAudit entityAudit = new EntityAudit(tableName, recordId, changeType);
+
+ final String userName = UUID.randomUUID().toString();
+ final CallOrigin callOrigin = CallOrigin.EXTERNAL;
+ final UserType userType = UserType.CUSTOMER;
+ final UUID userToken = UUID.randomUUID();
+ final ClockMock clock = new ClockMock();
+ final CallContext callContext = new DefaultCallContext(userName, callOrigin, userType, userToken, clock);
+
+ final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+
+ final AuditLogJson auditLogJson = new AuditLogJson(auditLog);
+ Assert.assertEquals(auditLogJson.getChangeType(), changeType.toString());
+ Assert.assertNotNull(auditLogJson.getChangeDate());
+ Assert.assertEquals(auditLogJson.getChangedBy(), userName);
+ Assert.assertNull(auditLogJson.getReasonCode());
+ Assert.assertNull(auditLogJson.getComments());
+ Assert.assertEquals(auditLogJson.getUserToken(), userToken.toString());
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java b/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java
new file mode 100644
index 0000000..6af61ea
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit.api;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.dao.AuditDao;
+import com.ning.billing.util.dao.ObjectType;
+import com.ning.billing.util.dao.TableName;
+
+import com.google.common.collect.ImmutableList;
+
+public class DefaultAuditUserApi implements AuditUserApi {
+
+ private final AuditDao auditDao;
+
+ @Inject
+ public DefaultAuditUserApi(final AuditDao auditDao) {
+ this.auditDao = auditDao;
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogs(final UUID objectId, final ObjectType objectType) {
+ final TableName tableName = getTableNameFromObjectType(objectType);
+ if (tableName == null) {
+ return ImmutableList.<AuditLog>of();
+ }
+
+ return auditDao.getAuditLogsForRecordId(tableName, objectId);
+ }
+
+ private TableName getTableNameFromObjectType(final ObjectType objectType) {
+ for (final TableName tableName : TableName.values()) {
+ if (objectType.equals(tableName.getObjectType())) {
+ return tableName;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java b/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java
new file mode 100644
index 0000000..224b78b
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit.dao;
+
+import java.util.List;
+import java.util.UUID;
+
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.dao.TableName;
+
+public interface AuditDao {
+
+ public List<AuditLog> getAuditLogsForRecordId(final TableName tableName, final UUID objectId);
+}
diff --git a/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java b/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java
new file mode 100644
index 0000000..7f38dee
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit.dao;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.inject.Inject;
+
+import org.skife.jdbi.v2.IDBI;
+
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.dao.AuditSqlDao;
+import com.ning.billing.util.dao.TableName;
+
+import com.google.common.collect.ImmutableList;
+
+public class DefaultAuditDao implements AuditDao {
+
+ private final AuditSqlDao auditSqlDao;
+
+ @Inject
+ public DefaultAuditDao(final IDBI dbi) {
+ this.auditSqlDao = dbi.onDemand(AuditSqlDao.class);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForRecordId(final TableName tableName, final UUID objectId) {
+ final Long recordId = auditSqlDao.getRecordIdForTable(tableName, objectId.toString());
+ if (recordId == null) {
+ return ImmutableList.<AuditLog>of();
+ } else {
+ return auditSqlDao.getAuditLogsForRecordId(tableName, recordId);
+ }
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java b/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java
new file mode 100644
index 0000000..513697e
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.dao.EntityAudit;
+
+public class DefaultAuditLog implements AuditLog {
+
+ private final EntityAudit entityAudit;
+ private final CallContext callContext;
+
+ public DefaultAuditLog(final EntityAudit entityAudit, final CallContext callContext) {
+ this.entityAudit = entityAudit;
+ this.callContext = callContext;
+ }
+
+ @Override
+ public ChangeType getChangeType() {
+ return entityAudit.getChangeType();
+ }
+
+ @Override
+ public String getUserName() {
+ return callContext.getUserName();
+ }
+
+ @Override
+ public DateTime getCreatedDate() {
+ return callContext.getCreatedDate();
+ }
+
+ @Override
+ public String getReasonCode() {
+ return callContext.getReasonCode();
+ }
+
+ @Override
+ public String getUserToken() {
+ if (callContext.getUserToken() == null) {
+ return null;
+ } else {
+ return callContext.getUserToken().toString();
+ }
+ }
+
+ @Override
+ public String getComment() {
+ return callContext.getComment();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultAuditLog");
+ sb.append("{entityAudit=").append(entityAudit);
+ sb.append(", callContext=").append(callContext);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultAuditLog that = (DefaultAuditLog) o;
+
+ if (callContext != null ? !callContext.equals(that.callContext) : that.callContext != null) {
+ return false;
+ }
+ if (entityAudit != null ? !entityAudit.equals(that.entityAudit) : that.entityAudit != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = entityAudit != null ? entityAudit.hashCode() : 0;
+ result = 31 * result + (callContext != null ? callContext.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/callcontext/CallContextBase.java b/util/src/main/java/com/ning/billing/util/callcontext/CallContextBase.java
index 40d7ef5..2c21d05 100644
--- a/util/src/main/java/com/ning/billing/util/callcontext/CallContextBase.java
+++ b/util/src/main/java/com/ning/billing/util/callcontext/CallContextBase.java
@@ -19,12 +19,13 @@ package com.ning.billing.util.callcontext;
import java.util.UUID;
public abstract class CallContextBase implements CallContext {
- private final UUID userToken;
- private final String userName;
- private final CallOrigin callOrigin;
- private final UserType userType;
- private final String reasonCode;
- private final String comment;
+
+ protected final UUID userToken;
+ protected final String userName;
+ protected final CallOrigin callOrigin;
+ protected final UserType userType;
+ protected final String reasonCode;
+ protected final String comment;
public CallContextBase(final String userName, final CallOrigin callOrigin, final UserType userType) {
this(userName, callOrigin, userType, null);
diff --git a/util/src/main/java/com/ning/billing/util/callcontext/DefaultCallContext.java b/util/src/main/java/com/ning/billing/util/callcontext/DefaultCallContext.java
index 081cd7e..e294d30 100644
--- a/util/src/main/java/com/ning/billing/util/callcontext/DefaultCallContext.java
+++ b/util/src/main/java/com/ning/billing/util/callcontext/DefaultCallContext.java
@@ -23,31 +23,102 @@ import org.joda.time.DateTime;
import com.ning.billing.util.clock.Clock;
public class DefaultCallContext extends CallContextBase {
- private final Clock clock;
+
+ private final DateTime createdDate;
public DefaultCallContext(final String userName, final CallOrigin callOrigin, final UserType userType, final UUID userToken, final Clock clock) {
super(userName, callOrigin, userType, userToken);
- this.clock = clock;
+ this.createdDate = clock.getUTCNow();
}
public DefaultCallContext(final String userName, final CallOrigin callOrigin, final UserType userType,
final String reasonCode, final String comment,
final UUID userToken, final Clock clock) {
super(userName, callOrigin, userType, reasonCode, comment, userToken);
- this.clock = clock;
+ this.createdDate = clock.getUTCNow();
}
public DefaultCallContext(final String userName, final CallOrigin callOrigin, final UserType userType, final Clock clock) {
this(userName, callOrigin, userType, null, clock);
}
+ public DefaultCallContext(final String userName, final DateTime createdDate, final String reasonCode,
+ final String comment, final UUID userToken) {
+ super(userName, null, null, reasonCode, comment, userToken);
+ this.createdDate = createdDate;
+ }
+
@Override
public DateTime getCreatedDate() {
- return clock.getUTCNow();
+ return createdDate;
}
@Override
public DateTime getUpdatedDate() {
- return clock.getUTCNow();
+ return createdDate;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("CallContextBase");
+ sb.append("{userToken=").append(userToken);
+ sb.append(", userName='").append(userName).append('\'');
+ sb.append(", callOrigin=").append(callOrigin);
+ sb.append(", userType=").append(userType);
+ sb.append(", reasonCode='").append(reasonCode).append('\'');
+ sb.append(", comment='").append(comment).append('\'');
+ sb.append(", createdDate='").append(createdDate).append('\'');
+ sb.append(", updatedDate='").append(createdDate).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultCallContext that = (DefaultCallContext) o;
+
+ if (callOrigin != that.callOrigin) {
+ return false;
+ }
+ if (comment != null ? !comment.equals(that.comment) : that.comment != null) {
+ return false;
+ }
+ if (reasonCode != null ? !reasonCode.equals(that.reasonCode) : that.reasonCode != null) {
+ return false;
+ }
+ if (userName != null ? !userName.equals(that.userName) : that.userName != null) {
+ return false;
+ }
+ if (userToken != null ? !userToken.equals(that.userToken) : that.userToken != null) {
+ return false;
+ }
+ if (createdDate != null ? createdDate.compareTo(that.createdDate) != 0 : that.createdDate != null) {
+ return false;
+ }
+ if (userType != that.userType) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = userToken != null ? userToken.hashCode() : 0;
+ result = 31 * result + (userName != null ? userName.hashCode() : 0);
+ result = 31 * result + (callOrigin != null ? callOrigin.hashCode() : 0);
+ result = 31 * result + (userType != null ? userType.hashCode() : 0);
+ result = 31 * result + (reasonCode != null ? reasonCode.hashCode() : 0);
+ result = 31 * result + (comment != null ? comment.hashCode() : 0);
+ result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
+ return result;
}
}
diff --git a/util/src/main/java/com/ning/billing/util/dao/AuditLogMapper.java b/util/src/main/java/com/ning/billing/util/dao/AuditLogMapper.java
new file mode 100644
index 0000000..89ca281
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/dao/AuditLogMapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.dao;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.DefaultAuditLog;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.DefaultCallContext;
+
+public class AuditLogMapper extends MapperBase implements ResultSetMapper<AuditLog> {
+
+ @Override
+ public AuditLog map(final int index, final ResultSet r, final StatementContext ctx) throws SQLException {
+ final String tableName = r.getString("table_name");
+ final long recordId = r.getLong("record_id");
+ final String changeType = r.getString("change_type");
+ final DateTime changeDate = getDateTime(r, "change_date");
+ final String changedBy = r.getString("changed_by");
+ final String reasonCode = r.getString("reason_code");
+ final String comments = r.getString("comments");
+ final String userToken = r.getString("user_token");
+
+ final EntityAudit entityAudit = new EntityAudit(TableName.valueOf(tableName), recordId, ChangeType.valueOf(changeType));
+ final CallContext callContext = new DefaultCallContext(changedBy, changeDate, reasonCode, comments, UUID.fromString(userToken));
+ return new DefaultAuditLog(entityAudit, callContext);
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java b/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
index 4f9c256..2e5d353 100644
--- a/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
@@ -22,13 +22,18 @@ import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlBatch;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.Define;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallContextBinder;
@ExternalizedSqlViaStringTemplate3
+@RegisterMapper(AuditLogMapper.class)
public interface AuditSqlDao {
+
@SqlUpdate
public void insertAuditFromTransaction(@AuditBinder final EntityAudit audit,
@CallContextBinder final CallContext context);
@@ -38,9 +43,17 @@ public interface AuditSqlDao {
@CallContextBinder final CallContext context);
@SqlQuery
+ public List<AuditLog> getAuditLogsForRecordId(@TableNameBinder final TableName tableName,
+ @Bind("recordId") final long recordId);
+
+ @SqlQuery
public Long getRecordId(@Bind("id") final String id);
@SqlQuery
+ public Long getRecordIdForTable(@Define("tableName") final TableName tableName,
+ @Bind("id") final String id);
+
+ @SqlQuery
public Long getHistoryRecordId(@Bind("recordId") final Long recordId);
}
diff --git a/util/src/main/java/com/ning/billing/util/dao/TableName.java b/util/src/main/java/com/ning/billing/util/dao/TableName.java
index a5038d5..4dedcd0 100644
--- a/util/src/main/java/com/ning/billing/util/dao/TableName.java
+++ b/util/src/main/java/com/ning/billing/util/dao/TableName.java
@@ -16,31 +16,40 @@
package com.ning.billing.util.dao;
+import javax.annotation.Nullable;
+
public enum TableName {
- ACCOUNT("accounts"),
- ACCOUNT_HISTORY("account_history"),
- ACCOUNT_EMAIL_HISTORY("account_email_history"),
- BUNDLES("bundles"),
- CUSTOM_FIELD_HISTORY("custom_field_history"),
- INVOICE_ITEMS("invoice_items"),
- INVOICE_PAYMENTS("invoice_payments"),
- INVOICES("invoices"),
- PAYMENT_ATTEMPTS("payment_attempts"),
- PAYMENT_HISTORY("payment_history"),
- PAYMENTS("payments"),
- PAYMENT_METHODS("payment_methods"),
- SUBSCRIPTIONS("subscriptions"),
- SUBSCRIPTION_EVENTS("subscription_events"),
- REFUNDS("refunds"),
- TAG_HISTORY("tag_history");
+ ACCOUNT("accounts", ObjectType.ACCOUNT),
+ ACCOUNT_HISTORY("account_history", null),
+ ACCOUNT_EMAIL_HISTORY("account_email_history", ObjectType.ACCOUNT_EMAIL),
+ BUNDLES("bundles", ObjectType.BUNDLE),
+ CUSTOM_FIELD_HISTORY("custom_field_history", null),
+ INVOICE_ITEMS("invoice_items", ObjectType.INVOICE_ITEM),
+ INVOICE_PAYMENTS("invoice_payments", ObjectType.INVOICE_PAYMENT),
+ INVOICES("invoices", ObjectType.INVOICE),
+ PAYMENT_ATTEMPTS("payment_attempts", null),
+ PAYMENT_HISTORY("payment_history", null),
+ PAYMENTS("payments", ObjectType.PAYMENT),
+ PAYMENT_METHODS("payment_methods", ObjectType.PAYMENT_METHOD),
+ SUBSCRIPTIONS("subscriptions", ObjectType.SUBSCRIPTION),
+ SUBSCRIPTION_EVENTS("subscription_events", null),
+ REFUNDS("refunds", ObjectType.REFUND),
+ TAG_DEFINITIONS("tag_definitions", ObjectType.TAG_DEFINITION),
+ TAG_HISTORY("tag_history", null);
private final String tableName;
+ private final ObjectType objectType;
- TableName(final String tableName) {
+ TableName(final String tableName, @Nullable final ObjectType objectType) {
this.tableName = tableName;
+ this.objectType = objectType;
}
public String getTableName() {
return tableName;
}
+
+ public ObjectType getObjectType() {
+ return objectType;
+ }
}
diff --git a/util/src/main/java/com/ning/billing/util/dao/TableNameBinder.java b/util/src/main/java/com/ning/billing/util/dao/TableNameBinder.java
index 545186c..9cacf92 100644
--- a/util/src/main/java/com/ning/billing/util/dao/TableNameBinder.java
+++ b/util/src/main/java/com/ning/billing/util/dao/TableNameBinder.java
@@ -31,7 +31,9 @@ import org.skife.jdbi.v2.sqlobject.BindingAnnotation;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface TableNameBinder {
+
public static class TableNameBinderFactory implements BinderFactory {
+
public Binder build(final Annotation annotation) {
return new Binder<TableNameBinder, TableName>() {
public void bind(final SQLStatement q, final TableNameBinder bind, final TableName tableName) {
diff --git a/util/src/main/java/com/ning/billing/util/glue/AuditModule.java b/util/src/main/java/com/ning/billing/util/glue/AuditModule.java
new file mode 100644
index 0000000..0a1e8fb
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/glue/AuditModule.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.glue;
+
+import com.ning.billing.util.audit.dao.AuditDao;
+import com.ning.billing.util.audit.dao.DefaultAuditDao;
+
+import com.google.inject.AbstractModule;
+
+public class AuditModule extends AbstractModule {
+
+ protected void installDaos() {
+ bind(AuditDao.class).to(DefaultAuditDao.class).asEagerSingleton();
+ }
+
+ @Override
+ protected void configure() {
+ installDaos();
+ }
+}
diff --git a/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java b/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
new file mode 100644
index 0000000..8ce34d0
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit.dao;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.Handle;
+import org.skife.jdbi.v2.IDBI;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
+import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.dao.ObjectType;
+import com.ning.billing.util.dao.TableName;
+import com.ning.billing.util.glue.AuditModule;
+import com.ning.billing.util.tag.MockTagStoreModuleSql;
+import com.ning.billing.util.tag.TagDefinition;
+import com.ning.billing.util.tag.dao.AuditedTagDao;
+import com.ning.billing.util.tag.dao.TagDefinitionDao;
+
+import com.google.inject.Inject;
+
+@Guice(modules = {MockTagStoreModuleSql.class, AuditModule.class})
+public class TestDefaultAuditDao extends UtilTestSuiteWithEmbeddedDB {
+
+ @Inject
+ private TagDefinitionDao tagDefinitionDao;
+
+ @Inject
+ private AuditedTagDao tagDao;
+
+ @Inject
+ private AuditDao auditDao;
+
+ @Inject
+ private Clock clock;
+
+ @Inject
+ private Bus bus;
+
+ @Inject
+ private IDBI dbi;
+
+ private CallContext context;
+
+ @BeforeClass(groups = "slow")
+ public void setup() throws IOException {
+ context = new DefaultCallContextFactory(clock).createCallContext("Audit DAO test", CallOrigin.TEST, UserType.TEST, UUID.randomUUID());
+ bus.start();
+ }
+
+ @AfterClass(groups = "slow")
+ public void tearDown() {
+ bus.stop();
+ }
+
+ @Test(groups = "slow")
+ public void testRetrieveAudits() throws Exception {
+ final TagDefinition defYo = tagDefinitionDao.create("yo", "defintion yo", context);
+
+ // Create a tag
+ tagDao.insertTag(UUID.randomUUID(), ObjectType.ACCOUNT, defYo.getId(), context);
+
+ // Verify we get an audit entry for the tag_history table
+ final Handle handle = dbi.open();
+ final String tagHistoryString = (String) handle.select("select id from tag_history limit 1").get(0).get("id");
+ handle.close();
+
+ final List<AuditLog> auditLogs = auditDao.getAuditLogsForRecordId(TableName.TAG_HISTORY, UUID.fromString(tagHistoryString));
+ Assert.assertEquals(auditLogs.size(), 1);
+ Assert.assertEquals(auditLogs.get(0).getUserToken(), context.getUserToken().toString());
+ Assert.assertEquals(auditLogs.get(0).getChangeType(), ChangeType.INSERT);
+ Assert.assertNull(auditLogs.get(0).getComment());
+ Assert.assertNull(auditLogs.get(0).getReasonCode());
+ Assert.assertEquals(auditLogs.get(0).getUserName(), context.getUserName());
+ Assert.assertNotNull(auditLogs.get(0).getCreatedDate());
+ }
+}
diff --git a/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java b/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java
new file mode 100644
index 0000000..709708f
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit;
+
+import java.util.UUID;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.util.ChangeType;
+import com.ning.billing.util.UtilTestSuite;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContext;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.util.dao.EntityAudit;
+import com.ning.billing.util.dao.TableName;
+
+public class TestDefaultAuditLog extends UtilTestSuite {
+
+ @Test(groups = "fast")
+ public void testGetters() throws Exception {
+ final TableName tableName = TableName.ACCOUNT_EMAIL_HISTORY;
+ final long recordId = Long.MAX_VALUE;
+ final ChangeType changeType = ChangeType.DELETE;
+ final EntityAudit entityAudit = new EntityAudit(tableName, recordId, changeType);
+
+ final String userName = UUID.randomUUID().toString();
+ final CallOrigin callOrigin = CallOrigin.EXTERNAL;
+ final UserType userType = UserType.CUSTOMER;
+ final UUID userToken = UUID.randomUUID();
+ final ClockMock clock = new ClockMock();
+ final CallContext callContext = new DefaultCallContext(userName, callOrigin, userType, userToken, clock);
+
+ final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+ Assert.assertEquals(auditLog.getChangeType(), changeType);
+ Assert.assertNull(auditLog.getComment());
+ Assert.assertNotNull(auditLog.getCreatedDate());
+ Assert.assertNull(auditLog.getReasonCode());
+ Assert.assertEquals(auditLog.getUserName(), userName);
+ Assert.assertEquals(auditLog.getUserToken(), userToken.toString());
+ }
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final TableName tableName = TableName.ACCOUNT_EMAIL_HISTORY;
+ final long recordId = Long.MAX_VALUE;
+ final ChangeType changeType = ChangeType.DELETE;
+ final EntityAudit entityAudit = new EntityAudit(tableName, recordId, changeType);
+
+ final String userName = UUID.randomUUID().toString();
+ final CallOrigin callOrigin = CallOrigin.EXTERNAL;
+ final UserType userType = UserType.CUSTOMER;
+ final UUID userToken = UUID.randomUUID();
+ final ClockMock clock = new ClockMock();
+ final CallContext callContext = new DefaultCallContext(userName, callOrigin, userType, userToken, clock);
+
+ final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+ Assert.assertEquals(auditLog, auditLog);
+
+ final AuditLog sameAuditLog = new DefaultAuditLog(entityAudit, callContext);
+ Assert.assertEquals(sameAuditLog, auditLog);
+
+ clock.addMonths(1);
+ final CallContext otherCallContext = new DefaultCallContext(userName, callOrigin, userType, userToken, clock);
+ final AuditLog otherAuditLog = new DefaultAuditLog(entityAudit, otherCallContext);
+ Assert.assertNotEquals(otherAuditLog, auditLog);
+ }
+}
diff --git a/util/src/test/java/com/ning/billing/util/callcontext/TestDefaultCallContext.java b/util/src/test/java/com/ning/billing/util/callcontext/TestDefaultCallContext.java
new file mode 100644
index 0000000..c56b5f3
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/callcontext/TestDefaultCallContext.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.callcontext;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.util.UtilTestSuite;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+
+public class TestDefaultCallContext extends UtilTestSuite {
+
+ private final Clock clock = new ClockMock();
+
+ @Test(groups = "fast")
+ public void testGetters() throws Exception {
+ final String userName = UUID.randomUUID().toString();
+ final DateTime createdDate = clock.getUTCNow();
+ final String reasonCode = UUID.randomUUID().toString();
+ final String comment = UUID.randomUUID().toString();
+ final UUID userToken = UUID.randomUUID();
+ final DefaultCallContext callContext = new DefaultCallContext(userName, createdDate, reasonCode, comment, userToken);
+
+ Assert.assertEquals(callContext.getCreatedDate(), createdDate);
+ Assert.assertNull(callContext.getCallOrigin());
+ Assert.assertEquals(callContext.getComment(), comment);
+ Assert.assertEquals(callContext.getReasonCode(), reasonCode);
+ Assert.assertEquals(callContext.getUserName(), userName);
+ Assert.assertEquals(callContext.getUpdatedDate(), createdDate);
+ Assert.assertEquals(callContext.getUserToken(), userToken);
+ Assert.assertNull(callContext.getUserType());
+ }
+
+ @Test(groups = "fast")
+ public void testEquals() throws Exception {
+ final String userName = UUID.randomUUID().toString();
+ final DateTime createdDate = clock.getUTCNow();
+ final String reasonCode = UUID.randomUUID().toString();
+ final String comment = UUID.randomUUID().toString();
+ final UUID userToken = UUID.randomUUID();
+
+ final DefaultCallContext callContext = new DefaultCallContext(userName, createdDate, reasonCode, comment, userToken);
+ Assert.assertEquals(callContext, callContext);
+
+ final DefaultCallContext sameCallContext = new DefaultCallContext(userName, createdDate, reasonCode, comment, userToken);
+ Assert.assertEquals(sameCallContext, callContext);
+
+ final DefaultCallContext otherCallContext = new DefaultCallContext(UUID.randomUUID().toString(), createdDate, reasonCode, comment, userToken);
+ Assert.assertNotEquals(otherCallContext, callContext);
+ }
+}