blob: fb8cd1a24067ec71085c4973bc7f108a7920ccfa [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.bval.jsr303;
import org.apache.bval.jsr303.groups.Group;
import org.apache.bval.jsr303.groups.Groups;
import org.apache.bval.jsr303.groups.GroupsComputer;
import org.apache.bval.model.MetaBean;
import javax.validation.metadata.ConstraintDescriptor;
import javax.validation.metadata.ElementDescriptor;
import javax.validation.metadata.ElementDescriptor.ConstraintFinder;
import javax.validation.metadata.Scope;
import java.lang.annotation.ElementType;
import java.util.*;
/**
* Description: Implementation of the fluent {@link ConstraintFinder} interface.<br/>
*/
final class ConstraintFinderImpl implements ElementDescriptor.ConstraintFinder {
private final MetaBean metaBean;
private final Set<Scope> findInScopes;
private Set<ConstraintValidation<?>> constraintDescriptors;
/**
* Create a new ConstraintFinderImpl instance.
*
* @param metaBean
* @param constraintDescriptors
*/
ConstraintFinderImpl(MetaBean metaBean, Set<ConstraintValidation<?>> constraintDescriptors) {
this.metaBean = metaBean;
this.constraintDescriptors = constraintDescriptors;
this.findInScopes = new HashSet<Scope>(Arrays.asList(Scope.values()));
}
/**
* {@inheritDoc}
*/
public ElementDescriptor.ConstraintFinder unorderedAndMatchingGroups(Class<?>... groups) {
Set<ConstraintValidation<?>> matchingDescriptors =
new HashSet<ConstraintValidation<?>>(constraintDescriptors.size());
Groups groupChain = new GroupsComputer().computeGroups(groups);
for (Group group : groupChain.getGroups()) {
if (group.isDefault()) {
// If group is default, check if it gets redefined
List<Group> expandedDefaultGroup = metaBean.getFeature(Jsr303Features.Bean.GROUP_SEQUENCE);
for (Group defaultGroupMember : expandedDefaultGroup) {
for (ConstraintValidation<?> descriptor : constraintDescriptors) {
if (isInScope(descriptor) && isInGroup(descriptor, defaultGroupMember)) {
matchingDescriptors.add(descriptor);
}
}
}
} else {
for (ConstraintValidation<?> descriptor : constraintDescriptors) {
if (isInScope(descriptor) && isInGroup(descriptor, group)) {
matchingDescriptors.add(descriptor);
}
}
}
}
return thisWith(matchingDescriptors);
}
/**
* {@inheritDoc}
*/
public ElementDescriptor.ConstraintFinder lookingAt(Scope scope) {
if (scope.equals(Scope.LOCAL_ELEMENT)) {
findInScopes.remove(Scope.HIERARCHY);
for (Iterator<ConstraintValidation<?>> it = constraintDescriptors.iterator(); it.hasNext();) {
ConstraintValidation<?> cv = it.next();
if (cv.getOwner() != metaBean.getBeanClass()) {
it.remove();
}
}
}
return this;
}
/**
* {@inheritDoc}
*/
public ElementDescriptor.ConstraintFinder declaredOn(ElementType... elementTypes) {
Set<ConstraintValidation<?>> matchingDescriptors =
new HashSet<ConstraintValidation<?>>(constraintDescriptors.size());
for (ElementType each : elementTypes) {
for (ConstraintValidation<?> descriptor : constraintDescriptors) {
if (isInScope(descriptor) && isAtElement(descriptor, each)) {
matchingDescriptors.add(descriptor);
}
}
}
return thisWith(matchingDescriptors);
}
private boolean isAtElement(ConstraintValidation<?> descriptor, ElementType each) {
return descriptor.getAccess().getElementType() == each;
}
private boolean isInScope(ConstraintValidation<?> descriptor) {
if (findInScopes.size() == Scope.values().length)
return true; // all scopes
if (metaBean != null) {
Class<?> owner = descriptor.getOwner();
for (Scope scope : findInScopes) {
switch (scope) {
case LOCAL_ELEMENT:
if (owner.equals(metaBean.getBeanClass()))
return true;
break;
case HIERARCHY:
if (!owner.equals(metaBean.getBeanClass()))
return true;
break;
}
}
}
return false;
}
private boolean isInGroup(ConstraintValidation<?> descriptor, Group group) {
return descriptor.getGroups().contains(group.getGroup());
}
private ElementDescriptor.ConstraintFinder thisWith(Set<ConstraintValidation<?>> matchingDescriptors) {
constraintDescriptors = matchingDescriptors;
return this;
}
/**
* {@inheritDoc}
*/
public Set<ConstraintDescriptor<?>> getConstraintDescriptors() {
return constraintDescriptors.isEmpty() ? Collections.<ConstraintDescriptor<?>> emptySet() : Collections
.<ConstraintDescriptor<?>> unmodifiableSet(constraintDescriptors);
}
/**
* {@inheritDoc}
*/
public boolean hasConstraints() {
return !constraintDescriptors.isEmpty();
}
}