1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.archive.crawler.util;
26
27 import java.util.AbstractCollection;
28 import java.util.Collection;
29 import java.util.Iterator;
30
31
32 /***
33 * A transformation of a collection. The elements in the transform are based
34 * on the elements of some other collection; the original collection's
35 * elements are transformed using a specified transformer. Changes to the
36 * original collection are automatically reflected in the transform and
37 * vice-versa.
38 *
39 * <p>If the transformer returns null for a given original object, then that
40 * object will not be included in the transform. Thus the transform might
41 * be smaller than the original collection. Note that Transform instances
42 * can never contain the null element.
43 *
44 * <p>This collection implementation does not support the optional add
45 * operation.
46 *
47 * @author pjack
48 *
49 * @param <Original> the type of the original elements in the collection
50 * @param <Transformed> the type of the tranformed elements
51 */
52 public class Transform<Original,Transformed>
53 extends AbstractCollection<Transformed> {
54
55 /*** The original collection. */
56 final private Collection<? extends Original> delegate;
57
58 /*** Transforms the original objects. */
59 final private Transformer<Original,Transformed> transformer;
60
61 /***
62 * Constructor.
63 *
64 * @param delegate The collection whose elements to transform.
65 * @param transformer Transforms the elements
66 */
67 public Transform(Collection<? extends Original> delegate,
68 Transformer<Original,Transformed> transformer) {
69 this.delegate = delegate;
70 this.transformer = transformer;
71 }
72
73 public int size() {
74 int count = 0;
75 Iterator<Transformed> iter = iterator();
76 while (iter.hasNext()) {
77 iter.next();
78 count++;
79 }
80 return count;
81 }
82
83 public Iterator<Transformed> iterator() {
84 return new TransformIterator<Original,Transformed>(
85 delegate.iterator(), transformer);
86 }
87
88
89 /***
90 * Returns a transform containing only objects of a given class.
91 *
92 * @param <Target> the target class
93 * @param c the collection to transform
94 * @param cls the class of objects to return
95 * @return a collection containing only objects of class cls
96 */
97 public static <Target> Collection<Target> subclasses(
98 Collection<? extends Object> c,
99 final Class<Target> cls) {
100 Transformer<Object,Target> t = new Transformer<Object,Target>() {
101 public Target transform(Object s) {
102 if (cls.isInstance(s)) {
103 return cls.cast(s);
104 } else {
105 return null;
106 }
107 }
108 };
109 return new Transform<Object,Target>(c, t);
110 }
111 }
112
113
114 class TransformIterator<Original,Transformed> implements Iterator<Transformed> {
115
116 final private Iterator<? extends Original> iterator;
117 final private Transformer<Original,Transformed> transformer;
118 private Transformed next;
119
120 public TransformIterator(Iterator<? extends Original> iterator,
121 Transformer<Original,Transformed> transformer) {
122 this.iterator = iterator;
123 this.transformer = transformer;
124 }
125
126 public boolean hasNext() {
127 if (next != null) {
128 return true;
129 }
130 while (iterator.hasNext()) {
131 Original o = iterator.next();
132 next = transformer.transform(o);
133 if (next != null) {
134 return true;
135 }
136 }
137 return false;
138 }
139
140 public Transformed next() {
141 if (!hasNext()) {
142 throw new IllegalStateException();
143 }
144 Transformed r = next;
145 next = null;
146 return r;
147 }
148
149
150
151
152
153
154
155
156 public void remove() {
157 iterator.remove();
158 }
159
160 }