org.xcmis.search.SearchService.java Source code

Java tutorial

Introduction

Here is the source code for org.xcmis.search.SearchService.java

Source

/*
 * Copyright (C) 2010 eXo Platform SAS.
 * 
 * This is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * 
 * This software 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 Lesser General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
 * site: http://www.fsf.org.
 */
package org.xcmis.search;

import org.apache.commons.lang.Validate;
import org.xcmis.search.config.SearchServiceConfiguration;
import org.xcmis.search.content.ContentEntry;
import org.xcmis.search.content.ContentModificationListener;
import org.xcmis.search.content.IndexModificationException;
import org.xcmis.search.content.command.InvocationContext;
import org.xcmis.search.content.command.index.ModifyIndexCommand;
import org.xcmis.search.content.command.query.ExecuteSelectorCommand;
import org.xcmis.search.content.command.query.ProcessQueryCommand;
import org.xcmis.search.content.interceptors.ContentReaderInterceptor;
import org.xcmis.search.content.interceptors.InterceptorChain;
import org.xcmis.search.content.interceptors.QueryProcessorInterceptor;
import org.xcmis.search.content.interceptors.QueryableIndexStorage;
import org.xcmis.search.model.Query;
import org.xcmis.search.query.QueryExecutionException;
import org.xcmis.search.query.Searcher;
import org.xcmis.search.query.optimize.CriteriaBasedOptimizer;
import org.xcmis.search.query.plan.SimplePlaner;
import org.xcmis.search.result.ScoredRow;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Main entry point to the search service.
 * 
 */
public class SearchService implements Startable, ContentModificationListener, Searcher {

    /**
     * Configuration of search service.
     */
    protected final SearchServiceConfiguration configuration;

    private final InterceptorChain interceptorChain;

    /**
     * Default invocation context.
     */
    private final InvocationContext defaultInvocationContext;

    /**
     * @param configuration
     *           SearchServiceConfiguration
     * @throws SearchServiceException
     */
    public SearchService(SearchServiceConfiguration configuration) throws SearchServiceException {
        Validate.notNull(configuration, "The configuration argument may not be null");
        Validate.notNull(configuration.getContentReader(), "The configuration.getContentReader()  may not be null");
        this.configuration = configuration;
        this.interceptorChain = new InterceptorChain(configuration.getContentReader());
        this.defaultInvocationContext = configuration;

        addQueryableIndexStorageInterceptor(interceptorChain);

        interceptorChain.addBeforeInterceptor(
                new QueryProcessorInterceptor(new SimplePlaner(), new CriteriaBasedOptimizer()),
                QueryableIndexStorage.class);

    }

    /**
     * Execute query.
     * 
     * @param query
     *           Query
     * @return
     * @throws InvalidQueryException
     *            , QueryExecutionException
     */
    @SuppressWarnings("unchecked")
    public List<ScoredRow> execute(Query query) throws InvalidQueryException, QueryExecutionException {
        if (defaultInvocationContext == null) {
            throw new QueryExecutionException("DefaultInvocationContext can't be null");
        }
        return execute(query, Collections.EMPTY_MAP);
    }

    /**
     * Execute query.
     * 
     * @param query
     *           Query
     * @param bindVariablesValues
     *           Map<String, Object>
     * @return List<ScoredRow>
     * @throws InvalidQueryException
     *            , QueryExecutionException
     */
    public List<ScoredRow> execute(Query query, Map<String, Object> bindVariablesValues)
            throws InvalidQueryException, QueryExecutionException {
        if (defaultInvocationContext == null) {
            throw new QueryExecutionException("DefaultInvocationContext can't be null");
        }
        return execute(query, bindVariablesValues, defaultInvocationContext);
    }

    /**
     * @see org.xcmis.search.query.Searcher#execute(org.xcmis.search.model.Query,
     *      java.util.Map, org.xcmis.search.content.command.InvocationContext)
     */
    @SuppressWarnings("unchecked")
    public List<ScoredRow> execute(Query query, Map<String, Object> bindVariablesValues,
            InvocationContext invocationContext) throws InvalidQueryException, QueryExecutionException {
        ProcessQueryCommand processQueryCommand = new ProcessQueryCommand(query, bindVariablesValues);

        try {
            return (List<ScoredRow>) interceptorChain.invoke(invocationContext, processQueryCommand);
        } catch (Throwable e) {
            throw new InvalidQueryException(e.getLocalizedMessage(), e);
        }
    }

