~mortenoh/+junk/dhis2-detailed-import-export

« back to all changes in this revision

Viewing changes to local/in/dhis-web-integration/src/main/java/org/hisp/dhis/integration/rims/action/RIMSExportResultAction.java

  • Committer: larshelge at gmail
  • Date: 2009-03-03 16:46:36 UTC
  • Revision ID: larshelge@gmail.com-20090303164636-2sjlrquo7ib1gf7r
Initial check-in

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.hisp.dhis.integration.rims.action;
 
2
 
 
3
import java.util.ArrayList;
 
4
import java.util.Calendar;
 
5
import java.util.Collection;
 
6
import java.util.Date;
 
7
import java.util.Iterator;
 
8
import java.util.List;
 
9
import java.util.regex.Matcher;
 
10
import java.util.regex.Pattern;
 
11
 
 
12
import org.hisp.dhis.aggregation.AggregationService;
 
13
import org.hisp.dhis.aggregation.batch.statement.StatementManager;
 
14
import org.hisp.dhis.dataelement.DataElement;
 
15
import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 
16
import org.hisp.dhis.dataelement.DataElementCategoryOptionComboService;
 
17
import org.hisp.dhis.dataelement.DataElementService;
 
18
import org.hisp.dhis.dataset.DataSet;
 
19
import org.hisp.dhis.dataset.DataSetService;
 
20
import org.hisp.dhis.datavalue.DataValue;
 
21
import org.hisp.dhis.datavalue.DataValueService;
 
22
import org.hisp.dhis.i18n.I18nFormat;
 
23
import org.hisp.dhis.integration.rims.api.RIMSService;
 
24
import org.hisp.dhis.integration.rims.api.RIMSTable;
 
25
import org.hisp.dhis.integration.rims.api.RIMS_Mapping_DataElement;
 
26
import org.hisp.dhis.integration.rims.api.RIMS_Mapping_Orgunit;
 
27
import org.hisp.dhis.integration.rims.api.tables.DistrictTable;
 
28
import org.hisp.dhis.integration.rims.api.tables.PHCTable;
 
29
import org.hisp.dhis.integration.rims.api.tables.RIMSDistrict;
 
30
import org.hisp.dhis.integration.rims.api.tables.RIMSOrgUnit;
 
31
import org.hisp.dhis.integration.rims.api.tables.RIMS_PHC;
 
32
import org.hisp.dhis.integration.rims.util.Configuration;
 
33
import org.hisp.dhis.integration.rims.util.ImportExportError;
 
34
import org.hisp.dhis.organisationunit.OrganisationUnit;
 
35
import org.hisp.dhis.organisationunit.OrganisationUnitService;
 
36
import org.hisp.dhis.period.Period;
 
37
import org.hisp.dhis.period.PeriodService;
 
38
import org.hisp.dhis.period.PeriodType;
 
39
import org.hisp.dhis.system.util.MathUtils;
 
40
import com.opensymphony.xwork.ActionSupport;
 
41
 
 
42
public class RIMSExportResultAction
 
43
    extends ActionSupport
 
