/* * 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.ivyde.eclipse.resolvevisualizer.model; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import org.apache.ivy.core.module.id.ModuleRevisionId; /** * Assists in the further separation of concerns between the view and the Ivy resolve report. The view looks at the * IvyNode in a unique way that can lead to expensive operations if we do not achieve this separation. */ public class IvyNodeElement { private ModuleRevisionId moduleRevisionId; private boolean evicted = false; private int depth = Integer.MAX_VALUE / 10; private Collection/* <IvyNodeElement> */dependencies = new HashSet/* <IvyNodeElement> */(); private Collection/* <IvyNodeElement> */callers = new HashSet/* <IvyNodeElement> */(); private Collection/* <IvyNodeElement> */conflicts = new HashSet/* <IvyNodeElement> */(); /** * The caller configurations that caused this node to be reached in the resolution, grouped by caller. */ private Map/* <IvyNodeElement, String[]> */callerConfigurationMap = new HashMap/* <IvyNodeElement, String[]> */(); /** * We try to avoid building the list of this nodes deep dependencies by storing them in this cache by depth level. */ private IvyNodeElement[] deepDependencyCache; public boolean equals(Object obj) { if (obj instanceof IvyNodeElement) { IvyNodeElement elem = (IvyNodeElement) obj; if (elem.getOrganization().equals(getOrganization()) && elem.getName().equals(getName()) && elem.getRevision().equals(getRevision())) return true; } return false; } public IvyNodeElement[] getDependencies() { return (IvyNodeElement[]) dependencies.toArray(new IvyNodeElement[dependencies.size()]); } /** * Recursive dependency retrieval * * @return The array of nodes that represents a node's immediate and transitive dependencies down to an arbitrary * depth. */ public IvyNodeElement[] getDeepDependencies() { if (deepDependencyCache == null) { deepDependencyCache = (IvyNodeElement[]) getDeepDependencies(this).toArray(new IvyNodeElement[] {}); } return deepDependencyCache; } /** * Recursive dependency retrieval * * @param node * @return */ private Collection/* <IvyNodeElement> */getDeepDependencies(IvyNodeElement node) { Collection/* <IvyNodeElement> */deepDependencies = new HashSet/* <IvyNodeElement> */(); deepDependencies.add(node); IvyNodeElement[] directDependencies = node.getDependencies(); for (int i = 0; i < directDependencies.length; i++) { deepDependencies.addAll(getDeepDependencies(directDependencies[i])); } return deepDependencies; } /** * @return An array of configurations by which this module was resolved */ public String[] getCallerConfigurations(IvyNodeElement caller) { return (String[]) callerConfigurationMap.get(caller); } public void setCallerConfigurations(IvyNodeElement caller, String[] configurations) { callerConfigurationMap.put(caller, configurations); } public String getOrganization() { return moduleRevisionId.getOrganisation(); } public String getName() { return moduleRevisionId.getName(); } public String getRevision() { return moduleRevisionId.getRevision(); } public boolean isEvicted() { return evicted; } public void setEvicted(boolean evicted) { this.evicted = evicted; } public int getDepth() { return depth; } /** * Set this node's depth and recursively update the node's children to relative to the new value. * * @param depth */ public void setDepth(int depth) { this.depth = depth; for (Iterator iter = dependencies.iterator(); iter.hasNext();) { IvyNodeElement dependency = (IvyNodeElement) iter.next(); dependency.setDepth(depth + 1); } } public IvyNodeElement[] getConflicts() { return (IvyNodeElement[]) conflicts.toArray(new IvyNodeElement[conflicts.size()]); } public void setConflicts(Collection conflicts) { this.conflicts = conflicts; } public ModuleRevisionId getModuleRevisionId() { return moduleRevisionId; } public void setModuleRevisionId(ModuleRevisionId moduleRevisionId) { this.moduleRevisionId = moduleRevisionId; } public void addCaller(IvyNodeElement caller) { callers.add(caller); caller.dependencies.add(this); } public IvyNodeElement[] getCallers() { return (IvyNodeElement[]) callers.toArray(new IvyNodeElement[callers.size()]); } }