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<Document>();
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 PerformActionMethod getPerformActionMethod() {
077 return _performActionMethod;
078 }
079
080 @Override
081 public PerformCountMethod getPerformCountMethod() {
082 return _performCountMethod;
083 }
084
085 @Override
086 public void performActions() throws PortalException {
087 long previousPrimaryKey = -1;
088
089 while (true) {
090 long lastPrimaryKey = doPerformActions(previousPrimaryKey);
091
092 if (lastPrimaryKey < 0) {
093 return;
094 }
095
096 intervalCompleted(previousPrimaryKey, lastPrimaryKey);
097
098 previousPrimaryKey = lastPrimaryKey;
099 }
100 }
101
102 @Override
103 public long performCount() throws PortalException {
104 if (_performCountMethod != null) {
105 return _performCountMethod.performCount();
106 }
107
108 DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
109 _clazz, _classLoader);
110
111 addDefaultCriteria(dynamicQuery);
112
113 addCriteria(dynamicQuery);
114
115 return (Long)executeDynamicQuery(
116 _dynamicQueryCountMethod, dynamicQuery, getCountProjection());
117 }
118
119 @Override
120 public void setAddCriteriaMethod(AddCriteriaMethod addCriteriaMethod) {
121 _addCriteriaMethod = addCriteriaMethod;
122 }
123
124 @Override
125 public void setBaseLocalService(BaseLocalService baseLocalService) {
126 _baseLocalService = baseLocalService;
127
128 Class<?> clazz = _baseLocalService.getClass();
129
130 try {
131 _dynamicQueryMethod = clazz.getMethod(
132 "dynamicQuery", DynamicQuery.class);
133 _dynamicQueryCountMethod = clazz.getMethod(
134 "dynamicQueryCount", DynamicQuery.class, Projection.class);
135 }
136 catch (NoSuchMethodException nsme) {
137 throw new SystemException(nsme);
138 }
139 }
140
141 @Override
142 public void setClass(Class<?> clazz) {
143 _clazz = clazz;
144 }
145
146 @Override
147 public void setClassLoader(ClassLoader classLoader) {
148 _classLoader = classLoader;
149 }
150
151 @Override
152 public void setCommitImmediately(boolean commitImmediately) {
153 _commitImmediately = commitImmediately;
154 }
155
156 @Override
157 public void setCompanyId(long companyId) {
158 _companyId = companyId;
159 }
160
161 @Override
162 public void setGroupId(long groupId) {
163 _groupId = groupId;
164 }
165
166 @Override
167 public void setGroupIdPropertyName(String groupIdPropertyName) {
168 _groupIdPropertyName = groupIdPropertyName;
169 }
170
171 @Override
172 public void setInterval(int interval) {
173 _interval = interval;
174 }
175
176 @Override
177 public void setPerformActionMethod(
178 PerformActionMethod performActionMethod) {
179
180 _performActionMethod = performActionMethod;
181 }
182
183 @Override
184 public void setPerformCountMethod(PerformCountMethod performCountMethod) {
185 _performCountMethod = performCountMethod;
186 }
187
188 @Override
189 public void setPrimaryKeyPropertyName(String primaryKeyPropertyName) {
190 _primaryKeyPropertyName = primaryKeyPropertyName;
191 }
192
193 @Override
194 public void setSearchEngineId(String searchEngineId) {
195 _searchEngineId = searchEngineId;
196 }
197
198 @Override
199 public void setTransactionAttribute(
200 TransactionAttribute transactionAttribute) {
201
202 _transactionAttribute = transactionAttribute;
203 }
204
205 protected void addCriteria(DynamicQuery dynamicQuery) {
206 if (_addCriteriaMethod != null) {
207 _addCriteriaMethod.addCriteria(dynamicQuery);
208 }
209 }
210
211 protected void addDefaultCriteria(DynamicQuery dynamicQuery) {
212 if (_companyId > 0) {
213 Property property = PropertyFactoryUtil.forName("companyId");
214
215 dynamicQuery.add(property.eq(_companyId));
216 }
217
218 if (_groupId > 0) {
219 Property property = PropertyFactoryUtil.forName(
220 _groupIdPropertyName);
221
222 dynamicQuery.add(property.eq(_groupId));
223 }
224 }
225
226 protected void addDocuments(Collection<Document> documents)
227 throws PortalException {
228
229 if (_documents == null) {
230 _documents = new ArrayList<Document>();
231 }
232
233 _documents.addAll(documents);
234
235 if (_documents.size() >= _interval) {
236 indexInterval();
237 }
238 }
239
240 protected long doPerformActions(long previousPrimaryKey)
241 throws PortalException {
242
243 final DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
244 _clazz, _classLoader);
245
246 Property property = PropertyFactoryUtil.forName(
247 _primaryKeyPropertyName);
248
249 dynamicQuery.add(property.gt(previousPrimaryKey));
250
251 dynamicQuery.addOrder(OrderFactoryUtil.asc(_primaryKeyPropertyName));
252
253 dynamicQuery.setLimit(0, _interval);
254
255 addDefaultCriteria(dynamicQuery);
256
257 addCriteria(dynamicQuery);
258
259 Callable<Long> callable = new Callable<Long>() {
260
261 @Override
262 public Long call() throws Exception {
263 List<Object> objects = (List<Object>)executeDynamicQuery(
264 _dynamicQueryMethod, dynamicQuery);
265
266 if (objects.isEmpty()) {
267 return -1L;
268 }
269
270 for (Object object : objects) {
271 performAction(object);
272 }
273
274 if (objects.size() < _interval) {
275 return -1L;
276 }
277
278 BaseModel<?> baseModel = (BaseModel<?>)objects.get(
279 objects.size() - 1);
280
281 return (Long)baseModel.getPrimaryKeyObj();
282 }
283
284 };
285
286 TransactionAttribute transactionAttribute = getTransactionAttribute();
287
288 try {
289 if (transactionAttribute == null) {
290 return callable.call();
291 }
292 else {
293 return TransactionInvokerUtil.invoke(
294 transactionAttribute, callable);
295 }
296 }
297 catch (Throwable t) {
298 if (t instanceof PortalException) {
299 throw (PortalException)t;
300 }
301
302 if (t instanceof SystemException) {
303 throw (SystemException)t;
304 }
305
306 throw new SystemException(t);
307 }
308 finally {
309 indexInterval();
310 }
311 }
312
313 protected Object executeDynamicQuery(
314 Method dynamicQueryMethod, Object... arguments)
315 throws PortalException {
316
317 try {
318 return dynamicQueryMethod.invoke(_baseLocalService, arguments);
319 }
320 catch (InvocationTargetException ite) {
321 Throwable throwable = ite.getCause();
322
323 if (throwable instanceof PortalException) {
324 throw (PortalException)throwable;
325 }
326 else if (throwable instanceof SystemException) {
327 throw (SystemException)throwable;
328 }
329
330 throw new SystemException(ite);
331 }
332 catch (Exception e) {
333 throw new SystemException(e);
334 }
335 }
336
337 protected Projection getCountProjection() {
338 return ProjectionFactoryUtil.rowCount();
339 }
340
341 protected String getSearchEngineId() {
342 return _searchEngineId;
343 }
344
345 protected TransactionAttribute getTransactionAttribute() {
346 return _transactionAttribute;
347 }
348
349 protected void indexInterval() throws PortalException {
350 if ((_documents == null) || _documents.isEmpty()) {
351 return;
352 }
353
354 if (Validator.isNull(_searchEngineId)) {
355 _searchEngineId = SearchEngineUtil.getSearchEngineId(_documents);
356 }
357
358 SearchEngineUtil.updateDocuments(
359 _searchEngineId, _companyId, new ArrayList<Document>(_documents),
360 _commitImmediately);
361
362 _documents.clear();
363 }
364
365 @SuppressWarnings("unused")
366 protected void intervalCompleted(long startPrimaryKey, long endPrimaryKey)
367 throws PortalException {
368 }
369
370 protected void performAction(Object object) throws PortalException {
371 if (_performActionMethod != null) {
372 _performActionMethod.performAction(object);
373 }
374 }
375
376 private AddCriteriaMethod _addCriteriaMethod;
377 private BaseLocalService _baseLocalService;
378 private ClassLoader _classLoader;
379 private Class<?> _clazz;
380 private boolean _commitImmediately;
381 private long _companyId;
382 private Collection<Document> _documents;
383 private Method _dynamicQueryCountMethod;
384 private Method _dynamicQueryMethod;
385 private long _groupId;
386 private String _groupIdPropertyName = "groupId";
387 private int _interval = Indexer.DEFAULT_INTERVAL;
388 private PerformActionMethod _performActionMethod;
389 private PerformCountMethod _performCountMethod;
390 private String _primaryKeyPropertyName;
391 private String _searchEngineId;
392 private TransactionAttribute _transactionAttribute;
393
394 }