/*
* 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.core.validation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.teiid.designer.core.ModelerCore;
/**
* ValidationRuleSet
*
* @since 8.0
*/
public class ValidationRuleSetImpl implements ValidationRuleSet {
private static final String EXCEPTION_DURING_VALIDATION_MSG = ModelerCore.Util.getString("ValidationRuleSetImpl.An_exception_was_encountered_during_validation._Check_the_log_for_details._1"); //$NON-NLS-1$
private static final String EXCEPTION_DURING_VALIDATION_LOG_MSG = ModelerCore.Util.getString("ValidationRuleSetImpl.An_exception_was_encountered_during_validation._2"); //$NON-NLS-1$
private static final ValidationRule[] EMPTY_ARRAY = new ValidationRule[0];
private ArrayList ruleSet;
/* (non-Javadoc)
* @See org.teiid.designer.core.validation.ValidationRuleSet#addRule(org.teiid.designer.core.validation.ValidationRule)
*/
@Override
public void addRule(final ValidationRule rule) {
if (rule == null) {
return;
}
if (ruleSet == null) {
ruleSet = new ArrayList(5);
}
boolean exists = false;
for (Object existingRule : ruleSet) {
if (existingRule == rule) {
exists = true;
break;
}
}
if (!exists) {
ruleSet.add(rule);
}
}
/* (non-Javadoc)
* @See org.teiid.designer.core.validation.ValidationRuleSet#getRules()
*/
@Override
public ValidationRule[] getRules() {
if ( !hasRules() ) {
return EMPTY_ARRAY;
}
ValidationRule[] result = new ValidationRule[ruleSet.size()];
ruleSet.toArray(result);
return result;
}
/* (non-Javadoc)
* @See org.teiid.designer.core.validation.ValidationRuleSet#hasRules()
*/
@Override
public boolean hasRules() {
return (ruleSet != null && ruleSet.size() > 0);
}
/* (non-Javadoc)
* @See org.teiid.designer.core.validation.ValidationRuleSet#validate(java.lang.Object, org.teiid.designer.core.validation.ValidationContext)
*/
@Override
public void validate(final IProgressMonitor progressMonitor, final Object object, final ValidationContext context) {
if ( !hasRules() ) {
return;
}
final IProgressMonitor monitor = progressMonitor != null ? progressMonitor : new NullProgressMonitor();
try {
// Run the ObjectValidationRule set
for (int i = 0, n = ruleSet.size(); i < n; i++) {
if(monitor.isCanceled()) {
return;
}
// see if context already has a fatal error for this object or it's resource.
// if it does don't validate object further
if (object instanceof EObject) {
Collection results = context.getTargetResults((EObject)object);
if ((results != null) && !results.isEmpty()) {
Iterator itr = results.iterator();
while (itr.hasNext()) {
ValidationResult result = (ValidationResult)itr.next();
if (result.isFatalResource() || result.isFatalObject(object)) {
return;
}
}
}
}
final ValidationRule rule = (ValidationRule)ruleSet.get(i);
if(object instanceof EObject) {
final EObject target = (EObject)object;
if (rule instanceof ObjectValidationRule) {
final ObjectValidationRule objRule = (ObjectValidationRule) rule;
// Apply this rule to the EObject
objRule.validate(target,context);
// Run the StructuralFeatureValidationRule set
} else if (rule instanceof StructuralFeatureValidationRule) {
final StructuralFeatureValidationRule featureRule = (StructuralFeatureValidationRule) rule;
// Apply this rule to all features associated with this EObject
final List features = target.eClass().getEAllStructuralFeatures();
for (Iterator iter = features.iterator(); iter.hasNext();) {
// Apply this rule to the EObject
EStructuralFeature feature = (EStructuralFeature)iter.next();
// don't validate volatile or transit features. validating these types of features
// took enormous amounts of time (see Defect 15699). Since these features
// are normally derived and/or not persisted, not validating them usually won't
// be a problem. readdress if it becomes a problem.
if (!feature.isVolatile() || !feature.isTransient()) {
featureRule.validate(feature, target, target.eGet(feature), context);
}
}
}
} else if(object instanceof Resource) {
final Resource resource = (Resource)object;
if (rule instanceof ResourceValidationRule) {
final ResourceValidationRule rscRule = (ResourceValidationRule) rule;
// Apply this rule to the resource
rscRule.validate(resource,context);
}
}
}
} catch (Throwable e) {
String errMsg = e.getMessage();
if (errMsg != null && errMsg.length() > 0) {
addProblem(object, 0, IStatus.ERROR, e.getMessage(), context);
} else {
addProblem(object, 0, IStatus.ERROR, EXCEPTION_DURING_VALIDATION_MSG, context);
ModelerCore.Util.log(IStatus.ERROR,e,EXCEPTION_DURING_VALIDATION_LOG_MSG);
}
}
}
private void addProblem(final Object object, final int code, final int severity,
final String msg, final ValidationContext context) {
ValidationProblem problem = new ValidationProblemImpl(code, severity, msg);
ValidationResult result = new ValidationResultImpl(object);
result.addProblem(problem);
context.addResult(result);
}
}