"""
Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)

Date:   Wed Aug 17 13:32:50 2016

Model author: Yentl Van Tendeloo
Model name:   HTTP Server
Model description:
Example HTTP echo server.
"""

from sccd.runtime.statecharts_core import *
import time
import os
import urllib
import sys
import json

import sys

# package "HTTP Server"

class Echo(RuntimeClassBase):
    def __init__(self, controller, params):
        RuntimeClassBase.__init__(self, controller)
        
        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
        self.semantics.priority = StatechartSemantics.SourceParent
        self.semantics.concurrency = StatechartSemantics.Single
        
        # build Statechart structure
        self.build_statechart_structure()
        
        # call user defined constructor
        Echo.user_defined_constructor(self, params)
    
    def user_defined_constructor(self, params):
        self.source = None
    
    def user_defined_destructor(self):
        pass
    
    
    # builds Statechart structure
    def build_statechart_structure(self):
        
        # state <root>
        self.states[""] = State(0, self)
        
        # state /init_server
        self.states["/init_server"] = State(1, self)
        self.states["/init_server"].setEnter(self._init_server_enter)
        
        # state /wait_for_requests
        self.states["/wait_for_requests"] = State(2, self)
        
        # state /wait_for_requests/wait
        self.states["/wait_for_requests/wait"] = State(3, self)
        
        # add children
        self.states[""].addChild(self.states["/init_server"])
        self.states[""].addChild(self.states["/wait_for_requests"])
        self.states["/wait_for_requests"].addChild(self.states["/wait_for_requests/wait"])
        self.states[""].fixTree()
        self.states[""].default_state = self.states["/init_server"]
        self.states["/wait_for_requests"].default_state = self.states["/wait_for_requests/wait"]
        
        # transition /init_server
        _init_server_0 = Transition(self, self.states["/init_server"], [self.states["/wait_for_requests"]])
        _init_server_0.setAction(self._init_server_0_exec)
        _init_server_0.setTrigger(Event("instance_created", None))
        self.states["/init_server"].addTransition(_init_server_0)
        
        # transition /wait_for_requests/wait
        _wait_for_requests_wait_0 = Transition(self, self.states["/wait_for_requests/wait"], [self.states["/wait_for_requests/wait"]])
        _wait_for_requests_wait_0.setAction(self._wait_for_requests_wait_0_exec)
        _wait_for_requests_wait_0.setTrigger(Event("HTTP_output", None))
        self.states["/wait_for_requests/wait"].addTransition(_wait_for_requests_wait_0)
    
    def _init_server_enter(self):
        self.big_step.outputEventOM(Event("create_instance", None, [self, 'to_server', 'Server', '', 8080]))
    
    def _init_server_0_exec(self, parameters):
        instancename = parameters[0]
        self.big_step.outputEventOM(Event("start_instance", None, [self, instancename]))
    
    def _wait_for_requests_wait_0_exec(self, parameters):
        source = parameters[0]
        data = parameters[1]
        print("Got input: " + str(data))
        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'to_server/%s' % source, Event("HTTP_input", None, [data])]))
    
    def initializeStatechart(self):
        # enter default state
        self.default_targets = self.states["/init_server"].getEffectiveTargetStates()
        RuntimeClassBase.initializeStatechart(self)

