blob: 2bc8ae8883f1f51ef8f8b2a5270978577ed8335a [file] [log] [blame]
/*
* 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));
}
}
}