1/*2 * Licensed to the Apache Software Foundation (ASF) under one3 * or more contributor license agreements. See the NOTICE file4 * distributed with this work for additional information5 * regarding copyright ownership. The ASF licenses this file6 * to you under the Apache License, Version 2.0 (the7 * "License"); you may not use this file except in compliance8 * with the License. You may obtain a copy of the License at9 *10 * http://www.apache.org/licenses/LICENSE-2.011 *12 * Unless required by applicable law or agreed to in writing, software13 * distributed under the License is distributed on an "AS IS" BASIS,14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15 * See the License for the specific language governing permissions and16 * limitations under the License.17 */18package org.apache.giraph.block_app.test_setup;
1920import java.util.ArrayList;
21import java.util.List;
22import java.util.Map.Entry;
2324import org.apache.giraph.conf.GiraphConfiguration;
25import org.apache.giraph.conf.ImmutableClassesGiraphConfiguration;
26import org.apache.giraph.edge.Edge;
27import org.apache.giraph.edge.EdgeFactory;
28import org.apache.giraph.function.Function;
29import org.apache.giraph.function.Supplier;
30import org.apache.giraph.graph.Vertex;
31import org.apache.giraph.utils.TestGraph;
32import org.apache.hadoop.io.DoubleWritable;
33import org.apache.hadoop.io.FloatWritable;
34import org.apache.hadoop.io.IntWritable;
35import org.apache.hadoop.io.LongWritable;
36import org.apache.hadoop.io.Writable;
37import org.apache.hadoop.io.WritableComparable;
38import org.apache.log4j.Logger;
3940import com.google.common.base.Preconditions;
4142/**43 * Wraps TestGraph to allow using numbers to create and inspect the graph,44 * instead of needing to have actual Writable values, which don't have45 * auto-boxing.46 *47 * @param <I> Vertex id type48 * @param <V> Vertex value type49 * @param <E> Edge value type50 */51publicclass NumericTestGraph<I extends WritableComparable,
52 V extends Writable,
53 E extends Writable> {
5455privatestaticfinal Logger LOG = Logger.getLogger(NumericTestGraph.class);
5657privatefinal TestGraph<I, V, E> testGraph;
58privatefinal Function<Number, I> numberToVertexId;
59privatefinal Function<Number, V> numberToVertexValue;
60privatefinal Function<Number, E> numberToEdgeValue;
6162publicNumericTestGraph(TestGraph<I, V, E> testGraph) {
63this.testGraph = testGraph;
64 numberToVertexId =
65 numericConvForType(testGraph.getConf().getVertexIdClass());
66 numberToVertexValue =
67 numericConvForType(testGraph.getConf().getVertexValueClass());
68 numberToEdgeValue =
69 numericConvForType(testGraph.getConf().getEdgeValueClass());
70 Preconditions.checkState(this.numberToVertexId != null);
71 }
7273publicNumericTestGraph(GiraphConfiguration conf) {
74this(new TestGraph<I, V, E>(conf));
75 }
7677public ImmutableClassesGiraphConfiguration<I, V, E> getConf() {
78return testGraph.getConf();
79 }
8081public TestGraph<I, V, E> getTestGraph() {
82return testGraph;
83 }
848586/**87 * Get Vertex for a given id.88 */89public Vertex<I, V, E> getVertex(Number vertexId) {
90return testGraph.getVertex(numberToVertexId(vertexId));
91 }
9293/**94 * Get Vertex Value for a given id.95 */96public V getValue(Number vertexId) {
97return testGraph.getVertex(numberToVertexId(vertexId)).getValue();
98 }
99100/**101 * Get number of vertices in the graph102 */103publicint getVertexCount() {
104return testGraph.getVertexCount();
105 }
106107/**108 * Add Vertex with a given id to the graph, initializing it to109 * default vertex value and no edges.110 */111publicvoid addVertex(Number vertexId) {
112 addVertex(vertexId, (Number) null);
113 }
114115/**116 * Add Vertex with a given id and a given Vertex Value to the graph,117 * initializing it to have no edges.118 */119publicvoid addVertex(Number vertexId, Number vertexValue) {
120 addVertex(vertexId, vertexValue, null);
121 }
122123/**124 * Add Vertex with a given id and a given Vertex Value to the graph,125 * with listed outgoing edges, all initialized to same provided126 * {@code edgeValue}.127 */128publicvoid addVertex(Number vertexId, Number vertexValue,
129 Number edgeValue, Number... outEdges) {
130 Vertex<I, V, E> vertex = makeVertex(
131 vertexId, vertexValue, edgeValue, outEdges);
132 testGraph.addVertex(vertex);
133 }
134135/**136 * Add Vertex with a given id and a given Vertex Value to the graph,137 * initializing it to have no edges.138 */139publicvoid addVertex(Number vertexId, V vertexValue) {
140 addVertex(vertexId, vertexValue, null);
141 }
142143/**144 * Add Vertex with a given id and a given Vertex Value to the graph,145 * with listed outgoing edges, all initialized to same provided146 * {@code edgeSupplier}.147 */148publicvoid addVertex(Number vertexId, V vertexValue,
149 Supplier<E> edgeSupplier, Number... outEdges) {
150 Vertex<I, V, E> vertex = makeVertex(
151 vertexId, vertexValue, edgeSupplier, outEdges);
152 testGraph.addVertex(vertex);
153 }
154155/**156 * Add Edge to the graph with default Edge Value, by adding it to157 * outEdges of {@code fromVertex}, potentially creating {@code fromVertex}158 * if it doesn't exist.159 */160publicvoid addEdge(Number fromVertex, Number toVertex) {
161 addEdge(fromVertex, toVertex, (Number) null);
162 }
163164/**165 * Add Edge to the graph with provided Edge Value, by adding it to166 * outEdges of {@code fromVertex}, potentially creating {@code fromVertex}167 * if it doesn't exist.168 */169publicvoid addEdge(Number fromVertex, Number toVertex, Number edgeValue) {
170 testGraph.addEdge(
171 numberToVertexId(fromVertex),
172 numberToVertexId(toVertex),
173 numberToEdgeValue(edgeValue));
174 }
175176/**177 * Add Edge to the graph with provided Edge Value, by adding it to178 * outEdges of {@code fromVertex}, potentially creating {@code fromVertex}179 * if it doesn't exist.180 */181publicvoid addEdge(Number fromVertex, Number toVertex, E edgeValue) {
182 testGraph.addEdge(
183 numberToVertexId(fromVertex),
184 numberToVertexId(toVertex),
185 edgeValueOrCreate(edgeValue));
186 }
187188/**189 * Add symmetric Edge to the graph with default Edge Value, by adding it to190 * outEdges of vertices on both ends, potentially creating them both,191 * if they don't exist.192 */193publicvoid addSymmetricEdge(Number fromVertex, Number toVertex) {
194 addEdge(fromVertex, toVertex);
195 addEdge(toVertex, fromVertex);
196 }
197198/**199 * Add symmetric Edge to the graph with provided Edge Value, by adding it to200 * outEdges of vertices on both ends, potentially creating them both,201 * if they don't exist.202 */203publicvoid addSymmetricEdge(
204 Number fromVertex, Number toVertex, Number edgeValue) {
205 addEdge(fromVertex, toVertex, edgeValue);
206 addEdge(toVertex, fromVertex, edgeValue);
207 }
208209/**210 * Add symmetric Edge to the graph with provided Edge Value, by adding it to211 * outEdges of vertices on both ends, potentially creating them both,212 * if they don't exist.213 */214publicvoid addSymmetricEdge(Number vertexId, Number toVertex, E edgeValue) {
215 addEdge(vertexId, toVertex, edgeValue);
216 addEdge(toVertex, vertexId, edgeValue);
217 }
218219/**220 * Creates a new Vertex object, without adding it into the graph.221 *222 * This function is safe to call from multiple threads at the same time,223 * and then synchronize only on actual addition of Vertex to the graph224 * itself.225 */226public Vertex<I, V, E> makeVertex(
227 Number vertexId, V vertexValue,
228 Entry<? extends Number, ? extends Number>... edges) {
229 Vertex<I, V, E> vertex = getConf().createVertex();
230 List<Edge<I, E>> edgesList = new ArrayList<>();
231232int i = 0;
233for (Entry<? extends Number, ? extends Number> edge: edges) {
234 edgesList.add(EdgeFactory.create(
235 numberToVertexId(edge.getKey()),
236 numberToEdgeValue(edge.getValue())));
237 i++;
238 }
239 vertex.initialize(
240 numberToVertexId(vertexId),
241 vertexValue != null ?
242 vertexValue : getConf().createVertexValue(),
243 edgesList);
244return vertex;
245 }
246247/**248 * Creates a new Vertex object, without adding it into the graph.249 *250 * This function is safe to call from multiple threads at the same time,251 * and then synchronize only on actual addition of Vertex to the graph252 * itself.253 */254public Vertex<I, V, E> makeVertex(
255 Number vertexId, V vertexValue,
256 Supplier<E> edgeSupplier, Number... edges) {
257 Vertex<I, V, E> vertex = getConf().createVertex();
258259 List<Edge<I, E>> edgesList = new ArrayList<>();
260for (Number edge: edges) {
261 edgesList.add(
262 EdgeFactory.create(numberToVertexId.apply(edge),
263 edgeSupplier != null ?
264 edgeSupplier.get() : getConf().createEdgeValue()));
265 }
266267 vertex.initialize(
268 numberToVertexId.apply(vertexId),
269 vertexValue != null ?
270 vertexValue : getConf().createVertexValue(),
271 edgesList);
272return vertex;
273 }
274275/**276 * Creates a new Vertex object, without adding it into the graph.277 *278 * This function is safe to call from multiple threads at the same time,279 * and then synchronize only on actual addition of Vertex to the graph280 * itself.281 */282public Vertex<I, V, E> makeVertex(
283 Number vertexId, Number value,
284 Number edgeValue, Number... edges) {
285 Vertex<I, V, E> vertex = getConf().createVertex();
286287 List<Edge<I, E>> edgesList = new ArrayList<>();
288for (Number edge: edges) {
289 edgesList.add(
290 EdgeFactory.create(numberToVertexId.apply(edge),
291 numberToEdgeValue(edgeValue)));
292 }
293294 vertex.initialize(
295 numberToVertexId.apply(vertexId),
296 numberToVertexValue(value),
297 edgesList);
298return vertex;
299 }
300301public I numberToVertexId(Number value) {
302return numberToVertexId.apply(value);
303 }
304305public V numberToVertexValue(Number value) {
306return value != null ?
307 numberToVertexValue.apply(value) : getConf().createVertexValue();
308 }
309310public E numberToEdgeValue(Number edgeValue) {
311return edgeValue != null ?
312 numberToEdgeValue.apply(edgeValue) : getConf().createEdgeValue();
313 }
314315public E edgeValueOrCreate(E edgeValue) {
316return edgeValue != null ? edgeValue : getConf().createEdgeValue();
317 }
318319320public Vertex<I, V, E> createVertex() {
321return getConf().createVertex();
322 }
323324publicvoid initializeVertex(
325 Vertex<I, V, E> v, I id, Supplier<V> valueSupplier,
326 List<Edge<I, E>> edgesList) {
327 v.initialize(
328 id,
329 valueSupplier != null ?
330 valueSupplier.get() : getConf().createVertexValue(),
331 edgesList != null ? edgesList : new ArrayList<Edge<I, E>>());
332 }
333334 @Override
335public String toString() {
336return testGraph.toString();
337 }
338339340privatestatic Function<Number, IntWritable> numberToInt() {
341returnnew Function<Number, IntWritable>() {
342 @Override
343public IntWritable apply(Number input) {
344returnnew IntWritable(input.intValue());
345 }
346 };
347 }
348349privatestatic Function<Number, LongWritable> numberToLong() {
350returnnew Function<Number, LongWritable>() {
351 @Override
352public LongWritable apply(Number input) {
353returnnew LongWritable(input.longValue());
354 }
355 };
356 }
357358privatestatic Function<Number, DoubleWritable> numberToDouble() {
359returnnew Function<Number, DoubleWritable>() {
360 @Override
361public DoubleWritable apply(Number input) {
362returnnew DoubleWritable(input.doubleValue());
363 }
364 };
365 }
366367privatestatic Function<Number, FloatWritable> numberToFloat() {
368returnnew Function<Number, FloatWritable>() {
369 @Override
370public FloatWritable apply(Number input) {
371returnnew FloatWritable(input.floatValue());
372 }
373 };
374 }
375376privatestatic <T> Function<Number, T> numericConvForType(Class<T> type) {
377if (type.equals(LongWritable.class)) {
378return (Function) numberToLong();
379 } elseif (type.equals(IntWritable.class)) {
380return (Function) numberToInt();
381 } elseif (type.equals(DoubleWritable.class)) {
382return (Function) numberToDouble();
383 } elseif (type.equals(FloatWritable.class)) {
384return (Function) numberToFloat();
385 } else {
386returnnull;
387 }
388 }
389 }