View Javadoc
1   package fr.ifremer.quadrige3.synchro.intercept.referential;
2   
3   /*-
4    * #%L
5    * Quadrige3 Core :: Quadrige3 Synchro Core
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2017 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import com.google.common.collect.ImmutableList;
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.SynchroDatabaseMetadata;
31  import fr.ifremer.quadrige3.synchro.meta.referential.ReferentialSynchroTables;
32  import fr.ifremer.quadrige3.synchro.meta.system.RuleSynchroTables;
33  import fr.ifremer.quadrige3.synchro.service.referential.ReferentialSynchroDatabaseConfiguration;
34  import fr.ifremer.quadrige3.synchro.vo.SynchroChangesVO;
35  import org.apache.commons.collections4.CollectionUtils;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.hibernate.tool.hbm2ddl.TableMetadata;
39  
40  import java.io.IOException;
41  import java.sql.SQLException;
42  import java.util.List;
43  
44  /**
45   * Listen all changes on main referential tables, and store changes onto a file (see
46   * ReferentialSynchroContext.getChangeLogFile())
47   * 
48   * @author Benoit Lavenier <benoit.lavenier@e-is.pro>
49   * @since 1.0
50   */
51  public class ChangeLogInterceptor extends AbstractReferentialInterceptor {
52  
53  	private static final Log log = LogFactory.getLog(ChangeLogInterceptor.class);
54  
55  	private static final boolean debug = log.isDebugEnabled();
56  
57  	private static final List<String> includedTableNames = ImmutableList.<String> builder()
58  			.add(ReferentialSynchroTables.MONITORING_LOCATION.name())
59  			.add(ReferentialSynchroTables.REFERENCE_TAXON.name())
60  			.add(ReferentialSynchroTables.TAXON_GROUP.name())
61  			.add(ReferentialSynchroTables.PARAMETER.name())
62  			.add(ReferentialSynchroTables.MATRIX.name())
63  			.add(ReferentialSynchroTables.FRACTION.name())
64  			.add(ReferentialSynchroTables.METHOD.name())
65  			.add(ReferentialSynchroTables.UNIT.name())
66  			.add(ReferentialSynchroTables.ANALYSIS_INSTRUMENT.name())
67  			.add(ReferentialSynchroTables.SAMPLING_EQUIPMENT.name())
68  			.add(ReferentialSynchroTables.PROGRAMME.name())
69  			.add(ReferentialSynchroTables.STRATEGY.name())
70  			.add(ReferentialSynchroTables.MORATORIUM.name())
71  			.add(ReferentialSynchroTables.QUSER.name())
72  			.add(ReferentialSynchroTables.DEPARTMENT.name())
73  			.add(RuleSynchroTables.RULE_LIST.name())
74  			.build();
75  
76  	private boolean isEnable = false;
77  
78  	private SynchroChangesVO changeLog = null;
79  
80  	/** {@inheritDoc} */
81  	@Override
82  	protected void init(ReferentialSynchroDatabaseConfiguration config) {
83  		super.init(config);
84  		isEnable = isChangeLogEnable(config);
85  		setEnableOnWrite(isEnable);
86  	}
87  
88  	/** {@inheritDoc} */
89  	@Override
90  	public SynchroInterceptorBase clone() {
91  		ChangeLogInterceptor result = (ChangeLogInterceptor) super.clone();
92  		result.isEnable = isEnable;
93  		return result;
94  	}
95  
96  	/** {@inheritDoc} */
97  	@Override
98  	public boolean doApply(SynchroDatabaseMetadata meta, TableMetadata table) {
99  		if (!isEnable
100 				|| CollectionUtils.isEmpty(includedTableNames)) {
101 			return false;
102 		}
103 
104 		return includedTableNames.contains(table.getName().toUpperCase());
105 	}
106 
107 	/** {@inheritDoc} */
108 	@Override
109 	protected void doOnWrite(Object[] data,
110 			List<Object> pk,
111 			SynchroTableDao sourceDao,
112 			SynchroTableDao targetDao,
113 			SynchroOperationRepository buffer,
114 			boolean insert) throws SQLException {
115 		String tableName = sourceDao.getTable().getName();
116 
117 		// log changes
118 		if (pk == null) {
119 			pk = sourceDao.getPk(data);
120 		}
121 
122 		if (changeLog == null) {
123 			changeLog = new SynchroChangesVO();
124 		}
125 
126 		// Add this changes to result
127 		if (insert) {
128 			if (debug) {
129 				log.debug(String.format("[%s] detect insert - pk %s", tableName, pk));
130 			}
131 
132 			changeLog.addInsert(tableName, pk);
133 		}
134 		else {
135 			if (debug) {
136 				log.debug(String.format("[%s] detect update - pk %s", tableName, pk));
137 			}
138 
139 			changeLog.addUpdate(tableName, pk);
140 		}
141 	}
142 
143 	/** {@inheritDoc} */
144 	@Override
145 	protected void doOnDelete(List<Object> pk, SynchroTableDao sourceDao, SynchroTableDao targetDao, SynchroOperationRepository buffer) {
146 		String tableName = sourceDao.getTable().getName();
147 
148 		if (changeLog == null) {
149 			changeLog = new SynchroChangesVO();
150 		}
151 
152 		if (debug) {
153 			log.debug(String.format("[%s] detect delete - pk %s", tableName, pk));
154 		}
155 
156 		// Add this changes to result
157 		changeLog.addDelete(tableName, pk);
158 	}
159 
160 	/** {@inheritDoc} */
161 	@Override
162 	protected void doClose() throws IOException {
163 		super.doClose();
164 
165 		// Save result to file
166 		if (changeLog != null) {
167 			changeLog.writeToFile(getConfig().getChangeLogFile(), true /* append */);
168 		}
169 	}
170 
171 	/* -- Internal methods -- */
172 
173 	/**
174 	 * <p>
175 	 * isChangeLogEnable.
176 	 * </p>
177 	 * 
178 	 * @param config
179 	 *            a {@link fr.ifremer.quadrige3.synchro.service.referential.ReferentialSynchroDatabaseConfiguration}
180 	 *            object.
181 	 * @return a boolean.
182 	 */
183 	protected boolean isChangeLogEnable(ReferentialSynchroDatabaseConfiguration config) {
184 		return config.getChangeLogFile() != null;
185 	}
186 }