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

de.is24.deadcode4j.IntermediateResults Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
package de.is24.deadcode4j;

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

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;

/**
 * Instances of IntermediateResults are used to keep track of and calculate the {@link IntermediateResult}s
 * produced by and being made available to {@link AnalysisContext} instances, respectively.
 *
 * @since 2.0.0
 */
public final class IntermediateResults {
    @Nonnull
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Nonnull
    private final Map> intermediateResults = newHashMap();

    public IntermediateResults() {
    }

    /**
     * Returns an IntermediateResultSet for the given Set.
* This method is defined for type inference, as it could simply be replaced with a constructor call. * * @since 2.0.0 */ @Nonnull public static IntermediateResultSet resultSetFor(@Nonnull Collection intermediateResults) { return new IntermediateResultSet(intermediateResults); } /** * Returns an IntermediateResultMap for the given Map.
* This method is defined for type inference, as it could simply be replaced with a constructor call. * * @since 2.0.0 */ @Nonnull public static IntermediateResultMap resultMapFor(@Nonnull Map intermediateResults) { return new IntermediateResultMap(intermediateResults); } /** * Returns an IntermediateResultSet from the given AnalysisContext for the given key.
* This method is defined to handle the unchecked cast to a typed IntermediateResultSet, * it could simply be replaced with {@link AnalysisContext#getIntermediateResult(Object)}. * * @since 2.0.0 */ @Nullable @SuppressWarnings("unchecked") public static IntermediateResultSet resultSetFrom(@Nonnull AnalysisContext analysisContext, Object key) { return (IntermediateResultSet) analysisContext.getIntermediateResult(key); } /** * Returns an IntermediateResultMap from the given AnalysisContext for the given key.
* This method is defined to handle the unchecked cast to a typed IntermediateResultMap, * it could simply be replaced with {@link AnalysisContext#getIntermediateResult(Object)}. * * @since 2.0.0 */ @Nullable @SuppressWarnings("unchecked") public static IntermediateResultMap resultMapFrom(@Nonnull AnalysisContext analysisContext, Object key) { return (IntermediateResultMap) analysisContext.getIntermediateResult(key); } /** * Adds the intermediate results of the given analysis context's cache. * * @since 2.0.0 */ public void add(@Nonnull AnalysisContext analysisContext) { intermediateResults.put(analysisContext.getModule(), getIntermediateResultsOf(analysisContext)); } /** * Calculates the intermediate results being available for the specified module. * * @since 2.0.0 */ @Nonnull public Map calculateIntermediateResultsFor(@Nonnull Module module) { return calculateIntermediateResults(module); } @Nonnull private Map getIntermediateResultsOf(@Nonnull AnalysisContext analysisContext) { Map intermediateResults = newHashMap(); for (Map.Entry cachedEntry : analysisContext.getCache().entrySet()) { Object cachedValue = cachedEntry.getValue(); if (IntermediateResult.class.isInstance(cachedValue)) { logger.debug("{} stored [{}].", analysisContext.getModule(), cachedValue); intermediateResults.put(cachedEntry.getKey(), IntermediateResult.class.cast(cachedValue)); } } return intermediateResults; } @Nonnull private Map calculateIntermediateResults(@Nonnull Module module) { Map results = calculateResultsOfParentsFor(module); mergeWithResultsOf(module, results); return results; } @Nonnull private Map calculateResultsOfParentsFor(@Nonnull Module module) { Map mergedResults = newHashMap(); for (Module requiredModule : module.getRequiredModules()) { Map results = calculateIntermediateResults(requiredModule); for (Map.Entry resultEntry : results.entrySet()) { Object key = resultEntry.getKey(); IntermediateResult intermediateResult = resultEntry.getValue(); IntermediateResult existingResult = mergedResults.get(key); mergedResults.put(key, existingResult == null ? intermediateResult : existingResult.mergeSibling(intermediateResult) ); } } return mergedResults; } private void mergeWithResultsOf(@Nonnull Module module, @Nonnull Map combinedResults) { Map intermediateResultsOfModule = intermediateResults.get(module); if (intermediateResultsOfModule == null) { return; } for (Map.Entry resultEntry : intermediateResultsOfModule.entrySet()) { Object key = resultEntry.getKey(); IntermediateResult intermediateResult = resultEntry.getValue(); IntermediateResult parentResult = combinedResults.get(key); combinedResults.put(key, parentResult == null ? intermediateResult : intermediateResult.mergeParent(parentResult) ); } } /** * An IntermediateResultSet is an implementation of {@link de.is24.deadcode4j.IntermediateResult} using * a Set to store the results. Concerning merging with siblings & parents, it simply adds both sets. * * @since 2.0.0 */ public static class IntermediateResultSet implements IntermediateResult { @Nonnull private final Set results; /** * Creates an IntermediateResultSet to store the given Set. * * @since 2.0.0 */ public IntermediateResultSet(@Nonnull Collection results) { this.results = Collections.unmodifiableSet(newHashSet(results)); } @Override public String toString() { return getClass().getSimpleName() + ": " + results; } @Nonnull @Override public IntermediateResult mergeSibling(@Nonnull IntermediateResult sibling) { return merge(sibling); } @Nonnull @Override public IntermediateResult mergeParent(@Nonnull IntermediateResult parent) { return merge(parent); } /** * Returns the stored read-only Set. * * @since 2.0.0 */ @Nonnull public Set getResults() { return this.results; } @Nonnull private IntermediateResult merge(@Nonnull IntermediateResult result) { Set mergedResults = newHashSet(this.results); mergedResults.addAll(getResults(result)); return new IntermediateResultSet(mergedResults); } @Nonnull @SuppressWarnings("unchecked") private Set getResults(@Nonnull IntermediateResult result) { return IntermediateResultSet.class.cast(result).getResults(); } } /** * An IntermediateResultMap is an implementation of {@link de.is24.deadcode4j.IntermediateResult} using * a Map to store the results. Concerning merging with siblings & parents, it *
    *
  • adds entries of siblings & parents to the results if they don't collide with those defined by itself
  • *
  • if an entry of sibling or parent collides with one defined by itself *
      *
    • and the values are Collections, they are added to one another
    • *
    • otherwise, the own value is kept and the other is discarded
    • *
    *
  • *
* * @since 2.0.0 */ public static class IntermediateResultMap implements IntermediateResult { @Nonnull private final Logger logger = LoggerFactory.getLogger(getClass()); @Nonnull private final Map results; /** * Creates an IntermediateResultMap to store the given Map. * * @since 2.0.0 */ public IntermediateResultMap(@Nonnull Map results) { this.results = Collections.unmodifiableMap(newHashMap(results)); } @Nonnull @Override public String toString() { return getClass().getSimpleName() + ": " + this.results; } @Nonnull @Override public IntermediateResult mergeSibling(@Nonnull IntermediateResult sibling) { return merge(sibling); } @Nonnull @Override public IntermediateResult mergeParent(@Nonnull IntermediateResult parent) { return merge(parent); } /** * Returns the stored read-only Map. * * @since 2.0.0 */ @Nonnull public Map getResults() { return this.results; } @Nonnull @SuppressWarnings("unchecked") private IntermediateResult merge(@Nonnull IntermediateResult result) { Map mergedResults = newHashMap(getResults()); for (Map.Entry resultEntry : getResults(result).entrySet()) { K key = resultEntry.getKey(); V value = resultEntry.getValue(); V existingResult = mergedResults.get(key); if (existingResult == null) { mergedResults.put(key, value); } else if (Collection.class.isInstance(existingResult)) { Collection.class.cast(existingResult).addAll(Collection.class.cast(value)); } else if (!existingResult.equals(value)) { logger.debug("Intermediate result [{}] refers to [{}] and [{}] defined by different modules, keeping the former.", key, existingResult, value); } } return new IntermediateResultMap(mergedResults); } @Nonnull @SuppressWarnings("unchecked") private Map getResults(IntermediateResult result) { return IntermediateResultMap.class.cast(result).getResults(); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy