Project

General

Profile

Download (8.89 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.logging.log4j.LogManager;import org.apache.logging.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

    
31
    private static final Logger logger = LogManager.getLogger(SortIndexUpdater.class);
32

    
33
	private final String tableName;
34
    private final String sortIndexColumn;
35
	private final String parentColumn;
36
    private String idColumn = "id";
37
	private String currentSortColumn = "id";
38
	private final boolean includeAudTable;
39
	private Integer baseValue = 0;
40

    
41
	public static final SortIndexUpdater NewInstance(List<ISchemaUpdaterStep> stepList, String stepName, String tableName, String parentColumn, String sortIndexColumn, boolean includeAudTable){
42
		return new SortIndexUpdater(stepList, stepName, tableName, parentColumn, sortIndexColumn, "id", "id", includeAudTable, 0);
43
	}
44

    
45
	public static final SortIndexUpdater NewInstance(List<ISchemaUpdaterStep> stepList, String stepName, String tableName, String parentColumn, String sortIndexColumn, String idColumn, boolean includeAudTable){
46
		return new SortIndexUpdater(stepList, stepName, tableName, parentColumn, sortIndexColumn, idColumn, idColumn, includeAudTable, 0);
47
	}
48

    
49
    /**
50
     * Returns an SortIndexUpdater that updates an existing sort index which might have missing sortindex numbers in between.
51
     */
52
    public static final SortIndexUpdater NewUpdateExistingSortindexInstance(List<ISchemaUpdaterStep> stepList, String stepName, String tableName, String parentColumn, String sortIndexColumn, boolean includeAudTable){
53
        return new SortIndexUpdater(stepList, stepName, tableName, parentColumn, sortIndexColumn, "id", sortIndexColumn, includeAudTable, 0);
54
    }
55

    
56
	protected SortIndexUpdater(List<ISchemaUpdaterStep> stepList, String stepName, String tableName, String parentColumn, String sortIndexColumn, String idColumn, String currentSortColumn, boolean includeAudTable, Integer baseValue) {
57
		super(stepList, stepName);
58
		this.tableName = tableName;
59
		this.parentColumn = parentColumn;
60
		this.sortIndexColumn = sortIndexColumn;
61
		this.idColumn = idColumn;
62
		this.currentSortColumn = currentSortColumn;
63
		this.includeAudTable = includeAudTable;
64
		this.baseValue = baseValue;
65
	}
66

    
67
    @Override
68
    public void invoke(ICdmDataSource datasource, IProgressMonitor monitor,
69
            CaseType caseType, SchemaUpdateResult result) throws SQLException {
70
		addColumn(tableName, datasource, result);
71
		if (includeAudTable){
72
			String aud = "_AUD";
73
			addColumn(caseType.transformTo(tableName + aud), datasource, result);
74
		}
75
		return;
76
	}
77

    
78
	private void addColumn( String tableName, ICdmDataSource datasource, SchemaUpdateResult result) throws SQLException {
79
		//Note: caseType not required here
80
	    Map<Integer, Set<Integer>> indexMap ;
81
	    if (tableName == null){
82
	        tableName = this.tableName;
83
	    }
84
	    indexMap = makeIndexMap(tableName, datasource);
85
	    updateIndices(tableName, datasource, indexMap);
86

    
87
		return;
88
	}
89

    
90
	public String createIndexMapQuery(){
91
	       String resultsetQuery = "SELECT @id as id, @parentColumn " +
92
	                " FROM @tableName " +
93
	                " WHERE @parentColumn IS NOT NULL " +
94
	                " ORDER BY @parentColumn, @sorted";
95
	        resultsetQuery = resultsetQuery.replace("@id", idColumn);
96
	        resultsetQuery = resultsetQuery.replace("@tableName", tableName);
97
	        resultsetQuery = resultsetQuery.replace("@parentColumn", parentColumn);
98
	        resultsetQuery = resultsetQuery.replace("@sorted", currentSortColumn);
99
	        return resultsetQuery;
100
	}
101

    
102
	/**
103
	 * For each (new) sortIndex value the according record ids are computed.
104
	 * This allows updating all records sortindex by sortindex.
105
	 * @param tableName
106
	 * @param datasource
107
	 * @return
108
	 * @throws SQLException
109
	 */
110
	private Map<Integer, Set<Integer>> makeIndexMap(String tableName, ICdmDataSource datasource) throws NumberFormatException, SQLException {
111
	    String resultsetQuery = createIndexMapQuery();
112

    
113
		ResultSet rs = datasource.executeQuery(resultsetQuery);
114
		List<Integer[]> result = new ArrayList<Integer[]>();
115
		while (rs.next()){
116
		    int id = rs.getInt("id");
117
            Object oParentId = rs.getObject(parentColumn);
118
            if (oParentId != null){
119
                int parentId = Integer.valueOf(oParentId.toString());
120
                result.add(new Integer[]{id,parentId});
121
            }
122
		}
123
        return makeIndexMap( result);
124

    
125
		//increase index with each row, set to 0 if parent is not the same as the previous one
126
	}
127

    
128
	public Map<Integer, Set<Integer>> makeIndexMap(List<Integer[]> oldIndexMap) throws NumberFormatException{
129
	    int oldParentId = -1;
130
	    Integer index = baseValue;
131
	    Map<Integer, Set<Integer>> indexMap = new HashMap<>();
132
        for (Integer[] entry: oldIndexMap){
133
            int id = entry[0];
134
            Integer oParentId = entry[1];
135
            if (oParentId != null){
136
                int parentId = Integer.valueOf(oParentId.toString());
137
                if (oldParentId != parentId){
138
                    index = baseValue;
139
                    oldParentId = parentId;
140
                }else{
141
                    index++;
142
                }
143
                putIndex(id, index, indexMap);
144
            }else{
145
                logger.warn("This should not happen");
146
                index = baseValue;
147
            }
148
//          System.out.println(oParentId + "," + id+","+ index+";");
149
        }
150
        return indexMap;
151
	}
152

    
153
	public String createUpdateIndicesQuery(String tableName, Integer index, String idSetString){
154
	    if (tableName == null){
155
	        tableName = this.tableName;
156
	    }
157
	    String updateQuery = "UPDATE @tableName SET @sortIndexColumn = @index WHERE @id IN (@idList) ";
158
        updateQuery = updateQuery.replace("@tableName", tableName);
159
        updateQuery = updateQuery.replace("@sortIndexColumn", sortIndexColumn);
160
        updateQuery = updateQuery.replace("@index", index.toString());
161
        updateQuery = updateQuery.replace("@idList", idSetString);
162
        updateQuery = updateQuery.replace("@id", idColumn);
163
        return updateQuery;
164
	}
165

    
166
	private void updateIndices(String tableName, ICdmDataSource datasource, Map<Integer, Set<Integer>> indexMap)
167
			throws SQLException {
168
	    String updateQuery ;
169
		for (Integer index :  indexMap.keySet()){
170
			Set<Integer> set = indexMap.get(index);
171
			String idSetString = makeIdSetString(set);
172

    
173
			updateQuery = createUpdateIndicesQuery(tableName, index, idSetString);
174
			datasource.executeUpdate(updateQuery);
175
		}
176
	}
177

    
178
	public static String makeIdSetString(Set<Integer> set) {
179
		StringBuffer result = new StringBuffer(set.size() * 5);
180
		for (Integer id:set){
181
			result.append(id + ",");
182
		}
183
		return result.substring(0, result.length() - 1);
184
	}
185

    
186
	/**
187
	 * Adds the id to the index (each id is attached to an (sort)index)
188
	 */
189
	public void putIndex(Integer id, Integer index, Map<Integer, Set<Integer>> indexMap) {
190
		Set<Integer> set = indexMap.get(index);
191
		if (set == null){
192
			set = new HashSet<>();
193
			indexMap.put(index, set);
194
		}
195
		set.add(id);
196
	}
197

    
198
	public String getChildrenCountQuery(){
199

    
200
        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";
201
        countSelect = countSelect.replace("@tableName", tableName);
202
        return countSelect;
203
	}
204

    
205
	public String getUpdateChildrenCount(int count, int id){
206
        String countUpdate =
207
                  " UPDATE @tableName "
208
                + " SET countChildren = " + count
209
                + " WHERE id = " + id;
210
        countUpdate = countUpdate.replace("@tableName", tableName);
211
        return countUpdate;
212
    }
213

    
214
	public void updateChildrenCount(String select, ICdmDataSource datasource) throws SQLException{
215

    
216
	    ResultSet rs = datasource.executeQuery(select);
217

    
218
        int count ;
219
        int countChildren;
220
        int parentId;
221
        while (rs.next()){
222
            count = rs.getInt("realCount");
223
            countChildren = rs.getInt("countChildren");
224
            parentId = rs.getInt("parentID");
225
            if (count != countChildren){
226
                String updateQuery = getUpdateChildrenCount(count, parentId);
227
                datasource.executeUpdate(updateQuery);
228
            }
229
        }
230
	}
231

    
232
    public String getParentColumn() {
233
        return parentColumn;
234
    }
235

    
236
    public String getTableName() {
237
        return tableName;
238
    }
239
}
(31-31/41)