From b0e425eca31a2698504a1a0c97c005e2a01e783a Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Thu, 20 Dec 2012 14:44:38 +0100
Subject: [PATCH] OO-449: move the HQL queries to NamedQueries annotations, add
 unit tests for all queries

---
 .../manager/InstantMessageDAO.java            |  28 +---
 .../manager/InstantMessagePreferencesDAO.java |  12 +-
 .../instantMessaging/manager/RosterDAO.java   |  28 +---
 .../model/ImPreferencesImpl.java              |  10 +-
 .../model/InstantMessageImpl.java             |   9 +-
 .../model/InstantMessageNotificationImpl.java |   9 +-
 .../model/RosterEntryImpl.java                |  10 +-
 .../InstantMessageDAOTest.java                |  25 ++-
 .../InstantMessagePreferencesDAOTest.java     | 147 ++++++++++++++++-
 .../InstantMessageServiceTest.java            |   4 +
 .../olat/instantMessaging/RosterDAOTest.java  | 154 ++++++++++++++++++
 .../java/org/olat/test/AllTestsJunit4.java    |   1 +
 12 files changed, 372 insertions(+), 65 deletions(-)
 create mode 100644 src/test/java/org/olat/instantMessaging/RosterDAOTest.java

diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessageDAO.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessageDAO.java
index 50aff006155..04445419d90 100644
--- a/src/main/java/org/olat/instantMessaging/manager/InstantMessageDAO.java
+++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessageDAO.java
@@ -59,12 +59,8 @@ public class InstantMessageDAO {
 	}
 
 	public InstantMessageImpl loadMessageById(Long key) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("select msg from ").append(InstantMessageImpl.class.getName()).append(" msg ")
-		  .append(" where msg.key=:key");
-		
 		List<InstantMessageImpl> msgs = dbInstance.getCurrentEntityManager()
-				.createQuery(sb.toString(), InstantMessageImpl.class)
+				.createNamedQuery("loadIMessageByKey", InstantMessageImpl.class)
 				.setParameter("key", key)
 				.getResultList();
 		
@@ -75,12 +71,8 @@ public class InstantMessageDAO {
 	}
 
 	public List<InstantMessage> getMessages(OLATResourceable ores, int firstResult, int maxResults) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("select msg from ").append(InstantMessageImpl.class.getName()).append(" msg ")
-		  .append(" where msg.resourceId=:resid and msg.resourceTypeName=:resname")
-		  .append(" order by msg.creationDate desc");
-		
-		TypedQuery<InstantMessage> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), InstantMessage.class)
+		TypedQuery<InstantMessage> query = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("loadIMessageByResource", InstantMessage.class)
 				.setParameter("resid", ores.getResourceableId())
 				.setParameter("resname", ores.getResourceableTypeName())
 				.setFirstResult(firstResult);
@@ -108,12 +100,7 @@ public class InstantMessageDAO {
 	}
 	
 	public void deleteNotification(Identity identity, OLATResourceable ores) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("delete from ").append(InstantMessageNotificationImpl.class.getName()).append(" notification ")
-		  .append(" where notification.toIdentityKey=:identityKey")
-		  .append(" and notification.resourceId=:resid and notification.resourceTypeName=:resname");
-		
-		dbInstance.getCurrentEntityManager().createQuery(sb.toString())
+		dbInstance.getCurrentEntityManager().createNamedQuery("deleteIMNotificationByResourceAndIdentity")
 				.setParameter("identityKey", identity.getKey())
 				.setParameter("resid", ores.getResourceableId())
 				.setParameter("resname", ores.getResourceableTypeName())
@@ -121,13 +108,8 @@ public class InstantMessageDAO {
 	}
 	
 	public List<InstantMessageNotification> getNotifications(Identity identity) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("select notification from ").append(InstantMessageNotificationImpl.class.getName()).append(" notification ")
-		  .append(" where notification.toIdentityKey=:identityKey")
-		  .append(" order by notification.creationDate desc");
-		
 		return dbInstance.getCurrentEntityManager()
-				.createQuery(sb.toString(), InstantMessageNotification.class)
+				.createNamedQuery("loadIMNotificationByIdentity", InstantMessageNotification.class)
 				.setParameter("identityKey", identity.getKey())
 				.setHint("org.hibernate.cacheable", Boolean.TRUE)
 				.getResultList();
diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
index 4f21c0b321a..39a767034d2 100644
--- a/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
+++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessagePreferencesDAO.java
@@ -22,8 +22,6 @@ package org.olat.instantMessaging.manager;
 import java.util.Date;
 import java.util.List;
 
-import javax.persistence.LockModeType;
-
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.instantMessaging.model.ImPreferencesImpl;
@@ -58,7 +56,8 @@ public class InstantMessagePreferencesDAO {
 		sb.append("select msg.rosterDefaultStatus from ").append(ImPreferencesImpl.class.getName()).append(" msg ")
 		  .append(" where msg.identity.key=:identityKey");
 		
-		List<String> msgs = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), String.class)
+		List<String> msgs = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("loadIMRosterStatusByIdentity", String.class)
 				.setParameter("identityKey", identityKey)
 				.getResultList();
 		
@@ -78,7 +77,8 @@ public class InstantMessagePreferencesDAO {
 		sb.append("select msg from ").append(ImPreferencesImpl.class.getName()).append(" msg ")
 		  .append(" where msg.identity.key=:identityKey");
 		
-		List<ImPreferencesImpl> msgs = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), ImPreferencesImpl.class)
+		List<ImPreferencesImpl> msgs = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("loadIMPreferencesByIdentity", ImPreferencesImpl.class)
 				.setParameter("identityKey", identity.getKey())
 				.getResultList();
 		
@@ -115,9 +115,9 @@ public class InstantMessagePreferencesDAO {
 		sb.append("select msg from ").append(ImPreferencesImpl.class.getName()).append(" msg ")
 		  .append(" where msg.identity.key=:identityKey");
 		
-		List<ImPreferencesImpl> msgs = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), ImPreferencesImpl.class)
+		List<ImPreferencesImpl> msgs = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("loadIMPreferencesForUpdate", ImPreferencesImpl.class)
 				.setParameter("identityKey", from.getKey())
-				.setLockMode(LockModeType.PESSIMISTIC_WRITE)
 				.getResultList();
 		
 		if(msgs.isEmpty()) {
diff --git a/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java b/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
index e87929085ba..7b0f091c222 100644
--- a/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
+++ b/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java
@@ -69,12 +69,8 @@ public class RosterDAO {
 	}
 	
 	private RosterEntryImpl loadForUpdate(OLATResourceable ores, Identity identity) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("select entry from ").append(RosterEntryImpl.class.getName()).append(" entry ")
-	  .append(" where entry.identityKey=:identityKey")
-	  .append(" and entry.resourceId=:resid and entry.resourceTypeName=:resname");
-		
-		TypedQuery<RosterEntryImpl> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), RosterEntryImpl.class)
+		TypedQuery<RosterEntryImpl> query = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("loadIMRosterEntryByIdentityandResource", RosterEntryImpl.class)
 				.setParameter("resid", ores.getResourceableId())
 				.setParameter("resname", ores.getResourceableTypeName())
 				.setParameter("identityKey", identity.getKey())
@@ -87,11 +83,8 @@ public class RosterDAO {
 	}
 	
 	public List<RosterEntryImpl> getRoster(OLATResourceable ores, int firstResult, int maxResults) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("select entry from ").append(RosterEntryImpl.class.getName()).append(" entry ")
-		  .append(" where entry.resourceId=:resid and entry.resourceTypeName=:resname");
-		
-		TypedQuery<RosterEntryImpl> query = dbInstance.getCurrentEntityManager().createQuery(sb.toString(), RosterEntryImpl.class)
+		TypedQuery<RosterEntryImpl> query = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("loadIMRosterEntryByResource", RosterEntryImpl.class)
 				.setParameter("resid", ores.getResourceableId())
 				.setParameter("resname", ores.getResourceableTypeName())
 				.setFirstResult(firstResult)
@@ -102,19 +95,12 @@ public class RosterDAO {
 		return query.getResultList();
 	}
 	
