org.openinfinity.core.async.ParallelServiceActivator.java Source code

Java tutorial

Introduction

Here is the source code for org.openinfinity.core.async.ParallelServiceActivator.java

Source

/*
 * Copyright (c) 2012-2014 the original author or authors.
 *
 * 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.
 */
package org.openinfinity.core.async;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import org.openinfinity.core.annotation.Log;
import org.openinfinity.core.exception.ExceptionLevel;
import org.openinfinity.core.exception.SystemException;
import org.openinfinity.core.integration.CrudService;
import org.openinfinity.core.util.ExceptionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.core.task.support.ExecutorServiceAdapter;
import org.springframework.stereotype.Component;

/**
 * This class is responsible of high end optimized CRUD service interface integrations by parallel processing. Class can be utilized for service orchestration by parallel processing.
 * 
 * @author Ilkka Leinonen
 * 
 * @version 1.0.0
 * @since 2.0.0
 */
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ParallelServiceActivator {

    /**
     * Executor service is responsible of maintaining the actual thread pool. Thread pool can be configured by dependency injection.
     */
    @Autowired
    private ExecutorServiceAdapter executorServiceAdapter;

    /**
     * Sets the Spring Framework's executor service.
     * 
     * @param executorServiceAdapter
     */
    public void setExecutorServiceAdapter(ExecutorServiceAdapter executorServiceAdapter) {
        this.executorServiceAdapter = executorServiceAdapter;
    }

    /**
     * Collection of callable interfaces.
     */
    private Collection<Callable<Object>> callables;

    /**
     * Result cache of the responses.
     */
    private Map<String, Loadable> resultCache;

    /**
     * Result presented as linked list.
     */
    private LinkedList<Loadable> resultQueue;

    /**
     * Constructor for the class. Initiates collection interfaces of the class.
     */
    public ParallelServiceActivator() {
        this.callables = Collections.checkedCollection(new ArrayList(), Callable.class);
        this.resultCache = new HashMap<String, Loadable>();
        this.resultQueue = new LinkedList<Loadable>();
    }

    /**
     * Parallel 'query all' interface by id. 
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param id Represents the actual unique id to be queried.
     * @return The type safe collection.
     */
    @Log
    public <T, ID extends Object> ParallelServiceActivator prepareToQueryAllById(CrudService<T, ID> crudService,
            ID id) {
        GenericCrudServiceQueryAllByIdCallable<T, ID> result = new GenericCrudServiceQueryAllByIdCallable<T, ID>(
                crudService, id);
        callables.add(result);
        this.resultQueue.add(result);
        return this;
    }

    /**
     * Parallel 'query by id' interface by id. 
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param id Represents the actual unique id to be queried.
     * @return The type safe collection.
     */
    @Log
    public <T, ID extends Object> ParallelServiceActivator prepareToQueryById(CrudService<T, ID> crudService,
            ID id) {
        GenericCrudServiceQueryByIdCallable<T, ID> result = new GenericCrudServiceQueryByIdCallable<T, ID>(
                crudService, id);
        callables.add(result);
        this.resultQueue.push(result);
        return this;
    }

    /**
     *  Parallel 'create' interface with type safe entity. 
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param id Represents the actual type of the unique id.
     * @param type Represents the actual type safe.
     * @return Type safe entity.
     */
    @Log
    public <T, ID, TYPE extends Object> ParallelServiceActivator prepareToCreate(CrudService<T, ID> crudService,
            ID id, TYPE type) {
        GenericCrudServiceCreateCallable<T, ID, TYPE> result = new GenericCrudServiceCreateCallable(crudService, id,
                type);
        callables.add(result);
        this.resultQueue.push(result);
        return this;
    }

    /**
     * Parallel 'delete by id' interface for removing unique entity. 
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param id Represents the actual unique id to be queried.
     * @return
     */
    @Log
    public <T, ID, TYPE extends Object> ParallelServiceActivator prepareToDelete(CrudService<T, ID> crudService,
            ID id) {
        GenericCrudServiceDeleteCallable<T, ID> result = new GenericCrudServiceDeleteCallable(crudService, id);
        callables.add(result);
        return this;
    }

    /**
     * Parallel 'query by id' interface for quering type safe entities. 
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param parameters Represents the query parameters (key, value) for the query interface.
     * @return Type safe result of the query.
     */
    @Log
    public <T, ID extends Object> ParallelServiceActivator prepareToQueryById(CrudService<T, ID> crudService,
            Map<?, ?> parameters) {
        GenericCrudServiceQueryAllByCriteriaCallable<T, ID> result = new GenericCrudServiceQueryAllByCriteriaCallable<T, ID>(
                crudService, parameters);
        callables.add(result);
        this.resultQueue.add(result);
        return this;
    }

    /**
     * Parallel 'query all by id' interface for quering type safe entities. 
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param id Represents the actual unique id to be queried.
     * @param resultIdentifier
     * @return
     */
    @Log
    public <T, ID extends Object> ParallelServiceActivator prepareToQueryAllById(CrudService<T, ID> crudService,
            ID id, String resultIdentifier) {
        GenericCrudServiceQueryAllByIdCallable<T, ID> result = new GenericCrudServiceQueryAllByIdCallable<T, ID>(
                crudService, id);
        callables.add(result);
        resultCache.put(resultIdentifier, result);
        return this;
    }

    /**
     * Parallel 'query by id' interface for quering type safe entities. 
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param id Represents the actual unique id to be queried.
     * @param resultIdentifier
     * @return
     */
    @Log
    public <T, ID extends Object> ParallelServiceActivator prepareToQueryById(CrudService<T, ID> crudService, ID id,
            String resultIdentifier) {
        GenericCrudServiceQueryByIdCallable<T, ID> result = new GenericCrudServiceQueryByIdCallable<T, ID>(
                crudService, id);
        callables.add(result);
        resultCache.put(resultIdentifier, result);
        return this;
    }

    /**
     * Parallel 'query by id' interface for quering collection of type safe entities. 
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param parameters
     * @param resultIdentifier
     * @return
     */
    @Log
    public <T, ID extends Object> ParallelServiceActivator prepareToQueryAllByCriteria(
            CrudService<T, ID> crudService, Map<?, ?> parameters, String resultIdentifier) {
        GenericCrudServiceQueryAllByCriteriaCallable<T, ID> result = new GenericCrudServiceQueryAllByCriteriaCallable<T, ID>(
                crudService, parameters);
        callables.add(result);
        resultCache.put(resultIdentifier, result);
        return this;
    }

    /**
     * Activates all prepared queries simultaniously.
     * 
     * @param crudService Represents the actual service implement <code>org.openinfinity.core.integration.CrudService</code>.
     * @param timeout Represents the timeout if activation is not processed in given time frame. 
     * @param unit Represents the time unit of the given time frame. 
     * @return
     * @throws SystemException
     */
    @Log
    public ParallelServiceActivator activate(long timeout, TimeUnit unit) throws SystemException {
        try {
            executorServiceAdapter.invokeAll(callables, timeout, unit);
        } catch (InterruptedException interruptedException) {
            ExceptionUtil.throwSystemException(interruptedException.getMessage(), interruptedException,
                    ExceptionLevel.ERROR, "unique.exception.system.threading.error");
        }
        return this;
    }

    /**
     * Activates all prepared queries simultaniously.
     *
     * @return Instanse of the service activator.
     * @throws SystemException
     */
    public ParallelServiceActivator activate() throws SystemException {
        try {
            executorServiceAdapter.invokeAll(callables);
        } catch (InterruptedException interruptedException) {
            ExceptionUtil.throwSystemException(interruptedException.getMessage(), interruptedException,
                    ExceptionLevel.ERROR, "unique.exception.system.threading.error");
        }
        return this;
    }

    /**
     * Loads given result with identifier after parallel execution.
     * 
     * @param resultIdentifier Represents the unique id of the predefined result.
     * @return
     */
    public <T extends Object> T loadResult(String resultIdentifier) {
        if (resultCache.containsKey(resultIdentifier)) {
            return (T) resultCache.get(resultIdentifier).loadResult();
        } else {
            ExceptionUtil.throwSystemException("unique.exception.id.not.found", ExceptionLevel.ERROR,
                    "unique.exception.system.threading.error");
        }
        return null;
    }

    /**
     * Loads result from the response queue.
     * 
     * @return
     */
    public <T extends Object> T loadResult() {
        if (resultQueue.size() > 0) {
            Loadable loadable = resultQueue.pop();
            return (T) loadable.loadResult();
        } else {
            ExceptionUtil.throwSystemException("unique.exception.id.not.found", ExceptionLevel.ERROR,
                    "unique.exception.system.threading.error");
        }
        return null;
    }

    /**
     * Result callback method for responses.
     * 
     * @param asyncResultCallback Represents the callback interface.
     * @return
     */
    public ParallelServiceActivator onResult(AsyncResultCallback asyncResultCallback) {
        if (resultQueue.size() > 0) {
            Loadable loadable = resultQueue.pop();
            asyncResultCallback.onResult(loadable.loadResult());
        } else {
            ExceptionUtil.throwSystemException("unique.exception.id.not.found", ExceptionLevel.ERROR,
                    "unique.exception.system.threading.error");
        }
        return this;
    }

    /**
     * * Result callback method for response based on result indentifier.
     * 
     * @param resultIdentifier Represent the unique identifier of the result.
     * @param asyncResultCallback Represent the callback interface for the result.
     * @return
     */
    public ParallelServiceActivator onResult(String resultIdentifier, AsyncResultCallback asyncResultCallback) {
        asyncResultCallback.onResult(loadResult(resultIdentifier));
        return this;
    }

}