blob: f869b7c310bf00dc7aacf8739c2ebe49ad6a1c37 [file] [log] [blame]
Thomas Vachuska58de4162015-09-10 16:15:33 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska58de4162015-09-10 16:15:33 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Thomas Vachuska6b331262015-04-27 11:09:07 -070016package org.onlab.jdvue;
17
18import java.util.ArrayList;
19import java.util.Collections;
20import java.util.List;
21import java.util.Objects;
22
Sho SHIMIZU43748e82015-08-25 10:05:08 -070023import static com.google.common.base.MoreObjects.toStringHelper;
Thomas Vachuska6b331262015-04-27 11:09:07 -070024
25/**
26 * Simple representation of a Java package dependency cycle.
27 */
28public class DependencyCycle {
29
30 private final List<JavaPackage> cycle;
31
32 /**
33 * Creates a normalized dependency cycle represented by the specified list
34 * of Java packages, which are expected to be given in order of dependency.
35 * List is assumed to be non-empty.
36 *
37 * @param cycle list of Java packages in the dependency cycle
38 * @param cause Java package that caused the cycle
39 */
40 DependencyCycle(List<JavaPackage> cycle, JavaPackage cause) {
41 this.cycle = normalize(cycle, cause);
42 }
43
44 /**
45 * Produces a normalized dependency cycle list. Normalization is performed
46 * by rotating the list so that the package with the least lexicographic
47 * name is at the start of the list.
48 *
49 * @param cycle list of Java packages in the dependency cycle
50 * @param cause Java package that caused the cycle
51 * @return normalized cycle
52 */
53 private List<JavaPackage> normalize(List<JavaPackage> cycle, JavaPackage cause) {
54 int start = cycle.indexOf(cause);
55 List<JavaPackage> clone = new ArrayList<>(cycle.subList(start, cycle.size()));
56 int leastIndex = findIndexOfLeastName(clone);
57 Collections.rotate(clone, -leastIndex);
58 return Collections.unmodifiableList(clone);
59 }
60
61 /**
62 * Returns the index of the Java package with the least name.
63 *
64 * @param cycle list of Java packages in the dependency cycle
65 * @return index of the least Java package name
66 */
67 private int findIndexOfLeastName(List<JavaPackage> cycle) {
68 int leastIndex = 0;
69 String leastName = cycle.get(leastIndex).name();
70 for (int i = 1, n = cycle.size(); i < n; i++) {
71 JavaPackage javaPackage = cycle.get(i);
72 if (leastName.compareTo(javaPackage.name()) > 0) {
73 leastIndex = i;
74 leastName = javaPackage.name();
75 }
76 }
77 return leastIndex;
78 }
79
80 /**
81 * Returns the normalized Java package dependency cycle
82 *
83 * @return list of packages in the dependency cycle
84 */
85 public List<JavaPackage> getCycle() {
86 return cycle;
87 }
88
89 /**
90 * Returns the dependency cycle in form of individual dependencies.
91 *
92 * @return list of dependencies forming the cycle
93 */
94 public List<Dependency> getCycleSegments() {
95 List<Dependency> dependencies = new ArrayList<>();
96 for (int i = 0, n = cycle.size(); i < n; i++) {
97 dependencies.add(new Dependency(cycle.get(i), cycle.get(i < n - 1 ? i + 1 : 0)));
98 }
99 return dependencies;
100 }
101
102 @Override
103 public boolean equals(Object o) {
104 if (o instanceof DependencyCycle) {
105 DependencyCycle that = (DependencyCycle) o;
106 return Objects.equals(cycle, that.cycle);
107 }
108 return false;
109 }
110
111 @Override
112 public int hashCode() {
HIGUCHI Yutaca9cc8e2015-10-29 23:26:51 -0700113 return cycle.hashCode();
Thomas Vachuska6b331262015-04-27 11:09:07 -0700114 }
115
116 @Override
117 public String toString() {
118 return toStringHelper(this).add("cycle", cycle).toString();
119 }
120
121 public String toShortString() {
122 StringBuilder sb = new StringBuilder("[");
123 for (JavaPackage javaPackage : cycle) {
124 sb.append(javaPackage.name()).append(", ");
125 }
126 if (sb.length() > 1) {
127 sb.delete(sb.length() - 2, sb.length());
128 }
129 sb.append("]");
130 return sb.toString();
131 }
132
133}