io.sarl.lang.ui.labeling.SARLLabelProvider.java Source code

Java tutorial

Introduction

Here is the source code for io.sarl.lang.ui.labeling.SARLLabelProvider.java

Source

/*
 * $Id$
 *
 * SARL is an general-purpose agent programming language.
 * More details on http://www.sarl.io
 *
 * Copyright (C) 2014-2017 the original authors or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.sarl.lang.ui.labeling;

import java.util.Collections;
import java.util.concurrent.locks.ReentrantLock;

import javax.inject.Singleton;

import com.google.common.base.Strings;
import com.google.inject.Inject;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jdt.ui.JavaElementImageDescriptor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.graphics.Image;
import org.eclipse.xtend.core.jvmmodel.IXtendJvmAssociations;
import org.eclipse.xtend.ide.labeling.XtendLabelProvider;
import org.eclipse.xtext.common.types.JvmAnnotationType;
import org.eclipse.xtext.common.types.JvmDeclaredType;
import org.eclipse.xtext.common.types.JvmEnumerationType;
import org.eclipse.xtext.common.types.JvmExecutable;
import org.eclipse.xtext.common.types.JvmGenericType;
import org.eclipse.xtext.common.types.JvmIdentifiableElement;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.JvmVisibility;
import org.eclipse.xtext.common.types.TypesPackage;
import org.eclipse.xtext.common.types.access.IJvmTypeProvider;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.util.Exceptions;
import org.eclipse.xtext.util.PolymorphicDispatcher;
import org.eclipse.xtext.util.PolymorphicDispatcher.ErrorHandler;
import org.eclipse.xtext.xbase.XVariableDeclaration;
import org.eclipse.xtext.xbase.scoping.featurecalls.OperatorMapping;
import org.eclipse.xtext.xbase.typesystem.IResolvedTypes;
import org.eclipse.xtext.xbase.typesystem.references.LightweightTypeReference;
import org.eclipse.xtext.xbase.typesystem.util.CommonTypeComputationServices;
import org.eclipse.xtext.xbase.ui.labeling.XbaseImageAdornments;
import org.eclipse.xtext.xbase.validation.UIStrings;

import io.sarl.lang.sarl.SarlAction;
import io.sarl.lang.sarl.SarlAgent;
import io.sarl.lang.sarl.SarlBehavior;
import io.sarl.lang.sarl.SarlBehaviorUnit;
import io.sarl.lang.sarl.SarlCapacity;
import io.sarl.lang.sarl.SarlCapacityUses;
import io.sarl.lang.sarl.SarlConstructor;
import io.sarl.lang.sarl.SarlEvent;
import io.sarl.lang.sarl.SarlField;
import io.sarl.lang.sarl.SarlPackage;
import io.sarl.lang.sarl.SarlRequiredCapacity;
import io.sarl.lang.sarl.SarlScript;
import io.sarl.lang.sarl.SarlSkill;
import io.sarl.lang.services.SARLGrammarKeywordAccess;
import io.sarl.lang.typesystem.InheritanceHelper;
import io.sarl.lang.ui.images.IQualifiedNameImageProvider;
import io.sarl.lang.ui.images.SARLImages;

/**
 * Provides labels for a EObjects.
 *
 * @author $Author: sgalland$
 * @version $FullVersion$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 * @see "https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#label-provider"
 */
@SuppressWarnings("checkstyle:classfanoutcomplexity")
@Singleton
public class SARLLabelProvider extends XtendLabelProvider implements IQualifiedNameImageProvider {

    /** Max length of the text for the behavior units.
     */
    public static final int BEHAVIOR_UNIT_TEXT_LENGTH = 7;

    @Inject
    private UIStrings uiStrings;

    @Inject
    private OperatorMapping operatorMapping;

    @Inject
    private IXtendJvmAssociations jvmModelAssociations;

    @Inject
    private SARLImages images;

    @Inject
    private XbaseImageAdornments adornments;

    private final PolymorphicDispatcher<ImageDescriptor> imageDescriptorDispatcher;

    private final ReentrantLock imageDescriptorLock = new ReentrantLock();

