org.geppetto.samplesimulation.SimulationServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.geppetto.samplesimulation.SimulationServlet.java

Source

/*******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2011, 2013 OpenWorm.
 * http://openworm.org
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the MIT License
 * which accompanies this distribution, and is available at
 * http://opensource.org/licenses/MIT
 *
 * Contributors:
 *        OpenWorm - http://openworm.org/people.html
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *******************************************************************************/

package org.geppetto.samplesimulation;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;
import org.geppetto.core.model.HHModel;
import org.geppetto.core.simulator.ISimulator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.google.gson.Gson;

public class SimulationServlet extends WebSocketServlet {

    @Autowired
    public SimulationConfig config;

    @Autowired
    public ISimulator sampleSimulatorService;

    private static final long serialVersionUID = 1L;

    private static final long UPDATE_CYCLE = 100;

    private final AtomicInteger _connectionIds = new AtomicInteger(0);

    private final ConcurrentHashMap<Integer, SessionContext> _simulations = new ConcurrentHashMap<Integer, SessionContext>();

    private final ConcurrentHashMap<Integer, SimDataInbound> _connections = new ConcurrentHashMap<Integer, SimDataInbound>();

    private Timer _simTimer;

    @Override
    protected StreamInbound createWebSocketInbound(String subProtocol, HttpServletRequest request) {
        return new SimDataInbound(_connectionIds.incrementAndGet());
    }

    @Override
    public void init() throws ServletException {
        super.init();
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    private void startClientUpdateTimer() {
        _simTimer = new Timer(
                SimulationServlet.class.getSimpleName() + " - Timer - " + new java.util.Date().getTime());
        _simTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    update();
                } catch (RuntimeException e) {
                    // log.error("Caught to prevent timer from shutting down", e);
                }
            }
        }, UPDATE_CYCLE, UPDATE_CYCLE);
    }

    private void update() {
        StringBuilder sb = new StringBuilder();
        for (Iterator<SessionContext> iterator = getSimulations().iterator(); iterator.hasNext();) {
            SessionContext simulation = iterator.next();

            if (simulation._models != null) {
                List<Float> xDataset = new ArrayList<Float>();
                List<Float> yDataset = new ArrayList<Float>();

                for (int t = 0; t < simulation._models.get("0").size(); t++) {
                    // plot from 0
                    if ((t * simulation._timeConfiguration.getTimeStepLength()) >= 0) {
                        xDataset.add(
                                t * config.getSamplingPeriod() * simulation._timeConfiguration.getTimeStepLength());
                        yDataset.add(((HHModel) simulation._models.get("0").get(t)).getV());
                    }
                }

                Gson gson = new Gson();
                // Put both objects in n array of 2 elements
                sb.append("[" + gson.toJson(xDataset) + "," + gson.toJson(yDataset) + "]");
            }
        }

        sendUpdate(sb.toString());
    }

    private void sendUpdate(String message) {
        for (SimDataInbound connection : getConnections()) {
            try {
                CharBuffer buffer = CharBuffer.wrap(message);
                connection.getWsOutbound().writeTextMessage(buffer);
            } catch (IOException ignore) {
                // Ignore
            }
        }
    }

    private Collection<SimDataInbound> getConnections() {
        return Collections.unmodifiableCollection(_connections.values());
    }

    private Collection<SessionContext> getSimulations() {
        return Collections.unmodifiableCollection(_simulations.values());
    }

    private final class SimDataInbound extends MessageInbound {

        private final int id;
        private SessionContext _sessionContext;

        private SimDataInbound(int id) {
            super();
            this.id = id;
        }

        @Override
        protected void onOpen(WsOutbound outbound) {
            _sessionContext = new SessionContext();
            _simulations.put(Integer.valueOf(id), _sessionContext);
            _connections.put(Integer.valueOf(id), this);
            // tentative support for multiple connections but we'll have to see
            // how the osgi services can be instantiated
        }

        @Override
        protected void onClose(int status) {
            _simulations.remove(Integer.valueOf(id));
            _connections.remove(Integer.valueOf(id));
        }

        @Override
        protected void onBinaryMessage(ByteBuffer message) throws IOException {
            throw new UnsupportedOperationException("Binary message not supported.");
        }

        @Override
        protected void onTextMessage(CharBuffer message) throws IOException {
            String msg = message.toString();
            if (msg.equals("start")) {
                _sessionContext._runSimulation = true;
                new SimulationThread(_sessionContext, config, sampleSimulatorService).start();
                startClientUpdateTimer();
            } else if (msg.equals("stop")) {
                _sessionContext._runSimulation = false;
                _simTimer.cancel();
            } else if (msg.equals("reset")) {
                // stop simulation in case it's running
                if (_sessionContext._runSimulation) {
                    _sessionContext._runSimulation = false;
                    _simTimer.cancel();
                }

                // reset simulation parameters
                resetSimulationParams();
            } else {
                _sessionContext.setCurrent(Float.valueOf(msg));
            }
        }

        private void resetSimulationParams() {
            _sessionContext._models = null;
            _sessionContext._processedElements = 0;
            _sessionContext._externalCurrent = 0.0f;
        }

    }
}