blob: 735fe52e16f1dedf13e69546c47b66d47ce219f8 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2008 E.D.Willink and others.
* 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:
* E.D.Willink - initial API and implementation
*
* </copyright>
*
* $Id: AbstractValidatorOperations.java,v 1.2 2009/01/14 20:58:50 ewillink Exp $
*/
package org.eclipse.qvt.declarative.ecore.operations;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.ResourceLocator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.plugin.EcorePlugin;
import org.eclipse.emf.ecore.util.EObjectValidator;
import org.eclipse.osgi.util.NLS;
/**
* AbstractOperations provides shared functionality that derived classes
* implementing Validator checking may find useful.
*/
public abstract class AbstractValidatorOperations extends AbstractOperations
{
public static final String ECORE_DIAGNOSTIC_SOURCE = EObjectValidator.DIAGNOSTIC_SOURCE;
public abstract class UniquenessChecker<K extends EObject,V extends EObject>
{
/*
* Check that each value has a distinct getKey(), appending an
* error for each uniqueness failure. (If there are N same-keyed
* values, N-1 errors are appended.)
*/
public boolean check(List<? extends V> values, String errorMessage, EObject contextObject, DiagnosticChain diagnostics, Map<Object, Object> context) {
boolean allOk = true;
Map<K, V> keyToFirstValue = new HashMap<K, V>();
for (V value : values)
{
K key = getKey(value);
V firstValue = keyToFirstValue.get(key);
if (firstValue == null)
keyToFirstValue.put(key, value);
else {
allOk = false;
Object typedModelLabel = getObjectLabel(key, context);
Object objectLabel = getObjectLabel(value, context);
Object firstObjectLabel = getObjectLabel(firstValue, context);
Object[] messageSubstitutions = new Object[] { typedModelLabel, objectLabel, firstObjectLabel };
appendDiagnostic(diagnostics, contextObject, getSeverity(), errorMessage, messageSubstitutions);
}
}
return allOk;
}
/*
* Implement to provide the 'unique' key for a value.
*/
protected abstract K getKey(V value);
protected int getSeverity() {
return Diagnostic.ERROR;
}
}
protected final EValidatorWithOperations validator;
protected final Map<String, Integer> messageToCode = new HashMap<String, Integer>();
protected AbstractValidatorOperations(EValidatorWithOperations validator) {
this.validator = validator;
}
protected void appendDiagnostic(DiagnosticChain diagnostics, Object astNode, int severity, String errorMessage, Object[] messageSubstitutions) {
appendDiagnostic(diagnostics, new Object[] { astNode }, severity, errorMessage, messageSubstitutions);
}
protected void appendDiagnostic(DiagnosticChain diagnostics, Object[] astNodes, int severity, String errorMessage, Object[] messageSubstitutions) {
appendDiagnostic(diagnostics, astNodes, validator.getDiagnosticSource(), severity, errorMessage, messageSubstitutions);
}
protected void appendDiagnostic(DiagnosticChain diagnostics, Object[] astNodes, String diagnosticSource, int severity, String errorMessage, Object[] messageSubstitutions) {
if (diagnostics != null) {
int errorCode = getErrorCode(errorMessage);
String message = NLS.bind(errorMessage, messageSubstitutions);
Diagnostic diagnostic = new BasicDiagnostic(severity, diagnosticSource, errorCode, message, astNodes);
diagnostics.add(diagnostic);
}
}
protected void appendError(DiagnosticChain diagnostics, Object astNode, String errorMessage, Object[] messageSubstitutions) {
appendDiagnostic(diagnostics, astNode, Diagnostic.ERROR, errorMessage, messageSubstitutions);
}
protected void appendError(DiagnosticChain diagnostics, Object[] astNodes, String errorMessage, Object[] messageSubstitutions) {
appendDiagnostic(diagnostics, astNodes, Diagnostic.ERROR, errorMessage, messageSubstitutions);
}
protected void appendWarning(DiagnosticChain diagnostics, Object astNode, String errorMessage, Object[] messageSubstitutions) {
appendDiagnostic(diagnostics, astNode, Diagnostic.WARNING, errorMessage, messageSubstitutions);
}
protected void appendWarning(DiagnosticChain diagnostics, Object[] astNodes, String errorMessage, Object[] messageSubstitutions) {
appendDiagnostic(diagnostics, astNodes, Diagnostic.WARNING, errorMessage, messageSubstitutions);
}
public boolean checkUniqueNames(Object parent, List<? extends ENamedElement> eNamedElements, String errorMessage, DiagnosticChain diagnostics, Map<Object, Object> context)
{
boolean allOk = true;
Map<String, ENamedElement> nameToFirst = new HashMap<String, ENamedElement>();
for (ENamedElement eNamedElement : eNamedElements)
{
String name = eNamedElement.getName();
ENamedElement firstENamedElement = nameToFirst.get(name);
if (firstENamedElement == null)
nameToFirst.put(name, eNamedElement);
else {
allOk = false;
Object objectLabel = getObjectLabel(eNamedElement, context);
Object firstObjectLabel = getObjectLabel(firstENamedElement, context);
Object[] messageSubstitutions = new Object[] { name, objectLabel, firstObjectLabel };
appendError(diagnostics, parent, errorMessage, messageSubstitutions);
}
}
return allOk;
}
@Deprecated
protected Diagnostic createDiagnostic(int severity, String source, int code, String messageKey, Object[] messageSubstitutions, Object[] data, Map<Object, Object> context) {
String message = ECORE_DIAGNOSTIC_SOURCE.equals(source) ?
getEcoreString(messageKey, messageSubstitutions) :
getString(messageKey, messageSubstitutions);
return new BasicDiagnostic(severity, source, code, message, data);
}
public boolean definesOppositeProperty(EClass eClass, EReference property) {
return property != null && isSuperClassOf(property.getEReferenceType(), eClass);
}
public boolean definesProperty(EClass eClass, EStructuralFeature property) {
return property != null && isSuperClassOf(property.getEContainingClass(), eClass);
}
protected <T extends EObject> T getAncestor(EObject eObject, Class<T> requiredClass) {
if (eObject == null)
return null;
else if (requiredClass.isAssignableFrom(eObject.getClass())) {
@SuppressWarnings("unchecked")
T object = (T) eObject;
return object;
} else
return getAncestor(eObject.eContainer(), requiredClass);
}
protected String getEcoreString(String key, Object [] substitutions) {
return getString(EcorePlugin.INSTANCE, key, substitutions);
}
/**
* Return the integer error code associated with errorMessage, or
* zero if the errorMessage has not been registered.
*/
public int getErrorCode(String message) {
Integer code = messageToCode.get(message);
return code != null ? code.intValue() : 0;
}
public <T extends ENamedElement> Map<String, T> getNames(List<T> eNamedElements)
{
Map<String, T> map = new HashMap<String, T>();
for (T eNamedElement : eNamedElements)
map.put(eNamedElement.getName(), eNamedElement);
return map;
}
protected String getObjectLabel(EObject eObject, Map<Object, Object> context) {
return EObjectValidator.getObjectLabel(eObject, context);
}
protected String getString(String key, Object [] substitutions) {
if ("_UI_GenericConstraint_diagnostic".equals(key))
return getString(EcorePlugin.INSTANCE, key, substitutions);
else
return getString(validator.getResourceLocator(), key, substitutions);
}
private String getString(ResourceLocator resourceLocator, String key, Object [] substitutions) {
if (substitutions == null)
return resourceLocator.getString(key);
else
return resourceLocator.getString(key, substitutions);
}
public EValidatorWithOperations getValidator() {
return validator;
}
public boolean hasAncestor(EObject childObject, EObject parentObject) {
for (EObject eObject = childObject; eObject != null; eObject = eObject.eContainer())
if (eObject == parentObject)
return true;
return false;
}
public boolean isSuperClassOf(EClass targetClass, EClass queryClass) {
if (targetClass == null)
return false;
if (queryClass == null)
return false;
return targetClass.isSuperTypeOf(queryClass);
}
/**
* Return the integer error code associated with errorMessage, or
* zero if the errorMessage has not been registered.
*
* Return non-null for a previous registration.
*/
public Integer registerErrorCode(String message, int errorCode) {
return messageToCode.put(message, Integer.valueOf(errorCode));
}
}