    @Inject
    private CommonTypeComputationServices services;

    @Inject
    private SARLGrammarKeywordAccess keywords;

    @Inject
    private InheritanceHelper inheritanceHelper;

    /**
     * @param delegate - the original provider.
     */
    @Inject
    public SARLLabelProvider(AdapterFactoryLabelProvider delegate) {
        super(delegate);
        this.imageDescriptorDispatcher = new PolymorphicDispatcher<>("imageDescriptor", //$NON-NLS-1$
                1, 1, Collections.singletonList(this), new ErrorHandler<ImageDescriptor>() {
                    @Override
                    public ImageDescriptor handle(Object[] params, Throwable exception) {
                        return handleImageDescriptorError(params, exception);
                    }
                });
    }

    /** Get the image descriptor for the given element.
     *
     * @param element - the element.
     * @return the image descriptor.
     */
    protected ImageDescriptor doGetImageDescriptor(Object element) {
        return this.imageDescriptorDispatcher.invoke(element);
    }

    /** Invoked when an image descriptor cannot be found.
     *
     * @param params - the parameters given to the method polymorphic dispatcher.
     * @param exception - the cause of the error.
     * @return the image descriptor for the error.
     */
    protected ImageDescriptor handleImageDescriptorError(Object[] params, Throwable exception) {
        if (exception instanceof NullPointerException) {
            final Object defaultImage = getDefaultImage();
            if (defaultImage instanceof ImageDescriptor) {
                return (ImageDescriptor) defaultImage;
            }
            if (defaultImage instanceof Image) {
                return ImageDescriptor.createFromImage((Image) defaultImage);
            }
            return super.imageDescriptor(params[0]);
        }
        return Exceptions.throwUncheckedException(exception);
    }

    /** Create a string representation of a signature without the return type.
     *
     * @param simpleName - the action name.
     * @param element - the executable element.
     * @return the signature.
     */
    protected StyledString signatureWithoutReturnType(StyledString simpleName, JvmExecutable element) {
        return simpleName.append(this.uiStrings.parameters(element));
    }

    /** Create a string representation of the given element.
     *
     * @param reference - the element.
     * @return the string representation.
     */
    protected StyledString getHumanReadableName(JvmTypeReference reference) {
        if (reference == null) {
            return new StyledString("Object"); //$NON-NLS-1$
        }
        String name = this.uiStrings.referenceToString(reference, "Object"); //$NON-NLS-1$
        //
        // FIXME: https://bugs.eclipse.org/bugs/show_bug.cgi?id=443131
        final JvmType type = reference.getType();
        if (type != null && type.eIsProxy() && reference.eResource() != null) {
            // This case occurs when the reference is unknown:
            // the found "name" is the fully qualified name of the type.
            // So we should extract the simple name
            int index = name.length() - 1;
            final char dot = '.';
            final char doll = '$';
            final char dies = '#';
            char ch;
            while (index >= 0) {
                ch = name.charAt(index);
                if (ch == dot || ch == doll || ch == dies) {
                    name = name.substring(index + 1);
                    // break the loop
                    index = -1;
                } else {
                    index--;
                }
            }
        }
        // END OF FIX
        //
        return convertToStyledString(name);
    }

    // Descriptors

