/**
* Copyright (c) 2011 - 2015, Lunifera GmbH (Gross Enzersdorf), Loetz KG (Heidelberg)
* 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:
* Florian Pirchner - Initial implementation
*/
package org.lunifera.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.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.NamesAreUniqueValidator;
import org.eclipse.xtext.validation.ValidationMessageAcceptor;
import org.lunifera.dsl.common.xtext.extensions.ModelExtensions;
import org.lunifera.dsl.semantic.common.types.LDataType;
import org.lunifera.dsl.semantic.common.types.LFeature;
import org.lunifera.dsl.semantic.common.types.LPackage;
import org.lunifera.dsl.semantic.common.types.LType;
import org.lunifera.dsl.semantic.common.types.LTypedPackage;
import org.lunifera.dsl.semantic.common.types.LunTypesPackage;
import com.google.inject.Inject;
/**
* Custom validation rules.
*
* see http://www.eclipse.org/Xtext/documentation.html#validation
*/
public class CommonGrammarJavaValidator
extends
org.lunifera.dsl.common.xtext.validation.AbstractCommonGrammarJavaValidator {
public static final String CODE__DUPLICATE_LPACKAGE_IN_PROJECT = "0_100";
public static final String CODE__DUPLICATE_LTYPE_IN_PROJECT = "0_101";
public static final String CODE__DUPLICATE_LPACKAGE_IN_FILE = "0_102";
public static final String CODE__MANY_TO_MANY__NOT_SUPPORTED = "0_103";
public static final String CODE__NOT_A_VALID_PRIMITIVE = "0_104";
public static final String CODE__FORBIDDEN_JAVA_KEYWORD = "0_105";
public static final String CODE__DUPLICATE_LDATATYPE_IN_PACKAGE = "0_106";
@Inject
private IQualifiedNameProvider qnp;
@Inject
private ModelExtensions extensions;
@Inject
private NamesAreUniqueValidator uniqueValidator;
@Inject
private IContainer.Manager containermanager;
@Inject
private ResourceDescriptionsProvider resourceDescriptionsProvider;
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");
}
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");
}
public Set<String> getKeywords() {
return Collections.unmodifiableSet(javakeywords);
}
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,
LunTypesPackage.Literals.LDATA_TYPE__AS_PRIMITIVE,
ValidationMessageAcceptor.INSIGNIFICANT_INDEX,
CODE__NOT_A_VALID_PRIMITIVE, (String[]) null);
}
}
}
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!",
LunTypesPackage.Literals.LFEATURE__NAME,
ValidationMessageAcceptor.INSIGNIFICANT_INDEX,
CODE__FORBIDDEN_JAVA_KEYWORD, (String[]) null);
}
}
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,
LunTypesPackage.Literals.LTYPE__NAME,
ValidationMessageAcceptor.INSIGNIFICANT_INDEX,
CODE__DUPLICATE_LTYPE_IN_PROJECT, (String[]) null);
}
}
/**
* Returns a map with the container (class path entry) as key and a
* collection with the found types.
*
* @param type
* @return
*/
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(LunTypesPackage.Literals.LTYPE,
qnp.getFullyQualifiedName(lType), false)) {
types.add((LType) eobjectDescription.getEObjectOrProxy());
}
}
return allEntities;
}
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,
LunTypesPackage.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 type
* @return
*/
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(LunTypesPackage.Literals.LPACKAGE,
qnp.getFullyQualifiedName(lPackage), false)) {
packages.add((LPackage) eobjectDescription.getEObjectOrProxy());
}
}
return allEntities;
}
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()),
LunTypesPackage.Literals.LTYPED_PACKAGE__TYPES,
counter, CODE__DUPLICATE_LDATATYPE_IN_PACKAGE,
(String[]) null);
break;
}
}
counter++;
}
}
}