← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 21187: Merged branch sms-refactor from Zubair. Implements SmSController / Web API for SMS gateways.

 

Merge authors:
  Zubair (rajazubair-asghar)
------------------------------------------------------------
revno: 21187 [merge]
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2015-11-24 14:14:24 +0100
message:
  Merged branch sms-refactor from Zubair. Implements SmSController / Web API for SMS gateways.
removed:
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/config/SMSGatewayStatus.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/outbound/SMSServiceStatus.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/sms/
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/sms/SmsController.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/config/SmsConfigurationManager.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/incoming/IncomingSmsService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/outbound/OutboundSmsTransportService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/config/DefaultSmsConfigurationManager.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/incoming/DefaultIncomingSmsService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/outbound/DefaultOutboundSmsTransportService.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 file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/config/SMSGatewayStatus.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/config/SMSGatewayStatus.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/config/SMSGatewayStatus.java	2015-11-24 13:14:24 +0000
@@ -0,0 +1,38 @@
+package org.hisp.dhis.sms.config;
+
+/*
+ * Copyright (c) 2004-2015, 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.
+ */
+
+/**
+ * Zubair <rajazubair.asghar@xxxxxxxxx>
+ */
+public enum SMSGatewayStatus
+{
+    STOPPED,STOPPING, STARTING, STARTED, UNDEFINED
+
+}

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/config/SmsConfigurationManager.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/config/SmsConfigurationManager.java	2015-10-07 14:40:33 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/config/SmsConfigurationManager.java	2015-11-24 13:14:24 +0000
@@ -28,6 +28,9 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/**
+ * Zubair <rajazubair.asghar@xxxxxxxxx>
+ */
 public interface SmsConfigurationManager
 {
     SmsConfiguration getSmsConfiguration();
@@ -35,4 +38,12 @@
     void updateSmsConfiguration( SmsConfiguration config );
     
     SmsGatewayConfig checkInstanceOfGateway( Class<?> clazz );
+    
+    boolean setDefaultSMSGateway(String gatewayId);
+    
+    boolean gatewayExists (String gatewayId);
+    
+    boolean removeSMSGatewayById(String gatewayId);
+    
+    String addSMSGateway();
 }
\ No newline at end of file

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/incoming/IncomingSmsService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/incoming/IncomingSmsService.java	2015-10-07 14:40:33 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/incoming/IncomingSmsService.java	2015-11-24 10:16:34 +0000
@@ -46,27 +46,29 @@
      * @return the oldest sms in the INCOMING state.
      */
     IncomingSms getNextUnprocessed();
-    
+
     void update( IncomingSms sms );
-    
-    IncomingSms findBy ( Integer id );
-    
+
+    IncomingSms findBy( Integer id );
+
     List<IncomingSms> listAllMessage();
-    
+
     List<IncomingSms> listAllMessageFromModem();
-    
+
     void deleteAllFromModem();
-    
+
     void deleteById( Integer id );
-    
+
     List<InboundMessage> getMsgList();
-    
-    void save ( IncomingSms sms );
-    
+
+    void save( IncomingSms sms );
+
+    void save( String message, String originator, String gateway );
+
     void setIncomingSmsQueue( MessageQueue incomingSmsQueue );
-    
+
     List<IncomingSms> getSmsByStatus( SmsMessageStatus status, String keyword );
-    
+
     List<IncomingSms> getSmsByStatus( SmsMessageStatus status, String keyword, Integer min, Integer max );
 
     IncomingSms convertToIncomingSms( InboundMessage message );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/outbound/OutboundSmsTransportService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/outbound/OutboundSmsTransportService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/outbound/OutboundSmsTransportService.java	2015-11-24 13:14:24 +0000
@@ -1,11 +1,5 @@
 package org.hisp.dhis.sms.outbound;
 
