// Path: src/main/java/org/laborra/beantrace/handlers/VertexHandler.java
// public interface VertexHandler {
// 
//     /**
//      * Specifies if this handler can manage the subject.
//      */
//     boolean canHandle(Object subject);
// 
//     /**
//      * Handle the passed vertex based on the subject.
//      */
//     void handle(Vertex vertex, Object subject, VertexFieldAdder vertexFieldAdder);
// 
//     class Composite implements VertexHandler {
// 
//         private final List<VertexHandler> delegates;
// 
//         public Composite(List<VertexHandler> delegates) {
//             this.delegates = delegates;
//         }
// 
//         @Override
//         public boolean canHandle(Object subject) {
//             for (VertexHandler vertexHandler : delegates) {
//                 if (vertexHandler.canHandle(subject)) {
//                     return true;
//                 }
//             }
// 
//             return false;
//         }
// 
//         @Override
//         public void handle(Vertex vertex, Object subject, VertexFieldAdder vertexFieldAdder) {
//             for (VertexHandler vertexHandler : delegates) {
//                 if (vertexHandler.canHandle(subject)) {
//                     vertexHandler.handle(vertex, subject, vertexFieldAdder);
//                     return;
//                 }
//             }
//         }
//     }
// 
//     class MapVertexHandler extends TypeBasedHandler<Map<Object, Object>> {
// 
//         public MapVertexHandler() {
//             super(Map.class);
//         }
// 
//         @Override
//         public void typedHandle(Vertex vertex, Map<Object, Object> subject, VertexFieldAdder vertexFieldAdder) {
//             int i = -1;
//             for (Map.Entry<Object, Object> entry : subject.entrySet()) {
//                 i++;
//                 final Object key = entry.getKey();
//                 final Object value = entry.getValue();
//                 final boolean primitiveKey = ReflectUtils.isPrimitive(key.getClass());
// 
//                 if (primitiveKey) {
//                     vertexFieldAdder.addField(vertex, key.toString(), value);
//                 }
// 
//                 if (!primitiveKey) {
//                     final Vertex entryVertex = new Vertex(Map.Entry.class, System.identityHashCode(entry) + "");
//                     vertexFieldAdder.addField(entryVertex, "key", key);
//                     vertexFieldAdder.addField(entryVertex, "value", value);
//                     vertex.getReferences().add(new Edge("entry_" + i, entryVertex));
//                 }
//             }
//         }
//     }
// 
//     class ArrayHandler implements VertexHandler {
// 
//         public boolean canHandle(Object subject) {
//             return subject.getClass().isArray();
//         }
// 
//         public void handle(Vertex vertex, Object subject, VertexFieldAdder vertexFieldAdder) {
//             int arrayLength = Array.getLength(subject);
//             for (int i = 0; i < arrayLength; i++) {
//                 Object item = Array.get(subject, i);
//                 vertexFieldAdder.addField(vertex, i + "", item);
//             }
//         }
//     }
// 
//     class ClassTypeHandler extends TypeBasedHandler<Class> {
// 
//         public ClassTypeHandler() {
//             super(Class.class);
//         }
// 
//         @Override
//         protected void typedHandle(Vertex vertex, Class subject, VertexFieldAdder vertexFieldAdder) {
//             vertexFieldAdder.addField(vertex, "name", subject.getName());
//         }
//     }
// 
// }
// 
// Path: src/main/java/org/laborra/beantrace/renderers/GraphRenderer.java
// public interface GraphRenderer {
//     public void render(Vertex subject);
// }
// 
// Path: src/main/java/org/laborra/beantrace/renderers/GraphRenderers.java
// public class GraphRenderers {
// 
//     /**
//      * Creates a new {@link GraphvizDotRenderer} that writes the contents to the given
//      * appendable.
//      */
//     public static GraphvizDotRenderer newGraphviz(Writer output) {
//         return new GraphvizDotRenderer(output);
//     }
// 
//     /**
//      * Shortcut to create a file graphviz renderer.
//      *
//      * @see #newGraphviz(Writer)
//      */
//     public static GraphvizDotRenderer newGraphviz(File outputFile) {
//         try {
//             return newGraphviz(new BufferedWriter(new FileWriter(outputFile), 1));
//         } catch (IOException e) {
//             throw new BeanTraceException(e);
//         }
//     }
// 
//     /**
//      * Creates a new {@link AsciiRenderer} that prints the graphs to the
//      * standard output.
//      */
//     public static AsciiRenderer newAscii() {
//         return newAscii(new PrintWriter(System.out));
//     }
// 
//     /**
//      * Creates a new {@link AsciiRenderer} that prints
//      * the graph to the given appendable.
//      *
//      * @param output Where to write the graph
//      * @return the create renderer
//      */
//     public static AsciiRenderer newAscii(Writer output) {
//         final AsciiRenderer ret = new AsciiRenderer();
//         ret.getConfig().setOutput(output);
//         return ret;
//     }
// 
//     /**
//      * Shortcut to create an ascii renderer that writes to a file.
//      *
//      * @see #newAscii(Writer)
//      */
//     public static AsciiRenderer newAscii(File outputFile) {
//         try {
//             return newAscii(new BufferedWriter(new FileWriter(outputFile), 1));
//         } catch (IOException e) {
//             throw new BeanTraceException(e);
//         }
//     }
// }


