org.eclipselabs.spray.xtext.validation.SprayJavaValidator.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipselabs.spray.xtext.validation.SprayJavaValidator.java

Source

/** ****************************************************************************
 * Copyright (c)  The Spray Project.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Spray Dev Team - initial API and implementation
 **************************************************************************** */
package org.eclipselabs.spray.xtext.validation;

import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.access.IJvmTypeProvider;
import org.eclipse.xtext.validation.Check;
import org.eclipselabs.spray.mm.spray.AliasableElement;
import org.eclipselabs.spray.mm.spray.Behavior;
import org.eclipselabs.spray.mm.spray.ConnectionInSpray;
import org.eclipselabs.spray.mm.spray.CreateBehavior;
import org.eclipselabs.spray.mm.spray.Diagram;
import org.eclipselabs.spray.mm.spray.Import;
import org.eclipselabs.spray.mm.spray.MetaClass;
import org.eclipselabs.spray.mm.spray.MetaReference;
import org.eclipselabs.spray.mm.spray.ShapeCompartmentAssignment;
import org.eclipselabs.spray.mm.spray.ShapeDslKey;
import org.eclipselabs.spray.mm.spray.ShapePropertyAssignment;
import org.eclipselabs.spray.mm.spray.SprayPackage;
import org.eclipselabs.spray.xtext.scoping.PackageSelector;
import org.eclipselabs.spray.xtext.util.GenModelHelper;
import org.eclipselabs.spray.xtext.util.TextBodyFetcher;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import javax.inject.Inject;

public class SprayJavaValidator extends AbstractSprayJavaValidator implements IssueCodes {
    @Inject
    private GenModelHelper genModelHelper;
    @Inject
    private IJvmTypeProvider.Factory typeProviderFactory;
    @Inject
    private PackageSelector packageSelector;
    @Inject
    private TextBodyFetcher textBodyFetcher;

    /**
     * Add additional EReferences for type conformance validation of expressions.
     */
    //    @Override
    //    protected Set<EReference> getTypeConformanceCheckedReferences() {
    //        Set<EReference> references = new HashSet<EReference>(super.getTypeConformanceCheckedReferences());
    //        references.add(SprayPackage.Literals.SHAPE_PROPERTY_ASSIGNMENT__VALUE);
    //        return references;
    //    }

    @Check
    public void checkGenModelAvailable(MetaClass clazz) {
        EClass type = clazz.getType();
        try {
            // call of getEPackageClassName will result in an IllegalStateException when no GenModel was found
            if (type.eIsProxy()) {
                return; // scoping problem; will be reported as separate problem
            }
            genModelHelper.getEPackageClassName(type);
        } catch (IllegalStateException e) {
            error("No genmodel registered for EClass " + type.getName(), clazz,
                    SprayPackage.Literals.META_CLASS__TYPE, IssueCodes.MISSING_GENMODEL);
        }
    }

    @Check
    public void checkDuplicateAliasName(final AliasableElement element) {
        if (element.getAlias() == null)
            return;

        final Predicate<AliasableElement> filter = new Predicate<AliasableElement>() {
            @Override
            public boolean apply(AliasableElement input) {
                return element.getAlias().equals(input.getAlias());
            }
        };

        if (element instanceof MetaClass) {
            Diagram diagram = (Diagram) element.eContainer();
            if (element != Iterables.find(diagram.getMetaClassesList(), filter)) {
                String alias = element.getAlias();
                error("Duplicate alias name " + alias, element, SprayPackage.Literals.ALIASABLE_ELEMENT__ALIAS,
                        IssueCodes.DUPLICATE_ALIAS_NAME, element.getAlias());
            }
        } else {
            MetaClass clazz = EcoreUtil2.getContainerOfType(element, MetaClass.class);
            List<AliasableElement> elements = EcoreUtil2.eAllOfType(clazz, AliasableElement.class);
            elements.remove(clazz);
            // ignore the first element with the alias, but raise errors for all following
            if (element != Iterables.find(elements, filter)) {
                String alias = element.getAlias();
                error("Duplicate alias name " + alias, element, SprayPackage.Literals.ALIASABLE_ELEMENT__ALIAS,
                        IssueCodes.DUPLICATE_ALIAS_NAME, element.getAlias());
            }
        }
    }

    @Check
    public void checkDuplicateConnectionReferences(final MetaClass element) {
        MetaReference found = null;
        for (MetaReference ref : element.getReferences()) {
            found = Iterables.find(Arrays.asList(element.getReferences()),
                    getDuplicateConnectionReferenceFilter(ref));
            if (found != null && found != ref) {
                String referenceName = getReferenceName(ref);
                error("Duplicate connection reference: " + referenceName, element,
                        SprayPackage.Literals.META_CLASS__REFERENCES, IssueCodes.DUPLICATE_CONNECTION_REFERENCE,
                        referenceName);
            }
        }
    }

