| /* |
| * 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)); |
| } |
| } |
| } |
| } |