/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.metamodels.xsd.aspects.validation.rules;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.util.XSDConstants;
import org.teiid.designer.core.validation.StructuralFeatureValidationRule;
import org.teiid.designer.core.validation.ValidationContext;
import org.teiid.designer.core.validation.ValidationProblem;
import org.teiid.designer.core.validation.ValidationProblemImpl;
import org.teiid.designer.core.validation.ValidationResult;
import org.teiid.designer.core.validation.ValidationResultImpl;
import org.teiid.designer.metamodels.xsd.XsdPlugin;
/**
* StringNameRule, rule that validates the string name
*
* @since 8.0
*/
public class BaseTypeRule implements StructuralFeatureValidationRule {
// id of the feature being validated
private int featureID;
/**
* Construct an instance of RuntimeTypeRule.
* @param featureID ID of the feature to validate
*/
public BaseTypeRule(int featureID) {
this.featureID = featureID;
}
/* (non-Javadoc)
* @See org.teiid.designer.core.validation.ValidationRule#validate(java.lang.Object, org.teiid.designer.core.validation.ValidationContext)
*/
@Override
public void validate(EStructuralFeature eStructuralFeature, EObject eObject, Object value, ValidationContext context) {
// check if the feature matches the given feature
if (eStructuralFeature.getFeatureID() != this.featureID) {
return;
}
// Check that the EObject is an instanceof SimpleDatatype
// otherwise we cannot apply this rule
if (eObject == null || !(eObject instanceof XSDSimpleTypeDefinition)) {
return;
}
ValidationResult result = new ValidationResultImpl(eObject);
// The basetype reference cannot be null
if (value == null) {
// create validation problem and add it to the result
ValidationProblem problem = new ValidationProblemImpl(0, IStatus.ERROR, XsdPlugin.Util.getString("BaseTypeRule.The_basetype_may_not_be_null_1")); //$NON-NLS-1$
result.addProblem(problem);
context.addResult(result);
return;
}
// Check that the value is an instance of XSDSimpleTypeDefinition
// otherwise we cannot apply this rule
if (!(value instanceof XSDSimpleTypeDefinition)) {
// create validation problem and add it to the result
ValidationProblem problem = new ValidationProblemImpl(0, IStatus.ERROR, XsdPlugin.Util.getString("BaseTypeRule.The_basetype_must_be_a_simple_type_definition_2")); //$NON-NLS-1$
result.addProblem(problem);
context.addResult(result);
return;
}
// Check that the basetype is not the same instance as the
// basetype (i.e. a datatype cannot have itself as its basetype)
if (eObject == value) {
// create validation problem and add it to the result
ValidationProblem problem = new ValidationProblemImpl(0, IStatus.ERROR, XsdPlugin.Util.getString("BaseTypeRule.The_datatype_cannot_have_itself_as_its_basetype_1")); //$NON-NLS-1$
result.addProblem(problem);
context.addResult(result);
return;
}
// Check that there are no circular dependencies within the datatype hierarchy
XSDSimpleTypeDefinition datatype = (XSDSimpleTypeDefinition) eObject;
if (this.hasCircularDependency(datatype)) {
ValidationProblem problem = new ValidationProblemImpl(0, IStatus.ERROR, XsdPlugin.Util.getString("BaseTypeRule.Cannot_have_a_circular_dependency_in_the_datatype_hierarchy_2")); //$NON-NLS-1$
result.addProblem(problem);
context.addResult(result);
return;
}
// add the result to the context
context.addResult(result);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
private boolean hasCircularDependency(final XSDSimpleTypeDefinition datatype) {
if (datatype == null) {
return false;
}
List typesInHierarchy = new ArrayList();
typesInHierarchy.add(this);
XSDSimpleTypeDefinition baseTypeDefn = datatype.getBaseTypeDefinition();
if (this.equals(baseTypeDefn)) {
return true;
}
while (baseTypeDefn != null && baseTypeDefn.getName() != null) {
// If the base type is "anyType" or "anySimpleType" then we have
// traversed the hierarchy without finding any circular dependencies
if (XSDConstants.isURType(baseTypeDefn)) {
return false;
}
// If the basetype already exists somewhere in the hierarchy
// then we have a circular dependency
if (typesInHierarchy.contains(baseTypeDefn)) {
return true;
}
// Tranverse up the hierarchy to the next super type
typesInHierarchy.add(baseTypeDefn);
baseTypeDefn = baseTypeDefn.getBaseTypeDefinition();
}
return false;
}
}