← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 3219: Implemented server side support for messaging

 

------------------------------------------------------------
revno: 3219
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2011-03-30 18:14:30 +0200
message:
  Implemented server side support for messaging
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/Message.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/UserMessage.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/UserMessageStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/HibernateUserMessageStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/Message.hbm.xml
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/UserMessage.hbm.xml
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MessageServiceTest.java
modified:
  dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== added directory 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/message'
=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/Message.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/Message.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/Message.java	2011-03-30 16:14:30 +0000
@@ -0,0 +1,145 @@
+package org.hisp.dhis.message;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class Message
+{
+    private int id;
+    
+    private String key;
+    
+    private String title;
+    
+    private String text;
+    
+    private Set<UserMessage> userMessages = new HashSet<UserMessage>();
+    
+    public Message()
+    {
+        this.key = UUID.randomUUID().toString();
+    }
+    
+    public Message( String title, String text )
+    {
+        this.key = UUID.randomUUID().toString();
+        this.title = title;
+        this.text = text;
+    }
+
+    public int getId()
+    {
+        return id;
+    }
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    public String getKey()
+    {
+        return key;
+    }
+
+    public void setKey( String key )
+    {
+        this.key = key;
+    }
+
+    public String getTitle()
+    {
+        return title;
+    }
+
+    public void setTitle( String title )
+    {
+        this.title = title;
+    }
+
+    public String getText()
+    {
+        return text;
+    }
+
+    public void setText( String text )
+    {
+        this.text = text;
+    }
+
+    public Set<UserMessage> getUserMessages()
+    {
+        return userMessages;
+    }
+
+    public void setUserMessages( Set<UserMessage> userMessages )
+    {
+        this.userMessages = userMessages;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return key.hashCode();
+    }
+
+    @Override
+    public boolean equals( Object object )
+    {
+        if ( this == object )
+        {
+            return true;
+        }
+        
+        if ( object == null )
+        {
+            return false;
+        }
+        
+        if ( getClass() != object.getClass() )
+        {
+            return false;
+        }
+        
+        final Message other = (Message) object;
+        
+        return key.equals( other.key );
+    }
+    
+    @Override
+    public String toString()
+    {
+        return "[Title: " + title + ", text: " + text + "]";
+    }
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/MessageService.java	2011-03-30 16:14:30 +0000
@@ -0,0 +1,54 @@
+package org.hisp.dhis.message;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.List;
+
+import org.hisp.dhis.user.User;
+
+/**
+ * @author Lars Helge Overland
+ */
+public interface MessageService
+{
+    final String ID = MessageService.class.getName();
+    
+    int saveMessage( Message message );
+    
+    Message getMessage( int id );
+    
+    UserMessage getUserMessage( int id );
+    
+    void updateUserMessage( UserMessage userMessage );
+    
+    void deleteUserMessage( UserMessage userMessage );
+    
+    List<UserMessage> getUserMessages( int first, int max );
+    
+    List<UserMessage> getUserMessages( User user, int first, int max );
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/UserMessage.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/UserMessage.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/UserMessage.java	2011-03-30 16:14:30 +0000
@@ -0,0 +1,152 @@
+package org.hisp.dhis.message;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.Date;
+
+import org.hisp.dhis.user.User;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class UserMessage
+{
+    private int id;
+    
+    private User user;
+    
+    private Message message;
+    
+    private boolean read;
+
+    private Date messageDate;
+    
+    public UserMessage()
+    {
+    }
+    
+    public UserMessage( User user, Message message )
+    {
+        this.user = user;
+        this.message = message;
+        this.read = false;
+        this.messageDate = new Date();
+    }
+    
+    public int getId()
+    {
+        return id;
+    }
+
+    public void setId( int id )
+    {
+        this.id = id;
+    }
+
+    public User getUser()
+    {
+        return user;
+    }
+
+    public void setUser( User user )
+    {
+        this.user = user;
+    }
+
+    public Message getMessage()
+    {
+        return message;
+    }
+
+    public void setMessage( Message message )
+    {
+        this.message = message;
+    }
+
+    public boolean isRead()
+    {
+        return read;
+    }
+
+    public void setRead( boolean read )
+    {
+        this.read = read;
+    }
+    
+    public Date getMessageDate()
+    {
+        return messageDate;
+    }
+
+    public void setMessageDate( Date messageDate )
+    {
+        this.messageDate = messageDate;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        
+        int result = 1;
+        
+        result = prime * result + message.hashCode();
+        result = prime * result + user.hashCode();
+        
+        return result;
+    }
+
+    @Override
+    public boolean equals( Object object )
+    {
+        if ( this == object )
+        {
+            return true;
+        }
+        
+        if ( object == null )
+        {
+            return false;
+        }
+        
+        if ( getClass() != object.getClass() )
+        {
+            return false;
+        }
+        
+        final UserMessage other = (UserMessage) object;
+        
+        return message.equals( other.message ) && user.equals( other.user );
+    }
+    
+    @Override
+    public String toString()
+    {
+        return "[User: " + user + ", message: " + message + ", read: " + read + ", date: " + messageDate + "]";
+    }
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/UserMessageStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/UserMessageStore.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/message/UserMessageStore.java	2011-03-30 16:14:30 +0000
@@ -0,0 +1,42 @@
+package org.hisp.dhis.message;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.List;
+
+import org.hisp.dhis.common.GenericStore;
+import org.hisp.dhis.user.User;
+
+/**
+ * @author Lars Helge Overland
+ */
+public interface UserMessageStore
+    extends GenericStore<UserMessage>
+{
+    List<UserMessage> getUserMessages( User user, int first, int max );
+}

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/DefaultMessageService.java	2011-03-30 16:14:30 +0000
@@ -0,0 +1,109 @@
+package org.hisp.dhis.message;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.List;
+
+import org.hisp.dhis.common.GenericStore;
+import org.hisp.dhis.user.CurrentUserService;
+import org.hisp.dhis.user.User;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author Lars Helge Overland
+ */
+@Transactional
+public class DefaultMessageService
+    implements MessageService
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private GenericStore<Message> messageStore;
+    
+    public void setMessageStore( GenericStore<Message> messageStore )
+    {
+        this.messageStore = messageStore;
+    }
+
+    private UserMessageStore userMessageStore;
+
+    public void setUserMessageStore( UserMessageStore userMessageStore )
+    {
+        this.userMessageStore = userMessageStore;
+    }
+
+    private CurrentUserService currentUserService;
+    
+    public void setCurrentUserService( CurrentUserService currentUserService )
+    {
+        this.currentUserService = currentUserService;
+    }
+
+    // -------------------------------------------------------------------------
+    // MessageService implementation
+    // -------------------------------------------------------------------------
+
+    public int saveMessage( Message message )
+    {
+        return messageStore.save( message );
+    }
+    
+    public Message getMessage( int id )
+    {
+        return messageStore.get( id );
+    }
+    
+    public UserMessage getUserMessage( int id )
+    {
+        return userMessageStore.get( id );
+    }
+    
+    public void updateUserMessage( UserMessage userMessage )
+    {
+        userMessageStore.update( userMessage );
+    }
+    
+    public void deleteUserMessage( UserMessage userMessage )
+    {
+        Message message = userMessage.getMessage();
+        message.getUserMessages().remove( userMessage );
+        userMessageStore.delete( userMessage );
+    }
+    
+    public List<UserMessage> getUserMessages( int first, int max )
+    {
+        return userMessageStore.getUserMessages( currentUserService.getCurrentUser(), first, max );
+    }
+
+    public List<UserMessage> getUserMessages( User user, int first, int max )
+    {
+        return userMessageStore.getUserMessages( user, first, max );
+    }
+}

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/HibernateUserMessageStore.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/HibernateUserMessageStore.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/message/hibernate/HibernateUserMessageStore.java	2011-03-30 16:14:30 +0000
@@ -0,0 +1,58 @@
+package org.hisp.dhis.message.hibernate;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.List;
+
+import org.hibernate.Criteria;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Restrictions;
+import org.hisp.dhis.hibernate.HibernateGenericStore;
+import org.hisp.dhis.message.UserMessage;
+import org.hisp.dhis.message.UserMessageStore;
+import org.hisp.dhis.user.User;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class HibernateUserMessageStore
+    extends HibernateGenericStore<UserMessage> implements UserMessageStore 
+{
+    @SuppressWarnings("unchecked")
+    public List<UserMessage> getUserMessages( User user, int first, int max )
+    {
+        Criteria criteria = sessionFactory.getCurrentSession().createCriteria( UserMessage.class );
+        
+        criteria.add( Restrictions.eq( "user", user ) );
+        criteria.setFirstResult( first );
+        criteria.setMaxResults( max );
+        criteria.addOrder( Order.desc( "messageDate" ) );
+        
+        return criteria.list();
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2011-03-14 20:23:43 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2011-03-30 16:14:30 +0000
@@ -120,15 +120,13 @@
 
 	<bean id="org.hisp.dhis.dataelement.DataElementCategoryStore"
 		class="org.hisp.dhis.hibernate.HibernateGenericStore">
-		<property name="clazz"
-			value="org.hisp.dhis.dataelement.DataElementCategory" />
+		<property name="clazz" value="org.hisp.dhis.dataelement.DataElementCategory" />
 		<property name="sessionFactory" ref="sessionFactory" />
 	</bean>
 
 	<bean id="org.hisp.dhis.dataelement.DataElementCategoryOptionStore"
 		class="org.hisp.dhis.hibernate.HibernateGenericStore">
-		<property name="clazz"
-			value="org.hisp.dhis.dataelement.DataElementCategoryOption" />
+		<property name="clazz" value="org.hisp.dhis.dataelement.DataElementCategoryOption" />
 		<property name="sessionFactory" ref="sessionFactory" />
 	</bean>
 
@@ -188,15 +186,15 @@
 		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
 	</bean>
 
-  <bean id="org.hisp.dhis.user.UserGroupStore" class="org.hisp.dhis.hibernate.HibernateGenericStore">
-    <property name="clazz" value="org.hisp.dhis.user.UserGroup" />
-    <property name="sessionFactory" ref="sessionFactory" />
-  </bean>
+	<bean id="org.hisp.dhis.user.UserGroupStore" class="org.hisp.dhis.hibernate.HibernateGenericStore">
+		<property name="clazz" value="org.hisp.dhis.user.UserGroup" />
+		<property name="sessionFactory" ref="sessionFactory" />
+	</bean>
 
-  <bean id="org.hisp.dhis.validation.ValidationCriteriaStore" class="org.hisp.dhis.hibernate.HibernateGenericStore">
-    <property name="clazz" value="org.hisp.dhis.validation.ValidationCriteria" />
-    <property name="sessionFactory" ref="sessionFactory" />
-  </bean>
+	<bean id="org.hisp.dhis.validation.ValidationCriteriaStore" class="org.hisp.dhis.hibernate.HibernateGenericStore">
+		<property name="clazz" value="org.hisp.dhis.validation.ValidationCriteria" />
+		<property name="sessionFactory" ref="sessionFactory" />
+	</bean>
 
 	<bean id="org.hisp.dhis.translation.TranslationStore"
 		class="org.hisp.dhis.translation.hibernate.HibernateTranslationStore">
@@ -213,6 +211,22 @@
 		<property name="sessionFactory" ref="sessionFactory" />
 	</bean>
 	
+	<bean id="org.hisp.dhis.message.MessageStore" class="org.hisp.dhis.hibernate.HibernateGenericStore">
+		<property name="sessionFactory" ref="sessionFactory"/>
+		<property name="clazz" value="org.hisp.dhis.message.Message"/>
+	</bean>
+	
+	<bean id="org.hisp.dhis.message.UserMessageStore" class="org.hisp.dhis.message.hibernate.HibernateUserMessageStore">
+		<property name="sessionFactory" ref="sessionFactory"/>
+		<property name="clazz" value="org.hisp.dhis.message.UserMessage"/>
+	</bean>
+	
+	<bean id="org.hisp.dhis.message.MessageService" class="org.hisp.dhis.message.DefaultMessageService">
+		<property name="messageStore" ref="org.hisp.dhis.message.MessageStore"/>
+		<property name="userMessageStore" ref="org.hisp.dhis.message.UserMessageStore"/>
+		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService"/>
+	</bean>
+	
 	<!-- Service definitions -->
 
 	<bean id="org.hisp.dhis.dataelement.DataElementOperandService"

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message'
=== added directory 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/Message.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/Message.hbm.xml	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/Message.hbm.xml	2011-03-30 16:14:30 +0000
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd";>
+
+<hibernate-mapping>
+  <class name="org.hisp.dhis.message.Message" table="message">
+    <id name="id" column="messageid">
+      <generator class="native"/>
+    </id>
+
+	<property name="key" column="key" not-null="true"/>
+    <property name="title" column="title" not-null="true"/>
+    <property name="text" column="text"/>
+    
+    <set name="userMessages" table="message_usermessages" cascade="save-update">
+      <key column="messageid"/>
+      <many-to-many class="org.hisp.dhis.message.UserMessage"
+        column="usermessageid" unique="true" foreign-key="fk_message_usermessages"/>
+    </set>
+    
+  </class>
+</hibernate-mapping>
\ No newline at end of file

=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/UserMessage.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/UserMessage.hbm.xml	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/message/hibernate/UserMessage.hbm.xml	2011-03-30 16:14:30 +0000
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd";>
+
+<hibernate-mapping>
+  <class name="org.hisp.dhis.message.UserMessage" table="usermessage">
+    <id name="id" column="usermessageid">
+      <generator class="native"/>
+    </id>
+
+    <property name="read" column="read" not-null="true"/>
+    <property name="messageDate" column="messageDate" not-null="true"/>
+    
+    <many-to-one name="user" class="org.hisp.dhis.user.User" 
+      column="userid" foreign-key="fk_usermessage_user" not-null="true"/>
+    
+    <join table="message_usermessages" inverse="true">
+      <key column="usermessageid"/>
+      <many-to-one column="messageid" name="message"/>
+    </join>
+    
+  </class>
+</hibernate-mapping>
\ No newline at end of file

=== added directory 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message'
=== added file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MessageServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MessageServiceTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/message/MessageServiceTest.java	2011-03-30 16:14:30 +0000
@@ -0,0 +1,153 @@
+package org.hisp.dhis.message;
+
+/*
+ * Copyright (c) 2004-2010, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.List;
+
+import org.hisp.dhis.DhisSpringTest;
+import org.hisp.dhis.user.User;
+import org.hisp.dhis.user.UserService;
+import org.junit.Test;
+
+import static junit.framework.Assert.*;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class MessageServiceTest
+    extends DhisSpringTest
+{
+    private User userA;
+    private User userB;
+
+    private Message messageA;
+    private Message messageB;
+    
+    private UserMessage userMessageA;
+    private UserMessage userMessageB;
+    private UserMessage userMessageC;
+    private UserMessage userMessageD;
+
+    // -------------------------------------------------------------------------
+    // Fixture
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void setUpTest()
+    {
+        userService = (UserService) getBean( UserService.ID );
+        messageService = (MessageService) getBean( MessageService.ID );
+        
+        userA = createUser( 'A' );
+        userB = createUser( 'B' );
+        
+        userService.addUser( userA );
+        userService.addUser( userB );
+
+        messageA = new Message( "TitleA", "TextA" );
+        messageB = new Message( "TitleB", "TextB" );
+        
+        userMessageA = new UserMessage( userA, messageA );
+        userMessageB = new UserMessage( userB, messageA );
+        userMessageC = new UserMessage( userA, messageB );
+        userMessageD = new UserMessage( userB, messageB );
+        
+        messageA.getUserMessages().add( userMessageA );
+        messageA.getUserMessages().add( userMessageB );
+        messageB.getUserMessages().add( userMessageC );
+        messageB.getUserMessages().add( userMessageD );
+    }
+    
+    @Test
+    public void testSaveMessage()
+    {
+        int idA = messageService.saveMessage( messageA );
+        
+        messageA = messageService.getMessage( idA );
+        
+        assertNotNull( messageA );
+        assertEquals( "TitleA", messageA.getTitle() );
+        assertEquals( "TextA", messageA.getText() );
+        assertEquals( 2, messageA.getUserMessages().size() );
+        assertTrue( messageA.getUserMessages().contains( userMessageA ) );
+        assertTrue( messageA.getUserMessages().contains( userMessageB ) );
+    }
+
+    @Test
+    public void testGetUserMessages()
+    {
+        messageService.saveMessage( messageA );
+        messageService.saveMessage( messageB );
+        
+        List<UserMessage> userMessages = messageService.getUserMessages( userA, 0, 10 );
+        
+        assertNotNull( userMessages );
+        assertEquals( 2, userMessages.size() );
+        assertTrue( userMessages.contains( userMessageA ) );
+        assertTrue( userMessages.contains( userMessageC ) );
+    }
+
+    @Test
+    public void testUpdateUserMessage()
+    {
+        messageService.saveMessage( messageA );
+        
+        assertNotNull( userMessageA );
+        assertFalse( userMessageA.isRead() );
+        
+        userMessageA.setRead( true );
+        
+        int idA = userMessageA.getId();
+        
+        messageService.updateUserMessage( userMessageA );
+        
+        userMessageA = messageService.getUserMessage( idA );
+        
+        assertNotNull( userMessageA );
+        assertTrue( userMessageA.isRead() );
+    }
+    
+    @Test
+    public void testDeleteUserMessage()
+    {
+        messageService.saveMessage( messageA );
+
+        assertEquals( 2, messageA.getUserMessages().size() );
+        assertTrue( messageA.getUserMessages().contains( userMessageA ) );
+        assertTrue( messageA.getUserMessages().contains( userMessageB ) );
+        
+        messageService.deleteUserMessage( userMessageB );
+
+        assertEquals( 1, messageA.getUserMessages().size() );
+        assertTrue( messageA.getUserMessages().contains( userMessageA ) );
+        
+        messageService.deleteUserMessage( userMessageA );
+
+        assertEquals( 0, messageA.getUserMessages().size() );
+    }
+}

=== modified file 'dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java'
--- dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java	2011-02-15 20:14:22 +0000
+++ dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java	2011-03-30 16:14:30 +0000
@@ -72,6 +72,7 @@
 import org.hisp.dhis.mapping.MapLegend;
 import org.hisp.dhis.mapping.MapLegendSet;
 import org.hisp.dhis.mapping.MappingService;
+import org.hisp.dhis.message.MessageService;
 import org.hisp.dhis.olap.OlapURL;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
@@ -92,6 +93,7 @@
 import org.hisp.dhis.sqlview.SqlView;
 import org.hisp.dhis.user.User;
 import org.hisp.dhis.user.UserGroup;
+import org.hisp.dhis.user.UserService;
 import org.hisp.dhis.validation.ValidationCriteria;
 import org.hisp.dhis.validation.ValidationCriteriaService;
 import org.hisp.dhis.validation.ValidationRule;
@@ -153,6 +155,10 @@
     protected ProgramStageService programStageService;
 
     protected DataEntryFormService dataEntryFormService;
+    
+    protected UserService userService;
+    
+    protected MessageService messageService;
 
     static
     {