package tc.oc.minecraft.server; import java.util.function.Predicate; import java.util.stream.Stream; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import tc.oc.api.docs.virtual.MapDoc; import tc.oc.api.docs.virtual.MatchDoc; import tc.oc.api.docs.virtual.ServerDoc; import tc.oc.commons.core.inspect.Inspectable; import tc.oc.commons.core.stream.Collectors; /** * General purpose object to filter server documents by various criteria. * * To match, every non-empty field of the filter must have a non-empty * intersection with the respective field of the server document. * In other words, different fields are combined with AND, but members * of the same field are combined with OR, and empty fields are ignored. * * @see ServerFilterParser */ public class ServerFilter extends Inspectable.Impl implements Predicate<ServerDoc.Identity> { @Inspect private final ImmutableSet<ServerDoc.Role> roles; @Inspect private final ImmutableSet<ServerDoc.Network> networks; @Inspect private final ImmutableSet<String> realms; @Inspect private final ImmutableSet<String> games; @Inspect private final ImmutableSet<MapDoc.Gamemode> gamemodes; public ServerFilter(Stream<ServerDoc.Role> roles, Stream<ServerDoc.Network> networks, Stream<String> realms, Stream<String> games, Stream<MapDoc.Gamemode> gamemodes) { this.roles = roles.collect(Collectors.toImmutableSet()); this.networks = networks.collect(Collectors.toImmutableSet()); this.realms = realms.collect(Collectors.toImmutableSet()); this.games = games.collect(Collectors.toImmutableSet()); this.gamemodes = gamemodes.collect(Collectors.toImmutableSet()); } /** * @see ServerDoc.Role * @see ServerDoc.Identity#role() */ public ImmutableSet<ServerDoc.Role> roles() { return roles; } /** * @see ServerDoc.Network * @see ServerDoc.Identity#network() */ public ImmutableSet<ServerDoc.Network> networks() { return networks; } /** * @see ServerDoc.Identity#realms() */ public ImmutableSet<String> realms() { return realms; } /** * @see ServerDoc.Identity#game_id() */ public ImmutableSet<String> games() { return games; } /** * @see MapDoc.Gamemode * @see ServerDoc.MatchStatus#current_match()#gamemodes() */ public ImmutableSet<MapDoc.Gamemode> gamemodes() { return gamemodes; } @Override public boolean test(ServerDoc.Identity server) { if(!roles.isEmpty() && !roles.contains(server.role())) return false; if(!networks.isEmpty() && !networks.contains(server.network())) return false; if(!realms.isEmpty() && Sets.intersection(realms, server.realms()).isEmpty()) return false; if(!games.isEmpty() && !games.contains(server.game_id())) return false; if(!gamemodes.isEmpty()) { if(!(server instanceof ServerDoc.MatchStatus)) return false; final MatchDoc match = ((ServerDoc.MatchStatus) server).current_match(); if(match == null) return false; if(Sets.intersection(gamemodes, match.map().gamemode()).isEmpty()) return false; } return true; } }