001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.util.Validator;
023    import com.liferay.portal.service.BaseLocalService;
024    
025    import java.lang.reflect.InvocationTargetException;
026    import java.lang.reflect.Method;
027    
028    import java.util.ArrayList;
029    import java.util.Collection;
030    import java.util.List;
031    
032    /**
033     * @author Brian Wing Shun Chan
034     */
035    public abstract class BaseActionableDynamicQuery
036            implements ActionableDynamicQuery {
037    
038            @Override
039            public void performActions() throws PortalException, SystemException {
040                    long count = doPerformCount();
041    
042                    if (count > _interval) {
043                            performActionsInMultipleIntervals();
044                    }
045                    else {
046                            performActionsInSingleInterval();
047                    }
048            }
049    
050            public void performActions(long startPrimaryKey, long endPrimaryKey)
051                    throws PortalException, SystemException {
052    
053                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
054                            _clazz, _classLoader);
055    
056                    Property property = PropertyFactoryUtil.forName(
057                            _primaryKeyPropertyName);
058    
059                    dynamicQuery.add(property.ge(startPrimaryKey));
060                    dynamicQuery.add(property.lt(endPrimaryKey));
061    
062                    addDefaultCriteria(dynamicQuery);
063    
064                    addCriteria(dynamicQuery);
065    
066                    List<Object> objects = (List<Object>)executeDynamicQuery(
067                            _dynamicQueryMethod, dynamicQuery);
068    
069                    for (Object object : objects) {
070                            performAction(object);
071                    }
072            }
073    
074            @Override
075            public long performCount() throws PortalException, SystemException {
076                    return doPerformCount();
077            }
078    
079            @Override
080            public void setBaseLocalService(BaseLocalService baseLocalService)
081                    throws SystemException {
082    
083                    _baseLocalService = baseLocalService;
084    
085                    Class<?> clazz = _baseLocalService.getClass();
086    
087                    try {
088                            _dynamicQueryMethod = clazz.getMethod(
089                                    "dynamicQuery", DynamicQuery.class);
090                            _dynamicQueryCountMethod = clazz.getMethod(
091                                    "dynamicQueryCount", DynamicQuery.class, Projection.class);
092                    }
093                    catch (NoSuchMethodException nsme) {
094                            throw new SystemException(nsme);
095                    }
096            }
097    
098            @Override
099            public void setClass(Class<?> clazz) {
100                    _clazz = clazz;
101            }
102    
103            @Override
104            public void setClassLoader(ClassLoader classLoader) {
105                    _classLoader = classLoader;
106            }
107    
108            @Override
109            public void setCompanyId(long companyId) {
110                    _companyId = companyId;
111            }
112    
113            @Override
114            public void setGroupId(long groupId) {
115                    _groupId = groupId;
116            }
117    
118            @Override
119            public void setGroupIdPropertyName(String groupIdPropertyName) {
120                    _groupIdPropertyName = groupIdPropertyName;
121            }
122    
123            @Override
124            public void setInterval(int interval) {
125                    _interval = interval;
126            }
127    
128            @Override
129            public void setPrimaryKeyPropertyName(String primaryKeyPropertyName) {
130                    _primaryKeyPropertyName = primaryKeyPropertyName;
131            }
132    
133            @Override
134            public void setSearchEngineId(String searchEngineId) {
135                    _searchEngineId = searchEngineId;
136            }
137    
138            protected void addCriteria(DynamicQuery dynamicQuery) {
139            }
140    
141            protected void addDefaultCriteria(DynamicQuery dynamicQuery) {
142                    if (_companyId > 0) {
143                            Property property = PropertyFactoryUtil.forName("companyId");
144    
145                            dynamicQuery.add(property.eq(_companyId));
146                    }
147    
148                    if (_groupId > 0) {
149                            Property property = PropertyFactoryUtil.forName(
150                                    _groupIdPropertyName);
151    
152                            dynamicQuery.add(property.eq(_groupId));
153                    }
154            }
155    
156            protected void addDocument(Document document) {
157                    if (_documents == null) {
158                            _documents = new ArrayList<Document>();
159                    }
160    
161                    _documents.add(document);
162            }
163    
164            protected void addDocuments(Collection<Document> documents) {
165                    if (_documents == null) {
166                            _documents = new ArrayList<Document>();
167                    }
168    
169                    _documents.addAll(documents);
170            }
171    
172            protected long doPerformCount() throws PortalException, SystemException {
173                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
174                            _clazz, _classLoader);
175    
176                    addDefaultCriteria(dynamicQuery);
177    
178                    addCriteria(dynamicQuery);
179    
180                    return (Long)executeDynamicQuery(
181                            _dynamicQueryCountMethod, dynamicQuery, getCountProjection());
182            }
183    
184            protected Object executeDynamicQuery(
185                            Method dynamicQueryMethod, Object... arguments)
186                    throws PortalException, SystemException {
187    
188                    try {
189                            return dynamicQueryMethod.invoke(_baseLocalService, arguments);
190                    }
191                    catch (InvocationTargetException ite) {
192                            Throwable throwable = ite.getCause();
193    
194                            if (throwable instanceof PortalException) {
195                                    throw (PortalException)throwable;
196                            }
197                            else if (throwable instanceof SystemException) {
198                                    throw (SystemException)throwable;
199                            }
200    
201                            throw new SystemException(ite);
202                    }
203                    catch (Exception e) {
204                            throw new SystemException(e);
205                    }
206            }
207    
208            protected Projection getCountProjection() {
209                    return ProjectionFactoryUtil.rowCount();
210            }
211    
212            protected String getSearchEngineId() {
213                    return _searchEngineId;
214            }
215    
216            protected void indexInterval() throws PortalException {
217                    if (Validator.isNull(_searchEngineId) || (_documents == null) ||
218                            _documents.isEmpty()) {
219    
220                            return;
221                    }
222    
223                    SearchEngineUtil.updateDocuments(
224                            _searchEngineId, _companyId, new ArrayList<Document>(_documents));
225    
226                    _documents.clear();
227            }
228    
229            @SuppressWarnings("unused")
230            protected void intervalCompleted(long startPrimaryKey, long endPrimaryKey)
231                    throws PortalException, SystemException {
232            }
233    
234            protected abstract void performAction(Object object)
235                    throws PortalException, SystemException;
236    
237            protected void performActionsInMultipleIntervals()
238                    throws PortalException, SystemException {
239    
240                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
241                            _clazz, _classLoader);
242    
243                    Projection minPrimaryKeyProjection = ProjectionFactoryUtil.min(
244                            _primaryKeyPropertyName);
245                    Projection maxPrimaryKeyProjection = ProjectionFactoryUtil.max(
246                            _primaryKeyPropertyName);
247    
248                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
249    
250                    projectionList.add(minPrimaryKeyProjection);
251                    projectionList.add(maxPrimaryKeyProjection);
252    
253                    dynamicQuery.setProjection(projectionList);
254    
255                    addDefaultCriteria(dynamicQuery);
256    
257                    addCriteria(dynamicQuery);
258    
259                    List<Object[]> results = (List<Object[]>)executeDynamicQuery(
260                            _dynamicQueryMethod, dynamicQuery);
261    
262                    Object[] minAndMaxPrimaryKeys = results.get(0);
263    
264                    if ((minAndMaxPrimaryKeys[0] == null) ||
265                            (minAndMaxPrimaryKeys[1] == null)) {
266    
267                            return;
268                    }
269    
270                    long minPrimaryKey = (Long)minAndMaxPrimaryKeys[0];
271                    long maxPrimaryKey = (Long)minAndMaxPrimaryKeys[1];
272    
273                    long startPrimaryKey = minPrimaryKey;
274                    long endPrimaryKey = startPrimaryKey + _interval;
275    
276                    while (startPrimaryKey <= maxPrimaryKey) {
277                            performActions(startPrimaryKey, endPrimaryKey);
278    
279                            indexInterval();
280    
281                            intervalCompleted(startPrimaryKey, endPrimaryKey);
282    
283                            startPrimaryKey = endPrimaryKey;
284                            endPrimaryKey += _interval;
285                    }
286            }
287    
288            protected void performActionsInSingleInterval()
289                    throws PortalException, SystemException {
290    
291                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
292                            _clazz, _classLoader);
293    
294                    addDefaultCriteria(dynamicQuery);
295    
296                    addCriteria(dynamicQuery);
297    
298                    List<Object> objects = (List<Object>)executeDynamicQuery(
299                            _dynamicQueryMethod, dynamicQuery);
300    
301                    for (Object object : objects) {
302                            performAction(object);
303                    }
304    
305                    indexInterval();
306            }
307    
308            private BaseLocalService _baseLocalService;
309            private ClassLoader _classLoader;
310            private Class<?> _clazz;
311            private long _companyId;
312            private Collection<Document> _documents;
313            private Method _dynamicQueryCountMethod;
314            private Method _dynamicQueryMethod;
315            private long _groupId;
316            private String _groupIdPropertyName = "groupId";
317            private int _interval = Indexer.DEFAULT_INTERVAL;
318            private String _primaryKeyPropertyName;
319            private String _searchEngineId;
320    
321    }