    @Override
    protected ImageDescriptor imageDescriptor(Object element) {
        if (this.imageDescriptorLock.isLocked()) {
            return super.imageDescriptor(element);
        }
        this.imageDescriptorLock.lock();
        try {
            return doGetImageDescriptor(element);
        } finally {
            this.imageDescriptorLock.unlock();
        }
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(Package element) {
        // Mostly used by the outline
        return this.images.forPackage();
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlScript element) {
        return this.images.forFile();
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlAgent element) {
        final JvmDeclaredType jvmElement = this.jvmModelAssociations.getInferredType(element);
        return this.images.forAgent(element.getVisibility(), this.adornments.get(jvmElement));
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlEvent element) {
        final JvmDeclaredType jvmElement = this.jvmModelAssociations.getInferredType(element);
        return this.images.forEvent(element.getVisibility(), this.adornments.get(jvmElement));
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlCapacity element) {
        final JvmDeclaredType jvmElement = this.jvmModelAssociations.getInferredType(element);
        return this.images.forCapacity(element.getVisibility(), this.adornments.get(jvmElement));
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlSkill element) {
        final JvmDeclaredType jvmElement = this.jvmModelAssociations.getInferredType(element);
        return this.images.forSkill(element.getVisibility(), this.adornments.get(jvmElement));
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlBehavior element) {
        final JvmDeclaredType jvmElement = this.jvmModelAssociations.getInferredType(element);
        return this.images.forBehavior(element.getVisibility(), this.adornments.get(jvmElement));
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlField element) {
        return this.images.forField(element.getVisibility(),
                this.adornments.get(this.jvmModelAssociations.getJvmField(element)));
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlConstructor element) {
        return this.images.forConstructor(element.getVisibility(),
                this.adornments.get(this.jvmModelAssociations.getInferredConstructor(element)));
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlAction element) {
        final JvmOperation jvmElement = this.jvmModelAssociations.getDirectlyInferredOperation(element);
        return this.images.forOperation(element.getVisibility(), this.adornments.get(jvmElement));
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlCapacityUses element) {
        return this.images.forCapacityUses();
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlRequiredCapacity element) {
        return this.images.forCapacityRequirements();
    }

    /** Replies the image for the given element.
     *
     * <p>This function is a Xtext dispatch function for {@link #imageDescriptor(Object)}.
     *
     * @param element - the element.
     * @return the image descriptor.
     * @see #imageDescriptor(Object)
     */
    protected ImageDescriptor imageDescriptor(SarlBehaviorUnit element) {
        return this.images.forBehaviorUnit();
    }

    // Texts

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    protected StyledString text(JvmTypeReference element) {
        return getHumanReadableName(element);
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    protected StyledString text(SarlAgent element) {
        return convertToStyledString(element.getName());
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    protected StyledString text(SarlEvent element) {
        return convertToStyledString(element.getName());
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    protected StyledString text(SarlCapacity element) {
        return convertToStyledString(element.getName());
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    protected StyledString text(SarlSkill element) {
        return convertToStyledString(element.getName());
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    protected StyledString text(SarlBehavior element) {
        return convertToStyledString(element.getName());
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    protected StyledString text(SarlAction element) {
        final JvmIdentifiableElement jvmElement = this.jvmModelAssociations.getDirectlyInferredOperation(element);
        final String simpleName = element.getName();
        if (simpleName != null) {
            final QualifiedName qnName = QualifiedName.create(simpleName);
            final QualifiedName operator = this.operatorMapping.getOperator(qnName);
            if (operator != null) {
                final StyledString result = signature(operator.getFirstSegment(), jvmElement);
                result.append(" (" + simpleName + ")", StyledString.COUNTER_STYLER); //$NON-NLS-1$//$NON-NLS-2$
                return result;
            }
        }
        return signature(element.getName(), jvmElement);
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    @SuppressWarnings("static-method")
    protected StyledString text(SarlCapacityUses element) {
        return new StyledString(Messages.SARLLabelProvider_0, StyledString.QUALIFIER_STYLER);
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    @SuppressWarnings("static-method")
    protected StyledString text(SarlRequiredCapacity element) {
        return new StyledString(Messages.SARLLabelProvider_1, StyledString.QUALIFIER_STYLER);
    }

    /** Replies the text for the given element.
     *
     * @param element - the element.
     * @return the text.
     */
    protected StyledString text(SarlBehaviorUnit element) {
        final StyledString text = new StyledString("on ", StyledString.DECORATIONS_STYLER); //$NON-NLS-1$
        text.append(getHumanReadableName(element.getName()));
        if (element.getGuard() != null) {
            String txt = null;
            final ICompositeNode node = NodeModelUtils.getNode(element.getGuard());
            if (node != null) {
                txt = node.getText().trim();
            }
            if (Strings.isNullOrEmpty(txt)) {
                txt = "[" + Messages.SARLLabelProvider_2 + "]"; //$NON-NLS-1$//$NON-NLS-2$
            } else {
                assert txt != null;
                final String dots = "..."; //$NON-NLS-1$
                if (txt.length() > BEHAVIOR_UNIT_TEXT_LENGTH + dots.length()) {
                    txt = "[" + txt.substring(0, BEHAVIOR_UNIT_TEXT_LENGTH) + dots + "]"; //$NON-NLS-1$//$NON-NLS-2$
                } else {
                    txt = "[" + txt + "]"; //$NON-NLS-1$//$NON-NLS-2$
                }
            }
            text.append(" "); //$NON-NLS-1$
            text.append(txt, StyledString.DECORATIONS_STYLER);
        }
        return text;
    }

    @Override
    protected String text(XVariableDeclaration variableDeclaration) {
        final IResolvedTypes resolvedTypes = getTypeResolver().resolveTypes(variableDeclaration);
        final LightweightTypeReference type = resolvedTypes
                .getActualType((JvmIdentifiableElement) variableDeclaration);
        if (type != null) {
            return variableDeclaration.getName() + " " + this.keywords.getColonKeyword() //$NON-NLS-1$
                    + " " + type.getHumanReadableName(); //$NON-NLS-1$
        }
        return variableDeclaration.getName();
    }

    @Override
    public Image getImageForQualifiedName(String qualifiedName, Notifier context,
            IJvmTypeProvider jvmTypeProvider) {
        return convertToImage(getImageDescriptorForQualifiedName(qualifiedName, context, jvmTypeProvider));
    }

    @SuppressWarnings("checkstyle:npathcomplexity")
    @Override
    public ImageDescriptor getImageDescriptorForQualifiedName(String qualifiedName, Notifier context,
            IJvmTypeProvider typeProvider) {
        JvmType type = null;
        if (typeProvider != null) {
            type = typeProvider.findTypeByName(qualifiedName);
        }
        if (type == null && context != null) {
            type = this.services.getTypeReferences().findDeclaredType(qualifiedName, context);
        }
        int adornments = this.adornments.get(type);
        JvmVisibility visibility = JvmVisibility.DEFAULT;
        if (type != null) {
            if (type.eClass() == TypesPackage.Literals.JVM_GENERIC_TYPE) {
                final JvmGenericType gtype = (JvmGenericType) type;
                visibility = gtype.getVisibility();
                final int ecoreCode = this.inheritanceHelper.getSarlElementEcoreType(gtype);
                switch (ecoreCode) {
                case SarlPackage.SARL_AGENT:
                    return this.images.forAgent(visibility, this.adornments.get(gtype));
                case SarlPackage.SARL_BEHAVIOR:
                    return this.images.forBehavior(visibility, this.adornments.get(gtype));
                case SarlPackage.SARL_CAPACITY:
                    // Remove the "abstract" ornment because capacities are always abstract.
                    adornments = (adornments & JavaElementImageDescriptor.ABSTRACT) ^ adornments;
                    return this.images.forCapacity(visibility, adornments);
                case SarlPackage.SARL_EVENT:
                    return this.images.forEvent(visibility, this.adornments.get(gtype));
                case SarlPackage.SARL_SKILL:
                    return this.images.forSkill(visibility, this.adornments.get(gtype));
                default:
                    if (gtype.isInterface()) {
                        return this.images.forInterface(visibility, this.adornments.get(gtype));
                    }
                }
            } else if (type.eClass() == TypesPackage.Literals.JVM_ENUMERATION_TYPE) {
                final JvmEnumerationType etype = (JvmEnumerationType) type;
                visibility = etype.getVisibility();
                return this.images.forEnum(visibility, adornments);
            } else if (type.eClass() == TypesPackage.Literals.JVM_ANNOTATION_TYPE) {
                final JvmAnnotationType atype = (JvmAnnotationType) type;
                visibility = atype.getVisibility();
                return this.images.forAnnotation(visibility, adornments);
            } else {
                visibility = JvmVisibility.DEFAULT;
            }
        }
        // Default icon is the class icon.
        return this.images.forClass(visibility, adornments);
    }

}