import org.laborra.beantrace.handlers.VertexHandler;
import org.laborra.beantrace.renderers.GraphRenderer;
import org.laborra.beantrace.renderers.GraphRenderers;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
package org.laborra.beantrace;



/**
 * This class represents the bean trace algorithm options.
 */
public class TraceConfiguration {

    /**
     * Default max depth to stop when scanning objects.
     */
    public static final Integer DEFAULT_MAX_DEPTH = 10;

    /**
     * The graph renderer to use.
     */
    private GraphRenderer graphRenderer = GraphRenderers.newAscii();
    private List<VertexHandler> customHandlers = new LinkedList<>();
    private Integer maxDepth = DEFAULT_MAX_DEPTH;
    private Collection<Class> excludedTypes = new LinkedList<>();

    public GraphRenderer getGraphRenderer() {
        return graphRenderer;
    }

// Path: src/main/java/org/laborra/beantrace/handlers/VertexHandler.java
// public interface VertexHandler {
// 
//     /**
//      * Specifies if this handler can manage the subject.
//      */
//     boolean canHandle(Object subject);
// 
//     /**
//      * Handle the passed vertex based on the subject.
//      */
//     void handle(Vertex vertex, Object subject, VertexFieldAdder vertexFieldAdder);
// 
//     class Composite implements VertexHandler {
// 
//         private final List<VertexHandler> delegates;
// 
//         public Composite(List<VertexHandler> delegates) {
//             this.delegates = delegates;
//         }
// 
//         @Override
//         public boolean canHandle(Object subject) {
//             for (VertexHandler vertexHandler : delegates) {
//                 if (vertexHandler.canHandle(subject)) {
//                     return true;
//                 }
//             }
// 
//             return false;
//         }
// 
//         @Override
//         public void handle(Vertex vertex, Object subject, VertexFieldAdder vertexFieldAdder) {
//             for (VertexHandler vertexHandler : delegates) {
//                 if (vertexHandler.canHandle(subject)) {
//                     vertexHandler.handle(vertex, subject, vertexFieldAdder);
//                     return;
//                 }
//             }
//         }
//     }
// 
//     class MapVertexHandler extends TypeBasedHandler<Map<Object, Object>> {
// 
//         public MapVertexHandler() {
//             super(Map.class);
//         }
// 
//         @Override
//         public void typedHandle(Vertex vertex, Map<Object, Object> subject, VertexFieldAdder vertexFieldAdder) {
//             int i = -1;
//             for (Map.Entry<Object, Object> entry : subject.entrySet()) {
//                 i++;
//                 final Object key = entry.getKey();
//                 final Object value = entry.getValue();
//                 final boolean primitiveKey = ReflectUtils.isPrimitive(key.getClass());
// 
//                 if (primitiveKey) {
//                     vertexFieldAdder.addField(vertex, key.toString(), value);
//                 }
// 
//                 if (!primitiveKey) {
//                     final Vertex entryVertex = new Vertex(Map.Entry.class, System.identityHashCode(entry) + "");
//                     vertexFieldAdder.addField(entryVertex, "key", key);
//                     vertexFieldAdder.addField(entryVertex, "value", value);
//                     vertex.getReferences().add(new Edge("entry_" + i, entryVertex));
//                 }
//             }
//         }
//     }
// 
//     class ArrayHandler implements VertexHandler {
// 
//         public boolean canHandle(Object subject) {
//             return subject.getClass().isArray();
//         }
// 
//         public void handle(Vertex vertex, Object subject, VertexFieldAdder vertexFieldAdder) {
//             int arrayLength = Array.getLength(subject);
//             for (int i = 0; i < arrayLength; i++) {
//                 Object item = Array.get(subject, i);
//                 vertexFieldAdder.addField(vertex, i + "", item);
//             }
//         }
//     }
// 
//     class ClassTypeHandler extends TypeBasedHandler<Class> {
// 
//         public ClassTypeHandler() {
//             super(Class.class);
//         }
// 
//         @Override
//         protected void typedHandle(Vertex vertex, Class subject, VertexFieldAdder vertexFieldAdder) {
//             vertexFieldAdder.addField(vertex, "name", subject.getName());
//         }
//     }
// 
// }
// 
// Path: src/main/java/org/laborra/beantrace/renderers/GraphRenderer.java
// public interface GraphRenderer {
//     public void render(Vertex subject);
// }
// 
// Path: src/main/java/org/laborra/beantrace/renderers/GraphRenderers.java
// public class GraphRenderers {
// 
//     /**
//      * Creates a new {@link GraphvizDotRenderer} that writes the contents to the given
//      * appendable.
//      */
//     public static GraphvizDotRenderer newGraphviz(Writer output) {
//         return new GraphvizDotRenderer(output);
//     }
// 
//     /**
//      * Shortcut to create a file graphviz renderer.
//      *
//      * @see #newGraphviz(Writer)
//      */
//     public static GraphvizDotRenderer newGraphviz(File outputFile) {
//         try {
//             return newGraphviz(new BufferedWriter(new FileWriter(outputFile), 1));
//         } catch (IOException e) {
//             throw new BeanTraceException(e);
//         }
//     }
// 
//     /**
//      * Creates a new {@link AsciiRenderer} that prints the graphs to the
//      * standard output.
//      */
//     public static AsciiRenderer newAscii() {
//         return newAscii(new PrintWriter(System.out));
//     }
// 
//     /**
//      * Creates a new {@link AsciiRenderer} that prints
//      * the graph to the given appendable.
//      *
//      * @param output Where to write the graph
//      * @return the create renderer
//      */
//     public static AsciiRenderer newAscii(Writer output) {
//         final AsciiRenderer ret = new AsciiRenderer();
//         ret.getConfig().setOutput(output);
//         return ret;
//     }
// 
//     /**
//      * Shortcut to create an ascii renderer that writes to a file.
//      *
//      * @see #newAscii(Writer)
//      */
//     public static AsciiRenderer newAscii(File outputFile) {
//         try {
//             return newAscii(new BufferedWriter(new FileWriter(outputFile), 1));
//         } catch (IOException e) {
//             throw new BeanTraceException(e);
//         }
//     }
// }


// Path: src/main/java/org/laborra/beantrace/TraceConfiguration.java
import org.laborra.beantrace.handlers.VertexHandler;
import org.laborra.beantrace.renderers.GraphRenderer;
import org.laborra.beantrace.renderers.GraphRenderers;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

package org.laborra.beantrace;



/**
 * This class represents the bean trace algorithm options.
 */
public class TraceConfiguration {

    /**
     * Default max depth to stop when scanning objects.
     */
    public static final Integer DEFAULT_MAX_DEPTH = 10;

    /**
     * The graph renderer to use.
     */
    private GraphRenderer graphRenderer = GraphRenderers.newAscii();
    private List<VertexHandler> customHandlers = new LinkedList<>();
    private Integer maxDepth = DEFAULT_MAX_DEPTH;
    private Collection<Class> excludedTypes = new LinkedList<>();

    public GraphRenderer getGraphRenderer() {
        return graphRenderer;
    }

    public void setGraphRenderer(GraphRenderer graphRenderer) {