Package org.broadleafcommerce.core.util.service

Source Code of org.broadleafcommerce.core.util.service.ResourcePurgeServiceImpl

/*
* #%L
* BroadleafCommerce Framework
* %%
* Copyright (C) 2009 - 2014 Broadleaf Commerce
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package org.broadleafcommerce.core.util.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.time.SystemTime;
import org.broadleafcommerce.common.util.StreamCapableTransactionalOperationAdapter;
import org.broadleafcommerce.common.util.StreamingTransactionCapableUtil;
import org.broadleafcommerce.core.order.domain.Order;
import org.broadleafcommerce.core.order.service.OrderService;
import org.broadleafcommerce.core.order.service.type.OrderStatus;
import org.broadleafcommerce.core.util.dao.ResourcePurgeDao;
import org.broadleafcommerce.core.util.service.type.PurgeCartVariableNames;
import org.broadleafcommerce.core.util.service.type.PurgeCustomerVariableNames;
import org.broadleafcommerce.profile.core.domain.Customer;
import org.broadleafcommerce.profile.core.service.CustomerService;
import org.springframework.stereotype.Service;

/**
* Service capable of deleting old or defunct entities from the persistence layer (e.g. Carts and anonymous Customers).
* {@link ResourcePurgeService} for additional API documentation.
* <p/>
* A basic Quartz scheduled job configuration for calling this service can be configured as follows:
* <p/>
* {@code
* <bean id="purgeCartConfig" class="org.springframework.beans.factory.config.MapFactoryBean">
* <property name="sourceMap">
* <map>
* <entry key="SECONDS_OLD" value="2592000"/>
* <entry key="STATUS" value="IN_PROCESS"/>
* </map>
* </property>
* </bean>
* <p/>
* <bean id="purgeCartJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
* <property name="targetObject" ref="blResourcePurgeService" />
* <property name="targetMethod" value="purgeCarts" />
* <property name="arguments">
* <list>
* <ref bean="purgeCartConfig"/>
* </list>
* </property>
* </bean>
* <p/>
* <bean id="purgeCartTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
* <property name="jobDetail" ref="purgeCartJobDetail" />
* <property name="startDelay" value="30000" />
* <property name="repeatInterval" value="86400000" />
* </bean>
*}
* @author Jeff Fischer
*/
@Service("blResourcePurgeService")
public class ResourcePurgeServiceImpl implements ResourcePurgeService {

    private static final Log LOG = LogFactory.getLog(ResourcePurgeServiceImpl.class);

    @Resource(name="blStreamingTransactionCapableUtil")
    protected StreamingTransactionCapableUtil transUtil;

    @Resource(name = "blResourcePurgeDao")
    protected ResourcePurgeDao resourcePurgeDao;

    @Resource(name = "blOrderService")
    protected OrderService orderService;

    @Resource(name = "blCustomerService")
    protected CustomerService customerService;

    protected Integer pageSize = 10;

    @PostConstruct
    public void init() {
        if (pageSize != null) {
            transUtil.setPageSize(pageSize);
        }
    }

