← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 9042: Added activemq and thread for parsing of incoming sms messages

 

------------------------------------------------------------
revno: 9042
committer: Magnus Korvald <korvald@xxxxxxxxxxx>
branch nick: trunk
timestamp: Thu 2012-11-15 09:44:31 +0100
message:
  Added activemq and thread for parsing of incoming sms messages
added:
  dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSConsumer.java
  dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSPublisher.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/parse/ParserManager.java
  dhis-2/dhis-services/dhis-service-sms/pom.xml
  dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/inbound/HibernateIncomingSmsStore.java
  dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/DefaultParserManager.java
  dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSParserKeyValue.java
  dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/smslib/SmsLibService.java
  dhis-2/dhis-services/dhis-service-sms/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-portal/pom.xml
  dhis-2/dhis-web/dhis-web-sms/src/main/java/org/hisp/dhis/sms/input/SMSInput.java
  dhis-2/dhis-web/dhis-web-sms/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/pom.xml


--
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
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/parse/ParserManager.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/parse/ParserManager.java	2012-08-30 12:47:05 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/sms/parse/ParserManager.java	2012-11-15 08:44:31 +0000
@@ -1,7 +1,9 @@
 package org.hisp.dhis.sms.parse;
 
+import org.hisp.dhis.sms.incoming.IncomingSms;
+
 public interface ParserManager
 {
-    public void parse( String sender, String message )
+    public void parse( IncomingSms sms )
         throws SMSParserException;
 }

=== modified file 'dhis-2/dhis-services/dhis-service-sms/pom.xml'
--- dhis-2/dhis-services/dhis-service-sms/pom.xml	2012-11-14 16:52:37 +0000
+++ dhis-2/dhis-services/dhis-service-sms/pom.xml	2012-11-15 08:44:31 +0000
@@ -32,6 +32,12 @@
     <!-- SMS -->
 
     <dependency>
+      <groupId>org.apache.activemq</groupId>
+      <artifactId>activemq-core</artifactId>
+      <version>5.7.0</version>
+    </dependency>
+
+    <dependency>
       <groupId>org.smslib</groupId>
       <artifactId>smslib</artifactId>
     </dependency>

=== modified file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/inbound/HibernateIncomingSmsStore.java'
--- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/inbound/HibernateIncomingSmsStore.java	2012-07-30 13:09:47 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/inbound/HibernateIncomingSmsStore.java	2012-11-15 08:44:31 +0000
@@ -29,6 +29,8 @@
 
 import java.util.Collection;
 
+import javax.jms.JMSException;
+
 import org.hibernate.Criteria;
 import org.hibernate.Session;
 import org.hibernate.SessionFactory;
@@ -38,6 +40,7 @@
 import org.hisp.dhis.sms.incoming.IncomingSms;
 import org.hisp.dhis.sms.incoming.IncomingSmsStore;
 import org.hisp.dhis.sms.incoming.SmsMessageStatus;
+import org.hisp.dhis.sms.parse.SMSPublisher;
 import org.springframework.transaction.annotation.Transactional;
 
 @Transactional
@@ -49,6 +52,8 @@
     // -------------------------------------------------------------------------
 
     private SessionFactory sessionFactory;
+    
+    private SMSPublisher smsPublisher;
 
     public void setSessionFactory( SessionFactory sessionFactory )
     {
@@ -62,7 +67,16 @@
     @Override
     public int save( IncomingSms sms )
     {
+        try
+        {
+            smsPublisher.putObject( sms );
+        }
+        catch ( JMSException e )
+        {
+            e.printStackTrace();
+        }   
         return (Integer) sessionFactory.getCurrentSession().save( sms );
+        
     }
 
     @Override
@@ -143,5 +157,10 @@
     // {
     // return getSms( null, startDate, endDate );
     // }
+    
+    public void setSmsPublisher( SMSPublisher smsPublisher )
+    {
+        this.smsPublisher = smsPublisher;
+    }
 
 }

