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

com.structurizr.component.ComponentFinder Maven / Gradle / Ivy

package com.structurizr.component;

import com.structurizr.component.filter.TypeFilter;
import com.structurizr.component.provider.TypeProvider;
import com.structurizr.model.Component;
import com.structurizr.model.Container;
import com.structurizr.util.StringUtils;
import org.apache.bcel.Repository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.*;

/**
 * Allows you to find components in a Java codebase based upon a set of pluggable and customisable rules.
 * Use the {@link ComponentFinderBuilder} to create an instance of this class.
 */
public final class ComponentFinder {

    private static final Log log = LogFactory.getLog(ComponentFinder.class);

    private static final String COMPONENT_TYPE_PROPERTY_NAME = "component.type";
    private static final String COMPONENT_SOURCE_PROPERTY_NAME = "component.src";

    private final TypeRepository typeRepository = new TypeRepository();
    private final Container container;
    private final List componentFinderStrategies = new ArrayList<>();

    ComponentFinder(Container container, TypeFilter typeFilter, Collection typeProviders, List componentFinderStrategies) {
        this.container = container;
        this.componentFinderStrategies.addAll(componentFinderStrategies);

        log.debug("Initialising component finder:");
        log.debug(" - for: " + container.getCanonicalName());
        for (TypeProvider typeProvider : typeProviders) {
            log.debug(" - from: " + typeProvider);
        }
        log.debug(" - filtered by: " + typeFilter);
        for (ComponentFinderStrategy strategy : componentFinderStrategies) {
            log.debug(" - with strategy: " + strategy);
        }

        new TypeFinder().run(typeProviders, typeFilter, typeRepository);
        Repository.clearCache();
        for (Type type : typeRepository.getTypes()) {
            if (type.getJavaClass() != null) {
                Repository.addClass(type.getJavaClass());
                new TypeDependencyFinder().run(type, typeRepository);
            }
        }
    }

    /**
     * Find components, using all configured strategies, in the order they were added.
     */
    public Set run() {
        Set discoveredComponents = new LinkedHashSet<>();
        Map componentMap = new HashMap<>();
        Set componentSet = new LinkedHashSet<>();

        for (ComponentFinderStrategy componentFinderStrategy : componentFinderStrategies) {
            Set set = componentFinderStrategy.run(typeRepository);
            if (set.isEmpty()) {
                throw new RuntimeException("No components were found by " + componentFinderStrategy);
            }
            discoveredComponents.addAll(set);
        }

        for (DiscoveredComponent discoveredComponent : discoveredComponents) {
            Component component = container.addComponent(discoveredComponent.getName());
            component.addProperty(COMPONENT_TYPE_PROPERTY_NAME, discoveredComponent.getPrimaryType().getFullyQualifiedName());
            if (!StringUtils.isNullOrEmpty(discoveredComponent.getPrimaryType().getSource())) {
                component.addProperty(COMPONENT_SOURCE_PROPERTY_NAME, discoveredComponent.getPrimaryType().getSource());
            }
            component.setDescription(discoveredComponent.getDescription());
            component.setTechnology(discoveredComponent.getTechnology());
            component.setUrl(discoveredComponent.getUrl());

            component.addTags(discoveredComponent.getTags().toArray(new String[0]));
            for (String name : discoveredComponent.getProperties().keySet()) {
                component.addProperty(name, discoveredComponent.getProperties().get(name));
            }

            componentMap.put(discoveredComponent, component);
            componentSet.add(component);
        }

        // find dependencies between all components
        for (DiscoveredComponent discoveredComponent : discoveredComponents) {
            Component component = componentMap.get(discoveredComponent);
            log.debug("Component dependencies for \"" + component.getName() + "\":");
            Set typeDependencies = discoveredComponent.getAllDependencies();
            for (Type typeDependency : typeDependencies) {
                for (DiscoveredComponent c : discoveredComponents) {
                    if (c != discoveredComponent) {
                        if (c.getAllTypes().contains(typeDependency)) {
                            Component componentDependency = componentMap.get(c);
                            log.debug(" -> " + componentDependency.getName());
                            component.uses(componentDependency, "");
                        }
                    }
                }
            }
            if (component.getRelationships().isEmpty()) {
                log.debug(" - none");
            }
        }

        // now visit all components
        for (DiscoveredComponent discoveredComponent : componentMap.keySet()) {
            Component component = componentMap.get(discoveredComponent);
            log.debug("Visiting \"" + component.getName() + "\"");
            discoveredComponent.getComponentFinderStrategy().visit(component);
        }

        return componentSet;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy