
com.gc.iotools.fmt.DetectionStrategy Maven / Gradle / Ivy
package com.gc.iotools.fmt;
/*
* Copyright (c) 2008, 2014 Gabriele Contini. This source code is released
* under the BSD License.
*/
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gc.iotools.fmt.base.Decoder;
import com.gc.iotools.fmt.base.DetectionLibrary;
import com.gc.iotools.fmt.base.FormatEnum;
import com.gc.iotools.fmt.base.FormatId;
import com.gc.iotools.fmt.base.ResettableInputStream;
import com.gc.iotools.fmt.decoders.CompositeDecoder;
import com.gc.iotools.fmt.detect.droid.DroidDetectorImpl;
final class DetectionStrategy {
private class IdentificationResult {
final FormatId[] formats;
final ResettableInputStream resettableIs;
IdentificationResult(final ResettableInputStream resettableIs,
final FormatId[] formats) {
this.resettableIs = resettableIs;
this.formats = formats;
}
}
private static final Logger LOG = LoggerFactory
.getLogger(DroidDetectorImpl.class);
private static FormatId detectFormatStream(
final ResettableInputStream stream,
final DetectionLibrary[] detectors,
final FormatEnum[] enabledFormats) throws IOException {
FormatId detected = new FormatId(FormatEnum.UNKNOWN, null);
final Collection toDetect = new ArrayList(
Arrays.asList(enabledFormats));
if (detectors != null) {
for (int i = 0; (i < detectors.length)
&& FormatEnum.UNKNOWN.equals(detected.format)
&& (toDetect.size() > 0); i++) {
final DetectionLibrary detectionLibrary = detectors[i];
try {
if (isDetectorNeeded(detectionLibrary, toDetect)) {
detected = detectionLibrary.detect(
toDetect.toArray(new FormatEnum[0]), stream);
toDetect.removeAll(Arrays.asList(detectionLibrary
.getDetectedFormats()));
}
} catch (final Exception e) {
LOG.debug("detector [" + detectionLibrary
+ "] threw exception", e);
}
stream.resetToBeginning();
}
}
return detected;
}
private static Map getDecodersMap(
final Decoder[] decoders) {
final Map formatsMap = new HashMap();
if (decoders != null) {
for (final Decoder decoder : decoders) {
formatsMap.put(decoder.getFormat(), decoder);
}
}
return formatsMap;
}
private static boolean isDetectorNeeded(final DetectionLibrary detect,
final Collection toDetect) {
final FormatEnum[] formats = detect.getDetectedFormats();
boolean result = false;
for (int i = 0; (i < formats.length) && (!result); i++) {
result |= toDetect.contains(formats[i]);
}
return result;
}
private final Decoder[] decoders;
private final DetectionLibrary[] detectionLibraries;
private FormatEnum[] enabledFormats;
private final ResettableStreamRASAdapter internalStream;
// recursion disabled by default
private int maxRecursion = 0;
private IdentificationResult result;
public DetectionStrategy(final DetectionLibrary[] detectors,
final Decoder[] decoders, final FormatEnum[] enabledFormats,
final ResettableStreamRASAdapter istream) {
this.internalStream = istream;
this.detectionLibraries = detectors;
this.decoders = decoders;
this.enabledFormats = enabledFormats;
}
private void checkInitialized() throws IOException {
if (this.result == null) {
this.result = identify();
}
}
private Decoder getDecoder(final List formats,
final Map decMap) {
final Decoder decoder;
if (formats.size() > 1) {
final Collection decoderColl = new ArrayList();
for (final FormatId formatId1 : formats) {
final FormatEnum format = formatId1.format;
final Decoder decoder1 = decMap.get(format);
decoderColl.add(decoder1);
}
decoder = new CompositeDecoder(
decoderColl.toArray(new Decoder[0]));
} else {
final FormatEnum format = formats.get(0).format;
decoder = decMap.get(format);
}
return decoder;
}
public FormatId[] getFormats() throws IOException {
checkInitialized();
return this.result.formats;
}
public ResettableInputStream getStream() throws IOException {
checkInitialized();
return this.result.resettableIs;
}
private IdentificationResult identify() throws IOException {
final List formats = new ArrayList();
final Map decMap = getDecodersMap(this.decoders);
FormatId curFormat;
this.internalStream.enable(true);
ResettableInputStream currentStream = this.internalStream;
int recursionLevel = 0;
do {
curFormat = detectFormatStream(currentStream,
this.detectionLibraries, this.enabledFormats);
if ((recursionLevel == 0)
|| !FormatEnum.UNKNOWN.equals(curFormat)) {
formats.add(curFormat);
}
if (!FormatEnum.UNKNOWN.equals(curFormat.format)
&& decMap.containsKey(curFormat.format)) {
final Decoder decoder = getDecoder(formats, decMap);
currentStream = new ResettableStreamWrapper(
this.internalStream, decoder);
}
recursionLevel++;
} while (decMap.containsKey(curFormat.format)
&& (recursionLevel <= this.maxRecursion));
this.internalStream.enable(false);
return new IdentificationResult(currentStream,
formats.toArray(new FormatId[formats.size()]));
}
public void setEnabledFormats(final FormatEnum[] enabledFormats) {
this.enabledFormats = enabledFormats;
this.result = null;
}
public void setMaxRecursion(final int maxRecursion) {
if (this.maxRecursion != maxRecursion) {
this.result = null;
}
this.maxRecursion = maxRecursion;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy