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

com.github.dynamicextensionsalfresco.osgi.DependencySorter Maven / Gradle / Ivy

Go to download

Adds an OSGi container to alfresco repository supporting dynamic code reloading, classpath isolation and a bunch of other useful features

There is a newer version: 3.1.0
Show newest version
package com.github.dynamicextensionsalfresco.osgi;

import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by jasper on 17/07/17.
 */
public class DependencySorter {
    public static Logger logger = LoggerFactory.getLogger(com.github.dynamicextensionsalfresco.osgi.DependencySorter.class);

    public static  Collection sort(Collection input, DependencyMetadataProvider metadataProvider) {
        ArrayList result = new ArrayList();
        Map exports = collectExports(input, metadataProvider);
        ArrayList visitedItems = new ArrayList();

        for (T item : input) {
            DependencySorter.visit(item, exports, result, visitedItems, metadataProvider);
        }
        LogDebug(input, result);
        return result;
    }

    private static  void LogDebug(Collection input, ArrayList result) {
        if (logger.isDebugEnabled()) {
            Iterator it = (input == null) ? null : input.iterator();
            if (it == null || !it.hasNext()) {
                logger.debug("sorting empty or 'null' collection");
                return;
            }
            logger.debug("sorting {}:", it.next());
            logger.debug("  input");
            for (T item : input) {
                logger.debug("  - {}", item);
            }
            logger.debug("  output");
            for (T item : result) {
                logger.debug("  - {}", item);
            }
        }
    }


    private static  void visit(
            T item,
            Map exports,
            ArrayList output,
            ArrayList visited,
            DependencyMetadataProvider metadataProvider) {
        visited.add(item);
        Collection imports = metadataProvider.imports(item);
        for (Object importz : imports) {
            T exportingItem = exports.get(importz);
            if (exportingItem != null && exportingItem != item && !output.contains(exportingItem)) {
                logger.debug("visit {} from {} for import {}", exportingItem, item, importz);
                if (!visited.contains(exportingItem)) {
                    visit(exportingItem, exports, output, visited, metadataProvider);
                } else if (!metadataProvider.allowCircularReferences()) {
                    String message = String.format("Circular dependency detected between %s and %s for import %s", item, exportingItem, importz);
                    throw new IllegalArgumentException(message);

                }
            }
        }

        if (!output.contains(item)) {
            output.add(item);
        }
    }

    private static  Map collectExports(Collection items, DependencyMetadataProvider metadataProvider) {
        HashMap result = new HashMap();

        for (T item : items) {
            Collection exports = metadataProvider.exports(item);
            for (Object export : exports) {
                result.put(export, item);
            }
        }
        return result;
    }

}