44
{
 
45
    private static final String NULL_REPLACEMENT = "0";
 
46
 
 
47
    // -------------------------------------------------------------------------
 
48
    // Dependencies
 
49
    // -------------------------------------------------------------------------
 
50
    private StatementManager statementManager;
 
51
 
 
52
    public void setStatementManager( StatementManager statementManager )
 
53
    {
 
54
        this.statementManager = statementManager;
 
55
    }
 
56
    
 
57
    private RIMSService rimsService;
 
58
 
 
59
    public void setRimsService( RIMSService rimsService )
 
60
    {
 
61
        this.rimsService = rimsService;
 
62
    }
 
63
 
 
64
    private DataSetService dataSetService;
 
65
 
 
66
    public void setDataSetService( DataSetService dataSetService )
 
67
    {
 
68
        this.dataSetService = dataSetService;
 
69
    }
 
70
 
 
71
    private PeriodService periodService;
 
72
 
 
73
    public void setPeriodService( PeriodService periodService )
 
74
    {
 
75
        this.periodService = periodService;
 
76
    }
 
77
 
 
78
    private OrganisationUnitService organisationUnitService;
 
79
 
 
80
    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
 
81
    {
 
82
        this.organisationUnitService = organisationUnitService;
 
83
    }
 
84
 
 
85
    private DataElementService dataElementService;
 
86
 
 
87
    public void setDataElementService( DataElementService dataElementService )
 
88
    {
 
89
        this.dataElementService = dataElementService;
 
90
    }
 
91
 
 
92
    private AggregationService aggregationService;
 
93
 
 
94
    public void setAggregationService( AggregationService aggregationService )
 
95
    {
 
96
        this.aggregationService = aggregationService;
 
97
    }
 
98
 
 
99
    private DataValueService dataValueService;
 
100
 
 
101
    public void setDataValueService( DataValueService dataValueService )
 
102
    {
 
103
        this.dataValueService = dataValueService;
 
104
    }
 
105
 
 
106
    private DataElementCategoryOptionComboService dataElementCategoryOptionComboService;
 
107
 
 
108
    public void setDataElementCategoryOptionComboService(
 
109
        DataElementCategoryOptionComboService dataElementCategoryOptionComboService )
 
110
    {
 
111
        this.dataElementCategoryOptionComboService = dataElementCategoryOptionComboService;
 
112
    }
 
113
 
 
114
    private I18nFormat format;
 
115
 
 
116
    public void setFormat( I18nFormat format )
 
117
    {
 
118
        this.format = format;
 
119
    }
 
120
 
 
121
    // --------------------------------------------------------------------------
 
122
    // Parameters
 
123
    // --------------------------------------------------------------------------
 
124
 
 
125
    private Date sDate;
 
126
 
 
127
    private Date eDate;
 
128
 
 
129
    private List<String> selectedOrgunits;
 
130
 
 
131
    public void setSelectedOrgunits( List<String> selectedOrgunits )
 
132
    {
 
133
        this.selectedOrgunits = selectedOrgunits;
 
134
    }
 
135
 
 
136
    private List<String> rimsDEGroups;
 
137
 
 
138
    public void setRimsDEGroups( List<String> rimsDEGroups )
 
139
    {
 
140
        this.rimsDEGroups = rimsDEGroups;
 
141
    }
 
142
 
 
143
    private String startDate;
 
144
 
 
145
    public void setStartDate( String startDate )
 
146
    {
 
147
        this.startDate = startDate;
 
148
    }
 
149
 
 
150
    private String endDate;
 
151
 
 
152
    public void setEndDate( String endDate )
 
153
    {
 
154
        this.endDate = endDate;
 
155
    }
 
156
 
 
157
    private String rimsDistricts;
 
158
    
 
159
    private String includeDistrict;
 
160
    
 
161
    private String connection;
 
162
    
 
163
    private int totalRecCount;
 
164
 
 
165
    public int getTotalRecCount()
 
166
    {
 
167
        return totalRecCount;
 
168
    }
 
169
    
 
170
    private Collection<ImportExportError> skipped = new ArrayList<ImportExportError>();
 
171
 
 
172
    private boolean abort;
 
173
 
 
174
    // --------------------------------------------------------------------------
 
175
    // Action Implementation
 
176
    // --------------------------------------------------------------------------
 
177
    public String execute()
 
178
        throws Exception
 
179
    {
 
180
        // TODO Useful for testing, turn off for production use
 
181
        boolean includeTotals = false;
 
182
        
 
183
        if ( connection == null )
 
184
        {
 
185
            throw new IllegalArgumentException( "Must choose connection" );
 
186
        }
 
187
 
 
188
        Configuration config = new Configuration( connection );
 
189
        statementManager.initialise();
 
190
 
 
191
        // ---------------------------------------------------------------------
 
192
        // OrganisationUnit Info
 
193
        // ---------------------------------------------------------------------
 
194
        // TODO Figure out this generics stuff
 
195
        List<Object> rimsSelectedOus = new ArrayList<Object>();
 
196
 
 
197
        if ( includeDistrict != null )
 
198
        {
 
199
            // Get selected district and add it to the list of selected OUs
 
200
            rimsSelectedOus.add( rimsService.getDistrict( rimsDistricts, connection ) );
 
201
        }
 
202
        else if ( selectedOrgunits == null )
 
203
        {
 
204
            throw new IllegalArgumentException( "No orgunits selected" );
 
205
        }
 
206
        
 
207
        if ( selectedOrgunits != null )
 
208
        {
 
209
            for ( String rimsOU: selectedOrgunits )
 
210
            {
 
211
                RIMS_PHC rimsOUObj = rimsService.getPHC( rimsOU, connection );
 
212
                rimsSelectedOus.add( rimsOUObj );
 
213
            }
 
214
        }
 
215
 
 
216
        // DataElement Info
 
217
        List<RIMS_Mapping_DataElement> rimsSelectedMappingDEs = new ArrayList<RIMS_Mapping_DataElement>(
 
218
            getSelctedMappingDes() );
 
219
 
 
220
        // Period Info
 
221
        sDate = format.parseDate( startDate );
 
222
        eDate = format.parseDate( endDate );
 
223
 
 
224
        List<Period> selectedPeriods = new ArrayList<Period>( periodService.getIntersectingPeriods( sDate, eDate ) );
 
225
        
 
226
        int orgUnitI = 0;
 
227
all:
 
228
        // TODO Figure out this generics stuff (see above)
 
229
        for ( Object o: rimsSelectedOus )
 
230
        {
 
231
            RIMSOrgUnit rimsOrgUnit = (RIMSOrgUnit) o;
 
232
            // Initialize tables
 
233
//            for( RIMSTable table: config.getTables() )
 
234
//            {
 
235
//                table.beginTransaction();
 
236
//            }
 
237
            
 
238
            int percentage = (int) (orgUnitI++ / (double) rimsSelectedOus.size() * 100);
 
239
            System.out.print( "("+ percentage +" %) Importing "+ rimsOrgUnit.getName() );
 
240
            
 
241
            RIMS_Mapping_Orgunit rimsMappingOrgUnit = rimsService.getMappingOrgUnit( rimsOrgUnit.getCode() );
 
242
            for ( RIMS_Mapping_DataElement mappingDataElement: rimsSelectedMappingDEs )
 
243
            {
 
244
                System.out.print( '.' );
 
245
 
 
246
                if ( mappingDataElement.getDhisExpression().equalsIgnoreCase( "NA" )
 
247
                    || mappingDataElement.getDhisExpression().equalsIgnoreCase( "NO_SUCH_DE" ) )
 
248
                {
 
249
                    continue;
 
250
                }
 
251
                
 
252
                if ( mappingDataElement.isTotal() && !includeTotals )
 
253
                {
 
254
                    continue;
 
255
                }
 
256
 
 
257
                for ( Period period: selectedPeriods )
 
258
                {
 
259
                    // Flip this using the debugger to abort.
 
260
                    // Eventually the progress indicator will have an abort button.
 
261
                    if ( abort )
 
262
                    {
 
263
                        break all;
 
264
                    }
 
265
                    try {
 
266
                        if ( period.getPeriodType().getName().equalsIgnoreCase( "monthly" ) )
 
267
                        {
 
268
                            if ( !config.getMonthlyFields().contains( mappingDataElement.getRimsColumn() ) )
 
269
                            {
 
270
                                continue;
 
271
                            }
 
272
                        }
 
273
                        else if ( period.getPeriodType().getName().equalsIgnoreCase( "yearly" ) )
 
274
                        {
 
275
                            if ( !config.getYearlyFields().contains( mappingDataElement.getRimsColumn() ) )
 
276
                            {
 
277
                                continue;
 
278
                            }
 
279
                        }
 
280
                        else
 
281
                        {
 
282
                            continue;
 
283
                        }
 
284
                        
 
285
                        // -----------------------------------------------------
 
286
                        // Skip if mixing district/PHC data
 
287
                        // -----------------------------------------------------
 
288
                        RIMSTable table = config.getTable( mappingDataElement.getTableName() );
 
289
                        
 
290
                        // Prevent superfluous "dataelement not found" errors
 
291
                        if ( ( table instanceof DistrictTable
 
292
                            && rimsOrgUnit instanceof RIMS_PHC ) 
 
293
                          || ( table instanceof PHCTable
 
294
                            && rimsOrgUnit instanceof RIMSDistrict ) )
 
295
                        {
 
296
                            continue;
 
297
                        }
 
298
                        
 
299
                        // -----------------------------------------------------
 
300
                        // Get data value
 
301
                        // -----------------------------------------------------
 
302
    
 
303
                        Calendar cal = Calendar.getInstance();
 
304
                        cal.setTime( period.getStartDate() );
 
305
                        int year = cal.get( Calendar.YEAR );
 
306
                        int month = cal.get( Calendar.MONTH );
 
307
                        month = month + 1;
 
308
                        
 
309
                        OrganisationUnit orgUnit = organisationUnitService.getOrganisationUnit( Integer
 
310
                            .parseInt( rimsMappingOrgUnit.getDhisid() ) );
 
311
                        String dhisValue = getDHISDataValue( mappingDataElement.getDhisExpression(), period, orgUnit );
 
312
                        
 
313
                        if ( dhisValue == null )
 
314
                        {
 
315
                            skipped.add( new ImportExportError( mappingDataElement, rimsMappingOrgUnit, period, "No value found for dataelement" ) );
 
316
                            continue;
 
317
                        }
 
318
                        
 
319
                        // ---------------------------------------------------------
 
320
                        // Call actual export code
 
321
                        // ---------------------------------------------------------
 
322
                        
 
323
                        if ( table.isData( rimsOrgUnit, month, year, mappingDataElement ) )
 
324
                        {
 
325
                            totalRecCount += table.updateData( rimsOrgUnit, month, year,
 
326
                                mappingDataElement, dhisValue );
 
327
                        }
 
328
                        else
 
329
                        {
 
330
                            totalRecCount += table.insertData( rimsOrgUnit, month, year,
 
331
                                mappingDataElement, dhisValue );    
 
332
                        }
 
333
                    }
 
334
                    catch ( Exception e )
 
335
                    {
 
336
                        // Log dataelement and reason
 
337
                        try 
 
338
                        {
 
339
                            DataElement dataElement = dataElementService
 
340
                                .getDataElement( mappingDataElement
 
341
                                    .getDhisDataElementId() );
 
342
                            skipped.add( new ImportExportError( dataElement,
 
343
                                rimsMappingOrgUnit, period, e ) );
 
344
                            // TODO DEBUG: Beep added
 
345
                            System.err.println( e.getClass().getSimpleName() +": "+ e.getMessage() );
 
346
                        }
 
347
                        catch ( NumberFormatException f )
 
348
                        {
 
349
                            skipped.add( new ImportExportError( mappingDataElement, 
 
350
                                rimsMappingOrgUnit, period, e ) );
 
351
                        }
 
352
                        continue;
 
353
                    }
 
354
                }
 
355
            }
 
356
            // ---------------------------------------------------------------------
 
357
            // Final fixup of the exported data
 
358
            // ---------------------------------------------------------------------
 
359
            for( RIMSTable table: config.getTables() )
 
360
            {
 
361
                table.fillInTotals();
 
362
                table.markIfComplete();
 
363
                table.commit();
 
364
            }
 
365
            System.out.println( "done" );
 
366
        }
 
367
 
 
368
        statementManager.destroy();
 
369
        
 
370
        return SUCCESS;
 
371
    }
 
372
 
 
373
    public List<RIMS_Mapping_DataElement> getSelctedMappingDes() throws Exception
 
374
    {
 
375
        List<RIMS_Mapping_DataElement> rimsSelctedMappingsDes = new ArrayList<RIMS_Mapping_DataElement>();
 
376
 
 
377
        Iterator<String> iterator1 = rimsDEGroups.iterator();
 
378
        while ( iterator1.hasNext() )
 
379
        {
 
380
            String sectionName = (String) iterator1.next();
 
381
            rimsSelctedMappingsDes.addAll( rimsService.getRIMSDataElementsByDEGroup( sectionName ) );
 
382
 
 
383
        }
 
384
        return rimsSelctedMappingsDes;
 
385
    }
 
386
 
 
387
    /*
 
388
     * Returns the PeriodType Object for selected DataElement, If no PeriodType
 
389
     * is found then by default returns Monthly Period type
 
390
     */
 
391
    public PeriodType getDataElementPeriodType( DataElement de )
 
392
    {
 
393
        List<DataSet> dataSetList = new ArrayList<DataSet>( dataSetService.getAllDataSets() );
 
394
        Iterator<DataSet> it = dataSetList.iterator();
 
395
        while ( it.hasNext() )
 
396
        {
 
397
            DataSet ds = (DataSet) it.next();
 
398
            List<DataElement> dataElementList = new ArrayList<DataElement>( ds.getDataElements() );
 
399
            if ( dataElementList.contains( de ) )
 
400
            {
 
401
                return ds.getPeriodType();
 
402
            }
 
403
        }
 
404
 
 
405
        return periodService.getPeriodTypeByName( "Monthly" );
 
406
    } // getDataElementPeriodType end
 
407
 
 
408
    private String getDHISDataValue( String formula, Period period, OrganisationUnit organisationUnit )
 
409
    {
 
410
        try
 
411
        {
 
412
            boolean typeNotInt = false;
 
413
            boolean valueFound = false;
 
414
            Pattern pattern = Pattern.compile( "(\\[\\d+\\.\\d+\\])" );
 
415
 
 
416
            Matcher matcher = pattern.matcher( formula );
 
417
            StringBuffer buffer = new StringBuffer();
 
418
 
 
419
            while ( matcher.find() )
 
420
            {
 
421
                String replaceString = matcher.group();
 
422
 
 
423
                replaceString = replaceString.replaceAll( "[\\[\\]]", "" );
 
424
                String optionComboIdStr = replaceString.substring( replaceString.indexOf( '.' ) + 1, replaceString
 
425
                    .length() );
 
426
 
 
427
                replaceString = replaceString.substring( 0, replaceString.indexOf( '.' ) );
 
428
 
 
429
                int dataElementId = Integer.parseInt( replaceString );
 
430
                int optionComboId = Integer.parseInt( optionComboIdStr );
 
431
 
 
432
                DataElement dataElement = dataElementService.getDataElement( dataElementId );
 
433
                DataElementCategoryOptionCombo optionCombo = dataElementCategoryOptionComboService
 
434
                    .getDataElementCategoryOptionCombo( optionComboId );
 
435
 
 
436
                if ( dataElement == null || optionCombo == null )
 
437
                {
 
438
                    replaceString = "";
 
439
                    matcher.appendReplacement( buffer, replaceString );
 
440
                    continue;
 
441
                }
 
442
                if ( dataElement.getType().equalsIgnoreCase( "int" ) )
 
443
                {
 
444
 
 
445
                    DataValue dataValue = dataValueService.getDataValue( organisationUnit, dataElement, 
 
446
                        period, optionCombo );
 
447
 
 
448
                    if ( dataValue == null )
 
449
                    {
 
450
                        replaceString = NULL_REPLACEMENT;
 
451
                    }
 
452
                    else
 
453
                    {
 
454
                        replaceString = dataValue.getValue();
 
455
                        valueFound = true;
 
456
                    }
 
457
                    
 
458
                    // Aggregated data values are not what we need when exporting
 
459
                    // to RIMS.
 
460
                    /*
 
461
                    double aggregatedValue = aggregationService.getAggregatedDataValue( dataElement, optionCombo,
 
462
                        theStartDate, theEndDate, organisationUnit );
 
463
 
 
464
                    if ( aggregatedValue == AggregationService.NO_VALUES_REGISTERED )
 
465
                    {
 
466
                        replaceString = NULL_REPLACEMENT;
 
467
                    }
 
468
                    else
 
469
                    {
 
470
                        replaceString = String.valueOf( aggregatedValue );
 
471
                        deFlag2 = 1;
 
472
                    }
 
473
                    */
 
474
                }
 
475
                else
 
476
                {
 
477
                    typeNotInt = true;
 
478
                    PeriodType dePeriodType = getDataElementPeriodType( dataElement );
 
479
                    List<Period> periodList = new ArrayList<Period>( periodService.getIntersectingPeriodsByPeriodType(
 
480
                        dePeriodType, period.getStartDate(), period.getEndDate() ) );
 
481
                    Period tempPeriod = new Period();
 
482
                    if ( periodList == null || periodList.isEmpty() )
 
483
                    {
 
484
                        replaceString = "";
 
485
                        matcher.appendReplacement( buffer, replaceString );
 
486
                        continue;
 
487
                    }
 
488
                    else
 
489
                    {
 
490
                        tempPeriod = (Period) periodList.get( 0 );
 
491
                    }
 
492
 
 
493
                    DataValue dataValue = dataValueService.getDataValue( organisationUnit, dataElement, tempPeriod,
 
494
                        optionCombo );
 
495
 
 
496
                    if ( dataValue != null )
 
497
                        replaceString = dataValue.getValue();
 
498
                    else
 
499
                        replaceString = "";
 
500
 
 
501
                }
 
502
                matcher.appendReplacement( buffer, replaceString );
 
503
            }
 
504
 
 
505
            matcher.appendTail( buffer );
 
506
 
 
507
            String resultValue = "";
 
508
            if ( !typeNotInt )
 
509
            {
 
510
                double d = 0.0;
 
511
                try
 
512
                {
 
513
                    if ( buffer.toString().contains( "/0.0" ) || buffer.toString().contains( "/0" )
 
514
                        || buffer.toString().contains( "/((0.0" ) || buffer.toString().contains( "/((0" ) )
 
515
                        d = 0.0;
 
516
                    else
 
517
                        d = MathUtils.calculateExpression( buffer.toString() );
 
518
                }
 
519
                catch ( ArithmeticException e )
 
520
                {
 
521
                    d = 0.0;
 
522
                    System.out.println( "Divide By Zero " );
 
523
                }
 
524
                catch ( Exception e )
 
525
                {
 
526
                    d = 0.0;
 
527
                    System.out.println( "Divide By Zero " );
 
528
                }
 
529
                if ( d == -1 )
 
530
                    d = 0.0;
 
531
                else
 
532
                {
 
533
                    d = Math.round( d * Math.pow( 10, 2 ) ) / Math.pow( 10, 2 );
 
534
                    resultValue = "" + (int) d;
 
535
                }
 
536
 
 
537
                if ( !valueFound )
 
538
                {
 
539
                    resultValue = null;
 
540
                }
 
541
            }
 
542
            else
 
543
            {
 
544
                resultValue = buffer.toString();
 
545
            }
 
546
            return resultValue;
 
547
        }
 
548
        catch ( NumberFormatException ex )
 
549
        {
 
550
            throw new RuntimeException( "Illegal DataElement id", ex );
 
551
        }
 
552
    }
 
553
 
 
554
    public Collection<ImportExportError> getSkipped()
 
555
    {
 
556
        return skipped;
 
557
    }
 
558
 
 
559
    public void setSkipped( Collection<ImportExportError> skipped )
 
560
    {
 
561
        this.skipped = skipped;
 
562
    }
 
563
 
 
564
    public void setIncludeDistrict( String includeDistrict )
 
565
    {
 
566
        this.includeDistrict = includeDistrict;
 
567
    }
 
568
 
 
569
    public void setRimsDistricts( String rimsDistricts )
 
570
    {
 
571
        this.rimsDistricts = rimsDistricts;
 
572
    }
 
573
 
 
574
    public void setConnection( String connection )
 
575
    {
 
576
        this.connection = connection;
 
577
    }
 
578
}