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