/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2017 the original authors or authors.
*
* Licensed 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 io.janusproject.kernel.bic;
import java.util.Collection;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import io.sarl.core.Destroy;
import io.sarl.core.Initialize;
import io.sarl.lang.core.Address;
import io.sarl.lang.core.AgentTrait;
import io.sarl.lang.core.Capacity;
import io.sarl.lang.core.Event;
import io.sarl.lang.core.EventListener;
/**
* Capacity that provides an event bus to notify the different components of an agent.
*
* <p><strong>This capacity is provided by the Janus kernel, not SARL.</strong>
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
public interface InternalEventBusCapacity extends Capacity {
/**
* Replies the state of the owner of the event bus.
*
* @return the state of the agent.
*/
OwnerState getOwnerState();
/**
* Register the given object on the event bus for receiving any event.
*
* @param listener - the listener on the SARL events.
* @deprecated see {@link #registerEventListener(Object, boolean, Function1)}.
*/
@Deprecated
void registerEventListener(Object listener);
/**
* Register the given object on the event bus for receiving any event.
*
* <p>If the filter is provided, it will be used for determining if the given behavior accepts a specific event.
* If the filter function replies {@code true} for a specific event as argument, the event is fired in the
* behavior context. If the filter function replies {@code false}, the event is not fired in the behavior context.
*
* @param listener - the listener on the SARL events.
* @param fireInitializeEvent - indicates if the {@code Initialize} event should be fired to the listener if the agent is alive.
* @param filter - the filter function.
* @since 0.5
*/
void registerEventListener(Object listener, boolean fireInitializeEvent, Function1<? super Event, ? extends Boolean> filter);
/**
* Unregister the given object on the event bus for receiving any event.
*
* @param listener - the listener on the SARL events.
* @deprecated see {@link #unregisterEventListener(Object, boolean)}.
*/
@Deprecated
void unregisterEventListener(Object listener);
/**
* Unregister the given object on the event bus for receiving any event.
*
* @param listener - the listener on the SARL events.
* @param fireDestroyEvent - indicates if the {@code Destroy} event should be fired to the listener if the agent is alive.
* @since 0.5
*/
void unregisterEventListener(Object listener, boolean fireDestroyEvent);
/**
* Replies if at least one event listener of the given type was registered.
*
* @param type the type of the expected event listener.
* @return <code>true</code> if one event listener of the given type is registered; otherwise <code>false</code>.
*/
boolean hasRegisteredEventListener(Class<?> type);
/**
* Fill the given collection with the events listeners of the given type.
*
* @param <T> the type of the expected event listener.
* @param type the type of the expected event listener.
* @param collection the collection to fill.
* @return the number of added elements.
*/
<T> int getRegisteredEventListeners(Class<T> type, Collection<? super T> collection);
/**
* Sends an event to itself using its defaultInnerAddress as source. Used for platform level event dispatching (i.e.
* {@link Initialize} and {@link Destroy})
*
* @param event - event to propagate into the agent.
*/
void selfEvent(Event event);
/**
* Replies the event listener linked to the owner of this capacity.
*
* @return the event listener of the owner of this skill.
*/
EventListener asEventListener();
/**
* Replies the address of the agent in its inner default space.
*
* @return the address of the agent in its inner default space.
*/
Address getInnerDefaultSpaceAddress();
/**
* Describe the states of the owner of an event bus.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
enum OwnerState {
/**
* The owner of the event bus is unstarted: before initialization process.
*/
UNSTARTED {
@Override
public boolean isEventHandling() {
return true;
}
},
/**
* The owner of the event bus is under creation.
*/
INITIALIZING {
@Override
public boolean isEventHandling() {
return true;
}
},
/**
* The owner of the event bus is running.
*/
ALIVE {
@Override
public boolean isEventHandling() {
return true;
}
},
/**
* The owner of the event bus is under destruction.
*/
DYING {
@Override
public boolean isEventHandling() {
return false;
}
},
/**
* The owner of the event bus was destroyed.
*/
DEAD {
@Override
public boolean isEventHandling() {
return false;
}
};
/** Replies if the state accepts event handling.
*
* @return {@code true} if the state accept event handling.
* @since 0.5
*/
public abstract boolean isEventHandling();
}
/** Context aware implementation of the {@link InternalEventBusCapacity}.
*
* @param <C> type of the capacity.
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @since 0.5
*/
class ContextAwareCapacityWrapper<C extends InternalEventBusCapacity>
extends Capacity.ContextAwareCapacityWrapper<C>
implements InternalEventBusCapacity {
/** Constructor.
*
* @param capacity the original capacity implementation.
* @param caller the caller of the capacity.
*/
public ContextAwareCapacityWrapper(final C capacity, final AgentTrait caller) {
super(capacity, caller);
}
@Override
public OwnerState getOwnerState() {
try {
ensureCallerInLocalThread();
return this.capacity.getOwnerState();
} finally {
resetCallerInLocalThread();
}
}
/** {@inheritDoc}.
* @deprecated see {@link #getRegisteredEventListeners(Class, Collection)}
*/
@Override
@Deprecated
public void registerEventListener(Object listener) {
try {
ensureCallerInLocalThread();
this.capacity.registerEventListener(listener);
} finally {
resetCallerInLocalThread();
}
}
@Override
public void registerEventListener(Object listener, boolean fireInitializeEvent,
Function1<? super Event, ? extends Boolean> filter) {
try {
ensureCallerInLocalThread();
this.capacity.registerEventListener(listener, fireInitializeEvent, filter);
} finally {
resetCallerInLocalThread();
}
}
/** {@inheritDoc}.
* @deprecated see {@link #unregisterEventListener(Object, boolean)}
*/
@Override
@Deprecated
public void unregisterEventListener(Object listener) {
try {
ensureCallerInLocalThread();
this.capacity.unregisterEventListener(listener);
} finally {
resetCallerInLocalThread();
}
}
@Override
public void unregisterEventListener(Object listener, boolean fireDestroyEvent) {
try {
ensureCallerInLocalThread();
this.capacity.unregisterEventListener(listener, fireDestroyEvent);
} finally {
resetCallerInLocalThread();
}
}
@Override
public boolean hasRegisteredEventListener(Class<?> type) {
try {
ensureCallerInLocalThread();
return this.capacity.hasRegisteredEventListener(type);
} finally {
resetCallerInLocalThread();
}
}
@Override
public <T> int getRegisteredEventListeners(Class<T> type, Collection<? super T> collection) {
try {
ensureCallerInLocalThread();
return this.capacity.getRegisteredEventListeners(type, collection);
} finally {
resetCallerInLocalThread();
}
}
@Override
public void selfEvent(Event event) {
try {
ensureCallerInLocalThread();
this.capacity.selfEvent(event);
} finally {
resetCallerInLocalThread();
}
}
@Override
public EventListener asEventListener() {
try {
ensureCallerInLocalThread();
return this.capacity.asEventListener();
} finally {
resetCallerInLocalThread();
}
}
@Override
public Address getInnerDefaultSpaceAddress() {
try {
ensureCallerInLocalThread();
return this.capacity.getInnerDefaultSpaceAddress();
} finally {
resetCallerInLocalThread();
}
}
}
}