// Path: src/main/java/org/laborra/beantrace/model/Attribute.java
// public class Attribute<T> {
//     private String name;
//     private T value;
// 
//     public Attribute(String name, T value) {
//         this.name = name;
//         this.value = value;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public T getValue() {
//         return value;
//     }
// }
// 
// Path: src/main/java/org/laborra/beantrace/model/Vertex.java
// public class Vertex {
//     private Class<?> clazz;
//     private String id;
//     private Set<Edge> references = new HashSet<>();
//     private Set<Attribute> attributes = new HashSet<>();
// 
//     public Vertex(Class<?> clazz, String id) {
//         this(clazz, id, new HashSet<Edge>(), new HashSet<Attribute>());
//     }
// 
//     public Vertex(Class<?> clazz, String id, Set<Edge> references, Set<Attribute> attributes) {
//         this.id = id;
//         this.clazz = clazz;
//         this.references = references;
//         this.attributes = attributes;
//     }
// 
//     public Set<Edge> getReferences() {
//         return references;
//     }
// 
//     public Set<Attribute> getAttributes() {
//         return attributes;
//     }
// 
//     public Class<?> getClazz() {
//         return clazz;
//     }
// 
//     public String getId() {
//         return id;
//     }
// }


import org.laborra.beantrace.model.Attribute;
import org.laborra.beantrace.model.Vertex;
package org.laborra.beantrace.internal;


/**
 * This decorator implements the stop-on-depth logic.
 *
 * @see org.laborra.beantrace.TraceConfiguration#maxDepth
 */
public class MaxDepthVertexFactoryDecorator implements VertexFactory {

    private final Integer maxDepth;
    private final VertexFactory delegate;

    private Integer depth = 1;

    public MaxDepthVertexFactoryDecorator(Integer maxDepth, VertexFactory delegate) {
        this.maxDepth = maxDepth;
        this.delegate = delegate;
    }

    @Override
    public Vertex create(Object subject) {
        if (depth >= maxDepth) {
            return makeProxy(subject);
        }
        try {
            depth++;
            return delegate.create(subject);
        } finally {
            depth--;
        }
    }

    private Vertex makeProxy(Object subject) {
        final Vertex ret = new Vertex(
                subject.getClass(),
                System.identityHashCode(subject) + ""
        );

// Path: src/main/java/org/laborra/beantrace/model/Attribute.java
// public class Attribute<T> {
//     private String name;
//     private T value;
// 
//     public Attribute(String name, T value) {
//         this.name = name;
//         this.value = value;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public T getValue() {
//         return value;
//     }
// }
// 
// Path: src/main/java/org/laborra/beantrace/model/Vertex.java
// public class Vertex {
//     private Class<?> clazz;
//     private String id;
//     private Set<Edge> references = new HashSet<>();
//     private Set<Attribute> attributes = new HashSet<>();
// 
//     public Vertex(Class<?> clazz, String id) {
//         this(clazz, id, new HashSet<Edge>(), new HashSet<Attribute>());
//     }
// 
//     public Vertex(Class<?> clazz, String id, Set<Edge> references, Set<Attribute> attributes) {
//         this.id = id;
//         this.clazz = clazz;
//         this.references = references;
//         this.attributes = attributes;
//     }
// 
//     public Set<Edge> getReferences() {
//         return references;
//     }
// 
//     public Set<Attribute> getAttributes() {
//         return attributes;
//     }
// 
//     public Class<?> getClazz() {
//         return clazz;
//     }
// 
//     public String getId() {
//         return id;
//     }
// }


// Path: src/main/java/org/laborra/beantrace/internal/MaxDepthVertexFactoryDecorator.java
import org.laborra.beantrace.model.Attribute;
import org.laborra.beantrace.model.Vertex;

package org.laborra.beantrace.internal;


/**
 * This decorator implements the stop-on-depth logic.
 *
 * @see org.laborra.beantrace.TraceConfiguration#maxDepth
 */
public class MaxDepthVertexFactoryDecorator implements VertexFactory {

    private final Integer maxDepth;
    private final VertexFactory delegate;

    private Integer depth = 1;

    public MaxDepthVertexFactoryDecorator(Integer maxDepth, VertexFactory delegate) {
        this.maxDepth = maxDepth;
        this.delegate = delegate;
    }

    @Override
    public Vertex create(Object subject) {
        if (depth >= maxDepth) {
            return makeProxy(subject);
        }
        try {
            depth++;
            return delegate.create(subject);
        } finally {
            depth--;
        }
    }

    private Vertex makeProxy(Object subject) {
        final Vertex ret = new Vertex(
                subject.getClass(),
                System.identityHashCode(subject) + ""
        );

        ret.getAttributes().add(new Attribute<>("...", "..."));