← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 10162: [mobile] improve J2MEDataEntryParser

 

------------------------------------------------------------
revno: 10162
committer: Long <Long@Long-Laptop>
branch nick: dhis2
timestamp: Wed 2013-03-13 13:43:01 +0700
message:
  [mobile] improve J2MEDataEntryParser
modified:
  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/J2MEDataEntryParser.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
=== 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	2013-03-09 12:23:42 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/DefaultParserManager.java	2013-03-13 06:43:01 +0000
@@ -1,5 +1,6 @@
 package org.hisp.dhis.sms.parse;
 
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
@@ -7,7 +8,6 @@
 import java.util.Date;
 import java.util.Iterator;
 import java.util.Map;
-
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -22,7 +22,13 @@
 import org.hisp.dhis.datavalue.DataValueService;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.period.CalendarPeriodType;
+import org.hisp.dhis.period.DailyPeriodType;
+import org.hisp.dhis.period.MonthlyPeriodType;
 import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodType;
+import org.hisp.dhis.period.QuarterlyPeriodType;
+import org.hisp.dhis.period.WeeklyPeriodType;
+import org.hisp.dhis.period.YearlyPeriodType;
 import org.hisp.dhis.sms.incoming.IncomingSms;
 import org.hisp.dhis.sms.outbound.OutboundSms;
 import org.hisp.dhis.sms.outbound.OutboundSmsService;
@@ -99,7 +105,6 @@
         }
 
         Collection<OrganisationUnit> orgUnits = getOrganisationUnitsByPhoneNumber( sender );
-
         if ( orgUnits == null || orgUnits.size() == 0 )
         {
             throw new SMSParserException( "No user associated with this phone number. Please contact your supervisor." );
@@ -125,6 +130,11 @@
                     runKeyValueParser( sender, message, orgUnits, command );
                     break;
                 }
+                else
+                {
+                    runJ2MEParser( sender, message, orgUnits, command );
+                    break;
+                }
             }
         }
         if ( !foundCommand )
@@ -137,7 +147,6 @@
     {
         Collection<OrganisationUnit> orgUnits = new ArrayList<OrganisationUnit>();
         Collection<User> users = userService.getUsersByPhoneNumber( sender );
-
         for ( User u : users )
         {
             if ( u.getOrganisationUnits() != null )
@@ -516,6 +525,267 @@
         }
         return user;
     }
