org.archifacts.integration.c4.model.C4ModelTransformer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of archifacts-c4-model Show documentation
Show all versions of archifacts-c4-model Show documentation
archifacts C4 Model integration
package org.archifacts.integration.c4.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.archifacts.core.model.Application;
import org.archifacts.core.model.Artifact;
import org.archifacts.core.model.ArtifactContainer;
import org.archifacts.core.model.ArtifactRelationship;
import org.archifacts.core.model.BuildingBlock;
import org.archifacts.core.model.Named;
import com.structurizr.model.Component;
import com.structurizr.model.Container;
import com.structurizr.model.Relationship;
import com.structurizr.model.SoftwareSystem;
public final class C4ModelTransformer {
private static final class CachingSupplier implements Supplier {
private T cachedValue;
private final Supplier originalSupplier;
public CachingSupplier(final Supplier originalSupplier) {
this.originalSupplier = originalSupplier;
}
@Override
public T get() {
if (cachedValue == null) {
cachedValue = originalSupplier.get();
}
return cachedValue;
}
}
private static Supplier memoize(final Supplier valueSupplier) {
return new CachingSupplier(valueSupplier);
}
private final Map containerMap = new HashMap<>();
private final Map componentMap = new HashMap<>();
private final Map relationshipMap = new HashMap<>();
private Optional noContainerContainer = Optional.empty();
private final Application application;
private final SoftwareSystem softwareSystem;
public C4ModelTransformer(final Application application, final SoftwareSystem softwareSystem) {
this.application = application;
this.softwareSystem = softwareSystem;
transform();
}
private void transform() {
transformContainers();
transformRelationships();
}
private void transformContainers() {
final Supplier noContainerContainerSupplier = memoize(() -> {
final Container noContainerContainer = softwareSystem.addContainer("no-container");
this.noContainerContainer = Optional.of(noContainerContainer);
return noContainerContainer;
});
final Map> containerArtifactsMap = new HashMap<>();
application.getArtifacts().forEach(artifact -> {
final Container container = artifact.getContainer()
.map(artifactContainer -> containerMap.computeIfAbsent(artifactContainer, m -> softwareSystem.addContainer(m.getName(), null, artifactContainer.getType().getName())))
.orElseGet(noContainerContainerSupplier);
final List artifacts = containerArtifactsMap.computeIfAbsent(container, x -> new ArrayList<>());
artifacts.add(artifact);
});
containerArtifactsMap.entrySet().forEach(entry -> {
final Container container = entry.getKey();
final List artifacts = entry.getValue();
final boolean containsAmbiguousNames = containsAmbiguousNames(artifacts);
artifacts.forEach(artifact -> {
final String componentName = containsAmbiguousNames ? artifact.getJavaClass().getFullName() : artifact.getName();
final Component component = container.addComponent(componentName, artifact.getJavaClass().getName(), null, getTechnology(artifact));
componentMap.put(artifact, component);
});
});
}
private void transformRelationships() {
application.getRelationships().forEach(artifactRelationship -> {
final Component sourceComponent = componentMap.get(artifactRelationship.getSource());
final Component targetComponent = componentMap.get(artifactRelationship.getTarget());
final Relationship relationship = sourceComponent.uses(targetComponent, artifactRelationship.getRole().getName());
relationshipMap.put(artifactRelationship, relationship);
});
}
private boolean containsAmbiguousNames(final List extends Named> named) {
return named
.stream()
.map(Named::getName)
.distinct()
.count() < named.size();
}
private String getTechnology(final Artifact artifact) {
if (artifact instanceof BuildingBlock) {
return ((BuildingBlock) artifact).getType().getName();
}
return null;
}
public Set getContainers(final Predicate predicate) {
return containerMap.entrySet().stream()
.filter(entry -> predicate.test(entry.getKey()))
.map(Entry::getValue)
.collect(Collectors.toUnmodifiableSet());
}
public Set getComponents(final Predicate predicate) {
return componentMap.entrySet().stream()
.filter(entry -> predicate.test(entry.getKey()))
.map(Entry::getValue)
.collect(Collectors.toUnmodifiableSet());
}
public Set getRelationships(final Predicate predicate) {
return relationshipMap.entrySet().stream()
.filter(entry -> predicate.test(entry.getKey()))
.map(Entry::getValue)
.collect(Collectors.toUnmodifiableSet());
}
public Optional getNoContainerContainer() {
return noContainerContainer;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy