/*
* 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.function.aspects.validation.rules;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.teiid.designer.core.validation.ObjectValidationRule;
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.function.FunctionPlugin;
import org.teiid.designer.metamodels.function.ScalarFunction;
/**
* ScalarFunctionUniquenessRule
*
* @since 8.0
*/
public abstract class FunctionEntityUniquenessRule implements ObjectValidationRule {
private final String ruleName;
/**
* Construct an instance of ScalarFunctionUniquenessRule.
*
*/
public FunctionEntityUniquenessRule() {
super();
this.ruleName = this.getClass().getName();
}
/**
* @see org.teiid.designer.core.validation.ObjectValidationRule#validate(org.eclipse.emf.ecore.EObject, org.teiid.designer.core.validation.ValidationContext)
*/
@Override
public void validate(final EObject eObject, final ValidationContext context) {
if(context.hasRunRule(eObject, this.ruleName)) {
return;
}
// Check whether there are any other scalar functions with a similar signature ...
final List siblings = getSiblingsForUniquenessCheck(eObject);
if ( siblings.size() < 2 ) {
return; // no siblings ...
}
// Get the signature of the siblings ...
final Map siblingsBySignature = new HashMap();
final Iterator iter = siblings.iterator();
while (iter.hasNext()) {
final EObject sibling = (EObject)iter.next();
if ( sibling instanceof ScalarFunction ) {
final String signature = computeSignature(sibling);
List existing = (List) siblingsBySignature.get(signature);
if ( existing == null ) {
existing = new LinkedList();
siblingsBySignature.put(signature,existing);
}
if ( !existing.contains(sibling) ) {
existing.add(sibling);
}
}
}
// Go through all the duplicate signatures and create errors ...
final Iterator iterator = siblingsBySignature.keySet().iterator();
while (iterator.hasNext()) {
final String signature = (String)iterator.next();
final List siblingsWithSameSignature = (List)siblingsBySignature.get(signature);
final int numSiblingsWithSameSignature = siblingsWithSameSignature.size();
// create validation problem and addit to the results
if ( numSiblingsWithSameSignature > 1 ) {
final Iterator siblingIter = siblingsWithSameSignature.iterator();
while (siblingIter.hasNext()) {
final EObject sibling = (EObject)siblingIter.next();
ValidationResult result = new ValidationResultImpl(sibling);
final String msg = getDuplicateMessage(numSiblingsWithSameSignature,signature);
ValidationProblem problem = new ValidationProblemImpl(0, IStatus.ERROR, msg);
result.addProblem(problem);
// add the result to the context
context.addResult(result);
}
}
}
// set the rule has been run
context.recordRuleRun(eObject, this.ruleName);
}
protected abstract String computeSignature(EObject eObject);
protected String getDuplicateMessage( final int numDuplicates, final String signature ) {
final Object[] params = new Object[]{new Integer(numDuplicates-1),signature};
final String msg = FunctionPlugin.Util.getString("FunctionEntityUniquenessRule.Same_signature_as_{0}_sibling(s)__{1}",params); //$NON-NLS-1$
return msg;
}
/**
* Obtain those siblings of the supplied object that are to be considered the domain of objects
* for the uniqueness check.
* @param eObject the object whose name is to be checked for uniqueness amongst its siblings
* @return the siblings that should be used to check for uniqueness in the name; never null
*/
protected List getSiblingsForUniquenessCheck( final EObject eObject ) {
final EObject parent = eObject.eContainer();
if ( parent != null ) {
// eObject is not a parent ...
return parent.eContents();
}
// eObject is one of the roots ...
final Resource resource = eObject.eResource();
if ( resource != null ) {
return resource.getContents();
}
return new ArrayList(1);
}
}