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

com.vladsch.flexmark.util.dependency.DependencyHandler Maven / Gradle / Ivy

There is a newer version: 4.15.102
Show newest version
package com.vladsch.flexmark.util.dependency;

import com.vladsch.flexmark.util.collection.iteration.ReversibleIndexedIterator;
import com.vladsch.flexmark.util.misc.Ref;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/**
 * @deprecated use DependencyResolver instead
 */
@SuppressWarnings("rawtypes")
@Deprecated
public abstract class DependencyHandler> {
    protected abstract @NotNull S createStage(List dependents);
    protected abstract @NotNull Class getDependentClass(D dependent);
    protected abstract @NotNull R createResolvedDependencies(List stages);

    public R resolveDependencies(List dependentsList) {
        if (dependentsList.size() == 0) {
            //noinspection unchecked
            return createResolvedDependencies((List) Collections.EMPTY_LIST);
        } else if (dependentsList.size() == 1) {
            D dependent = dependentsList.get(0);
            List dependents = Collections.singletonList(dependent);
            return createResolvedDependencies(Collections.singletonList(createStage(dependents)));
        } else {
            // resolve dependencies and processing lists
            int dependentCount = dependentsList.size();
            DependentItemMap dependentItemMap = new DependentItemMap<>(dependentCount);

            for (D dependent : dependentsList) {
                Class dependentClass = getDependentClass(dependent);
                if (dependentItemMap.containsKey(dependentClass)) {
                    throw new IllegalStateException("Dependent class " + dependentClass + " is duplicated. Only one instance can be present in the list");
                }
                DependentItem item = new DependentItem(dependentItemMap.size(), dependent, getDependentClass(dependent), dependent.affectsGlobalScope());
                dependentItemMap.put(dependentClass, item);
            }

            for (Map.Entry, DependentItem> entry : dependentItemMap) {
                DependentItem item = entry.getValue();
                Set> afterDependencies = item.dependent.getAfterDependents();

                if (afterDependencies != null && afterDependencies.size() > 0) {
                    for (Class dependentClass : afterDependencies) {
                        DependentItem dependentItem = dependentItemMap.get(dependentClass);
                        if (dependentItem != null) {
                            item.addDependency(dependentItem);
                            dependentItem.addDependent(item);
                        }
                    }
                }

                Set> beforeDependents = item.dependent.getBeforeDependents();
                if (beforeDependents != null && beforeDependents.size() > 0) {
                    for (Class dependentClass : beforeDependents) {
                        DependentItem dependentItem = dependentItemMap.get(dependentClass);
                        if (dependentItem != null) {
                            dependentItem.addDependency(item);
                            item.addDependent(dependentItem);
                        }
                    }
                }
            }

            dependentItemMap = prioritize(dependentItemMap);
            dependentCount = dependentItemMap.size();

            BitSet newReady = new BitSet(dependentCount);
            Ref newReadyRef = new Ref<>(newReady);
            ReversibleIndexedIterator> iterator = dependentItemMap.valueIterator();
            while (iterator.hasNext()) {
                DependentItem item = iterator.next();
                if (!item.hasDependencies()) {
                    newReadyRef.value.set(item.index);
                }
            }

            BitSet dependents = new BitSet(dependentCount);
            dependents.set(0, dependentItemMap.size());

            ArrayList dependencyStages = new ArrayList<>();

            while (newReady.nextSetBit(0) != -1) {
                // process these independents in unspecified order since they do not have dependencies
                ArrayList stageDependents = new ArrayList<>();
                BitSet nextDependents = new BitSet();

                // collect block processors ready for processing, any non-globals go into independents
                while (true) {
                    int i = newReady.nextSetBit(0);
                    if (i < 0) break;

                    newReady.clear(i);
                    DependentItem item = dependentItemMap.getValue(i);
                    assert item != null;

                    stageDependents.add(item.dependent);
                    dependents.clear(i);

                    // removeIndex it from dependent's dependencies
                    if (item.hasDependents()) {
                        while (true) {
                            int j = item.dependents.nextSetBit(0);
                            if (j < 0) break;

                            item.dependents.clear(j);
                            DependentItem dependentItem = dependentItemMap.getValue(j);
                            assert dependentItem != null;

                            if (!dependentItem.removeDependency(item)) {
                                if (item.isGlobalScope) {
                                    nextDependents.set(j);
                                } else {
                                    newReady.set(j);
                                }
                            }
                        }
                    } else if (item.isGlobalScope) {
                        // globals go in their own stage
                        nextDependents.or(newReady);
                        break;
                    }
                }

                // can process these in parallel since it will only contain non-globals or globals not dependent on other globals
                newReady = nextDependents;
                dependencyStages.add(createStage(stageDependents));
            }

            if (dependents.nextSetBit(0) != -1) {
                throw new IllegalStateException("have dependents with dependency cycles" + dependents);
            }

            return createResolvedDependencies(dependencyStages);
        }
    }

    protected DependentItemMap prioritize(DependentItemMap dependentMap) {
        return dependentMap;
    }
}