2 * Copyright (C) 2009 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.database
.update
;
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
;
20 import org
.apache
.logging
.log4j
.LogManager
;
21 import org
.apache
.logging
.log4j
.Logger
;
23 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
24 import eu
.etaxonomy
.cdm
.database
.ICdmDataSource
;
30 public class SortIndexUpdater
extends SchemaUpdaterStepBase
{
32 private static final Logger logger
= LogManager
.getLogger();
34 private final String tableName
;
35 private final String sortIndexColumn
;
36 private final String parentColumn
;
37 private String idColumn
= "id";
38 private String currentSortColumn
= "id";
39 private final boolean includeAudTable
;
40 private Integer baseValue
= 0;
42 public static final SortIndexUpdater
NewInstance(List
<ISchemaUpdaterStep
> stepList
, String stepName
, String tableName
, String parentColumn
, String sortIndexColumn
, boolean includeAudTable
){
43 return new SortIndexUpdater(stepList
, stepName
, tableName
, parentColumn
, sortIndexColumn
, "id", "id", includeAudTable
, 0);
46 public static final SortIndexUpdater
NewInstance(List
<ISchemaUpdaterStep
> stepList
, String stepName
, String tableName
, String parentColumn
, String sortIndexColumn
, String idColumn
, boolean includeAudTable
){
47 return new SortIndexUpdater(stepList
, stepName
, tableName
, parentColumn
, sortIndexColumn
, idColumn
, idColumn
, includeAudTable
, 0);
51 * Returns an SortIndexUpdater that updates an existing sort index which might have missing sortindex numbers in between.
53 public static final SortIndexUpdater
NewUpdateExistingSortindexInstance(List
<ISchemaUpdaterStep
> stepList
, String stepName
, String tableName
, String parentColumn
, String sortIndexColumn
, boolean includeAudTable
){
54 return new SortIndexUpdater(stepList
, stepName
, tableName
, parentColumn
, sortIndexColumn
, "id", sortIndexColumn
, includeAudTable
, 0);
57 protected SortIndexUpdater(List
<ISchemaUpdaterStep
> stepList
, String stepName
, String tableName
, String parentColumn
, String sortIndexColumn
, String idColumn
, String currentSortColumn
, boolean includeAudTable
, Integer baseValue
) {
58 super(stepList
, stepName
);
59 this.tableName
= tableName
;
60 this.parentColumn
= parentColumn
;
61 this.sortIndexColumn
= sortIndexColumn
;
62 this.idColumn
= idColumn
;
63 this.currentSortColumn
= currentSortColumn
;
64 this.includeAudTable
= includeAudTable
;
65 this.baseValue
= baseValue
;
69 public void invoke(ICdmDataSource datasource
, IProgressMonitor monitor
,
70 CaseType caseType
, SchemaUpdateResult result
) throws SQLException
{
71 addColumn(tableName
, datasource
, result
);
74 addColumn(caseType
.transformTo(tableName
+ aud
), datasource
, result
);
79 private void addColumn( String tableName
, ICdmDataSource datasource
, SchemaUpdateResult result
) throws SQLException
{
80 //Note: caseType not required here
81 Map
<Integer
, Set
<Integer
>> indexMap
;
82 if (tableName
== null){
83 tableName
= this.tableName
;
85 indexMap
= makeIndexMap(tableName
, datasource
);
86 updateIndices(tableName
, datasource
, indexMap
);
91 public String
createIndexMapQuery(){
92 String resultsetQuery
= "SELECT @id as id, @parentColumn " +
94 " WHERE @parentColumn IS NOT NULL " +
95 " ORDER BY @parentColumn, @sorted";
96 resultsetQuery
= resultsetQuery
.replace("@id", idColumn
);
97 resultsetQuery
= resultsetQuery
.replace("@tableName", tableName
);
98 resultsetQuery
= resultsetQuery
.replace("@parentColumn", parentColumn
);
99 resultsetQuery
= resultsetQuery
.replace("@sorted", currentSortColumn
);
100 return resultsetQuery
;
104 * For each (new) sortIndex value the according record ids are computed.
105 * This allows updating all records sortindex by sortindex.
109 * @throws SQLException
111 private Map
<Integer
, Set
<Integer
>> makeIndexMap(String tableName
, ICdmDataSource datasource
) throws NumberFormatException
, SQLException
{
112 String resultsetQuery
= createIndexMapQuery();
114 ResultSet rs
= datasource
.executeQuery(resultsetQuery
);
115 List
<Integer
[]> result
= new ArrayList
<>();
117 int id
= rs
.getInt("id");
118 Object oParentId
= rs
.getObject(parentColumn
);
119 if (oParentId
!= null){
120 int parentId
= Integer
.valueOf(oParentId
.toString());
121 result
.add(new Integer
[]{id
,parentId
});
124 return makeIndexMap( result
);
126 //increase index with each row, set to 0 if parent is not the same as the previous one
129 public Map
<Integer
, Set
<Integer
>> makeIndexMap(List
<Integer
[]> oldIndexMap
) throws NumberFormatException
{
130 int oldParentId
= -1;
131 Integer index
= baseValue
;
132 Map
<Integer
, Set
<Integer
>> indexMap
= new HashMap
<>();
133 for (Integer
[] entry
: oldIndexMap
){
135 Integer oParentId
= entry
[1];
136 if (oParentId
!= null){
137 int parentId
= Integer
.valueOf(oParentId
.toString());
138 if (oldParentId
!= parentId
){
140 oldParentId
= parentId
;
144 putIndex(id
, index
, indexMap
);
146 logger
.warn("This should not happen");
149 // System.out.println(oParentId + "," + id+","+ index+";");
154 public String
createUpdateIndicesQuery(String tableName
, Integer index
, String idSetString
){
155 if (tableName
== null){
156 tableName
= this.tableName
;
158 String updateQuery
= "UPDATE @tableName SET @sortIndexColumn = @index WHERE @id IN (@idList) ";
159 updateQuery
= updateQuery
.replace("@tableName", tableName
);
160 updateQuery
= updateQuery
.replace("@sortIndexColumn", sortIndexColumn
);
161 updateQuery
= updateQuery
.replace("@index", index
.toString());
162 updateQuery
= updateQuery
.replace("@idList", idSetString
);
163 updateQuery
= updateQuery
.replace("@id", idColumn
);
167 private void updateIndices(String tableName
, ICdmDataSource datasource
, Map
<Integer
, Set
<Integer
>> indexMap
)
168 throws SQLException
{
170 for (Integer index
: indexMap
.keySet()){
171 Set
<Integer
> set
= indexMap
.get(index
);
172 String idSetString
= makeIdSetString(set
);
174 updateQuery
= createUpdateIndicesQuery(tableName
, index
, idSetString
);
175 datasource
.executeUpdate(updateQuery
);
179 public static String
makeIdSetString(Set
<Integer
> set
) {
180 StringBuffer result
= new StringBuffer(set
.size() * 5);
181 for (Integer id
:set
){
182 result
.append(id
+ ",");
184 return result
.substring(0, result
.length() - 1);
188 * Adds the id to the index (each id is attached to an (sort)index)
190 private void putIndex(Integer id
, Integer index
, Map
<Integer
, Set
<Integer
>> indexMap
) {
191 Set
<Integer
> set
= indexMap
.get(index
);
193 set
= new HashSet
<>();
194 indexMap
.put(index
, set
);
199 public String
getChildrenCountQuery(){
201 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";
202 countSelect
= countSelect
.replace("@tableName", tableName
);
206 public String
getUpdateChildrenCountQuery(int count
, int id
){
208 " UPDATE @tableName "
209 + " SET countChildren = " + count
210 + " WHERE id = " + id
;
211 countUpdate
= countUpdate
.replace("@tableName", tableName
);
215 private void updateChildrenCount(String select
, ICdmDataSource datasource
) throws SQLException
{
217 ResultSet rs
= datasource
.executeQuery(select
);
223 count
= rs
.getInt("realCount");
224 countChildren
= rs
.getInt("countChildren");
225 parentId
= rs
.getInt("parentID");
226 if (count
!= countChildren
){
227 String updateQuery
= getUpdateChildrenCountQuery(count
, parentId
);
228 datasource
.executeUpdate(updateQuery
);
233 public String
getTableName() {