View Javadoc
1   package fr.ifremer.quadrige2.synchro.intercept.data;
2   
3   /*-
4    * #%L
5    * Quadrige2 Core :: Quadrige2 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.base.Joiner;
27  import com.google.common.collect.ImmutableList;
28  import com.google.common.collect.Sets;
29  import com.google.common.eventbus.Subscribe;
30  import fr.ifremer.common.synchro.intercept.SynchroInterceptorBase;
31  import fr.ifremer.common.synchro.meta.SynchroTableMetadata;
32  import fr.ifremer.common.synchro.meta.event.CreateQueryEvent;
33  import fr.ifremer.common.synchro.meta.event.LoadTableEvent;
34  import fr.ifremer.common.synchro.query.SynchroQueryBuilder;
35  import fr.ifremer.common.synchro.query.SynchroQueryOperator;
36  import fr.ifremer.quadrige2.core.dao.ObjectTypes;
37  import fr.ifremer.quadrige2.synchro.meta.DatabaseColumns;
38  import fr.ifremer.quadrige2.synchro.meta.data.DataSynchroTables;
39  import fr.ifremer.quadrige2.synchro.service.SynchroDirection;
40  import org.apache.commons.collections4.CollectionUtils;
41  
42  import java.util.List;
43  import java.util.Set;
44  
45  /**
46   * Import DELETED_ITEM_HISTORY rows, limited to data tables
47   * 
48   * @author Benoit Lavenier <benoit.lavenier@e-is.pro>
49   * @since 1.0
50   */
51  public class DeletedItemHistoryInterceptor extends AbstractDataInterceptor {
52  
53  	/** Constant <code>NATURAL_ID_COLUMNS</code> */
54  	public static final List<String> NATURAL_ID_COLUMNS = ImmutableList.of(
55  			DatabaseColumns.OBJECT_TYPE_CD.name(),
56  			DatabaseColumns.OBJECT_ID.name(),
57  			DatabaseColumns.OBJECT_CD.name());
58  
59  	private String whereClauseOnTableIncludes = null;
60  
61  	private String whereClauseForExportLocal2Temp = null;
62  
63  	/**
64  	 * <p>
65  	 * Constructor for DeletedItemHistoryInterceptor.
66  	 * </p>
67  	 */
68  	public DeletedItemHistoryInterceptor() {
69  
70  		super(DataSynchroTables.DELETED_ITEM_HISTORY.name(),
71  				// Exclude Temp -> Local (process in a special code)
72  				SynchroDirection.IMPORT_SERVER2TEMP,
73  				SynchroDirection.EXPORT_LOCAL2TEMP,
74  				SynchroDirection.EXPORT_TEMP2SERVER);
75  	}
76  
77  	/** {@inheritDoc} */
78  	@Override
79  	public SynchroInterceptorBase clone() {
80  		DeletedItemHistoryInterceptor newBean = (DeletedItemHistoryInterceptor) super.clone();
81  		newBean.whereClauseOnTableIncludes = this.whereClauseOnTableIncludes;
82  		return newBean;
83  	}
84  
85  	/**
86  	 * <p>
87  	 * handleCreateQuery.
88  	 * </p>
89  	 * 
90  	 * @param e
91  	 *            a {@link fr.ifremer.common.synchro.meta.event.CreateQueryEvent} object.
92  	 */
93  	@Subscribe
94  	public void handleCreateQuery(CreateQueryEvent e) {
95  		switch (e.queryName) {
96  		case count:
97  		case countFromUpdateDate:
98  		case select:
99  		case selectFromUpdateDate:
100 		case selectMaxUpdateDate:
101 			e.sql = addRestrictions(e.sql);
102 			break;
103 
104 		default:
105 			break;
106 		}
107 	}
108 
109 	/**
110 	 * <p>
111 	 * handleTableLoad.
112 	 * </p>
113 	 * 
114 	 * @param e
115 	 *            a {@link fr.ifremer.common.synchro.meta.event.LoadTableEvent} object.
116 	 */
117 	@Subscribe
118 	public void handleTableLoad(LoadTableEvent e) {
119 		SynchroTableMetadata table = e.table;
120 		SynchroDirection direction = getConfig().getDirection();
121 
122 		// Do not import this table to local
123 		boolean isRoot = isInDirections(SynchroDirection.IMPORT_SERVER2TEMP,
124 				SynchroDirection.EXPORT_LOCAL2TEMP,
125 				SynchroDirection.EXPORT_TEMP2SERVER);
126 
127 		e.table.setRoot(isRoot);
128 
129 		// Export: Temp DB -> Server DB
130 		if (direction == SynchroDirection.EXPORT_TEMP2SERVER) {
131 			// Define natural id, to avoid 2 rows inserted (because trigger will insert row also)
132 			table.addUniqueConstraint("NATURAL_ID_UNIQUE_C", NATURAL_ID_COLUMNS, SynchroTableMetadata.DuplicateKeyStrategy.WARN);
133 		}
134 	}
135 
136 	/* -- Internal methods -- */
137 
138 	private String addRestrictions(String sql) {
139 
140 		SynchroQueryBuilder query = SynchroQueryBuilder.newBuilder(sql);
141 
142 		// Add limit on included tables
143 		if (whereClauseOnTableIncludes == null) {
144 			whereClauseOnTableIncludes = createWhereClauseOnTableIncludes();
145 		}
146 		query.addWhere(SynchroQueryOperator.AND, whereClauseOnTableIncludes);
147 
148 		// Export: only delete done by connected user, and not exported deletion
149 		if (getConfig().getDirection() == SynchroDirection.EXPORT_LOCAL2TEMP) {
150 			if (whereClauseForExportLocal2Temp == null) {
151 				whereClauseForExportLocal2Temp = createWhereClauseForExportLocal2Temp();
152 			}
153 
154 			query.addWhere(SynchroQueryOperator.AND, whereClauseForExportLocal2Temp);
155 		}
156 
157 		return query.build();
158 	}
159 
160 	private String createWhereClauseOnTableIncludes() {
161 		Set<String> tableToIncludes = DataSynchroTables.getImportTablesIncludes();
162 
163 		// If no tables configured : should return no lines
164 		if (CollectionUtils.isEmpty(tableToIncludes)) {
165 			return "1=2";
166 		}
167 
168 		Set<String> allObjectTypeCds = Sets.newHashSet();
169 		for (String tableName : tableToIncludes) {
170 			Set<String> objectTypeCds = ObjectTypes.getObjectTypeFromTableName(tableName);
171 			if (CollectionUtils.isNotEmpty(objectTypeCds)) {
172 				allObjectTypeCds.addAll(objectTypeCds);
173 			}
174 			else {
175 				// By default, add the table name itself (i.e. PERSON_SESSION_VESSEL)
176 				allObjectTypeCds.add(tableName);
177 			}
178 		}
179 
180 		// Remove itself
181 		allObjectTypeCds.remove(DataSynchroTables.DELETED_ITEM_HISTORY.name());
182 
183 		return new StringBuilder()
184 				.append(DatabaseColumns.OBJECT_TYPE_CD)
185 				.append(" IN ('")
186 				.append(Joiner.on("','").join(allObjectTypeCds))
187 				.append("')")
188 				.toString();
189 	}
190 
191 	private String createWhereClauseForExportLocal2Temp() {
192 
193 		// mantis #22850 : do not limit to the recorder of the deletion
194 		// Integer recorderPersonId = checkAndGetPersonId();
195 		// return String.format("%s = %s AND %s is null",COLUMN_RECORDER_PERSON,recorderPersonId,COLUMN_REMOTE_ID);
196 
197 		return DatabaseColumns.REMOTE_ID.name() + " is null";
198 	}
199 }