Skip to content

Commit

Permalink
add getEventClass() to Listener interface
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaspayette committed Dec 10, 2024
1 parent ef84456 commit f7fd94d
Show file tree
Hide file tree
Showing 17 changed files with 139 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@
import tech.tablesaw.api.StringColumn;
import tech.tablesaw.api.Table;
import uk.ac.ox.poseidon.agents.behaviours.Action;
import uk.ac.ox.poseidon.io.tables.ListenerTable;
import uk.ac.ox.poseidon.core.events.AbstractListener;

public abstract class ActionListenerTable<A extends Action> implements ListenerTable<A> {
import java.util.function.Supplier;

public abstract class ActionListenerTable<A extends Action>
extends AbstractListener<A>
implements Supplier<Table> {
private final StringColumn vesselId = StringColumn.create("vessel_id");
private final DateTimeColumn actionStart = DateTimeColumn.create("action_start");
private final DateTimeColumn actionEnd = DateTimeColumn.create("action_end");
Expand All @@ -37,6 +41,10 @@ public abstract class ActionListenerTable<A extends Action> implements ListenerT
actionEnd
);

public ActionListenerTable(final Class<A> eventClass) {
super(eventClass);
}

@Override
public void receive(final A action) {
actionStart.append(action.getStart());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class FishingActionListenerTable extends GridActionListenerTable<FishingA
private final DoubleColumn biomassCaught = DoubleColumn.create("biomass_caught");

public FishingActionListenerTable(final GridExtent gridExtent) {
super(gridExtent);
super(FishingAction.class, gridExtent);
get().addColumns(speciesCode, biomassCaught);
}

Expand All @@ -43,8 +43,4 @@ public void receive(final FishingAction fishingAction) {
});
}

@Override
public Class<FishingAction> getEventClass() {
return FishingAction.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,22 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import uk.ac.ox.poseidon.agents.behaviours.fishing.FishingAction;
import uk.ac.ox.poseidon.core.Factory;
import uk.ac.ox.poseidon.core.Simulation;
import uk.ac.ox.poseidon.geography.grids.GridExtent;
import uk.ac.ox.poseidon.io.tables.ListenerTableFactory;
import uk.ac.ox.poseidon.io.tables.SimulationEventListenerFactory;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class FishingActionListenerTableFactory
extends ListenerTableFactory<FishingAction, FishingActionListenerTable> {
extends SimulationEventListenerFactory<FishingActionListenerTable> {

private Factory<? extends GridExtent> gridExtent;

@Override
protected FishingActionListenerTable newTable(final Simulation simulation) {
protected FishingActionListenerTable newListener(final Simulation simulation) {
return new FishingActionListenerTable(gridExtent.get(simulation));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ public abstract class GridActionListenerTable<A extends GridAction> extends Acti
private final DoubleColumn lon = DoubleColumn.create("lon");
private final DoubleColumn lat = DoubleColumn.create("lat");

public GridActionListenerTable(final GridExtent gridExtent) {
super();
public GridActionListenerTable(
final Class<A> eventClass,
final GridExtent gridExtent
) {
super(eventClass);
get().addColumns(lon, lat);
this.gridExtent = gridExtent;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@
*
*/

package uk.ac.ox.poseidon.io.tables;
package uk.ac.ox.poseidon.core.events;

import tech.tablesaw.api.Table;
import uk.ac.ox.poseidon.core.events.Listener;
import lombok.Getter;

import java.util.function.Supplier;
import static com.google.common.base.Preconditions.checkNotNull;

public interface ListenerTable<E> extends Listener<E>, Supplier<Table> {
Class<E> getEventClass();
@Getter
public abstract class AbstractListener<E> implements Listener<E> {
private final Class<E> eventClass;

protected AbstractListener(final Class<E> eventClass) {
this.eventClass = checkNotNull(eventClass);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,12 @@ public CombiningEphemeralAccumulatingListener(
) {
checkNotNull(eventManager);
firstListener = new EphemeralAccumulatingListener<>(
eventManager,
firstEventClass,
firstEventClass, eventManager,
firstInitialValue,
firstAccumulator
);
secondListener = new EphemeralAccumulatingListener<>(
eventManager,
secondEventClass,
secondEventClass, eventManager,
secondInitialValue,
secondAccumulator
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@

import static com.google.common.base.Preconditions.checkNotNull;

public class EphemeralAccumulatingListener<E, T> implements Listener<E>, Supplier<T> {
public class EphemeralAccumulatingListener<E, T>
extends AbstractListener<E>
implements Supplier<T> {

private final EventManager eventManager;
private final Class<E> eventClass;
private final BiFunction<T, E, T> accumulator;
private T value;
private boolean stillListening = true;

public EphemeralAccumulatingListener(
final EventManager eventManager,
final Class<E> eventClass,
final EventManager eventManager,
final T initialValue,
final BiFunction<T, E, T> accumulator
) {
super(eventClass);
this.eventManager = checkNotNull(eventManager);
this.eventClass = checkNotNull(eventClass);
this.accumulator = checkNotNull(accumulator);
this.value = initialValue;
eventManager.addListener(eventClass, this);
eventManager.addListener(this);
}

@Override
Expand All @@ -53,7 +54,7 @@ public void receive(final E event) {
@Override
public T get() {
if (stillListening) {
eventManager.removeListener(eventClass, this);
eventManager.removeListener(this);
stillListening = false;
}
return value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@
package uk.ac.ox.poseidon.core.events;

public interface EventManager {
<E> void addListener(
Class<E> eventClass,
Listener<E> listener

void addListener(
Listener<?> listener
);

<E> void removeListener(
Class<E> eventClass,
Listener<E> listener
void removeListener(
Listener<?> listener
);

<E> void broadcast(E event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,13 @@ public class ForwardingEventManager implements EventManager {
private final EventManager secondaryEventManager;

@Override
public <E> void addListener(
final Class<E> eventClass,
final Listener<E> listener
) {
primaryEventManager.addListener(eventClass, listener);
public void addListener(final Listener<?> listener) {
primaryEventManager.addListener(listener);
}

@Override
public <E> void removeListener(
final Class<E> eventClass,
final Listener<E> listener
) {
primaryEventManager.removeListener(eventClass, listener);
public void removeListener(final Listener<?> listener) {
primaryEventManager.removeListener(listener);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@

package uk.ac.ox.poseidon.core.events;

@FunctionalInterface
public interface Listener<E> {

Class<E> getEventClass();

void receive(E event);

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,15 @@ public class SimpleEventManager implements EventManager {
MultimapBuilder.hashKeys().arrayListValues().build();

@Override
public <E> void addListener(
final Class<E> eventClass,
final Listener<E> listener
) {
listeners.put(eventClass, listener);
public void addListener(final Listener<?> listener) {
listeners.put(listener.getEventClass(), listener);
}

@Override
public <E> void removeListener(
final Class<E> eventClass,
final Listener<E> listener
public void removeListener(
final Listener<?> listener
) {
listeners.get(eventClass).removeIf(l -> l == listener);
listeners.get(listener.getEventClass()).removeIf(l -> l == listener);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* POSEIDON: an agent-based model of fisheries
* Copyright (c) 2024 CoHESyS Lab [email protected]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package uk.ac.ox.poseidon.core.events;

import java.util.function.Consumer;

public class SimpleListener<E> extends AbstractListener<E> {
private final Consumer<E> consumer;

public SimpleListener(
final Class<E> eventClass,
final Consumer<E> consumer
) {
super(eventClass);
this.consumer = consumer;
}

@Override
public void receive(final E event) {
consumer.accept(event);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void testBasicAccumulation() {

// Initialize the listener with an initial value of 0
final EphemeralAccumulatingListener<Integer, Integer> listener =
new EphemeralAccumulatingListener<>(eventManager, Integer.class, 0, accumulator);
new EphemeralAccumulatingListener<>(Integer.class, eventManager, 0, accumulator);

// Simulate events being received
listener.receive(5);
Expand All @@ -61,13 +61,13 @@ void testAutoUnsubscriptionOnGet() {

// Initialize the listener with an initial value
final EphemeralAccumulatingListener<String, String> listener =
new EphemeralAccumulatingListener<>(eventManager, String.class, "", accumulator);
new EphemeralAccumulatingListener<>(String.class, eventManager, "", accumulator);

// Call get to retrieve the accumulated value, triggering unsubscription
listener.get();

// Verify that removeListener was called once on eventManager
verify(eventManager, times(1)).removeListener(String.class, listener);
verify(eventManager, times(1)).removeListener(listener);
}

@Test
Expand All @@ -77,7 +77,7 @@ void testSingleRetrievalReturnsSameValue() {

// Initialize the listener with an initial value of 2
final EphemeralAccumulatingListener<Integer, Integer> listener =
new EphemeralAccumulatingListener<>(eventManager, Integer.class, 2, accumulator);
new EphemeralAccumulatingListener<>(Integer.class, eventManager, 2, accumulator);

// Simulate events being received
listener.receive(3);
Expand All @@ -88,23 +88,23 @@ void testSingleRetrievalReturnsSameValue() {
assertEquals(24, listener.get());

// Verify that removeListener was only called once
verify(eventManager, times(1)).removeListener(Integer.class, listener);
verify(eventManager, times(1)).removeListener(listener);
}

@Test
void testNullSafetyInConstructor() {
// Verify that passing null to any constructor argument throws NullPointerException
assertThrows(
NullPointerException.class,
() -> new EphemeralAccumulatingListener<>(null, Integer.class, 0, Integer::sum)
() -> new EphemeralAccumulatingListener<>(Integer.class, null, 0, Integer::sum)
);
assertThrows(
NullPointerException.class,
() -> new EphemeralAccumulatingListener<>(eventManager, null, 0, Integer::sum)
() -> new EphemeralAccumulatingListener<>(null, eventManager, 0, Integer::sum)
);
assertThrows(
NullPointerException.class,
() -> new EphemeralAccumulatingListener<>(eventManager, Integer.class, 0, null)
() -> new EphemeralAccumulatingListener<>(Integer.class, eventManager, 0, null)
);
}

Expand All @@ -115,7 +115,7 @@ void testInitialValueIsUsedCorrectly() {

// Initialize the listener with an initial value of 100
final EphemeralAccumulatingListener<Integer, Integer> listener =
new EphemeralAccumulatingListener<>(eventManager, Integer.class, 100, accumulator);
new EphemeralAccumulatingListener<>(Integer.class, eventManager, 100, accumulator);

// Simulate events being received
listener.receive(10);
Expand Down
Loading

0 comments on commit f7fd94d

Please sign in to comment.