=== modified file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/DefaultParserManager.java'
--- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/DefaultParserManager.java	2012-10-18 13:04:28 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/DefaultParserManager.java	2012-11-15 08:44:31 +0000
@@ -1,31 +1,40 @@
 package org.hisp.dhis.sms.parse;
 
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.apache.commons.lang.StringUtils;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 import org.hisp.dhis.dataelement.DataElementCategoryService;
+import org.hisp.dhis.dataset.DataSetService;
 import org.hisp.dhis.datavalue.DataValue;
 import org.hisp.dhis.datavalue.DataValueService;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.period.CalendarPeriodType;
 import org.hisp.dhis.period.Period;
+import org.hisp.dhis.sms.incoming.IncomingSms;
+import org.hisp.dhis.sms.outbound.OutboundSms;
+import org.hisp.dhis.sms.outbound.OutboundSmsService;
 import org.hisp.dhis.smscommand.SMSCode;
 import org.hisp.dhis.smscommand.SMSCommand;
 import org.hisp.dhis.smscommand.SMSCommandService;
 import org.hisp.dhis.user.CurrentUserService;
 import org.hisp.dhis.user.User;
 import org.hisp.dhis.user.UserService;
+import org.joda.time.DateTime;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Required;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * 
  * @author Christian and Magnus
  */
