blob: f517670f55978b3406c6fe6c81fce611d8a51dab [file]
/*
* Copyright 2012 Google Inc.
*
* 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 com.google.gwt.validation.client;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Stack;
import javax.validation.groups.Default;
/**
* <strong>EXPERIMENTAL</strong> and subject to change. Do not use this in
* production code.
* <p>
* Contains all the information known about the inheritance information for validation groups.
*/
public class GroupInheritanceMap {
/**
* Builder for {@link GroupInheritanceMap}
*/
public static class Builder {
Map<Class<?>, Set<Class<?>>> mapping;
private Builder() {
mapping = new HashMap<Class<?>, Set<Class<?>>>();
addGroup(Default.class);
}
/**
* Adds a group to the inheritance map. May optionally include parents of the group.
* @param group The validation group to add.
* @param parents A list of validation groups which {@code group} extends. Can be empty if the
* group contains no parents.
*/
public Builder addGroup(Class<?> group, Class<?>... parents) {
mapping.put(group, new HashSet<Class<?>>(Arrays.asList(parents)));
return this;
}
public GroupInheritanceMap build() {
return new GroupInheritanceMap(mapping);
}
}
/**
* Creates a builder populated only with the {@link Default} group.
*/
public static Builder builder() {
return new Builder();
}
private final Map<Class<?>, Set<Class<?>>> mapping;
private GroupInheritanceMap(Map<Class<?>, Set<Class<?>>> mapping) {
this.mapping = Collections.unmodifiableMap(mapping);
}
/**
* Checks if a given group has been added to the map.
*/
public boolean containsGroup(Class<?> group) {
return mapping.containsKey(group);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof GroupInheritanceMap)) {
return false;
}
GroupInheritanceMap otherObj = (GroupInheritanceMap)other;
return mapping.equals(otherObj.mapping);
}
/**
* Finds all of the validation groups extended by an intial set of groups.
* @param baseGroups The initial set of groups to find parents of. These groups must have been
* added to the inheritance map already.
* @return A unified set of groups and their parents.
* @throws IllegalArgumentException If an initial group has not been added to the map before
* calling this method.
*/
public Set<Class<?>> findAllExtendedGroups(Collection<Class<?>> baseGroups)
throws IllegalArgumentException {
Set<Class<?>> found = new HashSet<Class<?>>();
Stack<Class<?>> remaining = new Stack<Class<?>>();
// initialize
for (Class<?> group : baseGroups) {
if (!mapping.containsKey(group)) {
throw new IllegalArgumentException("The collection of groups contains a group which" +
" was not added to the map. Be sure to call addGroup() for all groups first.");
}
remaining.push(group);
}
// traverse
Class<?> current;
Set<Class<?>> superInterfaces;
while (!remaining.isEmpty()) {
current = remaining.pop();
found.add(current);
superInterfaces = mapping.get(current);
for (Class<?> parent : superInterfaces) {
if (!found.contains(parent)) {
remaining.push(parent);
}
}
}
return found;
}
/**
* Recursively gets all of the groups in the map (children and parents alike) in one flat set.
*/
public Set<Class<?>> getAllGroups() {
Set<Class<?>> allGroups = new HashSet<Class<?>>();
for (Map.Entry<Class<?>, Set<Class<?>>> entry : mapping.entrySet()) {
allGroups.add(entry.getKey());
allGroups.addAll(entry.getValue());
}
return allGroups;
}
/**
* If the group has been added to the map then its parent groups (of one level above) are
* retrieved. Otherwise null is returned.
*
* @see #containsGroup(Class)
* @see #findAllExtendedGroups(Collection)
*/
public Set<Class<?>> getParentsOfGroup(Class<?> group) {
return mapping.get(group);
}
/**
* Returns all of the groups added to the map (but not their parents).
*/
public Set<Class<?>> getRootGroups() {
return mapping.keySet();
}
@Override
public int hashCode() {
return mapping.hashCode();
}
public boolean isEmpty() {
return mapping.isEmpty();
}
@Override
public String toString() {
return mapping.toString();
}
}