package com.fasterxml.jackson.databind.type; import java.util.ArrayList; import com.fasterxml.jackson.databind.JavaType; /** * Simple helper class used to keep track of 'call stack' for classes being referenced * (as well as unbound variables) * * @since 2.7 */ public final class ClassStack { protected final ClassStack _parent; protected final Class _current; private ArrayList _selfRefs; public ClassStack(Class rootType) { this(null, rootType); } private ClassStack(ClassStack parent, Class curr) { _parent = parent; _current = curr; } /** * @return New stack frame, if addition is ok; null if not */ public ClassStack child(Class cls) { return new ClassStack(this, cls); } /** * Method called to indicate that there is a self-reference from * deeper down in stack pointing into type this stack frame represents. */ public void addSelfReference(ResolvedRecursiveType ref) { if (_selfRefs == null) { _selfRefs = new ArrayList(); } _selfRefs.add(ref); } /** * Method called when type that this stack frame represents is * fully resolved, allowing self-references to be completed * (if there are any) */ public void resolveSelfReferences(JavaType resolved) { if (_selfRefs != null) { for (ResolvedRecursiveType ref : _selfRefs) { ref.setReference(resolved); } } } public ClassStack find(Class cls) { if (_current == cls) return this; for (ClassStack curr = _parent; curr != null; curr = curr._parent) { if (curr._current == cls) { return curr; } } return null; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[ClassStack (self-refs: ") .append((_selfRefs == null) ? "0" : String.valueOf(_selfRefs.size())) .append(')') ; for (ClassStack curr = this; curr != null; curr = curr._parent) { sb.append(' ').append(curr._current.getName()); } sb.append(']'); return sb.toString(); } }