com.tngtech.archunit.library.plantuml.JavaClassDiagramAssociation.java Source code

Java tutorial

Introduction

Here is the source code for com.tngtech.archunit.library.plantuml.JavaClassDiagramAssociation.java

Source

/*
 * Copyright 2019 TNG Technology Consulting GmbH
 *
 * 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.tngtech.archunit.library.plantuml;

import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
import com.tngtech.archunit.base.PackageMatcher;
import com.tngtech.archunit.core.domain.JavaClass;

import static com.google.common.collect.Iterables.getOnlyElement;

class JavaClassDiagramAssociation {
    private final Set<AssociatedComponent> components;

    JavaClassDiagramAssociation(PlantUmlDiagram diagram) {
        ImmutableSet.Builder<AssociatedComponent> components = ImmutableSet.builder();
        validateStereotypes(diagram);
        for (PlantUmlComponent component : diagram.getAllComponents()) {
            components.add(new AssociatedComponent(component));
        }
        this.components = components.build();
    }

    private void validateStereotypes(PlantUmlDiagram plantUmlDiagram) {
        Set<Stereotype> visited = new HashSet<>();
        for (PlantUmlComponent component : plantUmlDiagram.getAllComponents()) {
            for (Stereotype stereotype : component.getStereotypes()) {
                if (visited.contains(stereotype)) {
                    throw new IllegalDiagramException(
                            String.format("Stereotype '%s' should be unique", stereotype.asString()));
                }
                visited.add(stereotype);
            }
        }
    }

    Set<String> getTargetPackageIdentifiers(final JavaClass javaClass) {
        ImmutableSet.Builder<String> result = ImmutableSet.builder();
        for (PlantUmlComponent target : getComponentOf(javaClass).getDependencies()) {
            result.addAll(getPackageIdentifiersFromComponentOf(target));
        }
        return result.build();
    }

    Set<String> getPackageIdentifiersFromComponentOf(JavaClass javaClass) {
        return getPackageIdentifiersFromComponentOf(getComponentOf(javaClass));
    }

    private Set<String> getPackageIdentifiersFromComponentOf(PlantUmlComponent component) {
        ImmutableSet.Builder<String> result = ImmutableSet.builder();
        for (Stereotype stereotype : component.getStereotypes()) {
            result.add(stereotype.asString());
        }
        return result.build();
    }

    private PlantUmlComponent getComponentOf(final JavaClass javaClass) {
        Set<PlantUmlComponent> associatedComponents = getAssociatedComponents(javaClass);

        if (associatedComponents.size() > 1) {
            throw new ComponentIntersectionException(String.format(
                    "Class %s may not be contained in more than one component, but is contained in [%s]",
                    javaClass.getName(), Joiner.on(", ").join(getComponentNames(associatedComponents))));
        } else if (associatedComponents.isEmpty()) {
            throw new IllegalStateException(
                    String.format("Class %s is not contained in any component", javaClass.getName()));
        }

        return getOnlyElement(associatedComponents);
    }

    boolean contains(JavaClass javaClass) {
        return !getAssociatedComponents(javaClass).isEmpty();
    }

    private Set<PlantUmlComponent> getAssociatedComponents(JavaClass javaClass) {
        ImmutableSet.Builder<PlantUmlComponent> result = ImmutableSet.builder();
        for (AssociatedComponent component : components) {
            if (component.contains(javaClass)) {
                result.add(component.asPlantUmlComponent());
            }
        }
        return result.build();
    }

    private Set<String> getComponentNames(Set<PlantUmlComponent> associatedComponents) {
        Set<String> associatedComponentNames = new TreeSet<>();
        for (PlantUmlComponent associatedComponent : associatedComponents) {
            associatedComponentNames.add(associatedComponent.getComponentName().asString());
        }
        return associatedComponentNames;
    }

    private static class AssociatedComponent {
        private final PlantUmlComponent component;
        private final Set<PackageMatcher> packageMatchers;

        private AssociatedComponent(PlantUmlComponent component) {
            this.component = component;
            ImmutableSet.Builder<PackageMatcher> packageMatchers = ImmutableSet.builder();
            for (Stereotype stereotype : component.getStereotypes()) {
                packageMatchers.add(PackageMatcher.of(stereotype.asString()));
            }
            this.packageMatchers = packageMatchers.build();
        }

        private boolean contains(JavaClass javaClass) {
            for (PackageMatcher packageMatcher : packageMatchers) {
                if (packageMatcher.matches(javaClass.getPackageName())) {
                    return true;
                }
            }
            return false;
        }

        PlantUmlComponent asPlantUmlComponent() {
            return component;
        }
    }
}