-import java.util.Map;
-
-import org.hisp.dhis.sms.SmsServiceException;
-import org.hisp.dhis.sms.config.SmsConfigurable;
-import org.hisp.dhis.sms.config.SmsConfiguration;
-
 /*
  * Copyright (c) 2004-2015, University of Oslo
  * All rights reserved.
@@ -34,12 +28,19 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import java.util.Map;
+
+import org.hisp.dhis.sms.SmsServiceException;
+import org.hisp.dhis.sms.config.SMSGatewayStatus;
+import org.hisp.dhis.sms.config.SmsConfigurable;
+import org.hisp.dhis.sms.config.SmsConfiguration;
+
 /**
  * Marker interface for {@code OutboundSmsService outbound sms services}
- * providing actual sms sending.
+ * providing actual SMS sending.
  */
-public interface OutboundSmsTransportService extends SmsConfigurable
-
+public interface OutboundSmsTransportService 
+    extends SmsConfigurable
 {   
     Map<String, String> getGatewayMap();
 
@@ -55,6 +56,10 @@
     String getMessageStatus();
 
     String getDefaultGateway();
+    
+    SMSServiceStatus getServiceStatusEnum();
+    
+    SMSGatewayStatus getGatewayStatus();
 
     boolean isEnabled();
 

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/outbound/SMSServiceStatus.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/outbound/SMSServiceStatus.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/outbound/SMSServiceStatus.java	2015-11-24 13:14:24 +0000
@@ -0,0 +1,37 @@
+package org.hisp.dhis.sms.outbound;
+
+/*
+ * Copyright (c) 2004-2015, 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.
+ */
+
+/**
+ * Zubair <rajazubair.asghar@xxxxxxxxx>
+ */
+public enum SMSServiceStatus
+{
+    STARTED, STOPPED, STARTING, STOPPING
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/config/DefaultSmsConfigurationManager.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/config/DefaultSmsConfigurationManager.java	2015-10-07 14:40:33 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/config/DefaultSmsConfigurationManager.java	2015-11-24 13:14:24 +0000
@@ -29,13 +29,15 @@
  */
 
 import java.util.List;
-
 import javax.annotation.PostConstruct;
 
+import org.apache.commons.lang.NotImplementedException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.hisp.dhis.setting.Setting;
 import org.hisp.dhis.setting.SystemSettingManager;
+
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -130,4 +132,67 @@
         
         return null;
     }
+
+    @Override
+    public boolean setDefaultSMSGateway( String gatewayId )
+    {
+        boolean result = false;
+        
+        SmsConfiguration config = getSmsConfiguration();
+        
+        if ( config == null )
+        {
+            return result;
+        }
+        
+        List <SmsGatewayConfig> smsGatewayList = config.getGateways();
+
+        for ( SmsGatewayConfig gw : smsGatewayList )
+        {
+            if ( gw.getName().equals( gatewayId ) )
+            {
+                gw.setDefault( true );
+                result = true;
+
+            }
+            else
+            {
+                gw.setDefault( false );
+
+            }
+        }
+
+        updateSmsConfiguration( config );
+        
+        return result;
+    }
+
+    @Override
+    public boolean gatewayExists( String gatewayId )
+    {
+        SmsConfiguration config = getSmsConfiguration();
+        List<SmsGatewayConfig> gatewayList = config.getGateways();
+        
+        for ( SmsGatewayConfig gw : gatewayList )
+        {
+            if ( gw.getName().equals( gatewayId ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean removeSMSGatewayById( String gatewayId )
+    {
+        return false;
+    }
+
+    @Override
+    public String addSMSGateway()
+    {
+        throw new NotImplementedException();
+    } 
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/incoming/DefaultIncomingSmsService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/incoming/DefaultIncomingSmsService.java	2015-06-16 05:11:29 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/incoming/DefaultIncomingSmsService.java	2015-11-24 13:14:24 +0000
@@ -29,6 +29,7 @@
  */
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 import org.hisp.dhis.sms.MessageQueue;
@@ -44,6 +45,11 @@
 
     private IncomingSmsStore incomingSmsStore;
 
+    public void setIncomingSmsStore( IncomingSmsStore incomingSmsStore )
+    {
+        this.incomingSmsStore = incomingSmsStore;
+    }
+
     private MessageQueue incomingSmsQueue;
 
     @Override
@@ -52,11 +58,6 @@
         this.incomingSmsQueue = incomingSmsQueue;
     }
 
-    public void setIncomingSmsStore( IncomingSmsStore incomingSmsStore )
-    {
-        this.incomingSmsStore = incomingSmsStore;
-    }
-
     // -------------------------------------------------------------------------
     // Input & Output
     // -------------------------------------------------------------------------
@@ -118,7 +119,7 @@
         {
             e.printStackTrace();
         }
-        
+
         return msgList;
     }
 
@@ -130,6 +131,21 @@
     }
 
     @Override
+    public void save( String message, String originator, String gateway )
+    {
+        IncomingSms sms = new IncomingSms();
+        sms.setText( message );
+        sms.setOriginator( originator );
+        sms.setGatewayId( gateway );
+        sms.setSentDate( new Date() );
+        sms.setReceivedDate( new Date() );
+        sms.setEncoding( SmsMessageEncoding.ENC7BIT );
+        sms.setStatus( SmsMessageStatus.INCOMING );
+        save( sms );
+
+    }
+
+    @Override
     public void deleteAllFromModem()
     {
         try
@@ -145,7 +161,7 @@
         {
             e.printStackTrace();
         }
-        
+
         msgList.clear();
     }
 

=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java	2015-11-23 16:24:04 +0000
@@ -0,0 +1,188 @@
+package org.hisp.dhis.sms.listener;
+
+/*
+ * Copyright (c) 2004-2015, 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.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hisp.dhis.message.MessageService;
+import org.hisp.dhis.sms.SmsMessageSender;
+import org.hisp.dhis.sms.command.SMSCommand;
+import org.hisp.dhis.sms.command.SMSCommandService;
+import org.hisp.dhis.sms.incoming.IncomingSms;
+import org.hisp.dhis.sms.incoming.IncomingSmsListener;
+import org.hisp.dhis.sms.incoming.IncomingSmsService;
+import org.hisp.dhis.sms.incoming.SmsMessageStatus;
+import org.hisp.dhis.sms.parse.ParserType;
+import org.hisp.dhis.sms.parse.SMSParserException;
+import org.hisp.dhis.user.User;
+import org.hisp.dhis.user.UserGroup;
+import org.hisp.dhis.user.UserService;
+import org.springframework.transaction.annotation.Transactional;
+
+public class DHISMessageAlertListener
+    implements IncomingSmsListener
+{
+    private SMSCommandService smsCommandService;
+
+    public void setSmsCommandService( SMSCommandService smsCommandService )
+    {
+        this.smsCommandService = smsCommandService;
+    }
+
+    private UserService userService;
+
+    public void setUserService( UserService userService )
+    {
+        this.userService = userService;
+    }
+
+    private MessageService messageService;
+
+    public void setMessageService( MessageService messageService )
+    {
+        this.messageService = messageService;
+    }
+
+    private SmsMessageSender smsMessageSender;
+
+    public void setSmsMessageSender( SmsMessageSender smsMessageSender )
+    {
+        this.smsMessageSender = smsMessageSender;
+    }
+    
+    private IncomingSmsService incomingSmsService;
+
+    public void setIncomingSmsService( IncomingSmsService incomingSmsService )
+    {
+        this.incomingSmsService = incomingSmsService;
+    }
+
+    @Transactional
+    @Override
+    public boolean accept( IncomingSms sms )
+    {
+        String message = sms.getText();
+        String commandString = null;
+
+        for ( int i = 0; i < message.length(); i++ )
+        {
+            String c = String.valueOf( message.charAt( i ) );
+            if ( c.matches( "\\W" ) )
+            {
+                commandString = message.substring( 0, i );
+                message = message.substring( commandString.length() + 1 );
+                break;
+            }
+        }
+
+        return smsCommandService.getSMSCommand( commandString, ParserType.ALERT_PARSER ) != null;
+    }
+
+    @Transactional
+    @Override
+    public void receive( IncomingSms sms )
+    {
+        String message = sms.getText();
+        String commandString = null;
+
+        for ( int i = 0; i < message.length(); i++ )
+        {
+            String c = String.valueOf( message.charAt( i ) );
+            if ( c.matches( "\\W" ) )
+            {
+                commandString = message.substring( 0, i );
+                message = message.substring( commandString.length() + 1 );
+                break;
+            }
+        }
+
+        SMSCommand smsCommand = smsCommandService.getSMSCommand( commandString, ParserType.ALERT_PARSER );
+        UserGroup userGroup = smsCommand.getUserGroup();
+        String senderPhoneNumber = StringUtils.replace( sms.getOriginator(), "+", "" );
+
+        if ( userGroup != null )
+        {
+            Collection<User> users = userService.getUsersByPhoneNumber( senderPhoneNumber );
+
+            if ( users != null && users.size() > 1 )
+            {
+                String messageMoreThanOneUser = smsCommand.getMoreThanOneOrgUnitMessage();
+                if ( messageMoreThanOneUser.trim().equals( "" ) )
+                {
+                    messageMoreThanOneUser = SMSCommand.MORE_THAN_ONE_ORGUNIT_MESSAGE;
+                }
+                for ( Iterator<User> i = users.iterator(); i.hasNext(); )
+                {
+                    User user = i.next();
+                    messageMoreThanOneUser += " " + user.getName();
+                    if ( i.hasNext() )
+                    {
+                        messageMoreThanOneUser += ",";
+                    }
+                }
+                throw new SMSParserException( messageMoreThanOneUser );
+            }
+            else if ( users != null && users.size() == 1 )
+            {
+                User sender = users.iterator().next();
+
+                Set<User> receivers = new HashSet<>( userGroup.getMembers() );
+
+                // forward to user group by SMS,Dhis2 message, Email
+                messageService.sendMessage( smsCommand.getName(), message, null, receivers, sender, false, false );
+
+                // confirm SMS was received and forwarded completely
+                Set<User> feedbackList = new HashSet<>();
+                feedbackList.add( sender );
+
+                String confirmMessage = smsCommand.getReceivedMessage();
+
+                if ( confirmMessage == null )
+                {
+                    confirmMessage = SMSCommand.ALERT_FEEDBACK;
+                }
+
+                smsMessageSender.sendMessage( smsCommand.getName(), confirmMessage, null, null, feedbackList, true );
+
+                sms.setParsed( true );
+                sms.setStatus( SmsMessageStatus.PROCESSED );
+                incomingSmsService.update( sms );
+            }
+            else if ( users == null || users.size() == 0 )
+            {
+                throw new SMSParserException(
+                    "No user associated with this phone number. Please contact your supervisor." );
+            }
+        }
+    }
+}

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java	2015-10-07 14:40:33 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/listener/DHISMessageAlertListener.java	1970-01-01 00:00:00 +0000
@@ -1,188 +0,0 @@
-package org.hisp.dhis.sms.listener;
-
-/*
- * Copyright (c) 2004-2015, 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.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.commons.lang3.StringUtils;
-import org.hisp.dhis.message.MessageService;
-import org.hisp.dhis.sms.SmsMessageSender;
-import org.hisp.dhis.sms.command.SMSCommand;
-import org.hisp.dhis.sms.command.SMSCommandService;
-import org.hisp.dhis.sms.incoming.IncomingSms;
-import org.hisp.dhis.sms.incoming.IncomingSmsListener;
-import org.hisp.dhis.sms.incoming.IncomingSmsService;
-import org.hisp.dhis.sms.incoming.SmsMessageStatus;
-import org.hisp.dhis.sms.parse.ParserType;
-import org.hisp.dhis.sms.parse.SMSParserException;
-import org.hisp.dhis.user.User;
-import org.hisp.dhis.user.UserGroup;
-import org.hisp.dhis.user.UserService;
-import org.springframework.transaction.annotation.Transactional;
-
-public class DHISMessageAlertListener
-    implements IncomingSmsListener
-{
-    private SMSCommandService smsCommandService;
-
-    public void setSmsCommandService( SMSCommandService smsCommandService )
-    {
-        this.smsCommandService = smsCommandService;
-    }
-
-    private UserService userService;
-
-    public void setUserService( UserService userService )
-    {
-        this.userService = userService;
-    }
-
-    private MessageService messageService;
-
-    public void setMessageService( MessageService messageService )
-    {
-        this.messageService = messageService;
-    }
-
-    private SmsMessageSender smsMessageSender;
-
-    public void setSmsMessageSender( SmsMessageSender smsMessageSender )
-    {
-        this.smsMessageSender = smsMessageSender;
-    }
-    
-    private IncomingSmsService incomingSmsService;
-
-    public void setIncomingSmsService( IncomingSmsService incomingSmsService )
-    {
-        this.incomingSmsService = incomingSmsService;
-    }
-
-    @Transactional
-    @Override
-    public boolean accept( IncomingSms sms )
-    {
-        String message = sms.getText();
-        String commandString = null;
-
-        for ( int i = 0; i < message.length(); i++ )
-        {
-            String c = String.valueOf( message.charAt( i ) );
-            if ( c.matches( "\\W" ) )
-            {
-                commandString = message.substring( 0, i );
-                message = message.substring( commandString.length() + 1 );
-                break;
-            }
-        }
-
-        return smsCommandService.getSMSCommand( commandString, ParserType.ALERT_PARSER ) != null;
-    }
-
-    @Transactional
-    @Override
-    public void receive( IncomingSms sms )
-    {
-        String message = sms.getText();
-        String commandString = null;
-
-        for ( int i = 0; i < message.length(); i++ )
-        {
-            String c = String.valueOf( message.charAt( i ) );
-            if ( c.matches( "\\W" ) )
-            {
-                commandString = message.substring( 0, i );
-                message = message.substring( commandString.length() + 1 );
-                break;
-            }
-        }
-
-        SMSCommand smsCommand = smsCommandService.getSMSCommand( commandString, ParserType.ALERT_PARSER );
-        UserGroup userGroup = smsCommand.getUserGroup();
-        String senderPhoneNumber = StringUtils.replace( sms.getOriginator(), "+", "" );
-
-        if ( userGroup != null )
-        {
-            Collection<User> users = userService.getUsersByPhoneNumber( senderPhoneNumber );
-
-            if ( users != null && users.size() > 1 )
-            {
-                String messageMoreThanOneUser = smsCommand.getMoreThanOneOrgUnitMessage();
-                if ( messageMoreThanOneUser.trim().equals( "" ) )
-                {
-                    messageMoreThanOneUser = SMSCommand.MORE_THAN_ONE_ORGUNIT_MESSAGE;
-                }
-                for ( Iterator<User> i = users.iterator(); i.hasNext(); )
-                {
-                    User user = i.next();
-                    messageMoreThanOneUser += " " + user.getName();
-                    if ( i.hasNext() )
-                    {
-                        messageMoreThanOneUser += ",";
-                    }
-                }
-                throw new SMSParserException( messageMoreThanOneUser );
-            }
-            else if ( users != null && users.size() == 1 )
-            {
-                User sender = users.iterator().next();
-
-                Set<User> receivers = new HashSet<>( userGroup.getMembers() );
-
-                // forward to user group by SMS,Dhis2 message, Email
-                messageService.sendMessage( smsCommand.getName(), message, null, receivers, sender, false, false );
-
-                // confirm SMS was received and forwarded completely
-                Set<User> feedbackList = new HashSet<>();
-                feedbackList.add( sender );
-
-                String confirmMessage = smsCommand.getReceivedMessage();
-
-                if ( confirmMessage == null )
-                {
-                    confirmMessage = SMSCommand.ALERT_FEEDBACK;
-                }
-
-                smsMessageSender.sendMessage( smsCommand.getName(), confirmMessage, null, null, feedbackList, true );
-
-                sms.setParsed( true );
-                sms.setStatus( SmsMessageStatus.PROCESSED );
-                incomingSmsService.update( sms );
-            }
-            else if ( users == null || users.size() == 0 )
-            {
-                throw new SMSParserException(
-                    "No user associated with this phone number. Please contact your supervisor." );
-            }
-        }
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/outbound/DefaultOutboundSmsTransportService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/outbound/DefaultOutboundSmsTransportService.java	2015-10-07 14:40:33 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/sms/outbound/DefaultOutboundSmsTransportService.java	2015-11-24 13:14:24 +0000
@@ -42,13 +42,16 @@
 import org.hisp.dhis.sms.config.GateWayFactory;
 import org.hisp.dhis.sms.config.GenericHttpGatewayConfig;
 import org.hisp.dhis.sms.config.SMPPGatewayConfig;
+import org.hisp.dhis.sms.config.SMSGatewayStatus;
 import org.hisp.dhis.sms.config.SmsConfiguration;
 import org.hisp.dhis.sms.config.SmsGatewayConfig;
 import org.smslib.AGateway;
+import org.smslib.AGateway.GatewayStatuses;
 import org.smslib.GatewayException;
 import org.smslib.IInboundMessageNotification;
 import org.smslib.IOutboundMessageNotification;
 import org.smslib.OutboundMessage;
+import org.smslib.OutboundMessage.MessageStatuses;
 import org.smslib.SMSLibException;
 import org.smslib.Service;
 import org.smslib.Message.MessageEncodings;
@@ -60,12 +63,16 @@
     private static final Log log = LogFactory.getLog( DefaultOutboundSmsTransportService.class );
 
     private static final String BULK_GATEWAY = "bulk_gw";
+
     private static final String CLICKATELL_GATEWAY = "clickatell_gw";
+
     private static final String HTTP_GATEWAY = "generic_http_gw";
+
     private static final String MODEM_GATEWAY = "modem_gw";
+
     private static final String SMPP_GATEWAY = "smpp_gw";
-    
-    public static final Map<String, String> GATEWAY_MAP = new HashMap<>(); //TODO fix, poor solution
+
+    public static final Map<String, String> GATEWAY_MAP = new HashMap<>();
 
     private SmsConfiguration config;
 
@@ -81,7 +88,7 @@
     {
         this.smppInboundMessageNotification = smppInboundMessageNotification;
     }
-    
+
     private OutboundSmsService outboundSmsService;
 
     public void setOutboundSmsService( OutboundSmsService outboundSmsService )
@@ -107,7 +114,7 @@
         {
             reloadConfig();
         }
-        
+
         return GATEWAY_MAP;
     }
 
@@ -185,7 +192,6 @@
             message = "sms_unable_or_there_is_no_gateway_service_not_started";
             log.debug( "Sms not enabled or there is no any gateway, won't start service" );
         }
-
     }
 
     @Override
@@ -213,11 +219,11 @@
         else
         {
             GateWayFactory gatewayFactory = new GateWayFactory();
-            
+
             for ( SmsGatewayConfig gatewayConfig : config.getGateways() )
             {
                 try
-                {                    
+                {
                     gateway = gatewayFactory.create( gatewayConfig );
 
                     service.addGateway( gateway );
@@ -409,7 +415,7 @@
         OutboundMessage outboundMessage = new OutboundMessage( recipient, sms.getMessage() );
 
         // Check if text contain any specific unicode character
-        
+
         for ( char each : sms.getMessage().toCharArray() )
         {
             if ( !Character.UnicodeBlock.of( each ).equals( UnicodeBlock.BASIC_LATIN ) )
@@ -467,20 +473,19 @@
         {
             if ( recipients.size() > 1 )
             {
-                // Make sure we delete "tmp" group
                 removeGroup( recipient );
-            }
-            sms.setStatus( OutboundSmsStatus.ERROR );
+            }            
         }
 
-        if ( sent )
+        if ( outboundMessage.getMessageStatus() == MessageStatuses.SENT )
         {
             message = "success";
             sms.setStatus( OutboundSmsStatus.SENT );
         }
         else
         {
-            log.warn( "Message not sent" );
+            log.error( "Message not sent Failure " + outboundMessage.getFailureCause().toString() );
+            log.error( "Message not sent Status " + outboundMessage.getMessageStatus().toString() );
             message = "message_not_sent";
             sms.setStatus( OutboundSmsStatus.ERROR );
         }
@@ -534,4 +539,60 @@
     {
         getService().removeGroup( groupName );
     }
+
+    @Override
+    public SMSServiceStatus getServiceStatusEnum()
+    {
+        ServiceStatus serviceStatus = getService().getServiceStatus();
+
+        if ( serviceStatus == ServiceStatus.STARTED )
+        {
+            return SMSServiceStatus.STARTED;
+        }
+        else if ( serviceStatus == ServiceStatus.STARTING )
+        {
+            return SMSServiceStatus.STARTING;
+        }
+        else if ( serviceStatus == ServiceStatus.STOPPED )
+        {
+            return SMSServiceStatus.STOPPED;
+        }
+        else
+        {
+            return SMSServiceStatus.STOPPING;
+        }
+    }
+
+    @Override
+    public SMSGatewayStatus getGatewayStatus()
+    {
+        if ( getDefaultGateway() == null )
+        {
+            return SMSGatewayStatus.UNDEFINED;
+        }
+
+        AGateway aGateway = getService().getGateway( getDefaultGateway() );
+
+        if ( aGateway.getStatus() == GatewayStatuses.STARTED )
+        {
+            return SMSGatewayStatus.STARTED;
+        }
+
+        if ( aGateway.getStatus() == GatewayStatuses.STOPPED )
+        {
+            return SMSGatewayStatus.STOPPED;
+        }
+
+        if ( aGateway.getStatus() == GatewayStatuses.STARTING )
+        {
+            return SMSGatewayStatus.STARTING;
+        }
+
+        if ( aGateway.getStatus() == GatewayStatuses.STOPPING )
+        {
+            return SMSGatewayStatus.STOPPING;
+        }
+
+        return SMSGatewayStatus.UNDEFINED;
+    }
 }

=== added directory 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/sms'
=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/sms/SmsController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/sms/SmsController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/sms/SmsController.java	2015-11-24 13:14:24 +0000
@@ -0,0 +1,173 @@
+package org.hisp.dhis.webapi.controller.sms;
+
+/*
+ * Copyright (c) 2004-2015, 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.
+ */
+
+/**
+ * Zubair <rajazubair.asghar@xxxxxxxxx>
+ */
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.hisp.dhis.dxf2.webmessage.WebMessageException;
+import org.hisp.dhis.sms.SmsSender;
+import org.hisp.dhis.sms.incoming.IncomingSmsService;
+import org.hisp.dhis.webapi.service.WebMessageService;
+import org.hisp.dhis.webapi.utils.WebMessageUtils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class SmsController
+{
+    public static final String SENDSMS = "/sendSMS";
+    public static final String SENDSMSTOALL = "/sendSMSToAll";
+    public static final String GETAALLINBOUNDSMS = "/getAllInboundSMS";
+    public static final String GETALLOUTBOUNDSMS = "/getAllOutboundSMS";
+    public static final String RECEIVESMS = "/receiveSMS";
+    public static final String GETSMSSTATUS = "/getSMSStatus";
+    public static final String DELETESMS = "/deleteSMS";
+    public static final String DELETEALLSMS = "/deleteAllSMS";
+
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    @Autowired
+    private SmsSender smsSender;
+
+    @Autowired
+    private WebMessageService webMessageService;
+
+    @Autowired
+    private IncomingSmsService incomingSMSService;
+
+    // -------------------------------------------------------------------------
+    // POST
+    // -------------------------------------------------------------------------
+
+    @PreAuthorize( "hasRole('ALL') or hasRole(' F_MOBILE_SENDSMS')" )
+    @RequestMapping( value = SENDSMS, method = RequestMethod.POST )
+    public void sendSMSMessage( @RequestParam String recipient, @RequestParam String message,
+        HttpServletResponse response, HttpServletRequest request )
+            throws WebMessageException
+    {
+        if ( recipient == null || recipient.length() <= 0 )
+        {
+            throw new WebMessageException( WebMessageUtils.conflict( "Recipient must be specified" ) );
+        }
+
+        if ( message == null || message.length() <= 0 )
+        {
+            throw new WebMessageException( WebMessageUtils.conflict( "Message must be specified" ) );
+        }
+
+        String result = smsSender.sendMessage( message, recipient );
+
+        if ( result.equals( "success" ) )
+        {
+            webMessageService.send( WebMessageUtils.ok( "Message Sent" ), response, request );
+        }
+        else
+        {
+            throw new WebMessageException( WebMessageUtils.error( "Message seding failed" ) );
+        }
+    }
+
+    @PreAuthorize( "hasRole('ALL') or hasRole(' F_MOBILE_SENDSMS')" )
+    @RequestMapping( value = SENDSMS, method = RequestMethod.POST, consumes = "application/json" )
+    public void sendSMSMessage( @RequestBody Map<String, Object> jsonMessage, HttpServletResponse response,
+        HttpServletRequest request )
+            throws WebMessageException
+    {
+        if ( jsonMessage == null )
+        {
+            throw new WebMessageException( WebMessageUtils.conflict( "Request body must be specified" ) );
+        }
+
+        String result = smsSender.sendMessage( jsonMessage.get( "message" ).toString(),
+            jsonMessage.get( "recipient" ).toString() );
+
+        if ( result.equals( "success" ) )
+        {
+            webMessageService.send( WebMessageUtils.ok( "Message Sent" ), response, request );
+        }
+        else
+        {
+            throw new WebMessageException( WebMessageUtils.error( "Message seding failed" ) );
+        }
+    }
+
+    @RequestMapping( value = RECEIVESMS, method = RequestMethod.POST )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_MOBILE_SETTINGS')" )
+    public void receiveSMSMessage( @RequestParam String originator,
+        @RequestParam( required = false ) String received_time, @RequestParam String message,
+        @RequestParam( defaultValue = "Unknown", required = false ) String gateway, HttpServletRequest request,
+        HttpServletResponse response)
+            throws WebMessageException
+    {
+        if ( originator == null || originator.length() <= 0 )
+        {
+            throw new WebMessageException( WebMessageUtils.conflict( "originator must be specified" ) );
+        }
+
+        if ( message == null || message.length() <= 0 )
+        {
+            throw new WebMessageException( WebMessageUtils.conflict( "Message must be specified" ) );
+        }
+
+        incomingSMSService.save( message, originator, gateway );
+
+        webMessageService.send( WebMessageUtils.ok( "Received" ), response, request );
+    }
+
+    @RequestMapping( value = RECEIVESMS, method = RequestMethod.POST, consumes = "application/json" )
+    @PreAuthorize( "hasRole('ALL') or hasRole('F_MOBILE_SETTINGS')" )
+    public void receiveSMSMessage( @RequestBody Map<String, Object> jsonMassage, HttpServletRequest request,
+        HttpServletResponse response )
+            throws WebMessageException
+    {
+        if ( jsonMassage == null )
+        {
+            throw new WebMessageException( WebMessageUtils.conflict( "RequestBody must not be empty" ) );
+        }
+
+        incomingSMSService.save( jsonMassage.get( "message" ).toString(), jsonMassage.get( "originator" ).toString(),
+            jsonMassage.get( "gateway" ).toString() );
+
+        webMessageService.send( WebMessageUtils.ok( "Received" ), response, request );
+    }
+}