Package: ThreadSafeArrayListTree

ThreadSafeArrayListTree

nameinstructionbranchcomplexitylinemethod
ThreadSafeArrayListTree(Object)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
ThreadSafeArrayListTree(Object, Object)
M: 0 C: 14
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
ThreadSafeArrayListTree(Tree, Tree, Object)
M: 0 C: 41
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
addChild(Tree)
M: 0 C: 22
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
equals(Object)
M: 39 C: 103
73%
M: 4 C: 18
82%
M: 3 C: 9
75%
M: 6 C: 24
80%
M: 0 C: 1
100%
getChild(int)
M: 5 C: 13
72%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 2 C: 2
50%
M: 0 C: 1
100%
getChildren()
M: 0 C: 15
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
getParent()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getValue()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
hashCode()
M: 2 C: 30
94%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 5
100%
M: 0 C: 1
100%
numChildren()
M: 0 C: 11
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
removeChild(Tree)
M: 0 C: 20
100%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 5
100%
M: 0 C: 1
100%
setParent(Tree, Tree)
M: 0 C: 18
100%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 5
100%
M: 0 C: 1
100%
size()
M: 0 C: 29
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
static {...}
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
toString()
M: 0 C: 58
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 11
100%
M: 0 C: 1
100%
visit(Tree.ExceptionThrowingTreeVisitor)
M: 0 C: 22
100%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 6
100%
M: 0 C: 1
100%
visit(Tree.TreeVisitor)
M: 0 C: 22
100%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 6
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2008, 2010 VMware Inc.
3: * All rights reserved. This program and the accompanying materials
4: * are made available under the terms of the Eclipse Public License v1.0
5: * which accompanies this distribution, and is available at
6: * http://www.eclipse.org/legal/epl-v10.html
7: *
8: * Contributors:
9: * VMware Inc. - initial contribution
10: *******************************************************************************/
11:
12: package org.eclipse.virgo.util.common;
13:
14: import java.util.ArrayList;
15: import java.util.List;
16:
17: /**
18: * {@link ThreadSafeArrayListTree} is a value with an ordered collection of subtrees of the same type as the main tree.
19: * <p />
20: *
21: * <strong>Concurrent Semantics</strong><br />
22: *
23: * This class is thread safe.
24: *
25: * @param <V> type of values in tree
26: */
27:
28: public final class ThreadSafeArrayListTree<V> implements Tree<V> {
29:
30: private volatile V value;
31:
32: private final Object monitor;
33:
34: private static final Object tieMonitor = new Object();
35:
36: private final List<ThreadSafeArrayListTree<V>> children = new ArrayList<ThreadSafeArrayListTree<V>>();
37:
38: private Tree<V> parent;
39:
40: /**
41: * Construct a tree with the given value, which may be <code>null</code>.
42: *
43: * @param value the value of the tree, which may be <code>null</code>
44: */
45: public ThreadSafeArrayListTree(V value) {
46: this(value, new Object());
47: }
48:
49: protected ThreadSafeArrayListTree(V value, Object monitor) {
50: this.value = value;
51: this.monitor = monitor;
52: }
53:
54: /**
55: * Construct a tree by deeply copying the given tree, using the given parent, and inheriting the given monitor.
56: *
57: * @param tree the tree to copy
58: * @param parent the parent of the new tree or <code>null</code>
59: * @param monitor the monitor to inherit
60: */
61: protected ThreadSafeArrayListTree(Tree<V> tree, Tree<V> parent, Object monitor) {
62: this.value = tree.getValue();
63: this.monitor = monitor;
64: this.parent = parent;
65:• for (Tree<V> child : tree.getChildren()) {
66: this.children.add(new ThreadSafeArrayListTree<V>(child, this, this.monitor));
67: }
68: }
69:
70: /**
71: * Returns the tree's value. If there is no value associated with this tree, returns <code>null</code>.
72: *
73: * @return the value, which may be <code>null</code>
74: */
75: public final V getValue() {
76: return this.value;
77: }
78:
79: /**
80: * Returns a list of this tree's children (not copies of the children). If the tree has no children, returns an
81: * empty list. Never returns <code>null</code> .
82: * <p/>
83: * The returned list is synchronized to preserve thread safety, but may still result in
84: * ConcurrentModificationException being thrown.
85: *
86: * @return this tree's children
87: */
88: public List<Tree<V>> getChildren() {
89: synchronized (this.monitor) {
90: return new SynchronizedList<Tree<V>>(this.children, this.monitor);
91: }
92: }
93:
94: /**
95: * Adds a new child tree to this node's children. The child tree is copied, although its values are not. The copy
96: * shares this tree's monitor.
97: *
98: * @param child the child tree to add
99: * @return the copy of the child tree
100: */
101: public Tree<V> addChild(Tree<V> child) {
102: synchronized (this.monitor) {
103: ThreadSafeArrayListTree<V> childCopy = new ThreadSafeArrayListTree<V>(child, this, this.monitor);
104: this.children.add(childCopy);
105: return childCopy;
106: }
107: }
108:
109: /**
110: * Removes the first occurrence of the given child tree from this node's children. Returns <code>true</code> if the
111: * child was found and removed, otherwise <code>false</code>.
112: *
113: * @param child the child tree to remove
114: * @return <code>true</code> if the child tree was removed successfully, otherwise <code>false</code>.
115: * @see java.util.List#remove
116: */
117: public boolean removeChild(Tree<V> child) {
118: synchronized (this.monitor) {
119: boolean removed = this.children.remove(child);
120:• if (removed) {
121: setParent(child, null);
122: }
123: return removed;
124: }
125: }
126:
127: /*
128: * All the children in this.children share this.monitor.
129: */
130: private void setParent(Tree<V> child, Tree<V> parent) {
131: synchronized (this.monitor) {
132:• if (child instanceof ThreadSafeArrayListTree<?>) {
133: ThreadSafeArrayListTree<V> concreteChild = (ThreadSafeArrayListTree<V>) child;
134: concreteChild.parent = parent;
135: }
136: }
137: }
138:
139: /**
140: * Traverse this {@link ThreadSafeArrayListTree} in preorder (see below) and call the visit method of the given
141: * {@link Tree.TreeVisitor} at each node. The visitor determines whether the children of each visited tree should
142: * also be visited.
143: * <p/>
144: * Preorder traversal visits the tree and then visits, in preorder, each child of the tree.
145: *
146: * @param visitor a {@link Tree.TreeVisitor}
147: */
148: public void visit(TreeVisitor<V> visitor) {
149:• if (visitor.visit(this)) {
150:• for (int i = 0; i < numChildren(); i++) {
151: ThreadSafeArrayListTree<V> nextChild = getChild(i);
152:• if (nextChild != null) {
153: nextChild.visit(visitor);
154: } else {
155: break;
156: }
157: }
158: }
159: }
160:
161: /**
162: * {@inheritDoc}
163: */
164: public <E extends Exception> void visit(ExceptionThrowingTreeVisitor<V, E> visitor) throws E {
165:• if (visitor.visit(this)) {
166:• for (int i = 0; i < numChildren(); i++) {
167: ThreadSafeArrayListTree<V> nextChild = getChild(i);
168:• if (nextChild != null) {
169: nextChild.visit(visitor);
170: } else {
171: break;
172: }
173: }
174: }
175: }
176:
177: private ThreadSafeArrayListTree<V> getChild(int i) {
178: synchronized (this.monitor) {
179: try {
180: return this.children.get(i);
181: } catch (IndexOutOfBoundsException e) {
182: return null;
183: }
184: }
185: }
186:
187: private int numChildren() {
188: synchronized (this.monitor) {
189: return this.children.size();
190: }
191: }
192:
193: /**
194: * Returns the number of nodes in the tree. This is one plus the sum of the number of nodes in each of the children.
195: * <p/>
196: * If there are more than <tt>Integer.MAX_VALUE</tt> node, the return value is undefined and the user should seek
197: * professional help.
198: *
199: * @return the number of non-<code>null</code> nodes in the tree
200: */
201: public int size() {
202: int size = 1;
203: synchronized (this.monitor) {
204:• for (ThreadSafeArrayListTree<V> child : this.children) {
205: size += child.size();
206: }
207: }
208: return size;
209: }
210:
211: /**
212: * {@inheritDoc}
213: */
214: @Override
215: public int hashCode() {
216: synchronized (this.monitor) {
217: final int prime = 31;
218: int result = 1;
219: result = prime * result + children.hashCode();
220:• result = prime * result + ((value == null) ? 0 : value.hashCode());
221: return result;
222: }
223: }
224:
225: /**
226: * {@inheritDoc}
227: */
228: @SuppressWarnings("unchecked")
229: @Override
230: public boolean equals(Object obj) {
231:• if (this == obj) {
232: return true;
233: }
234:• if (obj == null) {
235: return false;
236: }
237:• if (getClass() != obj.getClass()) {
238: return false;
239: }
240: ThreadSafeArrayListTree<V> other = (ThreadSafeArrayListTree<V>) obj;
241: int thisHash = System.identityHashCode(this);
242: int otherHash = System.identityHashCode(other);
243:• if (thisHash < otherHash) {
244: synchronized (this.monitor) {
245: synchronized (other.monitor) {
246:• if (!children.equals(other.children)) {
247: return false;
248: }
249: }
250: }
251:• } else if (thisHash > otherHash) {
252: synchronized (other.monitor) {
253: synchronized (this.monitor) {
254:• if (!children.equals(other.children)) {
255: return false;
256: }
257: }
258: }
259: } else {
260: synchronized (tieMonitor) {
261: synchronized (this.monitor) {
262: synchronized (other.monitor) {
263:• if (!children.equals(other.children)) {
264: return false;
265: }
266: }
267: }
268: }
269: }
270:• if (value == null) {
271:• if (other.value != null) {
272: return false;
273: }
274:• } else if (!value.equals(other.value)) {
275: return false;
276: }
277: return true;
278: }
279:
280: /**
281: * {@inheritDoc}
282: */
283: @Override
284: public String toString() {
285: StringBuffer result = new StringBuffer();
286:• result.append(this.value != null ? this.value : "null").append("<");
287: synchronized (this.monitor) {
288: boolean first = true;
289:• for (ThreadSafeArrayListTree<V> child : this.children) {
290:• if (!first) {
291: result.append(", ");
292: }
293: result.append(child.toString());
294: first = false;
295: }
296: }
297: result.append(">");
298: return result.toString();
299: }
300:
301: /**
302: * {@inheritDoc}
303: */
304: public Tree<V> getParent() {
305: return this.parent;
306: }
307: }