| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.cassandra.simulator; |
| |
| import java.util.List; |
| import java.util.function.Consumer; |
| |
| public interface ActionListener |
| { |
| enum Before { EXECUTE, DROP, INVALIDATE } |
| |
| /** |
| * Immediately before the action is first executed |
| * @param action the action we are about to perform |
| * @param before if the action is to be performed (rather than dropped) |
| */ |
| default void before(Action action, Before before) {} |
| |
| /** |
| * Immediately after the action is first executed (or dropped) |
| * @param consequences the actions that result from the execution |
| */ |
| default void consequences(ActionList consequences) {} |
| |
| /** |
| * If an ActionThread, after termination; otherwise immediately after invoked |
| * @param finished the action that has finished |
| */ |
| default void after(Action finished) {} |
| |
| /** |
| * After the action and all its consequent terminate (excluding the initiation of an infinite loop execution) |
| * @param finished the action that has finished |
| */ |
| default void transitivelyAfter(Action finished) {} |
| |
| static ActionListener runAfter(Consumer<Action> after) |
| { |
| return new ActionListener() |
| { |
| @Override |
| public void after(Action performed) |
| { |
| after.accept(performed); |
| } |
| }; |
| } |
| |
| static ActionListener runAfterAndTransitivelyAfter(Consumer<Action> after) |
| { |
| return new ActionListener() |
| { |
| @Override |
| public void after(Action performed) |
| { |
| after.accept(performed); |
| } |
| |
| @Override |
| public void transitivelyAfter(Action performed) |
| { |
| after.accept(performed); |
| } |
| }; |
| } |
| |
| static ActionListener runAfterTransitiveClosure(Consumer<Action> transitivelyAfter) |
| { |
| return new ActionListener() |
| { |
| @Override |
| public void transitivelyAfter(Action performed) |
| { |
| transitivelyAfter.accept(performed); |
| } |
| }; |
| } |
| |
| static ActionListener recursive(ActionListener runOnAll) |
| { |
| return new WrappedRecursiveActionListener(runOnAll); |
| } |
| |
| public interface SelfAddingActionListener extends ActionListener, Consumer<Action> |
| { |
| @Override |
| default public void accept(Action action) |
| { |
| action.register(this); |
| } |
| } |
| |
| public static class RecursiveActionListener implements SelfAddingActionListener |
| { |
| @Override |
| public void consequences(ActionList consequences) |
| { |
| consequences.forEach(this); |
| } |
| } |
| |
| public static class WrappedRecursiveActionListener extends Wrapped implements SelfAddingActionListener |
| { |
| public WrappedRecursiveActionListener(ActionListener wrap) |
| { |
| super(wrap); |
| } |
| |
| @Override |
| public void consequences(ActionList consequences) |
| { |
| consequences.forEach(this); |
| super.consequences(consequences); |
| } |
| } |
| |
| public static class Wrapped implements ActionListener |
| { |
| final ActionListener wrap; |
| |
| public Wrapped(ActionListener wrap) |
| { |
| this.wrap = wrap; |
| } |
| |
| @Override |
| public void before(Action action, Before before) |
| { |
| wrap.before(action, before); |
| } |
| |
| @Override |
| public void consequences(ActionList consequences) |
| { |
| wrap.consequences(consequences); |
| } |
| |
| @Override |
| public void after(Action finished) |
| { |
| wrap.after(finished); |
| } |
| |
| @Override |
| public void transitivelyAfter(Action finished) |
| { |
| wrap.transitivelyAfter(finished); |
| } |
| } |
| |
| public static class Combined implements ActionListener |
| { |
| final List<ActionListener> combined; |
| |
| public Combined(List<ActionListener> combined) |
| { |
| this.combined = combined; |
| } |
| |
| @Override |
| public void before(Action action, Before before) |
| { |
| combined.forEach(listener -> listener.before(action, before)); |
| } |
| |
| @Override |
| public void consequences(ActionList consequences) |
| { |
| combined.forEach(listener -> listener.consequences(consequences)); |
| } |
| |
| @Override |
| public void after(Action finished) |
| { |
| combined.forEach(listener -> listener.after(finished)); |
| } |
| |
| @Override |
| public void transitivelyAfter(Action finished) |
| { |
| combined.forEach(listener -> listener.transitivelyAfter(finished)); |
| } |
| } |
| } |
| |