// Path: src/main/java/de/jfschaefer/layeredgraphlayout/Edge.java
// public class Edge<V, E> {
//     protected E originalEdge;
//     protected Node<V, E> from, to;
//     protected boolean flipped = false;
//     protected boolean locked = false;
// 
//     public Edge(E original, Node<V, E> from, Node<V, E> to) {
//         originalEdge = original;
//         this.from = from;
//         this.to = to;
//         from.addOutgoingEdge(this);
//         to.addIngoingEdge(this);
//     }
// 
//     public E getOriginalEdge() {
//         return originalEdge;
//     }
// 
//     public Node<V, E> getFrom() {
//         return flipped ? to : from;
//     }
// 
//     public Node<V, E> getTo() {
//         return flipped ? from : to;
//     }
// 
//     public Node<V, E> getRealFrom() {
//         return from;
//     }
// 
//     public Node<V, E> getRealTo() {
//         return to;
//     }
// 
//     public boolean isFlipped() {
//         return flipped;
//     }
// 
//     public void flip() {
//         assert !locked;
//         getFrom().reverseOutgoingEdge(this);
//         getTo().reverseIngoingEdge(this);
//         flipped = !flipped;
//     }
// 
//     public void lock() {
//         locked = true;
//     }
// 
//     public boolean isLocked() {
//         return locked;
//     }
// }
// 
// Path: src/main/java/de/jfschaefer/layeredgraphlayout/Node.java
// public class Node<V, E> {
//     protected V originalNode;
//     protected double width, height;
//     protected Set<Edge<V, E>> outgoingEdges;
//     protected Set<Edge<V, E>> ingoingEdges;
// 
//     public Node(V original, double width, double height) {
//         originalNode = original;
//         this.width = width;
//         this.height = height;
//         outgoingEdges = new HashSet<Edge<V, E>>();
//         ingoingEdges = new HashSet<Edge<V, E>>();
//     }
// 
//     void addIngoingEdge(Edge<V, E> edge) {
//         ingoingEdges.add(edge);
//     }
// 
//     void addOutgoingEdge(Edge<V, E> edge) {
//         outgoingEdges.add(edge);
//     }
// 
//     public void reverseIngoingEdge(Edge<V, E> edge) {
//         assert ingoingEdges.contains(edge);
//         ingoingEdges.remove(edge);
//         outgoingEdges.add(edge);
//     }
// 
//     public void reverseOutgoingEdge(Edge<V, E> edge) {
//         assert outgoingEdges.contains(edge);
//         outgoingEdges.remove(edge);
//         ingoingEdges.add(edge);
//     }
// 
//     public final Set<Edge<V, E>> getOutgoingEdges() {
//         return outgoingEdges;
//     }
// 
//     public final Set<Edge<V, E>> getIngoingEdges() {
//         return ingoingEdges;
//     }
// 
//     public boolean isSink() {
//         return outgoingEdges.isEmpty();
//     }
// 
//     public boolean isSource() {
//         return ingoingEdges.isEmpty();
//     }
// 
//     public boolean isSinkIn(Collection<Node<V, E>> subset) {
//         for (Edge<V, E> edge : outgoingEdges) {
//             if (subset.contains(edge.getTo())) {
//                 return false;
//             }
//         }
//         return true;
//     }
// 
//     public boolean isSourceIn(Collection<Node<V, E>> subset) {
//         for (Edge<V, E> edge : ingoingEdges) {
//             if (subset.contains(edge.getFrom())) {
//                 return false;
//             }
//         }
//         return true;
//     }
// 
//     public int inDegree() {
//         return ingoingEdges.size();
//     }
// 
//     public int outDegree() {
//         return outgoingEdges.size();
//     }
// 
//     public int inDegreeIn(Collection<Node<V, E>> subset) {
//         int indegree = 0;
//         for (Edge<V, E> edge : ingoingEdges) {
//             if (subset.contains(edge.getFrom())) {
//                 indegree ++;
//             }
//         }
//         return indegree;
//     }
// 
//     public int outDegreeIn(Collection<Node<V, E>> subset) {
//         int outdegree = 0;
//         for (Edge<V, E> edge : outgoingEdges) {
//             if (subset.contains(edge.getTo())) {
//                 outdegree ++;
//             }
//         }
//         return outdegree;
//     }
// 
//     public double getWidth() {
//         return width;
//     }
// 
//     public double getHeight() {
//         return height;
//     }
// 
//     public V getOriginalNode() {
//         return originalNode;
//     }
// }
// 
// Path: src/main/java/de/jfschaefer/layeredgraphlayout/util/Pair.java
// public class Pair<A, B> {
//     public final A first;
//     public final B second;
//     public Pair(A first, B second) {
//         this.first = first;
//         this.second = second;
//     }
// }


import de.jfschaefer.layeredgraphlayout.Edge;
import de.jfschaefer.layeredgraphlayout.Node;
import de.jfschaefer.layeredgraphlayout.util.Pair;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.util.ArrayList;
package de.jfschaefer.layeredgraphlayout.lgraph;



/**
 * Created by jfschaefer on 8/12/15.
 */

public class LGraphTest extends TestCase {
    public LGraphTest(String testName) {
        super(testName);
    }

    public static Test suite() {
        return new TestSuite(LGraphTest.class);
    }

