Effect.java
package com.redis.test.fi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
/**
* One discovered effect: the triggers that produce it, each with the database requirements it can
* run under. Typed envelope of a discovery response; the dbconfigs inside stay opaque.
*/
public final class Effect {
private final EffectType type;
private final int clusterNodes;
private final List<Trigger> triggers;
private Effect(EffectType type, int clusterNodes, List<Trigger> triggers) {
this.type = type;
this.clusterNodes = clusterNodes;
this.triggers = Collections.unmodifiableList(triggers);
}
@SuppressWarnings("unchecked")
static Effect parse(EffectType type, Map<String, Object> response) {
Map<String, Object> cluster = (Map<String, Object>) response.get("cluster");
int nodes = cluster == null ? 0 : ((Number) cluster.get("nodes")).intValue();
List<Trigger> triggers = new ArrayList<>();
for (Object t : (List<Object>) response.get("triggers")) {
triggers.add(Trigger.parse(type, (Map<String, Object>) t));
}
return new Effect(type, nodes, triggers);
}
/**
* The same effect discovered through several routes (e.g. {@code asm=false} and {@code asm=true}
* of {@code /slot-migrate}, which list disjoint triggers) folded into one trigger list.
*/
static Effect merge(Effect first, Effect second) {
List<Trigger> triggers = new ArrayList<>(first.triggers);
for (Trigger trigger : second.triggers) {
if (first.triggers.stream().noneMatch(t -> t.name().equals(trigger.name()))) {
triggers.add(trigger);
}
}
return new Effect(first.type, Math.max(first.clusterNodes, second.clusterNodes), triggers);
}
/** This effect without the triggers matching {@code dropped}; the rest keep their order. */
Effect without(Predicate<Trigger> dropped) {
List<Trigger> kept = new ArrayList<>();
for (Trigger trigger : triggers) {
if (!dropped.test(trigger)) {
kept.add(trigger);
}
}
return new Effect(type, clusterNodes, kept);
}
public EffectType type() {
return type;
}
public int clusterNodes() {
return clusterNodes;
}
public List<Trigger> triggers() {
return triggers;
}
/** The named trigger; fails loudly when the FI does not offer it for this effect. */
public Trigger trigger(String name) {
for (Trigger trigger : triggers) {
if (trigger.name().equals(name)) {
return trigger;
}
}
throw new IllegalArgumentException(
"FI offers no trigger '" + name + "' for " + type + "; available: " + triggers);
}
}