All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sysfoundry.kiln.base.ss.evt.SubscriberMeta Maven / Gradle / Ivy

There is a newer version: 0.1.3
Show newest version
/*
 * Copyright 2019 Sysfoundry (www.sysfoundry.org)
 *
 * 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.sysfoundry.kiln.base.ss.evt;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.sysfoundry.kiln.base.evt.Event;
import org.sysfoundry.kiln.base.evt.OnEvent;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
class SubscriberMeta {

    private Class subscriberType;
    private Optional interestedEventsOptional = Optional.empty();
    private Optional> interestedEventsOptionalList = Optional.empty();
    private Optional targetMethodOptional = Optional.empty();
    private Optional> targetMethodListOptional = Optional.empty();
    private boolean hasMultipleOnEventMethods = false;

    SubscriberMeta(@NonNull Class subscriberType){
        this.subscriberType = subscriberType;
        this.targetMethodListOptional = _findTargetMethods(this.subscriberType);
        log.trace("targetMethodListOptional {}",targetMethodListOptional);
        this.hasMultipleOnEventMethods = _hasMultipleOnEventMethods(this.targetMethodListOptional);
        this.targetMethodOptional = _chooseTargetMethod(this.targetMethodListOptional);

        targetMethodOptional.ifPresent(method->{
            interestedEventsOptional = _findInterestedEvents(method);
            interestedEventsOptional.ifPresent(events->{
                interestedEventsOptionalList = Optional.ofNullable(Arrays.asList(events));
            });
        });

    }

    boolean isValidEventTarget(){
        return targetMethodOptional.isPresent();
    }

    Optional> getInterestedEventsList(){
        return interestedEventsOptionalList;
    }

    boolean hasMultipleOnEventMethods(){
        return hasMultipleOnEventMethods;
    }

    Optional> getTargetMethods(){
        return targetMethodListOptional;
    }

    Optional getTargetMethod(){
        return targetMethodOptional;
    }

    Class getSubscriberType(){
        return subscriberType;
    }

    private Optional _findInterestedEvents(Method method) {
        Optional interestedEvents = Optional.empty();
        OnEvent onEventAnnotation = method.getAnnotation(OnEvent.class);
        if(onEventAnnotation != null){
            String[] events = onEventAnnotation.value();
            interestedEvents = Optional.ofNullable(events);
        }
        return interestedEvents;
    }

    private Optional _chooseTargetMethod(Optional> targetMethodListOptional) {
        if(targetMethodListOptional.isPresent()){
            List targetMethods = targetMethodListOptional.get();
            if(targetMethods.isEmpty()){
                return Optional.empty();
            }else if(targetMethods.size() == 1){
                return Optional.ofNullable(targetMethods.get(0));
            }else{
                //there are more than one method annotated with OnEvent
                //so pick the first one with the Event parameter
                List methodWithEventParams = targetMethods.stream().filter(method -> {
                    boolean retVal = false;
                    if(method.getParameterCount() == 1){
                        Class[] parameterTypes = method.getParameterTypes();
                        if(Event.class.isAssignableFrom(parameterTypes[0])){
                            retVal = true;
                        }
                    }
                    return retVal;
                }).collect(Collectors.toList());

                if(methodWithEventParams.isEmpty()){
                    //in this case just pick the first one in the list and return back
                    return Optional.ofNullable(targetMethods.get(0));
                }else{
                    return Optional.ofNullable(methodWithEventParams.get(0));
                }
            }

        }else{
            return Optional.empty();
        }

    }

    private boolean _hasMultipleOnEventMethods(Optional> targetMethodListOptional) {
        boolean retVal = false;

        if(targetMethodListOptional.isPresent()){
            List methods = targetMethodListOptional.get();
            if(methods.size() > 1){
                retVal = true;
            }
        }
        return retVal;
    }

    private Optional> _findTargetMethods(Class targetClass) {
        Method[] methods = targetClass.getDeclaredMethods();

        ArrayList targetMethods = new ArrayList<>();

        for (Method method : methods) {

            if(isValidTargetMethod(method)){
                targetMethods.add(method);
            }
        }

        return Optional.ofNullable(targetMethods);
    }

    private boolean isValidTargetMethod(Method declaredMethod) {
        boolean retVal = false;
        OnEvent onEventAnnotation = declaredMethod.getAnnotation(OnEvent.class);
        if(onEventAnnotation != null && declaredMethod.getParameterCount() < 2){
            if(declaredMethod.getParameterCount() > 0){
                Class[] parameterTypes = declaredMethod.getParameterTypes();
                if(Event.class.isAssignableFrom(parameterTypes[0])){
                    retVal = true;
                }
            }else{
                retVal = true;
            }
        }

        return retVal;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy