com.liferay.portal.kernel.dao.orm.DefaultActionableDynamicQuery.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.portal.kernel.dao.orm.DefaultActionableDynamicQuery.java

Source

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.portal.kernel.dao.orm;

import com.liferay.petra.executor.PortalExecutorManager;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.model.BaseModel;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.service.BaseLocalService;
import com.liferay.portal.kernel.transaction.Propagation;
import com.liferay.portal.kernel.transaction.TransactionConfig;
import com.liferay.portal.kernel.transaction.TransactionInvokerUtil;
import com.liferay.portal.kernel.util.ServiceProxyFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @author Brian Wing Shun Chan
 * @author Shuyang Zhou
 */
public class DefaultActionableDynamicQuery implements ActionableDynamicQuery {

    public static final TransactionConfig REQUIRES_NEW_TRANSACTION_CONFIG;

    static {
        TransactionConfig.Builder builder = new TransactionConfig.Builder();

        builder.setPropagation(Propagation.REQUIRES_NEW);
        builder.setRollbackForClasses(PortalException.class, SystemException.class);

        REQUIRES_NEW_TRANSACTION_CONFIG = builder.build();
    }

    @Override
    public AddCriteriaMethod getAddCriteriaMethod() {
        return _addCriteriaMethod;
    }

    @Override
    public AddOrderCriteriaMethod getAddOrderCriteriaMethod() {
        return _addOrderCriteriaMethod;
    }

    @Override
    public PerformActionMethod<?> getPerformActionMethod() {
        return _performActionMethod;
    }

    @Override
    public PerformCountMethod getPerformCountMethod() {
        return _performCountMethod;
    }

    @Override
    public boolean isParallel() {
        return _parallel;
    }

    @Override
    public void performActions() throws PortalException {
        try {
            long previousPrimaryKey = -1;

            while (true) {
                long lastPrimaryKey = doPerformActions(previousPrimaryKey);

                if (lastPrimaryKey < 0) {
                    return;
                }

                intervalCompleted(previousPrimaryKey, lastPrimaryKey);

                previousPrimaryKey = lastPrimaryKey;
            }
        } finally {
            _offset = 0;

            actionsCompleted();
        }
    }

    @Override
    public long performCount() throws PortalException {
        if (_performCountMethod != null) {
            return _performCountMethod.performCount();
        }

        DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(_modelClass, _classLoader);

        addDefaultCriteria(dynamicQuery);

        addCriteria(dynamicQuery);

        return (Long) executeDynamicQuery(_dynamicQueryCountMethod, dynamicQuery, getCountProjection());
    }

    @Override
    public void setAddCriteriaMethod(AddCriteriaMethod addCriteriaMethod) {
        _addCriteriaMethod = addCriteriaMethod;
    }

    @Override
    public void setAddOrderCriteriaMethod(AddOrderCriteriaMethod addOrderCriteriaMethod) {

        _addOrderCriteriaMethod = addOrderCriteriaMethod;
    }

    @Override
    public void setBaseLocalService(BaseLocalService baseLocalService) {
        _baseLocalService = baseLocalService;

        Class<?> clazz = _baseLocalService.getClass();

        try {
            _dynamicQueryMethod = clazz.getMethod("dynamicQuery", DynamicQuery.class);
            _dynamicQueryCountMethod = clazz.getMethod("dynamicQueryCount", DynamicQuery.class, Projection.class);
        } catch (NoSuchMethodException nsme) {
            throw new SystemException(nsme);
        }
    }

    @Override
    public void setClassLoader(ClassLoader classLoader) {
        _classLoader = classLoader;
    }

    @Override
    public void setCompanyId(long companyId) {
        _companyId = companyId;
    }

    @Override
    public void setGroupId(long groupId) {
        _groupId = groupId;
    }

    @Override
    public void setGroupIdPropertyName(String groupIdPropertyName) {
        _groupIdPropertyName = groupIdPropertyName;
    }

    @Override
    public void setInterval(int interval) {
        _interval = interval;
    }

    @Override
    public void setModelClass(Class<?> modelClass) {
        _modelClass = modelClass;
    }

    @Override
    public void setParallel(boolean parallel) {
        _parallel = parallel;
    }

    @Override
    public void setPerformActionMethod(PerformActionMethod<?> performActionMethod) {

        _performActionMethod = performActionMethod;
    }

    @Override
    public void setPerformCountMethod(PerformCountMethod performCountMethod) {
        _performCountMethod = performCountMethod;
    }

    @Override
    public void setPrimaryKeyPropertyName(String primaryKeyPropertyName) {
        _primaryKeyPropertyName = primaryKeyPropertyName;
    }

    @Override
    public void setTransactionConfig(TransactionConfig transactionConfig) {
        _transactionConfig = transactionConfig;
    }

    /**
     * @throws PortalException
     */
    protected void actionsCompleted() throws PortalException {
    }

    protected void addCriteria(DynamicQuery dynamicQuery) {
        if (_addCriteriaMethod != null) {
            _addCriteriaMethod.addCriteria(dynamicQuery);
        }
    }

