001
014
015 package com.liferay.portal.service.persistence.impl;
016
017 import com.liferay.portal.NoSuchModelException;
018 import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
019 import com.liferay.portal.kernel.cache.PortalCache;
020 import com.liferay.portal.kernel.dao.jdbc.MappingSqlQuery;
021 import com.liferay.portal.kernel.dao.jdbc.MappingSqlQueryFactoryUtil;
022 import com.liferay.portal.kernel.dao.jdbc.RowMapper;
023 import com.liferay.portal.kernel.dao.jdbc.SqlUpdate;
024 import com.liferay.portal.kernel.dao.jdbc.SqlUpdateFactoryUtil;
025 import com.liferay.portal.kernel.exception.SystemException;
026 import com.liferay.portal.kernel.util.ListUtil;
027 import com.liferay.portal.kernel.util.OrderByComparator;
028 import com.liferay.portal.model.BaseModel;
029 import com.liferay.portal.model.ModelListener;
030 import com.liferay.portal.service.persistence.BasePersistence;
031
032 import java.sql.Types;
033
034 import java.util.ArrayList;
035 import java.util.Arrays;
036 import java.util.Collections;
037 import java.util.List;
038
039 import javax.sql.DataSource;
040
041
044 public class TableMapperImpl<L extends BaseModel<L>, R extends BaseModel<R>>
045 implements TableMapper<L, R> {
046
047 public TableMapperImpl(
048 String tableName, String leftColumnName, String rightColumnName,
049 BasePersistence<L> leftBasePersistence,
050 BasePersistence<R> rightBasePersistence) {
051
052 this.leftColumnName = leftColumnName;
053 this.rightColumnName = rightColumnName;
054 this.leftBasePersistence = leftBasePersistence;
055 this.rightBasePersistence = rightBasePersistence;
056
057 DataSource dataSource = leftBasePersistence.getDataSource();
058
059 addTableMappingSqlUpdate = SqlUpdateFactoryUtil.getSqlUpdate(
060 dataSource,
061 "INSERT INTO " + tableName + " (" + leftColumnName + ", " +
062 rightColumnName + ") VALUES (?, ?)",
063 new int[] {Types.BIGINT, Types.BIGINT});
064 deleteLeftPrimaryKeyTableMappingsSqlUpdate =
065 SqlUpdateFactoryUtil.getSqlUpdate(
066 dataSource,
067 "DELETE FROM " + tableName + " WHERE " + leftColumnName +
068 " = ?",
069 new int[] {Types.BIGINT});
070 deleteRightPrimaryKeyTableMappingsSqlUpdate =
071 SqlUpdateFactoryUtil.getSqlUpdate(
072 dataSource,
073 "DELETE FROM " + tableName + " WHERE " + rightColumnName +
074 " = ?",
075 new int[] {Types.BIGINT});
076 deleteTableMappingSqlUpdate = SqlUpdateFactoryUtil.getSqlUpdate(
077 dataSource,
078 "DELETE FROM " + tableName + " WHERE " + leftColumnName +
079 " = ? AND " + rightColumnName + " = ?",
080 new int[] {Types.BIGINT, Types.BIGINT});
081 getLeftPrimaryKeysSqlQuery =
082 MappingSqlQueryFactoryUtil.getMappingSqlQuery(
083 dataSource,
084 "SELECT " + leftColumnName + " FROM " + tableName + " WHERE " +
085 rightColumnName + " = ?",
086 new int[] {Types.BIGINT}, RowMapper.PRIMARY_KEY);
087 getRightPrimaryKeysSqlQuery =
088 MappingSqlQueryFactoryUtil.getMappingSqlQuery(
089 dataSource,
090 "SELECT " + rightColumnName + " FROM " + tableName + " WHERE " +
091 leftColumnName + " = ?",
092 new int[] {Types.BIGINT}, RowMapper.PRIMARY_KEY);
093 leftToRightPortalCache = MultiVMPoolUtil.getCache(
094 TableMapper.class.getName() + "-" + tableName + "-LeftToRight");
095 rightToLeftPortalCache = MultiVMPoolUtil.getCache(
096 TableMapper.class.getName() + "-" + tableName + "-RightToLeft");
097 }
098
099 @Override
100 public boolean addTableMapping(long leftPrimaryKey, long rightPrimaryKey) {
101 if (containsTableMapping(leftPrimaryKey, rightPrimaryKey, false)) {
102 return false;
103 }
104
105 leftToRightPortalCache.remove(leftPrimaryKey);
106 rightToLeftPortalCache.remove(rightPrimaryKey);
107
108 Class<R> rightModelClass = rightBasePersistence.getModelClass();
109
110 ModelListener<L>[] leftModelListeners =
111 leftBasePersistence.getListeners();
112
113 for (ModelListener<L> leftModelListener : leftModelListeners) {
114 leftModelListener.onBeforeAddAssociation(
115 leftPrimaryKey, rightModelClass.getName(), rightPrimaryKey);
116 }
117
118 Class<L> leftModelClass = leftBasePersistence.getModelClass();
119
120 ModelListener<R>[] rightModelListeners =
121 rightBasePersistence.getListeners();
122
123 for (ModelListener<R> rightModelListener : rightModelListeners) {
124 rightModelListener.onBeforeAddAssociation(
125 rightPrimaryKey, leftModelClass.getName(), leftPrimaryKey);
126 }
127
128 try {
129 addTableMappingSqlUpdate.update(leftPrimaryKey, rightPrimaryKey);
130 }
131 catch (Exception e) {
132 throw new SystemException(e);
133 }
134
135 for (ModelListener<L> leftModelListener : leftModelListeners) {
136 leftModelListener.onAfterAddAssociation(
137 leftPrimaryKey, rightModelClass.getName(), rightPrimaryKey);
138 }
139
140 for (ModelListener<R> rightModelListener : rightModelListeners) {
141 rightModelListener.onAfterAddAssociation(
142 rightPrimaryKey, leftModelClass.getName(), leftPrimaryKey);
143 }
144
145 return true;
146 }
147
148 @Override
149 public boolean containsTableMapping(
150 long leftPrimaryKey, long rightPrimaryKey) {
151
152 return containsTableMapping(leftPrimaryKey, rightPrimaryKey, true);
153 }
154
155 @Override
156 public int deleteLeftPrimaryKeyTableMappings(long leftPrimaryKey) {
157 return deleteTableMappings(
158 leftBasePersistence, rightBasePersistence, leftToRightPortalCache,
159 rightToLeftPortalCache, getRightPrimaryKeysSqlQuery,
160 deleteLeftPrimaryKeyTableMappingsSqlUpdate, leftPrimaryKey);
161 }
162
163 @Override
164 public int deleteRightPrimaryKeyTableMappings(long rightPrimaryKey) {
165 return deleteTableMappings(
166 rightBasePersistence, leftBasePersistence, rightToLeftPortalCache,
167 leftToRightPortalCache, getLeftPrimaryKeysSqlQuery,
168 deleteRightPrimaryKeyTableMappingsSqlUpdate, rightPrimaryKey);
169 }
170
171 @Override
172 public boolean deleteTableMapping(
173 long leftPrimaryKey, long rightPrimaryKey) {
174
175 if (!containsTableMapping(leftPrimaryKey, rightPrimaryKey, false)) {
176 return false;
177 }
178
179 leftToRightPortalCache.remove(leftPrimaryKey);
180 rightToLeftPortalCache.remove(rightPrimaryKey);
181
182 Class<R> rightModelClass = rightBasePersistence.getModelClass();
183
184 ModelListener<L>[] leftModelListeners =
185 leftBasePersistence.getListeners();
186
187 for (ModelListener<L> leftModelListener : leftModelListeners) {
188 leftModelListener.onBeforeRemoveAssociation(
189 leftPrimaryKey, rightModelClass.getName(), rightPrimaryKey);
190 }
191
192 Class<L> leftModelClass = leftBasePersistence.getModelClass();
193
194 ModelListener<R>[] rightModelListeners =
195 rightBasePersistence.getListeners();
196
197 for (ModelListener<R> rightModelListener : rightModelListeners) {
198 rightModelListener.onBeforeRemoveAssociation(
199 rightPrimaryKey, leftModelClass.getName(), leftPrimaryKey);
200 }
201
202 int rowCount = 0;
203
204 try {
205 rowCount = deleteTableMappingSqlUpdate.update(
206 leftPrimaryKey, rightPrimaryKey);
207 }
208 catch (Exception e) {
209 throw new SystemException(e);
210 }
211
212 if (rowCount > 0) {
213 for (ModelListener<L> leftModelListener : leftModelListeners) {
214 leftModelListener.onAfterRemoveAssociation(
215 leftPrimaryKey, rightModelClass.getName(), rightPrimaryKey);
216 }
217
218 for (ModelListener<R> rightModelListener : rightModelListeners) {
219 rightModelListener.onAfterRemoveAssociation(
220 rightPrimaryKey, leftModelClass.getName(), leftPrimaryKey);
221 }
222
223 return true;
224 }
225
226 return false;
227 }
228
229 @Override
230 public void destroy() {
231 MultiVMPoolUtil.removeCache(leftToRightPortalCache.getName());
232 MultiVMPoolUtil.removeCache(rightToLeftPortalCache.getName());
233 }
234
235 @Override
236 public List<L> getLeftBaseModels(
237 long rightPrimaryKey, int start, int end, OrderByComparator<L> obc) {
238
239 return getBaseModels(
240 rightToLeftPortalCache, getLeftPrimaryKeysSqlQuery, rightPrimaryKey,
241 leftBasePersistence, start, end, obc);
242 }
243
244 @Override
245 public long[] getLeftPrimaryKeys(long rightPrimaryKey) {
246 return getPrimaryKeys(
247 rightToLeftPortalCache, getLeftPrimaryKeysSqlQuery, rightPrimaryKey,
248 true);
249 }
250
251 @Override
252 public TableMapper<R, L> getReverseTableMapper() {
253 return reverseTableMapper;
254 }
255
256 @Override
257 public List<R> getRightBaseModels(
258 long leftPrimaryKey, int start, int end, OrderByComparator<R> obc) {
259
260 return getBaseModels(
261 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
262 rightBasePersistence, start, end, obc);
263 }
264
265 @Override
266 public long[] getRightPrimaryKeys(long leftPrimaryKey) {
267 return getPrimaryKeys(
268 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
269 true);
270 }
271
272 @Override
273 public boolean matches(String leftColumnName, String rightColumnName) {
274 if (this.leftColumnName.equals(leftColumnName) &&
275 this.rightColumnName.equals(rightColumnName)) {
276
277 return true;
278 }
279
280 return false;
281 }
282
283 public void setReverseTableMapper(TableMapper<R, L> reverseTableMapper) {
284 this.reverseTableMapper = reverseTableMapper;
285 }
286
287 protected static <M extends BaseModel<M>, S extends BaseModel<S>> int
288 deleteTableMappings(
289 BasePersistence<M> masterBasePersistence,
290 BasePersistence<S> slaveBasePersistence,
291 PortalCache<Long, long[]> masterToSlavePortalCache,
292 PortalCache<Long, long[]> slaveToMasterPortalCache,
293 MappingSqlQuery<Long> mappingSqlQuery, SqlUpdate deleteSqlUpdate,
294 long masterPrimaryKey) {
295
296 ModelListener<M>[] masterModelListeners =
297 masterBasePersistence.getListeners();
298 ModelListener<S>[] slaveModelListeners =
299 slaveBasePersistence.getListeners();
300
301 long[] slavePrimaryKeys = getPrimaryKeys(
302 masterToSlavePortalCache, mappingSqlQuery, masterPrimaryKey, false);
303
304 Class<M> masterModelClass = null;
305 Class<S> slaveModelClass = null;
306
307 if ((masterModelListeners.length > 0) ||
308 (slaveModelListeners.length > 0)) {
309
310 masterModelClass = masterBasePersistence.getModelClass();
311 slaveModelClass = slaveBasePersistence.getModelClass();
312
313 for (long slavePrimaryKey : slavePrimaryKeys) {
314 for (ModelListener<M> masterModelListener :
315 masterModelListeners) {
316
317 masterModelListener.onBeforeRemoveAssociation(
318 masterPrimaryKey, slaveModelClass.getName(),
319 slavePrimaryKey);
320 }
321
322 for (ModelListener<S> slaveModelListener :
323 slaveModelListeners) {
324
325 slaveModelListener.onBeforeRemoveAssociation(
326 slavePrimaryKey, masterModelClass.getName(),
327 masterPrimaryKey);
328 }
329 }
330 }
331
332 masterToSlavePortalCache.remove(masterPrimaryKey);
333
334 for (long slavePrimaryKey : slavePrimaryKeys) {
335 slaveToMasterPortalCache.remove(slavePrimaryKey);
336 }
337
338 int rowCount = 0;
339
340 try {
341 rowCount = deleteSqlUpdate.update(masterPrimaryKey);
342 }
343 catch (Exception e) {
344 throw new SystemException(e);
345 }
346
347 if ((masterModelListeners.length > 0) ||
348 (slaveModelListeners.length > 0)) {
349
350 for (long slavePrimaryKey : slavePrimaryKeys) {
351 for (ModelListener<M> masterModelListener :
352 masterModelListeners) {
353
354 masterModelListener.onAfterRemoveAssociation(
355 masterPrimaryKey, slaveModelClass.getName(),
356 slavePrimaryKey);
357 }
358
359 for (ModelListener<S> slaveModelListener :
360 slaveModelListeners) {
361
362 slaveModelListener.onAfterRemoveAssociation(
363 slavePrimaryKey, masterModelClass.getName(),
364 masterPrimaryKey);
365 }
366 }
367 }
368
369 return rowCount;
370 }
371
372 protected static <T extends BaseModel<T>> List<T>
373 getBaseModels(
374 PortalCache<Long, long[]> portalCache,
375 MappingSqlQuery<Long> mappingSqlQuery, long masterPrimaryKey,
376 BasePersistence<T> slaveBasePersistence, int start, int end,
377 OrderByComparator<T> obc) {
378
379 long[] slavePrimaryKeys = getPrimaryKeys(
380 portalCache, mappingSqlQuery, masterPrimaryKey, true);
381
382 if (slavePrimaryKeys.length == 0) {
383 return Collections.emptyList();
384 }
385
386 List<T> slaveBaseModels = new ArrayList<T>(slavePrimaryKeys.length);
387
388 try {
389 for (long slavePrimaryKey : slavePrimaryKeys) {
390 slaveBaseModels.add(
391 slaveBasePersistence.findByPrimaryKey(slavePrimaryKey));
392 }
393 }
394 catch (NoSuchModelException nsme) {
395 throw new SystemException(nsme);
396 }
397
398 if (obc != null) {
399 Collections.sort(slaveBaseModels, obc);
400 }
401
402 return ListUtil.subList(slaveBaseModels, start, end);
403 }
404
405 protected static long[] getPrimaryKeys(
406 PortalCache<Long, long[]> portalCache,
407 MappingSqlQuery<Long> mappingSqlQuery, long masterPrimaryKey,
408 boolean updateCache) {
409
410 long[] primaryKeys = portalCache.get(masterPrimaryKey);
411
412 if (primaryKeys == null) {
413 List<Long> primaryKeysList = null;
414
415 try {
416 primaryKeysList = mappingSqlQuery.execute(masterPrimaryKey);
417 }
418 catch (Exception e) {
419 throw new SystemException(e);
420 }
421
422 primaryKeys = new long[primaryKeysList.size()];
423
424 for (int i = 0; i < primaryKeys.length; i++) {
425 primaryKeys[i] = primaryKeysList.get(i);
426 }
427
428 Arrays.sort(primaryKeys);
429
430 if (updateCache) {
431 portalCache.putQuiet(masterPrimaryKey, primaryKeys);
432 }
433 }
434
435 return primaryKeys;
436 }
437
438 protected boolean containsTableMapping(
439 long leftPrimaryKey, long rightPrimaryKey, boolean updateCache) {
440
441 long[] rightPrimaryKeys = getPrimaryKeys(
442 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
443 updateCache);
444
445 if (Arrays.binarySearch(rightPrimaryKeys, rightPrimaryKey) < 0) {
446 return false;
447 }
448 else {
449 return true;
450 }
451 }
452
453 protected SqlUpdate addTableMappingSqlUpdate;
454 protected SqlUpdate deleteLeftPrimaryKeyTableMappingsSqlUpdate;
455 protected SqlUpdate deleteRightPrimaryKeyTableMappingsSqlUpdate;
456 protected SqlUpdate deleteTableMappingSqlUpdate;
457 protected MappingSqlQuery<Long> getLeftPrimaryKeysSqlQuery;
458 protected MappingSqlQuery<Long> getRightPrimaryKeysSqlQuery;
459 protected BasePersistence<L> leftBasePersistence;
460 protected String leftColumnName;
461 protected PortalCache<Long, long[]> leftToRightPortalCache;
462 protected TableMapper<R, L> reverseTableMapper;
463 protected BasePersistence<R> rightBasePersistence;
464 protected String rightColumnName;
465 protected PortalCache<Long, long[]> rightToLeftPortalCache;
466
467 }