aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/utils/jdvue/src/main/java/org/onlab/jdvue/DependencyCycle.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/utils/jdvue/src/main/java/org/onlab/jdvue/DependencyCycle.java')
-rw-r--r--framework/src/onos/utils/jdvue/src/main/java/org/onlab/jdvue/DependencyCycle.java118
1 files changed, 118 insertions, 0 deletions
diff --git a/framework/src/onos/utils/jdvue/src/main/java/org/onlab/jdvue/DependencyCycle.java b/framework/src/onos/utils/jdvue/src/main/java/org/onlab/jdvue/DependencyCycle.java
new file mode 100644
index 00000000..65e3cfbc
--- /dev/null
+++ b/framework/src/onos/utils/jdvue/src/main/java/org/onlab/jdvue/DependencyCycle.java
@@ -0,0 +1,118 @@
+package org.onlab.jdvue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Simple representation of a Java package dependency cycle.
+ */
+public class DependencyCycle {
+
+ private final List<JavaPackage> cycle;
+
+ /**
+ * Creates a normalized dependency cycle represented by the specified list
+ * of Java packages, which are expected to be given in order of dependency.
+ * List is assumed to be non-empty.
+ *
+ * @param cycle list of Java packages in the dependency cycle
+ * @param cause Java package that caused the cycle
+ */
+ DependencyCycle(List<JavaPackage> cycle, JavaPackage cause) {
+ this.cycle = normalize(cycle, cause);
+ }
+
+ /**
+ * Produces a normalized dependency cycle list. Normalization is performed
+ * by rotating the list so that the package with the least lexicographic
+ * name is at the start of the list.
+ *
+ * @param cycle list of Java packages in the dependency cycle
+ * @param cause Java package that caused the cycle
+ * @return normalized cycle
+ */
+ private List<JavaPackage> normalize(List<JavaPackage> cycle, JavaPackage cause) {
+ int start = cycle.indexOf(cause);
+ List<JavaPackage> clone = new ArrayList<>(cycle.subList(start, cycle.size()));
+ int leastIndex = findIndexOfLeastName(clone);
+ Collections.rotate(clone, -leastIndex);
+ return Collections.unmodifiableList(clone);
+ }
+
+ /**
+ * Returns the index of the Java package with the least name.
+ *
+ * @param cycle list of Java packages in the dependency cycle
+ * @return index of the least Java package name
+ */
+ private int findIndexOfLeastName(List<JavaPackage> cycle) {
+ int leastIndex = 0;
+ String leastName = cycle.get(leastIndex).name();
+ for (int i = 1, n = cycle.size(); i < n; i++) {
+ JavaPackage javaPackage = cycle.get(i);
+ if (leastName.compareTo(javaPackage.name()) > 0) {
+ leastIndex = i;
+ leastName = javaPackage.name();
+ }
+ }
+ return leastIndex;
+ }
+
+ /**
+ * Returns the normalized Java package dependency cycle
+ *
+ * @return list of packages in the dependency cycle
+ */
+ public List<JavaPackage> getCycle() {
+ return cycle;
+ }
+
+ /**
+ * Returns the dependency cycle in form of individual dependencies.
+ *
+ * @return list of dependencies forming the cycle
+ */
+ public List<Dependency> getCycleSegments() {
+ List<Dependency> dependencies = new ArrayList<>();
+ for (int i = 0, n = cycle.size(); i < n; i++) {
+ dependencies.add(new Dependency(cycle.get(i), cycle.get(i < n - 1 ? i + 1 : 0)));
+ }
+ return dependencies;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof DependencyCycle) {
+ DependencyCycle that = (DependencyCycle) o;
+ return Objects.equals(cycle, that.cycle);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(cycle);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("cycle", cycle).toString();
+ }
+
+ public String toShortString() {
+ StringBuilder sb = new StringBuilder("[");
+ for (JavaPackage javaPackage : cycle) {
+ sb.append(javaPackage.name()).append(", ");
+ }
+ if (sb.length() > 1) {
+ sb.delete(sb.length() - 2, sb.length());
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+}