1 package com.fasterxml.jackson.databind.util; 2 3 import com.fasterxml.jackson.core.*; 4 import com.fasterxml.jackson.core.json.JsonReadContext; 5 6 /** 7 * Implementation of {@link JsonStreamContext} used by {@link TokenBuffer} 8 * to link back to the original context to try to keep location information 9 * consistent between source location and buffered content when it's re-read 10 * from the buffer. 11 * 12 * @since 2.9 13 */ 14 public class TokenBufferReadContext extends JsonStreamContext 15 { 16 protected final JsonStreamContext _parent; 17 18 protected final JsonLocation _startLocation; 19 20 // Benefit for reusing? 21 // protected JsonReadContext _child; 22 23 /* 24 /********************************************************** 25 /* Location/state information (minus source reference) 26 /********************************************************** 27 */ 28 29 protected String _currentName; 30 31 protected Object _currentValue; 32 TokenBufferReadContext(JsonStreamContext base, Object srcRef)33 protected TokenBufferReadContext(JsonStreamContext base, Object srcRef) { 34 super(base); 35 _parent = base.getParent(); 36 _currentName = base.getCurrentName(); 37 _currentValue = base.getCurrentValue(); 38 if (base instanceof JsonReadContext) { 39 JsonReadContext rc = (JsonReadContext) base; 40 _startLocation = rc.getStartLocation(srcRef); 41 } else { 42 _startLocation = JsonLocation.NA; 43 } 44 } 45 TokenBufferReadContext(JsonStreamContext base, JsonLocation startLoc)46 protected TokenBufferReadContext(JsonStreamContext base, JsonLocation startLoc) { 47 super(base); 48 _parent = base.getParent(); 49 _currentName = base.getCurrentName(); 50 _currentValue = base.getCurrentValue(); 51 _startLocation = startLoc; 52 } 53 54 /** 55 * Constructor for case where there is no real surrounding context: just create 56 * virtual ROOT 57 */ TokenBufferReadContext()58 protected TokenBufferReadContext() { 59 super(TYPE_ROOT, -1); 60 _parent = null; 61 _startLocation = JsonLocation.NA; 62 } 63 TokenBufferReadContext(TokenBufferReadContext parent, int type, int index)64 protected TokenBufferReadContext(TokenBufferReadContext parent, int type, int index) { 65 super(type, index); 66 _parent = parent; 67 _startLocation = parent._startLocation; 68 } 69 70 @Override getCurrentValue()71 public Object getCurrentValue() { 72 return _currentValue; 73 } 74 75 @Override setCurrentValue(Object v)76 public void setCurrentValue(Object v) { 77 _currentValue = v; 78 } 79 80 /* 81 /********************************************************** 82 /* Factory methods 83 /********************************************************** 84 */ 85 createRootContext(JsonStreamContext origContext)86 public static TokenBufferReadContext createRootContext(JsonStreamContext origContext) { 87 // First: possible to have no current context; if so, just create bogus ROOT context 88 if (origContext == null) { 89 return new TokenBufferReadContext(); 90 } 91 return new TokenBufferReadContext(origContext, null); 92 } 93 createChildArrayContext()94 public TokenBufferReadContext createChildArrayContext() { 95 // For current context there will be one next Array value, first: 96 ++_index; 97 return new TokenBufferReadContext(this, TYPE_ARRAY, -1); 98 } 99 createChildObjectContext()100 public TokenBufferReadContext createChildObjectContext() { 101 // For current context there will be one next Object value, first: 102 ++_index; 103 return new TokenBufferReadContext(this, TYPE_OBJECT, -1); 104 } 105 106 /** 107 * Helper method we need to handle discontinuity between "real" contexts buffer 108 * creates, and ones from parent: problem being they are of different types. 109 */ parentOrCopy()110 public TokenBufferReadContext parentOrCopy() { 111 // 30-Apr-2017, tatu: This is bit awkward since part on ancestor stack is of different 112 // type (usually `JsonReadContext`)... and so for unbalanced buffers (with extra 113 // END_OBJECT / END_ARRAY), we may need to create 114 if (_parent instanceof TokenBufferReadContext) { 115 return (TokenBufferReadContext) _parent; 116 } 117 if (_parent == null) { // unlikely, but just in case let's support 118 return new TokenBufferReadContext(); 119 } 120 return new TokenBufferReadContext(_parent, _startLocation); 121 } 122 123 /* 124 /********************************************************** 125 /* Abstract method implementation 126 /********************************************************** 127 */ 128 getCurrentName()129 @Override public String getCurrentName() { return _currentName; } 130 131 // @since 2.9 hasCurrentName()132 @Override public boolean hasCurrentName() { return _currentName != null; } 133 getParent()134 @Override public JsonStreamContext getParent() { return _parent; } 135 setCurrentName(String name)136 public void setCurrentName(String name) throws JsonProcessingException { 137 _currentName = name; 138 } 139 140 /* 141 /********************************************************** 142 /* Extended support for context updates 143 /********************************************************** 144 */ 145 146 /** 147 * @since 2.10.1 148 */ updateForValue()149 public void updateForValue() { 150 ++_index; 151 } 152 } 153