    protected void addDefaultCriteria(DynamicQuery dynamicQuery) {
        if (_companyId > 0) {
            Property property = PropertyFactoryUtil.forName("companyId");

            dynamicQuery.add(property.eq(_companyId));
        }

        if (_groupId > 0) {
            Property property = PropertyFactoryUtil.forName(_groupIdPropertyName);

            dynamicQuery.add(property.eq(_groupId));
        }
    }

    protected void addOrderCriteria(DynamicQuery dynamicQuery) {
        if (_addOrderCriteriaMethod == null) {
            dynamicQuery.addOrder(OrderFactoryUtil.asc(_primaryKeyPropertyName));
        } else {
            _addOrderCriteriaMethod.addOrderCriteria(dynamicQuery);
        }
    }

    protected long doPerformActions(long previousPrimaryKey) throws PortalException {

        final DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(_modelClass, _classLoader);

        if (_addOrderCriteriaMethod == null) {
            Property property = PropertyFactoryUtil.forName(_primaryKeyPropertyName);

            dynamicQuery.add(property.gt(previousPrimaryKey));

            dynamicQuery.setLimit(0, _interval);
        } else {
            dynamicQuery.setLimit(_offset, _interval + _offset);
        }

        addDefaultCriteria(dynamicQuery);

        addCriteria(dynamicQuery);

        addOrderCriteria(dynamicQuery);

        Callable<Long> callable = new Callable<Long>() {

            @Override
            public Long call() throws Exception {
                List<Object> objects = (List<Object>) executeDynamicQuery(_dynamicQueryMethod, dynamicQuery);

                _offset += objects.size();

                if (objects.isEmpty()) {
                    return -1L;
                }

                if (_parallel) {
                    List<Future<Void>> futures = new ArrayList<>(objects.size());

                    for (final Object object : objects) {
                        futures.add(_executorService.submit(new Callable<Void>() {

                            @Override
                            public Void call() throws PortalException {
                                performAction(object);

                                return null;
                            }

                        }));
                    }

                    for (Future<Void> future : futures) {
                        future.get();
                    }
                } else {
                    for (Object object : objects) {
                        performAction(object);
                    }
                }

                if (objects.size() < _interval) {
                    return -1L;
                }

                BaseModel<?> baseModel = (BaseModel<?>) objects.get(objects.size() - 1);

                return (Long) baseModel.getPrimaryKeyObj();
            }

        };

        TransactionConfig transactionConfig = getTransactionConfig();

        try {
            if (transactionConfig == null) {
                return callable.call();
            }

            return TransactionInvokerUtil.invoke(transactionConfig, callable);
        } catch (Throwable t) {
            if (t instanceof PortalException) {
                throw (PortalException) t;
            }

            if (t instanceof SystemException) {
                throw (SystemException) t;
            }

            throw new SystemException(t);
        }
    }

    protected Object executeDynamicQuery(Method dynamicQueryMethod, Object... arguments) throws PortalException {

        try {
            return dynamicQueryMethod.invoke(_baseLocalService, arguments);
        } catch (InvocationTargetException ite) {
            Throwable throwable = ite.getCause();

            if (throwable instanceof PortalException) {
                throw (PortalException) throwable;
            } else if (throwable instanceof SystemException) {
                throw (SystemException) throwable;
            }

            throw new SystemException(ite);
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }

    protected long getCompanyId() {
        return _companyId;
    }

    protected Projection getCountProjection() {
        return ProjectionFactoryUtil.rowCount();
    }

    protected int getInterval() {
        return _interval;
    }

    protected Class<?> getModelClass() {
        return _modelClass;
    }

    protected TransactionConfig getTransactionConfig() {
        return _transactionConfig;
    }

    protected void intervalCompleted(long startPrimaryKey, long endPrimaryKey) throws PortalException {
    }

    protected void performAction(Object object) throws PortalException {
        if (_performActionMethod != null) {
            _performActionMethod.performAction(object);
        }
    }

    private static volatile PortalExecutorManager _portalExecutorManager = ServiceProxyFactory
            .newServiceTrackedInstance(PortalExecutorManager.class, DefaultActionableDynamicQuery.class,
                    "_portalExecutorManager", true);

    private AddCriteriaMethod _addCriteriaMethod;
    private AddOrderCriteriaMethod _addOrderCriteriaMethod;
    private BaseLocalService _baseLocalService;
    private ClassLoader _classLoader;
    private long _companyId;
    private Method _dynamicQueryCountMethod;
    private Method _dynamicQueryMethod;
    private final ExecutorService _executorService = _portalExecutorManager
            .getPortalExecutor(DefaultActionableDynamicQuery.class.getName());
    private long _groupId;
    private String _groupIdPropertyName = "groupId";
    private int _interval = Indexer.DEFAULT_INTERVAL;
    private Class<?> _modelClass;
    private int _offset;
    private boolean _parallel;

    @SuppressWarnings("rawtypes")
    private PerformActionMethod _performActionMethod;

    private PerformCountMethod _performCountMethod;
    private String _primaryKeyPropertyName;
    private TransactionConfig _transactionConfig;

}