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) throws PortalException {
157                    if (_documents == null) {
158                            _documents = new ArrayList<Document>();
159                    }
160    
161                    _documents.add(document);
162    
163                    if (_documents.size() >= _interval) {
164                            indexInterval();
165                    }
166            }
167    
168            protected void addDocuments(Collection<Document> documents)
169                    throws PortalException {
170    
171                    if (_documents == null) {
172                            _documents = new ArrayList<Document>();
173                    }
174    
175                    _documents.addAll(documents);
176    
177                    if (_documents.size() >= _interval) {
178                            indexInterval();
179                    }
180            }
181    
182            protected long doPerformCount() throws PortalException, SystemException {
183                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
184                            _clazz, _classLoader);
185    
186                    addDefaultCriteria(dynamicQuery);
187    
188                    addCriteria(dynamicQuery);
189    
190                    return (Long)executeDynamicQuery(
191                            _dynamicQueryCountMethod, dynamicQuery, getCountProjection());
192            }
193    
194            protected Object executeDynamicQuery(
195                            Method dynamicQueryMethod, Object... arguments)
196                    throws PortalException, SystemException {
197    
198                    try {
199                            return dynamicQueryMethod.invoke(_baseLocalService, arguments);
200                    }
201                    catch (InvocationTargetException ite) {
202                            Throwable throwable = ite.getCause();
203    
204                            if (throwable instanceof PortalException) {
205                                    throw (PortalException)throwable;
206                            }
207                            else if (throwable instanceof SystemException) {
208                                    throw (SystemException)throwable;
209                            }
210    
211                            throw new SystemException(ite);
212                    }
213                    catch (Exception e) {
214                            throw new SystemException(e);
215                    }
216            }
217    
218            protected Projection getCountProjection() {
219                    return ProjectionFactoryUtil.rowCount();
220            }
221    
222            protected String getSearchEngineId() {
223                    return _searchEngineId;
224            }
225    
226            protected void indexInterval() throws PortalException {
227                    if ((_documents == null) || _documents.isEmpty()) {
228                            return;
229                    }
230    
231                    if (Validator.isNull(_searchEngineId)) {
232                            SearchEngineUtil.updateDocuments(
233                                    _companyId, new ArrayList<Document>(_documents));
234                    }
235                    else {
236                            SearchEngineUtil.updateDocuments(
237                                    _searchEngineId, _companyId,
238                                    new ArrayList<Document>(_documents));
239                    }
240    
241                    _documents.clear();
242            }
243    
244            @SuppressWarnings("unused")
245            protected void intervalCompleted(long startPrimaryKey, long endPrimaryKey)
246                    throws PortalException, SystemException {
247            }
248    
249            protected abstract void performAction(Object object)
250                    throws PortalException, SystemException;
251    
252            protected void performActionsInMultipleIntervals()
253                    throws PortalException, SystemException {
254    
255                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
256                            _clazz, _classLoader);
257    
258                    Projection minPrimaryKeyProjection = ProjectionFactoryUtil.min(
259                            _primaryKeyPropertyName);
260                    Projection maxPrimaryKeyProjection = ProjectionFactoryUtil.max(
261                            _primaryKeyPropertyName);
262    
263                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
264    
265                    projectionList.add(minPrimaryKeyProjection);
266                    projectionList.add(maxPrimaryKeyProjection);
267    
268                    dynamicQuery.setProjection(projectionList);
269    
270                    addDefaultCriteria(dynamicQuery);
271    
272                    addCriteria(dynamicQuery);
273    
274                    List<Object[]> results = (List<Object[]>)executeDynamicQuery(
275                            _dynamicQueryMethod, dynamicQuery);
276    
277                    Object[] minAndMaxPrimaryKeys = results.get(0);
278    
279                    if ((minAndMaxPrimaryKeys[0] == null) ||
280                            (minAndMaxPrimaryKeys[1] == null)) {
281    
282                            return;
283                    }
284    
285                    long minPrimaryKey = (Long)minAndMaxPrimaryKeys[0];
286                    long maxPrimaryKey = (Long)minAndMaxPrimaryKeys[1];
287    
288                    long startPrimaryKey = minPrimaryKey;
289                    long endPrimaryKey = startPrimaryKey + _interval;
290    
291                    while (startPrimaryKey <= maxPrimaryKey) {
292                            performActions(startPrimaryKey, endPrimaryKey);
293    
294                            indexInterval();
295    
296                            intervalCompleted(startPrimaryKey, endPrimaryKey);
297    
298                            startPrimaryKey = endPrimaryKey;
299                            endPrimaryKey += _interval;
300                    }
301            }
302    
303            protected void performActionsInSingleInterval()
304                    throws PortalException, SystemException {
305    
306                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
307                            _clazz, _classLoader);
308    
309                    addDefaultCriteria(dynamicQuery);
310    
311                    addCriteria(dynamicQuery);
312    
313                    List<Object> objects = (List<Object>)executeDynamicQuery(
314                            _dynamicQueryMethod, dynamicQuery);
315    
316                    for (Object object : objects) {
317                            performAction(object);
318                    }
319    
320                    indexInterval();
321            }
322    
323            private BaseLocalService _baseLocalService;
324            private ClassLoader _classLoader;
325            private Class<?> _clazz;
326            private long _companyId;
327            private Collection<Document> _documents;
328            private Method _dynamicQueryCountMethod;
329            private Method _dynamicQueryMethod;
330            private long _groupId;
331            private String _groupIdPropertyName = "groupId";
332            private int _interval = Indexer.DEFAULT_INTERVAL;
333            private String _primaryKeyPropertyName;
334            private String _searchEngineId;
335    
336    }