1
package org.hisp.dhis.aggregation.impl.dataelement;
4
* Copyright (c) 2004-2007, University of Oslo
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are met:
9
* * Redistributions of source code must retain the above copyright notice, this
10
* list of conditions and the following disclaimer.
11
* * Redistributions in binary form must reproduce the above copyright notice,
12
* this list of conditions and the following disclaimer in the documentation
13
* and/or other materials provided with the distribution.
14
* * Neither the name of the HISP project nor the names of its contributors may
15
* be used to endorse or promote products derived from this software without
16
* specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
import java.util.Collection;
31
import java.util.Date;
33
import org.hisp.dhis.aggregation.AggregationService;
34
import org.hisp.dhis.dataelement.DataElement;
35
import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
36
import org.hisp.dhis.datavalue.DataValue;
37
import org.hisp.dhis.organisationunit.OrganisationUnit;
38
import org.hisp.dhis.organisationunit.OrganisationUnitHierarchy;
39
import org.hisp.dhis.period.Period;
41
import static org.hisp.dhis.system.util.MathUtils.getDays;
44
* @author Lars Helge Overland
45
* @version $Id: SumIntDataElementAggregation.java 4753 2008-03-14 12:48:50Z larshelg $
47
public class SumIntDataElementAggregation
48
extends AbstractDataElementAggregation
50
public double getAggregatedValue( DataElement dataElement, DataElementCategoryOptionCombo optionCombo, Date aggregationStartDate, Date aggregationEndDate,
51
OrganisationUnit organisationUnit )
53
Collection<OrganisationUnitHierarchy> hierarchies = aggregationCache.getOrganisationUnitHierarchies(
54
aggregationStartDate, aggregationEndDate );
56
double[] sums = getSumAndRelevantDays( dataElement.getId(), optionCombo.getId(), aggregationStartDate, aggregationEndDate,
57
hierarchies, organisationUnit.getId() );
65
return AggregationService.NO_VALUES_REGISTERED;
69
protected Collection<DataValue> getDataValues( int dataElementId, int optionComboId, int organisationUnitId,
70
OrganisationUnitHierarchy hierarchy, Date startDate, Date endDate )
72
Collection<Integer> children = aggregationCache.getChildren( hierarchy, organisationUnitId );
74
Collection<Integer> periods = aggregationCache.getPeriodIds( startDate, endDate );
76
Collection<DataValue> values = aggregationStore.getDataValues( children, dataElementId, optionComboId, periods );
82
* Calculates the SUM for DataValues which period is within or overlapping
83
* startDate and / or endDate. This method is typically used for DataValues.
84
* It handles the four situations where a DataValue will count for the
85
* period that startDate to endDate constitutes ( referred to as d1 and d2 ):
87
* 1. startDate and endDate is between d1 - d2<br>
88
* 2. startDate is before d1 and endDate is between d1 - d2<br>
89
* 3. startDate is between d1 - d2 and endDate is after d2<br>
90
* 4. startDate is before d1 and endDate is after d2<br>
92
* The method iterates over every DataValue in the passed Collection and
93
* multiplies each value with a factor calculated according to the formula:
94
* <p> ( days in period between d1 - d2 / days in period )
96
* This value is then added to the sum. After the iteration is finished, the
99
* @param dataValues The datavalues to aggregate
100
* @param startDate Start date of the period to aggregate over
101
* @param endDate End date of the period to aggregate over
102
* @param aggregationStartDate The original start date of the entire
104
* @param aggregationEndDate The original end date of the entire aggregation
106
* @return The SUMMARIZED value
108
protected double[] getAggregateOfValues( Collection<DataValue> dataValues, Date startDate, Date endDate,
109
Date aggregationStartDate, Date aggregationEndDate )
112
double totalRelevantDays = 0;
114
for ( DataValue dataValue : dataValues )
116
Period currentPeriod = aggregationCache.getPeriod( dataValue.getPeriod().getId() );
117
Date currentStartDate = currentPeriod.getStartDate();
118
Date currentEndDate = currentPeriod.getEndDate();
124
value = Double.parseDouble( dataValue.getValue() );
126
catch ( Exception ex )
130
double currentPeriodDuration = ( getDays( currentEndDate ) - getDays( currentStartDate ) );
132
if ( currentPeriodDuration > 0 )
134
long relevantDays = 0;
136
if ( currentStartDate.compareTo( startDate ) >= 0 && currentEndDate.compareTo( endDate ) <= 0 )
138
relevantDays = getDays( endDate ) - getDays( startDate );
141
else if ( currentStartDate.compareTo( startDate ) <= 0 && currentEndDate.compareTo( startDate ) >= 0
142
&& currentEndDate.compareTo( endDate ) <= 0 )
144
relevantDays = getDays( currentEndDate ) - getDays( startDate );
145
double factor = relevantDays / currentPeriodDuration;
146
totalSum += value * factor;
148
else if ( currentStartDate.compareTo( startDate ) >= 0 && currentStartDate.compareTo( endDate ) <= 0
149
&& currentEndDate.compareTo( endDate ) >= 0 )
151
relevantDays = getDays( endDate ) - getDays( currentStartDate );
152
double factor = relevantDays / currentPeriodDuration;
153
totalSum += value * factor;
155
else if ( currentStartDate.compareTo( startDate ) <= 0 && currentEndDate.compareTo( endDate ) >= 0 )
157
relevantDays = getDays( endDate ) - getDays( startDate );
158
double factor = relevantDays / currentPeriodDuration;
159
totalSum += value * factor;
162
totalRelevantDays += relevantDays;
166
double[] fraction = { totalSum, totalRelevantDays };