Project

General

Profile

Download (9.04 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2009 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.database.update;
10

    
11
import java.sql.ResultSet;
12
import java.sql.SQLException;
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19

    
20
import org.apache.log4j.Logger;
21

    
22
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
23
import eu.etaxonomy.cdm.database.ICdmDataSource;
24

    
25
/**
26
 * @author a.mueller
27
 * @since 16.09.2010
28
 */
29
public class SortIndexUpdater extends SchemaUpdaterStepBase {
30
	private static final Logger logger = Logger.getLogger(SortIndexUpdater.class);
31

    
32
	private final String tableName;
33
	/**
34
     * @return the tableName
35
     */
36
    public String getTableName() {
37
        return tableName;
38
    }
39

    
40
    private final String sortIndexColumn;
41
	private final String parentColumn;
42
	/**
43
     * @return the parentColumn
44
     */
45
    public String getParentColumn() {
46
        return parentColumn;
47
    }
48

    
49
    private String idColumn = "id";
50
	private String currentSortColumn = "id";
51
	private final boolean includeAudTable;
52
	private Integer baseValue = 0;
53

    
54
	public static final SortIndexUpdater NewInstance(String stepName, String tableName, String parentColumn, String sortIndexColumn, boolean includeAudTable){
55
		return new SortIndexUpdater(stepName, tableName, parentColumn, sortIndexColumn, "id", "id", includeAudTable, 0);
56
	}
57

    
58
	public static final SortIndexUpdater NewInstance(String stepName, String tableName, String parentColumn, String sortIndexColumn, String idColumn, boolean includeAudTable){
59
		return new SortIndexUpdater(stepName, tableName, parentColumn,sortIndexColumn, idColumn, idColumn, includeAudTable, 0);
60
	}
61

    
62
    /**
63
     * Returns an SortIndexUpdater that updates an existing sortindex which might have missing sortindex numbers in between.
64
     *
65
     */
66
    public static final SortIndexUpdater NewUpdateExistingSortindexInstance(String stepName, String tableName, String parentColumn, String sortIndexColumn, boolean includeAudTable){
67
        return new SortIndexUpdater(stepName, tableName, parentColumn,sortIndexColumn, "id", sortIndexColumn, includeAudTable, 0);
68
    }
69

    
70

    
71
	protected SortIndexUpdater(String stepName, String tableName, String parentColumn, String sortIndexColumn, String idColumn, String currentSortColumn, boolean includeAudTable, Integer baseValue) {
72
		super(stepName);
73
		this.tableName = tableName;
74
		this.parentColumn = parentColumn;
75
		this.sortIndexColumn = sortIndexColumn;
76
		this.idColumn = idColumn;
77
		this.currentSortColumn = currentSortColumn;
78
		this.includeAudTable = includeAudTable;
79
		this.baseValue = baseValue;
80
	}
81

    
82
    @Override
83
    public void invoke(ICdmDataSource datasource, IProgressMonitor monitor,
84
            CaseType caseType, SchemaUpdateResult result) throws SQLException {
85
		addColumn(tableName, datasource, result);
86
		if (includeAudTable){
87
			String aud = "_AUD";
88
			addColumn(caseType.transformTo(tableName + aud), datasource, result);
89
		}
90
		return;
91
	}
92

    
93
	private void addColumn( String tableName, ICdmDataSource datasource, SchemaUpdateResult result) throws SQLException {
94
		//Note: caseType not required here
95
	    Map<Integer, Set<Integer>> indexMap ;
96
	    if (tableName == null){
97
	        tableName = this.tableName;
98
	    }
99
	    indexMap = makeIndexMap(tableName, datasource);
100
	    updateIndices(tableName, datasource, indexMap);
101

    
102
		return;
103
	}
104

    
105
	public String createIndexMapQuery(){
106
	       String resultsetQuery = "SELECT @id as id, @parentColumn " +
107
	                " FROM @tableName " +
108
	                " WHERE @parentColumn IS NOT NULL " +
109
	                " ORDER BY @parentColumn, @sorted";
110
	        resultsetQuery = resultsetQuery.replace("@id", idColumn);
111
	        resultsetQuery = resultsetQuery.replace("@tableName", tableName);
112
	        resultsetQuery = resultsetQuery.replace("@parentColumn", parentColumn);
113
	        resultsetQuery = resultsetQuery.replace("@sorted", currentSortColumn);
114
	        return resultsetQuery;
115
	}
116

    
117

    
118
	/**
119
	 * For each (new) sortIndex value the according record ids are computed.
120
	 * This allows updating all records sortindex by sortindex.
121
	 * @param tableName
122
	 * @param datasource
123
	 * @return
124
	 * @throws SQLException
125
	 */
126
	private Map<Integer, Set<Integer>> makeIndexMap(String tableName, ICdmDataSource datasource) throws NumberFormatException, SQLException {
127
	    String resultsetQuery = createIndexMapQuery();
128

    
129
		ResultSet rs = datasource.executeQuery(resultsetQuery);
130
		List<Integer[]> result = new ArrayList<Integer[]>();
131
		while (rs.next()){
132
		    int id = rs.getInt("id");
133
            Object oParentId = rs.getObject(parentColumn);
134
            if (oParentId != null){
135
                int parentId = Integer.valueOf(oParentId.toString());
136
                result.add(new Integer[]{id,parentId});
137
            }
138
		}
139
        return makeIndexMap( result);
140

    
141

    
142

    
143

    
144
		//increase index with each row, set to 0 if parent is not the same as the previous one
145

    
146
	}
147

    
148
	public Map<Integer, Set<Integer>> makeIndexMap(List<Integer[]> oldIndexMap) throws NumberFormatException, SQLException{
149
	    int oldParentId = -1;
150
	    Integer index = baseValue;
151
	    Map<Integer, Set<Integer>> indexMap = new HashMap<>();
152
        for (Integer[] entry: oldIndexMap){
153
            int id = entry[0];
154
            Integer oParentId = entry[1];
155
            if (oParentId != null){
156
                int parentId = Integer.valueOf(oParentId.toString());
157
                if (oldParentId != parentId){
158
                    index = baseValue;
159
                    oldParentId = parentId;
160
                }else{
161
                    index++;
162
                }
163
                putIndex(id, index, indexMap);
164
            }else{
165
                logger.warn("This should not happen");
166
                index = baseValue;
167
            }
168
//          System.out.println(oParentId + "," + id+","+ index+";");
169
        }
170
        return indexMap;
171
	}
172

    
173
	public String createUpdateIndicesQuery(String tableName, Integer index, String idSetString){
174
	    if (tableName == null){
175
	        tableName = this.tableName;
176
	    }
177
	    String updateQuery = "UPDATE @tableName SET @sortIndexColumn = @index WHERE @id IN (@idList) ";
178
        updateQuery = updateQuery.replace("@tableName", tableName);
179
        updateQuery = updateQuery.replace("@sortIndexColumn", sortIndexColumn);
180
        updateQuery = updateQuery.replace("@index", index.toString());
181
        updateQuery = updateQuery.replace("@idList", idSetString);
182
        updateQuery = updateQuery.replace("@id", idColumn);
183
        return updateQuery;
184

    
185
	}
186

    
187
	private void updateIndices(String tableName, ICdmDataSource datasource, Map<Integer, Set<Integer>> indexMap)
188
			throws SQLException {
189
	    String updateQuery ;
190
		for (Integer index :  indexMap.keySet()){
191
			Set<Integer> set = indexMap.get(index);
192
			String idSetString = makeIdSetString(set);
193

    
194
			updateQuery = createUpdateIndicesQuery(tableName, index, idSetString);
195
			datasource.executeUpdate(updateQuery);
196
		}
197
	}
198

    
199
	public static String makeIdSetString(Set<Integer> set) {
200
		StringBuffer result = new StringBuffer(set.size() * 5);
201
		for (Integer id:set){
202
			result.append(id + ",");
203
		}
204
		return result.substring(0, result.length() - 1);
205
	}
206

    
207
	/**
208
	 * Adds the id to the index (each id is attached to an (sort)index)
209
	 */
210
	public void putIndex(Integer id, Integer index, Map<Integer, Set<Integer>> indexMap) {
211
		Set<Integer> set = indexMap.get(index);
212
		if (set == null){
213
			set = new HashSet<>();
214
			indexMap.put(index, set);
215
		}
216
		set.add(id);
217
	}
218

    
219

    
220
	public String getChildrenCountQuery(){
221

    
222
        String countSelect = "SELECT COUNT(child.id) as realCount, parent.countChildren as countChildren, parent.id as parentID FROM @tableName child RIGHT JOIN @tableName parent ON child.parent_id = parent.id GROUP BY parent.id";
223
        countSelect = countSelect.replace("@tableName", tableName);
224
        return countSelect;
225

    
226
	}
227

    
228
	public String getUpdateChildrenCount(int count, int id){
229

    
230
        String countUpdate =  "UPDATE @tableName SET countChildren = " + count+" WHERE id = " + id;
231
        countUpdate = countUpdate.replace("@tableName", tableName);
232

    
233

    
234
        return countUpdate;
235

    
236
    }
237

    
238
	public void updateChildrenCount(String select, ICdmDataSource datasource) throws SQLException{
239
	    ResultSet rs;
240

    
241
        rs = datasource.executeQuery(select);
242

    
243
        List<Integer[]> result = new ArrayList<Integer[]>();
244
        int count ;
245
        int countChildren;
246
        int parentId;
247

    
248
        while (rs.next()){
249
            count = rs.getInt("realCount");
250
            countChildren = rs.getInt("countChildren");
251
            parentId = rs.getInt("parentID");
252
            if (count != countChildren){
253
                String updateQuery = getUpdateChildrenCount(count, parentId);
254
                datasource.executeUpdate(updateQuery);
255
            }
256
        }
257

    
258
	}
259

    
260
}
(26-26/35)