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 throws SystemException {
102
103 if (containsTableMapping(leftPrimaryKey, rightPrimaryKey, false)) {
104 return false;
105 }
106
107 leftToRightPortalCache.remove(leftPrimaryKey);
108 rightToLeftPortalCache.remove(rightPrimaryKey);
109
110 Class<R> rightModelClass = rightBasePersistence.getModelClass();
111
112 ModelListener<L>[] leftModelListeners =
113 leftBasePersistence.getListeners();
114
115 for (ModelListener<L> leftModelListener : leftModelListeners) {
116 leftModelListener.onBeforeAddAssociation(
117 leftPrimaryKey, rightModelClass.getName(), rightPrimaryKey);
118 }
119
120 Class<L> leftModelClass = leftBasePersistence.getModelClass();
121
122 ModelListener<R>[] rightModelListeners =
123 rightBasePersistence.getListeners();
124
125 for (ModelListener<R> rightModelListener : rightModelListeners) {
126 rightModelListener.onBeforeAddAssociation(
127 rightPrimaryKey, leftModelClass.getName(), leftPrimaryKey);
128 }
129
130 try {
131 addTableMappingSqlUpdate.update(leftPrimaryKey, rightPrimaryKey);
132 }
133 catch (Exception e) {
134 throw new SystemException(e);
135 }
136
137 for (ModelListener<L> leftModelListener : leftModelListeners) {
138 leftModelListener.onAfterAddAssociation(
139 leftPrimaryKey, rightModelClass.getName(), rightPrimaryKey);
140 }
141
142 for (ModelListener<R> rightModelListener : rightModelListeners) {
143 rightModelListener.onAfterAddAssociation(
144 rightPrimaryKey, leftModelClass.getName(), leftPrimaryKey);
145 }
146
147 return true;
148 }
149
150 @Override
151 public boolean containsTableMapping(
152 long leftPrimaryKey, long rightPrimaryKey)
153 throws SystemException {
154
155 return containsTableMapping(leftPrimaryKey, rightPrimaryKey, true);
156 }
157
158 @Override
159 public int deleteLeftPrimaryKeyTableMappings(long leftPrimaryKey)
160 throws SystemException {
161
162 return deleteTableMappings(
163 leftBasePersistence, rightBasePersistence, leftToRightPortalCache,
164 rightToLeftPortalCache, getRightPrimaryKeysSqlQuery,
165 deleteLeftPrimaryKeyTableMappingsSqlUpdate, leftPrimaryKey);
166 }
167
168 @Override
169 public int deleteRightPrimaryKeyTableMappings(long rightPrimaryKey)
170 throws SystemException {
171
172 return deleteTableMappings(
173 rightBasePersistence, leftBasePersistence, rightToLeftPortalCache,
174 leftToRightPortalCache, getLeftPrimaryKeysSqlQuery,
175 deleteRightPrimaryKeyTableMappingsSqlUpdate, rightPrimaryKey);
176 }
177
178 @Override
179 public boolean deleteTableMapping(long leftPrimaryKey, long rightPrimaryKey)
180 throws SystemException {
181
182 if (!containsTableMapping(leftPrimaryKey, rightPrimaryKey, false)) {
183 return false;
184 }
185
186 leftToRightPortalCache.remove(leftPrimaryKey);
187 rightToLeftPortalCache.remove(rightPrimaryKey);
188
189 Class<R> rightModelClass = rightBasePersistence.getModelClass();
190
191 ModelListener<L>[] leftModelListeners =
192 leftBasePersistence.getListeners();
193
194 for (ModelListener<L> leftModelListener : leftModelListeners) {
195 leftModelListener.onBeforeRemoveAssociation(
196 leftPrimaryKey, rightModelClass.getName(), rightPrimaryKey);
197 }
198
199 Class<L> leftModelClass = leftBasePersistence.getModelClass();
200
201 ModelListener<R>[] rightModelListeners =
202 rightBasePersistence.getListeners();
203
204 for (ModelListener<R> rightModelListener : rightModelListeners) {
205 rightModelListener.onBeforeRemoveAssociation(
206 rightPrimaryKey, leftModelClass.getName(), leftPrimaryKey);
207 }
208
209 int rowCount = 0;
210
211 try {
212 rowCount = deleteTableMappingSqlUpdate.update(
213 leftPrimaryKey, rightPrimaryKey);
214 }
215 catch (Exception e) {
216 throw new SystemException(e);
217 }
218
219 if (rowCount > 0) {
220 for (ModelListener<L> leftModelListener : leftModelListeners) {
221 leftModelListener.onAfterRemoveAssociation(
222 leftPrimaryKey, rightModelClass.getName(), rightPrimaryKey);
223 }
224
225 for (ModelListener<R> rightModelListener : rightModelListeners) {
226 rightModelListener.onAfterRemoveAssociation(
227 rightPrimaryKey, leftModelClass.getName(), leftPrimaryKey);
228 }
229
230 return true;
231 }
232
233 return false;
234 }
235
236 @Override
237 public void destroy() {
238 MultiVMPoolUtil.removeCache(leftToRightPortalCache.getName());
239 MultiVMPoolUtil.removeCache(rightToLeftPortalCache.getName());
240 }
241
242 @Override
243 public List<L> getLeftBaseModels(
244 long rightPrimaryKey, int start, int end, OrderByComparator obc)
245 throws SystemException {
246
247 return getBaseModels(
248 rightToLeftPortalCache, getLeftPrimaryKeysSqlQuery, rightPrimaryKey,
249 leftBasePersistence, start, end, obc);
250 }
251
252 @Override
253 public long[] getLeftPrimaryKeys(long rightPrimaryKey)
254 throws SystemException {
255
256 return getPrimaryKeys(
257 rightToLeftPortalCache, getLeftPrimaryKeysSqlQuery, rightPrimaryKey,
258 true);
259 }
260
261 @Override
262 public TableMapper<R, L> getReverseTableMapper() {
263 return reverseTableMapper;
264 }
265
266 @Override
267 public List<R> getRightBaseModels(
268 long leftPrimaryKey, int start, int end, OrderByComparator obc)
269 throws SystemException {
270
271 return getBaseModels(
272 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
273 rightBasePersistence, start, end, obc);
274 }
275
276 @Override
277 public long[] getRightPrimaryKeys(long leftPrimaryKey)
278 throws SystemException {
279
280 return getPrimaryKeys(
281 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
282 true);
283 }
284
285 @Override
286 public boolean matches(String leftColumnName, String rightColumnName) {
287 if (this.leftColumnName.equals(leftColumnName) &&
288 this.rightColumnName.equals(rightColumnName)) {
289
290 return true;
291 }
292
293 return false;
294 }
295
296 public void setReverseTableMapper(TableMapper<R, L> reverseTableMapper) {
297 this.reverseTableMapper = reverseTableMapper;
298 }
299
300 protected static <M extends BaseModel<M>, S extends BaseModel<S>> int
301 deleteTableMappings(
302 BasePersistence<M> masterBasePersistence,
303 BasePersistence<S> slaveBasePersistence,
304 PortalCache<Long, long[]> masterToSlavePortalCache,
305 PortalCache<Long, long[]> slaveToMasterPortalCache,
306 MappingSqlQuery<Long> mappingSqlQuery, SqlUpdate deleteSqlUpdate,
307 long masterPrimaryKey)
308 throws SystemException {
309
310 ModelListener<M>[] masterModelListeners =
311 masterBasePersistence.getListeners();
312 ModelListener<S>[] slaveModelListeners =
313 slaveBasePersistence.getListeners();
314
315 long[] slavePrimaryKeys = getPrimaryKeys(
316 masterToSlavePortalCache, mappingSqlQuery, masterPrimaryKey, false);
317
318 Class<M> masterModelClass = null;
319 Class<S> slaveModelClass = null;
320
321 if ((masterModelListeners.length > 0) ||
322 (slaveModelListeners.length > 0)) {
323
324 masterModelClass = masterBasePersistence.getModelClass();
325 slaveModelClass = slaveBasePersistence.getModelClass();
326
327 for (long slavePrimaryKey : slavePrimaryKeys) {
328 for (ModelListener<M> masterModelListener :
329 masterModelListeners) {
330
331 masterModelListener.onBeforeRemoveAssociation(
332 masterPrimaryKey, slaveModelClass.getName(),
333 slavePrimaryKey);
334 }
335
336 for (ModelListener<S> slaveModelListener :
337 slaveModelListeners) {
338
339 slaveModelListener.onBeforeRemoveAssociation(
340 slavePrimaryKey, masterModelClass.getName(),
341 masterPrimaryKey);
342 }
343 }
344 }
345
346 masterToSlavePortalCache.remove(masterPrimaryKey);
347
348 for (long slavePrimaryKey : slavePrimaryKeys) {
349 slaveToMasterPortalCache.remove(slavePrimaryKey);
350 }
351
352 int rowCount = 0;
353
354 try {
355 rowCount = deleteSqlUpdate.update(masterPrimaryKey);
356 }
357 catch (Exception e) {
358 throw new SystemException(e);
359 }
360
361 if ((masterModelListeners.length > 0) ||
362 (slaveModelListeners.length > 0)) {
363
364 for (long slavePrimaryKey : slavePrimaryKeys) {
365 for (ModelListener<M> masterModelListener :
366 masterModelListeners) {
367
368 masterModelListener.onAfterRemoveAssociation(
369 masterPrimaryKey, slaveModelClass.getName(),
370 slavePrimaryKey);
371 }
372
373 for (ModelListener<S> slaveModelListener :
374 slaveModelListeners) {
375
376 slaveModelListener.onAfterRemoveAssociation(
377 slavePrimaryKey, masterModelClass.getName(),
378 masterPrimaryKey);
379 }
380 }
381 }
382
383 return rowCount;
384 }
385
386 protected static <T extends BaseModel<T>> List<T>
387 getBaseModels(
388 PortalCache<Long, long[]> portalCache,
389 MappingSqlQuery<Long> mappingSqlQuery, long masterPrimaryKey,
390 BasePersistence<T> slaveBasePersistence, int start, int end,
391 OrderByComparator obc)
392 throws SystemException {
393
394 long[] slavePrimaryKeys = getPrimaryKeys(
395 portalCache, mappingSqlQuery, masterPrimaryKey, true);
396
397 if (slavePrimaryKeys.length == 0) {
398 return Collections.emptyList();
399 }
400
401 List<T> slaveBaseModels = new ArrayList<T>(slavePrimaryKeys.length);
402
403 try {
404 for (long slavePrimaryKey : slavePrimaryKeys) {
405 slaveBaseModels.add(
406 slaveBasePersistence.findByPrimaryKey(slavePrimaryKey));
407 }
408 }
409 catch (NoSuchModelException nsme) {
410 throw new SystemException(nsme);
411 }
412
413 if (obc != null) {
414 Collections.sort(slaveBaseModels, obc);
415 }
416
417 return ListUtil.subList(slaveBaseModels, start, end);
418 }
419
420 protected static long[] getPrimaryKeys(
421 PortalCache<Long, long[]> portalCache,
422 MappingSqlQuery<Long> mappingSqlQuery, long masterPrimaryKey,
423 boolean updateCache)
424 throws SystemException {
425
426 long[] primaryKeys = portalCache.get(masterPrimaryKey);
427
428 if (primaryKeys == null) {
429 List<Long> primaryKeysList = null;
430
431 try {
432 primaryKeysList = mappingSqlQuery.execute(masterPrimaryKey);
433 }
434 catch (Exception e) {
435 throw new SystemException(e);
436 }
437
438 primaryKeys = new long[primaryKeysList.size()];
439
440 for (int i = 0; i < primaryKeys.length; i++) {
441 primaryKeys[i] = primaryKeysList.get(i);
442 }
443
444 Arrays.sort(primaryKeys);
445
446 if (updateCache) {
447 portalCache.put(masterPrimaryKey, primaryKeys);
448 }
449 }
450
451 return primaryKeys;
452 }
453
454 protected boolean containsTableMapping(
455 long leftPrimaryKey, long rightPrimaryKey, boolean updateCache)
456 throws SystemException {
457
458 long[] rightPrimaryKeys = getPrimaryKeys(
459 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
460 updateCache);
461
462 if (Arrays.binarySearch(rightPrimaryKeys, rightPrimaryKey) < 0) {
463 return false;
464 }
465 else {
466 return true;
467 }
468 }
469
470 protected SqlUpdate addTableMappingSqlUpdate;
471 protected SqlUpdate deleteLeftPrimaryKeyTableMappingsSqlUpdate;
472 protected SqlUpdate deleteRightPrimaryKeyTableMappingsSqlUpdate;
473 protected SqlUpdate deleteTableMappingSqlUpdate;
474 protected MappingSqlQuery<Long> getLeftPrimaryKeysSqlQuery;
475 protected MappingSqlQuery<Long> getRightPrimaryKeysSqlQuery;
476 protected BasePersistence<L> leftBasePersistence;
477 protected String leftColumnName;
478 protected PortalCache<Long, long[]> leftToRightPortalCache;
479 protected TableMapper<R, L> reverseTableMapper;
480 protected BasePersistence<R> rightBasePersistence;
481 protected String rightColumnName;
482 protected PortalCache<Long, long[]> rightToLeftPortalCache;
483
484 }