blob: c754dd4013f6c8a510d64c549a8950066aacf50c [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
*
* http://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.lucene.validation.ivyde;
import org.apache.ivy.core.module.id.ModuleId;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.report.ResolveReport;
import org.apache.ivy.core.resolve.IvyNode;
import org.apache.ivy.core.resolve.IvyNodeCallers;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* This class is copied from org/apache/ivyde/eclipse/resolvevisualizer/model/IvyNodeElementAdapter.java at
* https://svn.apache.org/repos/asf/ant/ivy/ivyde/trunk/org.apache.ivyde.eclipse.resolvevisualizer/src/
*
* Changes include: uncommenting generics and converting to diamond operators where appropriate;
* removing unnecessary casts; and removing javadoc tags with no description.
*/
public class IvyNodeElementAdapter {
/**
* Adapt all dependencies and evictions from the ResolveReport.
* @return the root node adapted from the ResolveReport
*/
public static IvyNodeElement adapt(ResolveReport report) {
Map<ModuleRevisionId,IvyNodeElement> resolvedNodes = new HashMap<>();
IvyNodeElement root = new IvyNodeElement();
root.setModuleRevisionId(report.getModuleDescriptor().getModuleRevisionId());
resolvedNodes.put(report.getModuleDescriptor().getModuleRevisionId(), root);
@SuppressWarnings("unchecked") List<IvyNode> dependencies = report.getDependencies();
// First pass - build the map of resolved nodes by revision id
for (Iterator<IvyNode> iter = dependencies.iterator(); iter.hasNext();) {
IvyNode node = iter.next();
if (node.getAllEvictingNodes() != null) {
// Nodes that are evicted as a result of conf inheritance still appear
// as dependencies, but with eviction data. They also appear as evictions.
// We map them as evictions rather than dependencies.
continue;
}
IvyNodeElement nodeElement = new IvyNodeElement();
nodeElement.setModuleRevisionId(node.getResolvedId());
resolvedNodes.put(node.getResolvedId(), nodeElement);
}
// Second pass - establish relationships between the resolved nodes
for (Iterator<IvyNode> iter = dependencies.iterator(); iter.hasNext();) {
IvyNode node = iter.next();
if (node.getAllEvictingNodes() != null) {
continue; // see note above
}
IvyNodeElement nodeElement = resolvedNodes.get(node.getResolvedId());
IvyNodeCallers.Caller[] callers = node.getAllRealCallers();
for (int i = 0; i < callers.length; i++) {
IvyNodeElement caller = resolvedNodes.get(callers[i].getModuleRevisionId());
if (caller != null) {
nodeElement.addCaller(caller);
nodeElement.setCallerConfigurations(caller, callers[i].getCallerConfigurations());
}
}
}
IvyNode[] evictions = report.getEvictedNodes();
for (int i = 0; i < evictions.length; i++) {
IvyNode eviction = evictions[i];
IvyNodeElement evictionElement = new IvyNodeElement();
evictionElement.setModuleRevisionId(eviction.getResolvedId());
evictionElement.setEvicted(true);
IvyNodeCallers.Caller[] callers = eviction.getAllCallers();
for (int j = 0; j < callers.length; j++) {
IvyNodeElement caller = resolvedNodes.get(callers[j].getModuleRevisionId());
if (caller != null) {
evictionElement.addCaller(caller);
evictionElement.setCallerConfigurations(caller, callers[j].getCallerConfigurations());
}
}
}
// Recursively set depth starting at root
root.setDepth(0);
findConflictsBeneathNode(root);
return root;
}
/**
* Derives configuration conflicts that exist between node and all of its descendant dependencies.
*/
private static void findConflictsBeneathNode(IvyNodeElement node) {
// Derive conflicts
Map<ModuleId,Collection<IvyNodeElement>> moduleRevisionMap = new HashMap<>();
IvyNodeElement[] deepDependencies = node.getDeepDependencies();
for (int i = 0; i < deepDependencies.length; i++) {
if (deepDependencies[i].isEvicted())
continue;
ModuleId moduleId = deepDependencies[i].getModuleRevisionId().getModuleId();
if (moduleRevisionMap.containsKey(moduleId)) {
Collection<IvyNodeElement> conflicts = moduleRevisionMap.get(moduleId);
conflicts.add(deepDependencies[i]);
for (Iterator<IvyNodeElement> iter = conflicts.iterator(); iter.hasNext();) {
IvyNodeElement conflict = iter.next();
conflict.setConflicts(conflicts);
}
} else {
List<IvyNodeElement> immutableMatchingSet = Arrays.asList(deepDependencies[i]);
moduleRevisionMap.put(moduleId, new HashSet<>(immutableMatchingSet));
}
}
}
}