-public class DefaultParserManager
-    implements ParserManager
-{
+public class DefaultParserManager implements ParserManager {
 
     private CurrentUserService currentUserService;
 
@@ -35,168 +44,239 @@
 
     private SMSCommandService smsCommandService;
 
+    private OutboundSmsService outboundSmsService;
+
     @Autowired
     private DataElementCategoryService dataElementCategoryService;
 
-    public void parse( String sender, String message )
-        throws SMSParserException
-    {
-
-        OrganisationUnit orgunit = getOrganisationUnit( sender );
-
-        if ( orgunit == null )
-        {
-            throw new SMSParserException( "No user associated with this phone number. Please contact your supervisor." );
-        }
-
-        if ( message.indexOf( " " ) < 1 )
-        {
-            throw new SMSParserException( "No command in SMS" );
-        }
-
-        String commandString = message.substring( 0, message.indexOf( " " ) );
-        message = message.substring( commandString.length() );
+    @Transactional
+    public void parse(IncomingSms sms) {
+        try {
+            parse(sms.getOriginator(), sms.getText());
+        } catch (SMSParserException e) {
+            sendSMS(e.getMessage(), sms.getOriginator());
+            return;
+        }
+        // sendSMS("Your data report has been received", sms.getOriginator());
+    }
+
+    private void sendSMS(String message, String sender) {
+        if (outboundSmsService != null) {
+            outboundSmsService.sendMessage(new OutboundSms(message, sender), null);
+        } else {
+            // Just for testing
+            System.out.println("\n\n\n SMS: " + message + "\n\n\n");
+        }
+    }
+
+    @Transactional
+    private void parse(String sender, String message) throws SMSParserException {
+
+        if (StringUtils.isEmpty(sender)) {
+            return;
+        }
+
+        User user = getUser(sender);
+
+        if (user == null) {
+            throw new SMSParserException("No user associated with this phone number. Please contact your supervisor.");
+        }
+
+        if (StringUtils.isEmpty(message)) {
+            throw new SMSParserException("No command in SMS");
+        }
+
+        String commandString = message.substring(0, message.indexOf(" "));
+        message = message.substring(commandString.length());
 
         boolean foundCommand = false;
 
-        for ( SMSCommand command : smsCommandService.getSMSCommands() )
-        {
-            if ( command.getName().equalsIgnoreCase( commandString ) )
-            {
+        for (SMSCommand command : smsCommandService.getSMSCommands()) {
+            if (command.getName().equalsIgnoreCase(commandString)) {
                 foundCommand = true;
-                if ( ParserType.KEY_VALUE_PARSER.equals( command.getParserType() ) )
-                {
-                    runKeyValueParser( sender, message, orgunit, command );
+                if (ParserType.KEY_VALUE_PARSER.equals(command.getParserType())) {
+                    runKeyValueParser(sender, message, user, command);
                     break;
                 }
             }
         }
-        if ( !foundCommand )
-        {
-            throw new SMSParserException( "Command '" + commandString + "' does not exist" );
+        if (!foundCommand) {
+            throw new SMSParserException("Command '" + commandString + "' does not exist");
         }
     }
 
-    private void runKeyValueParser( String sender, String message, OrganisationUnit orgunit, SMSCommand command )
-    {
+    private void runKeyValueParser(String sender, String message, User user, SMSCommand command) {
         IParser p = new SMSParserKeyValue();
-        if ( !StringUtils.isBlank( command.getSeparator() ) )
-        {
-            p.setSeparator( command.getSeparator() );
-        }
-
-        Map<String, String> parsedMessage = p.parse( message );
-        if ( parsedMessage.isEmpty() )
-        {
-            throw new SMSParserException( command.getDefaultMessage() );
-        }
-
-        for ( SMSCode code : command.getCodes() )
-        {
-            if ( parsedMessage.containsKey( code.getCode().toUpperCase() ) )
-            {
-                storeDataValue( sender, orgunit, parsedMessage, code );
-            }
-        }
-    }
-
-    private void storeDataValue( String sender, OrganisationUnit orgunit, Map<String, String> parsedMessage,
-        SMSCode code )
-    {
+        if (!StringUtils.isBlank(command.getSeparator())) {
+            p.setSeparator(command.getSeparator());
+        }
+
+        Map<String, String> parsedMessage = p.parse(message);
+
+        Date date = lookForDate(message);
+
+        boolean valueStored = false;
+
+        for (SMSCode code : command.getCodes()) {
+            if (parsedMessage.containsKey(code.getCode().toUpperCase())) {
+                storeDataValue(sender, user.getOrganisationUnit(), parsedMessage, code, date);
+                valueStored = true;
+            }
+        }
+
+        if (parsedMessage.isEmpty() || !valueStored) {
+            if (StringUtils.isEmpty(command.getDefaultMessage())) {
+                throw new SMSParserException("No values reported for command '" + command.getName() + "'");
+            } else {
+                throw new SMSParserException(command.getDefaultMessage());
+            }
+        }
+
+        sendSuccessFeedback(sender, command, parsedMessage);
+
+    }
+
+    protected void sendSuccessFeedback(String sender, SMSCommand command, Map<String, String> parsedMessage) {
+        String reportBack = "Your report included the following values: ";
+        String notInReport = "Your report did not include values for: ";
+        boolean missingElements = false;
+        for (SMSCode code : command.getCodes()) {
+            if (parsedMessage.containsKey(code.getCode().toUpperCase())) {
+                reportBack += code.getCode() + "=" + parsedMessage.get(code.getCode().toUpperCase()) + " ";
+            } else {
+                notInReport += code.getCode() + ",";
+                missingElements = true;
+            }
+        }
+
+        notInReport = notInReport.substring(0,notInReport.length() - 1);
+
+        if (missingElements) {
+            sendSMS(reportBack + notInReport, sender);
+        } else {
+            sendSMS(reportBack, sender);
+        }
+    }
+
+    private Date lookForDate(String message) {
+        if (!message.contains(" ")) {
+            return null;
+        }
+        Date date = null;
+        String dateString = message.trim().split(" ")[0];
+        SimpleDateFormat format = new SimpleDateFormat("ddMM");
+
+        try {
+            Calendar cal = Calendar.getInstance();
+            date = format.parse(dateString);
+            cal.setTime(date);
+            int year = Calendar.getInstance().get(Calendar.YEAR);
+            int month = Calendar.getInstance().get(Calendar.MONTH);
+            if (cal.get(Calendar.MONTH) < month) {
+                cal.set(Calendar.YEAR, year);
+            } else {
+                cal.set(Calendar.YEAR, year - 1);
+            }
+            date = cal.getTime();
+            System.out.println("\nFound date in SMS:" + date.toString() + "\n");
+        } catch (Exception e) {
+            // no date found
+            System.out.println("\nNo date found in SMS \n");
+        }
+        return date;
+    }
+
+    private void storeDataValue(String sender, OrganisationUnit orgunit, Map<String, String> parsedMessage,
+            SMSCode code, Date date) {
         String upperCaseCode = code.getCode().toUpperCase();
 
         String storedBy = currentUserService.getCurrentUsername();
 
-        if ( StringUtils.isBlank( storedBy ) )
-        {
+        if (StringUtils.isBlank(storedBy)) {
             storedBy = "[unknown] from [" + sender + "]";
         }
 
         DataElementCategoryOptionCombo optionCombo = null;
-        optionCombo = dataElementCategoryService.getDataElementCategoryOptionCombo( code.getOptionId() );
+        optionCombo = dataElementCategoryService.getDataElementCategoryOptionCombo(code.getOptionId());
 
         Period period = code.getDataElement().getPeriodType().createPeriod();
         CalendarPeriodType cpt = (CalendarPeriodType) period.getPeriodType();
-        period = cpt.getPreviousPeriod( period );
-
-        DataValue dv = dataValueService.getDataValue( orgunit, code.getDataElement(), period, optionCombo );
-
-        if ( dv == null )
-        {
+        period = cpt.getPreviousPeriod(period);
+
+        if (date != null) {
+            period = cpt.createPeriod(date);
+        }
+
+        DataValue dv = dataValueService.getDataValue(orgunit, code.getDataElement(), period, optionCombo);
+
+        if (dv == null) {
             // New data element
             DataValue dataVal = new DataValue();
-            dataVal.setOptionCombo( optionCombo );
-            dataVal.setSource( orgunit );
-            dataVal.setDataElement( code.getDataElement() );
-            dataVal.setPeriod( period );
-            dataVal.setComment( "" );
-            dataVal.setTimestamp( new java.util.Date() );
-            dataVal.setStoredBy( storedBy );
-            dataVal.setValue( parsedMessage.get( upperCaseCode ) );
-            dataValueService.addDataValue( dataVal );
-        }
-        else
-        {
+            dataVal.setOptionCombo(optionCombo);
+            dataVal.setSource(orgunit);
+            dataVal.setDataElement(code.getDataElement());
+            dataVal.setPeriod(period);
+            dataVal.setComment("");
+            dataVal.setTimestamp(new java.util.Date());
+            dataVal.setStoredBy(storedBy);
+            dataVal.setValue(parsedMessage.get(upperCaseCode));
+            dataValueService.addDataValue(dataVal);
+        } else {
             // Update data element
-            dv.setValue( parsedMessage.get( upperCaseCode ) );
-            dv.setOptionCombo( optionCombo );
-            dataValueService.updateDataValue( dv );
+            dv.setValue(parsedMessage.get(upperCaseCode));
+            dv.setOptionCombo(optionCombo);
+            dataValueService.updateDataValue(dv);
         }
+
     }
 
-    private OrganisationUnit getOrganisationUnit( String sender )
-    {
+    private User getUser(String sender) {
         OrganisationUnit orgunit = null;
-        for ( User user : userService.getUsersByPhoneNumber( sender ) )
-        {
-            OrganisationUnit ou = user.getOrganisationUnit();
+        User user = null;
+        for (User u : userService.getUsersByPhoneNumber(sender)) {
+            OrganisationUnit ou = u.getOrganisationUnit();
 
             // Might be undefined if the user has more than one org.units
             // "attached"
-            if ( orgunit == null )
-            {
+            if (orgunit == null) {
                 orgunit = ou;
-            }
-            else if ( orgunit.getId() == ou.getId() )
-            {
+            } else if (orgunit.getId() == ou.getId()) {
                 // same orgunit, no problem...
-            }
-            else
-            {
+            } else {
                 throw new SMSParserException(
-                    "User is associated with more than one orgunit. Please contact your supervisor." );
+                        "User is associated with more than one orgunit. Please contact your supervisor.");
             }
+            user = u;
         }
-        return orgunit;
+        return user;
     }
 
-    public void setDataElementCategoryService( DataElementCategoryService dataElementCategoryService )
-    {
+    public void setDataElementCategoryService(DataElementCategoryService dataElementCategoryService) {
         this.dataElementCategoryService = dataElementCategoryService;
     }
 
     @Required
-    public void setSmsCommandService( SMSCommandService smsCommandService )
-    {
+    public void setSmsCommandService(SMSCommandService smsCommandService) {
         this.smsCommandService = smsCommandService;
     }
 
     @Required
-    public void setCurrentUserService( CurrentUserService currentUserService )
-    {
+    public void setCurrentUserService(CurrentUserService currentUserService) {
         this.currentUserService = currentUserService;
     }
 
     @Required
-    public void setDataValueService( DataValueService dataValueService )
-    {
+    public void setDataValueService(DataValueService dataValueService) {
         this.dataValueService = dataValueService;
     }
 
     @Required
-    public void setUserService( UserService userService )
-    {
+    public void setUserService(UserService userService) {
         this.userService = userService;
     }
 
+    public void setOutboundSmsService(OutboundSmsService outboundSmsService) {
+        this.outboundSmsService = outboundSmsService;
+    }
+
 }

=== added file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSConsumer.java'
--- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSConsumer.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSConsumer.java	2012-11-15 08:44:31 +0000
@@ -0,0 +1,125 @@
+package org.hisp.dhis.sms.parse;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.activemq.broker.BrokerService;
+import org.hisp.dhis.sms.incoming.IncomingSms;
+import org.springframework.beans.factory.InitializingBean;
+
+// IEatSMS
+public class SMSConsumer implements InitializingBean {
+
+    private ParserManager parserManager;
+
+    private ConnectionFactory factory;
+
+    private String brokerURL;
+
+    private String queue;
+
+    SMSConsumerThread thread;
+
+    public void start() {
+        if (thread == null) {
+            thread = new SMSConsumerThread();
+            thread.start();
+        }
+    }
+
+    public void setBrokerURL(String brokerURL) {
+        this.brokerURL = brokerURL;
+    }
+
+    public void setQueue(String queue) {
+        this.queue = queue;
+    }
+
+    public void setFactory(ConnectionFactory factory) {
+        this.factory = factory;
+    }
+
+    public void setParserManager(ParserManager parserManager) {
+        this.parserManager = parserManager;
+    }
+
+    public void stop() {
+        thread.stopFetching();
+        thread = null;
+    }
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        BrokerService broker = new BrokerService();
+        broker.setPersistent(true);
+        broker.addConnector(brokerURL);
+        broker.start();
+    }
+
+    private class SMSConsumerThread extends Thread {
+        private boolean stop;
+
+        public void run() {
+            while (!stop) {
+                try{
+                    fetchAndParseSMS();
+                }catch(Exception e){
+                    // ignore 
+                }
+                try {
+                    // Maybe we should speed up on successful receive?
+                    Thread.sleep(3000);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        /* Returns true when a message is found */
+        private void fetchAndParseSMS() {
+
+            try {
+                Connection connection = factory.createConnection();
+                connection.start();
+                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+                Queue destination = session.createQueue(queue);
+                MessageConsumer c = session.createConsumer(destination);
+
+                // Wait the maximum time of one second
+                Message m = c.receive(1000);
+                while (m != null) {
+                    if (m instanceof ObjectMessage) {
+                        ObjectMessage objMessage = (ObjectMessage) m;
+                        if (objMessage.getObject() instanceof IncomingSms) {
+                            IncomingSms sms = (IncomingSms) objMessage.getObject();
+                            parserManager.parse(sms);
+                        }
+                    }
+                    m = c.receive(1000);
+                }
+
+                connection.close();
+                session.close();
+
+
+            } catch (JMSException e) {
+                e.printStackTrace();
+
+            }
+        }
+
+        public void stopFetching() {
+            this.stop = true;
+        }
+
+    }
+
+}

=== modified file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSParserKeyValue.java'
--- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSParserKeyValue.java	2012-08-30 12:47:05 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSParserKeyValue.java	2012-11-15 08:44:31 +0000
@@ -15,8 +15,10 @@
 public class SMSParserKeyValue
     implements IParser
 {
-  //= "([a-zA-Z]+)\\s*(\\d+)";
-    private String defaultPattern = "(\\w+)\\s*\\*\\s*([\\w ]+)\\s*(\\*|$)*\\s*";
+    // "(\\w+)\\s*\\*\\s*([\\w ]+)\\s*(\\*|$)*\\s*";
+    // = "([a-zA-Z]+)\\s*(\\d+)";
+    private String defaultPattern = "([a-zA-Z]+)\\s*(\\d+)";
+
     private Pattern pattern = Pattern.compile( defaultPattern );
 
     @Override
@@ -42,7 +44,8 @@
 
     public void setSeparator( String separator )
     {
-        String x = "(\\w+)\\s*" + separator.trim()  + "\\s*(\\d+)";
+        String x = null;
+        x = "(\\w+)\\s*\\" + separator.trim() + "\\s*([\\w ]+)\\s*(\\" + separator.trim() + "|$)*\\s*";
         pattern = Pattern.compile( x );
     }
 

=== added file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSPublisher.java'
--- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSPublisher.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/SMSPublisher.java	2012-11-15 08:44:31 +0000
@@ -0,0 +1,44 @@
+package org.hisp.dhis.sms.parse;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.hisp.dhis.sms.incoming.IncomingSms;
+
+public class SMSPublisher {
+    private ConnectionFactory factory;
+
+    private String queue;
+
+    public void putObject(IncomingSms sms) throws JMSException {
+        Connection connection = factory.createConnection();
+        connection.start();
+        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+        ObjectMessage objMessage = session.createObjectMessage();
+        objMessage.setObject(sms);
+
+        Queue destination = session.createQueue(queue);
+        MessageProducer producer = session.createProducer(destination);
+
+        producer.send(objMessage);
+
+        session.close();
+        connection.close();
+    }
+
+    public void setFactory(ConnectionFactory factory) {
+        this.factory = factory;
+    }
+
+    public void setQueue(String queue) {
+        this.queue = queue;
+    }
+
+}

=== modified file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/smslib/SmsLibService.java'
--- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/smslib/SmsLibService.java	2012-10-22 08:51:28 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/smslib/SmsLibService.java	2012-11-15 08:44:31 +0000
@@ -46,6 +46,8 @@
 import org.hisp.dhis.sms.outbound.OutboundSmsStatus;
 import org.hisp.dhis.sms.outbound.OutboundSmsStore;
 import org.hisp.dhis.sms.outbound.OutboundSmsTransportService;
+import org.hisp.dhis.sms.parse.SMSConsumer;
+import org.hisp.dhis.sms.parse.SMSPublisher;
 import org.smslib.AGateway;
 import org.smslib.GatewayException;
 import org.smslib.IInboundMessageNotification;
@@ -86,10 +88,17 @@
 
     private OutboundSmsStore outboundSmsStore;
 
+    private SMSConsumer smsConsumer;
+
     // -------------------------------------------------------------------------
     // Implementation methods
     // -------------------------------------------------------------------------
 
+    public void setSmsConsumer( SMSConsumer smsConsumer )
+    {
+        this.smsConsumer = smsConsumer;
+    }
+
     @Override
     public boolean isEnabled()
     {
@@ -99,7 +108,7 @@
     @Override
     public Map<String, String> getGatewayMap()
     {
-        if( gatewayMap == null || gatewayMap.isEmpty())
+        if ( gatewayMap == null || gatewayMap.isEmpty() )
         {
             reloadConfig();
         }
@@ -334,6 +343,16 @@
                     getService().setInboundMessageNotification( smppInboundMessageNotification );
                 }
 
+                try
+                {  
+                    smsConsumer.start();
+                }
+                catch ( Exception e1 )
+                {
+                    message = "Unable to start smsConsumer service " + e1.getMessage();
+                    log.warn( "Unable to start smsConsumer service ", e1 );
+                }
+
             }
             catch ( SMSLibException e )
             {
@@ -366,6 +385,7 @@
         try
         {
             getService().stopService();
+            smsConsumer.stop();
         }
         catch ( SMSLibException e )
         {
@@ -493,4 +513,5 @@
         
         outboundSmsStore.delete( sms );   
     }
+
 }

=== modified file 'dhis-2/dhis-services/dhis-service-sms/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-sms/src/main/resources/META-INF/dhis/beans.xml	2012-09-14 08:13:33 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/resources/META-INF/dhis/beans.xml	2012-11-15 08:44:31 +0000
@@ -7,13 +7,52 @@
 
   <!-- Outbound SMS service -->
 
+<!-- 
+  <bean id="fetchAndParseSMSJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
+    <property name="targetObject" ref="smsConsumer" />
+    <property name="targetMethod" value="fetchAndParseSMS" />
+  </bean>
+
+  <bean id="fetchAndParseSMSTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
+    <property name="jobDetail" ref="fetchAndParseSMSJobDetail" />
+    <property name="repeatInterval" value="3000" />
+  </bean>
+
+  <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
+    <property name="triggers">
+      <list>
+        <ref bean="fetchAndParseSMSTrigger" />
+      </list>
+    </property>
+  </bean>
+
+ -->
+  <bean id="smsPublisher" class="org.hisp.dhis.sms.parse.SMSPublisher">
+    <property name="factory" ref="jmsFactory" />
+    <property name="queue" value="TEST.QUEUE" />
+  </bean>
+
+  <bean id="smsConsumer" class="org.hisp.dhis.sms.parse.SMSConsumer">
+    <property name="factory" ref="jmsFactory" />
+    <property name="queue" value="TEST.QUEUE" />
+    <property name="brokerURL" value="vm://localhost:61616" />
+    <property name="parserManager" ref="org.hisp.dhis.sms.parse.DefaultParserManager" />
+  </bean>
+
+  <bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
+    <property name="brokerURL">
+      <value>vm://localhost:61616</value>
+    </property>
+  </bean>
+
+
   <bean id="outboundSmsStore" class="org.hisp.dhis.sms.outbound.HibernateOutboundSmsStore">
     <property name="sessionFactory" ref="sessionFactory" />
     <property name="jdbcTemplate" ref="jdbcTemplate" />
   </bean>
 
   <bean id="org.hisp.dhis.sms.outbound.OutboundSmsService" class="org.hisp.dhis.sms.outbound.OutboundSmsServiceImpl">
-  	<property name="outboundSmsStore" ref="outboundSmsStore" />
+    <property name="outboundSmsStore" ref="outboundSmsStore" />
   </bean>
 
   <!-- Only for testing! OutboundSmsService stub just logging invocations, replacing the default one or use as the OutboundSmsTransportService.. -->
@@ -21,7 +60,8 @@
 
   <bean id="smsLibService" class="org.hisp.dhis.sms.smslib.SmsLibService">
     <property name="smppInboundMessageNotification" ref="org.hisp.dhis.sms.incoming.SMPPInboundNotification" />
-	<property name="outboundSmsStore" ref="outboundSmsStore" />
+    <property name="outboundSmsStore" ref="outboundSmsStore" />
+    <property name="smsConsumer" ref="smsConsumer" />
   </bean>
 
   <bean id="org.hisp.dhis.sms.incoming.SMPPInboundNotification" class="org.hisp.dhis.sms.incoming.SMPPInboundNotification">
@@ -38,18 +78,20 @@
 
   <bean id="org.hisp.dhis.sms.incoming.IncomingSmsStore" class="org.hisp.dhis.sms.inbound.HibernateIncomingSmsStore">
     <property name="sessionFactory" ref="sessionFactory" />
+    <property name="smsPublisher" ref="smsPublisher" />
   </bean>
 
   <bean id="org.hisp.dhis.sms.incoming.IncomingSmsService" class="org.hisp.dhis.sms.inbound.DefaultInboundSmsService">
     <property name="incomingSmsStore" ref="org.hisp.dhis.sms.incoming.IncomingSmsStore" />
   </bean>
 
-  <bean id="org.hisp.dhis.sms.parse.DefaultParserManager" class="org.hisp.dhis.sms.parse.DefaultParserManager">
+  <bean id="org.hisp.dhis.sms.parse.DefaultParserManager" class="org.hisp.dhis.sms.parse.DefaultParserManager"
+    depends-on="org.hisp.dhis.user.UserService">
     <property name="userService" ref="org.hisp.dhis.user.UserService" />
     <property name="smsCommandService" ref="smsCommandService" />
     <property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
     <property name="dataValueService" ref="org.hisp.dhis.datavalue.DataValueService" />
+    <property name="outboundSmsService" ref="org.hisp.dhis.sms.outbound.OutboundSmsService" />  
   </bean>
 
-
 </beans>

=== modified file 'dhis-2/dhis-web/dhis-web-portal/pom.xml'
--- dhis-2/dhis-web/dhis-web-portal/pom.xml	2012-11-14 16:52:37 +0000
+++ dhis-2/dhis-web/dhis-web-portal/pom.xml	2012-11-15 08:44:31 +0000
@@ -41,7 +41,12 @@
     </dependency>
 
     <!-- Web maintenance modules -->
-
+    <dependency>
+      <groupId>org.hisp.dhis</groupId>
+      <artifactId>dhis-web-sms</artifactId>
+        <version>${project.version}</version>
+      <type>war</type>
+    </dependency>	
     <dependency>
       <groupId>org.hisp.dhis</groupId>
       <artifactId>dhis-web-maintenance-datadictionary</artifactId>

=== modified file 'dhis-2/dhis-web/dhis-web-sms/src/main/java/org/hisp/dhis/sms/input/SMSInput.java'
--- dhis-2/dhis-web/dhis-web-sms/src/main/java/org/hisp/dhis/sms/input/SMSInput.java	2012-08-30 12:47:05 +0000
+++ dhis-2/dhis-web/dhis-web-sms/src/main/java/org/hisp/dhis/sms/input/SMSInput.java	2012-11-15 08:44:31 +0000
@@ -7,10 +7,8 @@
 import org.hisp.dhis.sms.incoming.IncomingSmsStore;
 import org.hisp.dhis.sms.incoming.SmsMessageEncoding;
 import org.hisp.dhis.sms.incoming.SmsMessageStatus;
-import org.hisp.dhis.sms.outbound.OutboundSms;
 import org.hisp.dhis.sms.outbound.OutboundSmsService;
 import org.hisp.dhis.sms.parse.ParserManager;
-import org.hisp.dhis.sms.parse.SMSParserException;
 
 import com.opensymphony.xwork2.Action;
 
@@ -22,8 +20,6 @@
     implements Action
 {
 
-    private ParserManager smsParserManager;
-
     private String msisdn, sender, message, dca, reffering_batch, network_id, concat_reference, concat_num_segments,
         concat_seq_num, received_time;
 
@@ -35,13 +31,6 @@
 
     private IncomingSmsStore smsStore;
 
-    private OutboundSmsService outboundSmsService;
-
-    public void setOutboundSmsService( OutboundSmsService outboundSmsService )
-    {
-        this.outboundSmsService = outboundSmsService;
-    }
-
     public SMSInput()
     {
     }
@@ -78,34 +67,9 @@
 
         smsStore.save( sms );
 
-        try
-        {
-            smsParserManager.parse( sender, message );
-        }
-        catch ( SMSParserException e )
-        {
-            sendSMS( e.getMessage() );
-            return ERROR;
-        }
-
-        sendSMS( "SMS successfully received" );
-        // TODO DataEntry stuff
         return SUCCESS;
     }
 
-    private void sendSMS( String message )
-    {
-        if ( outboundSmsService != null )
-        {
-            outboundSmsService.sendMessage( new OutboundSms( message, sender ), null );
-        }
-        else
-        {
-            // Just for testing
-            System.out.println( "\n\n\n SMS: " + message + "\n\n\n" );
-        }
-    }
-
     public void setSmsStore( IncomingSmsStore smsStore )
     {
         System.out.println( "Setting SMSStore: " + smsStore );
@@ -242,9 +206,5 @@
         this.source_id = source_id;
     }
 
-    public void setSmsParserManager( ParserManager smsParserManager )
-    {
-        this.smsParserManager = smsParserManager;
-    }
 
 }

=== modified file 'dhis-2/dhis-web/dhis-web-sms/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-sms/src/main/resources/META-INF/dhis/beans.xml	2012-08-30 12:47:05 +0000
+++ dhis-2/dhis-web/dhis-web-sms/src/main/resources/META-INF/dhis/beans.xml	2012-11-15 08:44:31 +0000
@@ -6,9 +6,6 @@
 	
     <bean id="org.hisp.dhis.sms.input.SMSInput" class="org.hisp.dhis.sms.input.SMSInput">
         <property name="smsStore" ref="org.hisp.dhis.sms.incoming.IncomingSmsStore"/>
-        <property name="smsParserManager" ref="org.hisp.dhis.sms.parse.DefaultParserManager" />
     </bean>
-    
- 
-	
+    	
 </beans>

=== modified file 'dhis-2/dhis-web/pom.xml'
--- dhis-2/dhis-web/pom.xml	2012-11-14 16:52:37 +0000
+++ dhis-2/dhis-web/pom.xml	2012-11-15 08:44:31 +0000
@@ -28,6 +28,7 @@
     <module>dhis-web-light</module>
     <module>dhis-web-mobile</module>
     <module>dhis-web-portal</module>
+    <module>dhis-web-sms</module>
   </modules>
   <build>
     <plugins>