Package com.codebullets.sagalib.startup

Source Code of com.codebullets.sagalib.startup.EventStreamBuilder

/*
* Copyright 2013 Stefan Domnanovits
*
* 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 com.codebullets.sagalib.startup;

import com.codebullets.sagalib.MessageStream;
import com.codebullets.sagalib.Saga;
import com.codebullets.sagalib.SagaLifetimeInterceptor;
import com.codebullets.sagalib.SagaModule;
import com.codebullets.sagalib.context.CurrentExecutionContext;
import com.codebullets.sagalib.context.SagaExecutionContext;
import com.codebullets.sagalib.processing.HandlerInvoker;
import com.codebullets.sagalib.processing.KeyExtractor;
import com.codebullets.sagalib.processing.Organizer;
import com.codebullets.sagalib.processing.ReflectionInvoker;
import com.codebullets.sagalib.processing.SagaEnvironment;
import com.codebullets.sagalib.processing.SagaFactory;
import com.codebullets.sagalib.processing.SagaKeyReaderExtractor;
import com.codebullets.sagalib.processing.SagaMessageStream;
import com.codebullets.sagalib.processing.SagaProviderFactory;
import com.codebullets.sagalib.storage.StateStorage;
import com.codebullets.sagalib.timeout.InMemoryTimeoutManager;
import com.codebullets.sagalib.timeout.TimeoutManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Provider;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import static com.google.common.base.Preconditions.checkNotNull;

/**
* Creates a new instance of an {@link com.codebullets.sagalib.MessageStream} to run the saga lib.
*/
public final class EventStreamBuilder implements StreamBuilder {
    private static final Logger LOG = LoggerFactory.getLogger(EventStreamBuilder.class);

    private final List<Class<? extends Saga>> preferredOrder = new ArrayList<>();
    private final Set<SagaModule> modules = new HashSet<>();
    private final Set<SagaLifetimeInterceptor> interceptors = new HashSet<>();
    private HandlerInvoker invoker;
    private SagaAnalyzer sagaAnalyzer;
    private TypeScanner scanner;
    private StateStorage storage;
    private SagaProviderFactory providerFactory;
    private TimeoutManager timeoutManager;
    private Provider<CurrentExecutionContext> contextProvider;
    private Executor executor;

    /**
     * Prevent instantiation from outside. Use {@link #configure()} instead.
     */
    private EventStreamBuilder() {
    }

    /**
     * Start configuration and creation of the saga lib event stream.
     */
    public static StreamBuilder configure() {
        return new EventStreamBuilder();
    }

    @Override
    public MessageStream build() {
        if (providerFactory == null) {
            throw new UnsupportedOperationException("The saga provider factory has to be set to build the event stream.");
        }

        buildTypeScanner();
        buildTimeoutManager();
        buildSagaAnalyzer();
        buildInvoker();
        buildContextProvider();
        buildExecutor();

        KeyExtractor extractor = new SagaKeyReaderExtractor(providerFactory);
        Organizer organizer = new Organizer(sagaAnalyzer, extractor);
        organizer.setPreferredOrder(preferredOrder);

        SagaFactory sagaFactory = new SagaFactory(providerFactory, storage, timeoutManager, organizer);
        SagaEnvironment environment = SagaEnvironment.create(timeoutManager, storage, sagaFactory, contextProvider, modules, interceptors);

        return new SagaMessageStream(invoker, environment, executor);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamBuilder usingScanner(final TypeScanner typeScanner) {
        checkNotNull(typeScanner, "Scanner to use must not be null.");

        this.scanner = typeScanner;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamBuilder usingStorage(final StateStorage stateStorage) {
        checkNotNull(stateStorage, "Storage to use must not be null.");

        this.storage = stateStorage;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamBuilder usingTimeoutManager(final TimeoutManager manager) {
        checkNotNull(manager, "Timeout manager must not be null.");

        this.timeoutManager = manager;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamBuilder usingSagaProviderFactory(final SagaProviderFactory sagaProviderFactory) {
        checkNotNull(sagaProviderFactory, "Provider factory must be set.");

        providerFactory = sagaProviderFactory;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamBuilder usingContextProvider(final Provider<CurrentExecutionContext> provider) {
        checkNotNull(contextProvider, "Context provider must be set.");

        contextProvider = provider;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamBuilder usingExecutor(final Executor executorService) {
        executor = executorService;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public FirstSagaToHandle defineHandlerExecutionOrder() {
        return new FirstSagaToHandle(preferredOrder, this);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamBuilder callingModule(final SagaModule module) {
        modules.add(module);
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public StreamBuilder callingInterceptor(final SagaLifetimeInterceptor interceptor) {
        interceptors.add(interceptor);
        return this;
    }

    private void buildTypeScanner() {
        if (scanner == null) {
            scanner = new ReflectionsTypeScanner();
        }
    }

    private void buildSagaAnalyzer() {
        if (sagaAnalyzer == null) {
            sagaAnalyzer = new AnnotationSagaAnalyzer(scanner);
        }
    }

    private void buildInvoker() {
        if (invoker == null) {
            invoker = new ReflectionInvoker(sagaAnalyzer);
        }
    }

    private void buildTimeoutManager() {
        if (timeoutManager == null) {
            timeoutManager = new InMemoryTimeoutManager();
        }
    }

    private void buildContextProvider() {
        if (contextProvider == null) {
            contextProvider = new Provider<CurrentExecutionContext>() {
                    @Override
                    public CurrentExecutionContext get() {
                        return new SagaExecutionContext();
                    }
                };
        }
    }

    private void buildExecutor() {
        if (executor == null) {
            executor = Executors.newSingleThreadExecutor(
                    new ThreadFactory() {
                        @Override
                        public Thread newThread(final Runnable r) {
                            Thread thread = new Thread(r, "saga-lib");
                            thread.setDaemon(true);
                            return thread;
                        }
                    }
            );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() {
        tryClose(timeoutManager);
        tryClose(storage);
    }

    /**
     * Calls close if object implements {@link AutoCloseable} interface.
     */
    private void tryClose(final Object objectToClose) {
        try {
            if (objectToClose instanceof AutoCloseable) {
                AutoCloseable closeable = (AutoCloseable) objectToClose;
                closeable.close();
            }
        } catch (Exception ex) {
            LOG.error("Error closing object {}.", objectToClose, ex);
        }
    }
}
TOP

Related Classes of com.codebullets.sagalib.startup.EventStreamBuilder

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.