Java tutorial
/* * This file is part of the ZoRa project: http://www.photozora.org. * * ZoRa is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * ZoRa is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ZoRa; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * (c) 2014-2018 Berthold Daum */ package com.bdaum.zoom.lal.internal; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.Field.Store; import org.apache.lucene.document.StringField; import org.apache.lucene.document.TextField; import org.apache.lucene.index.CompositeReader; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.Term; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.Query; import org.apache.lucene.store.AlreadyClosedException; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.store.LockObtainFailedException; import org.apache.lucene.store.SimpleFSDirectory; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; import org.eclipse.osgi.util.NLS; import org.osgi.framework.BundleContext; import com.bdaum.zoom.common.internal.Counter; import com.bdaum.zoom.core.internal.CoreActivator; import com.bdaum.zoom.core.internal.ai.IAiService; import com.bdaum.zoom.core.internal.lire.Algorithm; import com.bdaum.zoom.core.internal.lucene.ParseException; import com.bdaum.zoom.lal.internal.lire.ChainedDocumentBuilder; import com.bdaum.zoom.lal.internal.lire.Lire; import com.bdaum.zoom.lal.internal.lire.TextDocumentBuilder; import net.semanticmetadata.lire.builders.DocumentBuilder; import net.semanticmetadata.lire.builders.GlobalDocumentBuilder; import net.semanticmetadata.lire.imageanalysis.features.GlobalFeature; import net.semanticmetadata.lire.imageanalysis.features.global.ACCID; import net.semanticmetadata.lire.imageanalysis.features.global.AutoColorCorrelogram; import net.semanticmetadata.lire.imageanalysis.features.global.BinaryPatternsPyramid; import net.semanticmetadata.lire.imageanalysis.features.global.CEDD; import net.semanticmetadata.lire.imageanalysis.features.global.ColorLayout; import net.semanticmetadata.lire.imageanalysis.features.global.EdgeHistogram; import net.semanticmetadata.lire.imageanalysis.features.global.FCTH; import net.semanticmetadata.lire.imageanalysis.features.global.FuzzyColorHistogram; import net.semanticmetadata.lire.imageanalysis.features.global.FuzzyOpponentHistogram; import net.semanticmetadata.lire.imageanalysis.features.global.Gabor; import net.semanticmetadata.lire.imageanalysis.features.global.JCD; import net.semanticmetadata.lire.imageanalysis.features.global.JpegCoefficientHistogram; import net.semanticmetadata.lire.imageanalysis.features.global.LocalBinaryPatterns; import net.semanticmetadata.lire.imageanalysis.features.global.LuminanceLayout; import net.semanticmetadata.lire.imageanalysis.features.global.OpponentHistogram; import net.semanticmetadata.lire.imageanalysis.features.global.PHOG; import net.semanticmetadata.lire.imageanalysis.features.global.RotationInvariantLocalBinaryPatterns; import net.semanticmetadata.lire.imageanalysis.features.global.ScalableColor; import net.semanticmetadata.lire.imageanalysis.features.global.SimpleColorHistogram; import net.semanticmetadata.lire.imageanalysis.features.global.Tamura; import net.semanticmetadata.lire.imageanalysis.features.global.centrist.SpatialPyramidCentrist; import net.semanticmetadata.lire.imageanalysis.features.global.joint.JointHistogram; import net.semanticmetadata.lire.imageanalysis.features.global.joint.LocalBinaryPatternsAndOpponent; import net.semanticmetadata.lire.imageanalysis.features.global.joint.RankAndOpponent; import net.semanticmetadata.lire.imageanalysis.features.global.spatialpyramid.SPACC; import net.semanticmetadata.lire.imageanalysis.features.global.spatialpyramid.SPCEDD; import net.semanticmetadata.lire.imageanalysis.features.global.spatialpyramid.SPFCTH; import net.semanticmetadata.lire.imageanalysis.features.global.spatialpyramid.SPJCD; import net.semanticmetadata.lire.imageanalysis.features.global.spatialpyramid.SPLBP; import net.semanticmetadata.lire.searchers.GenericFastImageSearcher; import net.semanticmetadata.lire.searchers.ImageSearchHits; import net.semanticmetadata.lire.searchers.ImageSearcher; @SuppressWarnings("restriction") public class LireActivator extends Plugin { private class IndexWriterEntry { IndexWriter writer; int count; public IndexWriterEntry(IndexWriter indexWriter, int count) { this.writer = indexWriter; this.count = count; } public IndexWriter flushIndexWriter() throws IOException { Directory directory = writer.getDirectory(); try { writer.commit(); } catch (OutOfMemoryError e) { try { writer.close(); } finally { writer = createIndexWriter(directory, false); } } return writer; } } private class IndexReaderEntry { IndexReader currentReader; Map<IndexReader, Counter> readerCounts = new HashMap<IndexReader, Counter>(8); List<IndexReader> obsoleteReaders = new LinkedList<IndexReader>(); public IndexReaderEntry(IndexReader indexReader) { readerCounts.put(currentReader = indexReader, new Counter(1)); } public IndexReader getReader(File indexPath) throws CorruptIndexException, IOException { if (currentReader == null || obsoleteReaders.contains(currentReader)) { readerCounts.put(currentReader = createBaseIndexReader(indexPath), new Counter(1)); return currentReader; } IndexReader newReader = openIfChanged(currentReader); if (newReader != null) { Counter useCount = readerCounts.get(currentReader); if (useCount == null || useCount.equals(0)) { closeIndexReader(currentReader); readerCounts.remove(currentReader); } else obsoleteReaders.add(currentReader); return currentReader = newReader; } Counter useCount = readerCounts.get(currentReader); if (useCount == null) readerCounts.put(currentReader, new Counter(1)); else useCount.increment(); return currentReader; } public void releaseReader(IndexReader indexReader) { Counter useCount = readerCounts.get(indexReader); if (useCount == null) try { closeIndexReader(indexReader); if (currentReader == indexReader) currentReader = null; } catch (IOException e) { // ignore } else if (useCount.bigger(1)) useCount.decrement(); else readerCounts.remove(indexReader); Iterator<IndexReader> it = obsoleteReaders.iterator(); while (it.hasNext()) { IndexReader reader = it.next(); Counter u = readerCounts.get(reader); if (u == null || u.equals(0)) { try { closeIndexReader(reader); if (currentReader == reader) currentReader = null; } catch (IOException e) { // ignore } it.remove(); } } } public void invalidateAllReaders() { obsoleteReaders.addAll(readerCounts.keySet()); } public void releaseAllReaders() { for (IndexReader reader : readerCounts.keySet()) releaseReader(reader); readerCounts.clear(); } } // The plug-in ID public static final String PLUGIN_ID = "com.bdaum.zoom.lireAndLucene"; //$NON-NLS-1$ public static final String FIELD_NAME_FULL_TEXT = "descriptorFullText"; //$NON-NLS-1$ private static LireActivator plugin; private IndexWriter indexWriter; private final Map<File, IndexWriterEntry> indexWriterMap = new HashMap<File, IndexWriterEntry>(8); private final Map<File, IndexReaderEntry> indexReaderMap = new HashMap<File, IndexReaderEntry>(8); private Thread shutdownHook; private StandardAnalyzer analyzer; private Collection<String> textFields; private Collection<String> algorithms; private QueryParser queryParser; private Hashtable<IndexReader, ImageSearcher> searcherMap = new Hashtable<IndexReader, ImageSearcher>(); private Set<String> fieldsToLoad = new HashSet<>(3); @Override public void start(BundleContext context) throws Exception { super.start(context); plugin = this; shutdownHook = new Thread(new Runnable() { public void run() { try { closeIndexWriter(); } catch (IOException e) { // do nothing } } }); Runtime.getRuntime().addShutdownHook(shutdownHook); } public void closeIndexWriter() throws CorruptIndexException, IOException { synchronized (indexWriterMap) { try { if (indexWriter != null) indexWriter.close(); } finally { indexWriter = null; } } } public void closeIndexReader(IndexReader reader) throws IOException { searcherMap.remove(reader); try { if (reader instanceof CompositeReader) for (LeafReaderContext context : ((CompositeReader) reader).leaves()) context.reader().close(); reader.close(); } catch (AlreadyClosedException e) { // do nothing } } public IndexWriter createIndexWriter(Directory dir, boolean create) throws IOException, LockObtainFailedException { IndexWriterConfig config = new IndexWriterConfig(getLuceneAnalyzer()); config.setOpenMode(create ? IndexWriterConfig.OpenMode.CREATE : IndexWriterConfig.OpenMode.APPEND); return new IndexWriter(dir, config); } public StandardAnalyzer getLuceneAnalyzer() { if (analyzer == null) analyzer = new StandardAnalyzer(); return analyzer; } public IndexReader createBaseIndexReader(File indexPath) throws IOException { return DirectoryReader.open(SimpleFSDirectory.open(indexPath.toPath())); } public IndexReader openIfChanged(IndexReader oldReader) throws IOException { if (oldReader instanceof DirectoryReader) return DirectoryReader.openIfChanged((DirectoryReader) oldReader); return null; } public Field createTextSearchField(String fieldName, String value) { return new TextField(fieldName, value, Store.NO); } public Field createDocumentIdentifierField(String identifier) { return new StringField(DocumentBuilder.FIELD_NAME_IDENTIFIER, identifier, Store.YES); } public IndexWriter flushIndexWriter(File indexPath) throws IOException { synchronized (indexWriterMap) { IndexWriterEntry entry = indexWriterMap.get(indexPath); if (entry != null) return entry.flushIndexWriter(); } return null; } public IndexWriter getIndexWriter(File indexPath) throws LockObtainFailedException, IOException { synchronized (indexWriterMap) { IndexWriterEntry entry = indexWriterMap.get(indexPath); if (entry == null) { String[] members = indexPath.list(); IndexWriter writer = createIndexWriter(FSDirectory.open(indexPath.toPath()), members == null || members.length == 0); indexWriterMap.put(indexPath, new IndexWriterEntry(writer, 1)); return writer; } ++entry.count; return entry.writer; } } public void releaseIndexWriter(File indexPath, boolean force) throws CorruptIndexException, IOException { synchronized (indexWriterMap) { IndexWriterEntry entry = indexWriterMap.get(indexPath); if (entry != null) { if (--entry.count <= 0 || force) { try { IndexWriter writer = entry.writer; @SuppressWarnings("resource") Directory directory = writer.getDirectory(); writer.close(); directory.deleteFile("write.lock"); //$NON-NLS-1$ directory.close(); } finally { indexWriterMap.remove(indexPath); } } } } } public IndexReader getIndexReader(File indexPath) throws CorruptIndexException, IOException { synchronized (indexReaderMap) { IndexReaderEntry entry = indexReaderMap.get(indexPath); if (entry == null) { IndexReader indexReader = createBaseIndexReader(indexPath); indexReaderMap.put(indexPath, new IndexReaderEntry(indexReader)); return indexReader; } return entry.getReader(indexPath); } } public void releaseIndexReader(File indexPath, IndexReader indexReader) { synchronized (indexReaderMap) { searcherMap.remove(indexReader); IndexReaderEntry entry = indexReaderMap.get(indexPath); if (entry != null) entry.releaseReader(indexReader); else try { closeIndexReader(indexReader); } catch (IOException e) { // ignore } } } public void releaseAllIndexReadersAndWriters() { for (IndexReaderEntry entry : indexReaderMap.values()) entry.releaseAllReaders(); for (File indexPath : indexWriterMap.keySet()) try { releaseIndexWriter(indexPath, true); } catch (CorruptIndexException e) { logError(NLS.bind(Messages.LireActivator_corrupt_index, indexPath), e); } catch (IOException e) { logError(NLS.bind(Messages.LireActivator_io_error_reading, indexPath), e); } } public void invalidateAllReaders(File indexPath) { synchronized (indexReaderMap) { IndexReaderEntry entry = indexReaderMap.get(indexPath); if (entry != null) entry.invalidateAllReaders(); } } @Override public void stop(BundleContext context) throws Exception { super.stop(context); } public static LireActivator getDefault() { return plugin; } public void logError(String message, Throwable e) { getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, message, e)); } public void logInfo(String message) { getLog().log(new Status(IStatus.INFO, PLUGIN_ID, message)); } public DocumentBuilder constructFullDocumentBuilder() { return constructFullDocumentBuilder(getLuceneTextDocumentBuilder()); } public DocumentBuilder getLuceneTextDocumentBuilder() { return new TextDocumentBuilder(FIELD_NAME_FULL_TEXT, textFields); } @SuppressWarnings("unchecked") public DocumentBuilder constructFullDocumentBuilder(DocumentBuilder... additions) { ChainedDocumentBuilder cdb = new ChainedDocumentBuilder(); boolean mpeg7 = supportsAlgorithm(Lire.MPEG7); if (mpeg7 || supportsAlgorithm(Lire.SCALABLECOLOR) || supportsAlgorithm(Lire.COLORONLY)) cdb.addBuilder(new GlobalDocumentBuilder(ScalableColor.class)); if (mpeg7 || supportsAlgorithm(Lire.COLORLAYOUT)) cdb.addBuilder(new GlobalDocumentBuilder(ColorLayout.class)); if (mpeg7 || supportsAlgorithm(Lire.EDGEHISTOGRAM)) cdb.addBuilder(new GlobalDocumentBuilder(EdgeHistogram.class)); if (mpeg7 || supportsAlgorithm(Lire.CEDD)) cdb.addBuilder(new GlobalDocumentBuilder(CEDD.class)); if (supportsAlgorithm(Lire.FCTH)) cdb.addBuilder(new GlobalDocumentBuilder(FCTH.class)); if (supportsAlgorithm(Lire.TAMURA)) cdb.addBuilder(new GlobalDocumentBuilder(Tamura.class)); if (supportsAlgorithm(Lire.GABOR)) cdb.addBuilder(new GlobalDocumentBuilder(Gabor.class)); if (supportsAlgorithm(Lire.COLORHISTOGRAM)) cdb.addBuilder(new GlobalDocumentBuilder(SimpleColorHistogram.class)); if (supportsAlgorithm(Lire.JCD)) cdb.addBuilder(new GlobalDocumentBuilder(JCD.class)); if (supportsAlgorithm(Lire.JOINTHISTOGRAM)) cdb.addBuilder(new GlobalDocumentBuilder(JointHistogram.class)); if (supportsAlgorithm(Lire.JPEG)) cdb.addBuilder(new GlobalDocumentBuilder(JpegCoefficientHistogram.class)); if (supportsAlgorithm(Lire.LUMINANCE)) cdb.addBuilder(new GlobalDocumentBuilder(LuminanceLayout.class)); if (supportsAlgorithm(Lire.OPPONENTHISTOGRAM)) cdb.addBuilder(new GlobalDocumentBuilder(OpponentHistogram.class)); if (supportsAlgorithm(Lire.PHOG)) cdb.addBuilder(new GlobalDocumentBuilder(PHOG.class)); if (supportsAlgorithm(Lire.AUTOCOLOR)) cdb.addBuilder(new GlobalDocumentBuilder(AutoColorCorrelogram.class)); if (supportsAlgorithm(Lire.ACCID)) cdb.addBuilder(new GlobalDocumentBuilder(ACCID.class)); if (supportsAlgorithm(Lire.BINPATTERNSPYRAMID)) cdb.addBuilder(new GlobalDocumentBuilder(BinaryPatternsPyramid.class)); if (supportsAlgorithm(Lire.FUZZYOPPOHISTOGRAM)) cdb.addBuilder(new GlobalDocumentBuilder(FuzzyOpponentHistogram.class)); if (supportsAlgorithm(Lire.LOCALBINARYPATTERN)) cdb.addBuilder(new GlobalDocumentBuilder(LocalBinaryPatterns.class)); if (supportsAlgorithm(Lire.LOCALBINARYPATTERNOPPO)) cdb.addBuilder(new GlobalDocumentBuilder(LocalBinaryPatternsAndOpponent.class)); if (supportsAlgorithm(Lire.FUZZYCOLORHISTOGRAM)) cdb.addBuilder(new GlobalDocumentBuilder(FuzzyColorHistogram.class)); if (supportsAlgorithm(Lire.RANKOPPONENT)) cdb.addBuilder(new GlobalDocumentBuilder(RankAndOpponent.class)); if (supportsAlgorithm(Lire.ROTINVBINPATTERN)) cdb.addBuilder(new GlobalDocumentBuilder(RotationInvariantLocalBinaryPatterns.class)); if (supportsAlgorithm(Lire.SPACC)) cdb.addBuilder(new GlobalDocumentBuilder(SPACC.class)); if (supportsAlgorithm(Lire.SPATIALPYRAMIDCENTRIST)) cdb.addBuilder(new GlobalDocumentBuilder(SpatialPyramidCentrist.class)); if (supportsAlgorithm(Lire.SPCEDD)) cdb.addBuilder(new GlobalDocumentBuilder(SPCEDD.class)); if (supportsAlgorithm(Lire.SPFCTH)) cdb.addBuilder(new GlobalDocumentBuilder(SPFCTH.class)); if (supportsAlgorithm(Lire.SPJCD)) cdb.addBuilder(new GlobalDocumentBuilder(SPJCD.class)); if (supportsAlgorithm(Lire.SPLBP)) cdb.addBuilder(new GlobalDocumentBuilder(SPLBP.class)); IAiService service = CoreActivator.getDefault().getAiService(); if (service != null) for (Algorithm aiAlgorithm : service.getLireAlgorithms()) if (supportsAlgorithm(aiAlgorithm.getId())) { Class<? extends GlobalFeature> feature = (Class<? extends GlobalFeature>) service .getFeature(aiAlgorithm.getProviderId(), aiAlgorithm); if (feature != null) cdb.addBuilder(new GlobalDocumentBuilder(feature)); } for (DocumentBuilder documentBuilder : additions) cdb.addBuilder(documentBuilder); return cdb; } public boolean supportsAlgorithm(int id) { Algorithm algo = getAlgorithmById(id); return algo == null ? false : algorithms.contains(algo.getName()); } public Algorithm getAlgorithmById(int id) { for (Algorithm algo : getSupportedSimilarityAlgorithms()) if (algo.getId() == id) return algo; return null; } public Algorithm[] getSupportedSimilarityAlgorithms() { if (Lire.SupportedSimilarityAlgorithms == null) Lire.setUpAlgorithms(); return Lire.SupportedSimilarityAlgorithms; } public void setTextFields(Collection<String> textFields) { this.textFields = textFields; } public void setAlgorithms(Collection<String> algo) { algorithms = algo; } public Query parseQuery(String query) throws ParseException { if (queryParser == null) queryParser = new QueryParser(FIELD_NAME_FULL_TEXT, getLuceneAnalyzer()); try { return queryParser.parse(query); } catch (org.apache.lucene.queryparser.classic.ParseException e) { throw new ParseException(e); } } public void deleteDocuments(IndexWriter indexWriter, String assetId) throws IOException { indexWriter.deleteDocuments(new Term(DocumentBuilder.FIELD_NAME_IDENTIFIER, assetId)); } public ImageSearchHits search(IndexReader indexReader, Document document, int method, int maxResults) throws IOException { ImageSearcher imageSearcher = getImageSearcher(indexReader, method, maxResults); if (imageSearcher instanceof GenericFastImageSearcher) { fieldsToLoad.clear(); fieldsToLoad.add(((GenericFastImageSearcher) imageSearcher).getFieldName()); ((GenericFastImageSearcher) imageSearcher).setFieldsToLoad(fieldsToLoad); } return imageSearcher.search(document, indexReader); } private ImageSearcher getImageSearcher(IndexReader indexReader, int method, int maxResults) { ImageSearcher searcher = searcherMap.get(indexReader); if (searcher == null) searcherMap.put(indexReader, searcher = getContentSearcher(method, maxResults)); return searcher; } public ImageSearcher getContentSearcher(int method, int maxResults) { switch (method) { case Lire.SCALABLECOLOR: return new GenericFastImageSearcher(maxResults, ScalableColor.class, false, null, true); case Lire.EDGEHISTOGRAM: return new GenericFastImageSearcher(maxResults, EdgeHistogram.class, false, null, true); case Lire.COLORLAYOUT: return new GenericFastImageSearcher(maxResults, ColorLayout.class, false, null, true); case Lire.COLORONLY: return new GenericFastImageSearcher(maxResults, ScalableColor.class, false, null, true); case Lire.CEDD: return new GenericFastImageSearcher(maxResults, CEDD.class, false, null, true); case Lire.FCTH: return new GenericFastImageSearcher(maxResults, FCTH.class, false, null, true); case Lire.TAMURA: return new GenericFastImageSearcher(maxResults, Tamura.class, false, null, true); case Lire.GABOR: return new GenericFastImageSearcher(maxResults, Gabor.class, false, null, true); case Lire.COLORHISTOGRAM: return new GenericFastImageSearcher(maxResults, SimpleColorHistogram.class, false, null, true); case Lire.JCD: return new GenericFastImageSearcher(maxResults, JCD.class, false, null, true); case Lire.JOINTHISTOGRAM: return new GenericFastImageSearcher(maxResults, JointHistogram.class, false, null, true); case Lire.JPEG: return new GenericFastImageSearcher(maxResults, JpegCoefficientHistogram.class, false, null, true); case Lire.LUMINANCE: return new GenericFastImageSearcher(maxResults, LuminanceLayout.class, false, null, true); case Lire.OPPONENTHISTOGRAM: return new GenericFastImageSearcher(maxResults, OpponentHistogram.class, false, null, true); case Lire.PHOG: return new GenericFastImageSearcher(maxResults, PHOG.class, false, null, true); case Lire.AUTOCOLOR: return new GenericFastImageSearcher(maxResults, AutoColorCorrelogram.class, false, null, true); case Lire.MPEG7: return new GenericFastImageSearcher(maxResults, ColorLayout.class, false, null, true); case Lire.ACCID: return new GenericFastImageSearcher(maxResults, ACCID.class, false, null, true); case Lire.BINPATTERNSPYRAMID: return new GenericFastImageSearcher(maxResults, BinaryPatternsPyramid.class, false, null, true); case Lire.FUZZYOPPOHISTOGRAM: return new GenericFastImageSearcher(maxResults, FuzzyOpponentHistogram.class, false, null, true); case Lire.LOCALBINARYPATTERN: return new GenericFastImageSearcher(maxResults, LocalBinaryPatterns.class, false, null, true); case Lire.FUZZYCOLORHISTOGRAM: return new GenericFastImageSearcher(maxResults, FuzzyColorHistogram.class, false, null, true); case Lire.RANKOPPONENT: return new GenericFastImageSearcher(maxResults, RankAndOpponent.class, false, null, true); case Lire.ROTINVBINPATTERN: return new GenericFastImageSearcher(maxResults, RotationInvariantLocalBinaryPatterns.class, false, null, true); case Lire.SPACC: return new GenericFastImageSearcher(maxResults, SPACC.class, false, null, true); case Lire.SPATIALPYRAMIDCENTRIST: return new GenericFastImageSearcher(maxResults, SpatialPyramidCentrist.class, false, null, true); case Lire.SPCEDD: return new GenericFastImageSearcher(maxResults, SPCEDD.class, false, null, true); case Lire.SPFCTH: return new GenericFastImageSearcher(maxResults, SPFCTH.class, false, null, true); case Lire.SPJCD: return new GenericFastImageSearcher(maxResults, SPJCD.class, false, null, true); case Lire.SPLBP: return new GenericFastImageSearcher(maxResults, SPLBP.class, false, null, true); default: IAiService service = CoreActivator.getDefault().getAiService(); if (service != null) for (Algorithm aiAlgorithm : service.getLireAlgorithms()) if (method == aiAlgorithm.getId()) { @SuppressWarnings("unchecked") Class<? extends GlobalFeature> feature = (Class<? extends GlobalFeature>) service .getFeature(aiAlgorithm.getProviderId(), aiAlgorithm); if (feature != null) return new GenericFastImageSearcher(maxResults, feature, false, null, true); } } return null; } public ImageSearchHits search(IndexReader indexReader, BufferedImage image, int method, int maxResults) throws IOException { ImageSearcher imageSearcher = getImageSearcher(indexReader, method, maxResults); return imageSearcher == null ? null : imageSearcher.search(image, indexReader); } }