1
package org.hisp.dhis.datamart.crosstab;
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 static org.hisp.dhis.datamart.crosstab.jdbc.CrossTabStore.COLUMN_PREFIX;
31
import static org.hisp.dhis.datamart.crosstab.jdbc.CrossTabStore.SEPARATOR;
33
import java.util.ArrayList;
34
import java.util.Collection;
35
import java.util.Collections;
36
import java.util.HashMap;
37
import java.util.HashSet;
38
import java.util.List;
42
import org.apache.commons.logging.Log;
43
import org.apache.commons.logging.LogFactory;
44
import org.hisp.dhis.dataelement.Operand;
45
import org.hisp.dhis.datamart.DataMartStore;
46
import org.hisp.dhis.datamart.crosstab.jdbc.CrossTabStore;
47
import org.hisp.dhis.jdbc.BatchHandler;
48
import org.hisp.dhis.jdbc.BatchHandlerFactory;
49
import org.hisp.dhis.jdbc.batchhandler.DataValueCrossTabBatchHandler;
52
* @author Lars Helge Overland
53
* @version $Id: DefaultCrossTabService.java 6268 2008-11-12 15:16:02Z larshelg $
55
public class DefaultCrossTabService
56
implements CrossTabService
58
private static final Log log = LogFactory.getLog( DefaultCrossTabService.class );
60
private static final int MAX_LENGTH = 20;
62
// -------------------------------------------------------------------------
64
// -------------------------------------------------------------------------
66
private BatchHandlerFactory batchHandlerFactory;
68
public void setBatchHandlerFactory( BatchHandlerFactory batchHandlerFactory )
70
this.batchHandlerFactory = batchHandlerFactory;
73
private CrossTabStore crossTabStore;
75
public void setCrossTabStore( CrossTabStore crossTabTableManager )
77
this.crossTabStore = crossTabTableManager;
80
private DataMartStore dataMartStore;
82
public void setDataMartStore( DataMartStore dataMartStore )
84
this.dataMartStore = dataMartStore;
87
// -------------------------------------------------------------------------
88
// CrossTabService implementation
89
// -------------------------------------------------------------------------
91
public Collection<Operand> populateCrossTabTable( final Collection<Operand> operands,
92
final Collection<Integer> periodIds, final Collection<Integer> organisationUnitIds )
94
final Set<Operand> emptyOperands = new HashSet<Operand>( operands );
96
if ( validate( operands, periodIds, organisationUnitIds ) )
98
final List<Operand> operandList = new ArrayList<Operand>( operands );
100
Collections.sort( operandList );
102
crossTabStore.dropCrossTabTable();
104
log.info( "Dropped crosstab table" );
106
crossTabStore.createCrossTabTable( operandList );
108
log.info( "Created crosstab table" );
110
final BatchHandler batchHandler = batchHandlerFactory.createBatchHandler( DataValueCrossTabBatchHandler.class );
114
emptyOperands.addAll( operands );
116
Map<Operand, String> map = null;
118
List<String> valueList = null;
120
boolean hasValues = false;
124
for ( final Integer periodId : periodIds )
126
for ( final Integer sourceId : organisationUnitIds )
128
map = dataMartStore.getDataValueMap( periodId, sourceId );
130
valueList = new ArrayList<String>( operandList.size() + 2 );
132
valueList.add( String.valueOf( periodId ) );
133
valueList.add( String.valueOf( sourceId ) );
137
for ( Operand operand : operandList )
139
value = map.get( operand );
141
if ( value != null && value.length() > MAX_LENGTH )
143
log.warn( "Value ignored, too long: '" + value +
144
"', for dataelement id: '" + operand.getDataElementId() +
145
"', categoryoptioncombo id: '" + operand.getOptionComboId() +
146
"', period id: '" + periodId +
147
"', source id: '" + sourceId + "'" );
155
emptyOperands.remove( operand );
158
valueList.add( value );
163
batchHandler.addObject( valueList );
167
log.info( "Crosstabulated data for period " + periodId );
170
batchHandler.flush();
173
return emptyOperands;
176
public void dropCrossTabTable()
178
crossTabStore.dropCrossTabTable();
181
public void trimCrossTabTable( Collection<Operand> emptyOperands )
183
final Collection<String> columnNames = getCrossTabColumnNames( emptyOperands );
185
for ( final String columnName : columnNames )
187
crossTabStore.dropCrossTabColumn( columnName );
191
public Map<Operand, Integer> getOperandIndexMap( Collection<Operand> operands )
193
final Map<Integer, String> columnNames = crossTabStore.getCrossTabTableColumns();
195
final Map<Operand, Integer> operandMap = new HashMap<Operand, Integer>();
197
for ( final Map.Entry<Integer, String> entry : columnNames.entrySet() )
199
if ( entry.getValue().startsWith( CrossTabStore.COLUMN_PREFIX ) )
201
final String operandString = entry.getValue().replace( CrossTabStore.COLUMN_PREFIX, "" );
203
final int dataElementId = Integer.parseInt( operandString.substring( 0, operandString.indexOf( CrossTabStore.SEPARATOR ) ) );
204
final int categoryOptionComboId = Integer.parseInt( operandString.substring( operandString.indexOf( CrossTabStore.SEPARATOR ) + 1 ) );
206
final Operand operand = new Operand( dataElementId, categoryOptionComboId );
208
if ( operands.contains( operand ) )
210
operandMap.put( operand, entry.getKey() );
218
// -------------------------------------------------------------------------
219
// Supportive methods
220
// -------------------------------------------------------------------------
223
* Generates a collection of crosstab column names based on a collection of Operands.
225
private Collection<String> getCrossTabColumnNames( Collection<Operand> operands )
227
final Collection<String> columnNames = new HashSet<String>( operands.size() );
229
for ( final Operand operand : operands )
231
columnNames.add( COLUMN_PREFIX + operand.getDataElementId() + SEPARATOR + operand.getOptionComboId() );
238
* Validates whether the given collections of identifiers are not null and of size greater than 0.
240
private boolean validate( Collection<Operand> operands, Collection<Integer> periodIds, Collection<Integer> unitIds )
242
if ( operands == null || periodIds == null || unitIds == null )
247
if ( operands.size() == 0 || periodIds.size() == 0 || unitIds.size() == 0 )