View Javadoc

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, software
13   * 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 and
16   * limitations under the License.
17   */
18  package org.apache.giraph.block_app.test_setup;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.Map.Entry;
23  
24  import org.apache.giraph.conf.GiraphConfiguration;
25  import org.apache.giraph.conf.ImmutableClassesGiraphConfiguration;
26  import org.apache.giraph.edge.Edge;
27  import org.apache.giraph.edge.EdgeFactory;
28  import org.apache.giraph.function.Function;
29  import org.apache.giraph.function.Supplier;
30  import org.apache.giraph.graph.Vertex;
31  import org.apache.giraph.utils.TestGraph;
32  import org.apache.hadoop.io.DoubleWritable;
33  import org.apache.hadoop.io.FloatWritable;
34  import org.apache.hadoop.io.IntWritable;
35  import org.apache.hadoop.io.LongWritable;
36  import org.apache.hadoop.io.Writable;
37  import org.apache.hadoop.io.WritableComparable;
38  import org.apache.log4j.Logger;
39  
40  import com.google.common.base.Preconditions;
41  
42  /**
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 have
45   * auto-boxing.
46   *
47   * @param <I> Vertex id type
48   * @param <V> Vertex value type
49   * @param <E> Edge value type
50   */
51  public class NumericTestGraph<I extends WritableComparable,
52      V extends Writable,
53      E extends Writable> {
54  
55    private static final Logger LOG = Logger.getLogger(NumericTestGraph.class);
56  
57    private final TestGraph<I, V, E> testGraph;
58    private final Function<Number, I> numberToVertexId;
59    private final Function<Number, V> numberToVertexValue;
60    private final Function<Number, E> numberToEdgeValue;
61  
62    public NumericTestGraph(TestGraph<I, V, E> testGraph) {
63      this.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    }
72  
73    public NumericTestGraph(GiraphConfiguration conf) {
74      this(new TestGraph<I, V, E>(conf));
75    }
76  
77    public ImmutableClassesGiraphConfiguration<I, V, E> getConf() {
78      return testGraph.getConf();
79    }
80  
81    public TestGraph<I, V, E> getTestGraph() {
82      return testGraph;
83    }
84  
85  
86    /**
87     * Get Vertex for a given id.
88     */
89    public Vertex<I, V, E> getVertex(Number vertexId) {
90      return testGraph.getVertex(numberToVertexId(vertexId));
91    }
92  
93    /**
94     * Get Vertex Value for a given id.
95     */
96    public V getValue(Number vertexId) {
97      return testGraph.getVertex(numberToVertexId(vertexId)).getValue();
98    }
99  
100   /**
101    * Get number of vertices in the graph
102    */
103   public int getVertexCount() {
104     return testGraph.getVertices().size();
105   }
106 
107   /**
108    * Add Vertex with a given id to the graph, initializing it to
109    * default vertex value and no edges.
110    */
111   public void addVertex(Number vertexId) {
112     addVertex(vertexId, (Number) null);
113   }
114 
115   /**
116    * Add Vertex with a given id and a given Vertex Value to the graph,
117    * initializing it to have no edges.
118    */
119   public void addVertex(Number vertexId, Number vertexValue) {
120     addVertex(vertexId, vertexValue, null);
121   }
122 
123   /**
124    * Add Vertex with a given id and a given Vertex Value to the graph,
125    * with listed outgoing edges, all initialized to same provided
126    * {@code edgeValue}.
127    */
128   public void 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   }
134 
135   /**
136    * Add Vertex with a given id and a given Vertex Value to the graph,
137    * initializing it to have no edges.
138    */
139   public void addVertex(Number vertexId, V vertexValue) {
140     addVertex(vertexId, vertexValue, null);
141   }
142 
143   /**
144    * Add Vertex with a given id and a given Vertex Value to the graph,
145    * with listed outgoing edges, all initialized to same provided
146    * {@code edgeSupplier}.
147    */
148   public void 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   }
154 
155   /**
156    * Add Edge to the graph with default Edge Value, by adding it to
157    * outEdges of {@code fromVertex}, potentially creating {@code fromVertex}
158    * if it doesn't exist.
159    */
160   public void addEdge(Number fromVertex, Number toVertex) {
161     addEdge(fromVertex, toVertex, (Number) null);
162   }
163 
164   /**
165    * Add Edge to the graph with provided Edge Value, by adding it to
166    * outEdges of {@code fromVertex}, potentially creating {@code fromVertex}
167    * if it doesn't exist.
168    */
169   public void addEdge(Number fromVertex, Number toVertex, Number edgeValue) {
170     testGraph.addEdge(
171         numberToVertexId(fromVertex),
172         numberToVertexId(toVertex),
173         numberToEdgeValue(edgeValue));
174   }
175 
176   /**
177    * Add Edge to the graph with provided Edge Value, by adding it to
178    * outEdges of {@code fromVertex}, potentially creating {@code fromVertex}
179    * if it doesn't exist.
180    */
181   public void addEdge(Number fromVertex, Number toVertex, E edgeValue) {
182     testGraph.addEdge(
183         numberToVertexId(fromVertex),
184         numberToVertexId(toVertex),
185         edgeValueOrCreate(edgeValue));
186   }
187 
188   /**
189    * Add symmetric Edge to the graph with default Edge Value, by adding it to
190    * outEdges of vertices on both ends, potentially creating them both,
191    * if they don't exist.
192    */
193   public void addSymmetricEdge(Number fromVertex, Number toVertex) {
194     addEdge(fromVertex, toVertex);
195     addEdge(toVertex, fromVertex);
196   }
197 
198   /**
199    * Add symmetric Edge to the graph with provided Edge Value, by adding it to
200    * outEdges of vertices on both ends, potentially creating them both,
201    * if they don't exist.
202    */
203   public void addSymmetricEdge(
204       Number fromVertex, Number toVertex, Number edgeValue) {
205     addEdge(fromVertex, toVertex, edgeValue);
206     addEdge(toVertex, fromVertex, edgeValue);
207   }
208 
209   /**
210    * Add symmetric Edge to the graph with provided Edge Value, by adding it to
211    * outEdges of vertices on both ends, potentially creating them both,
212    * if they don't exist.
213    */
214   public void addSymmetricEdge(Number vertexId, Number toVertex, E edgeValue) {
215     addEdge(vertexId, toVertex, edgeValue);
216     addEdge(toVertex, vertexId, edgeValue);
217   }
218 
219   /**
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 graph
224    * itself.
225    */
226   public 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<>();
231 
232     int i = 0;
233     for (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);
244     return vertex;
245   }
246 
247   /**
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 graph
252    * itself.
253    */
254   public Vertex<I, V, E> makeVertex(
255       Number vertexId, V vertexValue,
256       Supplier<E> edgeSupplier, Number... edges) {
257     Vertex<I, V, E> vertex = getConf().createVertex();
258 
259     List<Edge<I, E>> edgesList = new ArrayList<>();
260     for (Number edge: edges) {
261       edgesList.add(
262           EdgeFactory.create(numberToVertexId.apply(edge),
263           edgeSupplier != null ?
264             edgeSupplier.get() : getConf().createEdgeValue()));
265     }
266 
267     vertex.initialize(
268         numberToVertexId.apply(vertexId),
269         vertexValue != null ?
270           vertexValue : getConf().createVertexValue(),
271         edgesList);
272     return vertex;
273   }
274 
275   /**
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 graph
280    * itself.
281    */
282   public Vertex<I, V, E> makeVertex(
283       Number vertexId, Number value,
284       Number edgeValue, Number... edges) {
285     Vertex<I, V, E> vertex = getConf().createVertex();
286 
287     List<Edge<I, E>> edgesList = new ArrayList<>();
288     for (Number edge: edges) {
289       edgesList.add(
290           EdgeFactory.create(numberToVertexId.apply(edge),
291           numberToEdgeValue(edgeValue)));
292     }
293 
294     vertex.initialize(
295         numberToVertexId.apply(vertexId),
296         numberToVertexValue(value),
297         edgesList);
298     return vertex;
299   }
300 
301   public I numberToVertexId(Number value) {
302     return numberToVertexId.apply(value);
303   }
304 
305   public V numberToVertexValue(Number value) {
306     return value != null ?
307       numberToVertexValue.apply(value) : getConf().createVertexValue();
308   }
309 
310   public E numberToEdgeValue(Number edgeValue) {
311     return edgeValue != null ?
312       numberToEdgeValue.apply(edgeValue) : getConf().createEdgeValue();
313   }
314 
315   public E edgeValueOrCreate(E edgeValue) {
316     return edgeValue != null ? edgeValue : getConf().createEdgeValue();
317   }
318 
319 
320   public Vertex<I, V, E> createVertex() {
321     return getConf().createVertex();
322   }
323 
324   public void 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   }
333 
334   @Override
335   public String toString() {
336     return testGraph.toString();
337   }
338 
339 
340   private static Function<Number, IntWritable> numberToInt() {
341     return new Function<Number, IntWritable>() {
342       @Override
343       public IntWritable apply(Number input) {
344         return new IntWritable(input.intValue());
345       }
346     };
347   }
348 
349   private static Function<Number, LongWritable> numberToLong() {
350     return new Function<Number, LongWritable>() {
351       @Override
352       public LongWritable apply(Number input) {
353         return new LongWritable(input.longValue());
354       }
355     };
356   }
357 
358   private static Function<Number, DoubleWritable> numberToDouble() {
359     return new Function<Number, DoubleWritable>() {
360       @Override
361       public DoubleWritable apply(Number input) {
362         return new DoubleWritable(input.doubleValue());
363       }
364     };
365   }
366 
367   private static Function<Number, FloatWritable> numberToFloat() {
368     return new Function<Number, FloatWritable>() {
369       @Override
370       public FloatWritable apply(Number input) {
371         return new FloatWritable(input.floatValue());
372       }
373     };
374   }
375 
376   private static <T> Function<Number, T> numericConvForType(Class<T> type) {
377     if (type.equals(LongWritable.class)) {
378       return (Function) numberToLong();
379     } else if (type.equals(IntWritable.class)) {
380       return (Function) numberToInt();
381     } else if (type.equals(DoubleWritable.class)) {
382       return (Function) numberToDouble();
383     } else if (type.equals(FloatWritable.class)) {
384       return (Function) numberToFloat();
385     } else {
386       return null;
387     }
388   }
389 }