package io.airlift.airship.coordinator;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import io.airlift.airship.shared.CoordinatorLifecycleState;
import io.airlift.airship.shared.CoordinatorStatus;
import io.airlift.airship.shared.HttpUriBuilder;
import javax.annotation.Nullable;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
import java.util.List;
import java.util.Map.Entry;
public class CoordinatorFilterBuilder
{
public static CoordinatorFilterBuilder builder()
{
return new CoordinatorFilterBuilder();
}
public static Predicate<CoordinatorStatus> build(UriInfo uriInfo)
{
CoordinatorFilterBuilder builder = new CoordinatorFilterBuilder();
for (Entry<String, List<String>> entry : uriInfo.getQueryParameters().entrySet()) {
if ("uuid".equals(entry.getKey())) {
for (String uuidFilter : entry.getValue()) {
builder.addUuidFilter(uuidFilter);
}
}
if ("!uuid".equals(entry.getKey())) {
for (String notUuidFilter : entry.getValue()) {
builder.addNotUuidFilter(notUuidFilter);
}
}
else if ("state".equals(entry.getKey())) {
for (String stateFilter : entry.getValue()) {
builder.addStateFilter(stateFilter);
}
}
else if ("!state".equals(entry.getKey())) {
for (String notStateFilter : entry.getValue()) {
builder.addNotStateFilter(notStateFilter);
}
}
else if ("host".equals(entry.getKey())) {
for (String hostGlob : entry.getValue()) {
builder.addHostGlobFilter(hostGlob);
}
}
else if ("!host".equals(entry.getKey())) {
for (String notHostGlob : entry.getValue()) {
builder.addNotHostGlobFilter(notHostGlob);
}
}
else if ("machine".equals(entry.getKey())) {
for (String machineGlob : entry.getValue()) {
builder.addMachineGlobFilter(machineGlob);
}
}
else if ("!machine".equals(entry.getKey())) {
for (String notMachineGlob : entry.getValue()) {
builder.addNotMachineGlobFilter(notMachineGlob);
}
}
else if ("all".equals(entry.getKey())) {
builder.selectAll();
}
}
return builder.buildPredicate();
}
private final List<String> uuidFilters = Lists.newArrayListWithCapacity(6);
private final List<String> notUuidFilters = Lists.newArrayListWithCapacity(6);
private final List<CoordinatorLifecycleState> stateFilters = Lists.newArrayListWithCapacity(6);
private final List<CoordinatorLifecycleState> notStateFilters = Lists.newArrayListWithCapacity(6);
private final List<String> hostGlobs = Lists.newArrayListWithCapacity(6);
private final List<String> notHostGlobs = Lists.newArrayListWithCapacity(6);
private final List<String> machineGlobs = Lists.newArrayListWithCapacity(6);
private final List<String> notMachineGlobs = Lists.newArrayListWithCapacity(6);
private boolean selectAll;
public void addUuidFilter(String uuid)
{
Preconditions.checkNotNull(uuid, "uuid is null");
uuidFilters.add(uuid);
}
public void addNotUuidFilter(String notUuid)
{
Preconditions.checkNotNull(notUuid, "notUuid is null");
notUuidFilters.add(notUuid);
}
public void addStateFilter(String stateFilter)
{
Preconditions.checkNotNull(stateFilter, "stateFilter is null");
CoordinatorLifecycleState state = CoordinatorLifecycleState.valueOf(stateFilter.toUpperCase());
Preconditions.checkArgument(state != null, "unknown state %s", stateFilter);
stateFilters.add(state);
}
public void addNotStateFilter(String notStateFilter)
{
Preconditions.checkNotNull(notStateFilter, "notStateFilter is null");
CoordinatorLifecycleState state = CoordinatorLifecycleState.valueOf(notStateFilter.toUpperCase());
Preconditions.checkArgument(state != null, "unknown state %s", notStateFilter);
notStateFilters.add(state);
}
public void addHostGlobFilter(String hostGlob)
{
Preconditions.checkNotNull(hostGlob, "hostGlob is null");
hostGlobs.add(hostGlob);
}
public void addNotHostGlobFilter(String notHostGlob)
{
Preconditions.checkNotNull(notHostGlob, "notHostGlob is null");
notHostGlobs.add(notHostGlob);
}
public void addMachineGlobFilter(String machineGlob)
{
Preconditions.checkNotNull(machineGlob, "machineGlob is null");
machineGlobs.add(machineGlob);
}
public void addNotMachineGlobFilter(String notMachineGlob)
{
Preconditions.checkNotNull(notMachineGlob, "notMachineGlob is null");
notMachineGlobs.add(notMachineGlob);
}
public void selectAll()
{
this.selectAll = true;
}
public Predicate<CoordinatorStatus> buildPredicate()
{
Predicate<CoordinatorStatus> include = buildIncludesPredicate();
Optional<Predicate<CoordinatorStatus>> excludesPredicate = buildExcludesPredicate();
if (excludesPredicate.isPresent()) {
// includes and not excluded
return Predicates.and(include, Predicates.not(excludesPredicate.get()));
}
return include;
}
private Predicate<CoordinatorStatus> buildIncludesPredicate()
{
List<Predicate<CoordinatorStatus>> andPredicates = Lists.newArrayListWithCapacity(6);
if (!uuidFilters.isEmpty()) {
Predicate<CoordinatorStatus> predicate = Predicates.or(Lists.transform(uuidFilters, new Function<String, UuidPredicate>()
{
@Override
public UuidPredicate apply(String uuid)
{
return new UuidPredicate(uuid);
}
}));
andPredicates.add(predicate);
}
if (!stateFilters.isEmpty()) {
Predicate<CoordinatorStatus> predicate = Predicates.or(Lists.transform(stateFilters, new Function<CoordinatorLifecycleState, StatePredicate>()
{
@Override
public StatePredicate apply(CoordinatorLifecycleState state)
{
return new StatePredicate(state);
}
}));
andPredicates.add(predicate);
}
if (!hostGlobs.isEmpty()) {
Predicate<CoordinatorStatus> predicate = Predicates.or(Lists.transform(hostGlobs, new Function<String, HostPredicate>()
{
@Override
public HostPredicate apply(String hostGlob)
{
return new HostPredicate(hostGlob);
}
}));
andPredicates.add(predicate);
}
if (!machineGlobs.isEmpty()) {
Predicate<CoordinatorStatus> predicate = Predicates.or(Lists.transform(machineGlobs, new Function<String, MachinePredicate>()
{
@Override
public MachinePredicate apply(String machineGlob)
{
return new MachinePredicate(machineGlob);
}
}));
andPredicates.add(predicate);
}
if (selectAll || andPredicates.isEmpty()) {
return Predicates.alwaysTrue();
}
else {
return Predicates.and(andPredicates);
}
}
private Optional<Predicate<CoordinatorStatus>> buildExcludesPredicate()
{
List<Predicate<CoordinatorStatus>> excludes = Lists.newArrayListWithCapacity(6);
excludes.addAll(Lists.transform(notUuidFilters, new Function<String, UuidPredicate>()
{
@Override
public UuidPredicate apply(String uuid)
{
return new UuidPredicate(uuid);
}
}));
excludes.addAll(Lists.transform(notStateFilters, new Function<CoordinatorLifecycleState, StatePredicate>()
{
@Override
public StatePredicate apply(CoordinatorLifecycleState state)
{
return new StatePredicate(state);
}
}));
excludes.addAll(Lists.transform(notHostGlobs, new Function<String, HostPredicate>()
{
@Override
public HostPredicate apply(String hostGlob)
{
return new HostPredicate(hostGlob);
}
}));
excludes.addAll(Lists.transform(notMachineGlobs, new Function<String, MachinePredicate>()
{
@Override
public MachinePredicate apply(String machineGlob)
{
return new MachinePredicate(machineGlob);
}
}));
if (excludes.isEmpty()) {
return Optional.absent();
}
return Optional.of(Predicates.or(excludes));
}
public URI buildUri(URI baseUri)
{
HttpUriBuilder uriBuilder = HttpUriBuilder.uriBuilderFrom(baseUri);
return buildUri(uriBuilder);
}
public URI buildUri(HttpUriBuilder uriBuilder)
{
for (String uuidFilter : uuidFilters) {
uriBuilder.addParameter("uuid", uuidFilter);
}
for (String notUuidFilter : notUuidFilters) {
uriBuilder.addParameter("!uuid", notUuidFilter);
}
for (String hostGlob : hostGlobs) {
uriBuilder.addParameter("host", hostGlob);
}
for (String notHostGlob : notHostGlobs) {
uriBuilder.addParameter("!host", notHostGlob);
}
for (String machineGlob : machineGlobs) {
uriBuilder.addParameter("machine", machineGlob);
}
for (String notMachineGlob : notMachineGlobs) {
uriBuilder.addParameter("!machine", notMachineGlob);
}
for (CoordinatorLifecycleState stateFilter : stateFilters) {
uriBuilder.addParameter("state", stateFilter.name());
}
for (CoordinatorLifecycleState notStateFilter : notStateFilters) {
uriBuilder.addParameter("!state", notStateFilter.name());
}
if (selectAll) {
uriBuilder.addParameter("all");
}
return uriBuilder.build();
}
public static class UuidPredicate
implements Predicate<CoordinatorStatus>
{
private final String uuid;
public UuidPredicate(String uuid)
{
this.uuid = uuid;
}
@Override
public boolean apply(@Nullable CoordinatorStatus coordinatorStatus)
{
return uuid.equals(coordinatorStatus.getCoordinatorId());
}
}
public static class HostPredicate
implements Predicate<CoordinatorStatus>
{
private final UriHostPredicate predicate;
public HostPredicate(String hostGlob)
{
predicate = new UriHostPredicate(hostGlob.toLowerCase());
}
@Override
public boolean apply(@Nullable CoordinatorStatus coordinatorStatus)
{
return coordinatorStatus != null &&
(predicate.apply(coordinatorStatus.getExternalUri()) || predicate.apply(coordinatorStatus.getInternalUri()));
}
}
public static class MachinePredicate
implements Predicate<CoordinatorStatus>
{
private final GlobPredicate predicate;
public MachinePredicate(String machineGlob)
{
predicate = new GlobPredicate(machineGlob);
}
@Override
public boolean apply(@Nullable CoordinatorStatus coordinatorStatus)
{
return coordinatorStatus != null && predicate.apply(coordinatorStatus.getInstanceId());
}
}
public static class StatePredicate
implements Predicate<CoordinatorStatus>
{
private final CoordinatorLifecycleState state;
public StatePredicate(CoordinatorLifecycleState state)
{
this.state = state;
}
@Override
public boolean apply(@Nullable CoordinatorStatus coordinatorStatus)
{
return coordinatorStatus.getState() == state;
}
}
}