/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.flink.graph.library;
import org.apache.flink.api.java.ExecutionEnvironment;
import org.apache.flink.api.java.io.LocalCollectionOutputFormat;
import org.apache.flink.graph.Edge;
import org.apache.flink.graph.Graph;
import org.apache.flink.graph.Vertex;
import org.apache.flink.graph.asm.translate.TranslateEdgeValues;
import org.apache.flink.graph.asm.translate.TranslateFunction;
import org.apache.flink.graph.asm.translate.TranslateVertexValues;
import org.apache.flink.graph.asm.translate.translators.ToNullValue;
import org.apache.flink.graph.examples.data.SummarizationData;
import org.apache.flink.graph.library.Summarization.EdgeValue;
import org.apache.flink.test.util.MultipleProgramsTestBase;
import org.apache.flink.types.NullValue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Pattern;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RunWith(Parameterized.class)
public class SummarizationITCase extends MultipleProgramsTestBase {
private static final Pattern TOKEN_SEPARATOR = Pattern.compile(";");
private static final Pattern ID_SEPARATOR = Pattern.compile(",");
public SummarizationITCase(TestExecutionMode mode) {
super(mode);
}
@Test
public void testWithVertexAndEdgeStringValues() throws Exception {
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
Graph<Long, String, String> input = Graph.fromDataSet(
SummarizationData.getVertices(env),
SummarizationData.getEdges(env),
env);
List<Vertex<Long, Summarization.VertexValue<String>>> summarizedVertices = new ArrayList<>();
List<Edge<Long, EdgeValue<String>>> summarizedEdges = new ArrayList<>();
Graph<Long, Summarization.VertexValue<String>, EdgeValue<String>> output =
input.run(new Summarization<Long, String, String>());
output.getVertices().output(new LocalCollectionOutputFormat<>(summarizedVertices));
output.getEdges().output(new LocalCollectionOutputFormat<>(summarizedEdges));
env.execute();
validateVertices(SummarizationData.EXPECTED_VERTICES, summarizedVertices);
validateEdges(SummarizationData.EXPECTED_EDGES_WITH_VALUES, summarizedEdges);
}
@Test
public void testWithVertexAndAbsentEdgeStringValues() throws Exception {
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
Graph<Long, String, NullValue> input = Graph.fromDataSet(
SummarizationData.getVertices(env),
SummarizationData.getEdges(env),
env)
.run(new TranslateEdgeValues<Long, String, String, NullValue>(new ToNullValue<String>()));
List<Vertex<Long, Summarization.VertexValue<String>>> summarizedVertices = new ArrayList<>();
List<Edge<Long, EdgeValue<NullValue>>> summarizedEdges = new ArrayList<>();
Graph<Long, Summarization.VertexValue<String>, EdgeValue<NullValue>> output =
input.run(new Summarization<Long, String, NullValue>());
output.getVertices().output(new LocalCollectionOutputFormat<>(summarizedVertices));
output.getEdges().output(new LocalCollectionOutputFormat<>(summarizedEdges));
env.execute();
validateVertices(SummarizationData.EXPECTED_VERTICES, summarizedVertices);
validateEdges(SummarizationData.EXPECTED_EDGES_ABSENT_VALUES, summarizedEdges);
}
@Test
public void testWithVertexAndEdgeLongValues() throws Exception {
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
Graph<Long, Long, Long> input = Graph.fromDataSet(
SummarizationData.getVertices(env),
SummarizationData.getEdges(env),
env)
.run(new TranslateVertexValues<Long, String, Long, String>(new StringToLong()))
.run(new TranslateEdgeValues<Long, Long, String, Long>(new StringToLong()));
List<Vertex<Long, Summarization.VertexValue<Long>>> summarizedVertices = new ArrayList<>();
List<Edge<Long, EdgeValue<Long>>> summarizedEdges = new ArrayList<>();
Graph<Long, Summarization.VertexValue<Long>, EdgeValue<Long>> output =
input.run(new Summarization<Long, Long, Long>());
output.getVertices().output(new LocalCollectionOutputFormat<>(summarizedVertices));
output.getEdges().output(new LocalCollectionOutputFormat<>(summarizedEdges));
env.execute();
validateVertices(SummarizationData.EXPECTED_VERTICES, summarizedVertices);
validateEdges(SummarizationData.EXPECTED_EDGES_WITH_VALUES, summarizedEdges);
}
private <VV extends Comparable<VV>> void validateVertices(String[] expectedVertices, List<Vertex<Long, Summarization.VertexValue<VV>>> actualVertices) {
Arrays.sort(expectedVertices);
Collections.sort(actualVertices, new Comparator<Vertex<Long, Summarization.VertexValue<VV>>>() {
@Override
public int compare(Vertex<Long, Summarization.VertexValue<VV>> o1, Vertex<Long, Summarization.VertexValue<VV>> o2) {
int result = o1.getId().compareTo(o2.getId());
if (result == 0) {
result = o1.getValue().getVertexGroupValue().compareTo(o2.getValue().getVertexGroupValue());
}
return result;
}
});
for (int i = 0; i < expectedVertices.length; i++) {
validateVertex(expectedVertices[i], actualVertices.get(i));
}
}
private <EV extends Comparable<EV>> void validateEdges(String[] expectedEdges, List<Edge<Long, EdgeValue<EV>>> actualEdges) {
Arrays.sort(expectedEdges);
Collections.sort(actualEdges, new Comparator<Edge<Long, EdgeValue<EV>>> () {
@Override
public int compare(Edge<Long, EdgeValue<EV>> o1, Edge<Long, EdgeValue<EV>> o2) {
int result = o1.getSource().compareTo(o2.getSource());
if (result == 0) {
result = o1.getTarget().compareTo(o2.getTarget());
}
if (result == 0) {
result = o1.getValue().getEdgeGroupValue().compareTo(o2.getValue().getEdgeGroupValue());
}
return result;
}
});
for (int i = 0; i < expectedEdges.length; i++) {
validateEdge(expectedEdges[i], actualEdges.get(i));
}
}
private <VV> void validateVertex(String expected, Vertex<Long, Summarization.VertexValue<VV>> actual) {
String[] tokens = TOKEN_SEPARATOR.split(expected);
assertTrue(getListFromIdRange(tokens[0]).contains(actual.getId()));
assertEquals(getGroupValue(tokens[1]), actual.getValue().getVertexGroupValue().toString());
assertEquals(getGroupCount(tokens[1]), actual.getValue().getVertexGroupCount());
}
private <EV> void validateEdge(String expected, Edge<Long, EdgeValue<EV>> actual) {
String[] tokens = TOKEN_SEPARATOR.split(expected);
assertTrue(getListFromIdRange(tokens[0]).contains(actual.getSource()));
assertTrue(getListFromIdRange(tokens[1]).contains(actual.getTarget()));
assertEquals(getGroupValue(tokens[2]), actual.getValue().getEdgeGroupValue().toString());
assertEquals(getGroupCount(tokens[2]), actual.getValue().getEdgeGroupCount());
}
private List<Long> getListFromIdRange(String idRange) {
String[] split = ID_SEPARATOR.split(idRange);
List<Long> result = new ArrayList<>(split.length);
for (String id : split) {
result.add(Long.parseLong(id));
}
return result;
}
private String getGroupValue(String token) {
return ID_SEPARATOR.split(token)[0];
}
private Long getGroupCount(String token) {
return Long.valueOf(ID_SEPARATOR.split(token)[1]);
}
private static class StringToLong implements TranslateFunction<String, Long> {
@Override
public Long translate(String value, Long reuse) throws Exception {
return Long.parseLong(value);
}
}
}