com.castlemock.web.basis.service.ServiceProcessorImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.castlemock.web.basis.service.ServiceProcessorImpl.java

Source

/*
 * Copyright 2015 Karl Dahlgren
 *
 * 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.castlemock.web.basis.service;

import com.castlemock.core.basis.model.*;
import com.castlemock.core.basis.model.user.domain.User;
import com.castlemock.core.basis.model.validation.validator.NotNullValidator;
import com.castlemock.core.basis.model.validation.validator.Validator;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

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

/**
 * The ServiceProcessor is responsible for processing input message and route them to the service responsible
 * for processing and handling the incoming message. The ServiceProcessor is also responsible for validating
 * both the input and output message.
 * @author Karl Dahlgren
 * @since 1.0
 */
@Component
public class ServiceProcessorImpl implements ServiceProcessor {

    @Autowired
    private ServiceRegistry serviceRegistry;
    private static final String UNKNOWN_USER = "Unknown";
    private static final Logger LOGGER = Logger.getLogger(ServiceProcessorImpl.class);
    private static final List<Validator> VALIDATORS = new ArrayList<Validator>();

    static {
        VALIDATORS.add(new NotNullValidator());
    }

    /**
     * The process method is responsible for processing the incoming input message and
     * route it to the corresponding service class.
     * @param input The incoming input message
     * @param <I> Input type
     * @param <O> Output type
     * @return Returns the service result generated by the service responsible for processing the incoming input message
     */
    @Override
    public <I extends Input, O extends Output> O process(final I input) {
        validateMessage(input);
        final Service<I, O> service = serviceRegistry.getService(input);

        if (service == null) {
            throw new IllegalArgumentException("Unable to find service for " + input.getClass().getSimpleName());
        }

        final ServiceTask<I> serviceTask = new ServiceTask<I>();
        serviceTask.setInput(input);
        serviceTask.setServiceConsumer(getLoggedInUsername());
        LOGGER.debug(getLoggedInUsername() + " is requesting " + service.getClass().getSimpleName()
                + " to process the following input message: " + input.getClass().getSimpleName());
        final ServiceResult<O> serviceResult = service.process(serviceTask);
        validateMessage(serviceResult.getOutput());
        return serviceResult.getOutput();
    }

    /**
     * Very much like the {@link ServiceProcessor#process(Input)}, the process async method is responsible for
     * processing the incoming input message and route it to the corresponding service class. However, the main
     * difference between this method and {@link ServiceProcessor#process(Input)} is that this method process
     * the input message asynchronously. The method will return a future object instead. The future object
     * contains methods to determine the state of the ongoing process, such as {@link Future#isDone()}.
     * @param input The incoming input message
     * @param <I> Input type
     * @param <O> Output type
     * @return Returns the service result generated by the service responsible for processing the incoming input message
     */
    @Override
    @Async
    public <I extends Input, O extends Output> Future<O> processAsync(final I input) {
        O output = process(input);
        return new AsyncResult<O>(output);
    }

    /**
     * The method is responsible for validating the incoming or outgoing message with all the registered validators
     * @param message The message that will be validated
     * @param <M> The message type (Input or output)
     * @see Message
     * @see Input
     * @see Output
     * @see Validator
     */
    private static <M extends Message> void validateMessage(M message) {
        for (Validator validator : VALIDATORS) {
            validator.validateMessage(message);
        }
    }

    /**
     * Get the current logged in user username
     * @return The username of the current logged in user
     * @see User
     */
    protected String getLoggedInUsername() {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            return UNKNOWN_USER;
        }
        return authentication.getName();
    }

}