io.cereebro.core.SimpleSystemResolver Maven / Gradle / Ivy
/*
* Copyright © 2017 the original authors (http://cereebro.io)
*
* 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 io.cereebro.core;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import io.cereebro.core.ComponentRelationships.ComponentRelationshipsBuilder;
import io.cereebro.core.System.SystemBuilder;
import lombok.extern.slf4j.Slf4j;
/**
* Simple system resolver, adding up all the relationships discovered while
* browsing a SnitchRegistry.
*
* @author michaeltecourt
*/
@Slf4j
public class SimpleSystemResolver implements SystemResolver {
private static final String DEFAULT_ERROR_MESSAGE = "Could not access or process Snitch";
@Override
public System resolve(String systemName, SnitchRegistry snitchRegistry) {
Set frags = new HashSet<>();
Set errors = new HashSet<>();
for (Snitch snitch : snitchRegistry.getAll()) {
try {
frags.add(snitch.snitch());
} catch (SnitchingException e) {
LOGGER.error("Snitch error caught while resolving system at URI : " + e.getSnitchUri(), e);
errors.add(ResolutionError.translate(e));
} catch (RuntimeException e) {
LOGGER.error("Technical error caught while resolving system at URI : " + snitch.getUri(), e);
errors.add(ResolutionError.of(snitch.getUri(), DEFAULT_ERROR_MESSAGE));
}
}
return resolveBuilder(systemName, frags).errors(errors).build();
}
@Override
public System resolve(String systemName, Collection fragments) {
return resolveBuilder(systemName, fragments).build();
}
/**
* Resolves the system and returns a mutable {@link SystemBuilder} instance.
*
* @param systemName
* System name.
* @param fragments
* System fragments.
* @return mutable SystemBuilder ready to be built into the real System.
*/
private SystemBuilder resolveBuilder(String systemName, Collection fragments) {
// Flatten all fragments into a single relationship set
Set relationships = fragments.stream().map(SystemFragment::getComponentRelationships)
.flatMap(Collection::stream).collect(Collectors.toSet());
Map map = new HashMap<>();
// Browse all relationships to complete them with one another
for (ComponentRelationships rel : relationships) {
ComponentRelationshipsBuilder builder = getOrCreate(map, rel.getComponent());
Set dependencies = rel.getDependencies();
builder.addDependencies(dependencies);
// Add the current component as a consumer of its dependencies
for (Dependency dependency : dependencies) {
ComponentRelationshipsBuilder dependencyBuilder = getOrCreate(map, dependency.getComponent());
dependencyBuilder.addConsumer(Consumer.by(rel.getComponent()));
}
Set consumers = rel.getConsumers();
builder.addConsumers(consumers);
// Add the current component as a dependency of its consumers
for (Consumer consumer : consumers) {
ComponentRelationshipsBuilder consumerBuilder = getOrCreate(map, consumer.getComponent());
consumerBuilder.addDependency(Dependency.on(rel.getComponent()));
}
}
// @formatter:off
Set bigPicture = map.values().stream()
.map(ComponentRelationshipsBuilder::build)
.collect(Collectors.toSet());
// @formatter:on
return System.builder().name(systemName).componentRelationships(bigPicture);
}
/**
* Create a ComponentRelationshipsBuilder if one didn't already exist in the
* map.
*
* @param map
* @param component
* @return ComponentRelationshipsBuilder
*/
private ComponentRelationshipsBuilder getOrCreate(Map map,
Component component) {
ComponentRelationshipsBuilder builder = map.get(component);
if (builder == null) {
builder = ComponentRelationships.builder().component(component);
map.put(component, builder);
}
return builder;
}
}