br.com.anteros.bean.validation.groups.GroupsComputer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Anteros-Bean-Validation Show documentation
Show all versions of Anteros-Bean-Validation Show documentation
Anteros Bean Validation for Java.
/*******************************************************************************
* Copyright 2012 Anteros Tecnologia
*
* 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 br.com.anteros.bean.validation.groups;
import java.util.*;
import br.com.anteros.validation.api.GroupDefinitionException;
import br.com.anteros.validation.api.GroupSequence;
import br.com.anteros.validation.api.ValidationException;
import br.com.anteros.validation.api.groups.Default;
/**
* Description: compute group order, based on the RI behavior as to guarantee
* compatibility with interpretations of the spec.
* Implementation is thread-safe.
*/
public class GroupsComputer {
/** The default group array used in case any of the validate methods is called without a group. */
private static final Groups DEFAULT_GROUPS;
static {
DEFAULT_GROUPS = new GroupsComputer().computeGroups(Arrays.asList(getDefaultGroupArray()));
}
/**
* Get the default group array.
* @return {@link Default}.class
only
*/
public static Class>[] getDefaultGroupArray() {
return new Class>[] { Default.class };
}
/** caching resolved groups in a thread-safe map. */
private final Map, List> resolvedSequences = Collections
.synchronizedMap(new HashMap, List>());
/**
* Compute groups from an array of group classes.
* @param groups
* @return {@link Groups}
*/
public Groups computeGroups(Class>[] groups) {
if (groups == null) {
throw new IllegalArgumentException("null passed as group");
}
// if no groups is specified use the default
if (groups.length == 0) {
return DEFAULT_GROUPS;
}
return computeGroups(Arrays.asList(groups));
}
/**
* Main compute implementation.
* @param groups
* @return {@link Groups}
*/
protected Groups computeGroups(Collection> groups) {
if (groups == null || groups.size() == 0) {
throw new IllegalArgumentException("At least one group has to be specified.");
}
for (Class> clazz : groups) {
if (!clazz.isInterface()) {
throw new ValidationException(
"A group has to be an interface. " + clazz.getName() + " is not.");
}
}
Groups chain = new Groups();
for (Class> clazz : groups) {
GroupSequence anno = clazz.getAnnotation(GroupSequence.class);
if (anno == null) {
Group group = new Group(clazz);
chain.insertGroup(group);
insertInheritedGroups(clazz, chain);
} else {
insertSequence(clazz, anno, chain);
}
}
return chain;
}
private void insertInheritedGroups(Class> clazz, Groups chain) {
for (Class> extendedInterface : clazz.getInterfaces()) {
Group group = new Group(extendedInterface);
chain.insertGroup(group);
insertInheritedGroups(extendedInterface, chain);
}
}
private void insertSequence(Class> clazz, GroupSequence anno, Groups chain) {
List sequence;
if (resolvedSequences.containsKey(clazz)) {
sequence = resolvedSequences.get(clazz);
} else {
sequence = resolveSequence(clazz, anno, new HashSet>());
}
chain.insertSequence(sequence);
}
private List resolveSequence(Class> group, GroupSequence sequenceAnnotation,
Set> processedSequences) {
if (processedSequences.contains(group)) {
throw new GroupDefinitionException("Cyclic dependency in groups definition");
} else {
processedSequences.add(group);
}
List resolvedGroupSequence = new LinkedList();
Class>[] sequenceArray = sequenceAnnotation.value();
for (Class> clazz : sequenceArray) {
GroupSequence anno = clazz.getAnnotation(GroupSequence.class);
if (anno == null) {
resolvedGroupSequence.add(new Group(clazz)); // group part of sequence
} else {
List tmpSequence =
resolveSequence(clazz, anno, processedSequences); // recursion!
resolvedGroupSequence.addAll(tmpSequence);
}
}
resolvedSequences.put(group, resolvedGroupSequence);
return resolvedGroupSequence;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy