1 package fr.ifremer.quadrige3.synchro.intercept.referential;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import com.google.common.eventbus.Subscribe;
27 import fr.ifremer.common.synchro.dao.SynchroTableDao;
28 import fr.ifremer.common.synchro.intercept.SynchroInterceptorBase;
29 import fr.ifremer.common.synchro.intercept.SynchroOperationRepository;
30 import fr.ifremer.common.synchro.meta.SynchroTableMetadata;
31 import fr.ifremer.common.synchro.meta.event.CreateQueryEvent;
32 import fr.ifremer.common.synchro.meta.event.LoadTableEvent;
33 import fr.ifremer.common.synchro.query.SynchroQueryBuilder;
34 import fr.ifremer.common.synchro.query.SynchroQueryName;
35 import fr.ifremer.common.synchro.query.SynchroQueryOperator;
36 import fr.ifremer.quadrige3.core.dao.referential.StatusCode;
37 import fr.ifremer.quadrige3.core.dao.technical.Daos;
38 import fr.ifremer.quadrige3.synchro.meta.DatabaseColumns;
39 import fr.ifremer.quadrige3.synchro.meta.data.DataSynchroTables;
40 import fr.ifremer.quadrige3.synchro.meta.referential.ReferentialSynchroTables;
41 import fr.ifremer.quadrige3.synchro.service.SynchroDirection;
42 import fr.ifremer.quadrige3.synchro.service.referential.ReferentialSynchroContext;
43 import fr.ifremer.quadrige3.synchro.service.referential.ReferentialSynchroDatabaseConfiguration;
44 import org.apache.commons.collections4.CollectionUtils;
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47
48 import java.io.IOException;
49 import java.sql.PreparedStatement;
50 import java.sql.ResultSet;
51 import java.sql.SQLException;
52 import java.sql.Types;
53 import java.util.List;
54 import java.util.Set;
55
56
57
58
59
60
61
62
63
64
65
66 public class ReferenceTaxonInterceptor extends AbstractReferentialInterceptor {
67
68 private static final Log log = LogFactory.getLog(ReferenceTaxonInterceptor.class);
69
70 static String UPDATED_ITEM_HISTORY_TABLE = "UPDATED_ITEM_HISTORY";
71 private String localOnlyWhereClause;
72 private PreparedStatement updatedItemHistoryTableExistsStatement = null;
73 private PreparedStatement selectNewRefTaxonIdStatement = null;
74 private PreparedStatement updateTaxonMeasurementByRefTaxonIdStatement = null;
75 private Boolean updatedItemHistoryTableExists = null;
76
77
78
79
80
81
82 public ReferenceTaxonInterceptor() {
83 super(ReferentialSynchroTables.REFERENCE_TAXON.name());
84 setEnableOnWrite(true);
85 }
86
87
88 @Override
89 protected void init(ReferentialSynchroDatabaseConfiguration config) {
90 localOnlyWhereClause = createLocalOnlyWhereClause(config);
91 }
92
93
94 @Override
95 public SynchroInterceptorBase clone() {
96 ReferenceTaxonInterceptor result = (ReferenceTaxonInterceptor) super.clone();
97 result.localOnlyWhereClause = this.localOnlyWhereClause;
98 return result;
99 }
100
101 @Override
102 protected void doOnDelete(List<Object> pk, SynchroTableDao sourceDao, SynchroTableDao targetDao, SynchroOperationRepository buffer) throws SQLException {
103
104 ReferentialSynchroContext context = (ReferentialSynchroContext) buffer.getSynchroContext();
105
106 if (context.getDirection() == SynchroDirection.IMPORT_TEMP2LOCAL || context.getDirection() == SynchroDirection.IMPORT_FILE2LOCAL) {
107
108 Long id = Daos.convertToLong(pk.get(0));
109
110
111 updateTaxonMeasurementByRefTaxonId(sourceDao, targetDao, id);
112 }
113
114 }
115
116 private void updateTaxonMeasurementByRefTaxonId(SynchroTableDao sourceDao, SynchroTableDao targetDao, Long id) throws SQLException {
117 if (updateTaxonMeasurementByRefTaxonIdStatement == null || updateTaxonMeasurementByRefTaxonIdStatement.isClosed()) {
118 updateTaxonMeasurementByRefTaxonIdStatement = targetDao.getPreparedStatement(getUpdateTaxonMeasurementByRefTaxonIdQuery());
119 }
120
121
122 Long newRefTaxonId = findNewRefTaxonId(sourceDao, id);
123 if (newRefTaxonId != null) {
124 updateTaxonMeasurementByRefTaxonIdStatement.setLong(1, newRefTaxonId);
125 } else {
126 updateTaxonMeasurementByRefTaxonIdStatement.setNull(1, Types.NUMERIC);
127 }
128 updateTaxonMeasurementByRefTaxonIdStatement.setLong(2, id);
129 updateTaxonMeasurementByRefTaxonIdStatement.execute();
130 }
131
132 private Long findNewRefTaxonId(SynchroTableDao dao, Long id) {
133
134 if (historyTableExists(dao)) {
135
136 ResultSet resultSet = null;
137 try {
138 try {
139 if (selectNewRefTaxonIdStatement == null || selectNewRefTaxonIdStatement.isClosed()) {
140 selectNewRefTaxonIdStatement = dao.getPreparedStatement(
141 String.format("select NEW_VALUE from %s where OBJECT_TYPE_CD='%s' and COLUMN_NAME='%s' and OLD_VALUE=?",
142 UPDATED_ITEM_HISTORY_TABLE,
143 ReferentialSynchroTables.TAXON_NAME.name(),
144 DatabaseColumns.REF_TAXON_ID)
145 );
146 }
147 selectNewRefTaxonIdStatement.setString(1, id.toString());
148 resultSet = selectNewRefTaxonIdStatement.executeQuery();
149 resultSet.next();
150 String result = resultSet.getString(1);
151 if (result != null) {
152 return Long.parseLong(result);
153 }
154 } catch (SQLException | NumberFormatException e) {
155 log.warn(String.format("Can't get new %s (from deleted %s) from %s : %s", DatabaseColumns.REF_TAXON_ID, id, UPDATED_ITEM_HISTORY_TABLE, e.getMessage()));
156 }
157 } finally {
158 Daos.closeSilently(resultSet);
159 }
160
161 }
162 return null;
163 }
164
165 private boolean historyTableExists(SynchroTableDao dao) {
166 if (updatedItemHistoryTableExists != null) {
167 return updatedItemHistoryTableExists;
168 }
169
170 ResultSet resultSet = null;
171 try {
172 try {
173 if (updatedItemHistoryTableExistsStatement == null || updatedItemHistoryTableExistsStatement.isClosed()) {
174 updatedItemHistoryTableExistsStatement = dao.getPreparedStatement(getUpdatedItemHistoryTableExistsQuery());
175 }
176 resultSet = updatedItemHistoryTableExistsStatement.executeQuery();
177 resultSet.next();
178 updatedItemHistoryTableExists = resultSet.getLong(1) != 0;
179 } catch (SQLException e) {
180 log.warn(String.format("Can't check if table %s exists: %s", UPDATED_ITEM_HISTORY_TABLE, e.getMessage()));
181 updatedItemHistoryTableExists = false;
182 }
183 } finally {
184 Daos.closeSilently(resultSet);
185 }
186
187 return updatedItemHistoryTableExists;
188 }
189
190 private String getUpdatedItemHistoryTableExistsQuery() {
191 return String.format("select count(*) from INFORMATION_SCHEMA.TABLES where TABLE_NAME='%s'", UPDATED_ITEM_HISTORY_TABLE);
192 }
193
194 @Override
195 protected void doClose() throws IOException {
196 super.doClose();
197
198 Daos.closeSilently(updatedItemHistoryTableExistsStatement);
199 updatedItemHistoryTableExistsStatement = null;
200 Daos.closeSilently(selectNewRefTaxonIdStatement);
201 selectNewRefTaxonIdStatement = null;
202 Daos.closeSilently(updateTaxonMeasurementByRefTaxonIdStatement);
203 updateTaxonMeasurementByRefTaxonIdStatement = null;
204 }
205
206
207
208
209
210
211
212
213
214 @Subscribe
215 public void handleQuery(CreateQueryEvent e) {
216
217 switch (e.queryName) {
218 case count:
219 case countFromUpdateDate:
220 case select:
221 case selectFromUpdateDate:
222 case selectMaxUpdateDate:
223
224 e.sql = addRestriction(e.source, e.queryName, e.sql);
225
226 default:
227 break;
228 }
229 }
230
231
232
233
234
235
236
237
238
239 @Subscribe
240 public void handleTableLoad(LoadTableEvent e) {
241 SynchroTableMetadata table = e.table;
242
243
244 if (!table.isRoot()
245 && localOnlyWhereClause != null) {
246 table.setRoot(true);
247 }
248 }
249
250
251
252
253
254
255
256
257
258
259
260
261
262 protected String createLocalOnlyWhereClause(ReferentialSynchroDatabaseConfiguration config) {
263
264 Set<String> statusCodeIncludes = config.getStatusCodeIncludes();
265 if (CollectionUtils.isEmpty(statusCodeIncludes)
266 || (!statusCodeIncludes.contains(StatusCode.LOCAL_DISABLE.getValue())
267 && !statusCodeIncludes.contains(StatusCode.LOCAL_ENABLE.getValue()))) {
268 return null;
269 }
270
271
272 return String.format("t.%s < 0",
273 DatabaseColumns.REF_TAXON_ID);
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 protected String addRestriction(SynchroTableMetadata table, SynchroQueryName queryName, String sql) {
290
291
292 if (localOnlyWhereClause == null) {
293 return sql;
294 }
295
296 SynchroQueryBuilder queryBuilder = SynchroQueryBuilder.newBuilder(sql);
297 queryBuilder.addWhere(SynchroQueryOperator.AND, localOnlyWhereClause);
298
299 return queryBuilder.build();
300 }
301
302
303
304
305 private String getUpdateTaxonMeasurementByRefTaxonIdQuery() {
306 return String.format(
307 "UPDATE %s SET %s=? WHERE %s=?",
308 DataSynchroTables.TAXON_MEASUREMENT.name(),
309 DatabaseColumns.REF_TAXON_ID.name(),
310 DatabaseColumns.REF_TAXON_ID.name()
311 );
312 }
313
314 }