/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Gephi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Gephi. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.filters.impl;
import java.util.ArrayList;
import java.util.List;
import org.gephi.filters.AbstractQueryImpl;
import org.gephi.filters.FilterProcessor;
import org.gephi.filters.FilterQueryImpl;
import org.gephi.filters.OperatorQueryImpl;
import org.gephi.filters.api.Query;
import org.gephi.filters.spi.EdgeFilter;
import org.gephi.filters.spi.Filter;
import org.gephi.filters.spi.FilterProperty;
import org.gephi.filters.spi.NodeFilter;
import org.gephi.filters.spi.Operator;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphController;
import org.gephi.graph.api.GraphFactory;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.Node;
import org.gephi.project.api.ProjectController;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openide.util.Lookup;
/**
*
* @author Mathieu Bastian
*/
public class FilterProcessorTest {
private GraphModel graphModel;
private Graph rootGraph;
private Query simpleQuery;
private Query chainQuery;
private Query complexQueryUnion;
private Query veryComplexQueryInter;
@Before
public void setUp() {
//Graph
ProjectController pj = Lookup.getDefault().lookup(ProjectController.class);
pj.newProject();
GraphController gc = Lookup.getDefault().lookup(GraphController.class);
graphModel = gc.getModel();
GraphFactory factory = graphModel.factory();
Graph graph = gc.getModel().getUndirectedGraph();
rootGraph = graph;
//Add 8 nodes
for (int i = 0; i < 8; i++) {
Node node = factory.newNode();
graph.addNode(node);
}
//Add edges
graph.addEdge(factory.newEdge("0-1", graph.getNode(0), graph.getNode(1), 1f, false));
graph.addEdge(factory.newEdge("1-3",graph.getNode(1), graph.getNode(3), 1f, false));
graph.addEdge(factory.newEdge("3-2",graph.getNode(3), graph.getNode(2), 1f, false));
graph.addEdge(factory.newEdge("2-0",graph.getNode(2), graph.getNode(0), 1f, false));
graph.addEdge(factory.newEdge("4-5",graph.getNode(4), graph.getNode(5), 2f, false));
graph.addEdge(factory.newEdge("5-7",graph.getNode(5), graph.getNode(7), 2f, false));
graph.addEdge(factory.newEdge("7-6",graph.getNode(7), graph.getNode(6), 2f, false));
graph.addEdge(factory.newEdge("6-4",graph.getNode(6), graph.getNode(4), 2f, false));
graph.addEdge(factory.newEdge("3-4",graph.getNode(3), graph.getNode(4), 5f, false));
//Query
NodeDegreeFilter nodeDegreeFilter = new NodeDegreeFilter(3);
simpleQuery = new FilterQueryImpl(nodeDegreeFilter);
nodeDegreeFilter = new NodeDegreeFilter(1);
chainQuery = new FilterQueryImpl(nodeDegreeFilter);
((FilterQueryImpl) chainQuery).addSubQuery(new FilterQueryImpl(new EdgeWeightFilter(1)));
complexQueryUnion = new OperatorQueryImpl(new UnionOperator());
((OperatorQueryImpl) complexQueryUnion).addSubQuery(new FilterQueryImpl(new NodeIdFilter(1)));
((OperatorQueryImpl) complexQueryUnion).addSubQuery(new FilterQueryImpl(new NodeIdFilter(3)));
veryComplexQueryInter = new FilterQueryImpl(new EdgeWeightFilter(0));
OperatorQueryImpl q1 = new OperatorQueryImpl(new UnionOperator());
((FilterQueryImpl) veryComplexQueryInter).addSubQuery(q1);
q1.addSubQuery(new FilterQueryImpl(new NodeIdFilter(0)));
OperatorQueryImpl q2 = new OperatorQueryImpl(new UnionOperator());
q2.addSubQuery(new FilterQueryImpl(new NodeIdFilter(1)));
q2.addSubQuery(new FilterQueryImpl(new NodeIdFilter(2)));
q1.addSubQuery(q2);
FilterQueryImpl q3 = new FilterQueryImpl(new NodeDegreeFilter(2));
q3.addSubQuery(new FilterQueryImpl(new EdgeWeightFilter(1)));
q1.addSubQuery(q3);
}
@After
public void tearDown() {
rootGraph = null;
simpleQuery = null;
chainQuery = null;
veryComplexQueryInter = null;
complexQueryUnion = null;
}
@Test
public void testProcess() {
FilterProcessor filterProcessor = new FilterProcessor();
printGraph(rootGraph);
Graph result = filterProcessor.process((AbstractQueryImpl) veryComplexQueryInter, graphModel);
printGraph(result);
// printGraph(rootGraph);
// rootGraph.removeNode(rootGraph.getNode(0));
// printGraph(rootGraph);
}
private void printGraph(Graph graph) {
Node[] nodes = graph.getNodes().toArray();
Edge[] edges = graph.getEdges().toArray();
System.out.println("--- Graph");
System.out.println("--- Nodes: " + nodes.length);
System.out.println("--- Edges: " + edges.length);
for (Node n : nodes) {
System.out.println("" + n.getId());
}
System.out.println("---------------");
for (Edge e : edges) {
System.out.println(e.getSource().getId() + "-" + e.getTarget().getId());
}
System.out.println("---------------");
System.out.flush();
}
private static class EdgeWeightFilter implements EdgeFilter {
private final float threshold;
public EdgeWeightFilter(float threshold) {
this.threshold = threshold;
}
public boolean evaluate(Graph graph, Edge edge) {
return edge.getWeight() > threshold;
}
public String getName() {
return "EdgeWeightFilter";
}
public FilterProperty[] getProperties() {
return null;
}
public boolean init(Graph graph) {
return true;
}
public void finish() {
}
}
private static class NodeDegreeFilter implements NodeFilter {
private final float threshold;
public NodeDegreeFilter(float threshold) {
this.threshold = threshold;
}
public boolean evaluate(Graph graph, Node node) {
int degree = graph.getDegree(node);
return degree > threshold;
}
public String getName() {
return "NodeDegreeFilter";
}
public FilterProperty[] getProperties() {
return null;
}
public boolean init(Graph graph) {
return true;
}
public void finish() {
}
}
private static class NodeIdFilter implements NodeFilter {
private final int id;
public NodeIdFilter(int id) {
this.id = id;
}
public boolean evaluate(Graph graph, Node node) {
return node.getId() == id;
}
public String getName() {
return "NodeIdFilter " + id;
}
public FilterProperty[] getProperties() {
return null;
}
public boolean init(Graph graph) {
return true;
}
public void finish() {
}
}
private static class UnionOperator implements Operator {
public int getInputCount() {
return 2;
}
public String getName() {
return "UNION";
}
public FilterProperty[] getProperties() {
return null;
}
public Graph filter(Graph[] graphs) {
Graph maxGraph = graphs[0];
int maxElements = 0;
for (int i = 0; i < graphs.length; i++) {
int count = graphs[i].getNodeCount();
if (count > maxElements) {
maxGraph = graphs[i];
maxElements = count;
}
}
for (int i = 0; i < graphs.length; i++) {
if (graphs[i] != maxGraph) {
//Merge
for (Node n : graphs[i].getNodes().toArray()) {
maxGraph.addNode(n);
}
for (Edge e : graphs[i].getEdges().toArray()) {
maxGraph.addEdge(e);
}
}
}
return maxGraph;
}
public Graph filter(Graph graph, Filter[] filters) {
List<NodeFilter> nodeFilters = new ArrayList<NodeFilter>();
List<EdgeFilter> edgeFilters = new ArrayList<EdgeFilter>();
for (Filter f : filters) {
if (f instanceof NodeFilter) {
nodeFilters.add((NodeFilter) f);
} else if (f instanceof EdgeFilter) {
edgeFilters.add((EdgeFilter) f);
}
}
if (nodeFilters.size() > 0) {
List<Node> nodesToRemove = new ArrayList<Node>();
for (Node n : graph.getNodes()) {
boolean remove = true;
for (NodeFilter nf : nodeFilters) {
if (nf.evaluate(graph, n)) {
remove = false;
}
}
if (remove) {
nodesToRemove.add(n);
}
}
for (Node n : nodesToRemove) {
graph.removeNode(n);
}
}
if (edgeFilters.size() > 0) {
List<Edge> edgesToRemove = new ArrayList<Edge>();
for (Edge e : graph.getEdges()) {
boolean remove = true;
for (EdgeFilter nf : edgeFilters) {
if (nf.evaluate(graph, e)) {
remove = false;
}
}
if (remove) {
edgesToRemove.add(e);
}
}
for (Edge e : edgesToRemove) {
graph.removeEdge(e);
}
}
return graph;
}
}
}