blob: e022ccf231be272eb897ba42502c99996a9f3fcf [file] [log] [blame]
/*
* 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.impl.metadata;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import javax.validation.groups.Default;
/**
* Contains all the information known about the inheritance information for validation groups.
*/
public class ValidationGroupsMetadata {
/**
* Builder for {@link ValidationGroupsMetadata}
*/
public static class Builder {
private final Map<Class<?>, Set<Class<?>>> inheritanceinheritanceMap;
private final Map<Class<?>, List<Class<?>>> sequenceMap;
private Builder() {
inheritanceinheritanceMap = new HashMap<Class<?>, Set<Class<?>>>();
sequenceMap = new HashMap<Class<?>, List<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) {
inheritanceinheritanceMap.put(group, new HashSet<Class<?>>(Arrays.asList(parents)));
return this;
}
/**
* Adds a group sequence to the sequence map.
* @param groupSequence The class representing the sequence (annotated with &#064;GroupSequence)
* @param sequenceGroups The groups in the sequence.
*/
public Builder addSequence(Class<?> groupSequence, Class<?>... sequenceGroups) {
sequenceMap.put(groupSequence, Arrays.asList(sequenceGroups));
return this;
}
public ValidationGroupsMetadata build() {
return new ValidationGroupsMetadata(inheritanceinheritanceMap, sequenceMap);
}
}
/**
* Creates a builder populated only with the {@link Default} group.
*/
public static Builder builder() {
return new Builder();
}
private final Map<Class<?>, Set<Class<?>>> inheritanceMapping;
private final Map<Class<?>, List<Class<?>>> sequenceMapping;
private ValidationGroupsMetadata(Map<Class<?>, Set<Class<?>>> inheritanceinheritanceMap,
Map<Class<?>, List<Class<?>>> sequenceMap) {
this.inheritanceMapping = Collections.unmodifiableMap(inheritanceinheritanceMap);
this.sequenceMapping = Collections.unmodifiableMap(sequenceMap);
}
/**
* Checks if a given group has been added to the inheritance map.
*/
public boolean containsGroup(Class<?> group) {
return inheritanceMapping.containsKey(group);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ValidationGroupsMetadata)) {
return false;
}
ValidationGroupsMetadata otherObj = (ValidationGroupsMetadata)other;
return inheritanceMapping.equals(otherObj.inheritanceMapping)
&& sequenceMapping.equals(otherObj.sequenceMapping);
}
/**
* 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 (!inheritanceMapping.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 = inheritanceMapping.get(current);
for (Class<?> parent : superInterfaces) {
if (!found.contains(parent)) {
remaining.push(parent);
}
}
}
return found;
}
/**
* Recursively gets all of the groups and sequence groups in the map (children and parents alike)
* in one flat set.
*/
public Set<Class<?>> getAllGroupsAndSequences() {
Set<Class<?>> allGroups = new HashSet<Class<?>>();
for (Map.Entry<Class<?>, Set<Class<?>>> entry : inheritanceMapping.entrySet()) {
allGroups.add(entry.getKey());
allGroups.addAll(entry.getValue());
}
allGroups.addAll(sequenceMapping.keySet());
return allGroups;
}
/**
* Returns all the known group sequence classes.
*/
public Set<Class<?>> getGroupSequences() {
return sequenceMapping.keySet();
}
/**
* 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 inheritanceMapping.get(group);
}
/**
* Returns all of the groups added to the map (but not their parents).
*/
public Set<Class<?>> getRootGroups() {
return inheritanceMapping.keySet();
}
/**
* If the sequence class has been added to the map then the actual sequence list is retrieved.
* Otherwise null is returned.
*/
public List<Class<?>> getSequenceList(Class<?> sequence) {
return sequenceMapping.get(sequence);
}
@Override
public int hashCode() {
int result = inheritanceMapping.hashCode();
result = 31 * result + sequenceMapping.hashCode();
return result;
}
/**
* Checks if a group extends other groups (has parents).
*/
public boolean hasParents(Class<?> group) {
Set<Class<?>> possibleParents = getParentsOfGroup(group);
return possibleParents != null && !possibleParents.isEmpty();
}
public boolean isInheritanceMapEmpty() {
return inheritanceMapping.isEmpty();
}
/**
* Checks if a given class is a group sequence map.
*/
public boolean isSeqeuence(Class<?> sequence) {
return sequenceMapping.containsKey(sequence);
}
public boolean isSequenceMapEmpty() {
return sequenceMapping.isEmpty();
}
@Override
public String toString() {
return "ValidationGroupsMetaData{inheritanceMap=" + inheritanceMapping + ", " +
"sequenceMap=" + sequenceMapping + "}";
}
}