All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fasterxml.jackson.databind.deser.DataFormatReaders Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 35.0.0.Beta1
Show newest version
package com.fasterxml.jackson.databind.deser;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.format.*;
import com.fasterxml.jackson.core.io.MergedStream;

import com.fasterxml.jackson.databind.*;

/**
 * Alternative to {@link DataFormatDetector} that needs to be used when
 * using data-binding.
 * 
 * @since 2.1
 */
public class DataFormatReaders
{
    /**
     * By default we will look ahead at most 64 bytes; in most cases,
     * much less (4 bytes or so) is needed, but we will allow bit more
     * leniency to support data formats that need more complex heuristics.
     */
    public final static int DEFAULT_MAX_INPUT_LOOKAHEAD = 64;
    
    /**
     * Ordered list of readers which both represent data formats to
     * detect (in precedence order, starting with highest) and contain
     * factories used for actual detection.
     */
    protected final ObjectReader[] _readers;

    /**
     * Strength of match we consider to be good enough to be used
     * without checking any other formats.
     * Default value is {@link MatchStrength#SOLID_MATCH}, 
     */
    protected final MatchStrength _optimalMatch;

    /**
     * Strength of minimal match we accept as the answer, unless
     * better matches are found. 
     * Default value is {@link MatchStrength#WEAK_MATCH}, 
     */
    protected final MatchStrength _minimalMatch;

    /**
     * Maximum number of leading bytes of the input that we can read
     * to determine data format.
     *

* Default value is {@link #DEFAULT_MAX_INPUT_LOOKAHEAD}. */ protected final int _maxInputLookahead; /* /********************************************************** /* Construction /********************************************************** */ public DataFormatReaders(ObjectReader... detectors) { this(detectors, MatchStrength.SOLID_MATCH, MatchStrength.WEAK_MATCH, DEFAULT_MAX_INPUT_LOOKAHEAD); } public DataFormatReaders(Collection detectors) { this(detectors.toArray(new ObjectReader[detectors.size()])); } private DataFormatReaders(ObjectReader[] detectors, MatchStrength optMatch, MatchStrength minMatch, int maxInputLookahead) { _readers = detectors; _optimalMatch = optMatch; _minimalMatch = minMatch; _maxInputLookahead = maxInputLookahead; } /* /********************************************************** /* Fluent factories for changing match settings /********************************************************** */ public DataFormatReaders withOptimalMatch(MatchStrength optMatch) { if (optMatch == _optimalMatch) { return this; } return new DataFormatReaders(_readers, optMatch, _minimalMatch, _maxInputLookahead); } public DataFormatReaders withMinimalMatch(MatchStrength minMatch) { if (minMatch == _minimalMatch) { return this; } return new DataFormatReaders(_readers, _optimalMatch, minMatch, _maxInputLookahead); } public DataFormatReaders with(ObjectReader[] readers) { return new DataFormatReaders(readers, _optimalMatch, _minimalMatch, _maxInputLookahead); } public DataFormatReaders withMaxInputLookahead(int lookaheadBytes) { if (lookaheadBytes == _maxInputLookahead) { return this; } return new DataFormatReaders(_readers, _optimalMatch, _minimalMatch, lookaheadBytes); } /* /********************************************************** /* Fluent factories for changing underlying readers /********************************************************** */ public DataFormatReaders with(DeserializationConfig config) { final int len = _readers.length; ObjectReader[] r = new ObjectReader[len]; for (int i = 0; i < len; ++i) { r[i] = _readers[i].with(config); } return new DataFormatReaders(r, _optimalMatch, _minimalMatch, _maxInputLookahead); } public DataFormatReaders withType(JavaType type) { final int len = _readers.length; ObjectReader[] r = new ObjectReader[len]; for (int i = 0; i < len; ++i) { r[i] = _readers[i].forType(type); } return new DataFormatReaders(r, _optimalMatch, _minimalMatch, _maxInputLookahead); } /* /********************************************************** /* Public API /********************************************************** */ /** * Method to call to find format that content (accessible via given * {@link InputStream}) given has, as per configuration of this detector * instance. * * @return Matcher object which contains result; never null, even in cases * where no match (with specified minimal match strength) is found. */ public Match findFormat(InputStream in) throws IOException { return _findFormat(new AccessorForReader(in, new byte[_maxInputLookahead])); } /** * Method to call to find format that given content (full document) * has, as per configuration of this detector instance. * * @return Matcher object which contains result; never null, even in cases * where no match (with specified minimal match strength) is found. */ public Match findFormat(byte[] fullInputData) throws IOException { return _findFormat(new AccessorForReader(fullInputData)); } /** * Method to call to find format that given content (full document) * has, as per configuration of this detector instance. * * @return Matcher object which contains result; never null, even in cases * where no match (with specified minimal match strength) is found. * * @since 2.1 */ public Match findFormat(byte[] fullInputData, int offset, int len) throws IOException { return _findFormat(new AccessorForReader(fullInputData, offset, len)); } /* /********************************************************** /* Overrides /********************************************************** */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('['); final int len = _readers.length; if (len > 0) { sb.append(_readers[0].getFactory().getFormatName()); for (int i = 1; i < len; ++i) { sb.append(", "); sb.append(_readers[i].getFactory().getFormatName()); } } sb.append(']'); return sb.toString(); } /* /********************************************************** /* Internal methods /********************************************************** */ private Match _findFormat(AccessorForReader acc) throws IOException { ObjectReader bestMatch = null; MatchStrength bestMatchStrength = null; for (ObjectReader f : _readers) { acc.reset(); MatchStrength strength = f.getFactory().hasFormat(acc); // if not better than what we have so far (including minimal level limit), skip if (strength == null || strength.ordinal() < _minimalMatch.ordinal()) { continue; } // also, needs to better match than before if (bestMatch != null) { if (bestMatchStrength.ordinal() >= strength.ordinal()) { continue; } } // finally: if it's good enough match, we are done bestMatch = f; bestMatchStrength = strength; if (strength.ordinal() >= _optimalMatch.ordinal()) { break; } } return acc.createMatcher(bestMatch, bestMatchStrength); } /* /********************************************************** /* Helper classes /********************************************************** */ /** * We need sub-class here as well, to be able to access efficiently. */ protected static class AccessorForReader extends InputAccessor.Std { public AccessorForReader(InputStream in, byte[] buffer) { super(in, buffer); } public AccessorForReader(byte[] inputDocument) { super(inputDocument); } public AccessorForReader(byte[] inputDocument, int start, int len) { super(inputDocument, start, len); } public Match createMatcher(ObjectReader match, MatchStrength matchStrength) { return new Match(_in, _buffer, _bufferedStart, (_bufferedEnd - _bufferedStart), match, matchStrength); } } /** * Result class, similar to {@link DataFormatMatcher} */ public static class Match { protected final InputStream _originalStream; /** * Content read during format matching process */ protected final byte[] _bufferedData; /** * Pointer to the first byte in buffer available for reading */ protected final int _bufferedStart; /** * Number of bytes available in buffer. */ protected final int _bufferedLength; /** * Factory that produced sufficient match (if any) */ protected final ObjectReader _match; /** * Strength of match with {@link #_match} */ protected final MatchStrength _matchStrength; protected Match(InputStream in, byte[] buffered, int bufferedStart, int bufferedLength, ObjectReader match, MatchStrength strength) { _originalStream = in; _bufferedData = buffered; _bufferedStart = bufferedStart; _bufferedLength = bufferedLength; _match = match; _matchStrength = strength; } /* /********************************************************** /* Public API, simple accessors /********************************************************** */ /** * Accessor to use to see if any formats matched well enough with * the input data. */ public boolean hasMatch() { return _match != null; } /** * Method for accessing strength of the match, if any; if no match, * will return {@link MatchStrength#INCONCLUSIVE}. */ public MatchStrength getMatchStrength() { return (_matchStrength == null) ? MatchStrength.INCONCLUSIVE : _matchStrength; } /** * Accessor for {@link JsonFactory} that represents format that data matched. */ public ObjectReader getReader() { return _match; } /** * Accessor for getting brief textual name of matched format if any (null * if none). Equivalent to: *

         *   return hasMatch() ? getMatch().getFormatName() : null;
         *
*/ public String getMatchedFormatName() { return _match.getFactory().getFormatName(); } /* /********************************************************** /* Public API, factory methods /********************************************************** */ /** * Convenience method for trying to construct a {@link JsonParser} for * parsing content which is assumed to be in detected data format. * If no match was found, returns null. */ public JsonParser createParserWithMatch() throws IOException { if (_match == null) { return null; } JsonFactory jf = _match.getFactory(); if (_originalStream == null) { return jf.createParser(_bufferedData, _bufferedStart, _bufferedLength); } return jf.createParser(getDataStream()); } /** * Method to use for accessing input for which format detection has been done. * This must be used instead of using stream passed to detector * unless given stream itself can do buffering. * Stream will return all content that was read during matching process, as well * as remaining contents of the underlying stream. */ public InputStream getDataStream() { if (_originalStream == null) { return new ByteArrayInputStream(_bufferedData, _bufferedStart, _bufferedLength); } return new MergedStream(null, _originalStream, _bufferedData, _bufferedStart, _bufferedLength); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy