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