// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.search.rendering; import com.yahoo.component.ComponentId; import com.yahoo.component.ComponentSpecification; import com.yahoo.component.provider.ComponentRegistry; import com.yahoo.prelude.templates.PageTemplateSet; import com.yahoo.prelude.templates.SearchRendererAdaptor; import com.yahoo.prelude.templates.TiledTemplateSet; import com.yahoo.prelude.templates.UserTemplate; import com.yahoo.processing.rendering.Renderer; import com.yahoo.search.Result; import java.util.Collection; import java.util.Collections; import java.util.concurrent.Executor; /** * Holds all configured and built-in renderers. * This registry is always frozen. * * @author bratseth */ public final class RendererRegistry extends ComponentRegistry> { public static final ComponentId xmlRendererId = ComponentId.fromString("DefaultRenderer"); public static final ComponentId jsonRendererId = ComponentId.fromString("JsonRenderer"); public static final ComponentId defaultRendererId = jsonRendererId; private final ComponentId tiledRendererId; private final ComponentId pageRendererId; /** Creates a registry containing the built-in renderers only */ public RendererRegistry() { this(Collections.emptyList()); } /** * Creates a registry containing the built-in renderers only, using a custom executor. * Using a custom executor is useful for tests to avoid creating new threads for each renderer registry: * Use MoreExecutors.directExecutor(). */ public RendererRegistry(Executor executor) { this(Collections.emptyList(), executor); } /** Creates a registry of the given renderers plus the built-in ones */ public RendererRegistry(Collection renderers) { this(renderers, null); } /** * Creates a registry of the given renderers plus the built-in ones, using a custom executor. * Using a custom executor is useful for tests to avoid creating new threads for each renderer registry. */ public RendererRegistry(Collection renderers, Executor executor) { // add json renderer Renderer jsonRenderer = new JsonRenderer(executor); jsonRenderer.initId(RendererRegistry.jsonRendererId); register(jsonRenderer.getId(), jsonRenderer); // Add xml renderer Renderer xmlRenderer = new DefaultRenderer(executor); xmlRenderer.initId(xmlRendererId); register(xmlRenderer.getId(), xmlRenderer); // add application renderers for (Renderer renderer : renderers) register(renderer.getId(), renderer); // add legacy "templates" converted to renderers // TODO: Remove on Vespa 7 tiledRendererId = addTemplateSet(new TiledTemplateSet()); pageRendererId = addTemplateSet(new PageTemplateSet()); freeze(); } /** Must be called when use of this is discontinued to free the resources it has allocated */ public void deconstruct() { // deconstruct the renderers which was created by this getRenderer(jsonRendererId.toSpecification()).deconstruct(); getRenderer(xmlRendererId.toSpecification()).deconstruct(); getRenderer(tiledRendererId.toSpecification()).deconstruct(); getRenderer(pageRendererId.toSpecification()).deconstruct(); } @SuppressWarnings({"deprecation", "unchecked"}) private ComponentId addTemplateSet(UserTemplate templateSet) { Renderer renderer = new SearchRendererAdaptor(templateSet); ComponentId rendererId = new ComponentId(templateSet.getName()); renderer.initId(rendererId); register(rendererId, renderer); return rendererId; } /** * Returns the default JSON renderer * * @return the default built-in result renderer */ public com.yahoo.processing.rendering.Renderer getDefaultRenderer() { return getComponent(jsonRendererId); } /** * Returns the requested renderer. * * @param format the id or format alias of the renderer to return. If null is passed the default renderer * is returned * @throws IllegalArgumentException if the renderer cannot be resolved */ public com.yahoo.processing.rendering.Renderer getRenderer(ComponentSpecification format) { if (format == null || format.stringValue().equals("default")) return getDefaultRenderer(); if (format.stringValue().equals("json")) return getComponent(jsonRendererId); if (format.stringValue().equals("xml")) return getComponent(xmlRendererId); com.yahoo.processing.rendering.Renderer renderer = getComponent(format); if (renderer == null) throw new IllegalArgumentException("No renderer with id or alias '" + format + "'. " + "Available renderers are: [" + rendererNames() + "]."); return renderer; } private String rendererNames() { StringBuilder r = new StringBuilder(); for (Renderer c : allComponents()) { if (r.length() > 0) r.append(", "); r.append(c.getId().stringValue()); } return r.toString(); } }