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

com.coditory.quark.context.ContextResolver Maven / Gradle / Ivy

There is a newer version: 0.1.22
Show newest version
package com.coditory.quark.context;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

final class ContextResolver {
    private static final Logger log = LoggerFactory.getLogger(ContextResolver.class);

    private ContextResolver() {
        throw new UnsupportedOperationException("Do not instantiate utility class");
    }

    static Map, List>> resolve(Set> beanHolders, Map properties) {
        Set> holders = new HashSet<>(beanHolders);
        ConditionContext contextWithAllBeans = ConditionContext.from(holders, properties);
        ConditionContext contextWithNoBeans = ConditionContext.from(properties);
        Set> stableBeanHolders = findStableBeans(holders, contextWithAllBeans, contextWithNoBeans);
        holders.removeAll(stableBeanHolders);
        Set> additiveBeanHolders = findAdditiveBeans(holders, contextWithAllBeans);
        holders.removeAll(additiveBeanHolders);
        return resolve(stableBeanHolders, additiveBeanHolders, holders, properties);
    }

    private static Set> findStableBeans(Set> holders, ConditionContext contextWithAllBeans, ConditionContext contextWithNoBeans) {
        return holders.stream()
                .filter(it -> it.isActive(contextWithNoBeans))
                .filter(it -> it.isActive(contextWithAllBeans))
                .collect(toSet());
    }

    private static Set> findAdditiveBeans(Set> holders, ConditionContext contextWithAllBeans) {
        return holders.stream()
                .filter(it -> it.isActive(contextWithAllBeans))
                .collect(toSet());
    }

    private static Map, List>> resolve(
            Set> stableBeanHolders,
            Set> additiveBeanHolders,
            Set> remainingBeanHolders,
            Map properties
    ) {
        Set beanNames = new HashSet<>();
        Set> registeredBeans = new HashSet<>();
        Map, List>> result = new HashMap<>();
        stableBeanHolders.forEach(holder -> {
            addBeanName(beanNames, holder);
            addBeanHolderWithClassHierarchy(result, holder);
            registeredBeans.add(holder);
        });
        ConditionContext context = ConditionContext.from(registeredBeans, properties);
        int registered;
        do {
            do {
                registered = registeredBeans.size();
                for (BeanHolder holder : additiveBeanHolders) {
                    if (canBeAddedToContext(holder, registeredBeans, context)) {
                        addBeanName(beanNames, holder);
                        addBeanHolderWithClassHierarchy(result, holder);
                        registeredBeans.add(holder);
                        context = context.with(holder);
                    }
                }
                additiveBeanHolders.removeAll(registeredBeans);
            } while (registered < registeredBeans.size());
            for (BeanHolder holder : remainingBeanHolders) {
                if (canBeAddedToContext(holder, registeredBeans, context)) {
                    addBeanName(beanNames, holder);
                    addBeanHolderWithClassHierarchy(result, holder);
                    registeredBeans.add(holder);
                    context = context.with(holder);
                    break;
                }
            }
            remainingBeanHolders.removeAll(registeredBeans);
        } while (registered < registeredBeans.size());
        logResolvedBeans(registeredBeans, additiveBeanHolders, remainingBeanHolders);
        return result;
    }

    private static void logResolvedBeans(Set> registered, Set> additiveBeanHolders, Set> remainingBeanHolders) {
        if (log.isInfoEnabled()) {
            List names = registered.stream()
                    .map(h -> h.getDescriptor().toShortString())
                    .sorted()
                    .collect(toList());
            log.info("Registered beans: {}", names);
        }
        Set> skipped = new HashSet<>();
        skipped.addAll(additiveBeanHolders);
        skipped.addAll(remainingBeanHolders);
        if (log.isDebugEnabled() && !skipped.isEmpty()) {
            List names = skipped.stream()
                    .map(h -> h.getDescriptor().toShortString())
                    .sorted()
                    .collect(toList());
            log.debug("Skipped beans: {}", names);
        }
    }

    private static boolean canBeAddedToContext(BeanHolder holder, Set> registeredBeans, ConditionContext context) {
        if (!holder.isActive(context)) {
            return false;
        }
        ConditionContext contextWithBean = context.with(holder);
        return registeredBeans.stream()
                .allMatch(registered -> registered.isActive(contextWithBean));
    }

    private static void addBeanName(Set beanNames, BeanHolder holder) {
        String name = holder.getBeanName();
        if (name == null) {
            return;
        }
        if (beanNames.contains(name)) {
            throw new ContextException("Duplicated bean name: " + name);
        }
        beanNames.add(name);
    }

    private static  void addBeanHolderWithClassHierarchy(Map, List>> holders, BeanHolder holder) {
        holder.getBeanClassHierarchyDescriptors().forEach(descriptor -> {
            List> registeredBeanCreators = holders
                    .computeIfAbsent(descriptor, (k) -> new ArrayList<>());
            registeredBeanCreators.add(holder);
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy