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

com.fasterxml.jackson.core.format.DataFormatDetector Maven / Gradle / Ivy

There is a newer version: 2.17.0
Show newest version
package com.fasterxml.jackson.core.format;

import java.io.*;
import java.util.*;

import com.fasterxml.jackson.core.*;

/**
 * Simple helper class that allows data format (content type) auto-detection,
 * given an ordered set of {@link JsonFactory} instances to use for actual low-level
 * detection.
 */
public class DataFormatDetector
{
    /**
     * 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 factories which both represent data formats to
     * detect (in precedence order, starting with highest) and are used
     * for actual detection.
     */
    protected final JsonFactory[] _detectors;

    /**
     * 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 DataFormatDetector(JsonFactory... detectors) { this(detectors, MatchStrength.SOLID_MATCH, MatchStrength.WEAK_MATCH, DEFAULT_MAX_INPUT_LOOKAHEAD); } public DataFormatDetector(Collection detectors) { this(detectors.toArray(new JsonFactory[detectors.size()])); } /** * Method that will return a detector instance that uses given * optimal match level (match that is considered sufficient to return, without * trying to find stronger matches with other formats). */ public DataFormatDetector withOptimalMatch(MatchStrength optMatch) { if (optMatch == _optimalMatch) { return this; } return new DataFormatDetector(_detectors, optMatch, _minimalMatch, _maxInputLookahead); } /** * Method that will return a detector instance that uses given * minimal match level; match that may be returned unless a stronger match * is found with other format detectors. */ public DataFormatDetector withMinimalMatch(MatchStrength minMatch) { if (minMatch == _minimalMatch) { return this; } return new DataFormatDetector(_detectors, _optimalMatch, minMatch, _maxInputLookahead); } /** * Method that will return a detector instance that allows detectors to * read up to specified number of bytes when determining format match strength. */ public DataFormatDetector withMaxInputLookahead(int lookaheadBytes) { if (lookaheadBytes == _maxInputLookahead) { return this; } return new DataFormatDetector(_detectors, _optimalMatch, _minimalMatch, lookaheadBytes); } private DataFormatDetector(JsonFactory[] detectors, MatchStrength optMatch, MatchStrength minMatch, int maxInputLookahead) { _detectors = detectors; _optimalMatch = optMatch; _minimalMatch = minMatch; _maxInputLookahead = 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 DataFormatMatcher findFormat(InputStream in) throws IOException { return _findFormat(new InputAccessor.Std(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 DataFormatMatcher findFormat(byte[] fullInputData) throws IOException { return _findFormat(new InputAccessor.Std(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 DataFormatMatcher findFormat(byte[] fullInputData, int offset, int len) throws IOException { return _findFormat(new InputAccessor.Std(fullInputData, offset, len)); } /* /********************************************************** /* Overrides /********************************************************** */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('['); final int len = _detectors.length; if (len > 0) { sb.append(_detectors[0].getFormatName()); for (int i = 1; i < len; ++i) { sb.append(", "); sb.append(_detectors[i].getFormatName()); } } sb.append(']'); return sb.toString(); } /* /********************************************************** /* Internal methods /********************************************************** */ private DataFormatMatcher _findFormat(InputAccessor.Std acc) throws IOException { JsonFactory bestMatch = null; MatchStrength bestMatchStrength = null; for (JsonFactory f : _detectors) { acc.reset(); MatchStrength strength = f.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); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy