Package org.carrot2.webapp.model

Source Code of org.carrot2.webapp.model.WebappConfig

/*
* Carrot2 project.
*
* Copyright (C) 2002-2014, Dawid Weiss, Stanisław Osiński.
* All rights reserved.
*
* Refer to the full license file "carrot2.LICENSE"
* in the root folder of the repository checkout or at:
* http://www.carrot2.org/carrot2.LICENSE
*/

package org.carrot2.webapp.model;

import java.io.InputStream;
import java.util.*;

import javax.servlet.ServletContext;

import org.carrot2.core.*;
import org.carrot2.core.attribute.AttributeNames;
import org.carrot2.core.attribute.InternalAttributePredicate;
import org.carrot2.util.CloseableUtils;
import org.carrot2.util.attribute.*;
import org.carrot2.util.resource.*;
import org.carrot2.util.resource.ResourceLookup.Location;
import org.carrot2.webapp.QueryProcessorServlet;
import org.carrot2.webapp.filter.QueryWordHighlighter;
import org.simpleframework.xml.*;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.core.Persister;
import org.slf4j.Logger;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.*;

/**
* The application-wide configuration.
*/
public class WebappConfig
{
    private final static Logger log = org.slf4j.LoggerFactory
        .getLogger(WebappConfig.class);

    @Element(required = false)
    public ProcessingComponentSuite components;

    /**
     * Descriptors of attributes to display in the advanced document source options view,
     * keyed by document source id.
     */
    public Map<String, List<AttributeDescriptor>> sourceAttributeMetadata;

    /**
     * Values of document source attributes set at component initialization time, keyed by
     * document source id. We need these to show proper default values in advanced options
     * for those sources for which the default attribute values have been overridden in
     * the component suite.
     */
    public Map<String, Map<String, Object>> sourceInitializationAttributes;

    /**
     * A set of keys of all internal attributes of all components. We need this to prevent
     * these attributes to be bound from the HTTP request parameters.
     */
    public Set<String> componentInternalAttributeKeys;

    @ElementList(entry = "skin")
    public ArrayList<SkinModel> skins;

    @ElementList(entry = "size")
    public ArrayList<ResultsSizeModel> sizes;

    @ElementList(entry = "view")
    public ArrayList<ResultsViewModel> views;

    @ElementList(entry = "cache", required = false)
    public ArrayList<ResultsCacheModel> caches = Lists.newArrayList();
   
    @Attribute(name = "skins-folder")
    public String skinsFolder;

    @Attribute(name = "component-suite")
    public String componentSuite = "suites/suite-webapp.xml";

    @Attribute(name = "search-url", required = false)
    public String SEARCH_URL = "search";

    @Attribute(name = "xml-url", required = false)
    public String XML_URL = "xml";

    @Attribute(name = "query-highlighter", required = false)
    public String QUERY_HIGHLIGHTER_ID = QueryWordHighlighter.class.getName();

    @Attribute(name = "max-carrot2-results", required = false)
    public Integer maxCarrot2Results = null;

    // These are for output serialization only, this is somewhat clumsy.

    @Attribute(name = "query-param", required = false)
    public final static String QUERY_PARAM = AttributeNames.QUERY;
    public final static String QUERY_PARAM_ALIAS = "q";

    @Attribute(name = "results-param", required = false)
    public final static String RESULTS_PARAM = AttributeNames.RESULTS;

    @Attribute(name = "source-param", required = false)
    public final static String SOURCE_PARAM = "source";

    @Attribute(name = "algorithm-param", required = false)
    public final static String ALGORITHM_PARAM = "algorithm";

    @Attribute(name = "type-param", required = false)
    public final static String TYPE_PARAM = "type";

    @Attribute(name = "view-param", required = false)
    public final static String VIEW_PARAM = "view";

    @Attribute(name = "skin-param", required = false)
    public final static String SKIN_PARAM = "skin";

    @Attribute(name = "stylesheet-param", required = false)
    public final static String STYLESHEET_PARAM = "stylesheet";

    /**
     * @return Initialize the global configuration and return it.
     */
    public final static WebappConfig getSingleton(ServletContext context)
    {
        try
        {
            // Load web application configuration.
            final IResource webappConfig = new ResourceLookup(
                    new PrefixDecoratorLocator(new ServletContextLocator(context), "/WEB-INF/"))
                .getFirst("webapp-config.xml");

            if (webappConfig == null)
                throw new RuntimeException("Could not find WEB-INF/webapp-config.xml.");

            final WebappConfig conf = deserialize(webappConfig);

            if (conf.skins.size() == 0)
            {
                throw new RuntimeException("Configuration must contain at least one skin");
            }

            if (conf.views.size() == 0)
            {
                throw new RuntimeException("Configuration must contain at least one view");
            }

            if (conf.sizes.size() == 0)
            {
                throw new RuntimeException(
                    "Configuration must contain at least one result list size");
            }

            // Load component suite.
            List<IResourceLocator> resourceLocators = Lists.newArrayList();
            resourceLocators.add(new PrefixDecoratorLocator(
                new ServletContextLocator(context), "/WEB-INF/suites/"));

            if (Boolean.getBoolean(QueryProcessorServlet.ENABLE_CLASSPATH_LOCATOR))
                resourceLocators.add(Location.CONTEXT_CLASS_LOADER.locator);

            ResourceLookup suitesLookup = new ResourceLookup(resourceLocators);
            IResource suite = suitesLookup.getFirst(conf.componentSuite);

            if (suite == null)
            {
                throw new Exception("Suite file not found in servlet context's /WEB-INF/suites: "
                    + conf.componentSuite);
            }

            conf.components = ProcessingComponentSuite.deserialize(suite, suitesLookup);

            log.info("Loaded " + conf.components.getSources().size() + " sources and "
                + conf.components.getAlgorithms().size() + " algorithms");

            // Prepare attribute descriptors for document sources
            conf.sourceAttributeMetadata = prepareSourceAttributeMetadata(conf.components);
            conf.sourceInitializationAttributes = prepareSourceInitializationAttributes(conf.components);
            conf.componentInternalAttributeKeys = prepareComponentInternalAttributeKeys(conf.components);

            return conf;
        }
        catch (Exception e)
        {
            log.error("Could not load application config.", e);
            throw new RuntimeException("Could not load application config.", e);
        }
    }