    /**
     * @see org.xcmis.search.Startable#start()
     */

    public void start() {
        interceptorChain.start();
    }

    /**
     * @see org.xcmis.search.Startable#stop()
     */
    public void stop() {
        interceptorChain.stop();
    }

    /**
     * @see org.xcmis.search.content.ContentModificationListener#update(org.xcmis.search.content.ContentEntry,
     *      java.lang.String)
     */
    public void update(ContentEntry addedEntry, String removedEntry) throws IndexModificationException {
        List<ContentEntry> addedEntries = new ArrayList<ContentEntry>(1);
        if (addedEntry != null) {
            addedEntries.add(addedEntry);
        }
        Set<String> removedSet = new HashSet<String>(1);
        if (removedEntry != null) {
            removedSet.add(removedEntry);
        }
        update(addedEntries, removedSet);
    }

    /**
     * @see org.xcmis.search.content.ContentModificationListener#update(java.util.List,
     *      java.util.Set)
     */
    public void update(List<ContentEntry> addedEntries, Set<String> removedEntries)
            throws IndexModificationException {
        update(addedEntries, removedEntries, defaultInvocationContext);
    }

    /**
     * @see org.xcmis.search.content.ContentModificationListener#update(java.util.List,
     *      java.util.Set, org.xcmis.search.content.command.InvocationContext)
     */
    public void update(List<ContentEntry> addedEntries, Set<String> removedEntries,
            InvocationContext invocationContext) throws IndexModificationException {
        ModifyIndexCommand modifyIndexCommand = new ModifyIndexCommand(addedEntries, removedEntries);

        try {
            interceptorChain.invoke(invocationContext, modifyIndexCommand);
        } catch (IndexModificationException e) {
            throw e;
        } catch (Throwable e) {
            throw new IndexModificationException(e.getLocalizedMessage(), e);
        }

    }

    /**
     * Add interceptors that handle {@link ModifyIndexCommand} and
     * {@link ExecuteSelectorCommand}
     * 
     * @param interceptorChain
     *           InterceptorChain
     * @throws SearchServiceException
     *            if error occurs
     */
    protected void addQueryableIndexStorageInterceptor(InterceptorChain interceptorChain)
            throws SearchServiceException {
        String className = configuration.getIndexConfuguration().getQueryableIndexStorage();
        try {
            Class<?> queryableIndexStorageClass = Class.forName(className);
            if (QueryableIndexStorage.class.isAssignableFrom(queryableIndexStorageClass)) {

                Constructor<QueryableIndexStorage> constructor = (Constructor<QueryableIndexStorage>) queryableIndexStorageClass
                        .getConstructor(configuration.getClass());
                QueryableIndexStorage queryableIndexStorage = constructor.newInstance(configuration);
                interceptorChain.addBeforeInterceptor(queryableIndexStorage, ContentReaderInterceptor.class);
            } else {
                throw new SearchServiceException(
                        className + "is no assignable from " + QueryableIndexStorage.class);
            }
        } catch (ClassNotFoundException e) {
            throw new SearchServiceException(e.getLocalizedMessage(), e);
        } catch (SecurityException e) {
            throw new SearchServiceException(e.getLocalizedMessage(), e);
        } catch (NoSuchMethodException e) {
            throw new SearchServiceException(e.getLocalizedMessage(), e);
        } catch (IllegalArgumentException e) {
            throw new SearchServiceException(e.getLocalizedMessage(), e);
        } catch (InstantiationException e) {
            throw new SearchServiceException(e.getLocalizedMessage(), e);
        } catch (IllegalAccessException e) {
            throw new SearchServiceException(e.getLocalizedMessage(), e);
        } catch (InvocationTargetException e) {
            throw new SearchServiceException(e.getTargetException());
        }

    }
}