001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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                    addOrderCriteria(dynamicQuery);
067    
068                    List<Object> objects = (List<Object>)executeDynamicQuery(
069                            _dynamicQueryMethod, dynamicQuery);
070    
071                    for (Object object : objects) {
072                            performAction(object);
073                    }
074            }
075    
076            @Override
077            public long performCount() throws PortalException, SystemException {
078                    return doPerformCount();
079            }
080    
081            @Override
082            public void setBaseLocalService(BaseLocalService baseLocalService)
083                    throws SystemException {
084    
085                    _baseLocalService = baseLocalService;
086    
087                    Class<?> clazz = _baseLocalService.getClass();
088    
089                    try {
090                            _dynamicQueryMethod = clazz.getMethod(
091                                    "dynamicQuery", DynamicQuery.class);
092                            _dynamicQueryCountMethod = clazz.getMethod(
093                                    "dynamicQueryCount", DynamicQuery.class, Projection.class);
094                    }
095                    catch (NoSuchMethodException nsme) {
096                            throw new SystemException(nsme);
097                    }
098            }
099    
100            @Override
101            public void setClass(Class<?> clazz) {
102                    _clazz = clazz;
103            }
104    
105            @Override
106            public void setClassLoader(ClassLoader classLoader) {
107                    _classLoader = classLoader;
108            }
109    
110            @Override
111            public void setCompanyId(long companyId) {
112                    _companyId = companyId;
113            }
114    
115            @Override
116            public void setGroupId(long groupId) {
117                    _groupId = groupId;
118            }
119    
120            @Override
121            public void setGroupIdPropertyName(String groupIdPropertyName) {
122                    _groupIdPropertyName = groupIdPropertyName;
123            }
124    
125            @Override
126            public void setInterval(int interval) {
127                    _interval = interval;
128            }
129    
130            @Override
131            public void setPrimaryKeyPropertyName(String primaryKeyPropertyName) {
132                    _primaryKeyPropertyName = primaryKeyPropertyName;
133            }
134    
135            @Override
136            public void setSearchEngineId(String searchEngineId) {
137                    _searchEngineId = searchEngineId;
138            }
139    
140            protected void addCriteria(DynamicQuery dynamicQuery) {
141            }
142    
143            protected void addOrderCriteria(DynamicQuery dynamicQuery) {
144            }
145    
146            protected void addDefaultCriteria(DynamicQuery dynamicQuery) {
147                    if (_companyId > 0) {
148                            Property property = PropertyFactoryUtil.forName("companyId");
149    
150                            dynamicQuery.add(property.eq(_companyId));
151                    }
152    
153                    if (_groupId > 0) {
154                            Property property = PropertyFactoryUtil.forName(
155                                    _groupIdPropertyName);
156    
157                            dynamicQuery.add(property.eq(_groupId));
158                    }
159            }
160    
161            protected void addDocument(Document document) throws PortalException {
162                    if (_documents == null) {
163                            _documents = new ArrayList<Document>();
164                    }
165    
166                    _documents.add(document);
167    
168                    if (_documents.size() >= _interval) {
169                            indexInterval();
170                    }
171            }
172    
173            protected void addDocuments(Collection<Document> documents)
174                    throws PortalException {
175    
176                    if (_documents == null) {
177                            _documents = new ArrayList<Document>();
178                    }
179    
180                    _documents.addAll(documents);
181    
182                    if (_documents.size() >= _interval) {
183                            indexInterval();
184                    }
185            }
186    
187            protected long doPerformCount() throws PortalException, SystemException {
188                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
189                            _clazz, _classLoader);
190    
191                    addDefaultCriteria(dynamicQuery);
192    
193                    addCriteria(dynamicQuery);
194    
195                    return (Long)executeDynamicQuery(
196                            _dynamicQueryCountMethod, dynamicQuery, getCountProjection());
197            }
198    
199            protected Object executeDynamicQuery(
200                            Method dynamicQueryMethod, Object... arguments)
201                    throws PortalException, SystemException {
202    
203                    try {
204                            return dynamicQueryMethod.invoke(_baseLocalService, arguments);
205                    }
206                    catch (InvocationTargetException ite) {
207                            Throwable throwable = ite.getCause();
208    
209                            if (throwable instanceof PortalException) {
210                                    throw (PortalException)throwable;
211                            }
212                            else if (throwable instanceof SystemException) {
213                                    throw (SystemException)throwable;
214                            }
215    
216                            throw new SystemException(ite);
217                    }
218                    catch (Exception e) {
219                            throw new SystemException(e);
220                    }
221            }
222    
223            protected Projection getCountProjection() {
224                    return ProjectionFactoryUtil.rowCount();
225            }
226    
227            protected String getSearchEngineId() {
228                    return _searchEngineId;
229            }
230    
231            protected void indexInterval() throws PortalException {
232                    if ((_documents == null) || _documents.isEmpty()) {
233                            return;
234                    }
235    
236                    if (Validator.isNull(_searchEngineId)) {
237                            SearchEngineUtil.updateDocuments(
238                                    _companyId, new ArrayList<Document>(_documents));
239                    }
240                    else {
241                            SearchEngineUtil.updateDocuments(
242                                    _searchEngineId, _companyId,
243                                    new ArrayList<Document>(_documents));
244                    }
245    
246                    _documents.clear();
247            }
248    
249            @SuppressWarnings("unused")
250            protected void intervalCompleted(long startPrimaryKey, long endPrimaryKey)
251                    throws PortalException, SystemException {
252            }
253    
254            protected abstract void performAction(Object object)
255                    throws PortalException, SystemException;
256    
257            protected void performActionsInMultipleIntervals()
258                    throws PortalException, SystemException {
259    
260                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
261                            _clazz, _classLoader);
262    
263                    Projection minPrimaryKeyProjection = ProjectionFactoryUtil.min(
264                            _primaryKeyPropertyName);
265                    Projection maxPrimaryKeyProjection = ProjectionFactoryUtil.max(
266                            _primaryKeyPropertyName);
267    
268                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
269    
270                    projectionList.add(minPrimaryKeyProjection);
271                    projectionList.add(maxPrimaryKeyProjection);
272    
273                    dynamicQuery.setProjection(projectionList);
274    
275                    addDefaultCriteria(dynamicQuery);
276    
277                    addCriteria(dynamicQuery);
278    
279                    List<Object[]> results = (List<Object[]>)executeDynamicQuery(
280                            _dynamicQueryMethod, dynamicQuery);
281    
282                    Object[] minAndMaxPrimaryKeys = results.get(0);
283    
284                    if ((minAndMaxPrimaryKeys[0] == null) ||
285                            (minAndMaxPrimaryKeys[1] == null)) {
286    
287                            return;
288                    }
289    
290                    long minPrimaryKey = (Long)minAndMaxPrimaryKeys[0];
291                    long maxPrimaryKey = (Long)minAndMaxPrimaryKeys[1];
292    
293                    long startPrimaryKey = minPrimaryKey;
294                    long endPrimaryKey = startPrimaryKey + _interval;
295    
296                    while (startPrimaryKey <= maxPrimaryKey) {
297                            performActions(startPrimaryKey, endPrimaryKey);
298    
299                            indexInterval();
300    
301                            intervalCompleted(startPrimaryKey, endPrimaryKey);
302    
303                            startPrimaryKey = endPrimaryKey;
304                            endPrimaryKey += _interval;
305                    }
306            }
307    
308            protected void performActionsInSingleInterval()
309                    throws PortalException, SystemException {
310    
311                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
312                            _clazz, _classLoader);
313    
314                    addDefaultCriteria(dynamicQuery);
315    
316                    addCriteria(dynamicQuery);
317    
318                    addOrderCriteria(dynamicQuery);
319    
320                    List<Object> objects = (List<Object>)executeDynamicQuery(
321                            _dynamicQueryMethod, dynamicQuery);
322    
323                    for (Object object : objects) {
324                            performAction(object);
325                    }
326    
327                    indexInterval();
328            }
329    
330            private BaseLocalService _baseLocalService;
331            private ClassLoader _classLoader;
332            private Class<?> _clazz;
333            private long _companyId;
334            private Collection<Document> _documents;
335            private Method _dynamicQueryCountMethod;
336            private Method _dynamicQueryMethod;
337            private long _groupId;
338            private String _groupIdPropertyName = "groupId";
339            private int _interval = Indexer.DEFAULT_INTERVAL;
340            private String _primaryKeyPropertyName;
341            private String _searchEngineId;
342    
343    }