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 List<L> getLeftBaseModels(
238 long rightPrimaryKey, int start, int end, OrderByComparator obc)
239 throws SystemException {
240
241 return getBaseModels(
242 rightToLeftPortalCache, getLeftPrimaryKeysSqlQuery, rightPrimaryKey,
243 leftBasePersistence, start, end, obc);
244 }
245
246 @Override
247 public long[] getLeftPrimaryKeys(long rightPrimaryKey)
248 throws SystemException {
249
250 return getPrimaryKeys(
251 rightToLeftPortalCache, getLeftPrimaryKeysSqlQuery, rightPrimaryKey,
252 true);
253 }
254
255 @Override
256 public TableMapper<R, L> getReverseTableMapper() {
257 return reverseTableMapper;
258 }
259
260 @Override
261 public List<R> getRightBaseModels(
262 long leftPrimaryKey, int start, int end, OrderByComparator obc)
263 throws SystemException {
264
265 return getBaseModels(
266 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
267 rightBasePersistence, start, end, obc);
268 }
269
270 @Override
271 public long[] getRightPrimaryKeys(long leftPrimaryKey)
272 throws SystemException {
273
274 return getPrimaryKeys(
275 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
276 true);
277 }
278
279 @Override
280 public boolean matches(String leftColumnName, String rightColumnName) {
281 if (this.leftColumnName.equals(leftColumnName) &&
282 this.rightColumnName.equals(rightColumnName)) {
283
284 return true;
285 }
286
287 return false;
288 }
289
290 public void setReverseTableMapper(TableMapper<R, L> reverseTableMapper) {
291 this.reverseTableMapper = reverseTableMapper;
292 }
293
294 protected static <M extends BaseModel<M>, S extends BaseModel<S>> int
295 deleteTableMappings(
296 BasePersistence<M> masterBasePersistence,
297 BasePersistence<S> slaveBasePersistence,
298 PortalCache<Long, long[]> masterToSlavePortalCache,
299 PortalCache<Long, long[]> slaveToMasterPortalCache,
300 MappingSqlQuery<Long> mappingSqlQuery, SqlUpdate deleteSqlUpdate,
301 long masterPrimaryKey)
302 throws SystemException {
303
304 ModelListener<M>[] masterModelListeners =
305 masterBasePersistence.getListeners();
306 ModelListener<S>[] slaveModelListeners =
307 slaveBasePersistence.getListeners();
308
309 long[] slavePrimaryKeys = getPrimaryKeys(
310 masterToSlavePortalCache, mappingSqlQuery, masterPrimaryKey, false);
311
312 Class<M> masterModelClass = null;
313 Class<S> slaveModelClass = null;
314
315 if ((masterModelListeners.length > 0) ||
316 (slaveModelListeners.length > 0)) {
317
318 masterModelClass = masterBasePersistence.getModelClass();
319 slaveModelClass = slaveBasePersistence.getModelClass();
320
321 for (long slavePrimaryKey : slavePrimaryKeys) {
322 for (ModelListener<M> masterModelListener :
323 masterModelListeners) {
324
325 masterModelListener.onBeforeRemoveAssociation(
326 masterPrimaryKey, slaveModelClass.getName(),
327 slavePrimaryKey);
328 }
329
330 for (ModelListener<S> slaveModelListener :
331 slaveModelListeners) {
332
333 slaveModelListener.onBeforeRemoveAssociation(
334 slavePrimaryKey, masterModelClass.getName(),
335 masterPrimaryKey);
336 }
337 }
338 }
339
340 masterToSlavePortalCache.remove(masterPrimaryKey);
341
342 for (long slavePrimaryKey : slavePrimaryKeys) {
343 slaveToMasterPortalCache.remove(slavePrimaryKey);
344 }
345
346 int rowCount = 0;
347
348 try {
349 rowCount = deleteSqlUpdate.update(masterPrimaryKey);
350 }
351 catch (Exception e) {
352 throw new SystemException(e);
353 }
354
355 if ((masterModelListeners.length > 0) ||
356 (slaveModelListeners.length > 0)) {
357
358 for (long slavePrimaryKey : slavePrimaryKeys) {
359 for (ModelListener<M> masterModelListener :
360 masterModelListeners) {
361
362 masterModelListener.onAfterRemoveAssociation(
363 masterPrimaryKey, slaveModelClass.getName(),
364 slavePrimaryKey);
365 }
366
367 for (ModelListener<S> slaveModelListener :
368 slaveModelListeners) {
369
370 slaveModelListener.onAfterRemoveAssociation(
371 slavePrimaryKey, masterModelClass.getName(),
372 masterPrimaryKey);
373 }
374 }
375 }
376
377 return rowCount;
378 }
379
380 protected static <T extends BaseModel<T>> List<T>
381 getBaseModels(
382 PortalCache<Long, long[]> portalCache,
383 MappingSqlQuery<Long> mappingSqlQuery, long masterPrimaryKey,
384 BasePersistence<T> slaveBasePersistence, int start, int end,
385 OrderByComparator obc)
386 throws SystemException {
387
388 long[] slavePrimaryKeys = getPrimaryKeys(
389 portalCache, mappingSqlQuery, masterPrimaryKey, true);
390
391 if (slavePrimaryKeys.length == 0) {
392 return Collections.emptyList();
393 }
394
395 List<T> slaveBaseModels = new ArrayList<T>(slavePrimaryKeys.length);
396
397 try {
398 for (long slavePrimaryKey : slavePrimaryKeys) {
399 slaveBaseModels.add(
400 slaveBasePersistence.findByPrimaryKey(slavePrimaryKey));
401 }
402 }
403 catch (NoSuchModelException nsme) {
404 throw new SystemException(nsme);
405 }
406
407 if (obc != null) {
408 Collections.sort(slaveBaseModels, obc);
409 }
410
411 return ListUtil.subList(slaveBaseModels, start, end);
412 }
413
414 protected static long[] getPrimaryKeys(
415 PortalCache<Long, long[]> portalCache,
416 MappingSqlQuery<Long> mappingSqlQuery, long masterPrimaryKey,
417 boolean updateCache)
418 throws SystemException {
419
420 long[] primaryKeys = portalCache.get(masterPrimaryKey);
421
422 if (primaryKeys == null) {
423 List<Long> primaryKeysList = null;
424
425 try {
426 primaryKeysList = mappingSqlQuery.execute(masterPrimaryKey);
427 }
428 catch (Exception e) {
429 throw new SystemException(e);
430 }
431
432 primaryKeys = new long[primaryKeysList.size()];
433
434 for (int i = 0; i < primaryKeys.length; i++) {
435 primaryKeys[i] = primaryKeysList.get(i);
436 }
437
438 Arrays.sort(primaryKeys);
439
440 if (updateCache) {
441 portalCache.put(masterPrimaryKey, primaryKeys);
442 }
443 }
444
445 return primaryKeys;
446 }
447
448 protected boolean containsTableMapping(
449 long leftPrimaryKey, long rightPrimaryKey, boolean updateCache)
450 throws SystemException {
451
452 long[] rightPrimaryKeys = getPrimaryKeys(
453 leftToRightPortalCache, getRightPrimaryKeysSqlQuery, leftPrimaryKey,
454 updateCache);
455
456 if (Arrays.binarySearch(rightPrimaryKeys, rightPrimaryKey) < 0) {
457 return false;
458 }
459 else {
460 return true;
461 }
462 }
463
464 protected SqlUpdate addTableMappingSqlUpdate;
465 protected SqlUpdate deleteLeftPrimaryKeyTableMappingsSqlUpdate;
466 protected SqlUpdate deleteRightPrimaryKeyTableMappingsSqlUpdate;
467 protected SqlUpdate deleteTableMappingSqlUpdate;
468 protected MappingSqlQuery<Long> getLeftPrimaryKeysSqlQuery;
469 protected MappingSqlQuery<Long> getRightPrimaryKeysSqlQuery;
470 protected BasePersistence<L> leftBasePersistence;
471 protected String leftColumnName;
472 protected PortalCache<Long, long[]> leftToRightPortalCache;
473 protected TableMapper<R, L> reverseTableMapper;
474 protected BasePersistence<R> rightBasePersistence;
475 protected String rightColumnName;
476 protected PortalCache<Long, long[]> rightToLeftPortalCache;
477
478 }