-	protected void clear() {
-		StringBuilder sb = new StringBuilder();
-		sb.append("delete from ").append(RosterEntryImpl.class.getName()).append(" entry ");
-		dbInstance.getCurrentEntityManager().createQuery(sb.toString()).executeUpdate();
+	public void clear() {
+		dbInstance.getCurrentEntityManager().createNamedQuery("clearIMRosterEntry").executeUpdate();
 	}
 	
 	public void deleteEntry(Identity identity, OLATResourceable ores) {
-		StringBuilder sb = new StringBuilder();
-		sb.append("delete from ").append(RosterEntryImpl.class.getName()).append(" entry ")
-		  .append(" where entry.identityKey=:identityKey")
-		  .append(" and entry.resourceId=:resid and entry.resourceTypeName=:resname");
-		
-		dbInstance.getCurrentEntityManager().createQuery(sb.toString())
+		dbInstance.getCurrentEntityManager().createNamedQuery("deleteIMRosterEntryByIdentityAndResource")
 				.setParameter("identityKey", identity.getKey())
 				.setParameter("resid", ores.getResourceableId())
 				.setParameter("resname", ores.getResourceableTypeName())
diff --git a/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java b/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java
index 64272872d65..165dd475d4f 100644
--- a/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java
+++ b/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java
@@ -33,6 +33,9 @@ import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
+import javax.persistence.LockModeType;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.persistence.Temporal;
@@ -51,8 +54,13 @@ import org.olat.instantMessaging.ImPreferences;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-@Entity
+@Entity(name="impreferences")
 @Table(name="o_im_preferences")
+@NamedQueries({
+	@NamedQuery(name="loadIMRosterStatusByIdentity", query="select msg.rosterDefaultStatus from impreferences msg where msg.identity.key=:identityKey"),
+	@NamedQuery(name="loadIMPreferencesByIdentity", query="select msg from impreferences msg where msg.identity.key=:identityKey"),
+	@NamedQuery(name="loadIMPreferencesForUpdate", query="select msg from impreferences msg where msg.identity.key=:identityKey", lockMode=LockModeType.PESSIMISTIC_WRITE)
+})
 public class ImPreferencesImpl implements ImPreferences, Persistable, CreateInfo {
 
 	private static final long serialVersionUID = -7269061512818714778L;
diff --git a/src/main/java/org/olat/instantMessaging/model/InstantMessageImpl.java b/src/main/java/org/olat/instantMessaging/model/InstantMessageImpl.java
index a445ee33505..4d538f5f61e 100644
--- a/src/main/java/org/olat/instantMessaging/model/InstantMessageImpl.java
+++ b/src/main/java/org/olat/instantMessaging/model/InstantMessageImpl.java
@@ -25,6 +25,8 @@ import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 import javax.persistence.Table;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
@@ -41,8 +43,13 @@ import org.olat.instantMessaging.InstantMessage;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-@Entity
+@Entity(name="instantmessage")
 @Table(name="o_im_message")
+@NamedQueries({
+	@NamedQuery(name="loadIMessageByKey",query="select msg from instantmessage msg  where msg.key=:key"),
+	@NamedQuery(name="loadIMessageByResource", query="select msg from instantmessage msg where msg.resourceId=:resid and msg.resourceTypeName=:resname order by msg.creationDate desc")
+		
+})
 public class InstantMessageImpl implements InstantMessage, Persistable, CreateInfo {
 	
 	private static final long serialVersionUID = 1425964260797865080L;
diff --git a/src/main/java/org/olat/instantMessaging/model/InstantMessageNotificationImpl.java b/src/main/java/org/olat/instantMessaging/model/InstantMessageNotificationImpl.java
index 5de149b77e7..73c2a0bae67 100644
--- a/src/main/java/org/olat/instantMessaging/model/InstantMessageNotificationImpl.java
+++ b/src/main/java/org/olat/instantMessaging/model/InstantMessageNotificationImpl.java
@@ -25,6 +25,8 @@ import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 import javax.persistence.Table;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
@@ -42,8 +44,13 @@ import org.olat.instantMessaging.InstantMessageNotification;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-@Entity
+@Entity(name="imnotification")
 @Table(name="o_im_notification")
+@NamedQueries({
+		@NamedQuery(name="loadIMNotificationByIdentity", query="select notification from imnotification notification where notification.toIdentityKey=:identityKey order by notification.creationDate desc"),
+		@NamedQuery(name="deleteIMNotificationByResourceAndIdentity", query="delete from imnotification notification where notification.toIdentityKey=:identityKey and notification.resourceId=:resid and notification.resourceTypeName=:resname"),
+
+})
 public class InstantMessageNotificationImpl implements InstantMessageNotification, Persistable, CreateInfo  {
 
 	private static final long serialVersionUID = -1244360269062615091L;
diff --git a/src/main/java/org/olat/instantMessaging/model/RosterEntryImpl.java b/src/main/java/org/olat/instantMessaging/model/RosterEntryImpl.java
index 7675ae7370b..cee5ecdf749 100644
--- a/src/main/java/org/olat/instantMessaging/model/RosterEntryImpl.java
+++ b/src/main/java/org/olat/instantMessaging/model/RosterEntryImpl.java
@@ -25,6 +25,8 @@ import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 import javax.persistence.Table;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
@@ -39,8 +41,14 @@ import org.olat.core.id.Persistable;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-@Entity
+@Entity(name="imrosterentry")
 @Table(name="o_im_roster_entry")
+@NamedQueries({
+	@NamedQuery(name="loadIMRosterEntryByIdentityandResource", query="select entry from imrosterentry entry where entry.identityKey=:identityKey and entry.resourceId=:resid and entry.resourceTypeName=:resname"),
+	@NamedQuery(name="loadIMRosterEntryByResource", query="select entry from imrosterentry entry where entry.resourceId=:resid and entry.resourceTypeName=:resname"),
+	@NamedQuery(name="clearIMRosterEntry", query="delete from imrosterentry entry"),
+	@NamedQuery(name="deleteIMRosterEntryByIdentityAndResource", query="delete from imrosterentry entry where entry.identityKey=:identityKey and entry.resourceId=:resid and entry.resourceTypeName=:resname"),
+})
 public class RosterEntryImpl implements Persistable, CreateInfo {
 
 	private static final long serialVersionUID = -4265724240924748369L;
diff --git a/src/test/java/org/olat/instantMessaging/InstantMessageDAOTest.java b/src/test/java/org/olat/instantMessaging/InstantMessageDAOTest.java
index 379b2fe387f..b3fac17e458 100644
--- a/src/test/java/org/olat/instantMessaging/InstantMessageDAOTest.java
+++ b/src/test/java/org/olat/instantMessaging/InstantMessageDAOTest.java
@@ -61,9 +61,9 @@ public class InstantMessageDAOTest extends OlatTestCase {
 	}
 	
 	@Test
-	public void testLoadMessage() {
+	public void testLoadMessage_byId() {
 		//create a message
-		OLATResourceable chatResources = OresHelper.createOLATResourceableInstance("unit-test-2", System.currentTimeMillis());
+		OLATResourceable chatResources = OresHelper.createOLATResourceableInstance("unit-test-2-" + UUID.randomUUID().toString(), System.currentTimeMillis());
 		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-2-" + UUID.randomUUID().toString());
 		InstantMessage msg = imDao.createMessage(id, id.getName(), false, "Hello load by id", chatResources);
 		Assert.assertNotNull(msg);
@@ -76,9 +76,26 @@ public class InstantMessageDAOTest extends OlatTestCase {
 		Assert.assertEquals("Hello load by id", reloadedMsg.getBody());
 	}
 	
+	@Test
+	public void testLoadMessage_byResource() {
+		//create a message
+		OLATResourceable chatResources = OresHelper.createOLATResourceableInstance("unit-test-3-" + UUID.randomUUID().toString(), System.currentTimeMillis());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-3-" + UUID.randomUUID().toString());
+		InstantMessage msg = imDao.createMessage(id, id.getName(), false, "Hello load by resource", chatResources);
+		Assert.assertNotNull(msg);
+		dbInstance.commitAndCloseSession();
+		
+		//load the message
+		List<InstantMessage> messageList = imDao.getMessages(chatResources, 0, -1);
+		Assert.assertNotNull(messageList);
+		Assert.assertEquals(1, messageList.size());
+		Assert.assertEquals(msg.getKey(), messageList.get(0).getKey());
+		Assert.assertEquals("Hello load by resource", messageList.get(0).getBody());
+	}
+	
 	@Test
 	public void testCreateNotification() {
-		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-3", System.currentTimeMillis());
+		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-4", System.currentTimeMillis());
 		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-3-" + UUID.randomUUID().toString());
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsAdmin("im-9-" + UUID.randomUUID().toString());
 		InstantMessageNotification notification = imDao.createNotification(id2.getKey(), id.getKey(), chatResource);
@@ -90,7 +107,7 @@ public class InstantMessageDAOTest extends OlatTestCase {
 	
 	@Test
 	public void testDeleteNotification() {
-		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-3", System.currentTimeMillis());
+		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-5", System.currentTimeMillis());
 		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-3-" + UUID.randomUUID().toString());
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsAdmin("im-7-" + UUID.randomUUID().toString());
 		InstantMessageNotification notification = imDao.createNotification(id2.getKey(), id.getKey(), chatResource);
diff --git a/src/test/java/org/olat/instantMessaging/InstantMessagePreferencesDAOTest.java b/src/test/java/org/olat/instantMessaging/InstantMessagePreferencesDAOTest.java
index 06ca162bc39..1a15a4a8964 100644
--- a/src/test/java/org/olat/instantMessaging/InstantMessagePreferencesDAOTest.java
+++ b/src/test/java/org/olat/instantMessaging/InstantMessagePreferencesDAOTest.java
@@ -20,12 +20,16 @@
 package org.olat.instantMessaging;
 
 import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import junit.framework.Assert;
 
 import org.junit.Test;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
 import org.olat.instantMessaging.manager.InstantMessagePreferencesDAO;
 import org.olat.instantMessaging.model.ImPreferencesImpl;
 import org.olat.instantMessaging.model.Presence;
@@ -41,27 +45,33 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class InstantMessagePreferencesDAOTest extends OlatTestCase {
 	
+	private static final OLog log = Tracing.createLoggerFor(InstantMessagePreferencesDAOTest.class);
+	private static int NUM_OF_THREADS = 20;
+	
 	@Autowired
 	private DB dbInstance;
 	@Autowired
 	private InstantMessagePreferencesDAO imDao;
 	
 	@Test
-	public void testCreateMessage() {
+	public void testCreatePreferences() {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-prefs-1-" + UUID.randomUUID().toString());
 		ImPreferencesImpl prefs = imDao.createPreferences(id, Presence.available.name(), true);
+		dbInstance.commitAndCloseSession();
+		
 		Assert.assertNotNull(prefs);
 		Assert.assertNotNull(prefs.getKey());
 		Assert.assertNotNull(prefs.getCreationDate());
-		
-		dbInstance.commitAndCloseSession();
+		Assert.assertEquals(id, prefs.getIdentity());
+		Assert.assertEquals(Presence.available.name(), prefs.getRosterDefaultStatus());
+		Assert.assertTrue(prefs.isVisibleToOthers());
 	}
 	
 	@Test
-	public void testLoadMessage() {
+	public void testLoadPreferences() {
 		//create a message
 		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-prefs-2-" + UUID.randomUUID().toString());
-		ImPreferencesImpl prefs = imDao.createPreferences(id, Presence.available.name(), true);
+		ImPreferencesImpl prefs = imDao.createPreferences(id, Presence.unavailable.name(), true);
 		Assert.assertNotNull(prefs);
 		dbInstance.commitAndCloseSession();
 		
@@ -69,8 +79,131 @@ public class InstantMessagePreferencesDAOTest extends OlatTestCase {
 		ImPreferencesImpl reloadedPrefs = imDao.getPreferences(id);
 		Assert.assertNotNull(reloadedPrefs);
 		Assert.assertEquals(prefs.getKey(), reloadedPrefs.getKey());
+		Assert.assertEquals(id, reloadedPrefs.getIdentity());
+		Assert.assertEquals(Presence.unavailable.name(), prefs.getRosterDefaultStatus());
+		Assert.assertTrue(prefs.isVisibleToOthers());
 	}
 
+	@Test
+	public void testUpdatePreferences_visibility() {
+		//create a message
+		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-prefs-3-" + UUID.randomUUID().toString());
+		ImPreferencesImpl prefs = imDao.createPreferences(id, Presence.unavailable.name(), true);
+		Assert.assertNotNull(prefs);
+		dbInstance.commitAndCloseSession();
+		
+		//update visibility
+		imDao.updatePreferences(id, false);
+		dbInstance.commitAndCloseSession();
+		
+		//check the visibility
+		ImPreferencesImpl reloadedPrefs = imDao.getPreferences(id);
+		Assert.assertNotNull(reloadedPrefs);
+		Assert.assertEquals(prefs.getKey(), reloadedPrefs.getKey());
+		Assert.assertEquals(id, reloadedPrefs.getIdentity());
+		Assert.assertFalse(reloadedPrefs.isVisibleToOthers());
+	}
+	
+	@Test
+	public void testUpdatePreferences_status() {
+		//create a message
+		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-prefs-4-" + UUID.randomUUID().toString());
+		ImPreferencesImpl prefs = imDao.createPreferences(id, Presence.dnd.name(), true);
+		Assert.assertNotNull(prefs);
+		dbInstance.commitAndCloseSession();
+		
+		//update visibility
+		imDao.updatePreferences(id, Presence.unavailable.name());
+		dbInstance.commitAndCloseSession();
+		
+		//check the visibility
+		ImPreferencesImpl reloadedPrefs = imDao.getPreferences(id);
+		Assert.assertNotNull(reloadedPrefs);
+		Assert.assertEquals(prefs.getKey(), reloadedPrefs.getKey());
+		Assert.assertEquals(id, reloadedPrefs.getIdentity());
+		Assert.assertEquals(Presence.unavailable.name(), reloadedPrefs.getRosterDefaultStatus());
+	}
+	
+	@Test
+	public void testUpdatePreferences_concurrent() {
+		//create a message
+		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-prefs-4-" + UUID.randomUUID().toString());
+		ImPreferencesImpl prefs = imDao.createPreferences(id, Presence.dnd.name(), true);
+		Assert.assertNotNull(prefs);
+		dbInstance.commitAndCloseSession();
+		
+		final CountDownLatch finishCount = new CountDownLatch(NUM_OF_THREADS);
+		
+		UpdateThread[] threads = new UpdateThread[NUM_OF_THREADS];
+		for(int i=0; i<NUM_OF_THREADS; i++) {
+			threads[i] = new UpdateThread(id, finishCount, i, dbInstance, imDao);
+		}
+		
+		for(int i=0; i<NUM_OF_THREADS; i++) {
+			threads[i].start();
+		}
+		
+		try {
+			finishCount.await(20, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			log.error("", e);
+		}
+		
+		boolean allOk = true;
+		for(int i=0; i<NUM_OF_THREADS; i++) {
+			allOk &= threads[i].isOk();
+		}
+		Assert.assertTrue(allOk);
+	}
+	
+	private static class UpdateThread extends Thread {
+		
+		private boolean ok = true;
+		private final Identity id;
+		private final CountDownLatch finishCount;
+		
+		private final DB dbInstance;
+		private final InstantMessagePreferencesDAO imDao;
+		
+		public UpdateThread(Identity id, CountDownLatch finishCount, int num, 
+				DB dbInstance, InstantMessagePreferencesDAO imDao) {
+			super("Update im preferences - " + num);
+			this.id = id;
+			this.finishCount = finishCount;
+			this.dbInstance = dbInstance;
+			this.imDao = imDao;
+		}
+		
+		public boolean isOk() {
+			return ok;
+		}
 
-
-}
+		@Override
+		public void run() {
+			try {
+				Thread.sleep(10);
+				
+				for(int i=0; i<NUM_OF_THREADS; i++) {
+					double r = Math.random() * 5.0d;
+					if(r < 1.0d) {
+						imDao.updatePreferences(id, true);
+					} else if(r < 2.0d) {
+						imDao.updatePreferences(id, false);
+					} else if(r < 3.0d) {
+						imDao.updatePreferences(id, Presence.available.name());
+					} else if(r < 4.0d) {
+						imDao.updatePreferences(id, Presence.dnd.name());
+					} else {
+						imDao.updatePreferences(id, Presence.unavailable.name());
+					}
+					dbInstance.commitAndCloseSession();
+				}
+			} catch (Exception e) {
+				log.error("", e);
+				ok = false;
+			} finally {
+				finishCount.countDown();
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java b/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
index 283c64329c4..13eaa20fa19 100644
--- a/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
+++ b/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java
@@ -25,6 +25,7 @@ import org.junit.Test;
 import org.olat.core.commons.persistence.DB;
 import org.olat.instantMessaging.manager.InstantMessageDAO;
 import org.olat.instantMessaging.manager.InstantMessagePreferencesDAO;
+import org.olat.instantMessaging.manager.RosterDAO;
 import org.olat.test.OlatTestCase;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -43,6 +44,8 @@ public class InstantMessageServiceTest extends OlatTestCase {
 	@Autowired
 	private InstantMessagePreferencesDAO preferencesDao;
 	@Autowired
+	private RosterDAO rosterDao;
+	@Autowired
 	private InstantMessagingService imService;
 
 	@Test
@@ -50,6 +53,7 @@ public class InstantMessageServiceTest extends OlatTestCase {
 		Assert.assertNotNull(dbInstance);
 		Assert.assertNotNull(imDao);
 		Assert.assertNotNull(preferencesDao);
+		Assert.assertNotNull(rosterDao);
 		Assert.assertNotNull(imService);
 	}
 }
diff --git a/src/test/java/org/olat/instantMessaging/RosterDAOTest.java b/src/test/java/org/olat/instantMessaging/RosterDAOTest.java
new file mode 100644
index 00000000000..e320c2e4f8f
--- /dev/null
+++ b/src/test/java/org/olat/instantMessaging/RosterDAOTest.java
@@ -0,0 +1,154 @@
+package org.olat.instantMessaging;
+
+import java.util.List;
+import java.util.UUID;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.util.resource.OresHelper;
+import org.olat.instantMessaging.manager.RosterDAO;
+import org.olat.instantMessaging.model.RosterEntryImpl;
+import org.olat.test.JunitTestHelper;
+import org.olat.test.OlatTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 20.12.2012<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class RosterDAOTest extends OlatTestCase {
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private RosterDAO rosterDao;
+	
+	@Test
+	public void testCreateRosterEntry() {
+		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-1-" + UUID.randomUUID().toString(), System.currentTimeMillis());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-roster-1-" + UUID.randomUUID().toString());
+		
+		RosterEntryImpl entry = rosterDao.createRosterEntry(chatResource, id, "My full name", "A nick name", false);
+		dbInstance.commitAndCloseSession();
+		
+		Assert.assertNotNull(entry);
+		Assert.assertNotNull(entry.getKey());
+		Assert.assertEquals(id.getKey(), entry.getIdentityKey());
+		Assert.assertEquals("My full name", entry.getFullName());
+		Assert.assertEquals("A nick name", entry.getNickName());
+		Assert.assertFalse(entry.isAnonym());
+		Assert.assertEquals(chatResource.getResourceableTypeName(), entry.getResourceTypeName());
+		Assert.assertEquals(chatResource.getResourceableId(), entry.getResourceId());
+	}
+
+	@Test
+	public void testLoadRosterEntries() {
+		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-2-" + UUID.randomUUID().toString(), System.currentTimeMillis());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-roster-2-" + UUID.randomUUID().toString());
+		rosterDao.createRosterEntry(chatResource, id, "My full name", "A nick name", false);
+		dbInstance.commitAndCloseSession();
+		
+		//load the entries
+		List<RosterEntryImpl> entries = rosterDao.getRoster(chatResource, 0, -1);
+		Assert.assertNotNull(entries);
+		Assert.assertEquals(1, entries.size());
+		
+		RosterEntryImpl entry = entries.get(0);
+		Assert.assertNotNull(entry);
+		Assert.assertNotNull(entry.getKey());
+		Assert.assertEquals(id.getKey(), entry.getIdentityKey());
+		Assert.assertEquals("My full name", entry.getFullName());
+		Assert.assertEquals("A nick name", entry.getNickName());
+		Assert.assertFalse(entry.isAnonym());
+		Assert.assertEquals(chatResource.getResourceableTypeName(), entry.getResourceTypeName());
+		Assert.assertEquals(chatResource.getResourceableId(), entry.getResourceId());
+	}
+	
+	@Test
+	public void testUpdateRosterEntry() {
+		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-7-" + UUID.randomUUID().toString(), System.currentTimeMillis());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-roster-7-" + UUID.randomUUID().toString());
+		rosterDao.createRosterEntry(chatResource, id, "My name", "Nick", false);
+		dbInstance.commitAndCloseSession();
+		
+		//load the entry
+		rosterDao.updateRosterEntry(chatResource, id, "My updated full name", "My updated nick name", true);
+		dbInstance.commitAndCloseSession();
+		
+		//load the entry
+		List<RosterEntryImpl> entries = rosterDao.getRoster(chatResource, 0, -1);
+		Assert.assertNotNull(entries);
+		Assert.assertEquals(1, entries.size());
+			
+		RosterEntryImpl entry = entries.get(0);
+		
+		Assert.assertNotNull(entries);
+		Assert.assertEquals(1, entries.size());
+		
+		RosterEntryImpl reloadEntry = entries.get(0);
+		Assert.assertNotNull(reloadEntry);
+		Assert.assertNotNull(reloadEntry.getKey());
+		Assert.assertEquals(id.getKey(), reloadEntry.getIdentityKey());
+		Assert.assertEquals("My updated full name", reloadEntry.getFullName());
+		Assert.assertEquals("My updated nick name", reloadEntry.getNickName());
+		Assert.assertTrue(entry.isAnonym());
+		Assert.assertEquals(chatResource.getResourceableTypeName(), reloadEntry.getResourceTypeName());
+		Assert.assertEquals(chatResource.getResourceableId(), reloadEntry.getResourceId());
+	}
+	
+	@Test
+	public void testDeleteRosterEntries() {
+		//create an entry
+		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-3-" + UUID.randomUUID().toString(), System.currentTimeMillis());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-roster-3-" + UUID.randomUUID().toString());
+		rosterDao.createRosterEntry(chatResource, id, "My full name", "A nick name", false);
+		dbInstance.commitAndCloseSession();
+		
+		//check the presence of the entry
+		List<RosterEntryImpl> entries = rosterDao.getRoster(chatResource, 0, -1);
+		Assert.assertNotNull(entries);
+		Assert.assertEquals(1, entries.size());
+		dbInstance.commitAndCloseSession();
+		
+		//delete the entry
+		rosterDao.deleteEntry(id, chatResource);
+		dbInstance.commitAndCloseSession();
+		
+		//check the absence of the entry
+		List<RosterEntryImpl> reloadedEntries = rosterDao.getRoster(chatResource, 0, -1);
+		Assert.assertNotNull(reloadedEntries);
+		Assert.assertTrue(reloadedEntries.isEmpty());
+	}
+	
+	@Test
+	public void testClearRosterEntries() {
+		//create an entry
+		OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-4-" + UUID.randomUUID().toString(), System.currentTimeMillis());
+		for(int i=0; i<10; i++) {
+			Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-roster-4-" + UUID.randomUUID().toString());
+			rosterDao.createRosterEntry(chatResource, id, "My full name", "A nick name", false);
+		}
+		dbInstance.commitAndCloseSession();
+		
+		//check the presence of the entries
+		List<RosterEntryImpl> entries = rosterDao.getRoster(chatResource, 0, -1);
+		Assert.assertNotNull(entries);
+		Assert.assertEquals(10, entries.size());
+		dbInstance.commitAndCloseSession();
+		
+		//delete the entry
+		rosterDao.clear();
+		dbInstance.commitAndCloseSession();
+		
+		//check the absence of the entry
+		List<RosterEntryImpl> reloadedEntries = rosterDao.getRoster(chatResource, 0, -1);
+		Assert.assertNotNull(reloadedEntries);
+		Assert.assertTrue(reloadedEntries.isEmpty());
+	}
+}
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index 8455d7df636..7f7bb1fffe7 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -95,6 +95,7 @@ import org.junit.runners.Suite;
 	org.olat.repository.RepositoryManagerQueryTest.class,//ok
 	org.olat.instantMessaging.InstantMessageDAOTest.class,//ok
 	org.olat.instantMessaging.InstantMessagePreferencesDAOTest.class,//ok
+	org.olat.instantMessaging.RosterDAOTest.class,//ok
 	org.olat.instantMessaging.InstantMessageServiceTest.class,//ok
 	org.olat.course.nodes.en.EnrollmentManagerTest.class,//ok
 	org.olat.course.assessment.AssessmentManagerTest.class,//ok
-- 
GitLab