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

« back to all changes in this revision

Viewing changes to dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/crosstab/DefaultCrossTabService.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.datamart.crosstab;
 
2
 
 
3
/*
 
4
 * Copyright (c) 2004-2007, University of Oslo
 
5
 * All rights reserved.
 
6
 *
 
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.
 
17
 *
 
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.
 
28
 */
 
29
 
 
30
import static org.hisp.dhis.datamart.crosstab.jdbc.CrossTabStore.COLUMN_PREFIX;
 
31
import static org.hisp.dhis.datamart.crosstab.jdbc.CrossTabStore.SEPARATOR;
 
32
 
 
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;
 
39
import java.util.Map;
 
40
import java.util.Set;
 
41
 
 
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;
 
50
 
 
51
/**
 
52
 * @author Lars Helge Overland
 
53
 * @version $Id: DefaultCrossTabService.java 6268 2008-11-12 15:16:02Z larshelg $
 
54
 */
 
55
public class DefaultCrossTabService
 
56
    implements CrossTabService
 
57
{
 
58
    private static final Log log = LogFactory.getLog( DefaultCrossTabService.class );
 
59
    
 
60
    private static final int MAX_LENGTH = 20;
 
61
    
 
62
    // -------------------------------------------------------------------------
 
63
    // Dependencies
 
64
    // -------------------------------------------------------------------------
 
65
 
 
66
    private BatchHandlerFactory batchHandlerFactory;
 
67
        
 
68
    public void setBatchHandlerFactory( BatchHandlerFactory batchHandlerFactory )
 
69
    {
 
70
        this.batchHandlerFactory = batchHandlerFactory;
 
71
    }
 
72
    
 
73
    private CrossTabStore crossTabStore;
 
74
        
 
75
    public void setCrossTabStore( CrossTabStore crossTabTableManager )
 
76
    {
 
77
        this.crossTabStore = crossTabTableManager;
 
78
    }
 
79
    
 
80
    private DataMartStore dataMartStore;
 
81
        
 
82
    public void setDataMartStore( DataMartStore dataMartStore )
 
83
    {
 
84
        this.dataMartStore = dataMartStore;
 
85
    }
 
86
    
 
87
    // -------------------------------------------------------------------------
 
88
    // CrossTabService implementation
 
89
    // -------------------------------------------------------------------------
 
90
 
 
91
    public Collection<Operand> populateCrossTabTable( final Collection<Operand> operands, 
 
92
        final Collection<Integer> periodIds, final Collection<Integer> organisationUnitIds )
 
93
    {
 
94
        final Set<Operand> emptyOperands = new HashSet<Operand>( operands );
 
95
 
 
96
        if ( validate( operands, periodIds, organisationUnitIds ) )
 
97
        {
 
98
            final List<Operand> operandList = new ArrayList<Operand>( operands );
 
99
            
 
100
            Collections.sort( operandList );
 
101
 
 
102
            crossTabStore.dropCrossTabTable();
 
103
            
 
104
            log.info( "Dropped crosstab table" );
 
105
            
 
106
            crossTabStore.createCrossTabTable( operandList );
 
107
            
 
108
            log.info( "Created crosstab table" );
 
109
            
 
110
            final BatchHandler batchHandler = batchHandlerFactory.createBatchHandler( DataValueCrossTabBatchHandler.class );
 
111
            
 
112
            batchHandler.init();
 
113
            
 
114
            emptyOperands.addAll( operands );
 
115
            
 
116
            Map<Operand, String> map = null;
 
117
            
 
118
            List<String> valueList = null;
 
119
            
 
120
            boolean hasValues = false;
 
121
            
 
122
            String value = null;
 
123
            
 
124
            for ( final Integer periodId : periodIds )
 
125
            {
 
126
                for ( final Integer sourceId : organisationUnitIds )
 
127
                {
 
128
                    map = dataMartStore.getDataValueMap( periodId, sourceId );
 
129
                    
 
130
                    valueList = new ArrayList<String>( operandList.size() + 2 );
 
131
                    
 
132
                    valueList.add( String.valueOf( periodId ) );
 
133
                    valueList.add( String.valueOf( sourceId ) );
 
134
 
 
135
                    hasValues = false;
 
136
                    
 
137
                    for ( Operand operand : operandList )
 
138
                    {
 
139
                        value = map.get( operand );
 
140
                        
 
141
                        if ( value != null && value.length() > MAX_LENGTH )
 
142
                        {
 
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 + "'" );
 
148
                            
 
149
                            value = null;
 
150
                        }                        
 
151
                        
 
152
                        if ( value != null )
 
153
                        {
 
154
                            hasValues = true;                            
 
155
                            emptyOperands.remove( operand );                            
 
156
                        }
 
157
                        
 
158
                        valueList.add( value );
 
159
                    }
 
160
                    
 
161
                    if ( hasValues )
 
162
                    {
 
163
                        batchHandler.addObject( valueList );
 
164
                    }
 
165
                }
 
166
                
 
167
                log.info( "Crosstabulated data for period " + periodId );
 
168
            }
 
169
            
 
170
            batchHandler.flush();
 
171
        }
 
172
 
 
173
        return emptyOperands;
 
174
    }
 