    public String getContextRelativeSkinStylesheet(RequestModel requestModel)
    {
        return "/" + skinsFolder + "/" + requestModel.skin + "/" + requestModel.stylesheet;
    }

    public SkinModel getSkinById(String skinId)
    {
        // Short list, we can afford linear search
        for (SkinModel skin : skins)
        {
            if (skin.id.equals(skinId))
            {
                return skin;
            }
        }

        return ModelWithDefault.getDefault(skins);
    }

    private static WebappConfig deserialize(IResource resource) throws Exception
    {
        final InputStream inputStream = resource.open();
        final WebappConfig loaded;
        try
        {
            loaded = new Persister().read(WebappConfig.class, inputStream);
        }
        finally
        {
            CloseableUtils.close(inputStream);
        }

        return loaded;
    }

    @SuppressWarnings("unchecked")
    private static Map<String, List<AttributeDescriptor>> prepareSourceAttributeMetadata(
        ProcessingComponentSuite components) throws Exception
    {
        final List<DocumentSourceDescriptor> sources = components.getSources();
        final Map<String, List<AttributeDescriptor>> sourceDescriptors = Maps
            .newLinkedHashMap();

        for (DocumentSourceDescriptor documentSourceDescriptor : sources)
        {
            final BindableDescriptor bindableDescriptor = documentSourceDescriptor
                .getBindableDescriptor().only(Input.class).only(
                    new LevelsPredicate(AttributeLevel.BASIC, AttributeLevel.MEDIUM))
                .only(
                    Predicates.<AttributeDescriptor> and(Predicates
                        .not(new InternalAttributePredicate()),
                        new Predicate<AttributeDescriptor>()
                        {
                            /** Attribute types supported in advanced source options */
                            final Set<Class<?>> ALLOWED_PLAIN_TYPES = ImmutableSet
                                .<Class<?>> of(Byte.class, Short.class, Integer.class,
                                    Long.class, Float.class, Double.class, Boolean.class,
                                    String.class, Character.class);

                            private final Set<String> IGNORED = ImmutableSet.<String> of(
                                AttributeNames.QUERY, AttributeNames.RESULTS);

                            public boolean apply(AttributeDescriptor d)
                            {
                                return (d.type.isEnum() || ALLOWED_PLAIN_TYPES
                                    .contains(d.type))
                                    && !IGNORED.contains(d.key);
                            }
                        }));

            final List<AttributeDescriptor> descriptors = Lists
                .newArrayList(bindableDescriptor.attributeDescriptors.values());
            Collections.sort(descriptors, new Comparator<AttributeDescriptor>()
            {
                public int compare(AttributeDescriptor d1, AttributeDescriptor d2)
                {
                    return getOrder(d1) - getOrder(d2);
                }

                private int getOrder(AttributeDescriptor d)
                {
                    if (d.type.isEnum())
                    {
                        return 0;
                    }
                    else if (d.type.equals(Boolean.class))
                    {
                        return 2;
                    }
                    else
                    {
                        return 1;
                    }
                }
            });

            sourceDescriptors.put(documentSourceDescriptor.getId(), descriptors);
        }

        return sourceDescriptors;
    }

    private static Map<String, Map<String, Object>> prepareSourceInitializationAttributes(
        ProcessingComponentSuite components)
    {
        final List<DocumentSourceDescriptor> sources = components.getSources();
        final Map<String, Map<String, Object>> initAttributes = Maps.newHashMap();

        for (DocumentSourceDescriptor documentSourceDescriptor : sources)
        {
            initAttributes.put(documentSourceDescriptor.getId(), documentSourceDescriptor
                .getComponentConfiguration().attributes);
        }

        return initAttributes;
    }

    private static Set<String> prepareComponentInternalAttributeKeys(
        ProcessingComponentSuite components) throws Exception
    {
        final List<ProcessingComponentDescriptor> descriptors = components
            .getComponents();
        final Set<String> internalAttributeKeys = Sets.newHashSet();

        for (ProcessingComponentDescriptor descriptor : descriptors)
        {
            internalAttributeKeys.addAll(Lists.transform(Lists
                .newArrayList(descriptor.getBindableDescriptor().only(
                    new InternalAttributePredicate()).attributeDescriptors.values()),
                AttributeDescriptor.AttributeDescriptorToKey.INSTANCE));
        }

        internalAttributeKeys.remove(AttributeNames.QUERY);

        return internalAttributeKeys;
    }
}
TOP

Related Classes of org.carrot2.webapp.model.WebappConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.