    public void testIntersectionCounting() {
        LGraph<String, String> lgraph = new LGraph<String, String>(new LGraphConfig());
        String a1 = "Hello";
        String a2 = "World";
        String b1 = "Welcome";
        String b2 = "Home";
        String e1 = "Hello Home";
        String e2 = "World Welcome";

// Path: src/main/java/de/jfschaefer/layeredgraphlayout/Edge.java
// public class Edge<V, E> {
//     protected E originalEdge;
//     protected Node<V, E> from, to;
//     protected boolean flipped = false;
//     protected boolean locked = false;
// 
//     public Edge(E original, Node<V, E> from, Node<V, E> to) {
//         originalEdge = original;
//         this.from = from;
//         this.to = to;
//         from.addOutgoingEdge(this);
//         to.addIngoingEdge(this);
//     }
// 
//     public E getOriginalEdge() {
//         return originalEdge;
//     }
// 
//     public Node<V, E> getFrom() {
//         return flipped ? to : from;
//     }
// 
//     public Node<V, E> getTo() {
//         return flipped ? from : to;
//     }
// 
//     public Node<V, E> getRealFrom() {
//         return from;
//     }
// 
//     public Node<V, E> getRealTo() {
//         return to;
//     }
// 
//     public boolean isFlipped() {
//         return flipped;
//     }
// 
//     public void flip() {
//         assert !locked;
//         getFrom().reverseOutgoingEdge(this);
//         getTo().reverseIngoingEdge(this);
//         flipped = !flipped;
//     }
// 
//     public void lock() {
//         locked = true;
//     }
// 
//     public boolean isLocked() {
//         return locked;
//     }
// }
// 
// Path: src/main/java/de/jfschaefer/layeredgraphlayout/Node.java
// public class Node<V, E> {
//     protected V originalNode;
//     protected double width, height;
//     protected Set<Edge<V, E>> outgoingEdges;
//     protected Set<Edge<V, E>> ingoingEdges;
// 
//     public Node(V original, double width, double height) {
//         originalNode = original;
//         this.width = width;
//         this.height = height;
//         outgoingEdges = new HashSet<Edge<V, E>>();
//         ingoingEdges = new HashSet<Edge<V, E>>();
//     }
// 
//     void addIngoingEdge(Edge<V, E> edge) {
//         ingoingEdges.add(edge);
//     }
// 
//     void addOutgoingEdge(Edge<V, E> edge) {
//         outgoingEdges.add(edge);
//     }
// 
//     public void reverseIngoingEdge(Edge<V, E> edge) {
//         assert ingoingEdges.contains(edge);
//         ingoingEdges.remove(edge);
//         outgoingEdges.add(edge);
//     }
// 
//     public void reverseOutgoingEdge(Edge<V, E> edge) {
//         assert outgoingEdges.contains(edge);
//         outgoingEdges.remove(edge);
//         ingoingEdges.add(edge);
//     }
// 
//     public final Set<Edge<V, E>> getOutgoingEdges() {
//         return outgoingEdges;
//     }
// 
//     public final Set<Edge<V, E>> getIngoingEdges() {
//         return ingoingEdges;
//     }
// 
//     public boolean isSink() {
//         return outgoingEdges.isEmpty();
//     }
// 
//     public boolean isSource() {
//         return ingoingEdges.isEmpty();
//     }
// 
//     public boolean isSinkIn(Collection<Node<V, E>> subset) {
//         for (Edge<V, E> edge : outgoingEdges) {
//             if (subset.contains(edge.getTo())) {
//                 return false;
//             }
//         }
//         return true;
//     }
// 
//     public boolean isSourceIn(Collection<Node<V, E>> subset) {
//         for (Edge<V, E> edge : ingoingEdges) {
//             if (subset.contains(edge.getFrom())) {
//                 return false;
//             }
//         }
//         return true;
//     }
// 
//     public int inDegree() {
//         return ingoingEdges.size();
//     }
// 
//     public int outDegree() {
//         return outgoingEdges.size();
//     }
// 
//     public int inDegreeIn(Collection<Node<V, E>> subset) {
//         int indegree = 0;
//         for (Edge<V, E> edge : ingoingEdges) {
//             if (subset.contains(edge.getFrom())) {
//                 indegree ++;
//             }
//         }
//         return indegree;
//     }
// 
//     public int outDegreeIn(Collection<Node<V, E>> subset) {
//         int outdegree = 0;
//         for (Edge<V, E> edge : outgoingEdges) {
//             if (subset.contains(edge.getTo())) {
//                 outdegree ++;
//             }
//         }
//         return outdegree;
//     }
// 
//     public double getWidth() {
//         return width;
//     }
// 
//     public double getHeight() {
//         return height;
//     }
// 
//     public V getOriginalNode() {
//         return originalNode;
//     }
// }
// 
// Path: src/main/java/de/jfschaefer/layeredgraphlayout/util/Pair.java
// public class Pair<A, B> {
//     public final A first;
//     public final B second;
//     public Pair(A first, B second) {
//         this.first = first;
//         this.second = second;
//     }
// }


// Path: src/test/java/de/jfschaefer/layeredgraphlayout/lgraph/LGraphTest.java
import de.jfschaefer.layeredgraphlayout.Edge;
import de.jfschaefer.layeredgraphlayout.Node;
import de.jfschaefer.layeredgraphlayout.util.Pair;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import java.util.ArrayList;

package de.jfschaefer.layeredgraphlayout.lgraph;



/**
 * Created by jfschaefer on 8/12/15.
 */

public class LGraphTest extends TestCase {
    public LGraphTest(String testName) {
        super(testName);
    }

    public static Test suite() {
        return new TestSuite(LGraphTest.class);
    }

    public void testIntersectionCounting() {
        LGraph<String, String> lgraph = new LGraph<String, String>(new LGraphConfig());
        String a1 = "Hello";
        String a2 = "World";
        String b1 = "Welcome";
        String b2 = "Home";
        String e1 = "Hello Home";
        String e2 = "World Welcome";

        Node<String, String> na1 = new Node<String, String>(a1, 100, 20);