-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TEIIDDES-1211 Added unique sibling name validation rule that crosses …
…object types
- Loading branch information
Showing
6 changed files
with
232 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
214 changes: 214 additions & 0 deletions
214
.../metamodels/relational/aspects/validation/rules/RelationalChildrenNameValidationRule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
/* | ||
* 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.relational.aspects.validation.rules; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import org.eclipse.core.runtime.IStatus; | ||
import org.eclipse.emf.ecore.EObject; | ||
import org.teiid.core.designer.util.CoreStringUtil; | ||
import org.teiid.designer.core.ModelerCore; | ||
import org.teiid.designer.core.ValidationPreferences; | ||
import org.teiid.designer.core.util.ModelVisitorProcessor; | ||
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.core.ModelAnnotation; | ||
import org.teiid.designer.metamodels.core.ModelType; | ||
import org.teiid.designer.metamodels.relational.Index; | ||
import org.teiid.designer.metamodels.relational.Procedure; | ||
import org.teiid.designer.metamodels.relational.RelationalEntity; | ||
import org.teiid.designer.metamodels.relational.RelationalPlugin; | ||
import org.teiid.designer.metamodels.relational.Table; | ||
import org.teiid.designer.metamodels.relational.util.RelationalUtil; | ||
|
||
/** | ||
* This rule is required to check sibling names of different metamodel types for uniqueness. | ||
* | ||
* Example is an INDEX and a TABLE with same name. This may cause issues when exporting both to DDL and attempting to | ||
* execute that DDL in a DB. | ||
*/ | ||
public class RelationalChildrenNameValidationRule implements ObjectValidationRule { | ||
|
||
private static final String nameFeatureName = RelationalPlugin.Util.getString("_UI_RelationalEntity_name_feature"); //$NON-NLS-1$ | ||
private static final String RULE_NAME = RelationalChildrenNameValidationRule.class.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) { | ||
|
||
// nothing to validate if there are no siblings | ||
if(!shouldRun(eObject, context)) { | ||
return; | ||
} | ||
|
||
// get siblings to validate | ||
List siblings = getSiblingsForUniqueNameCheck(eObject); | ||
if(siblings.isEmpty()) { | ||
return; | ||
} | ||
|
||
final int statusForCaseSensitive = getPreferenceStatus(context); | ||
final int statusForCaseInsensitive = statusForCaseSensitive == IStatus.ERROR ? IStatus.WARNING : statusForCaseSensitive; | ||
|
||
ValidationResults validationResults = new ValidationResults(siblings.size()); | ||
for(int i=0; i < siblings.size(); i++) { | ||
EObject siblingI = (EObject)siblings.get(i); | ||
String nameA = getName(siblingI); | ||
final ValidationResult result = validationResults.get(i,siblingI); | ||
|
||
if(!CoreStringUtil.isEmpty(nameA)) { | ||
for(int j=i+1; j < siblings.size(); j++) { | ||
EObject siblingJ = (EObject)siblings.get(j); | ||
String nameB = getName(siblings.get(j)); | ||
if(!CoreStringUtil.isEmpty(nameB)) { | ||
if(nameA.equals(nameB)) { | ||
// create validation problem and add it to the result | ||
final Object[] params = new Object[]{nameA,nameB,nameFeatureName}; | ||
final String msg = RelationalPlugin.Util.getString("RelationalChildrenNameValidationRule.failure_message_case_sensitive",params); //$NON-NLS-1$ | ||
ValidationProblem problem = new ValidationProblemImpl(0, statusForCaseSensitive,msg); | ||
problem.setHasPreference(context.hasPreferences()); | ||
result.addProblem(problem); | ||
// creating additional validation results on other sibling | ||
// note this would create markers with duplicate messages but targets | ||
// will be different | ||
final ValidationResult resultJ = validationResults.get(j,siblingJ); | ||
ValidationProblem problemJ = new ValidationProblemImpl(0, statusForCaseSensitive,msg); | ||
problemJ.setHasPreference(context.hasPreferences()); | ||
resultJ.addProblem(problemJ); | ||
} else if(nameA.equalsIgnoreCase(nameB)) { | ||
// create validation problem and add it to the result | ||
final Object[] params = new Object[]{nameA,nameB,nameFeatureName}; | ||
final String msg = RelationalPlugin.Util.getString("RelationalChildrenNameValidationRule.failure_message_case_insensitive",params); //$NON-NLS-1$ | ||
ValidationProblem problem = new ValidationProblemImpl(0, statusForCaseInsensitive ,msg); | ||
problem.setHasPreference(context.hasPreferences()); | ||
result.addProblem(problem); | ||
// creating additional validation results on other sibling | ||
// note this would create markers with duplicate messages but targets | ||
// will be different | ||
final ValidationResult resultJ = validationResults.get(j,siblingJ); | ||
ValidationProblem problemJ = new ValidationProblemImpl(0, statusForCaseInsensitive,msg); | ||
problemJ.setHasPreference(context.hasPreferences()); | ||
resultJ.addProblem(problemJ); | ||
} | ||
} | ||
} | ||
} | ||
// add the result to the context | ||
context.addResult(result); | ||
} | ||
} | ||
|
||
//############################################################################################################################ | ||
//# P R O T E C T E D M E T H O D S # | ||
//############################################################################################################################ | ||
|
||
protected class ValidationResults { | ||
private final ValidationResult[] results; | ||
public ValidationResults(final int size) { | ||
this.results = new ValidationResult[size]; | ||
} | ||
public ValidationResult get(final int index, final EObject object ) { | ||
ValidationResult result = this.results[index]; | ||
if ( result == null ) { | ||
result = new ValidationResultImpl(object); | ||
this.results[index] = result; | ||
} | ||
return result; | ||
} | ||
} | ||
|
||
protected int getPreferenceStatus(final ValidationContext context) { | ||
return context.getPreferenceStatus(ValidationPreferences.RELATIONAL_SIBLING_NAME, IStatus.OK); | ||
} | ||
|
||
/** | ||
* This method groups siblings into the following domains, and chooses only those siblings that are in | ||
* the same domain as the supplied object. | ||
* <ul> | ||
* <li>{@link Table} and {@link View} instances</li> | ||
* <li>{@link Procedure} instances</li> | ||
* <li>{@link Index} instances</li> | ||
* <li></li> | ||
* <li></li> | ||
* </ul> | ||
* @see org.teiid.designer.core.validation.rules.StringNameRule#getSiblingsForUniqueNameCheck(org.eclipse.emf.ecore.EObject) | ||
*/ | ||
protected List getSiblingsForUniqueNameCheck(final EObject eObject) { | ||
Object parent = eObject.eContainer(); | ||
if ( parent == null ) { | ||
parent = eObject.eResource(); | ||
} | ||
|
||
if ( eObject instanceof Table || | ||
eObject instanceof Procedure || | ||
eObject instanceof Index ) { | ||
List siblings = new ArrayList(); | ||
siblings.addAll(RelationalUtil.findTables(parent, ModelVisitorProcessor.DEPTH_ONE)); | ||
siblings.addAll(RelationalUtil.findProcedures(parent, ModelVisitorProcessor.DEPTH_ONE)); | ||
siblings.addAll(RelationalUtil.findIndexes(parent, ModelVisitorProcessor.DEPTH_ONE)); | ||
return siblings; | ||
} | ||
return Collections.EMPTY_LIST; | ||
} | ||
|
||
//############################################################################################################################ | ||
//# P R I V A T E M E T H O D S # | ||
//############################################################################################################################ | ||
|
||
// private String getNameInSource(final Object sibling) { | ||
// if(sibling instanceof RelationalEntity) { | ||
// RelationalEntity entity = (RelationalEntity) sibling; | ||
// return entity.getNameInSource(); | ||
// } | ||
// return null; | ||
// } | ||
|
||
private String getName(final Object sibling) { | ||
if(sibling instanceof RelationalEntity) { | ||
RelationalEntity entity = (RelationalEntity) sibling; | ||
return entity.getName(); | ||
} | ||
return ModelerCore.getModelEditor().getModelRelativePathIncludingModel((EObject) sibling).toString(); | ||
} | ||
|
||
private boolean shouldRun(final EObject eObject, final ValidationContext context) { | ||
if(getPreferenceStatus(context) == IStatus.OK) { | ||
return false; | ||
} | ||
|
||
// run the rule only for physical models | ||
try { | ||
ModelAnnotation modelAnnotation = ModelerCore.getModelEditor().getModelAnnotation(eObject); | ||
int modelType = modelAnnotation.getModelType().getValue(); | ||
if(modelType != ModelType.PHYSICAL) { | ||
return false; | ||
} | ||
} catch(Exception e) { | ||
RelationalPlugin.Util.log(IStatus.ERROR, e, e.getMessage()); | ||
} | ||
|
||
// type of object this rule is being run on. | ||
String objType = eObject.eClass().getName(); | ||
// this rule is being run once per object type per parent | ||
if(context.hasRunRule(eObject, RULE_NAME+objType)) { | ||
return false; | ||
} | ||
context.recordRuleRun(eObject, RULE_NAME+objType); | ||
|
||
return true; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters