package org.activityinfo.core.shared.criteria;
import com.google.common.collect.Sets;
import org.activityinfo.model.resource.ResourceId;
import java.util.Set;
/**
* The set of FormClasses that could be potentially selected by a given
* criteria
*/
public class FormClassSet {
public static final FormClassSet OPEN = new FormClassSet();
private boolean open = true;
private Set<ResourceId> closed = Sets.newHashSet();
private FormClassSet() {
}
private FormClassSet(ResourceId classId) {
open = false;
closed.add(classId);
}
public FormClassSet(FormClassSet set) {
open = false;
closed.addAll(set.closed);
}
public static FormClassSet of(Criteria criteria) {
if(criteria instanceof ClassCriteria) {
return new FormClassSet(((ClassCriteria) criteria).getClassId());
} else if(criteria instanceof CriteriaUnion) {
return computeUnion((CriteriaUnion) criteria);
} else if(criteria instanceof CriteriaIntersection) {
return computeIntersection((CriteriaIntersection)criteria);
} else {
return OPEN;
}
}
public boolean isOpen() {
return open;
}
public boolean isClosed() {
return !open;
}
public boolean isEmpty() {
return !open && closed.isEmpty();
}
public boolean isSingleton() {
return !open && closed.size() == 1;
}
public ResourceId unique() {
assert !open : "The set is open";
assert !closed.isEmpty() : "The set is empty";
assert closed.size() == 1 : "The set includes more than one class";
return closed.iterator().next();
}
public Set<ResourceId> getElements() {
assert isClosed();
return closed;
}
private static FormClassSet computeUnion(CriteriaUnion criteria) {
FormClassSet union = new FormClassSet();
union.open = false;
for(Criteria element : criteria.getElements()) {
FormClassSet elementSet = FormClassSet.of(element);
if(elementSet.open) {
union.open = true;
break;
} else {
union.closed.addAll(elementSet.closed);
}
}
return union;
}
private static FormClassSet computeIntersection(CriteriaIntersection criteria) {
FormClassSet intersection = OPEN;
for(Criteria element : criteria.getElements()) {
FormClassSet elementSet = FormClassSet.of(element);
if(!elementSet.open) {
if(intersection == OPEN) {
intersection = new FormClassSet(elementSet);
} else {
intersection.closed.retainAll(elementSet.closed);
}
}
}
return intersection;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FormClassSet that = (FormClassSet) o;
if (open != that.open) return false;
if (!closed.equals(that.closed)) return false;
return true;
}
@Override
public int hashCode() {
int result = (open ? 1 : 0);
result = 31 * result + closed.hashCode();
return result;
}
public static FormClassSet of(Set<ResourceId> range) {
FormClassSet set = new FormClassSet();
set.open = false;
set.closed.addAll(range);
return set;
}
}