    @Override
    public void purgeCarts(final Map<String, String> config) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Purging carts");
        }
        if (MapUtils.isEmpty(config)) {
            throw new IllegalArgumentException("Cannot purge carts since there was no configuration provided. " +
                    "In the absence of config params, all carts would be candidates for deletion.");
        }
        try {
            //The removal will be performed in chunks based on page size. This minimizes transaction times.
            transUtil.runStreamingTransactionalOperation(new StreamCapableTransactionalOperationAdapter() {
                @Override
                public void pagedExecute(Object[] param) throws Throwable {
                    List<Order> orders = (List<Order>) param[0];
                    for (Order cart : orders) {
                        deleteCart(cart);
                    }
                }

                @Override
                public Object[] retrievePage(int startPos, int pageSize) {
                    List<Order> results = getCartsToPurge(config, startPos, pageSize);
                    return new Object[]{results};
                }

                @Override
                public Long retrieveTotalCount() {
                    return getCartsToPurgeLength(config);
                }

                @Override
                public boolean shouldRetryOnTransactionLockAcquisitionFailure() {
                    return true;
                }
            }, RuntimeException.class);
        } catch (Exception e) {
            LOG.error("Unable to purge carts", e);
        }
    }

    @Override
    public void purgeCustomers(final Map<String, String> config) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Purging customers");
        }
        if (MapUtils.isEmpty(config)) {
            throw new IllegalArgumentException("Cannot purge customers since there was no configuration provided. " +
                    "In the absence of config params, all customers would be candidates for deletion.");
        }
        try {
            //The removal will be performed in chunks based on page size. This minimizes transaction times.
            transUtil.runStreamingTransactionalOperation(new StreamCapableTransactionalOperationAdapter() {
                @Override
                public void pagedExecute(Object[] param) throws Throwable {
                    List<Customer> customers = (List<Customer>) param[0];
                    for (Customer customer : customers) {
                        deleteCustomer(customer);
                    }
                }

                @Override
                public Object[] retrievePage(int startPos, int pageSize) {
                    List<Customer> results = getCustomersToPurge(config, startPos, pageSize);
                    return new Object[]{results};
                }

                @Override
                public Long retrieveTotalCount() {
                    return getCustomersToPurgeLength(config);
                }

                @Override
                public boolean shouldRetryOnTransactionLockAcquisitionFailure() {
                    return true;
                }
            }, RuntimeException.class);
        } catch (Exception e) {
            LOG.error("Unable to purge customers", e);
        }
    }

    @Override
    public Integer getPageSize() {
        return pageSize;
    }

    @Override
    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    /**
     * Get the list of carts to delete from the database. Subclasses may override for custom cart retrieval logic.
     *
     * @param config params for the query
     * @return list of carts to delete
     */
    protected List<Order> getCartsToPurge(Map<String, String> config, int startPos, int length) {
        CartPurgeParams purgeParams = new CartPurgeParams(config).invoke();
        String[] nameArray = purgeParams.getNameArray();
        OrderStatus[] statusArray = purgeParams.getStatusArray();
        Date dateCreatedMinThreshold = purgeParams.getDateCreatedMinThreshold();
        Boolean isPreview = purgeParams.getIsPreview();
        return resourcePurgeDao.findCarts(nameArray, statusArray, dateCreatedMinThreshold, isPreview, startPos, length);
    }

    /**
     * Get the count of carts to delete from the database. Subclasses may override for custom cart retrieval logic.
     *
     * @param config params for the query
     * @return count of carts to delete
     */
    protected Long getCartsToPurgeLength(Map<String, String> config) {
        CartPurgeParams purgeParams = new CartPurgeParams(config).invoke();
        String[] nameArray = purgeParams.getNameArray();
        OrderStatus[] statusArray = purgeParams.getStatusArray();
        Date dateCreatedMinThreshold = purgeParams.getDateCreatedMinThreshold();
        Boolean isPreview = purgeParams.getIsPreview();
        return resourcePurgeDao.findCartsCount(nameArray, statusArray, dateCreatedMinThreshold, isPreview);
    }

    /**
     * Remove the cart from the persistence layer. Subclasses may override for custom cart retrieval logic.
     *
     * @param cart the cart to remove
     */
    protected void deleteCart(Order cart) {
        //We delete the order this way (rather than with a delete query) in order to ensure the cascades take place
        try {
            orderService.deleteOrder(cart);
        } catch (Exception e) {
            LOG.error("Unable to purge a cart", e);
        }
    }

    /**
     * Get the list of carts to delete from the database. Subclasses may override for custom cart retrieval logic.
     *
     * @param config params for the query
     * @return list of carts to delete
     */
    protected List<Customer> getCustomersToPurge(Map<String, String> config, int startPos, int length) {
        CustomerPurgeParams purgeParams = new CustomerPurgeParams(config).invoke();
        Boolean isRegistered = purgeParams.getIsRegistered();
        Boolean isDeactivated = purgeParams.getIsDeactivated();
        Date dateCreatedMinThreshold = purgeParams.getDateCreatedMinThreshold();
        Boolean isPreview = purgeParams.getIsPreview();
        return resourcePurgeDao.findCustomers(dateCreatedMinThreshold, isRegistered, isDeactivated, isPreview, startPos, length);
    }

    /**
     * Get the count of carts to delete from the database. Subclasses may override for custom cart retrieval logic.
     *
     * @param config params for the query
     * @return count of carts to delete
     */
    protected Long getCustomersToPurgeLength(Map<String, String> config) {
        CustomerPurgeParams purgeParams = new CustomerPurgeParams(config).invoke();
        Boolean isRegistered = purgeParams.getIsRegistered();
        Boolean isDeactivated = purgeParams.getIsDeactivated();
        Date dateCreatedMinThreshold = purgeParams.getDateCreatedMinThreshold();
        Boolean isPreview = purgeParams.getIsPreview();
        return resourcePurgeDao.findCustomersCount(dateCreatedMinThreshold, isRegistered, isDeactivated, isPreview);
    }

    /**
     * Remove the cart from the persistence layer. Subclasses may override for custom cart retrieval logic.
     *
     * @param customer the customer to remove
     */
    protected void deleteCustomer(Customer customer) {
        //We delete the customer this way (rather than with a delete query) in order to ensure the cascades take place
        try {
            customerService.deleteCustomer(customer);
        } catch (Exception e) {
            LOG.error("Unable to purge a customer", e);
        }
    }

    private class CartPurgeParams {

        private Map<String, String> config;
        private String[] nameArray;
        private OrderStatus[] statusArray;
        private Date dateCreatedMinThreshold;
        private Boolean isPreview;

        public CartPurgeParams(Map<String, String> config) {
            this.config = config;
        }

        public String[] getNameArray() {
            return nameArray;
        }

        public OrderStatus[] getStatusArray() {
            return statusArray;
        }

        public Date getDateCreatedMinThreshold() {
            return dateCreatedMinThreshold;
        }

        public Boolean getIsPreview() {
            return isPreview;
        }

        public CartPurgeParams invoke() {
            nameArray = null;
            statusArray = null;
            dateCreatedMinThreshold = null;
            isPreview = null;
            for (Map.Entry<String, String> entry : config.entrySet()) {
                if (PurgeCartVariableNames.STATUS.toString().equals(entry.getKey())) {
                    String[] temp = entry.getValue().split(",");
                    statusArray = new OrderStatus[temp.length];
                    int index = 0;
                    for (String name : temp) {
                        OrderStatus orderStatus = OrderStatus.getInstance(name);
                        statusArray[index] = orderStatus;
                        index++;
                    }
                }
                if (PurgeCartVariableNames.NAME.toString().equals(entry.getKey())) {
                    nameArray = entry.getValue().split(",");
                }
                if (PurgeCartVariableNames.SECONDS_OLD.toString().equals(entry.getKey())) {
                    Long secondsOld = Long.parseLong(entry.getValue());
                    dateCreatedMinThreshold = new Date(SystemTime.asMillis() - (secondsOld * 1000));
                }
                if (PurgeCartVariableNames.IS_PREVIEW.toString().equals(entry.getKey())) {
                    isPreview = Boolean.parseBoolean(entry.getValue());
                }
            }
            return this;
        }
    }

    private class CustomerPurgeParams {

        private Map<String, String> config;
        private Date dateCreatedMinThreshold;
        private Boolean isPreview;
        private Boolean isRegistered;
        private Boolean isDeactivated;

        public CustomerPurgeParams(Map<String, String> config) {
            this.config = config;
        }

        public Date getDateCreatedMinThreshold() {
            return dateCreatedMinThreshold;
        }

        public Boolean getIsPreview() {
            return isPreview;
        }

        public Boolean getIsRegistered() {
            return isRegistered;
        }

        public Boolean getIsDeactivated() {
            return isDeactivated;
        }

        public CustomerPurgeParams invoke() {
            isRegistered = null;
            isDeactivated = null;
            dateCreatedMinThreshold = null;
            isPreview = null;
            for (Map.Entry<String, String> entry : config.entrySet()) {
                if (PurgeCustomerVariableNames.SECONDS_OLD.toString().equals(entry.getKey())) {
                    Long secondsOld = Long.parseLong(entry.getValue());
                    dateCreatedMinThreshold = new Date(SystemTime.asMillis() - (secondsOld * 1000));
                }
                if (PurgeCustomerVariableNames.IS_REGISTERED.toString().equals(entry.getKey())) {
                    isRegistered = Boolean.parseBoolean(entry.getValue());
                }
                if (PurgeCustomerVariableNames.IS_DEACTIVATED.toString().equals(entry.getKey())) {
                    isDeactivated = Boolean.parseBoolean(entry.getValue());
                }
                if (PurgeCustomerVariableNames.IS_PREVIEW.toString().equals(entry.getKey())) {
                    isPreview = Boolean.parseBoolean(entry.getValue());
                }
            }
            return this;
        }
    }
}
TOP

Related Classes of org.broadleafcommerce.core.util.service.ResourcePurgeServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.