org.switchyard.internal.validate.BaseValidatorRegistry Maven / Gradle / Ivy
/*
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.switchyard.internal.validate;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EventObject;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.namespace.QName;
import org.jboss.logging.Logger;
import org.switchyard.common.xml.QNameUtil;
import org.switchyard.event.EventPublisher;
import org.switchyard.event.ValidatorAddedEvent;
import org.switchyard.event.ValidatorRemovedEvent;
import org.switchyard.runtime.RuntimeMessages;
import org.switchyard.validate.ValidationResult;
import org.switchyard.validate.Validator;
import org.switchyard.validate.ValidatorRegistry;
/**
* Maintains a local collection of validation instances and provides
* facilities to add, query, and remove validates.
*/
public class BaseValidatorRegistry implements ValidatorRegistry {
private static Logger _log = Logger.getLogger(BaseValidatorRegistry.class);
private final ConcurrentHashMap> _validators =
new ConcurrentHashMap>();
private final ConcurrentHashMap> _fallbackValidators =
new ConcurrentHashMap>();
private EventPublisher _eventPublisher;
/**
* Constructor.
*/
public BaseValidatorRegistry() {
}
/**
* Create a new ValidatorRegistry instance and add the list of validators
* to the registry.
* @param validators set of validators to add to registry
*/
public BaseValidatorRegistry(Set> validators) {
for (Validator> t : validators) {
addValidator(t);
}
}
@Override
public BaseValidatorRegistry addValidator(Validator> validator) {
_fallbackValidators.clear();
_validators.put(validator.getName(), validator);
publishEvent(new ValidatorAddedEvent(validator));
return this;
}
@Override
public ValidatorRegistry addValidator(Validator> validator, QName name) {
_fallbackValidators.clear();
_validators.put(name, validator);
publishEvent(new ValidatorAddedEvent(validator));
return null;
}
@Override
public Validator> getValidator(QName name) {
Validator> validator = _validators.get(name);
if (validator == null) {
validator = _fallbackValidators.get(name);
if (validator == null && QNameUtil.isJavaMessageType(name)) {
validator = getJavaFallbackValidator(name);
if (validator != null && _log.isDebugEnabled()) {
_log.debug("Selecting fallback validator: name '" + validator.getName() + "'. Type: " + validator.getClass().getName());
} else if (_log.isDebugEnabled()) {
_log.debug("No compatible validator registered: name '" + name + "'");
}
}
} else if (_log.isDebugEnabled()) {
_log.debug("Selecting validator: name '" + validator.getName() + "'. Type: " + validator.getClass().getName());
}
return validator == NULL_VALIDATOR ? null : validator;
}
@Override
public boolean hasValidator(QName name) {
return _validators.containsKey(name);
}
@Override
public boolean removeValidator(Validator> validator) {
_fallbackValidators.clear();
boolean removed = _validators.remove(validator.getName()) != null;
if (removed) {
publishEvent(new ValidatorRemovedEvent(validator));
}
return removed;
}
/**
* Sets the EventPublisher instance to be used for validator events.
* @param eventPublisher event publisher
*/
public void setEventPublisher(EventPublisher eventPublisher) {
_eventPublisher = eventPublisher;
}
// Convenience method to guard against cases when an event publisher has
// not been set.
private void publishEvent(EventObject event) {
if (_eventPublisher != null) {
_eventPublisher.publish(event);
}
}
private Validator> getJavaFallbackValidator(QName name) {
Class> javaType = QNameUtil.toJavaMessageType(name);
if (javaType == null) {
return null;
}
Set>> entrySet = _validators.entrySet();
List fallbackValidates = new ArrayList();
for (Map.Entry> entry : entrySet) {
QName nameKey = entry.getKey();
if (QNameUtil.isJavaMessageType(nameKey)) {
Class> candidateType = QNameUtil.toJavaMessageType(nameKey);
if (candidateType != null && candidateType.isAssignableFrom(javaType)) {
fallbackValidates.add(new JavaSourceFallbackValidator(candidateType, entry.getValue()));
}
}
}
if (fallbackValidates.size() == 0) {
addFallbackValidator(NULL_VALIDATOR, name);
return NULL_VALIDATOR;
}
if (fallbackValidates.size() == 1) {
Validator> fallbackValidator = fallbackValidates.get(0).getValidator();
addFallbackValidator(fallbackValidator, name);
return fallbackValidator;
}
JavaSourceFallbackValidatorComparator comparator = new JavaSourceFallbackValidatorComparator();
Collections.sort(fallbackValidates, comparator);
if (_log.isDebugEnabled()) {
StringBuilder messageBuilder = new StringBuilder();
messageBuilder.append(RuntimeMessages.MESSAGES.multipleFallbackValidatorsAvailable());
for (JavaSourceFallbackValidator t : fallbackValidates) {
messageBuilder.append("\n\t- name '" + t.getValidator().getName() + "'");
}
_log.debug(messageBuilder.toString());
}
// Closest super-type will be first in the list..
Validator> fallbackValidator = fallbackValidates.get(0).getValidator();
addFallbackValidator(fallbackValidator, name);
return fallbackValidator;
}
private void addFallbackValidator(Validator> fallbackValidator, QName name) {
// Fallback validators are cached so as to save on lookup times...
_fallbackValidators.put(name, fallbackValidator);
}
/**
* Holder type for Fallback Validator.
*/
public static class JavaSourceFallbackValidator {
private Class> _javaType;
private Validator> _validator;
/**
* Constructor.
* @param javaType Java type.
* @param validator Validator instance.
*/
public JavaSourceFallbackValidator(Class> javaType, Validator> validator) {
this._javaType = javaType;
this._validator = validator;
}
/**
* Get the Java type.
* @return The Java type.
*/
public Class> getJavaType() {
return _javaType;
}
/**
* Get the Validator.
* @return The Validator.
*/
public Validator> getValidator() {
return _validator;
}
}
/**
* Fallback Validator Sorter.
* @param JavaSourceFallbackValidator.
*/
@SuppressWarnings("serial")
public static class JavaSourceFallbackValidatorComparator implements Comparator, Serializable {
@Override
public int compare(T t1, T t2) {
if (t1.getJavaType() == t2.getJavaType()) {
return 0;
} else if (t1.getJavaType().isAssignableFrom(t2.getJavaType())) {
return 1;
} else if (t2.getJavaType().isAssignableFrom(t1.getJavaType())) {
return -1;
} else {
// Unrelated types. This means there are branches in the inheritance options,
// which means there are multiple possibilities, therefore it's not uniquely resolvable.
// Marking as equal for now...
return 0;
}
}
}
/**
* NULL_VALIDATOR is a default validator used to prevent searching for
* fallback validators multiple times. Searching for fallback validators is
* expensive because of Class.forName() usage.
*/
private static final Validator NULL_VALIDATOR = new Validator() {
@Override
public ValidationResult validate(Object content) {
return null;
}
@Override
public Validator setName(QName name) {
return null;
}
@Override
public QName getName() {
return null;
}
@Override
public Class getType() {
return null;
}
};
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy