| /** |
| * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Florian Pirchner - Initial implementation |
| */ |
| package org.eclipse.osbp.dsl.common.xtext.validation; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.osbp.dsl.common.xtext.extensions.ModelExtensions; |
| import org.eclipse.osbp.dsl.semantic.common.types.LAttribute; |
| import org.eclipse.osbp.dsl.semantic.common.types.LDataType; |
| import org.eclipse.osbp.dsl.semantic.common.types.LFeature; |
| import org.eclipse.osbp.dsl.semantic.common.types.LFeaturesHolder; |
| import org.eclipse.osbp.dsl.semantic.common.types.LPackage; |
| import org.eclipse.osbp.dsl.semantic.common.types.LReference; |
| import org.eclipse.osbp.dsl.semantic.common.types.LType; |
| import org.eclipse.osbp.dsl.semantic.common.types.LTypedPackage; |
| import org.eclipse.osbp.dsl.semantic.common.types.OSBPTypesPackage; |
| import org.eclipse.xtext.naming.IQualifiedNameProvider; |
| import org.eclipse.xtext.resource.IContainer; |
| import org.eclipse.xtext.resource.IEObjectDescription; |
| import org.eclipse.xtext.resource.IResourceDescription; |
| import org.eclipse.xtext.resource.IResourceDescriptions; |
| import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider; |
| import org.eclipse.xtext.validation.Check; |
| import org.eclipse.xtext.validation.CheckType; |
| import org.eclipse.xtext.validation.NamesAreUniqueValidator; |
| import org.eclipse.xtext.validation.ValidationMessageAcceptor; |
| |
| import com.google.inject.Inject; |
| |
| // TODO: Auto-generated Javadoc |
| /** |
| * Custom validation rules. |
| * |
| * see http://www.eclipse.org/Xtext/documentation.html#validation |
| */ |
| public class CommonGrammarValidator |
| extends org.eclipse.osbp.dsl.common.xtext.validation.AbstractCommonGrammarValidator { |
| |
| /** The Constant CODE__DUPLICATE_LPACKAGE_IN_PROJECT. */ |
| public static final String CODE__DUPLICATE_LPACKAGE_IN_PROJECT = "0_100"; |
| |
| /** The Constant CODE__DUPLICATE_LTYPE_IN_PROJECT. */ |
| public static final String CODE__DUPLICATE_LTYPE_IN_PROJECT = "0_101"; |
| |
| /** The Constant CODE__DUPLICATE_LPACKAGE_IN_FILE. */ |
| public static final String CODE__DUPLICATE_LPACKAGE_IN_FILE = "0_102"; |
| |
| /** The Constant CODE__MANY_TO_MANY__NOT_SUPPORTED. */ |
| public static final String CODE__MANY_TO_MANY__NOT_SUPPORTED = "0_103"; |
| |
| /** The Constant CODE__NOT_A_VALID_PRIMITIVE. */ |
| public static final String CODE__NOT_A_VALID_PRIMITIVE = "0_104"; |
| |
| /** The Constant CODE__FORBIDDEN_JAVA_KEYWORD. */ |
| public static final String CODE__FORBIDDEN_JAVA_KEYWORD = "0_105"; |
| |
| /** The Constant CODE__DUPLICATE_LDATATYPE_IN_PACKAGE. */ |
| public static final String CODE__DUPLICATE_LDATATYPE_IN_PACKAGE = "0_106"; |
| |
| /** The Constant CODE__MISSING__JAVAX_PERSISTENCE. */ |
| public static final String CODE__MISSING__JAVAX_PERSISTENCE = "0_107"; |
| |
| /** The Constant CODE__MISSING__L_RUNTIME_COMMON. */ |
| public static final String CODE__MISSING__L_RUNTIME_COMMON = "0_108"; |
| |
| /** The Constant CODE__MISSING__DATATYPE_LIB. */ |
| public static final String CODE__MISSING__DATATYPE_LIB = "0_109"; |
| |
| /** The Constant CODE__MISSING__DTO_LIB. */ |
| public static final String CODE__MISSING__DTO_LIB = "0_110"; |
| |
| /** The Constant CODE__MISSING__XBASE_LIB. */ |
| public static final String CODE__MISSING__XBASE_LIB = "0_111"; |
| |
| /** The Constant CODE__MISSING__JDK_1_5. */ |
| public static final String CODE__MISSING__JDK_1_5 = "0_112"; |
| |
| /** The Constant CODE__FEATURE_LOWERCASE. */ |
| public static final String CODE__FEATURE_LOWERCASE = "0_113"; |
| |
| public static final String CODE__DUPLICATE_FEATURE_NAME = "0_114"; |
| |
| /** The qnp. */ |
| @Inject |
| private IQualifiedNameProvider qnp; |
| |
| /** The extensions. */ |
| @Inject |
| private ModelExtensions extensions; |
| |
| /** The unique validator. */ |
| @Inject |
| private NamesAreUniqueValidator uniqueValidator; |
| |
| /** The containermanager. */ |
| @Inject |
| private IContainer.Manager containermanager; |
| |
| /** The resource descriptions provider. */ |
| @Inject |
| private ResourceDescriptionsProvider resourceDescriptionsProvider; |
| |
| /** The Constant javakeywords. */ |
| public static final Set<String> javakeywords = new HashSet<String>(); |
| static { |
| javakeywords.add("abstract"); |
| javakeywords.add("assert"); |
| javakeywords.add("boolean"); |
| javakeywords.add("break"); |
| javakeywords.add("byte"); |
| javakeywords.add("case"); |
| javakeywords.add("catch"); |
| javakeywords.add("char"); |
| javakeywords.add("class"); |
| javakeywords.add("const"); |
| javakeywords.add("continue"); |
| javakeywords.add("default"); |
| javakeywords.add("double"); |
| javakeywords.add("do"); |
| javakeywords.add("else"); |
| javakeywords.add("enum"); |
| javakeywords.add("extends"); |
| javakeywords.add("false"); |
| javakeywords.add("final"); |
| javakeywords.add("finally"); |
| javakeywords.add("float"); |
| javakeywords.add("for"); |
| javakeywords.add("goto"); |
| javakeywords.add("if"); |
| javakeywords.add("implements"); |
| javakeywords.add("import"); |
| javakeywords.add("instanceof"); |
| javakeywords.add("int"); |
| javakeywords.add("interface"); |
| javakeywords.add("native"); |
| javakeywords.add("new"); |
| javakeywords.add("null"); |
| javakeywords.add("package"); |
| javakeywords.add("private"); |
| javakeywords.add("protected"); |
| javakeywords.add("public"); |
| javakeywords.add("return"); |
| javakeywords.add("short"); |
| javakeywords.add("static"); |
| javakeywords.add("strictfp"); |
| javakeywords.add("super"); |
| javakeywords.add("switch"); |
| javakeywords.add("synchronized"); |
| javakeywords.add("this"); |
| javakeywords.add("throw"); |
| javakeywords.add("throws"); |
| javakeywords.add("transient"); |
| javakeywords.add("true"); |
| javakeywords.add("try"); |
| javakeywords.add("void"); |
| javakeywords.add("volatile"); |
| javakeywords.add("while"); |
| } |
| |
| /** The Constant primitiveWrappers. */ |
| private static final Set<String> primitiveWrappers = new HashSet<String>(); |
| static { |
| primitiveWrappers.add("java.lang.Integer"); |
| primitiveWrappers.add("java.lang.Long"); |
| primitiveWrappers.add("java.lang.Short"); |
| primitiveWrappers.add("java.lang.Double"); |
| primitiveWrappers.add("java.lang.Float"); |
| primitiveWrappers.add("java.lang.Character"); |
| primitiveWrappers.add("java.lang.Byte"); |
| primitiveWrappers.add("java.lang.Boolean"); |
| } |
| |
| /** |
| * Gets the keywords. |
| * |
| * @return the keywords |
| */ |
| public Set<String> getKeywords() { |
| return Collections.unmodifiableSet(javakeywords); |
| } |
| |
| /** |
| * Check datatype_as primitive. |
| * |
| * @param dt |
| * the dt |
| */ |
| public void checkDatatype_asPrimitive(LDataType dt) { |
| if (dt.isAsPrimitive()) { |
| if (!primitiveWrappers.contains(dt.getJvmTypeReference().getQualifiedName())) { |
| error("The type is not a wrapper from a primitive type!", dt, |
| OSBPTypesPackage.Literals.LDATA_TYPE__AS_PRIMITIVE, |
| ValidationMessageAcceptor.INSIGNIFICANT_INDEX, CODE__NOT_A_VALID_PRIMITIVE, (String[]) null); |
| } |
| } |
| } |
| |
| /** |
| * Check properties_ java key word. |
| * |
| * @param lprop |
| * the lprop |
| */ |
| public void checkProperties_JavaKeyWord(LFeature lprop) { |
| if (lprop.getName() == null) { |
| return; |
| } |
| if (javakeywords.contains(lprop.getName())) { |
| error("The name of the property is a java keyword and not allowed!", |
| OSBPTypesPackage.Literals.LFEATURE__NAME, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, |
| CODE__FORBIDDEN_JAVA_KEYWORD, (String[]) null); |
| } |
| } |
| |
| /** |
| * Check duplicate type_ in project. |
| * |
| * @param type |
| * the type |
| */ |
| public void checkDuplicateType_InProject(LType type) { |
| Map<IContainer, List<LType>> lTypes = getAllFor(type); |
| for (Map.Entry<IContainer, List<LType>> temp : lTypes.entrySet()) |
| if (temp.getValue().size() > 1) { |
| error(String.format("Duplicate type %s in container", qnp.getFullyQualifiedName(type).toString()), type, |
| OSBPTypesPackage.Literals.LTYPE__NAME, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, |
| CODE__DUPLICATE_LTYPE_IN_PROJECT, (String[]) null); |
| } |
| } |
| |
| @Check |
| public void checkDuplicateFeatures(LFeaturesHolder type) { |
| Set<String> names = new HashSet<>(); |
| for (LFeature feature : type.getAllFeatures()) { |
| if(feature.getName() == null) { |
| // annotation support features have no name |
| continue; |
| } |
| if(names.contains(feature.getName())) { |
| error(String.format("Duplicate feature %s in type", feature.getName()), feature, |
| OSBPTypesPackage.Literals.LFEATURE__NAME, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, |
| CODE__DUPLICATE_FEATURE_NAME, (String[]) null); |
| } |
| names.add(feature.getName()); |
| } |
| } |
| |
| /** |
| * Returns a map with the container (class path entry) as key and a |
| * collection with the found types. |
| * |
| * @param lType |
| * the l type |
| * @return the all for |
| */ |
| public Map<IContainer, List<LType>> getAllFor(LType lType) { |
| Map<IContainer, List<LType>> allEntities = new HashMap<IContainer, List<LType>>(); |
| IResourceDescriptions resourceDescriptions = resourceDescriptionsProvider |
| .getResourceDescriptions(lType.eResource()); |
| IResourceDescription resourceDescription = resourceDescriptions |
| .getResourceDescription(lType.eResource().getURI()); |
| List<IContainer> visiblecontainers = containermanager.getVisibleContainers(resourceDescription, |
| resourceDescriptions); |
| for (IContainer container : visiblecontainers) { |
| List<LType> types = new ArrayList<LType>(); |
| allEntities.put(container, types); |
| if (lType.getName() == null) { |
| continue; |
| } |
| for (IEObjectDescription eobjectDescription : container.getExportedObjects(OSBPTypesPackage.Literals.LTYPE, |
| qnp.getFullyQualifiedName(lType), false)) { |
| types.add((LType) eobjectDescription.getEObjectOrProxy()); |
| } |
| } |
| return allEntities; |
| } |
| |
| /** |
| * Check duplicate package_ in project. |
| * |
| * @param lPackage |
| * the l package |
| */ |
| public void checkDuplicatePackage_InProject(LPackage lPackage) { |
| Map<IContainer, List<LPackage>> packages = getAllFor(lPackage); |
| for (Map.Entry<IContainer, List<LPackage>> temp : packages.entrySet()) |
| if (temp.getValue().size() > 1) { |
| warning(String.format("Duplicate package %s in container ", |
| qnp.getFullyQualifiedName(lPackage).toString()), lPackage, |
| OSBPTypesPackage.Literals.LPACKAGE__NAME, CODE__DUPLICATE_LPACKAGE_IN_PROJECT, (String[]) null); |
| } |
| } |
| |
| /** |
| * Returns a map with the container (class path entry) as key and a |
| * collection with the found packages. |
| * |
| * @param lPackage |
| * the l package |
| * @return the all for |
| */ |
| public Map<IContainer, List<LPackage>> getAllFor(LPackage lPackage) { |
| Map<IContainer, List<LPackage>> allEntities = new HashMap<IContainer, List<LPackage>>(); |
| IResourceDescriptions resourceDescriptions = resourceDescriptionsProvider |
| .getResourceDescriptions(lPackage.eResource()); |
| IResourceDescription resourceDescription = resourceDescriptions |
| .getResourceDescription(lPackage.eResource().getURI()); |
| List<IContainer> visiblecontainers = containermanager.getVisibleContainers(resourceDescription, |
| resourceDescriptions); |
| for (IContainer container : visiblecontainers) { |
| List<LPackage> packages = new ArrayList<LPackage>(); |
| allEntities.put(container, packages); |
| for (IEObjectDescription eobjectDescription : container.getExportedObjects( |
| OSBPTypesPackage.Literals.LPACKAGE, qnp.getFullyQualifiedName(lPackage), false)) { |
| packages.add((LPackage) eobjectDescription.getEObjectOrProxy()); |
| } |
| } |
| return allEntities; |
| } |
| |
| /** |
| * Check duplicate datatype in package. |
| * |
| * @param pkg |
| * the pkg |
| */ |
| public void checkDuplicateDatatypeInPackage(LTypedPackage pkg) { |
| Set<String> names = new HashSet<String>(); |
| int counter = 0; |
| for (LType type : pkg.getTypes()) { |
| if (type instanceof LDataType) { |
| String name = ((LDataType) type).getName(); |
| if (!names.add(name)) { |
| error(String.format("Datatype %s must be unique in package %s!", name, pkg.getName()), |
| OSBPTypesPackage.Literals.LTYPED_PACKAGE__TYPES, counter, |
| CODE__DUPLICATE_LDATATYPE_IN_PACKAGE, (String[]) null); |
| break; |
| } |
| } |
| counter++; |
| } |
| } |
| |
| /** |
| * Check feature has name. |
| * |
| * @param feature |
| * the feature |
| */ |
| @Check(CheckType.FAST) |
| public void checkFeatureHasName(LFeature feature) { |
| if (feature.eContainingFeature() != OSBPTypesPackage.Literals.LFEATURE__ANNOTATION_INFO) { |
| if (feature.getName() == null || feature.getName().trim().equals("")) { |
| error("Feature needs a name!", feature, OSBPTypesPackage.Literals.LFEATURE__NAME, "", (String[]) null); |
| } |
| } |
| } |
| |
| /** |
| * Check feature is lowercase. |
| * |
| * @param feature |
| * the feature |
| */ |
| @Check(CheckType.FAST) |
| public void checkFeatureIsLowercase(LFeature feature) { |
| if (feature instanceof LAttribute) { |
| LAttribute att = (LAttribute) feature; |
| if (att.getName() != null && !att.getName().trim().equals("")) { |
| char character = att.getName().charAt(0); |
| if (Character.isUpperCase(character)) { |
| warning("Attribute should start with lower case! Strange behaviour might occur...", feature, |
| OSBPTypesPackage.Literals.LFEATURE__NAME, CODE__FEATURE_LOWERCASE, (String[]) null); |
| } |
| } |
| } else if (feature instanceof LReference) { |
| LReference ref = (LReference) feature; |
| if (ref.getName() != null && !ref.getName().trim().equals("")) { |
| char character = ref.getName().charAt(0); |
| if (Character.isUpperCase(character)) { |
| warning("Reference should start with lower case! Strange behaviour might occur...", feature, |
| OSBPTypesPackage.Literals.LFEATURE__NAME, CODE__FEATURE_LOWERCASE, (String[]) null); |
| } |
| } |
| } |
| } |
| } |