+    
+    //Run the J2ME parser for mobile
+    
+    private void runJ2MEParser( String sender, String message, Collection<OrganisationUnit> orgUnits, SMSCommand command )
+    {
+        J2MEDataEntryParser j2meParser = new J2MEDataEntryParser();
+        j2meParser.setSmsCommand( command );
+        message = message.trim();
+
+        if ( !StringUtils.isBlank( command.getSeparator() ) )
+        {
+            j2meParser.setSeparator( command.getSeparator() );
+        }
+        String token[] = message.split( "!" );
+        Period period = getPeriod( token[0].trim(), command.getDataset().getPeriodType() );
+        Map<String, String> parsedMessage = j2meParser.parse( token[1] );
+        OrganisationUnit orgUnit = selectOrganisationUnit( orgUnits, parsedMessage );
+
+        boolean valueStored = false;
+        for ( SMSCode code : command.getCodes() )
+        {
+            if ( parsedMessage.containsKey( code.getCode().toUpperCase() ) )
+            {
+                storeDataValue( sender, orgUnit, parsedMessage, code, command, period, command.getDataset(),
+                    formIsComplete( command, parsedMessage ) );
+                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() );
+            }
+        }
+
+        registerCompleteDataSet( command.getDataset(), period, orgUnit, "mobile" );
+
+        sendSuccessFeedback( sender, command, parsedMessage, period, orgUnit );
+
+    }
+
+    private void sendSuccessFeedback( String sender, SMSCommand command, Map<String, String> parsedMessage,
+        Period period, OrganisationUnit orgUnit )
+    {
+        String reportBack = "Thank you! Values entered: ";
+        String notInReport = "Missing values for: ";
+        boolean missingElements = false;
+
+        for ( SMSCode code : command.getCodes() )
+        {
+
+            DataElementCategoryOptionCombo optionCombo = dataElementCategoryService
+                .getDataElementCategoryOptionCombo( code.getOptionId() );
+
+            DataValue dv = dataValueService.getDataValue( orgUnit, code.getDataElement(), period, optionCombo );
+
+            if ( dv == null && !StringUtils.isEmpty( code.getCode() ) )
+            {
+                notInReport += code.getCode() + ",";
+                missingElements = true;
+            }
+            else if ( dv != null )
+            {
+                String value = dv.getValue();
+                if ( StringUtils.equals( dv.getDataElement().getType(), DataElement.VALUE_TYPE_BOOL ) )
+                {
+                    if ( "true".equals( value ) )
+                    {
+                        value = "Yes";
+                    }
+                    else if ( "false".equals( value ) )
+                    {
+                        value = "No";
+                    }
+                }
+                reportBack += code.getCode() + "=" + value + " ";
+            }
+        }
+
+        notInReport = notInReport.substring( 0, notInReport.length() - 1 );
+
+        if ( missingElements )
+        {
+            sendSMS( reportBack + notInReport, sender );
+        }
+        else
+        {
+            sendSMS( reportBack, sender );
+        }
+
+    }
+
+    private void storeDataValue( String sender, OrganisationUnit orgUnit, Map<String, String> parsedMessage,
+        SMSCode code, SMSCommand command, Period period, DataSet dataset, boolean formIsComplete )
+    {
+        String upperCaseCode = code.getCode().toUpperCase();
+
+        String storedBy = getUser( sender ).getUsername();
+
+        if ( StringUtils.isBlank( storedBy ) )
+        {
+            storedBy = "[unknown] from [" + sender + "]";
+        }
+
+        DataElementCategoryOptionCombo optionCombo = dataElementCategoryService.getDataElementCategoryOptionCombo( code
+            .getOptionId() );
+
+        DataValue dv = dataValueService.getDataValue( orgUnit, code.getDataElement(), period, optionCombo );
+
+        String value = parsedMessage.get( upperCaseCode );
+        if ( !StringUtils.isEmpty( value ) )
+        {
+            boolean newDataValue = false;
+            if ( dv == null )
+            {
+                dv = new DataValue();
+                dv.setOptionCombo( optionCombo );
+                dv.setSource( orgUnit );
+                dv.setDataElement( code.getDataElement() );
+                dv.setPeriod( period );
+                dv.setComment( "" );
+                newDataValue = true;
+            }
+
+            if ( StringUtils.equals( dv.getDataElement().getType(), DataElement.VALUE_TYPE_BOOL ) )
+            {
+                if ( "Y".equals( value.toUpperCase() ) || "YES".equals( value.toUpperCase() ) )
+                {
+                    value = "true";
+                }
+                else if ( "N".equals( value.toUpperCase() ) || "NO".equals( value.toUpperCase() ) )
+                {
+                    value = "false";
+                }
+            }
+
+            dv.setValue( value );
+            dv.setTimestamp( new java.util.Date() );
+            dv.setStoredBy( storedBy );
+
+            if ( newDataValue )
+            {
+                dataValueService.addDataValue( dv );
+            }
+            else
+            {
+                dataValueService.updateDataValue( dv );
+            }
+        }
+
+    }
+
+    public static Period getPeriod( String periodName, PeriodType periodType )
+        throws IllegalArgumentException
+    {
+
+        if ( periodType instanceof DailyPeriodType )
+        {
+            String pattern = "yyyy-MM-dd";
+            SimpleDateFormat formatter = new SimpleDateFormat( pattern );
+            Date date;
+            try
+            {
+                date = formatter.parse( periodName );
+            }
+            catch ( ParseException e )
+            {
+                throw new IllegalArgumentException( "Couldn't make a period of type " + periodType.getName()
+                    + " and name " + periodName, e );
+            }
+            return periodType.createPeriod( date );
+
+        }
+
+        if ( periodType instanceof WeeklyPeriodType )
+        {
+            String pattern = "yyyy-MM-dd";
+            SimpleDateFormat formatter = new SimpleDateFormat( pattern );
+            Date date;
+            try
+            {
+                date = formatter.parse( periodName );
+            }
+            catch ( ParseException e )
+            {
+                throw new IllegalArgumentException( "Couldn't make a period of type " + periodType.getName()
+                    + " and name " + periodName, e );
+            }
+            return periodType.createPeriod( date );
+        }
+
+        if ( periodType instanceof MonthlyPeriodType )
+        {
+            int dashIndex = periodName.indexOf( '-' );
+
+            if ( dashIndex < 0 )
+            {
+                return null;
+            }
+
+            int month = Integer.parseInt( periodName.substring( 0, dashIndex ) );
+            int year = Integer.parseInt( periodName.substring( dashIndex + 1, periodName.length() ) );
+
+            Calendar cal = Calendar.getInstance();
+            cal.set( Calendar.YEAR, year );
+            cal.set( Calendar.MONTH, month );
+
+            return periodType.createPeriod( cal.getTime() );
+        }
+
+        if ( periodType instanceof YearlyPeriodType )
+        {
+            Calendar cal = Calendar.getInstance();
+            cal.set( Calendar.YEAR, Integer.parseInt( periodName ) );
+
+            return periodType.createPeriod( cal.getTime() );
+        }
+
+        if ( periodType instanceof QuarterlyPeriodType )
+        {
+            Calendar cal = Calendar.getInstance();
+
+            int month = 0;
+            if ( periodName.substring( 0, periodName.indexOf( " " ) ).equals( "Jan" ) )
+            {
+                month = 1;
+            }
+            else if ( periodName.substring( 0, periodName.indexOf( " " ) ).equals( "Apr" ) )
+            {
+                month = 4;
+            }
+            else if ( periodName.substring( 0, periodName.indexOf( " " ) ).equals( "Jul" ) )
+            {
+                month = 6;
+            }
+            else if ( periodName.substring( 0, periodName.indexOf( " " ) ).equals( "Oct" ) )
+            {
+                month = 10;
+            }
+
+            int year = Integer.parseInt( periodName.substring( periodName.lastIndexOf( " " ) + 1 ) );
+
+            cal.set( Calendar.MONTH, month );
+            cal.set( Calendar.YEAR, year );
+
+            if ( month != 0 )
+            {
+                return periodType.createPeriod( cal.getTime() );
+            }
+
+        }
+
+        throw new IllegalArgumentException( "Couldn't make a period of type " + periodType.getName() + " and name "
+            + periodName );
+    }
 
     public void setDataElementCategoryService( DataElementCategoryService dataElementCategoryService )
     {

=== modified file 'dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/J2MEDataEntryParser.java'
--- dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/J2MEDataEntryParser.java	2013-01-22 08:08:14 +0000
+++ dhis-2/dhis-services/dhis-service-sms/src/main/java/org/hisp/dhis/sms/parse/J2MEDataEntryParser.java	2013-03-13 06:43:01 +0000
@@ -1,24 +1,53 @@
 package org.hisp.dhis.sms.parse;
 
+import java.util.HashMap;
 import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.hisp.dhis.smscommand.SMSCommand;
 
 public class J2MEDataEntryParser
     implements IParser
 {
+    private SMSCommand smsCommand;
 
     @Override
     public Map<String, String> parse( String sms )
     {
-        String keyValueSection = sms.split( "" )[1];
-        
-        return null;
+        String[] keyValuePairs = null;
+        if ( sms.indexOf( "#" ) > -1 )
+        {
+            keyValuePairs = sms.split( "#" );
+        }
+        else
+        {
+            keyValuePairs = new String[1];
+            keyValuePairs[0] = sms;
+        }
+
+        Map<String, String> keyValueMap = new HashMap<String, String>();
+        for ( String keyValuePair : keyValuePairs )
+        {
+            String[] token = keyValuePair.split( Pattern.quote( smsCommand.getSeparator() ) );
+            keyValueMap.put( token[0], token[1] );
+        }
+
+        return keyValueMap;
     }
 
     @Override
     public void setSeparator( String separator )
     {
         // TODO Auto-generated method stub
-
-    }
-
+    }
+
+    public SMSCommand getSmsCommand()
+    {
+        return smsCommand;
+    }
+
+    public void setSmsCommand( SMSCommand smsCommand )
+    {
+        this.smsCommand = smsCommand;
+    }
 }