class Server(RuntimeClassBase):
    def __init__(self, controller, address, port):
        RuntimeClassBase.__init__(self, controller)
        
        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
        self.semantics.priority = StatechartSemantics.SourceParent
        self.semantics.concurrency = StatechartSemantics.Single
        
        # build Statechart structure
        self.build_statechart_structure()
        
        # call user defined constructor
        Server.user_defined_constructor(self, address, port)
    
    def user_defined_constructor(self, address, port):
        self.socket = None
        self.address = address
        self.port = port
    
    def user_defined_destructor(self):
        pass
    
    
    # builds Statechart structure
    def build_statechart_structure(self):
        
        # state <root>
        self.states[""] = State(0, self)
        
        # state /main
        self.states["/main"] = ParallelState(1, self)
        
        # state /main/forward
        self.states["/main/forward"] = State(2, self)
        
        # state /main/forward/forward
        self.states["/main/forward/forward"] = State(3, self)
        
        # state /main/server
        self.states["/main/server"] = State(4, self)
        
        # state /main/server/init
        self.states["/main/server/init"] = State(5, self)
        self.states["/main/server/init"].setEnter(self._main_server_init_enter)
        
        # state /main/server/binding
        self.states["/main/server/binding"] = State(6, self)
        self.states["/main/server/binding"].setEnter(self._main_server_binding_enter)
        
        # state /main/server/listening
        self.states["/main/server/listening"] = State(7, self)
        self.states["/main/server/listening"].setEnter(self._main_server_listening_enter)
        
        # state /main/server/accepting
        self.states["/main/server/accepting"] = State(8, self)
        self.states["/main/server/accepting"].setEnter(self._main_server_accepting_enter)
        self.states["/main/server/accepting"].setExit(self._main_server_accepting_exit)
        
        # state /main/close_socket
        self.states["/main/close_socket"] = State(9, self)
        
        # state /main/close_socket/close
        self.states["/main/close_socket/close"] = State(10, self)
        
        # add children
        self.states[""].addChild(self.states["/main"])
        self.states["/main"].addChild(self.states["/main/forward"])
        self.states["/main"].addChild(self.states["/main/server"])
        self.states["/main"].addChild(self.states["/main/close_socket"])
        self.states["/main/forward"].addChild(self.states["/main/forward/forward"])
        self.states["/main/server"].addChild(self.states["/main/server/init"])
        self.states["/main/server"].addChild(self.states["/main/server/binding"])
        self.states["/main/server"].addChild(self.states["/main/server/listening"])
        self.states["/main/server"].addChild(self.states["/main/server/accepting"])
        self.states["/main/close_socket"].addChild(self.states["/main/close_socket/close"])
        self.states[""].fixTree()
        self.states[""].default_state = self.states["/main"]
        self.states["/main/forward"].default_state = self.states["/main/forward/forward"]
        self.states["/main/server"].default_state = self.states["/main/server/init"]
        self.states["/main/close_socket"].default_state = self.states["/main/close_socket/close"]
        
        # transition /main/forward/forward
        _main_forward_forward_0 = Transition(self, self.states["/main/forward/forward"], [self.states["/main/forward/forward"]])
        _main_forward_forward_0.setAction(self._main_forward_forward_0_exec)
        _main_forward_forward_0.setTrigger(Event("HTTP_output", None))
        self.states["/main/forward/forward"].addTransition(_main_forward_forward_0)
        
        # transition /main/server/init
        _main_server_init_0 = Transition(self, self.states["/main/server/init"], [self.states["/main/server/binding"]])
        _main_server_init_0.setAction(self._main_server_init_0_exec)
        _main_server_init_0.setTrigger(Event("created_socket", "socket_in"))
        self.states["/main/server/init"].addTransition(_main_server_init_0)
        
        # transition /main/server/binding
        _main_server_binding_0 = Transition(self, self.states["/main/server/binding"], [self.states["/main/server/listening"]])
        _main_server_binding_0.setTrigger(Event("bound_socket", "socket_in"))
        _main_server_binding_0.setGuard(self._main_server_binding_0_guard)
        self.states["/main/server/binding"].addTransition(_main_server_binding_0)
        
        # transition /main/server/listening
        _main_server_listening_0 = Transition(self, self.states["/main/server/listening"], [self.states["/main/server/accepting"]])
        _main_server_listening_0.setAction(self._main_server_listening_0_exec)
        _main_server_listening_0.setTrigger(Event("listened_socket", "socket_in"))
        _main_server_listening_0.setGuard(self._main_server_listening_0_guard)
        self.states["/main/server/listening"].addTransition(_main_server_listening_0)
        
        # transition /main/server/accepting
        _main_server_accepting_0 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]])
        _main_server_accepting_0.setAction(self._main_server_accepting_0_exec)
        _main_server_accepting_0.setTrigger(Event("accepted_socket", "socket_in"))
        self.states["/main/server/accepting"].addTransition(_main_server_accepting_0)
        _main_server_accepting_1 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]])
        _main_server_accepting_1.setAction(self._main_server_accepting_1_exec)
        _main_server_accepting_1.setTrigger(Event("instance_created", None))
        self.states["/main/server/accepting"].addTransition(_main_server_accepting_1)
        _main_server_accepting_2 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]])
        _main_server_accepting_2.setTrigger(Event("_0after"))
        self.states["/main/server/accepting"].addTransition(_main_server_accepting_2)
        
        # transition /main/close_socket/close
        _main_close_socket_close_0 = Transition(self, self.states["/main/close_socket/close"], [self.states["/main/close_socket/close"]])
        _main_close_socket_close_0.setAction(self._main_close_socket_close_0_exec)
        _main_close_socket_close_0.setTrigger(Event("close_socket", None))
        self.states["/main/close_socket/close"].addTransition(_main_close_socket_close_0)
    
    def _main_server_init_enter(self):
        self.big_step.outputEvent(Event("create_socket", "socket_out", []))
    
    def _main_server_binding_enter(self):
        self.big_step.outputEvent(Event("bind_socket", "socket_out", [self.socket, (self.address, self.port)]))
    
    def _main_server_listening_enter(self):
        self.big_step.outputEvent(Event("listen_socket", "socket_out", [self.socket]))
    
    def _main_server_accepting_enter(self):
        self.addTimer(0, 1.0)
    
    def _main_server_accepting_exit(self):
        self.removeTimer(0)
    
    def _main_forward_forward_0_exec(self, parameters):
        association_name = parameters[0]
        data = parameters[1]
        print("Forward")
        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("HTTP_output", None, [association_name, data])]))
    
    def _main_server_init_0_exec(self, parameters):
        socket = parameters[0]
        self.socket = socket
    
    def _main_server_binding_0_guard(self, parameters):
        socket = parameters[0]
        return self.socket == socket
    
    def _main_server_listening_0_exec(self, parameters):
        socket = parameters[0]
        self.big_step.outputEvent(Event("accept_socket", "socket_out", [self.socket]))
    
    def _main_server_listening_0_guard(self, parameters):
        socket = parameters[0]
        return self.socket == socket
    
    def _main_server_accepting_0_exec(self, parameters):
        socket = parameters[0]
        connected_socket = parameters[1]
        self.big_step.outputEventOM(Event("create_instance", None, [self, 'sockets', 'Socket', connected_socket]))
        self.big_step.outputEvent(Event("accept_socket", "socket_out", [self.socket]))
    
    def _main_server_accepting_1_exec(self, parameters):
        instancename = parameters[0]
        self.big_step.outputEventOM(Event("start_instance", None, [self, instancename]))
        self.big_step.outputEventOM(Event("narrow_cast", None, [self, instancename, Event("set_association_name", None, [instancename])]))
    
    def _main_close_socket_close_0_exec(self, parameters):
        association_name = parameters[0]
        self.big_step.outputEventOM(Event("delete_instance", None, [self, association_name]))
    
    def initializeStatechart(self):
        # enter default state
        self.default_targets = self.states["/main"].getEffectiveTargetStates()
        RuntimeClassBase.initializeStatechart(self)

