001
014
015 package com.liferay.portal.kernel.dao.orm;
016
017 import com.liferay.portal.kernel.concurrent.ThreadPoolExecutor;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.executor.PortalExecutorManagerUtil;
021 import com.liferay.portal.kernel.model.BaseModel;
022 import com.liferay.portal.kernel.search.Indexer;
023 import com.liferay.portal.kernel.service.BaseLocalService;
024 import com.liferay.portal.kernel.transaction.Propagation;
025 import com.liferay.portal.kernel.transaction.TransactionConfig;
026 import com.liferay.portal.kernel.transaction.TransactionInvokerUtil;
027
028 import java.lang.reflect.InvocationTargetException;
029 import java.lang.reflect.Method;
030
031 import java.util.ArrayList;
032 import java.util.List;
033 import java.util.concurrent.Callable;
034 import java.util.concurrent.Future;
035
036
040 public class DefaultActionableDynamicQuery implements ActionableDynamicQuery {
041
042 public static final TransactionConfig REQUIRES_NEW_TRANSACTION_CONFIG;
043
044 static {
045 TransactionConfig.Builder builder = new TransactionConfig.Builder();
046
047 builder.setPropagation(Propagation.REQUIRES_NEW);
048 builder.setRollbackForClasses(
049 PortalException.class, SystemException.class);
050
051 REQUIRES_NEW_TRANSACTION_CONFIG = builder.build();
052 }
053
054 @Override
055 public AddCriteriaMethod getAddCriteriaMethod() {
056 return _addCriteriaMethod;
057 }
058
059 @Override
060 public AddOrderCriteriaMethod getAddOrderCriteriaMethod() {
061 return _addOrderCriteriaMethod;
062 }
063
064 @Override
065 public PerformActionMethod<?> getPerformActionMethod() {
066 return _performActionMethod;
067 }
068
069 @Override
070 public PerformCountMethod getPerformCountMethod() {
071 return _performCountMethod;
072 }
073
074 @Override
075 public boolean isParallel() {
076 return _parallel;
077 }
078
079 @Override
080 public void performActions() throws PortalException {
081 try {
082 long previousPrimaryKey = -1;
083
084 while (true) {
085 long lastPrimaryKey = doPerformActions(previousPrimaryKey);
086
087 if (lastPrimaryKey < 0) {
088 return;
089 }
090
091 intervalCompleted(previousPrimaryKey, lastPrimaryKey);
092
093 previousPrimaryKey = lastPrimaryKey;
094 }
095 }
096 finally {
097 actionsCompleted();
098 }
099 }
100
101 @Override
102 public long performCount() throws PortalException {
103 if (_performCountMethod != null) {
104 return _performCountMethod.performCount();
105 }
106
107 DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
108 _modelClass, _classLoader);
109
110 addDefaultCriteria(dynamicQuery);
111
112 addCriteria(dynamicQuery);
113
114 return (Long)executeDynamicQuery(
115 _dynamicQueryCountMethod, dynamicQuery, getCountProjection());
116 }
117
118 @Override
119 public void setAddCriteriaMethod(AddCriteriaMethod addCriteriaMethod) {
120 _addCriteriaMethod = addCriteriaMethod;
121 }
122
123 @Override
124 public void setAddOrderCriteriaMethod(
125 AddOrderCriteriaMethod addOrderCriteriaMethod) {
126
127 _addOrderCriteriaMethod = addOrderCriteriaMethod;
128 }
129
130 @Override
131 public void setBaseLocalService(BaseLocalService baseLocalService) {
132 _baseLocalService = baseLocalService;
133
134 Class<?> clazz = _baseLocalService.getClass();
135
136 try {
137 _dynamicQueryMethod = clazz.getMethod(
138 "dynamicQuery", DynamicQuery.class);
139 _dynamicQueryCountMethod = clazz.getMethod(
140 "dynamicQueryCount", DynamicQuery.class, Projection.class);
141 }
142 catch (NoSuchMethodException nsme) {
143 throw new SystemException(nsme);
144 }
145 }
146
147
150 @Deprecated
151 @Override
152 public void setClass(Class<?> modelClass) {
153 _modelClass = modelClass;
154 }
155
156 @Override
157 public void setClassLoader(ClassLoader classLoader) {
158 _classLoader = classLoader;
159 }
160
161 @Override
162 public void setCompanyId(long companyId) {
163 _companyId = companyId;
164 }
165
166 @Override
167 public void setGroupId(long groupId) {
168 _groupId = groupId;
169 }
170
171 @Override
172 public void setGroupIdPropertyName(String groupIdPropertyName) {
173 _groupIdPropertyName = groupIdPropertyName;
174 }
175
176 @Override
177 public void setInterval(int interval) {
178 _interval = interval;
179 }
180
181 @Override
182 public void setModelClass(Class<?> modelClass) {
183 _modelClass = modelClass;
184 }
185
186 @Override
187 public void setParallel(boolean parallel) {
188 _parallel = parallel;
189 }
190
191 @Override
192 public void setPerformActionMethod(
193 PerformActionMethod<?> performActionMethod) {
194
195 _performActionMethod = performActionMethod;
196 }
197
198 @Override
199 public void setPerformCountMethod(PerformCountMethod performCountMethod) {
200 _performCountMethod = performCountMethod;
201 }
202
203 @Override
204 public void setPrimaryKeyPropertyName(String primaryKeyPropertyName) {
205 _primaryKeyPropertyName = primaryKeyPropertyName;
206 }
207
208 @Override
209 public void setTransactionConfig(TransactionConfig transactionConfig) {
210 _transactionConfig = transactionConfig;
211 }
212
213
216 protected void actionsCompleted() throws PortalException {
217 }
218
219 protected void addCriteria(DynamicQuery dynamicQuery) {
220 if (_addCriteriaMethod != null) {
221 _addCriteriaMethod.addCriteria(dynamicQuery);
222 }
223 }
224
225 protected void addDefaultCriteria(DynamicQuery dynamicQuery) {
226 if (_companyId > 0) {
227 Property property = PropertyFactoryUtil.forName("companyId");
228
229 dynamicQuery.add(property.eq(_companyId));
230 }
231
232 if (_groupId > 0) {
233 Property property = PropertyFactoryUtil.forName(
234 _groupIdPropertyName);
235
236 dynamicQuery.add(property.eq(_groupId));
237 }
238 }
239
240 protected void addOrderCriteria(DynamicQuery dynamicQuery) {
241 if (_addOrderCriteriaMethod != null) {
242 _addOrderCriteriaMethod.addOrderCriteria(dynamicQuery);
243 }
244 else {
245 dynamicQuery.addOrder(
246 OrderFactoryUtil.asc(_primaryKeyPropertyName));
247 }
248 }
249
250 protected long doPerformActions(long previousPrimaryKey)
251 throws PortalException {
252
253 final DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
254 _modelClass, _classLoader);
255
256 Property property = PropertyFactoryUtil.forName(
257 _primaryKeyPropertyName);
258
259 dynamicQuery.add(property.gt(previousPrimaryKey));
260
261 dynamicQuery.setLimit(0, _interval);
262
263 addDefaultCriteria(dynamicQuery);
264
265 addCriteria(dynamicQuery);
266
267 addOrderCriteria(dynamicQuery);
268
269 Callable<Long> callable = new Callable<Long>() {
270
271 @Override
272 public Long call() throws Exception {
273 List<Object> objects = (List<Object>)executeDynamicQuery(
274 _dynamicQueryMethod, dynamicQuery);
275
276 if (objects.isEmpty()) {
277 return -1L;
278 }
279
280 if (_parallel) {
281 List<Future<Void>> futures = new ArrayList<>(
282 objects.size());
283
284 for (final Object object : objects) {
285 futures.add(
286 _threadPoolExecutor.submit(
287 new Callable<Void>() {
288
289 @Override
290 public Void call() throws PortalException {
291 performAction(object);
292
293 return null;
294 }
295
296 }));
297 }
298
299 for (Future<Void> future : futures) {
300 future.get();
301 }
302 }
303 else {
304 for (Object object : objects) {
305 performAction(object);
306 }
307 }
308
309 if (objects.size() < _interval) {
310 return -1L;
311 }
312
313 BaseModel<?> baseModel = (BaseModel<?>)objects.get(
314 objects.size() - 1);
315
316 return (Long)baseModel.getPrimaryKeyObj();
317 }
318
319 };
320
321 TransactionConfig transactionConfig = getTransactionConfig();
322
323 try {
324 if (transactionConfig == null) {
325 return callable.call();
326 }
327 else {
328 return TransactionInvokerUtil.invoke(
329 transactionConfig, callable);
330 }
331 }
332 catch (Throwable t) {
333 if (t instanceof PortalException) {
334 throw (PortalException)t;
335 }
336
337 if (t instanceof SystemException) {
338 throw (SystemException)t;
339 }
340
341 throw new SystemException(t);
342 }
343 }
344
345 protected Object executeDynamicQuery(
346 Method dynamicQueryMethod, Object... arguments)
347 throws PortalException {
348
349 try {
350 return dynamicQueryMethod.invoke(_baseLocalService, arguments);
351 }
352 catch (InvocationTargetException ite) {
353 Throwable throwable = ite.getCause();
354
355 if (throwable instanceof PortalException) {
356 throw (PortalException)throwable;
357 }
358 else if (throwable instanceof SystemException) {
359 throw (SystemException)throwable;
360 }
361
362 throw new SystemException(ite);
363 }
364 catch (Exception e) {
365 throw new SystemException(e);
366 }
367 }
368
369 protected long getCompanyId() {
370 return _companyId;
371 }
372
373 protected Projection getCountProjection() {
374 return ProjectionFactoryUtil.rowCount();
375 }
376
377 protected int getInterval() {
378 return _interval;
379 }
380
381 protected Class<?> getModelClass() {
382 return _modelClass;
383 }
384
385 protected TransactionConfig getTransactionConfig() {
386 return _transactionConfig;
387 }
388
389 @SuppressWarnings("unused")
390 protected void intervalCompleted(long startPrimaryKey, long endPrimaryKey)
391 throws PortalException {
392 }
393
394 protected void performAction(Object object) throws PortalException {
395 if (_performActionMethod != null) {
396 _performActionMethod.performAction(object);
397 }
398 }
399
400 private AddCriteriaMethod _addCriteriaMethod;
401 private AddOrderCriteriaMethod _addOrderCriteriaMethod;
402 private BaseLocalService _baseLocalService;
403 private ClassLoader _classLoader;
404 private long _companyId;
405 private Method _dynamicQueryCountMethod;
406 private Method _dynamicQueryMethod;
407 private long _groupId;
408 private String _groupIdPropertyName = "groupId";
409 private int _interval = Indexer.DEFAULT_INTERVAL;
410 private Class<?> _modelClass;
411 private boolean _parallel;
412
413 @SuppressWarnings("rawtypes")
414 private PerformActionMethod _performActionMethod;
415
416 private PerformCountMethod _performCountMethod;
417 private String _primaryKeyPropertyName;
418 private final ThreadPoolExecutor _threadPoolExecutor =
419 PortalExecutorManagerUtil.getPortalExecutor(
420 DefaultActionableDynamicQuery.class.getName());
421 private TransactionConfig _transactionConfig;
422
423 }