org.mapfish.print.parser.OneOfTracker Maven / Gradle / Ivy
package org.mapfish.print.parser;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.vividsolutions.jts.util.Assert;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Keeps track of which OneOf groups there are and which ones are satisfied.
*
* @author Jesse on 4/10/2014.
*/
final class OneOfTracker {
private Map mapping = Maps.newHashMap();
/**
* Check if a field is part of a {@link org.mapfish.print.parser.OneOf} relationship and add if necessary.
*
* @param field the field to register.
*/
public void register(final Field field) {
final OneOf oneOfAnnotation = field.getAnnotation(OneOf.class);
String groupName = null;
if (oneOfAnnotation != null) {
groupName = oneOfAnnotation.value();
} else {
final CanSatisfyOneOf canSatisfyOneOf = field.getAnnotation(CanSatisfyOneOf.class);
if (canSatisfyOneOf != null) {
groupName = canSatisfyOneOf.value();
}
}
if (groupName != null) {
OneOfGroup oneOfGroup = this.mapping.get(groupName);
if (oneOfGroup == null) {
oneOfGroup = new OneOfGroup(groupName);
this.mapping.put(groupName, oneOfGroup);
}
oneOfGroup.choices.add(field);
}
}
/**
* Check if a field is part of a {@link org.mapfish.print.parser.OneOf} relationship and mark the group as satisfied.
*
* @param field the field that is done.
*/
public void markAsVisited(final Field field) {
final OneOf oneOfAnnotation = field.getAnnotation(OneOf.class);
if (oneOfAnnotation != null) {
final OneOfGroup oneOfGroup = this.mapping.get(oneOfAnnotation.value());
oneOfGroup.satisfiedBy.add(new OneOfSatisfier(field, false));
}
final CanSatisfyOneOf canSatisfyOneOf = field.getAnnotation(CanSatisfyOneOf.class);
if (canSatisfyOneOf != null) {
final OneOfGroup oneOfGroup = this.mapping.get(canSatisfyOneOf.value());
oneOfGroup.satisfiedBy.add(new OneOfSatisfier(field, true));
}
}
/**
* Check that each group is satisfied by one and only one field.
* @param currentPath the json path to the element being checked
*/
public void checkAllGroupsSatisfied(final String currentPath) {
StringBuilder errors = new StringBuilder();
for (OneOfGroup group : this.mapping.values()) {
if (group.satisfiedBy.isEmpty()) {
errors.append("\n");
errors.append("\t* The OneOf choice: ").append(group.name).append(" was not satisfied. One (and only one) of the ");
errors.append("following fields is required in the request data: ").append(toNames(group.choices));
}
Collection oneOfSatisfiers = Collections2.filter(group.satisfiedBy, new Predicate() {
@Override
public boolean apply(@Nonnull final OneOfSatisfier input) {
return !input.isCanSatisfy;
}
});
if (oneOfSatisfiers.size() > 1) {
errors.append("\n");
errors.append("\t* The OneOf choice: ").append(group.name).append(" was satisfied by too many fields. Only one choice ");
errors.append("may be in the request data. The fields found were: ").append(toNames(toFields(group.satisfiedBy)));
}
}
Assert.equals(0, errors.length(), "\nErrors were detected when analysing the @OneOf dependencies of '" + currentPath +
"': \n" + errors);
}
private Collection toFields(final Set satisfiedBy) {
return Collections2.transform(satisfiedBy, new Function() {
@Nullable
@Override
public Field apply(@Nonnull final OneOfSatisfier input) {
return input.field;
}
});
}
private String toNames(final Collection choices) {
StringBuilder names = new StringBuilder();
for (Field choice : choices) {
if (names.length() > 0) {
names.append(", ");
}
String type = choice.getType().getName();
if (choice.getType().isArray()) {
type = choice.getType().getComponentType().getName() + "[]";
}
names.append(type).append(' ').append(choice.getName());
}
return names.toString();
}
private static final class OneOfGroup {
private String name;
private Collection choices = Lists.newArrayList();
private Set satisfiedBy = Sets.newHashSet();
public OneOfGroup(final String name) {
this.name = name;
}
}
private static final class OneOfSatisfier {
private final Field field;
private final boolean isCanSatisfy;
public OneOfSatisfier(@Nonnull final Field field,
final boolean isCanSatisfy) {
this.field = field;
this.isCanSatisfy = isCanSatisfy;
}
// CHECKSTYLE:OFF
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OneOfSatisfier that = (OneOfSatisfier) o;
if (!field.equals(that.field)) return false;
return true;
}
@Override
public int hashCode() {
return field.hashCode();
}
// CHECKSTYLE:ON
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy