/* Jackson JSON-processor.
 *
 * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi
 */

package com.fasterxml.jackson.core;

import java.nio.charset.Charset;

Object that encapsulates Location information used for reporting parsing (or potentially generation) errors, as well as current location within input streams.
/** * Object that encapsulates Location information used for reporting * parsing (or potentially generation) errors, as well as current location * within input streams. */
public class JsonLocation implements java.io.Serializable { private static final long serialVersionUID = 1L;
Include at most first 500 characters/bytes from contents; should be enough to give context, but not cause unfortunate side effects in things like logs.
Since:2.9
/** * Include at most first 500 characters/bytes from contents; should be enough * to give context, but not cause unfortunate side effects in things like * logs. * * @since 2.9 */
public static final int MAX_CONTENT_SNIPPET = 500;
Shared immutable "N/A location" that can be returned to indicate that no location information is available.

NOTE: before 2.9, Location was given as String "N/A"; with 2.9 it was removed so that source should be indicated as "UNKNOWN".

/** * Shared immutable "N/A location" that can be returned to indicate * that no location information is available. *<p> * NOTE: before 2.9, Location was given as String "N/A"; with 2.9 it was * removed so that source should be indicated as "UNKNOWN". */
public final static JsonLocation NA = new JsonLocation(null, -1L, -1L, -1, -1); protected final long _totalBytes; protected final long _totalChars; protected final int _lineNr; protected final int _columnNr;
Displayable description for input source: file path, URL.

NOTE: transient since 2.2 so that Location itself is Serializable.

/** * Displayable description for input source: file path, URL. *<p> * NOTE: <code>transient</code> since 2.2 so that Location itself is Serializable. */
final transient Object _sourceRef; public JsonLocation(Object srcRef, long totalChars, int lineNr, int colNr) { /* Unfortunately, none of legal encodings are straight single-byte * encodings. Could determine offset for UTF-16/UTF-32, but the * most important one is UTF-8... * so for now, we'll just not report any real byte count */ this(srcRef, -1L, totalChars, lineNr, colNr); } public JsonLocation(Object sourceRef, long totalBytes, long totalChars, int lineNr, int columnNr) { _sourceRef = sourceRef; _totalBytes = totalBytes; _totalChars = totalChars; _lineNr = lineNr; _columnNr = columnNr; }
Reference to the original resource being read, if one available. For example, when a parser has been constructed by passing a File instance, this method would return that File. Will return null if no such reference is available, for example when InputStream was used to construct the parser instance.
Returns:Source reference this location was constructed with, if any; null if none
/** * Reference to the original resource being read, if one available. * For example, when a parser has been constructed by passing * a {@link java.io.File} instance, this method would return * that File. Will return null if no such reference is available, * for example when {@link java.io.InputStream} was used to * construct the parser instance. * * @return Source reference this location was constructed with, if any; {@code null} if none */
public Object getSourceRef() { return _sourceRef; }
Returns:Line number of the location (1-based)
/** * @return Line number of the location (1-based) */
public int getLineNr() { return _lineNr; }
Returns:Column number of the location (1-based)
/** * @return Column number of the location (1-based) */
public int getColumnNr() { return _columnNr; }
Returns:Character offset within underlying stream, reader or writer, if available; -1 if not.
/** * @return Character offset within underlying stream, reader or writer, * if available; -1 if not. */
public long getCharOffset() { return _totalChars; }
Returns:Byte offset within underlying stream, reader or writer, if available; -1 if not.
/** * @return Byte offset within underlying stream, reader or writer, * if available; -1 if not. */
public long getByteOffset() { return _totalBytes; }
Accessor for getting a textual description of source reference (Object returned by getSourceRef()), as included in description returned by toString().

NOTE: not added as a "getter" to prevent it from getting serialized.

Returns:Description of the source reference (see getSourceRef()
Since:2.9
/** * Accessor for getting a textual description of source reference * (Object returned by {@link #getSourceRef()}), as included in * description returned by {@link #toString()}. *<p> * NOTE: not added as a "getter" to prevent it from getting serialized. * * @return Description of the source reference (see {@link #getSourceRef()} * * @since 2.9 */
public String sourceDescription() { return _appendSourceDesc(new StringBuilder(100)).toString(); } /* /********************************************************** /* Std method overrides /********************************************************** */ @Override public int hashCode() { int hash = (_sourceRef == null) ? 1 : _sourceRef.hashCode(); hash ^= _lineNr; hash += _columnNr; hash ^= (int) _totalChars; hash += (int) _totalBytes; return hash; } @Override public boolean equals(Object other) { if (other == this) return true; if (other == null) return false; if (!(other instanceof JsonLocation)) return false; JsonLocation otherLoc = (JsonLocation) other; if (_sourceRef == null) { if (otherLoc._sourceRef != null) return false; } else if (!_sourceRef.equals(otherLoc._sourceRef)) return false; return (_lineNr == otherLoc._lineNr) && (_columnNr == otherLoc._columnNr) && (_totalChars == otherLoc._totalChars) && (getByteOffset() == otherLoc.getByteOffset()) ; } @Override public String toString() { StringBuilder sb = new StringBuilder(80); sb.append("[Source: "); _appendSourceDesc(sb); sb.append("; line: "); sb.append(_lineNr); sb.append(", column: "); sb.append(_columnNr); sb.append(']'); return sb.toString(); } protected StringBuilder _appendSourceDesc(StringBuilder sb) { final Object srcRef = _sourceRef; if (srcRef == null) { sb.append("UNKNOWN"); return sb; } // First, figure out what name to use as source type Class<?> srcType = (srcRef instanceof Class<?>) ? ((Class<?>) srcRef) : srcRef.getClass(); String tn = srcType.getName(); // standard JDK types without package if (tn.startsWith("java.")) { tn = srcType.getSimpleName(); } else if (srcRef instanceof byte[]) { // then some other special cases tn = "byte[]"; } else if (srcRef instanceof char[]) { tn = "char[]"; } sb.append('(').append(tn).append(')'); // and then, include (part of) contents for selected types: int len; String charStr = " chars"; if (srcRef instanceof CharSequence) { CharSequence cs = (CharSequence) srcRef; len = cs.length(); len -= _append(sb, cs.subSequence(0, Math.min(len, MAX_CONTENT_SNIPPET)).toString()); } else if (srcRef instanceof char[]) { char[] ch = (char[]) srcRef; len = ch.length; len -= _append(sb, new String(ch, 0, Math.min(len, MAX_CONTENT_SNIPPET))); } else if (srcRef instanceof byte[]) { byte[] b = (byte[]) srcRef; int maxLen = Math.min(b.length, MAX_CONTENT_SNIPPET); _append(sb, new String(b, 0, maxLen, Charset.forName("UTF-8"))); len = b.length - maxLen; charStr = " bytes"; } else { len = 0; } if (len > 0) { sb.append("[truncated ").append(len).append(charStr).append(']'); } return sb; } private int _append(StringBuilder sb, String content) { sb.append('"').append(content).append('"'); return content.length(); } }