blob: 712a203cfb18b31fda0037cecc231c87d613030a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* https://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 org.apache.ivy.core.sort;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.resolve.IvyNode;
import org.apache.ivy.plugins.circular.CircularDependencyException;
import org.apache.ivy.plugins.circular.CircularDependencyStrategy;
import org.apache.ivy.plugins.circular.IgnoreCircularDependencyStrategy;
import org.apache.ivy.plugins.version.VersionMatcher;
import org.apache.ivy.util.Checks;
public class SortEngine {
private SortEngineSettings settings;
public SortEngine(SortEngineSettings settings) {
if (settings == null) {
throw new NullPointerException("SortEngine.settings can not be null");
}
this.settings = settings;
}
/**
* Same as {@link #sortModuleDescriptors(Collection, SortOptions)} but for <code>IvyNode</code>
* s.
*
* @param nodes
* a Collection of nodes to sort
* @param options
* Options to use to sort the nodes.
* @return a List of sorted IvyNode
* @throws CircularDependencyException
* if a circular dependency exists and circular dependency strategy decide to throw
* an exception
*/
public List<IvyNode> sortNodes(Collection<IvyNode> nodes, SortOptions options) {
/*
* here we want to use the sort algorithm which work on module descriptors : so we first put
* dependencies on a map from descriptors to dependency, then we sort the keySet (i.e. a
* collection of descriptors), then we replace in the sorted list each descriptor by the
* corresponding dependency
*/
Map<ModuleDescriptor, List<IvyNode>> dependenciesMap = new LinkedHashMap<>();
List<IvyNode> nulls = new ArrayList<>();
for (IvyNode node : nodes) {
if (node.getDescriptor() == null) {
nulls.add(node);
} else {
List<IvyNode> n = dependenciesMap.get(node.getDescriptor());
if (n == null) {
n = new ArrayList<>();
dependenciesMap.put(node.getDescriptor(), n);
}
n.add(node);
}
}
List<ModuleDescriptor> list = sortModuleDescriptors(dependenciesMap.keySet(), options);
final double adjustFactor = 1.3;
List<IvyNode> ret = new ArrayList<>(
(int) (list.size() * adjustFactor + nulls.size()));
// attempt to adjust the size to avoid too much list resizing
for (ModuleDescriptor md : list) {
List<IvyNode> n = dependenciesMap.get(md);
ret.addAll(n);
}
ret.addAll(0, nulls);
return ret;
}
/**
* Sorts the given ModuleDescriptors from the less dependent to the more dependent. This sort
* ensures that a ModuleDescriptor is always found in the list before all ModuleDescriptors
* depending directly on it.
*
* @param moduleDescriptors
* a Collection of ModuleDescriptor to sort
* @param options
* Options to use to sort the descriptors.
* @return a List of sorted ModuleDescriptors
* @throws CircularDependencyException
* if a circular dependency exists and circular dependency strategy decide to throw
* an exception
*/
public List<ModuleDescriptor> sortModuleDescriptors(
Collection<ModuleDescriptor> moduleDescriptors, SortOptions options)
throws CircularDependencyException {
Checks.checkNotNull(options, "options");
ModuleDescriptorSorter sorter = new ModuleDescriptorSorter(moduleDescriptors,
getVersionMatcher(), options.getNonMatchingVersionReporter(),
options.isUseCircularDependencyStrategy() ? getCircularStrategy()
: IgnoreCircularDependencyStrategy.getInstance());
return sorter.sortModuleDescriptors();
}
protected CircularDependencyStrategy getCircularStrategy() {
return settings.getCircularDependencyStrategy();
}
protected VersionMatcher getVersionMatcher() {
return settings.getVersionMatcher();
}
}