1
package org.hisp.dhis.integration.rims.action;
3
import java.util.ArrayList;
4
import java.util.Calendar;
5
import java.util.Collection;
7
import java.util.Iterator;
9
import java.util.regex.Matcher;
10
import java.util.regex.Pattern;
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;
42
public class RIMSExportResultAction
45
private static final String NULL_REPLACEMENT = "0";
47
// -------------------------------------------------------------------------
49
// -------------------------------------------------------------------------
50
private StatementManager statementManager;
52
public void setStatementManager( StatementManager statementManager )
54
this.statementManager = statementManager;
57
private RIMSService rimsService;
59
public void setRimsService( RIMSService rimsService )
61
this.rimsService = rimsService;
64
private DataSetService dataSetService;
66
public void setDataSetService( DataSetService dataSetService )
68
this.dataSetService = dataSetService;
71
private PeriodService periodService;
73
public void setPeriodService( PeriodService periodService )
75
this.periodService = periodService;
78
private OrganisationUnitService organisationUnitService;
80
public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
82
this.organisationUnitService = organisationUnitService;
85
private DataElementService dataElementService;
87
public void setDataElementService( DataElementService dataElementService )
89
this.dataElementService = dataElementService;
92
private AggregationService aggregationService;
94
public void setAggregationService( AggregationService aggregationService )
96
this.aggregationService = aggregationService;
99
private DataValueService dataValueService;
101
public void setDataValueService( DataValueService dataValueService )
103
this.dataValueService = dataValueService;
106
private DataElementCategoryOptionComboService dataElementCategoryOptionComboService;
108
public void setDataElementCategoryOptionComboService(
109
DataElementCategoryOptionComboService dataElementCategoryOptionComboService )
111
this.dataElementCategoryOptionComboService = dataElementCategoryOptionComboService;
114
private I18nFormat format;
116
public void setFormat( I18nFormat format )
118
this.format = format;
121
// --------------------------------------------------------------------------
123
// --------------------------------------------------------------------------
129
private List<String> selectedOrgunits;
131
public void setSelectedOrgunits( List<String> selectedOrgunits )
133
this.selectedOrgunits = selectedOrgunits;
136
private List<String> rimsDEGroups;
138
public void setRimsDEGroups( List<String> rimsDEGroups )
140
this.rimsDEGroups = rimsDEGroups;
143
private String startDate;
145
public void setStartDate( String startDate )
147
this.startDate = startDate;
150
private String endDate;
152
public void setEndDate( String endDate )
154
this.endDate = endDate;
157
private String rimsDistricts;
159
private String includeDistrict;
161
private String connection;
163
private int totalRecCount;
165
public int getTotalRecCount()
167
return totalRecCount;
170
private Collection<ImportExportError> skipped = new ArrayList<ImportExportError>();
172
private boolean abort;
174
// --------------------------------------------------------------------------
175
// Action Implementation
176
// --------------------------------------------------------------------------
177
public String execute()
180
// TODO Useful for testing, turn off for production use
181
boolean includeTotals = false;
183
if ( connection == null )
185
throw new IllegalArgumentException( "Must choose connection" );
188
Configuration config = new Configuration( connection );
189
statementManager.initialise();
191
// ---------------------------------------------------------------------
192
// OrganisationUnit Info
193
// ---------------------------------------------------------------------
194
// TODO Figure out this generics stuff
195
List<Object> rimsSelectedOus = new ArrayList<Object>();
197
if ( includeDistrict != null )
199
// Get selected district and add it to the list of selected OUs
200
rimsSelectedOus.add( rimsService.getDistrict( rimsDistricts, connection ) );
202
else if ( selectedOrgunits == null )
204
throw new IllegalArgumentException( "No orgunits selected" );
207
if ( selectedOrgunits != null )
209
for ( String rimsOU: selectedOrgunits )
211
RIMS_PHC rimsOUObj = rimsService.getPHC( rimsOU, connection );
212
rimsSelectedOus.add( rimsOUObj );
217
List<RIMS_Mapping_DataElement> rimsSelectedMappingDEs = new ArrayList<RIMS_Mapping_DataElement>(
218
getSelctedMappingDes() );
221
sDate = format.parseDate( startDate );
222
eDate = format.parseDate( endDate );
224
List<Period> selectedPeriods = new ArrayList<Period>( periodService.getIntersectingPeriods( sDate, eDate ) );
228
// TODO Figure out this generics stuff (see above)
229
for ( Object o: rimsSelectedOus )
231
RIMSOrgUnit rimsOrgUnit = (RIMSOrgUnit) o;
233
// for( RIMSTable table: config.getTables() )
235
// table.beginTransaction();
238
int percentage = (int) (orgUnitI++ / (double) rimsSelectedOus.size() * 100);
239
System.out.print( "("+ percentage +" %) Importing "+ rimsOrgUnit.getName() );
241
RIMS_Mapping_Orgunit rimsMappingOrgUnit = rimsService.getMappingOrgUnit( rimsOrgUnit.getCode() );
242
for ( RIMS_Mapping_DataElement mappingDataElement: rimsSelectedMappingDEs )
244
System.out.print( '.' );
246
if ( mappingDataElement.getDhisExpression().equalsIgnoreCase( "NA" )
247
|| mappingDataElement.getDhisExpression().equalsIgnoreCase( "NO_SUCH_DE" ) )
252
if ( mappingDataElement.isTotal() && !includeTotals )
257
for ( Period period: selectedPeriods )
259
// Flip this using the debugger to abort.
260
// Eventually the progress indicator will have an abort button.
266
if ( period.getPeriodType().getName().equalsIgnoreCase( "monthly" ) )
268
if ( !config.getMonthlyFields().contains( mappingDataElement.getRimsColumn() ) )
273
else if ( period.getPeriodType().getName().equalsIgnoreCase( "yearly" ) )
275
if ( !config.getYearlyFields().contains( mappingDataElement.getRimsColumn() ) )
285
// -----------------------------------------------------
286
// Skip if mixing district/PHC data
287
// -----------------------------------------------------
288
RIMSTable table = config.getTable( mappingDataElement.getTableName() );
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 ) )
299
// -----------------------------------------------------
301
// -----------------------------------------------------
303
Calendar cal = Calendar.getInstance();
304
cal.setTime( period.getStartDate() );
305
int year = cal.get( Calendar.YEAR );
306
int month = cal.get( Calendar.MONTH );
309
OrganisationUnit orgUnit = organisationUnitService.getOrganisationUnit( Integer
310
.parseInt( rimsMappingOrgUnit.getDhisid() ) );
311
String dhisValue = getDHISDataValue( mappingDataElement.getDhisExpression(), period, orgUnit );
313
if ( dhisValue == null )
315
skipped.add( new ImportExportError( mappingDataElement, rimsMappingOrgUnit, period, "No value found for dataelement" ) );
319
// ---------------------------------------------------------
320
// Call actual export code
321
// ---------------------------------------------------------
323
if ( table.isData( rimsOrgUnit, month, year, mappingDataElement ) )
325
totalRecCount += table.updateData( rimsOrgUnit, month, year,
326
mappingDataElement, dhisValue );
330
totalRecCount += table.insertData( rimsOrgUnit, month, year,
331
mappingDataElement, dhisValue );
334
catch ( Exception e )
336
// Log dataelement and reason
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() );
347
catch ( NumberFormatException f )
349
skipped.add( new ImportExportError( mappingDataElement,
350
rimsMappingOrgUnit, period, e ) );
356
// ---------------------------------------------------------------------
357
// Final fixup of the exported data
358
// ---------------------------------------------------------------------
359
for( RIMSTable table: config.getTables() )
361
table.fillInTotals();
362
table.markIfComplete();
365
System.out.println( "done" );
368
statementManager.destroy();
373
public List<RIMS_Mapping_DataElement> getSelctedMappingDes() throws Exception
375
List<RIMS_Mapping_DataElement> rimsSelctedMappingsDes = new ArrayList<RIMS_Mapping_DataElement>();
377
Iterator<String> iterator1 = rimsDEGroups.iterator();
378
while ( iterator1.hasNext() )
380
String sectionName = (String) iterator1.next();
381
rimsSelctedMappingsDes.addAll( rimsService.getRIMSDataElementsByDEGroup( sectionName ) );
384
return rimsSelctedMappingsDes;
388
* Returns the PeriodType Object for selected DataElement, If no PeriodType
389
* is found then by default returns Monthly Period type
391
public PeriodType getDataElementPeriodType( DataElement de )
393
List<DataSet> dataSetList = new ArrayList<DataSet>( dataSetService.getAllDataSets() );
394
Iterator<DataSet> it = dataSetList.iterator();
395
while ( it.hasNext() )
397
DataSet ds = (DataSet) it.next();
398
List<DataElement> dataElementList = new ArrayList<DataElement>( ds.getDataElements() );
399
if ( dataElementList.contains( de ) )
401
return ds.getPeriodType();
405
return periodService.getPeriodTypeByName( "Monthly" );
406
} // getDataElementPeriodType end
408
private String getDHISDataValue( String formula, Period period, OrganisationUnit organisationUnit )
412
boolean typeNotInt = false;
413
boolean valueFound = false;
414
Pattern pattern = Pattern.compile( "(\\[\\d+\\.\\d+\\])" );
416
Matcher matcher = pattern.matcher( formula );
417
StringBuffer buffer = new StringBuffer();
419
while ( matcher.find() )
421
String replaceString = matcher.group();
423
replaceString = replaceString.replaceAll( "[\\[\\]]", "" );
424
String optionComboIdStr = replaceString.substring( replaceString.indexOf( '.' ) + 1, replaceString
427
replaceString = replaceString.substring( 0, replaceString.indexOf( '.' ) );
429
int dataElementId = Integer.parseInt( replaceString );
430
int optionComboId = Integer.parseInt( optionComboIdStr );
432
DataElement dataElement = dataElementService.getDataElement( dataElementId );
433
DataElementCategoryOptionCombo optionCombo = dataElementCategoryOptionComboService
434
.getDataElementCategoryOptionCombo( optionComboId );
436
if ( dataElement == null || optionCombo == null )
439
matcher.appendReplacement( buffer, replaceString );
442
if ( dataElement.getType().equalsIgnoreCase( "int" ) )
445
DataValue dataValue = dataValueService.getDataValue( organisationUnit, dataElement,
446
period, optionCombo );
448
if ( dataValue == null )
450
replaceString = NULL_REPLACEMENT;
454
replaceString = dataValue.getValue();
458
// Aggregated data values are not what we need when exporting
461
double aggregatedValue = aggregationService.getAggregatedDataValue( dataElement, optionCombo,
462
theStartDate, theEndDate, organisationUnit );
464
if ( aggregatedValue == AggregationService.NO_VALUES_REGISTERED )
466
replaceString = NULL_REPLACEMENT;
470
replaceString = String.valueOf( aggregatedValue );
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() )
485
matcher.appendReplacement( buffer, replaceString );
490
tempPeriod = (Period) periodList.get( 0 );
493
DataValue dataValue = dataValueService.getDataValue( organisationUnit, dataElement, tempPeriod,
496
if ( dataValue != null )
497
replaceString = dataValue.getValue();
502
matcher.appendReplacement( buffer, replaceString );
505
matcher.appendTail( buffer );
507
String resultValue = "";
513
if ( buffer.toString().contains( "/0.0" ) || buffer.toString().contains( "/0" )
514
|| buffer.toString().contains( "/((0.0" ) || buffer.toString().contains( "/((0" ) )
517
d = MathUtils.calculateExpression( buffer.toString() );
519
catch ( ArithmeticException e )
522
System.out.println( "Divide By Zero " );
524
catch ( Exception e )
527
System.out.println( "Divide By Zero " );
533
d = Math.round( d * Math.pow( 10, 2 ) ) / Math.pow( 10, 2 );
534
resultValue = "" + (int) d;
544
resultValue = buffer.toString();
548
catch ( NumberFormatException ex )
550
throw new RuntimeException( "Illegal DataElement id", ex );
554
public Collection<ImportExportError> getSkipped()
559
public void setSkipped( Collection<ImportExportError> skipped )
561
this.skipped = skipped;
564
public void setIncludeDistrict( String includeDistrict )
566
this.includeDistrict = includeDistrict;
569
public void setRimsDistricts( String rimsDistricts )
571
this.rimsDistricts = rimsDistricts;
574
public void setConnection( String connection )
576
this.connection = connection;