175
    
 
176
    public void dropCrossTabTable()
 
177
    {
 
178
        crossTabStore.dropCrossTabTable();
 
179
    }
 
180
    
 
181
    public void trimCrossTabTable( Collection<Operand> emptyOperands )
 
182
    {
 
183
        final Collection<String> columnNames = getCrossTabColumnNames( emptyOperands );
 
184
        
 
185
        for ( final String columnName : columnNames )
 
186
        {
 
187
            crossTabStore.dropCrossTabColumn( columnName );
 
188
        }     
 
189
    }
 
190
    
 
191
    public Map<Operand, Integer> getOperandIndexMap( Collection<Operand> operands )
 
192
    {
 
193
        final Map<Integer, String> columnNames = crossTabStore.getCrossTabTableColumns();
 
194
 
 
195
        final Map<Operand, Integer> operandMap = new HashMap<Operand, Integer>();
 
196
        
 
197
        for ( final Map.Entry<Integer, String> entry : columnNames.entrySet() )
 
198
        {
 
199
            if ( entry.getValue().startsWith( CrossTabStore.COLUMN_PREFIX ) )
 
200
            {
 
201
                final String operandString = entry.getValue().replace( CrossTabStore.COLUMN_PREFIX, "" );
 
202
                
 
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 ) );
 
205
                
 
206
                final Operand operand = new Operand( dataElementId, categoryOptionComboId );
 
207
                
 
208
                if ( operands.contains( operand ) )
 
209
                {
 
210
                    operandMap.put( operand, entry.getKey() );
 
211
                }
 
212
            }
 
213
        }
 
214
        
 
215
        return operandMap;
 
216
    }
 
217
    
 
218
    // -------------------------------------------------------------------------
 
219
    // Supportive methods
 
220
    // -------------------------------------------------------------------------
 
221
 
 
222
    /**
 
223
     * Generates a collection of crosstab column names based on a collection of Operands.
 
224
     */
 
225
    private Collection<String> getCrossTabColumnNames( Collection<Operand> operands )
 
226
    {
 
227
        final Collection<String> columnNames = new HashSet<String>( operands.size() );
 
228
        
 
229
        for ( final Operand operand : operands )
 
230
        {
 
231
            columnNames.add( COLUMN_PREFIX + operand.getDataElementId() + SEPARATOR + operand.getOptionComboId() );
 
232
        }
 
233
        
 
234
        return columnNames;
 
235
    }
 
236
 
 
237
    /**
 
238
     * Validates whether the given collections of identifiers are not null and of size greater than 0.
 
239
     */
 
240
    private boolean validate( Collection<Operand> operands, Collection<Integer> periodIds, Collection<Integer> unitIds )
 
241
    {
 
242
        if ( operands == null || periodIds == null || unitIds == null )
 
243
        {
 
244
            return false;
 
245
        }
 
246
        
 
247
        if ( operands.size() == 0 || periodIds.size() == 0 || unitIds.size() == 0 )
 
248
        {
 
249
            return false;
 
250
        }
 
251
        
 
252
        return true;
 
253
    }
 
254
}