ch.algotrader.adapter.ib.DefaultIBSessionStateHolder.java Source code

Java tutorial

Introduction

Here is the source code for ch.algotrader.adapter.ib.DefaultIBSessionStateHolder.java

Source

/***********************************************************************************
 * AlgoTrader Enterprise Trading Framework
 *
 * Copyright (C) 2015 AlgoTrader GmbH - All rights reserved
 *
 * All information contained herein is, and remains the property of AlgoTrader GmbH.
 * The intellectual and technical concepts contained herein are proprietary to
 * AlgoTrader GmbH. Modification, translation, reverse engineering, decompilation,
 * disassembly or reproduction of this material is strictly forbidden unless prior
 * written permission is obtained from AlgoTrader GmbH
 *
 * Fur detailed terms and conditions consult the file LICENSE.txt or contact
 *
 * AlgoTrader GmbH
 * Aeschstrasse 6
 * 8834 Schindellegi
 ***********************************************************************************/
package ch.algotrader.adapter.ib;

import java.util.concurrent.atomic.AtomicReference;

import org.apache.commons.lang.Validate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import ch.algotrader.enumeration.ConnectionState;
import ch.algotrader.event.dispatch.EventDispatcher;
import ch.algotrader.event.dispatch.EventRecipient;
import ch.algotrader.vo.SessionEventVO;

/**
 * @author <a href="mailto:aflury@algotrader.ch">Andy Flury</a>
 */
public class DefaultIBSessionStateHolder implements IBSessionStateHolder {

    private static final Logger LOGGER = LogManager.getLogger(DefaultIBSessionStateHolder.class);

    private final String name;
    private final EventDispatcher eventDispatcher;
    private final AtomicReference<ConnectionState> connState;

    public DefaultIBSessionStateHolder(final String name, final EventDispatcher eventDispatcher) {

        Validate.notEmpty(name, "Session name is null");
        Validate.notNull(eventDispatcher, "PlatformEventDispatcher is null");

        this.name = name;
        this.eventDispatcher = eventDispatcher;
        this.connState = new AtomicReference<>(ConnectionState.DISCONNECTED);
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void onCreate() {
        onConnect();
    }

    @Override
    public void onLogon() {
        onLogon(false);
    }

    @Override
    public void onConnect() {

        if (compareAndSet(ConnectionState.DISCONNECTED, ConnectionState.CONNECTED)) {

            SessionEventVO event = new SessionEventVO(ConnectionState.CONNECTED, this.name);
            this.eventDispatcher.broadcast(event, EventRecipient.ALL);
        }
    }

    @Override
    public void onDisconnect() {

        ConnectionState previousState = this.connState.getAndSet(ConnectionState.DISCONNECTED);
        if (previousState.compareTo(ConnectionState.DISCONNECTED) > 0) {

            this.connState.set(ConnectionState.DISCONNECTED);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("change state to {}", ConnectionState.DISCONNECTED);
            }

            SessionEventVO event = new SessionEventVO(ConnectionState.DISCONNECTED, this.name);
            this.eventDispatcher.broadcast(event, EventRecipient.ALL);
        }

    }

    /**
     * logon with subscriptions either maintained or not-maintained
     * returns true if a re-subscription is necessary
     */
    @Override
    public void onLogon(boolean maintained) {

        if (onLogon0(maintained)) {

            SessionEventVO event = new SessionEventVO(ConnectionState.LOGGED_ON, this.name);
            this.eventDispatcher.broadcast(event, EventRecipient.ALL);
        }
    }

    private synchronized boolean onLogon0(boolean maintained) {

        if (maintained) {

            // if we have previously been IDLE no need to re-subscribe
            if (compareAndSet(ConnectionState.IDLE, ConnectionState.SUBSCRIBED)) {
                return false;
            }

            // if we have been CONNECTED we need to resubscribe
            return compareAndSet(ConnectionState.CONNECTED, ConnectionState.LOGGED_ON);

        } else {

            // re-subscribe if we have been previously CONNECTED or IDLE
            return (compareAndSet(ConnectionState.IDLE, ConnectionState.LOGGED_ON)
                    || compareAndSet(ConnectionState.CONNECTED, ConnectionState.LOGGED_ON));
        }
    }

    @Override
    public void onLogoff() {

        if (onLogoff0()) {

            SessionEventVO event = new SessionEventVO(ConnectionState.CONNECTED, this.name);
            this.eventDispatcher.broadcast(event, EventRecipient.ALL);
        }
    }

    private synchronized boolean onLogoff0() {

        return compareAndSet(ConnectionState.LOGGED_ON, ConnectionState.CONNECTED)
                || compareAndSet(ConnectionState.SUBSCRIBED, ConnectionState.IDLE);
    }

    /**
     * returns true if there is a need to subscribe
     */
    @Override
    public boolean onSubscribe() {

        if (compareAndSet(ConnectionState.LOGGED_ON, ConnectionState.SUBSCRIBED)) {

            SessionEventVO event = new SessionEventVO(ConnectionState.SUBSCRIBED, this.name);
            this.eventDispatcher.broadcast(event, EventRecipient.ALL);
            return true;
        } else {

            return false;
        }
    }

    @Override
    public ConnectionState getConnectionState() {

        return this.connState.get();
    }

    @Override
    public boolean isLoggedOn() {

        return this.connState.get().getValue() >= ConnectionState.LOGGED_ON.getValue();
    }

    @Override
    public boolean isSubscribed() {

        return this.connState.get().getValue() >= ConnectionState.SUBSCRIBED.getValue();
    }

    private boolean compareAndSet(ConnectionState before, ConnectionState after) {

        boolean success = this.connState.compareAndSet(before, after);

        if (success) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("change state from {} to {}", before, after);
            }
        }

        return success;
    }
}