public enum Direction {
    UNI_DIRECTIONAL, BI_DIRECTIONAL
} public class DomainObject {

    public final String packageName;
    public final String className;
    public final String description;

    public DomainObject(String packageName, String className, String description) {
        this.packageName = packageName;
        this.className = className;
        this.description = description;
    }

    public DomainObject(Class<?> clazz, String description) {
        this(clazz.getPackage().getName(), clazz.getSimpleName(), description);
    }

    public DomainObject(Class<?> clazz) {
        this(clazz, null);
    }

    public String getPackageName() {
        return packageName;
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj);
    }

    @Override
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
} public class Edge {

    public final DomainObject source;
    public final DomainObject target;
    public final EdgeType type;
    public final Direction direction;

    public Edge(DomainObject source, DomainObject target, EdgeType type, Direction direction) {
        this.source = source;
        this.target = target;
        this.type = type;
        this.direction = direction;
    }

    public Edge(DomainObject source, DomainObject target, EdgeType type) {
        this(source, target, type, null);
    }

    @Override
    public final int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public final boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj);
    }

    @Override
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
} public enum EdgeType {

    ONE_TO_ONE, MANY_TO_ONE, MANY_TO_MANY, ONE_TO_MANY, EXTENDS, INNER_CLASS;

    public static EdgeType resolveEdgeType(EdgeType source, EdgeType target) {
        if (source.equals(target)) {
            switch (source) {
                case ONE_TO_ONE:
                case MANY_TO_MANY:
                    return source;
                case MANY_TO_ONE:
                case ONE_TO_MANY:
                    return MANY_TO_MANY;
                case EXTENDS:
                case INNER_CLASS:
                    throw new RuntimeException("impossible");
            }
        }
        if (source.equals(ONE_TO_ONE)) {
            return target;
        } else if (target.equals(ONE_TO_ONE)) {
            return source;
        }
        throw new RuntimeException("impossible");
    }

} public class Child {
    Mother mommy;
} public class Husband {
    Wife wife;
} public class Mother {
    List<Child> childs;
    Child favorite;
} public class Wife {
    private Husband husband;
} public class DoubleReferer {
    private Manager myBoss;
    private Manager myTeamManager;
} public class Manager extends Person {
    private final String name;

    public Manager(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
} public class Person {
    private Company company;
    private List<PhoneNumber> contactNumbers;
} public class Outer {

    public class Inner {
    }
}
import com.nitorcreations.domain.Direction;
import com.nitorcreations.domain.DomainObject;
import com.nitorcreations.domain.Edge;
import com.nitorcreations.domain.EdgeType;
import com.nitorcreations.testdomain.*;
import com.nitorcreations.testdomain.family.Child;
import com.nitorcreations.testdomain.family.Husband;
import com.nitorcreations.testdomain.family.Mother;
import com.nitorcreations.testdomain.family.Wife;
import com.nitorcreations.testdomain.person.DoubleReferer;
import com.nitorcreations.testdomain.person.Manager;
import com.nitorcreations.testdomain.person.Person;
import com.nitorcreations.testdomain.weirdos.Outer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
package com.nitorcreations.scanners;




public class FieldScannerTest {

    private final Edge firstReference = createReference(
            DoubleReferer.class, "myBoss", Manager.class, null, EdgeType.ONE_TO_ONE, Direction.UNI_DIRECTIONAL);
    private final Edge secondReference = createReference(
            DoubleReferer.class, "myTeamManager", Manager.class, null, EdgeType.ONE_TO_ONE, Direction.UNI_DIRECTIONAL);

    private final Edge motherToChilds = createReference(
            Mother.class, "childs", Child.class, "mommy", EdgeType.ONE_TO_MANY, Direction.BI_DIRECTIONAL);
    private final Edge motherToFavorite = createReference(
            Mother.class, "favorite", Child.class, "mommy", EdgeType.ONE_TO_ONE, Direction.BI_DIRECTIONAL);

    private final Edge selfReference = createReference(
            Selfie.class, "me", Selfie.class, null, EdgeType.ONE_TO_ONE, Direction.UNI_DIRECTIONAL);

    private final Edge phoneNumbersReference = createReference(
            Person.class, "contactNumbers", PhoneNumber.class, null, EdgeType.ONE_TO_MANY, Direction.UNI_DIRECTIONAL);

    private final Edge companyPersonReferences = createReference(
            Company.class, "employees", Person.class, "company", EdgeType.ONE_TO_MANY, Direction.BI_DIRECTIONAL);

    private final Edge marriageReference = createReference(
            Husband.class, "wife", Wife.class, "husband", EdgeType.ONE_TO_ONE, Direction.BI_DIRECTIONAL);