Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Vertex |
|
| 1.6363636363636365;1.636 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | ||
20 | package org.apache.myfaces.config.util; | |
21 | ||
22 | import java.util.ArrayList; | |
23 | import java.util.List; | |
24 | ||
25 | /** | |
26 | * Vertex is used to track dependencies and each node in a graph. Typical | |
27 | * uses would be to ensure components are started up and torn down in the | |
28 | * proper order, or bundles were loaded and unloaded in the proper order, etc. | |
29 | * | |
30 | * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a> | |
31 | * @version CVS $ Revision: 1.1 $ | |
32 | */ | |
33 | 0 | public final class Vertex<T> implements Comparable<Vertex<T>> |
34 | { | |
35 | private final String m_name; | |
36 | private final T m_node; | |
37 | private int m_order; | |
38 | ||
39 | /** Flag used to keep track of whether or not a given vertex has been | |
40 | * seen by the resolveOrder methods. */ | |
41 | private boolean m_seen; | |
42 | ||
43 | /** List of all direct dependent Vertices. */ | |
44 | private final List< Vertex<T> > m_dependencies; | |
45 | ||
46 | /** | |
47 | * A vertex wraps a node, which can be anything. | |
48 | * | |
49 | * @param node The wrapped node. | |
50 | */ | |
51 | public Vertex(final T node) | |
52 | { | |
53 | 0 | this(node.toString(), node); |
54 | 0 | } |
55 | ||
56 | /** | |
57 | * A vertex wraps a node, which can be anything. | |
58 | * | |
59 | * @param name A name for the node which will be used to produce useful errors. | |
60 | * @param node The wrapped node. | |
61 | */ | |
62 | public Vertex(final String name, final T node) | |
63 | 0 | { |
64 | 0 | m_name = name; |
65 | 0 | m_node = node; |
66 | 0 | m_dependencies = new ArrayList< Vertex<T> >(); |
67 | 0 | reset(); |
68 | 0 | } |
69 | ||
70 | /** | |
71 | * Reset the Vertex so that all the flags and runtime states are set back | |
72 | * to the original values. | |
73 | */ | |
74 | public void reset() | |
75 | { | |
76 | 0 | m_order = 0; |
77 | 0 | m_seen = false; |
78 | 0 | } |
79 | ||
80 | /** | |
81 | * Returns the name of the Vertex. | |
82 | * | |
83 | * @return The name of the Vertex. | |
84 | */ | |
85 | public String getName() | |
86 | { | |
87 | 0 | return m_name; |
88 | } | |
89 | ||
90 | /** | |
91 | * Get the wrapped node that this Vertex represents. | |
92 | * | |
93 | * @return the node | |
94 | */ | |
95 | public T getNode() | |
96 | { | |
97 | 0 | return m_node; |
98 | } | |
99 | ||
100 | /** | |
101 | * Add a dependecy to this Vertex. The Vertex that this one depends on will | |
102 | * be marked as referenced and then added to the list of dependencies. The | |
103 | * list is checked before the dependency is added. | |
104 | * | |
105 | * @param v The vertex we depend on. | |
106 | */ | |
107 | public void addDependency(Vertex<T> v) | |
108 | { | |
109 | 0 | if (!m_dependencies.contains(v)) |
110 | { | |
111 | 0 | m_dependencies.add(v); |
112 | } | |
113 | 0 | } |
114 | ||
115 | /** | |
116 | * Recurse through the tree from this vertex assigning an order to each | |
117 | * and at the same time checking for any cyclic dependencies. | |
118 | * | |
119 | * @throws CyclicDependencyException If a cyclic dependency is discovered. | |
120 | */ | |
121 | public void resolveOrder() throws CyclicDependencyException | |
122 | { | |
123 | 0 | resolveOrder(getName()); |
124 | 0 | } |
125 | ||
126 | /** | |
127 | * Recursively searches for cycles by travelling down the dependency lists | |
128 | * of this vertex, looking for the start vertex. | |
129 | * | |
130 | * @param path The path to the Vertex. It is worth the load as it makes a | |
131 | * descriptive error message possible. | |
132 | * | |
133 | * @return The highest order of any of the dependent vertices. | |
134 | * | |
135 | * @throws CyclicDependencyException If a cyclic dependency is discovered. | |
136 | */ | |
137 | private int resolveOrder(String path) throws CyclicDependencyException | |
138 | { | |
139 | 0 | m_seen = true; |
140 | try | |
141 | { | |
142 | 0 | int highOrder = -1; |
143 | 0 | for (Vertex<T> dv : m_dependencies) |
144 | { | |
145 | 0 | if (dv.m_seen) |
146 | { | |
147 | 0 | throw new CyclicDependencyException(path + " -> " |
148 | + dv.getName()); | |
149 | } | |
150 | else | |
151 | { | |
152 | 0 | highOrder = Math.max(highOrder, dv.resolveOrder(path |
153 | + " -> " + dv.getName())); | |
154 | } | |
155 | 0 | } |
156 | ||
157 | // Set this order so it is one higher than the highest dependency. | |
158 | 0 | m_order = highOrder + 1; |
159 | 0 | return m_order; |
160 | } | |
161 | finally | |
162 | { | |
163 | 0 | m_seen = false; |
164 | } | |
165 | } | |
166 | ||
167 | /** | |
168 | * Get the list of dependencies. | |
169 | * | |
170 | * @return The list of dependencies. | |
171 | */ | |
172 | public List< Vertex<T> > getDependencies() | |
173 | { | |
174 | 0 | return m_dependencies; |
175 | } | |
176 | ||
177 | /** | |
178 | * Used in the sort algorithm to sort all the Vertices so that they respect | |
179 | * the ordinal they were given during the topological sort. | |
180 | * | |
181 | * @param o The other Vertex to compare with | |
182 | * @return -1 if this < o, 0 if this == o, or 1 if this > o | |
183 | */ | |
184 | public int compareTo(final Vertex<T> o) | |
185 | { | |
186 | int orderInd; | |
187 | ||
188 | 0 | if (m_order < o.m_order) |
189 | { | |
190 | 0 | orderInd = -1; |
191 | } | |
192 | 0 | else if (m_order > o.m_order) |
193 | { | |
194 | 0 | orderInd = 1; |
195 | } | |
196 | else | |
197 | { | |
198 | 0 | orderInd = 0; |
199 | } | |
200 | ||
201 | 0 | return orderInd; |
202 | } | |
203 | ||
204 | /** | |
205 | * Get the ordinal for this vertex. | |
206 | * | |
207 | * @return the order. | |
208 | */ | |
209 | public int getOrder() | |
210 | { | |
211 | 0 | return m_order; |
212 | } | |
213 | } |