001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.eclipse.aether.util.graph.manager;
020
021import java.util.ArrayList;
022import java.util.Collection;
023
024import org.eclipse.aether.collection.DependencyManager;
025import org.eclipse.aether.graph.Exclusion;
026import org.eclipse.aether.scope.ScopeManager;
027import org.eclipse.aether.scope.SystemDependencyScope;
028
029/**
030 * A dependency manager that applies management at all levels with aggressive transitive behavior.
031 *
032 * <h2>Overview</h2>
033 * <p>
034 * This manager provides the most aggressive dependency management approach, applying management
035 * rules at every level of the dependency graph. Unlike other managers, it starts applying
036 * management from the very first level (depth=0) and continues indefinitely.
037 * </p>
038 *
039 * <h2>Key Characteristics</h2>
040 * <ul>
041 * <li><strong>Aggressive Application:</strong> {@code deriveUntil=Integer.MAX_VALUE}, {@code applyFrom=0}</li>
042 * <li><strong>First Level Management:</strong> Applies management even at the root level</li>
043 * <li><strong>ModelBuilder Interference:</strong> Ignores and overrides ModelBuilder's work</li>
044 * <li><strong>Complete Transitivity:</strong> Manages dependencies at all depths</li>
045 * </ul>
046 *
047 * <h2>When NOT to Use</h2>
048 * <p>
049 * <strong>⚠️ Warning:</strong> This manager is <em>not recommended for Maven or Maven-like use cases</em>
050 * because it interferes with ModelBuilder, potentially rewriting models that ModelBuilder has
051 * already processed correctly. This can lead to unexpected dependency resolution behavior.
052 * </p>
053 *
054 * <h2>When to Use</h2>
055 * <p>
056 * Consider this manager only for non-Maven scenarios where you need complete control over
057 * dependency management at all levels and are not using Maven's ModelBuilder.
058 * </p>
059 *
060 * <h2>Comparison with Other Managers</h2>
061 * <ul>
062 * <li>{@link ClassicDependencyManager}: Maven 2.x compatibility, limited scope</li>
063 * <li>{@link TransitiveDependencyManager}: Proper transitive management, ModelBuilder-friendly</li>
064 * <li><strong>This manager:</strong> Aggressive, all-level management (use with caution)</li>
065 * </ul>
066 *
067 * @author Christian Schulte
068 * @since 1.4.0
069 * @see ClassicDependencyManager
070 * @see TransitiveDependencyManager
071 */
072public final class DefaultDependencyManager extends AbstractDependencyManager {
073    /**
074     * Creates a new dependency manager without any management information.
075     */
076    public DefaultDependencyManager() {
077        this(null);
078    }
079
080    /**
081     * Creates a new dependency manager with aggressive management behavior.
082     * <p>
083     * <strong>⚠️ Warning:</strong> This manager is not recommended for Maven use cases.
084     * It initializes with the most aggressive settings:
085     * <ul>
086     * <li>deriveUntil = Integer.MAX_VALUE (always collect management rules)</li>
087     * <li>applyFrom = 0 (apply management from the very first level)</li>
088     * <li>No respect for ModelBuilder's work</li>
089     * </ul>
090     *
091     * @param scopeManager application-specific scope manager for handling system dependencies,
092     *                     may be null to use legacy system dependency scope handling
093     */
094    public DefaultDependencyManager(ScopeManager scopeManager) {
095        super(Integer.MAX_VALUE, 0, scopeManager);
096    }
097
098    @SuppressWarnings("checkstyle:ParameterNumber")
099    private DefaultDependencyManager(
100            ArrayList<AbstractDependencyManager> path,
101            int depth,
102            int deriveUntil,
103            int applyFrom,
104            MMap<Key, String> managedVersions,
105            MMap<Key, String> managedScopes,
106            MMap<Key, Boolean> managedOptionals,
107            MMap<Key, String> managedLocalPaths,
108            MMap<Key, Holder<Collection<Exclusion>>> managedExclusions,
109            SystemDependencyScope systemDependencyScope) {
110        super(
111                path,
112                depth,
113                deriveUntil,
114                applyFrom,
115                managedVersions,
116                managedScopes,
117                managedOptionals,
118                managedLocalPaths,
119                managedExclusions,
120                systemDependencyScope);
121    }
122
123    @Override
124    protected DependencyManager newInstance(
125            MMap<Key, String> managedVersions,
126            MMap<Key, String> managedScopes,
127            MMap<Key, Boolean> managedOptionals,
128            MMap<Key, String> managedLocalPaths,
129            MMap<Key, Holder<Collection<Exclusion>>> managedExclusions) {
130        ArrayList<AbstractDependencyManager> path = new ArrayList<>(this.path);
131        path.add(this);
132        return new DefaultDependencyManager(
133                path,
134                depth + 1,
135                deriveUntil,
136                applyFrom,
137                managedVersions,
138                managedScopes,
139                managedOptionals,
140                managedLocalPaths,
141                managedExclusions,
142                systemDependencyScope);
143    }
144}