    private String getReferenceName(MetaReference ref) {
        String name = ref.getTarget().getName();
        if (name == null) {
            name = EcoreUtil2.getURI(ref.getTarget()).toString();
        }
        return name;
    }

    private Predicate<? super MetaReference> getDuplicateConnectionReferenceFilter(final MetaReference reference) {
        return new Predicate<MetaReference>() {
            @Override
            public boolean apply(MetaReference input) {
                return reference.getTarget().equals(input.getTarget());
            }
        };
    }

    @Check
    public void checkConnectionReferenceToContainmentFeature(final MetaClass element) {
        for (MetaReference ref : element.getReferences()) {
            if ((ref.getTarget() != null && ref.getTarget().isContainment())) {
                String referenceName = getReferenceName(ref);
                error("Connection reference to containment reference not supported yet: " + referenceName, element,
                        SprayPackage.Literals.META_CLASS__REFERENCES, IssueCodes.CONTAINMENT_CONNECTION_REFERENCE,
                        referenceName);
            }
        }
    }

    @Check
    public void checkCreateBehavior(final MetaClass element) {
        Predicate<Behavior> createBehaviorFilter = new Predicate<Behavior>() {
            @Override
            public boolean apply(Behavior input) {
                return input instanceof CreateBehavior;
            }
        };
        String name = (element.getType() != null && element.getType().getName() != null)
                ? element.getType().getName()
                : element.toString();
        if (!Iterables.filter(element.getBehaviorsList(), createBehaviorFilter).iterator().hasNext()) {
            warning("There is no create behavior defined for class " + name, element,
                    SprayPackage.Literals.META_CLASS__TYPE, IssueCodes.NO_CREATE_BEHAVIOR, name);
        }
    }

    /**
     * The connection to reference must be specified, except for the case of a MetaReference, since there the reference is already defined as target
     * 
     * @param connection
     */
    @Check
    public void checkConnectionFromTo(final ConnectionInSpray connection) {
        if (connection.getTo() == null && !(connection.eContainer() instanceof MetaReference)) {
            error("to reference not specified", SprayPackage.Literals.CONNECTION_IN_SPRAY__TO);
        }
    }

    @Check
    public void checkImports(final Import imp) {
        if (imp.getImportedNamespace().endsWith(".*")) {
            Iterable<EPackage> ePackages = packageSelector.getFilteredEPackages(imp);
            for (EPackage ePackage : ePackages) {
                if ((ePackage.getName() + ".*").equals(imp.getImportedNamespace())) {
                    return;
                }
            }
            error("The import " + imp.getImportedNamespace() + " cannot be resolved",
                    SprayPackage.Literals.IMPORT__IMPORTED_NAMESPACE, IMPORT_NOTEXISTS, new String[0]);
        }
        IJvmTypeProvider typeProvider = typeProviderFactory
                .findOrCreateTypeProvider(imp.eResource().getResourceSet());
        JvmType jvmType = typeProvider.findTypeByName(imp.getImportedNamespace());
        if (jvmType == null) {
            error("The import " + imp.getImportedNamespace() + " cannot be resolved",
                    SprayPackage.Literals.IMPORT__IMPORTED_NAMESPACE, IMPORT_NOTEXISTS, new String[0]);
        }
    }

    @Check
    public void checkIdReferences(final ShapePropertyAssignment shapePropertyAssignment) {
        ShapeDslKey shapeDslKey = shapePropertyAssignment.getKey();
        if (shapeDslKey != null) {
            String currentKey = shapeDslKey.getDslKey();
            if (currentKey != null) {
                final Predicate<EObject> filterPredicate = textBodyFetcher.getPropertyAssignmentIdsFilter();
                Set<String> textBodyIds = textBodyFetcher.getTextBodyIds(shapePropertyAssignment,
                        textBodyFetcher.getShapeContainerElementResolver(), filterPredicate);
                if (!textBodyIds.contains(currentKey)) {
                    error("The given id " + currentKey + " cannot be resolved inside the referenced shape",
                            SprayPackage.Literals.SHAPE_PROPERTY_ASSIGNMENT__KEY);
                }
            }
        }
    }

    @Check
    public void checkIdReferences(final ShapeCompartmentAssignment shapeCompartmentAssignment) {
        ShapeDslKey shapeDslKey = shapeCompartmentAssignment.getShapeDslKey();
        if (shapeDslKey != null) {
            String currentKey = shapeDslKey.getDslKey();
            if (currentKey != null) {
                final Predicate<EObject> filterPredicate = textBodyFetcher.getCompartmentAssignmentIdsFilter();
                Set<String> textBodyIds = textBodyFetcher.getTextBodyIds(shapeCompartmentAssignment,
                        textBodyFetcher.getShapeContainerElementResolver(), filterPredicate);
                if (!textBodyIds.contains(currentKey)) {
                    error("The given id " + currentKey + " cannot be resolved inside the referenced shape",
                            SprayPackage.Literals.SHAPE_COMPARTMENT_ASSIGNMENT__SHAPE_DSL_KEY);
                }
            }
        }
    }
}