content: /*
   * Copyright 2007 ZXing authors
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.ailiwean.core.zxing.core;
  
  
  import com.ailiwean.core.zxing.core.aztec.AztecReader;
  import com.ailiwean.core.zxing.core.datamatrix.DataMatrixReader;
  import com.ailiwean.core.zxing.core.maxicode.MaxiCodeReader;
  import com.ailiwean.core.zxing.core.oned.MultiFormatOneDReader;
  import com.ailiwean.core.zxing.core.pdf417.PDF417Reader;
  import com.ailiwean.core.zxing.core.qrcode.QRCodeReader;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Map;
  
  /**
   * MultiFormatReader is a convenience class and the main entry point into the library for most uses.
   * By default it attempts to decode all barcode formats that the library supports. Optionally, you
   * can provide a hints object to request different behavior, for example only decoding QR codes.
   *
   * @author Sean Owen
   * @author dswitkin@google.com (Daniel Switkin)
   */
  public final class MultiFormatReader implements Reader {
  
    private static final Reader[] EMPTY_READER_ARRAY = new Reader[0];
  
    private Map<DecodeHintType,?> hints;
    private Reader[] readers;
  
    /**
     * This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it
     * passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.
     * Use setHints() followed by decodeWithState() for continuous scan applications.
     *
     * @param image The pixel data to decode
     * @return The contents of the image
     * @throws NotFoundException Any errors which occurred
     */
    @Override
    public Result decode(BinaryBitmap image) throws NotFoundException {
      setHints(null);
      return decodeInternal(image);
    }
  
    /**
     * Decode an image using the hints provided. Does not honor existing state.
     *
     * @param image The pixel data to decode
     * @param hints The hints to use, clearing the previous state.
     * @return The contents of the image
     * @throws NotFoundException Any errors which occurred
     */
    @Override
    public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints) throws NotFoundException {
      setHints(hints);
      return decodeInternal(image);
    }
  
    /**
     * Decode an image using the state set up by calling setHints() previously. Continuous scan
     * clients will get a <b>large</b> speed increase by using this instead of decode().
     *
     * @param image The pixel data to decode
     * @return The contents of the image
     * @throws NotFoundException Any errors which occurred
     */
    public Result decodeWithState(BinaryBitmap image) throws NotFoundException {
      // Make sure to set up the default state so we don't crash
      if (readers == null) {
        setHints(null);
      }
      return decodeInternal(image);
    }
  
    /**
     * This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
     * to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
     * is important for performance in continuous scan clients.
     *
     * @param hints The set of hints to use for subsequent calls to decode(image)
     */
    public void setHints(Map<DecodeHintType,?> hints) {
      this.hints = hints;
  
      boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
      @SuppressWarnings("unchecked")
      Collection<BarcodeFormat> formats =
          hints == null ? null : (Collection<BarcodeFormat>) hints.get(DecodeHintType.POSSIBLE_FORMATS);
      Collection<Reader> readers = new ArrayList<>();
      if (formats != null) {
        boolean addOneDReader =
            formats.contains(BarcodeFormat.UPC_A) ||
            formats.contains(BarcodeFormat.UPC_E) ||
            formats.contains(BarcodeFormat.EAN_13) ||
            formats.contains(BarcodeFormat.EAN_8) ||
            formats.contains(BarcodeFormat.CODABAR) ||
            formats.contains(BarcodeFormat.CODE_39) ||
            formats.contains(BarcodeFormat.CODE_93) ||
            formats.contains(BarcodeFormat.CODE_128) ||
            formats.contains(BarcodeFormat.ITF) ||
            formats.contains(BarcodeFormat.RSS_14) ||
            formats.contains(BarcodeFormat.RSS_EXPANDED);
        // Put 1D readers upfront in "normal" mode
        if (addOneDReader && !tryHarder) {
          readers.add(new MultiFormatOneDReader(hints));
        }
        if (formats.contains(BarcodeFormat.QR_CODE)) {
          readers.add(new QRCodeReader());
        }
        if (formats.contains(BarcodeFormat.DATA_MATRIX)) {
          readers.add(new DataMatrixReader());
        }
        if (formats.contains(BarcodeFormat.AZTEC)) {
          readers.add(new AztecReader());
        }
        if (formats.contains(BarcodeFormat.PDF_417)) {
           readers.add(new PDF417Reader());
        }
        if (formats.contains(BarcodeFormat.MAXICODE)) {
           readers.add(new MaxiCodeReader());
        }
        // At end in "try harder" mode
        if (addOneDReader && tryHarder) {
          readers.add(new MultiFormatOneDReader(hints));
        }
      }
      if (readers.isEmpty()) {
        if (!tryHarder) {
          readers.add(new MultiFormatOneDReader(hints));
        }
  
        readers.add(new QRCodeReader());
        readers.add(new DataMatrixReader());
        readers.add(new AztecReader());
        readers.add(new PDF417Reader());
        readers.add(new MaxiCodeReader());
  
        if (tryHarder) {
          readers.add(new MultiFormatOneDReader(hints));
        }
      }
      this.readers = readers.toArray(EMPTY_READER_ARRAY);
    }
  
    @Override
    public void reset() {
      if (readers != null) {
        for (Reader reader : readers) {
          reader.reset();
        }
      }
    }
  
    private Result decodeInternal(BinaryBitmap image) throws NotFoundException {
      if (readers != null) {
        for (Reader reader : readers) {
          try {
            return reader.decode(image, hints);
          } catch (ReaderException re) {
            // continue
          }
        }
      }
      throw NotFoundException.getNotFoundInstance();
    }
  
  }
  