/** * Performs processing using components designated by their class. If you initialized * this controller using {@link #init(Map, ProcessingComponentConfiguration...)} and * would like to designate components by their identifiers, call * {@link #process(Map, String...)} or {@link #process(Map, Object...)}. * * @param attributes attributes to be used during processing. {@link Input} attributes * will be transferred from this map to the corresponding fields. Keys of * the map are computed based on the <code>key</code> parameter of the * {@link Attribute} annotation. Controller will not modify the provided * map, processing results will be available in the returned * {@link ProcessingResult}. * @param processingComponentClasses classes of components to perform processing in * the order they should be arranged in the pipeline. Each provided class * must implement {@link IProcessingComponent}. * @return results of the processing */ public ProcessingResult process(Map<String, Object> attributes, Class<?>... processingComponentClasses) throws ProcessingException { return process(attributes, (Object []) processingComponentClasses); }
/** * Initializes this controller with the provided @{@link Init}-time attributes. The * provided attributes will be applied to all processing components managed by this * controller. {@link Init}-time attributes can be overridden at processing time, see * {@link #process(Map, Class...)} or {@link #process(Map, Object...)}. * * @param attributes initialization-time attributes to be applied to all processing * components in this controller * @return this controller for convenience */ public synchronized Controller init(Map<String, Object> attributes) throws ComponentInitializationException { return init(attributes, new ProcessingComponentConfiguration [0]); }
/** Implement closeable so that controller can be closed with Java 1.7 resource block. */ @Override public void close() { dispose(); }
Object... processingComponentClassesOrIds) throws ProcessingException checkClosed(); init(); for (int i = 0; i < processingComponentClassesOrIds.length; i++) configurations[i] = resolveComponent(processingComponentClassesOrIds[i]); .isAssignableFrom(configurations[i].componentClass)) addTime(AttributeNames.PROCESSING_TIME_SOURCE, time, resultAttributes); .isAssignableFrom(configurations[i].componentClass)) addTime(AttributeNames.PROCESSING_TIME_ALGORITHM, time, resultAttributes); addTime(AttributeNames.PROCESSING_TIME_TOTAL, time, resultAttributes);
/** * Creates a controller with the specified pooling and caching settings. * * @param componentPooling if <code>true</code>, component pooling * will be performed (soft pool), otherwise no component pool will be used. * @param cachedProcessingComponents classes of components whose output should be cached * by the controller. If a superclass is provided here, e.g. * {@link IDocumentSource}, all its subclasses will be subject to caching. * If {@link IProcessingComponent} is provided here, output of all * components will be cached. */ @SafeVarargs public static Controller create(boolean componentPooling, Class<? extends IProcessingComponent>... cachedProcessingComponents) { final IProcessingComponentManager baseManager = (componentPooling ? new PoolingProcessingComponentManager() : new SimpleProcessingComponentManager()); return new Controller(addCachingManager(baseManager, cachedProcessingComponents)); }
/** * Initializes this controller with the provided {@link Init}-time attributes and * additional component-specific {@link Init}-time attributes. {@link Init}-time * attributes can be overridden at processing time, see * {@link #process(Map, Class...)} or {@link #process(Map, Object...)}. * * @param attributes initialization-time attributes to be applied to all processing * components in this controller * @param configurations additional component-specific {@link Init}-time attributes * @return this controller for convenience */ public synchronized Controller init(Map<String, Object> attributes, ProcessingComponentConfiguration... configurations) throws ComponentInitializationException { checkClosed(); if (componentIdToConfiguration != null) { throw new IllegalStateException("This controller is already initialized."); } initAttributes = Collections.unmodifiableMap(Maps.newHashMap(attributes)); componentIdToConfiguration = ProcessingComponentConfiguration .indexByComponentId(configurations); componentManager.init(context, attributes, configurations); return this; }
/** * Creates a controller with the specified fixed-size pooling and caching settings. * * @param instancePoolSize Number of instances created for a single component class-ID * pair. For computational components it is sensible to set this pool to * the number of CPU cores available on the machine. * @param cachedProcessingComponents classes of components whose output should be * cached by the controller. If a superclass is provided here, e.g. * {@link IDocumentSource}, all its subclasses will be subject to caching. * If {@link IProcessingComponent} is provided here, output of all * components will be cached. */ @SafeVarargs public static Controller create(int instancePoolSize, Class<? extends IProcessingComponent>... cachedProcessingComponents) { if (instancePoolSize <= 0) throw new IllegalArgumentException("Instance pool size must be greater than zero: " + instancePoolSize); final IProcessingComponentManager baseManager = new PoolingProcessingComponentManager( new FixedSizePool<IProcessingComponent, String>(instancePoolSize)); return new Controller(addCachingManager(baseManager, cachedProcessingComponents)); }
/** * Performs processing using components designated by their identifiers. Identifiers * can be assigned to component configurations using the {@link #init()} method. * * @param attributes attributes to be used during processing. {@link Input} attributes * will be transferred from this map to the corresponding fields. Keys of * the map are computed based on the <code>key</code> parameter of the * {@link Attribute} annotation. Controller will not modify the provided * map, processing results will be available in the returned * {@link ProcessingResult}. * @param processingComponentIdsOrClassNames identifiers of components to perform * processing in the order they should be arranged in the pipeline. * Fully-qualified class names are also accepted. Each provided class must * implement {@link IProcessingComponent}. * @return results of the processing * @see #init(Map, ProcessingComponentConfiguration...) */ public ProcessingResult process(Map<String, Object> attributes, String... processingComponentIdsOrClassNames) throws ProcessingException { return process(attributes, (Object []) processingComponentIdsOrClassNames); }
/** * Initializes this controller with an empty {@link Init}-time attributes map. Calling * this method is optional, if {@link #process(Map, Object...)} is called on an * uninitialized controller, {@link #init()} will be called automatically. * * @return this controller for convenience */ public synchronized Controller init() throws ComponentInitializationException { return init(ImmutableMap.<String, Object> of()); }
@RunWith(SpringRunner.class) //@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) //@TestExecutionListeners({DependencyInjectionTestExecutionListener.class}) //@ContextConfiguration() @ActiveProfiles(profiles = {Profiles.WEB_REST}) //@TestPropertySource("/config/rest.yml") @WebMvcTest(EntityController.class) @DirtiesContext public class ServicesControllerTest { @Autowired private MockMvc mvc; @MockBean private Controller controller; @Test public void testAll() throws Exception { given(controller.process(null)).willReturn(null); mvc.perform(get("/").accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); } }
withContextClassLoader(core.getResourceLoader().getClassLoader(), () -> this.controller.init(initAttributes));
/** * Convenience method for clustering the provided list of {@link Document}s. If the * query that generated the <code>documents</code> is available, it can be provided in * the <code>queryHint</code> parameter to increase the quality of clusters. * <p> * For a method allowing to pass more attributes, see: {@link #process(Map, Class...)}. * </p> * * @param documents the documents to cluster * @param queryHint the query that generated the documents, optional, can be * <code>null</code> if not available. * @param processingComponentClasses classes of components to perform processing in * the order they should be arranged in the pipeline. Each provided class * must implement {@link IProcessingComponent}. * @return results of the processing * @throws ProcessingException */ public ProcessingResult process(List<Document> documents, String queryHint, Class<?>... processingComponentClasses) throws ProcessingException { final Map<String, Object> attributes = Maps.newHashMap(); attributes.put(AttributeNames.DOCUMENTS, documents); if (StringUtils.isNotBlank(queryHint)) { attributes.put(AttributeNames.QUERY, queryHint); } return process(attributes, processingComponentClasses); }
/** * Convenience method for performing processing with the provided query and number of * results. The typical use cases for this method is fetching the specified number of * results from an {@link IDocumentSource} and, optionally, clustering them with an * {@link IClusteringAlgorithm}. * <p> * For a method allowing to pass more attributes, see: {@link #process(Map, Class...)}. * </p> * * @param query the query to use during processing * @param results the number of results to fetch. If <code>null</code> is provided, * the default number of results will be requested. * @param processingComponentClasses classes of components to perform processing in * the order they should be arranged in the pipeline. Each provided class * must implement {@link IProcessingComponent}. * @return results of the processing */ public ProcessingResult process(String query, Integer results, Class<?>... processingComponentClasses) throws ProcessingException { final Map<String, Object> attributes = Maps.newHashMap(); attributes.put(AttributeNames.QUERY, query); if (results != null) { attributes.put(AttributeNames.RESULTS, results); } return process(attributes, processingComponentClasses); }
@Override public Object cluster(Query query, SolrDocumentList solrDocList, Map<SolrDocument, Integer> docIds, SolrQueryRequest sreq) { try { // Prepare attributes for Carrot2 clustering call Map<String, Object> attributes = new HashMap<>(); List<Document> documents = getDocuments(solrDocList, docIds, query, sreq); attributes.put(AttributeNames.DOCUMENTS, documents); attributes.put(AttributeNames.QUERY, query.toString()); // Pass the fields on which clustering runs. attributes.put("solrFieldNames", getFieldsForClustering(sreq)); // Pass extra overriding attributes from the request, if any extractCarrotAttributes(sreq.getParams(), attributes); // Perform clustering and convert to an output structure of clusters. // // Carrot2 uses current thread's context class loader to get // certain classes (e.g. custom tokenizer/stemmer) at runtime. // To make sure classes from contrib JARs are available, // we swap the context class loader for the time of clustering. return withContextClassLoader(core.getResourceLoader().getClassLoader(), () -> clustersToNamedList(controller.process(attributes, clusteringAlgorithmClass).getClusters(), sreq.getParams())); } catch (Exception e) { log.error("Carrot2 clustering failed", e); throw new SolrException(ErrorCode.SERVER_ERROR, "Carrot2 clustering failed", e); } }
.documents(documents); processingResult = controller.process( attributes, LingoClusteringAlgorithm.class);