Project

General

Profile

Download (8.94 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
 * @date 16.09.2010
28
 */
29
public class SortIndexUpdater extends SchemaUpdaterStepBase<SortIndexUpdater> {
30
	private static final Logger logger = Logger.getLogger(SortIndexUpdater.class);
31

    
32
	private final String tableName;
33
	private final String sortIndexColumn;
34
	private final String parentColumn;
35
	/**
36
     * @return the parentColumn
37
     */
38
    public String getParentColumn() {
39
        return parentColumn;
40
    }
41

    
42
    private String idColumn = "id";
43
	private String currentSortColumn = "id";
44
	private final boolean includeAudTable;
45
	private Integer baseValue = 0;
46

    
47
	public static final SortIndexUpdater NewInstance(String stepName, String tableName, String parentColumn, String sortIndexColumn, boolean includeAudTable){
48
		return new SortIndexUpdater(stepName, tableName, parentColumn, sortIndexColumn, "id", "id", includeAudTable, 0);
49
	}
50

    
51
	public static final SortIndexUpdater NewInstance(String stepName, String tableName, String parentColumn, String sortIndexColumn, String idColumn, boolean includeAudTable){
52
		return new SortIndexUpdater(stepName, tableName, parentColumn,sortIndexColumn, idColumn, idColumn, includeAudTable, 0);
53
	}
54

    
55
    /**
56
     * Returns an SortIndexUpdater that updates an existing sortindex which might have missing sortindex numbers in between.
57
     *
58
     */
59
    public static final SortIndexUpdater NewUpdateExistingSortindexInstance(String stepName, String tableName, String parentColumn, String sortIndexColumn, boolean includeAudTable){
60
        return new SortIndexUpdater(stepName, tableName, parentColumn,sortIndexColumn, "id", sortIndexColumn, includeAudTable, 0);
61
    }
62

    
63

    
64
	protected SortIndexUpdater(String stepName, String tableName, String parentColumn, String sortIndexColumn, String idColumn, String currentSortColumn, boolean includeAudTable, Integer baseValue) {
65
		super(stepName);
66
		this.tableName = tableName;
67
		this.parentColumn = parentColumn;
68
		this.sortIndexColumn = sortIndexColumn;
69
		this.idColumn = idColumn;
70
		this.currentSortColumn = currentSortColumn;
71
		this.includeAudTable = includeAudTable;
72
		this.baseValue = baseValue;
73
	}
74

    
75
	@Override
76
	public Integer invoke(ICdmDataSource datasource, IProgressMonitor monitor, CaseType caseType) throws SQLException {
77
		boolean result = true;
78
		result &= addColumn(tableName, datasource);
79
		if (includeAudTable){
80
			String aud = "_AUD";
81
			result &= addColumn(caseType.transformTo(tableName + aud), datasource);
82
		}
83
		return (result == true )? 0 : null;
84
	}
85

    
86
	private boolean addColumn( String tableName, ICdmDataSource datasource) throws SQLException {
87
		//Note: caseType not required here
88
	    Map<Integer, Set<Integer>> indexMap ;
89
	    if (tableName == null){
90
	        tableName = this.tableName;
91
	    }
92
	    indexMap = makeIndexMap(tableName, datasource);
93
	    updateIndices(tableName, datasource, indexMap);
94

    
95
		return true;
96
	}
97

    
98
	public String createIndexMapQuery(){
99
	       String resultsetQuery = "SELECT @id as id, @parentColumn " +
100
	                " FROM @tableName " +
101
	                " WHERE @parentColumn IS NOT NULL " +
102
	                " ORDER BY @parentColumn, @sorted";
103
	        resultsetQuery = resultsetQuery.replace("@id", idColumn);
104
	        resultsetQuery = resultsetQuery.replace("@tableName", tableName);
105
	        resultsetQuery = resultsetQuery.replace("@parentColumn", parentColumn);
106
	        resultsetQuery = resultsetQuery.replace("@sorted", currentSortColumn);
107
	        return resultsetQuery;
108
	}
109

    
110

    
111
	/**
112
	 * For each (new) sortIndex value the according record ids are computed.
113
	 * This allows updating all records sortindex by sortindex.
114
	 * @param tableName
115
	 * @param datasource
116
	 * @return
117
	 * @throws SQLException
118
	 */
119
	private Map<Integer, Set<Integer>> makeIndexMap(String tableName, ICdmDataSource datasource) throws NumberFormatException, SQLException {
120
	    String resultsetQuery = createIndexMapQuery();
121

    
122
		ResultSet rs = datasource.executeQuery(resultsetQuery);
123
		List<Integer[]> result = new ArrayList<Integer[]>();
124
		while (rs.next()){
125
		    int id = rs.getInt("id");
126
            Object oParentId = rs.getObject(parentColumn);
127
            if (oParentId != null){
128
                int parentId = Integer.valueOf(oParentId.toString());
129
                result.add(new Integer[]{id,parentId});
130
            }
131
		}
132
        return makeIndexMap( result);
133

    
134

    
135

    
136

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

    
139
	}
140

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

    
166
	public String createUpdateIndicesQuery(String tableName, Integer index, String idSetString){
167
	    if (tableName == null){
168
	        tableName = this.tableName;
169
	    }
170
	    String updateQuery = "UPDATE @tableName SET @sortIndexColumn = @index WHERE @id IN (@idList) ";
171
        updateQuery = updateQuery.replace("@tableName", tableName);
172
        updateQuery = updateQuery.replace("@sortIndexColumn", sortIndexColumn);
173
        updateQuery = updateQuery.replace("@index", index.toString());
174
        updateQuery = updateQuery.replace("@idList", idSetString);
175
        updateQuery = updateQuery.replace("@id", idColumn);
176
        return updateQuery;
177

    
178
	}
179

    
180
	private void updateIndices(String tableName, ICdmDataSource datasource, Map<Integer, Set<Integer>> indexMap)
181
			throws SQLException {
182
	    String updateQuery ;
183
		for (Integer index :  indexMap.keySet()){
184
			Set<Integer> set = indexMap.get(index);
185
			String idSetString = makeIdSetString(set);
186

    
187
			updateQuery = createUpdateIndicesQuery(tableName, index, idSetString);
188
			datasource.executeUpdate(updateQuery);
189
		}
190
	}
191

    
192
	public static String makeIdSetString(Set<Integer> set) {
193
		StringBuffer result = new StringBuffer(set.size() * 5);
194
		for (Integer id:set){
195
			result.append(id + ",");
196
		}
197
		return result.substring(0, result.length() - 1);
198
	}
199

    
200
	/**
201
	 * Adds the id to the index (each id is attached to an (sort)index)
202
	 */
203
	public void putIndex(Integer id, Integer index, Map<Integer, Set<Integer>> indexMap) {
204
		Set<Integer> set = indexMap.get(index);
205
		if (set == null){
206
			set = new HashSet<>();
207
			indexMap.put(index, set);
208
		}
209
		set.add(id);
210
	}
211

    
212

    
213
	public String getChildrenCountQuery(){
214

    
215
        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";
216
        countSelect = countSelect.replace("@tableName", tableName);
217
        return countSelect;
218

    
219
	}
220

    
221
	public String getUpdateChildrenCount(int count, int id){
222

    
223
        String countUpdate =  "UPDATE @tableName SET countChildren = " + count+" WHERE id = " + id;
224
        countUpdate = countUpdate.replace("@tableName", tableName);
225

    
226

    
227
        return countUpdate;
228

    
229
    }
230

    
231
	public void updateChildrenCount(String select, ICdmDataSource datasource) throws SQLException{
232
	    ResultSet rs;
233

    
234
        rs = datasource.executeQuery(select);
235

    
236
        List<Integer[]> result = new ArrayList<Integer[]>();
237
        int count ;
238
        int countChildren;
239
        int parentId;
240

    
241
        while (rs.next()){
242
            count = rs.getInt("realCount");
243
            countChildren = rs.getInt("countChildren");
244
            parentId = rs.getInt("parentID");
245
            if (count != countChildren){
246
                String updateQuery = getUpdateChildrenCount(count, parentId);
247
                datasource.executeUpdate(updateQuery);
248
            }
249
        }
250

    
251
	}
252

    
253
}
(26-26/36)