package rocks.inspectit.server.diagnosis.engine.session; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import rocks.inspectit.server.diagnosis.engine.DiagnosisEngine; import rocks.inspectit.server.diagnosis.engine.rule.RuleDefinition; import rocks.inspectit.server.diagnosis.engine.rule.RuleInput; import rocks.inspectit.server.diagnosis.engine.rule.store.IRuleOutputStorage; /** * A <code>SessionContext</code> represents the runtime information of a currently processing * {@link Session}. Each {@link SessionContext} is associated to exactly one {@link Session} and is * not viable without a {@link Session}. <br> * <code>SessionContext</code>s implement the same life cycle as {@link Session}: * {@link #activate(Object, Map<String, ?>)}, {@link #passivate()}, {@link #destroy()}. * * @param <I> * The type of the input of this session.s * @author Claudio Waldvogel, Alexander Wert * @see Session */ public class SessionContext<I> { /** * The input object the session is analyzing. */ private I input; /** * ImmutableSet of all available {@link RuleDefinition}s within the {@link DiagnosisEngine}. * This is a backup to restore the {@link #ruleSet} to an initial state as soon as the * <code>SessionContext</code> gets activated. */ private final ImmutableSet<RuleDefinition> backupRules; /** * The set of processable {@link RuleDefinition}s. As soon as a Session executed a * {@link RuleDefinition}, this definition is evicted from the set. Thus it is easily possible * to determine when a {@link Session} executed all possible {@link RuleDefinition}s. * * @see RuleDefinition * @see Session */ private Set<RuleDefinition> ruleSet; /** * The {@link IRuleOutputStorage} used in this {@link Session}. * * @see IRuleOutputStorage */ private IRuleOutputStorage storage; /** * The available session variables for this {@link Session} execution. */ private final Map<String, Object> sessionVariables = new HashMap<>(); /** * Multimap of {@link RuleDefinition}s to {@link RuleInput}s to track which rules have already * been excecuted for which inputs. */ private final Multimap<RuleDefinition, RuleInput> executions; /** * Default constructor to create new <code>SessionContext</code>s. * * @param rules * The set of {@link RuleDefinition}s * @param storage * The {@link IRuleOutputStorage} implementation * @see RuleDefinition * @see IRuleOutputStorage */ SessionContext(Set<RuleDefinition> rules, IRuleOutputStorage storage) { // Protected the initial rules from being manipulated checkArgument(CollectionUtils.isNotEmpty(rules), "Rules must not be null or empty."); this.backupRules = ImmutableSet.copyOf(rules); this.ruleSet = new HashSet<>(); this.storage = checkNotNull(storage, "Storage must not be null."); this.executions = ArrayListMultimap.create(); } // ------------------------------------------------------------- // Methods: LifeCycle // ------------------------------------------------------------- /** * Activate the <code>SessionContext</code>. The {@link #ruleSet} is restored to * {@link #backupRules}. * * @param input * The object to to be analyzed. * @param variables * The valid session variables, * @return The SessionContext itself. * @see Session * @see Session#activate(Object, Map<String, ?>) */ SessionContext<I> activate(I input, Map<String, ?> variables) { this.input = input; // ensure a shallow copy, we must never ever operate on the original RuleSet this.ruleSet.addAll(backupRules); this.sessionVariables.putAll(variables); return this; } /** * Passivates the <code>SessionContext</code> by clearing th {@link #ruleSet}, the * {@link #sessionVariables}, the {@link #storage}, and the {@link #input}. * * @return The SessionContext itself. * @see Session * @see Session#passivate() */ SessionContext<I> passivate() { this.input = null; // NOPMD this.ruleSet.clear(); this.storage.clear(); this.executions.clear(); this.sessionVariables.clear(); // NOPMD return this; } /** * Track an execution of the given rule for the given input. * * @param ruleDefinition * {@link RuleDefinition} executed rule. * @param input * {@link RuleInput} used for the rule execution. */ public void addExecution(RuleDefinition ruleDefinition, RuleInput input) { executions.put(ruleDefinition, input); } // ------------------------------------------------------------- // Methods: Accessors // ------------------------------------------------------------- /** * Gets {@link #input}. * * @return {@link #input} */ public I getInput() { return input; } /** * Gets {@link #sessionVariables}. * * @return {@link #sessionVariables} */ public Map<String, Object> getSessionVariables() { return sessionVariables; } /** * Gets {@link #ruleSet}. * * @return {@link #ruleSet} */ public Set<RuleDefinition> getRuleSet() { return ruleSet; } /** * Gets {@link #storage}. * * @return {@link #storage} */ public IRuleOutputStorage getStorage() { return storage; } /** * Gets {@link #executions}. * * @return {@link #executions} */ public Multimap<RuleDefinition, RuleInput> getExecutions() { return executions; } }