1 package com.fasterxml.jackson.databind.type; 2 3 import java.util.ArrayList; 4 5 import com.fasterxml.jackson.databind.JavaType; 6 7 /** 8 * Simple helper class used to keep track of 'call stack' for classes being referenced 9 * (as well as unbound variables) 10 * 11 * @since 2.7 12 */ 13 public final class ClassStack 14 { 15 protected final ClassStack _parent; 16 protected final Class<?> _current; 17 18 private ArrayList<ResolvedRecursiveType> _selfRefs; 19 ClassStack(Class<?> rootType)20 public ClassStack(Class<?> rootType) { 21 this(null, rootType); 22 } 23 ClassStack(ClassStack parent, Class<?> curr)24 private ClassStack(ClassStack parent, Class<?> curr) { 25 _parent = parent; 26 _current = curr; 27 } 28 29 /** 30 * @return New stack frame, if addition is ok; null if not 31 */ child(Class<?> cls)32 public ClassStack child(Class<?> cls) { 33 return new ClassStack(this, cls); 34 } 35 36 /** 37 * Method called to indicate that there is a self-reference from 38 * deeper down in stack pointing into type this stack frame represents. 39 */ addSelfReference(ResolvedRecursiveType ref)40 public void addSelfReference(ResolvedRecursiveType ref) 41 { 42 if (_selfRefs == null) { 43 _selfRefs = new ArrayList<ResolvedRecursiveType>(); 44 } 45 _selfRefs.add(ref); 46 } 47 48 /** 49 * Method called when type that this stack frame represents is 50 * fully resolved, allowing self-references to be completed 51 * (if there are any) 52 */ resolveSelfReferences(JavaType resolved)53 public void resolveSelfReferences(JavaType resolved) 54 { 55 if (_selfRefs != null) { 56 for (ResolvedRecursiveType ref : _selfRefs) { 57 ref.setReference(resolved); 58 } 59 } 60 } 61 find(Class<?> cls)62 public ClassStack find(Class<?> cls) 63 { 64 if (_current == cls) return this; 65 for (ClassStack curr = _parent; curr != null; curr = curr._parent) { 66 if (curr._current == cls) { 67 return curr; 68 } 69 } 70 return null; 71 } 72 73 @Override toString()74 public String toString() { 75 StringBuilder sb = new StringBuilder(); 76 sb.append("[ClassStack (self-refs: ") 77 .append((_selfRefs == null) ? "0" : String.valueOf(_selfRefs.size())) 78 .append(')') 79 ; 80 for (ClassStack curr = this; curr != null; curr = curr._parent) { 81 sb.append(' ').append(curr._current.getName()); 82 } 83 sb.append(']'); 84 return sb.toString(); 85 } 86 } 87