Package org.carrot2.core

Source Code of org.carrot2.core.ProcessingComponentDescriptor

/*
* 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.core;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.carrot2.core.attribute.Init;
import org.carrot2.util.CloseableUtils;
import org.carrot2.util.ReflectionUtils;
import org.carrot2.util.attribute.AttributeBinder;
import org.carrot2.util.attribute.AttributeValueSet;
import org.carrot2.util.attribute.AttributeValueSets;
import org.carrot2.util.attribute.Bindable;
import org.carrot2.util.attribute.BindableDescriptor;
import org.carrot2.util.attribute.BindableDescriptorBuilder;
import org.carrot2.util.attribute.Input;
import org.carrot2.util.attribute.Output;
import org.carrot2.util.attribute.Required;
import org.carrot2.util.resource.IResource;
import org.carrot2.util.resource.ResourceLookup;
import org.carrot2.util.simplexml.PersisterHelpers;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.core.Commit;

import com.google.common.base.Function;
import com.google.common.collect.Maps;

/**
* Descriptor of a {@link IProcessingComponent} being part of a
* {@link ProcessingComponentSuite}.
*/
public class ProcessingComponentDescriptor
{
    @Attribute(name = "component-class")
    private String componentClassName;

    /** Cached component class instantiated from {@link #componentClassName}. */
    private Class<? extends IProcessingComponent> componentClass;

    /** If not <code>null</code>, component initialization ended with an exception. */
    private Throwable initializationException;

    @Attribute
    private String id;

    @Element
    private String label;

    @Element(required = false)
    private String mnemonic;

    @Element
    private String title;

    @Element(required = false, name = "icon-path")
    private String iconPath;

    @Element(required = false)
    private String description;

    private AttributeValueSets attributeSets;

    @Attribute(name = "attribute-sets-resource", required = false)
    private String attributeSetsResource;

    @Attribute(name = "attribute-set-id", required = false)
    private String attributeSetId;

    /**
     * Cached bindable descriptor for this component.
     */
    private BindableDescriptor bindableDescriptor;

    ProcessingComponentDescriptor()
    {
    }

    public ProcessingComponentConfiguration getComponentConfiguration()
    {
        return new ProcessingComponentConfiguration(getComponentClass(), id,
            getAttributes());
    }

    private Map<String, Object> getAttributes()
    {
        Map<String, Object> result = AttributeValueSet
            .getAttributeValues(getAttributeSets().getAttributeValueSet(attributeSetId,
                true));

        if (result == null)
        {
            result = Maps.newHashMap();
        }

        return result;
    }

    /**
     * @return Returns the {@link Class} object for this component.
     * @throws RuntimeException if the class cannot be defined for some reason (class
     *             loader issues).
     */
    @SuppressWarnings("unchecked")
    public synchronized Class<? extends IProcessingComponent> getComponentClass()
    {
        if (this.componentClass == null)
        {
            try
            {
                this.componentClass = (Class<? extends IProcessingComponent>) ReflectionUtils
                    .classForName(componentClassName);
            }
            catch (Exception e)
            {
                throw new RuntimeException("Component class cannot be acquired: "
                    + componentClassName, e);
            }
        }
        return this.componentClass;
    }

    public String getId()
    {
        return id;
    }

    public String getLabel()
    {
        return label;
    }

    public String getMnemonic()
    {
        return mnemonic;
    }

    public String getTitle()
    {
        return title;
    }

    /**
     * @return Returns (optional) path to the icon of this component. The interpretation
     *         of this path is up to the application (icon resources may be placed in
     *         various places).
     */
    public String getIconPath()
    {
        return iconPath;
    }

    public String getDescription()
    {
        return description;
    }

    /**
     * @return Return the name of a resource from which {@link #getAttributeSets()} were
     *         read or <code>null</code> if there was no such resource.
     */
    public String getAttributeSetsResource()
    {
        return attributeSetsResource;
    }

    public AttributeValueSets getAttributeSets()
    {
        return attributeSets;
    }

    public String getAttributeSetId()
    {
        return attributeSetId;
    }

    /**
     * Creates a new initialized instance of the processing component corresponding to
     * this descriptor. The instance will be initialized with the {@link Init} attributes
     * from this descriptor's default attribute set. Checking whether all {@link Required}
     * attribute have been provided will not be made, which, when attributes of
     * {@link Bindable} are <code>null</code>, may cause {@link #getBindableDescriptor()}
     * to return incomplete descriptor.
     * <p>
     * The instance may or may not be usable for processing because the
     * {@link IControllerContext} on which it is initialized is disposed before the value
     * is returned.
     * </p>
     */
    @SuppressWarnings("unchecked")
    private IProcessingComponent newInitializedInstance()
        throws InstantiationException, IllegalAccessException
    {
        final IProcessingComponent instance = getComponentClass().newInstance();
        final Map<String, Object> initAttributes = Maps.newHashMap();
        final AttributeValueSet defaultAttributeValueSet = attributeSets
            .getDefaultAttributeValueSet();
        if (defaultAttributeValueSet != null)
        {
            initAttributes.putAll(defaultAttributeValueSet.getAttributeValues());
        }

        final ControllerContextImpl context = new ControllerContextImpl();
        try
        {
            AttributeBinder
                .set(instance, initAttributes, false, Input.class);

            try
            {
                instance.init(context);
            }
            catch (Throwable t)
            {
                // Ignore if failed to initialize.
            }

            AttributeBinder.get(instance, initAttributes, Output.class,
                Init.class);
        }
        finally
        {
            context.dispose();
        }

        return instance;
    }

    /**
     * Builds and returns a {@link BindableDescriptor} for an instance of this
     * descriptor's {@link IProcessingComponent}, with default {@link Init} attributes
     * initialized with the default attribute set. If the default attribute set does not
     * provide values for some required {@link Bindable} {@link Init} attributes, the
     * returned descriptor may be incomplete.
     */
    public BindableDescriptor getBindableDescriptor()
    {
        if (bindableDescriptor == null)
            throw new RuntimeException(
                "Descriptor not available.", this.initializationException);

        return bindableDescriptor;
    }

    /**
     * @return Return <code>true</code> if instances of this descriptor are available
     *         (class can be resolved, instances can be created).
     */
    public boolean isComponentAvailable()
    {
        return this.initializationException == null;
    }

    /**
     * Returns initialization failure ({@link Throwable}) or <code>null</code>.
     */
    public Throwable getInitializationFailure()
    {
        return this.initializationException;
    }

    /**
     * Invoked by the XML loading framework when the object is deserialized.
     */
    private void loadAttributeSets(ResourceLookup resourceLookup) throws Exception
    {
        attributeSets = new AttributeValueSets();

        IResource resource = null;
        if (!StringUtils.isBlank(attributeSetsResource))
        {
            // Try to load from the directly provided resource name
            resource = resourceLookup.getFirst(attributeSetsResource);

            if (resource == null)
            {
                throw new IOException("Attribute set resource not found: "
                    + attributeSetsResource);
            }
        }

        if (resource != null)
        {
            final InputStream inputStream = resource.open();
            try
            {
                attributeSets = AttributeValueSets.deserialize(inputStream);
            }
            finally
            {
                CloseableUtils.close(inputStream);
            }
        }

        if (getAttributeSets() == null)
        {
            attributeSets = new AttributeValueSets();
        }
    }

    /**
     * On commit, attempt to verify component class and instance availability.
     */
    @Commit
    @SuppressWarnings({"unused"})
    private void onCommit(Map<Object, Object> session)
    {
        this.initializationException = null;
        try
        {
            ResourceLookup resourceLookup = PersisterHelpers.getResourceLookup(session);
            loadAttributeSets(resourceLookup);
            bindableDescriptor =
                BindableDescriptorBuilder.buildDescriptor(newInitializedInstance());
        }
        catch (Throwable e)
        {
            org.slf4j.LoggerFactory.getLogger(this.getClass()).warn(
                "Component unavailable: " + componentClassName, e);
            this.initializationException = e;
        }
    }

    /**
     * Transforms a {@link ProcessingComponentDescriptor} to its identifier.
     */
    public static final class ProcessingComponentDescriptorToId implements
        Function<ProcessingComponentDescriptor, String>
    {
        public static final ProcessingComponentDescriptorToId INSTANCE = new ProcessingComponentDescriptorToId();

        private ProcessingComponentDescriptorToId()
        {
        }

        public String apply(ProcessingComponentDescriptor descriptor)
        {
            return descriptor.id;
        }
    }

    @Override
    public String toString()
    {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
    }
}
TOP

Related Classes of org.carrot2.core.ProcessingComponentDescriptor

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.