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