package org.gcube.data.spd.manager.search; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; import net.sf.ehcache.CacheManager; import org.gcube.common.authorization.library.AuthorizedTasks; import org.gcube.data.spd.caching.QueryCacheFactory; import org.gcube.data.spd.manager.search.workers.CacheReaderWorker; import org.gcube.data.spd.manager.search.workers.HavingFilterWorker; import org.gcube.data.spd.manager.search.workers.ObjectManagerWorker; import org.gcube.data.spd.manager.search.workers.SearchCachingEventDispatcher; import org.gcube.data.spd.manager.search.workers.SearchWorker; import org.gcube.data.spd.manager.search.writers.ConsumerEventHandler; import org.gcube.data.spd.manager.search.writers.WorkerWriterPool; import org.gcube.data.spd.model.Condition; import org.gcube.data.spd.model.products.ResultElement; import org.gcube.data.spd.model.service.exceptions.UnsupportedCapabilityException; import org.gcube.data.spd.model.service.exceptions.UnsupportedPluginException; import org.gcube.data.spd.plugin.PluginUtils; import org.gcube.data.spd.plugin.fwk.AbstractPlugin; import org.gcube.data.spd.plugin.fwk.Searchable; import org.gcube.data.spd.plugin.fwk.writers.ClosableWriter; import org.gcube.data.spd.plugin.fwk.writers.ResultElementWriterManager; import org.gcube.data.spd.plugin.fwk.writers.Writer; import org.gcube.data.spd.plugin.fwk.writers.rswrapper.AbstractWrapper; import org.gcube.data.spd.utils.ExecutorsContainer; import org.gcube.dataaccess.spd.havingengine.HavingStatement; import org.gcube.dataaccess.spd.havingengine.HavingStatementFactory; import org.gcube.dataaccess.spd.havingengine.exl.HavingStatementFactoryEXL; import org.gcube.dataaccess.spql.model.ExpandClause; import org.gcube.dataaccess.spql.model.Query; import org.gcube.dataaccess.spql.model.ResolveClause; import org.gcube.dataaccess.spql.model.Term; import org.gcube.dataaccess.spql.model.UnfoldClause; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Search { Logger logger = LoggerFactory.getLogger(Search.class); AbstractWrapper wrapper; Map plugins ; CacheManager cacheManager; QueryCacheFactory queryCacheFactory; Class> writerManagerClass; public Search(AbstractWrapper wrapper, Map plugins, Class> writerManagerClass, QueryCacheFactory queryCacheFactory) { this.wrapper = wrapper; this.writerManagerClass = writerManagerClass; this.cacheManager = CacheManager.getInstance(); this.plugins = plugins; this.queryCacheFactory = queryCacheFactory; } @SuppressWarnings("unchecked") public void search(Map> searchableMapping, Query parsedQuery, Condition ... properties) throws UnsupportedCapabilityException, UnsupportedPluginException, Exception { ClosableWriter outputWriter = new Writer(wrapper); //preparing the query (and checking semantic) List> workers = new ArrayList>(); logger.info("HAVING expression is null ?? "+(parsedQuery.getHavingExpression()==null)); //adding Having filter if specified WorkerWriterPool havingInputWriterPool = null; if (parsedQuery.getHavingExpression()!=null){ HavingStatementFactory factory = new HavingStatementFactoryEXL(); HavingStatement havingFilter = factory.compile(parsedQuery.getHavingExpression().getExpression()); ((Writer)outputWriter).register(); Worker havingWorker = new HavingFilterWorker(outputWriter, havingFilter); workers.add(havingWorker); havingInputWriterPool = new WorkerWriterPool(havingWorker); logger.debug("adding HavingFilterWorker"); } List> consumers = new ArrayList>(); for (Entry> entry: searchableMapping.entrySet()){ boolean cachablePlugin = plugins.get(entry.getKey()).isUseCache(); if(havingInputWriterPool==null) ((Writer)outputWriter).register(); else outputWriter = havingInputWriterPool.get(); ObjectManagerWorker managerWorker = new ObjectManagerWorker(outputWriter, writerManagerClass.getConstructor(String.class).newInstance(entry.getKey())); WorkerWriterPool writerPool = new WorkerWriterPool(managerWorker); logger.debug("("+entry.getKey()+") creating search worker "); SearchWorker searchWorker = new SearchWorker( writerPool.get(),entry.getKey(), cachablePlugin, entry.getValue(), cacheManager, queryCacheFactory, properties); workers.add(managerWorker); workers.add(searchWorker); if (cachablePlugin){ logger.trace("key is "+entry.getKey()+" and value "+entry.getValue()); CacheReaderWorker cacheReaderWorker = new CacheReaderWorker( writerPool.get(), cacheManager, entry.getKey(), properties, entry.getValue().getHandledClass()); workers.add(cacheReaderWorker); consumers.add(new SearchCachingEventDispatcher(searchWorker, cacheReaderWorker, cacheManager, entry.getKey(), properties, entry.getValue().getHandledClass())); }else consumers.add(searchWorker); } List searchFlows = extractFlows(parsedQuery); for (SearchFlow flow: searchFlows) workers.addAll(flow.createWorkers(consumers.toArray(new ConsumerEventHandler[consumers.size()]))); //starting workers for (Worker worker: workers) ExecutorsContainer.execSearch(AuthorizedTasks.bind(worker)); for (SearchFlow flow: searchFlows) flow.injectWords(); } private List extractFlows(Query parsedQuery) throws UnsupportedCapabilityException, UnsupportedPluginException{ List flows = new ArrayList(); for (Term term :parsedQuery.getTerms()){ List words = term.getWords(); Collection expanders = getExpanders(term.getExpandClause()); Collection resolvers = getResolvers(term.getResolveClause()); SearchFlow flow = new SearchFlow(words, expanders, resolvers); UnfoldClause unfoldClause = term.getUnfoldClause(); if (unfoldClause!=null) flow.setUnfolder(getUnfolder(unfoldClause)); flows.add(flow); } return flows; } private Collection getExpanders(ExpandClause expandClause) throws UnsupportedCapabilityException, UnsupportedPluginException{ Collection expanders = Collections.emptyList(); if (expandClause!=null){ expanders =expandClause.getDatasources().size()>0?PluginUtils.getPluginsSubList(expandClause.getDatasources(), plugins): PluginUtils.getExtenderPlugins(plugins.values()); if (expanders.size()==0) throw new UnsupportedCapabilityException(); } return expanders; } private Collection getResolvers(ResolveClause resolveClause) throws UnsupportedCapabilityException, UnsupportedPluginException{ Collection resolvers = Collections.emptyList(); if (resolveClause!=null){ resolvers =resolveClause.getDatasources().size()>0?PluginUtils.getPluginsSubList(resolveClause.getDatasources(), plugins): PluginUtils.getResolverPlugins(plugins.values()); if (resolvers.size()==0) throw new UnsupportedCapabilityException(); } return resolvers; } private AbstractPlugin getUnfolder(UnfoldClause unfoldClause) throws UnsupportedCapabilityException, UnsupportedPluginException{ String datasource = unfoldClause.getDatasource(); AbstractPlugin unfolder = plugins.get(datasource); if (unfolder==null){ logger.error(datasource+" not found"); throw new UnsupportedPluginException(); } if (unfolder.getUnfoldInterface()==null) throw new UnsupportedCapabilityException(); return unfolder; } }