blob: 3682383bd6610dae0f292885382232cc047ef879 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 CEA LIST 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 (CEA LIST) - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.validation;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
/**
* A ComposedEValidator supports validation over a list of EValidators, validation terminating prematurely at
* the first child EValidator that returns false.
* <p>
* A ComposedEValidator may be installed to displace an EValidator.Registry.INSTANCE entry. This in itself is
* harmless but since the EValidator.Registry.INSTANCE is global, any additional EValidators added to the
* ComposedEValidator should restrict their activities to ResourceSets in which they are required.
*/
public class ComposedEValidator implements EValidator
{
private static @Nullable Object getEValidator(@NonNull EValidator.Registry eValidatorRegistry, @NonNull EClass eClass) {
List<EClass> eSuperTypes = eClass.getESuperTypes();
EClass eSuperClass = eSuperTypes.size() > 0 ? eSuperTypes.get(0) : null;
if (eSuperClass == null) {
return eValidatorRegistry.get(null);
}
Object eValidator = eValidatorRegistry.get(eSuperClass.eContainer());
if (eValidator != null) {
return eValidator;
}
return getEValidator(eValidatorRegistry, eSuperClass);
}
/**
* Install a ComposedEValidator for ePackage displacing the prevailing EValidator.Registry.INSTANCE
* entry and adding it as the first ComposedEValidator child.
*/
public static synchronized @NonNull ComposedEValidator install(@NonNull EPackage ePackage) {
Registry eValidatorRegistry = EValidator.Registry.INSTANCE;
synchronized (eValidatorRegistry) {
Object oldEValidator = eValidatorRegistry.get(ePackage);
if (oldEValidator == null) {
for (EClassifier eClassifier : ePackage.getEClassifiers()) {
if (eClassifier instanceof EClass) {
oldEValidator = getEValidator(eValidatorRegistry, (EClass)eClassifier);
if (oldEValidator != null) {
break;
}
}
}
}
if (oldEValidator instanceof ComposedEValidator) {
return (ComposedEValidator) oldEValidator;
}
if (oldEValidator instanceof EValidator.Descriptor) {
oldEValidator = ((EValidator.Descriptor)oldEValidator).getEValidator();
}
ComposedEValidator newEValidator = new ComposedEValidator(oldEValidator instanceof EValidator ? (EValidator) oldEValidator : null);
eValidatorRegistry.put(ePackage, newEValidator);
return newEValidator;
}
}
protected final @NonNull List<EValidator> eValidators = new ArrayList<EValidator>();
public ComposedEValidator(@Nullable EValidator eValidator) {
if (eValidator != null) {
eValidators.add(eValidator);
}
}
/**
* Add a child EValidator, suppressing null and duplicates.
*/
public void addChild(@Nullable EValidator eValidator) {
if (eValidator != null) {
synchronized (this) {
if (!eValidators.contains(eValidator)) {
eValidators.add(eValidator);
}
}
}
}
public @NonNull List<EValidator> getChildren() {
return eValidators;
}
public boolean removeChild(@Nullable EValidator eValidator) {
return eValidators.remove(eValidator);
}
@Override
public boolean validate(EObject eObject, DiagnosticChain diagnostics, Map<Object, Object> context) {
boolean allOk = true;
for (EValidator eValidator : eValidators) {
if (allOk || (diagnostics != null)) {
allOk &= eValidator.validate(eObject, diagnostics, context);
}
}
return allOk;
}
@Override
public boolean validate(EClass eClass, EObject eObject, DiagnosticChain diagnostics, Map<Object, Object> context) {
boolean allOk = true;
for (EValidator eValidator : eValidators) {
if (allOk || (diagnostics != null)) {
allOk &= eValidator.validate(eClass, eObject, diagnostics, context);
}
}
return allOk;
}
@Override
public boolean validate(EDataType eDataType, Object value, DiagnosticChain diagnostics, Map<Object, Object> context) {
boolean allOk = true;
for (EValidator eValidator : eValidators) {
if (allOk || (diagnostics != null)) {
allOk &= eValidator.validate(eDataType, value, diagnostics, context);
}
}
return allOk;
}
}