/* Copyright (c) 2011 Danish Maritime Authority.
*
* 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 net.maritimecloud.internal.mms.client;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.TimeUnit;
import net.maritimecloud.core.id.MaritimeId;
import net.maritimecloud.internal.mms.client.broadcast.BroadcastDeserializer;
import net.maritimecloud.internal.mms.client.broadcast.ClientBroadcastManager;
import net.maritimecloud.internal.mms.client.connection.ClientConnection;
import net.maritimecloud.internal.mms.client.connection.DefaultMmsConnection;
import net.maritimecloud.internal.mms.client.connection.transport.ClientTransportFactory;
import net.maritimecloud.internal.mms.client.endpoint.ClientEndpointManager;
import net.maritimecloud.internal.util.logging.Logger;
import net.maritimecloud.message.Message;
import net.maritimecloud.message.MessageSerializer;
import net.maritimecloud.message.ValueSerializer;
import net.maritimecloud.net.BroadcastConsumer;
import net.maritimecloud.net.BroadcastMessage;
import net.maritimecloud.net.BroadcastSubscription;
import net.maritimecloud.net.DispatchedMessage;
import net.maritimecloud.net.EndpointImplementation;
import net.maritimecloud.net.EndpointInvocationFuture;
import net.maritimecloud.net.EndpointRegistration;
import net.maritimecloud.net.LocalEndpoint;
import net.maritimecloud.net.mms.MmsBroadcastOptions;
import net.maritimecloud.net.mms.MmsClient;
import net.maritimecloud.net.mms.MmsClientConfiguration;
import net.maritimecloud.net.mms.MmsConnection;
import net.maritimecloud.net.mms.MmsEndpointLocator;
import net.maritimecloud.util.geometry.Area;
import org.cakeframework.container.Container;
import org.cakeframework.container.Container.State;
import org.cakeframework.container.ContainerConfiguration;
/**
* An implementation of {@link MmsClient} using WebSockets and JSON. This class delegates all work to other services.
*
* @author Kasper Nielsen
*/
public class DefaultMmsClient implements MmsClient {
/** The logger. */
private static final Logger LOGGER = Logger.get(DefaultMmsClient.class);
/** Responsible for listening and sending broadcasts. */
private final ClientBroadcastManager broadcaster;
private final ClientInfo clientInfo;
/** Manages registration of services. */
private final MmsConnection connection;
/** The internal client. */
private final Container container;
/** Manages registration of services. */
private final ClientEndpointManager endpoints;
/**
* Creates a new instance of this class.
*
* @param configuration
* the configuration of the connection
*/
public DefaultMmsClient(MmsClientConfiguration configuration) {
container = createClient(configuration);
broadcaster = container.getService(ClientBroadcastManager.class);
connection = container.getService(MmsConnection.class);
endpoints = container.getService(ClientEndpointManager.class);
clientInfo = container.getService(ClientInfo.class);
}
/** {@inheritDoc} */
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return container.awaitState(State.TERMINATED, timeout, unit);
}
/** {@inheritDoc} */
@Override
public DispatchedMessage broadcast(BroadcastMessage message, MmsBroadcastOptions options) {
return broadcaster.broadcast(message, options);
}
public <T extends BroadcastMessage> BroadcastSubscription broadcastSubscribe(BroadcastDeserializer bd, String type,
BroadcastConsumer<T> listener, Area area) {
return broadcaster.broadcastSubscribe(bd, type, listener, area);
}
/** {@inheritDoc} */
@Override
public <T extends BroadcastMessage> BroadcastSubscription broadcastSubscribe(Class<T> messageType,
BroadcastConsumer<T> consumer) {
return broadcaster.broadcastSubscribe(messageType, consumer, null);
}
/** {@inheritDoc} */
@Override
public <T extends BroadcastMessage> BroadcastSubscription broadcastSubscribe(Class<T> messageType,
BroadcastConsumer<T> consumer, Area area) {
return broadcaster.broadcastSubscribe(messageType, consumer, requireNonNull(area, "area is null"));
}
/** {@inheritDoc} */
@Override
public void shutdown() {
container.shutdown();
}
/** {@inheritDoc} */
@Override
public MmsConnection connection() {
return connection;
}
/** {@inheritDoc} */
@Override
public <T extends LocalEndpoint> T endpointCreate(MaritimeId id, Class<T> endpointType) {
return endpoints.endpointFrom(id, endpointType);
}
/** {@inheritDoc} */
@Override
public <T extends LocalEndpoint> MmsEndpointLocator<T> endpointLocate(Class<T> endpointType) {
return endpoints.endpointFind(endpointType);
}
/** {@inheritDoc} */
@Override
public EndpointRegistration endpointRegister(EndpointImplementation implementation) {
return endpoints.endpointRegister(implementation);
}
protected void finalize() {
shutdown();
}
/** {@inheritDoc} */
@Override
public final MaritimeId getClientId() {
return clientInfo.getClientId();
}
public <T> EndpointInvocationFuture<T> invokeRemote(MaritimeId receiver, String endpoint, Message parameters,
MessageSerializer<? extends Message> serializer, ValueSerializer<T> resultParser) {
return endpoints.invokeRemote(receiver, endpoint, parameters, serializer, resultParser);
}
/** {@inheritDoc} */
@Override
public boolean isShutdown() {
return container.getState().isShutdown();
}
/** {@inheritDoc} */
@Override
public boolean isTerminated() {
return container.getState() == State.TERMINATED;
}
public static Container createClient(MmsClientConfiguration configuration) {
MaritimeId clientId = requireNonNull(configuration.getId());
ContainerConfiguration cc = new ContainerConfiguration();
cc.addService(configuration.getPositionReader());
cc.addService(clientId);
cc.addService(configuration);
cc.addService(ConnectionKeepAlive.class);
cc.addService(ClientInfo.class);
cc.addService(ClientBroadcastManager.class);
cc.addService(ClientEndpointManager.class);
cc.addService(DefaultMmsConnection.class);
cc.addService(MmsThreadManager.class);
cc.addService(ClientConnection.class);
cc.addService(ClientTransportFactory.create(configuration));
LOGGER.debug("Creating client for " + clientId);
return cc.create();
}
}