class Socket(RuntimeClassBase):
    def __init__(self, controller, my_socket):
        RuntimeClassBase.__init__(self, controller)
        
        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
        self.semantics.priority = StatechartSemantics.SourceParent
        self.semantics.concurrency = StatechartSemantics.Single
        
        # build Statechart structure
        self.build_statechart_structure()
        
        # call user defined constructor
        Socket.user_defined_constructor(self, my_socket)
    
    def user_defined_constructor(self, my_socket):
        self.socket = my_socket
        self.received_data = ""
        self.send_data = ""
        self.closed = False
        self.association_name = None
    
    def user_defined_destructor(self):
        pass
    
    
    # builds Statechart structure
    def build_statechart_structure(self):
        
        # state <root>
        self.states[""] = State(0, self)
        
        # state /init
        self.states["/init"] = State(1, self)
        
        # state /connected
        self.states["/connected"] = ParallelState(2, self)
        
        # state /connected/listening
        self.states["/connected/listening"] = State(3, self)
        
        # state /connected/listening/listen
        self.states["/connected/listening/listen"] = State(4, self)
        self.states["/connected/listening/listen"].setEnter(self._connected_listening_listen_enter)
        
        # state /connected/listening/closed
        self.states["/connected/listening/closed"] = State(5, self)
        self.states["/connected/listening/closed"].setEnter(self._connected_listening_closed_enter)
        
        # state /connected/sending
        self.states["/connected/sending"] = State(6, self)
        
        # state /connected/sending/waiting_for_data
        self.states["/connected/sending/waiting_for_data"] = State(7, self)
        
        # state /connected/sending/transferring
        self.states["/connected/sending/transferring"] = State(8, self)
        
        # state /connected/queueing
        self.states["/connected/queueing"] = State(9, self)
        
        # state /connected/queueing/queueing
        self.states["/connected/queueing/queueing"] = State(10, self)
        
        # state /connected/parsing
        self.states["/connected/parsing"] = State(11, self)
        
        # state /connected/parsing/wait_for_header
        self.states["/connected/parsing/wait_for_header"] = State(12, self)
        
        # state /connected/parsing/closing
        self.states["/connected/parsing/closing"] = State(13, self)
        self.states["/connected/parsing/closing"].setEnter(self._connected_parsing_closing_enter)
        self.states["/connected/parsing/closing"].setExit(self._connected_parsing_closing_exit)
        
        # state /connected/parsing/wait_for_payload
        self.states["/connected/parsing/wait_for_payload"] = State(14, self)
        
        # state /close
        self.states["/close"] = State(15, self)
        self.states["/close"].setEnter(self._close_enter)
        
        # add children
        self.states[""].addChild(self.states["/init"])
        self.states[""].addChild(self.states["/connected"])
        self.states[""].addChild(self.states["/close"])
        self.states["/connected"].addChild(self.states["/connected/listening"])
        self.states["/connected"].addChild(self.states["/connected/sending"])
        self.states["/connected"].addChild(self.states["/connected/queueing"])
        self.states["/connected"].addChild(self.states["/connected/parsing"])
        self.states["/connected/listening"].addChild(self.states["/connected/listening/listen"])
        self.states["/connected/listening"].addChild(self.states["/connected/listening/closed"])
        self.states["/connected/sending"].addChild(self.states["/connected/sending/waiting_for_data"])
        self.states["/connected/sending"].addChild(self.states["/connected/sending/transferring"])
        self.states["/connected/queueing"].addChild(self.states["/connected/queueing/queueing"])
        self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_header"])
        self.states["/connected/parsing"].addChild(self.states["/connected/parsing/closing"])
        self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_payload"])
        self.states[""].fixTree()
        self.states[""].default_state = self.states["/init"]
        self.states["/connected/listening"].default_state = self.states["/connected/listening/listen"]
        self.states["/connected/sending"].default_state = self.states["/connected/sending/waiting_for_data"]
        self.states["/connected/queueing"].default_state = self.states["/connected/queueing/queueing"]
        self.states["/connected/parsing"].default_state = self.states["/connected/parsing/wait_for_header"]
        
        # transition /init
        _init_0 = Transition(self, self.states["/init"], [self.states["/connected"]])
        _init_0.setAction(self._init_0_exec)
        _init_0.setTrigger(Event("set_association_name", None))
        self.states["/init"].addTransition(_init_0)
        
        # transition /connected/listening/listen
        _connected_listening_listen_0 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/listen"]])
        _connected_listening_listen_0.setAction(self._connected_listening_listen_0_exec)
        _connected_listening_listen_0.setTrigger(Event("received_socket", "socket_in"))
        _connected_listening_listen_0.setGuard(self._connected_listening_listen_0_guard)
        self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_0)
        _connected_listening_listen_1 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/closed"]])
        _connected_listening_listen_1.setAction(self._connected_listening_listen_1_exec)
        _connected_listening_listen_1.setTrigger(Event("received_socket", "socket_in"))
        _connected_listening_listen_1.setGuard(self._connected_listening_listen_1_guard)
        self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_1)
        
        # transition /connected/sending/waiting_for_data
        _connected_sending_waiting_for_data_0 = Transition(self, self.states["/connected/sending/waiting_for_data"], [self.states["/connected/sending/transferring"]])
        _connected_sending_waiting_for_data_0.setAction(self._connected_sending_waiting_for_data_0_exec)
        _connected_sending_waiting_for_data_0.setTrigger(None)
        _connected_sending_waiting_for_data_0.setGuard(self._connected_sending_waiting_for_data_0_guard)
        self.states["/connected/sending/waiting_for_data"].addTransition(_connected_sending_waiting_for_data_0)
        
        # transition /connected/sending/transferring
        _connected_sending_transferring_0 = Transition(self, self.states["/connected/sending/transferring"], [self.states["/connected/sending/waiting_for_data"]])
        _connected_sending_transferring_0.setAction(self._connected_sending_transferring_0_exec)
        _connected_sending_transferring_0.setTrigger(Event("sent_socket", "socket_in"))
        _connected_sending_transferring_0.setGuard(self._connected_sending_transferring_0_guard)
        self.states["/connected/sending/transferring"].addTransition(_connected_sending_transferring_0)
        
        # transition /connected/queueing/queueing
        _connected_queueing_queueing_0 = Transition(self, self.states["/connected/queueing/queueing"], [self.states["/connected/queueing/queueing"]])
        _connected_queueing_queueing_0.setAction(self._connected_queueing_queueing_0_exec)
        _connected_queueing_queueing_0.setTrigger(Event("HTTP_input", None))
        self.states["/connected/queueing/queueing"].addTransition(_connected_queueing_queueing_0)
        
        # transition /connected/parsing/wait_for_header
        _connected_parsing_wait_for_header_0 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/wait_for_payload"]])
        _connected_parsing_wait_for_header_0.setAction(self._connected_parsing_wait_for_header_0_exec)
        _connected_parsing_wait_for_header_0.setTrigger(None)
        _connected_parsing_wait_for_header_0.setGuard(self._connected_parsing_wait_for_header_0_guard)
        self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_0)
        _connected_parsing_wait_for_header_1 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/closing"]])
        _connected_parsing_wait_for_header_1.setTrigger(None)
        _connected_parsing_wait_for_header_1.setGuard(self._connected_parsing_wait_for_header_1_guard)
        self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_1)
        
        # transition /connected/parsing/closing
        _connected_parsing_closing_0 = Transition(self, self.states["/connected/parsing/closing"], [self.states["/connected/parsing/closing"]])
        _connected_parsing_closing_0.setAction(self._connected_parsing_closing_0_exec)
        _connected_parsing_closing_0.setTrigger(Event("_0after"))
        self.states["/connected/parsing/closing"].addTransition(_connected_parsing_closing_0)
        
        # transition /connected/parsing/wait_for_payload
        _connected_parsing_wait_for_payload_0 = Transition(self, self.states["/connected/parsing/wait_for_payload"], [self.states["/connected/parsing/wait_for_header"]])
        _connected_parsing_wait_for_payload_0.setAction(self._connected_parsing_wait_for_payload_0_exec)
        _connected_parsing_wait_for_payload_0.setTrigger(None)
        _connected_parsing_wait_for_payload_0.setGuard(self._connected_parsing_wait_for_payload_0_guard)
        self.states["/connected/parsing/wait_for_payload"].addTransition(_connected_parsing_wait_for_payload_0)
        
        # transition /connected
        _connected_0 = Transition(self, self.states["/connected"], [self.states["/close"]])
        _connected_0.setTrigger(Event("close", None))
        self.states["/connected"].addTransition(_connected_0)
    
    def _connected_listening_listen_enter(self):
        self.big_step.outputEvent(Event("recv_socket", "socket_out", [self.socket]))
    
    def _connected_listening_closed_enter(self):
        self.closed = True
    
    def _connected_parsing_closing_enter(self):
        self.addTimer(0, 0.0)
    
    def _connected_parsing_closing_exit(self):
        self.removeTimer(0)
    
    def _close_enter(self):
        self.big_step.outputEvent(Event("close_socket", "socket_out", [self.socket]))
        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("close_socket", None, [self.association_name])]))
    
    def _init_0_exec(self, parameters):
        association_name = parameters[0]
        self.association_name = association_name
    
    def _connected_listening_listen_0_exec(self, parameters):
        socket = parameters[0]
        data = parameters[1]
        self.received_data += data
        self.raiseInternalEvent(Event("received_data", None, []))
    
    def _connected_listening_listen_0_guard(self, parameters):
        socket = parameters[0]
        data = parameters[1]
        return (self.socket == socket) and (len(data) > 0)
    
    def _connected_listening_listen_1_exec(self, parameters):
        socket = parameters[0]
        data = parameters[1]
        self.raiseInternalEvent(Event("received_data", None, []))
    
    def _connected_listening_listen_1_guard(self, parameters):
        socket = parameters[0]
        data = parameters[1]
        return (self.socket == socket) and (len(data) == 0)
    
    def _connected_sending_waiting_for_data_0_exec(self, parameters):
        self.big_step.outputEvent(Event("send_socket", "socket_out", [self.socket, self.send_data]))
    
    def _connected_sending_waiting_for_data_0_guard(self, parameters):
        return len(self.send_data) > 0
    
    def _connected_sending_transferring_0_exec(self, parameters):
        socket = parameters[0]
        sent_bytes = parameters[1]
        self.send_data = self.send_data[sent_bytes:]
    
    def _connected_sending_transferring_0_guard(self, parameters):
        socket = parameters[0]
        sent_bytes = parameters[1]
        return self.socket == socket
    
    def _connected_queueing_queueing_0_exec(self, parameters):
        data = parameters[0]
        #post_data = "&".join(["%s=%s" % (urllib.quote(k), urllib.quote(v)) for k, v in data.iteritems()])
        #post_data = "&".join(["%s=%s" % (k, v) for k, v in data.iteritems()])
        post_data = data
        self.send_data += "HTTP/1.0 200 OK\r\n"
        self.send_data += "Content-Length: %s\r\n" % len(post_data)
        self.send_data += "Content-Type: %s; charset=UTF-8\r\n" % "text/plain"
        self.send_data += "\r\n"
        self.send_data += str(post_data)
    
    def _connected_parsing_wait_for_header_0_exec(self, parameters):
        header, self.received_data = self.received_data.split("\r\n\r\n", 1)
        header = header.lower()
        if "content-length" in header:
            _, after = header.split("content-length:", 1)
            after = after.split("\r\n", 1)[0]
            after = after.strip()
            self.length = int(after)
        else:
            self.length = float('inf')
    
    def _connected_parsing_wait_for_header_0_guard(self, parameters):
        return '\r\n\r\n' in self.received_data and self.received_data.startswith('POST')
    
    def _connected_parsing_wait_for_header_1_guard(self, parameters):
        return self.closed and len(self.received_data) == 0
    
    def _connected_parsing_closing_0_exec(self, parameters):
        self.raiseInternalEvent(Event("close", None, []))
    
    def _connected_parsing_wait_for_payload_0_exec(self, parameters):
        if self.length == float('inf'):
            data = self.received_data
            self.received_data = ""
        else:
            data = self.received_data[:self.length]
            self.received_data = self.received_data[self.length:]
        
        print("Got data: " + str(data))
        
        # We support POST data only, so everything is in the data
        #try:
        #    params = dict([p.split('=') for p in data.split('&')])
        #    data = {k: urllib.unquote_plus(v) for k, v in params.iteritems()}
        #except:
        #    data = {}
        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("HTTP_output", None, [self.association_name, data])]))
    
    def _connected_parsing_wait_for_payload_0_guard(self, parameters):
        return len(self.received_data) >= self.length or self.closed
    
    def initializeStatechart(self):
        # enter default state
        self.default_targets = self.states["/init"].getEffectiveTargetStates()
        RuntimeClassBase.initializeStatechart(self)

class ObjectManager(ObjectManagerBase):
    def __init__(self, controller):
        ObjectManagerBase.__init__(self, controller)
    
    def instantiate(self, class_name, construct_params):
        if class_name == "Echo":
            instance = Echo(self.controller, construct_params[0])
            instance.associations = {}
            instance.associations["to_server"] = Association("Server", 1, 1)
        elif class_name == "Server":
            instance = Server(self.controller, construct_params[0], construct_params[1])
            instance.associations = {}
            instance.associations["sockets"] = Association("Socket", 0, -1)
            instance.associations["parent"] = Association("Echo", 1, 1)
        elif class_name == "Socket":
            instance = Socket(self.controller, construct_params[0])
            instance.associations = {}
            instance.associations["parent"] = Association("Server", 1, 1)
        else:
            raise Exception("Cannot instantiate class " + class_name)
        return instance

class Controller(ThreadsControllerBase):
    def __init__(self, params, keep_running = None, behind_schedule_callback = None):
        if keep_running == None: keep_running = True
        if behind_schedule_callback == None: behind_schedule_callback = None
        ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running, behind_schedule_callback)
        self.addInputPort("socket_in")
        self.addOutputPort("socket_out")
        self.object_manager.createInstance("Echo", [params])