"""
Generated by Statechart compiler by Glenn De Jonghe and Joeri Exelmans

Date:   Wed Jul 27 14:38:22 2016

Model author: Yentl Van Tendeloo
Model name:   MvK Server
Model description:
Modelverse Kernel server. Server for the MvI, client of the MvS.
"""

from python_runtime.statecharts_core import *
import time
import os
import urllib
import sys
import json

import sys
from collections import defaultdict
sys.path.append("../kernel/")
sys.path.append("../state/")
from modelverse_kernel.main import ModelverseKernel
from modelverse_state.main import ModelverseState

# package "MvK Server"

class MvKController(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
		
		# Call user defined constructor
		MvKController.user_defined_constructor(self, params)
	
	def user_defined_constructor(self, params):
		self.mvs = ModelverseState("../bootstrap/bootstrap.m")
		self.root = self.mvs.read_root()[0]
		self.mvk = ModelverseKernel(self.root)
		self.all_failed = False
		self.timeout = False
		
		self.users = set()
		self.input_queue = defaultdict(list)
		self.output_queue = defaultdict(list)
		self.source = None
		
		self.mvs_operations = {
		        "CN": self.mvs.create_node,
		        "CE": self.mvs.create_edge,
		        "CNV": self.mvs.create_nodevalue,
		        "CD": self.mvs.create_dict,
		
		        "RV": self.mvs.read_value,
		        "RO": self.mvs.read_outgoing,
		        "RI": self.mvs.read_incoming,
		        "RE": self.mvs.read_edge,
		        "RD": self.mvs.read_dict,
		        "RDN": self.mvs.read_dict_node,
		        "RDNE": self.mvs.read_dict_node_edge,
		        "RDE": self.mvs.read_dict_edge,
		        "RRD": self.mvs.read_reverse_dict,
		        "RR": self.mvs.read_root,
		        "RDK": self.mvs.read_dict_keys,
		
		        "DE": self.mvs.delete_edge,
		        "DN": self.mvs.delete_node,
		    }
		
		self.execute_modelverse("", "load_primitives", [])
	
	def user_defined_destructor(self):
		pass
	
	
	# User defined method
	def execute_modelverse(self, username, operation, params):
		reply = None
		commands = []
		while 1:
		    commands = self.mvk.execute_yields(username, operation, params, reply)
		    if commands is None:
		        break
		    reply = [self.mvs_operations[command[0]](*(command[1]))[0] for command in commands]
		    if len(reply) == 1:
		        reply = reply[0]
	
	def initializeStatechart(self):
		self.current_state[self.Root] = []
		self.current_state[self.Root_running] = []
		self.current_state[self.Root_running_wait_for_requests] = []
		self.current_state[self.Root_running_execution] = []
		self.current_state[self.Root_running_remove_sockets] = []
		
		# Enter default state
		self.enter_Root_init_server()
	
	# Unique IDs for all statechart nodes
	Root = 0
	Root_running = 1
	Root_running_wait_for_requests = 2
	Root_running_execution = 3
	Root_running_remove_sockets = 4
	Root_init_server = 5
	Root_running_wait_for_requests_wait = 6
	Root_running_execution_execution = 7
	Root_running_remove_sockets_remove_sockets = 8
	
	# Statechart enter/exit action method(s)
	
	def enter_Root_running(self):
		self.current_state[self.Root].append(self.Root_running)
	
	def exit_Root_running(self):
		self.exit_Root_running_wait_for_requests()
		self.exit_Root_running_execution()
		self.exit_Root_running_remove_sockets()
		self.current_state[self.Root] = []
	
	def enter_Root_running_wait_for_requests(self):
		self.current_state[self.Root_running].append(self.Root_running_wait_for_requests)
	
	def exit_Root_running_wait_for_requests(self):
		if self.Root_running_wait_for_requests_wait in self.current_state[self.Root_running_wait_for_requests]:
			self.exit_Root_running_wait_for_requests_wait()
		self.current_state[self.Root_running] = []
	
	def enter_Root_running_execution(self):
		self.current_state[self.Root_running].append(self.Root_running_execution)
	
	def exit_Root_running_execution(self):
		if self.Root_running_execution_execution in self.current_state[self.Root_running_execution]:
			self.exit_Root_running_execution_execution()
		self.current_state[self.Root_running] = []
	
	def enter_Root_running_remove_sockets(self):
		self.current_state[self.Root_running].append(self.Root_running_remove_sockets)
	
	def exit_Root_running_remove_sockets(self):
		if self.Root_running_remove_sockets_remove_sockets in self.current_state[self.Root_running_remove_sockets]:
			self.exit_Root_running_remove_sockets_remove_sockets()
		self.current_state[self.Root_running] = []
	
	def enter_Root_init_server(self):
		self.big_step.outputEventOM(Event("create_instance", None, [self, 'to_mvi', 'Server', '', 8001]))
		self.current_state[self.Root].append(self.Root_init_server)
	
	def exit_Root_init_server(self):
		self.current_state[self.Root] = []
	
	def enter_Root_running_wait_for_requests_wait(self):
		self.current_state[self.Root_running_wait_for_requests].append(self.Root_running_wait_for_requests_wait)
	
	def exit_Root_running_wait_for_requests_wait(self):
		self.current_state[self.Root_running_wait_for_requests] = []
	
	def enter_Root_running_execution_execution(self):
		self.timers[0] = 0
		self.timers[1] = 0.1
		self.timers[2] = 0
		self.timeout = False
		self.destination = None
		if self.users:
		    user = self.users.pop()
		
		    # Check if there are values to input
		    if self.input_queue[user]:
		        source, args = self.input_queue[user].pop(0)
		        for args_entry in args:
		            self.execute_modelverse(user, "set_input", args_entry)
		
		        self.destination = source
		        self.value = {"id": 200, "value": "OK"}
		        self.all_failed = False
		
		    # Now process for some steps, or until we are again blocked for input
		    for x in xrange(200):
		        self.execute_modelverse(user, "execute_rule", [])
		
		        if not self.mvk.success:
		            # Blocking or broken, so quit already to stop wasting CPU
		            break
		
		        self.all_failed = False
		
		    # Check that we don't have anything to output yet, otherwise we wait
		    if self.destination is None:
		        # Perform output if there is anything
		        if self.output_queue[user]:
		            self.execute_modelverse(user, "get_output", [])
		            if self.mvk.success:
		                self.destination = self.output_queue[user].pop(0)
		                self.value = self.mvk.returnvalue
		                self.all_failed = False
		else:
		    out = self.mvs.read_outgoing(self.root)[0]
		    for m in out:
		        src, user = self.mvs.read_edge(m)[0]
		        outgoing = self.mvs.read_outgoing(m)[0]
		        first = self.mvs.read_edge(outgoing[0])[0]
		        dest = first[1]
		        name = self.mvs.read_value(dest)[0]
		        if name.startswith("__"):
		            continue
		        self.users.add(name)
		    self.timeout = self.all_failed
		    self.all_failed = True
		self.current_state[self.Root_running_execution].append(self.Root_running_execution_execution)
	
	def exit_Root_running_execution_execution(self):
		self.timers.pop(0, None)
		self.timers.pop(1, None)
		self.timers.pop(2, None)
		self.current_state[self.Root_running_execution] = []
	
	def enter_Root_running_remove_sockets_remove_sockets(self):
		self.current_state[self.Root_running_remove_sockets].append(self.Root_running_remove_sockets_remove_sockets)
	
	def exit_Root_running_remove_sockets_remove_sockets(self):
		self.current_state[self.Root_running_remove_sockets] = []
	
	# Statechart enter/exit default method(s)
	
	def enterDefault_Root_running(self):
		self.enter_Root_running()
		self.enterDefault_Root_running_wait_for_requests()
		self.enterDefault_Root_running_execution()
		self.enterDefault_Root_running_remove_sockets()
	
	def enterDefault_Root_running_wait_for_requests(self):
		self.enter_Root_running_wait_for_requests()
		self.enter_Root_running_wait_for_requests_wait()
	
	def enterDefault_Root_running_execution(self):
		self.enter_Root_running_execution()
		self.enter_Root_running_execution_execution()
	
	def enterDefault_Root_running_remove_sockets(self):
		self.enter_Root_running_remove_sockets()
		self.enter_Root_running_remove_sockets_remove_sockets()
	
	# Statechart transitions
	
	def generateCandidatesChildren_Root(self):
		if self.current_state[self.Root][0] == self.Root_init_server:
			return self.generateCandidates_Root_init_server()
		elif self.current_state[self.Root][0] == self.Root_running:
			return self.generateCandidates_Root_running()
		return False
	
	def generateCandidates_Root(self):
		if not self.combo_step.isArenaChanged(self.Root):
			return self.generateCandidatesChildren_Root()
		else:
			return True
	
	def generateCandidatesCurrent_Root_init_server(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "instance_created":
				self.small_step.addCandidate(self.transition_Root_init_server_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_init_server(self):
		if not self.combo_step.isArenaChanged(self.Root_init_server):
			return self.generateCandidatesCurrent_Root_init_server()
		else:
			return True
	
	def transition_Root_init_server_1(self, parameters):
		instancename = parameters[0]
		self.exit_Root_init_server()
		self.big_step.outputEventOM(Event("start_instance", None, [self, instancename]))
		self.combo_step.setArenaChanged(self.Root)
		self.enterDefault_Root_running()
	
	def generateCandidatesChildren_Root_running(self):
		branch_done = False
		branch_done = (self.generateCandidates_Root_running_wait_for_requests() or branch_done)
		branch_done = (self.generateCandidates_Root_running_execution() or branch_done)
		branch_done = (self.generateCandidates_Root_running_remove_sockets() or branch_done)
		return branch_done
	
	def generateCandidates_Root_running(self):
		if not self.combo_step.isArenaChanged(self.Root_running):
			return self.generateCandidatesChildren_Root_running()
		else:
			return True
	
	def generateCandidatesChildren_Root_running_wait_for_requests(self):
		if self.current_state[self.Root_running_wait_for_requests][0] == self.Root_running_wait_for_requests_wait:
			return self.generateCandidates_Root_running_wait_for_requests_wait()
		return False
	
	def generateCandidates_Root_running_wait_for_requests(self):
		if not self.combo_step.isArenaChanged(self.Root_running_wait_for_requests):
			return self.generateCandidatesChildren_Root_running_wait_for_requests()
		else:
			return True
	
	def generateCandidatesCurrent_Root_running_wait_for_requests_wait(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "from_mvi":
				self.small_step.addCandidate(self.transition_Root_running_wait_for_requests_wait_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_running_wait_for_requests_wait(self):
		if not self.combo_step.isArenaChanged(self.Root_running_wait_for_requests_wait):
			return self.generateCandidatesCurrent_Root_running_wait_for_requests_wait()
		else:
			return True
	
	def transition_Root_running_wait_for_requests_wait_1(self, parameters):
		source = parameters[0]
		data = parameters[1]
		self.exit_Root_running_wait_for_requests_wait()
		# No JSON encoding necessary, as it is not complex
		try:
		    if data["op"] == "set_input":
		        if "element_type" in data:
		            if data["element_type"] == "V":
		                value = json.loads(data["value"])
		            else:
		                value = data["value"]
		            args = [data["element_type"], value]
		            self.input_queue[data["username"]].append((source, [args]))
		        else:
		            d = []
		            for t, v in json.loads(data["data"]):
		                if t == "V":
		                    v = json.loads(v)
		                d.append([t, v])
		            self.input_queue[data["username"]].append((source, d))
		    elif data["op"] == "get_output":
		        self.output_queue[data["username"]].append(source)
		    else:
		        print("DROPPING unknown operation: " + str(data["op"]))
		except:
		    print("DROPPING deserialization error")
		self.combo_step.setArenaChanged(self.Root_running_wait_for_requests)
		self.enter_Root_running_wait_for_requests_wait()
	
	def generateCandidatesChildren_Root_running_execution(self):
		if self.current_state[self.Root_running_execution][0] == self.Root_running_execution_execution:
			return self.generateCandidates_Root_running_execution_execution()
		return False
	
	def generateCandidates_Root_running_execution(self):
		if not self.combo_step.isArenaChanged(self.Root_running_execution):
			return self.generateCandidatesChildren_Root_running_execution()
		else:
			return True
	
	def generateCandidatesCurrent_Root_running_execution_execution(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "_0after":
				parameters = e.parameters
				if self.destination is not None:
					self.small_step.addCandidate(self.transition_Root_running_execution_execution_1, e.parameters)
					return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "_1after":
				parameters = e.parameters
				if self.timeout and self.destination is None:
					self.small_step.addCandidate(self.transition_Root_running_execution_execution_2, e.parameters)
					return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "_2after":
				parameters = e.parameters
				if not self.timeout and self.destination is None:
					self.small_step.addCandidate(self.transition_Root_running_execution_execution_3, e.parameters)
					return True
		return False
	
	def generateCandidates_Root_running_execution_execution(self):
		if not self.combo_step.isArenaChanged(self.Root_running_execution_execution):
			return self.generateCandidatesCurrent_Root_running_execution_execution()
		else:
			return True
	
	def transition_Root_running_execution_execution_1(self, parameters):
		self.exit_Root_running_execution_execution()
		self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'to_mvi/%s' % self.destination, Event("HTTP_input", None, [self.value])]))
		self.combo_step.setArenaChanged(self.Root_running_execution)
		self.enter_Root_running_execution_execution()
	
	def transition_Root_running_execution_execution_2(self, parameters):
		self.exit_Root_running_execution_execution()
		self.combo_step.setArenaChanged(self.Root_running_execution)
		self.enter_Root_running_execution_execution()
	
	def transition_Root_running_execution_execution_3(self, parameters):
		self.exit_Root_running_execution_execution()
		self.combo_step.setArenaChanged(self.Root_running_execution)
		self.enter_Root_running_execution_execution()
	
	def generateCandidatesChildren_Root_running_remove_sockets(self):
		if self.current_state[self.Root_running_remove_sockets][0] == self.Root_running_remove_sockets_remove_sockets:
			return self.generateCandidates_Root_running_remove_sockets_remove_sockets()
		return False
	
	def generateCandidates_Root_running_remove_sockets(self):
		if not self.combo_step.isArenaChanged(self.Root_running_remove_sockets):
			return self.generateCandidatesChildren_Root_running_remove_sockets()
		else:
			return True
	
	def generateCandidatesCurrent_Root_running_remove_sockets_remove_sockets(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "delete_socket":
				self.small_step.addCandidate(self.transition_Root_running_remove_sockets_remove_sockets_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_running_remove_sockets_remove_sockets(self):
		if not self.combo_step.isArenaChanged(self.Root_running_remove_sockets_remove_sockets):
			return self.generateCandidatesCurrent_Root_running_remove_sockets_remove_sockets()
		else:
			return True
	
	def transition_Root_running_remove_sockets_remove_sockets_1(self, parameters):
		socket = parameters[0]
		self.exit_Root_running_remove_sockets_remove_sockets()
		for user in self.output_queue.keys():
		    self.output_queue[user] = [s for s in self.output_queue[user] if s != socket]
		self.combo_step.setArenaChanged(self.Root_running_remove_sockets)
		self.enter_Root_running_remove_sockets_remove_sockets()
	
	# Generate transition candidates for current small step
	def generateCandidates(self):
		self.generateCandidates_Root()

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
		
		# 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
	
	def initializeStatechart(self):
		self.current_state[self.Root] = []
		self.current_state[self.Root_main] = []
		self.current_state[self.Root_main_forward] = []
		self.current_state[self.Root_main_server] = []
		self.current_state[self.Root_main_close_socket] = []
		
		# Enter default state
		self.enterDefault_Root_main()
	
	# Unique IDs for all statechart nodes
	Root = 0
	Root_main = 1
	Root_main_forward = 2
	Root_main_server = 3
	Root_main_close_socket = 4
	Root_main_forward_forward = 5
	Root_main_server_init = 6
	Root_main_server_binding = 7
	Root_main_server_listening = 8
	Root_main_server_accepting = 9
	Root_main_close_socket_close = 10
	
	# Statechart enter/exit action method(s)
	
	def enter_Root_main(self):
		self.current_state[self.Root].append(self.Root_main)
	
	def exit_Root_main(self):
		self.exit_Root_main_forward()
		self.exit_Root_main_server()
		self.exit_Root_main_close_socket()
		self.current_state[self.Root] = []
	
	def enter_Root_main_forward(self):
		self.current_state[self.Root_main].append(self.Root_main_forward)
	
	def exit_Root_main_forward(self):
		if self.Root_main_forward_forward in self.current_state[self.Root_main_forward]:
			self.exit_Root_main_forward_forward()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_server(self):
		self.current_state[self.Root_main].append(self.Root_main_server)
	
	def exit_Root_main_server(self):
		if self.Root_main_server_init in self.current_state[self.Root_main_server]:
			self.exit_Root_main_server_init()
		if self.Root_main_server_binding in self.current_state[self.Root_main_server]:
			self.exit_Root_main_server_binding()
		if self.Root_main_server_listening in self.current_state[self.Root_main_server]:
			self.exit_Root_main_server_listening()
		if self.Root_main_server_accepting in self.current_state[self.Root_main_server]:
			self.exit_Root_main_server_accepting()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_close_socket(self):
		self.current_state[self.Root_main].append(self.Root_main_close_socket)
	
	def exit_Root_main_close_socket(self):
		if self.Root_main_close_socket_close in self.current_state[self.Root_main_close_socket]:
			self.exit_Root_main_close_socket_close()
		self.current_state[self.Root_main] = []
	
	def enter_Root_main_forward_forward(self):
		self.current_state[self.Root_main_forward].append(self.Root_main_forward_forward)
	
	def exit_Root_main_forward_forward(self):
		self.current_state[self.Root_main_forward] = []
	
	def enter_Root_main_server_init(self):
		self.big_step.outputEvent(Event("create_socket", "socket_out", []))
		self.current_state[self.Root_main_server].append(self.Root_main_server_init)
	
	def exit_Root_main_server_init(self):
		self.current_state[self.Root_main_server] = []
	
	def enter_Root_main_server_binding(self):
		self.big_step.outputEvent(Event("bind_socket", "socket_out", [self.socket, (self.address, self.port)]))
		self.current_state[self.Root_main_server].append(self.Root_main_server_binding)
	
	def exit_Root_main_server_binding(self):
		self.current_state[self.Root_main_server] = []
	
	def enter_Root_main_server_listening(self):
		self.big_step.outputEvent(Event("listen_socket", "socket_out", [self.socket]))
		self.current_state[self.Root_main_server].append(self.Root_main_server_listening)
	
	def exit_Root_main_server_listening(self):
		self.current_state[self.Root_main_server] = []
	
	def enter_Root_main_server_accepting(self):
		self.timers[0] = 1.0
		self.current_state[self.Root_main_server].append(self.Root_main_server_accepting)
	
	def exit_Root_main_server_accepting(self):
		self.timers.pop(0, None)
		self.current_state[self.Root_main_server] = []
	
	def enter_Root_main_close_socket_close(self):
		self.current_state[self.Root_main_close_socket].append(self.Root_main_close_socket_close)
	
	def exit_Root_main_close_socket_close(self):
		self.current_state[self.Root_main_close_socket] = []
	
	# Statechart enter/exit default method(s)
	
	def enterDefault_Root_main(self):
		self.enter_Root_main()
		self.enterDefault_Root_main_forward()
		self.enterDefault_Root_main_server()
		self.enterDefault_Root_main_close_socket()
	
	def enterDefault_Root_main_forward(self):
		self.enter_Root_main_forward()
		self.enter_Root_main_forward_forward()
	
	def enterDefault_Root_main_server(self):
		self.enter_Root_main_server()
		self.enter_Root_main_server_init()
	
	def enterDefault_Root_main_close_socket(self):
		self.enter_Root_main_close_socket()
		self.enter_Root_main_close_socket_close()
	
	# Statechart transitions
	
	def generateCandidatesChildren_Root(self):
		if self.current_state[self.Root][0] == self.Root_main:
			return self.generateCandidates_Root_main()
		return False
	
	def generateCandidates_Root(self):
		if not self.combo_step.isArenaChanged(self.Root):
			return self.generateCandidatesChildren_Root()
		else:
			return True
	
	def generateCandidatesChildren_Root_main(self):
		branch_done = False
		branch_done = (self.generateCandidates_Root_main_forward() or branch_done)
		branch_done = (self.generateCandidates_Root_main_server() or branch_done)
		branch_done = (self.generateCandidates_Root_main_close_socket() or branch_done)
		return branch_done
	
	def generateCandidates_Root_main(self):
		if not self.combo_step.isArenaChanged(self.Root_main):
			return self.generateCandidatesChildren_Root_main()
		else:
			return True
	
	def generateCandidatesChildren_Root_main_forward(self):
		if self.current_state[self.Root_main_forward][0] == self.Root_main_forward_forward:
			return self.generateCandidates_Root_main_forward_forward()
		return False
	
	def generateCandidates_Root_main_forward(self):
		if not self.combo_step.isArenaChanged(self.Root_main_forward):
			return self.generateCandidatesChildren_Root_main_forward()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_forward_forward(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "HTTP_output":
				self.small_step.addCandidate(self.transition_Root_main_forward_forward_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_forward_forward(self):
		if not self.combo_step.isArenaChanged(self.Root_main_forward_forward):
			return self.generateCandidatesCurrent_Root_main_forward_forward()
		else:
			return True
	
	def transition_Root_main_forward_forward_1(self, parameters):
		association_name = parameters[0]
		data = parameters[1]
		self.exit_Root_main_forward_forward()
		self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("from_mvi", None, [association_name, data])]))
		self.combo_step.setArenaChanged(self.Root_main_forward)
		self.enter_Root_main_forward_forward()
	
	def generateCandidatesChildren_Root_main_server(self):
		if self.current_state[self.Root_main_server][0] == self.Root_main_server_init:
			return self.generateCandidates_Root_main_server_init()
		elif self.current_state[self.Root_main_server][0] == self.Root_main_server_binding:
			return self.generateCandidates_Root_main_server_binding()
		elif self.current_state[self.Root_main_server][0] == self.Root_main_server_listening:
			return self.generateCandidates_Root_main_server_listening()
		elif self.current_state[self.Root_main_server][0] == self.Root_main_server_accepting:
			return self.generateCandidates_Root_main_server_accepting()
		return False
	
	def generateCandidates_Root_main_server(self):
		if not self.combo_step.isArenaChanged(self.Root_main_server):
			return self.generateCandidatesChildren_Root_main_server()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_server_init(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "created_socket") and (e.port == "socket_in"):
				self.small_step.addCandidate(self.transition_Root_main_server_init_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_server_init(self):
		if not self.combo_step.isArenaChanged(self.Root_main_server_init):
			return self.generateCandidatesCurrent_Root_main_server_init()
		else:
			return True
	
	def transition_Root_main_server_init_1(self, parameters):
		socket = parameters[0]
		self.exit_Root_main_server_init()
		self.socket = socket
		self.combo_step.setArenaChanged(self.Root_main_server)
		self.enter_Root_main_server_binding()
	
	def generateCandidatesCurrent_Root_main_server_binding(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "bound_socket") and (e.port == "socket_in"):
				parameters = e.parameters
				socket = parameters[0]
				if self.socket == socket:
					self.small_step.addCandidate(self.transition_Root_main_server_binding_1, e.parameters)
					return True
		return False
	
	def generateCandidates_Root_main_server_binding(self):
		if not self.combo_step.isArenaChanged(self.Root_main_server_binding):
			return self.generateCandidatesCurrent_Root_main_server_binding()
		else:
			return True
	
	def transition_Root_main_server_binding_1(self, parameters):
		socket = parameters[0]
		self.exit_Root_main_server_binding()
		self.combo_step.setArenaChanged(self.Root_main_server)
		self.enter_Root_main_server_listening()
	
	def generateCandidatesCurrent_Root_main_server_listening(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "listened_socket") and (e.port == "socket_in"):
				parameters = e.parameters
				socket = parameters[0]
				if self.socket == socket:
					self.small_step.addCandidate(self.transition_Root_main_server_listening_1, e.parameters)
					return True
		return False
	
	def generateCandidates_Root_main_server_listening(self):
		if not self.combo_step.isArenaChanged(self.Root_main_server_listening):
			return self.generateCandidatesCurrent_Root_main_server_listening()
		else:
			return True
	
	def transition_Root_main_server_listening_1(self, parameters):
		socket = parameters[0]
		self.exit_Root_main_server_listening()
		self.big_step.outputEvent(Event("accept_socket", "socket_out", [self.socket]))
		self.combo_step.setArenaChanged(self.Root_main_server)
		self.enter_Root_main_server_accepting()
	
	def generateCandidatesCurrent_Root_main_server_accepting(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "accepted_socket") and (e.port == "socket_in"):
				self.small_step.addCandidate(self.transition_Root_main_server_accepting_1, e.parameters)
				return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "instance_created":
				self.small_step.addCandidate(self.transition_Root_main_server_accepting_2, e.parameters)
				return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "_0after":
				self.small_step.addCandidate(self.transition_Root_main_server_accepting_3, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_server_accepting(self):
		if not self.combo_step.isArenaChanged(self.Root_main_server_accepting):
			return self.generateCandidatesCurrent_Root_main_server_accepting()
		else:
			return True
	
	def transition_Root_main_server_accepting_1(self, parameters):
		socket = parameters[0]
		connected_socket = parameters[1]
		self.exit_Root_main_server_accepting()
		self.big_step.outputEventOM(Event("create_instance", None, [self, 'sockets', 'Socket', connected_socket]))
		self.big_step.outputEvent(Event("accept_socket", "socket_out", [self.socket]))
		self.combo_step.setArenaChanged(self.Root_main_server)
		self.enter_Root_main_server_accepting()
	
	def transition_Root_main_server_accepting_2(self, parameters):
		instancename = parameters[0]
		self.exit_Root_main_server_accepting()
		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])]))
		self.combo_step.setArenaChanged(self.Root_main_server)
		self.enter_Root_main_server_accepting()
	
	def transition_Root_main_server_accepting_3(self, parameters):
		self.exit_Root_main_server_accepting()
		self.combo_step.setArenaChanged(self.Root_main_server)
		self.enter_Root_main_server_accepting()
	
	def generateCandidatesChildren_Root_main_close_socket(self):
		if self.current_state[self.Root_main_close_socket][0] == self.Root_main_close_socket_close:
			return self.generateCandidates_Root_main_close_socket_close()
		return False
	
	def generateCandidates_Root_main_close_socket(self):
		if not self.combo_step.isArenaChanged(self.Root_main_close_socket):
			return self.generateCandidatesChildren_Root_main_close_socket()
		else:
			return True
	
	def generateCandidatesCurrent_Root_main_close_socket_close(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "close_socket":
				self.small_step.addCandidate(self.transition_Root_main_close_socket_close_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_main_close_socket_close(self):
		if not self.combo_step.isArenaChanged(self.Root_main_close_socket_close):
			return self.generateCandidatesCurrent_Root_main_close_socket_close()
		else:
			return True
	
	def transition_Root_main_close_socket_close_1(self, parameters):
		association_name = parameters[0]
		self.exit_Root_main_close_socket_close()
		self.big_step.outputEventOM(Event("delete_instance", None, [self, association_name]))
		self.big_step.outputEventOM(Event("broad_cast", None, [Event("delete_socket", None, [association_name])]))
		self.combo_step.setArenaChanged(self.Root_main_close_socket)
		self.enter_Root_main_close_socket_close()
	
	# Generate transition candidates for current small step
	def generateCandidates(self):
		self.generateCandidates_Root()

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
		
		# 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
	
	def initializeStatechart(self):
		self.current_state[self.Root] = []
		self.current_state[self.Root_connected] = []
		self.current_state[self.Root_connected_listening] = []
		self.current_state[self.Root_connected_sending] = []
		self.current_state[self.Root_connected_queueing] = []
		self.current_state[self.Root_connected_parsing] = []
		
		# Enter default state
		self.enter_Root_init()
	
	# Unique IDs for all statechart nodes
	Root = 0
	Root_connected = 1
	Root_connected_listening = 2
	Root_connected_sending = 3
	Root_connected_queueing = 4
	Root_connected_parsing = 5
	Root_init = 6
	Root_connected_listening_listen = 7
	Root_connected_listening_closed = 8
	Root_connected_sending_waiting_for_data = 9
	Root_connected_sending_transferring = 10
	Root_connected_queueing_queueing = 11
	Root_connected_parsing_wait_for_header = 12
	Root_connected_parsing_closing = 13
	Root_connected_parsing_wait_for_payload = 14
	Root_close = 15
	
	# Statechart enter/exit action method(s)
	
	def enter_Root_connected(self):
		self.current_state[self.Root].append(self.Root_connected)
	
	def exit_Root_connected(self):
		self.exit_Root_connected_listening()
		self.exit_Root_connected_sending()
		self.exit_Root_connected_queueing()
		self.exit_Root_connected_parsing()
		self.current_state[self.Root] = []
	
	def enter_Root_connected_listening(self):
		self.current_state[self.Root_connected].append(self.Root_connected_listening)
	
	def exit_Root_connected_listening(self):
		if self.Root_connected_listening_listen in self.current_state[self.Root_connected_listening]:
			self.exit_Root_connected_listening_listen()
		if self.Root_connected_listening_closed in self.current_state[self.Root_connected_listening]:
			self.exit_Root_connected_listening_closed()
		self.current_state[self.Root_connected] = []
	
	def enter_Root_connected_sending(self):
		self.current_state[self.Root_connected].append(self.Root_connected_sending)
	
	def exit_Root_connected_sending(self):
		if self.Root_connected_sending_waiting_for_data in self.current_state[self.Root_connected_sending]:
			self.exit_Root_connected_sending_waiting_for_data()
		if self.Root_connected_sending_transferring in self.current_state[self.Root_connected_sending]:
			self.exit_Root_connected_sending_transferring()
		self.current_state[self.Root_connected] = []
	
	def enter_Root_connected_queueing(self):
		self.current_state[self.Root_connected].append(self.Root_connected_queueing)
	
	def exit_Root_connected_queueing(self):
		if self.Root_connected_queueing_queueing in self.current_state[self.Root_connected_queueing]:
			self.exit_Root_connected_queueing_queueing()
		self.current_state[self.Root_connected] = []
	
	def enter_Root_connected_parsing(self):
		self.current_state[self.Root_connected].append(self.Root_connected_parsing)
	
	def exit_Root_connected_parsing(self):
		if self.Root_connected_parsing_wait_for_header in self.current_state[self.Root_connected_parsing]:
			self.exit_Root_connected_parsing_wait_for_header()
		if self.Root_connected_parsing_closing in self.current_state[self.Root_connected_parsing]:
			self.exit_Root_connected_parsing_closing()
		if self.Root_connected_parsing_wait_for_payload in self.current_state[self.Root_connected_parsing]:
			self.exit_Root_connected_parsing_wait_for_payload()
		self.current_state[self.Root_connected] = []
	
	def enter_Root_init(self):
		self.current_state[self.Root].append(self.Root_init)
	
	def exit_Root_init(self):
		self.current_state[self.Root] = []
	
	def enter_Root_connected_listening_listen(self):
		self.big_step.outputEvent(Event("recv_socket", "socket_out", [self.socket]))
		self.current_state[self.Root_connected_listening].append(self.Root_connected_listening_listen)
	
	def exit_Root_connected_listening_listen(self):
		self.current_state[self.Root_connected_listening] = []
	
	def enter_Root_connected_listening_closed(self):
		self.closed = True
		self.current_state[self.Root_connected_listening].append(self.Root_connected_listening_closed)
	
	def exit_Root_connected_listening_closed(self):
		self.current_state[self.Root_connected_listening] = []
	
	def enter_Root_connected_sending_waiting_for_data(self):
		self.current_state[self.Root_connected_sending].append(self.Root_connected_sending_waiting_for_data)
	
	def exit_Root_connected_sending_waiting_for_data(self):
		self.current_state[self.Root_connected_sending] = []
	
	def enter_Root_connected_sending_transferring(self):
		self.current_state[self.Root_connected_sending].append(self.Root_connected_sending_transferring)
	
	def exit_Root_connected_sending_transferring(self):
		self.current_state[self.Root_connected_sending] = []
	
	def enter_Root_connected_queueing_queueing(self):
		self.current_state[self.Root_connected_queueing].append(self.Root_connected_queueing_queueing)
	
	def exit_Root_connected_queueing_queueing(self):
		self.current_state[self.Root_connected_queueing] = []
	
	def enter_Root_connected_parsing_wait_for_header(self):
		self.current_state[self.Root_connected_parsing].append(self.Root_connected_parsing_wait_for_header)
	
	def exit_Root_connected_parsing_wait_for_header(self):
		self.current_state[self.Root_connected_parsing] = []
	
	def enter_Root_connected_parsing_closing(self):
		self.timers[0] = 0.0
		self.current_state[self.Root_connected_parsing].append(self.Root_connected_parsing_closing)
	
	def exit_Root_connected_parsing_closing(self):
		self.timers.pop(0, None)
		self.current_state[self.Root_connected_parsing] = []
	
	def enter_Root_connected_parsing_wait_for_payload(self):
		self.current_state[self.Root_connected_parsing].append(self.Root_connected_parsing_wait_for_payload)
	
	def exit_Root_connected_parsing_wait_for_payload(self):
		self.current_state[self.Root_connected_parsing] = []
	
	def enter_Root_close(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])]))
		self.current_state[self.Root].append(self.Root_close)
	
	def exit_Root_close(self):
		self.current_state[self.Root] = []
	
	# Statechart enter/exit default method(s)
	
	def enterDefault_Root_connected(self):
		self.enter_Root_connected()
		self.enterDefault_Root_connected_listening()
		self.enterDefault_Root_connected_sending()
		self.enterDefault_Root_connected_queueing()
		self.enterDefault_Root_connected_parsing()
	
	def enterDefault_Root_connected_listening(self):
		self.enter_Root_connected_listening()
		self.enter_Root_connected_listening_listen()
	
	def enterDefault_Root_connected_sending(self):
		self.enter_Root_connected_sending()
		self.enter_Root_connected_sending_waiting_for_data()
	
	def enterDefault_Root_connected_queueing(self):
		self.enter_Root_connected_queueing()
		self.enter_Root_connected_queueing_queueing()
	
	def enterDefault_Root_connected_parsing(self):
		self.enter_Root_connected_parsing()
		self.enter_Root_connected_parsing_wait_for_header()
	
	# Statechart transitions
	
	def generateCandidatesChildren_Root(self):
		if self.current_state[self.Root][0] == self.Root_init:
			return self.generateCandidates_Root_init()
		elif self.current_state[self.Root][0] == self.Root_connected:
			return self.generateCandidates_Root_connected()
		elif self.current_state[self.Root][0] == self.Root_close:
			return self.generateCandidates_Root_close()
		return False
	
	def generateCandidates_Root(self):
		if not self.combo_step.isArenaChanged(self.Root):
			return self.generateCandidatesChildren_Root()
		else:
			return True
	
	def generateCandidatesCurrent_Root_init(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "set_association_name":
				self.small_step.addCandidate(self.transition_Root_init_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_init(self):
		if not self.combo_step.isArenaChanged(self.Root_init):
			return self.generateCandidatesCurrent_Root_init()
		else:
			return True
	
	def transition_Root_init_1(self, parameters):
		association_name = parameters[0]
		self.exit_Root_init()
		self.association_name = association_name
		self.combo_step.setArenaChanged(self.Root)
		self.enterDefault_Root_connected()
	
	def generateCandidatesChildren_Root_connected(self):
		branch_done = False
		branch_done = (self.generateCandidates_Root_connected_listening() or branch_done)
		branch_done = (self.generateCandidates_Root_connected_sending() or branch_done)
		branch_done = (self.generateCandidates_Root_connected_queueing() or branch_done)
		branch_done = (self.generateCandidates_Root_connected_parsing() or branch_done)
		return branch_done
	
	def generateCandidatesCurrent_Root_connected(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "close":
				self.small_step.addCandidate(self.transition_Root_connected_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_connected(self):
		if not self.combo_step.isArenaChanged(self.Root_connected):
			branch_done = False
			if self.semantics.priority == StatechartSemantics.SourceParent:
				branch_done = self.generateCandidatesCurrent_Root_connected()
				if not branch_done:
					branch_done = self.generateCandidatesChildren_Root_connected()
			elif self.semantics.priority == StatechartSemantics.SourceChild:
				branch_done = self.generateCandidatesChildren_Root_connected()
				if not branch_done:
					branch_done = self.generateCandidatesCurrent_Root_connected()
			return branch_done
		else:
			return True
	
	def transition_Root_connected_1(self, parameters):
		self.exit_Root_connected()
		self.combo_step.setArenaChanged(self.Root)
		self.enter_Root_close()
	
	def generateCandidatesChildren_Root_connected_listening(self):
		if self.current_state[self.Root_connected_listening][0] == self.Root_connected_listening_listen:
			return self.generateCandidates_Root_connected_listening_listen()
		elif self.current_state[self.Root_connected_listening][0] == self.Root_connected_listening_closed:
			return self.generateCandidates_Root_connected_listening_closed()
		return False
	
	def generateCandidates_Root_connected_listening(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_listening):
			return self.generateCandidatesChildren_Root_connected_listening()
		else:
			return True
	
	def generateCandidatesCurrent_Root_connected_listening_listen(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "received_socket") and (e.port == "socket_in"):
				parameters = e.parameters
				socket = parameters[0]
				data = parameters[1]
				if (self.socket == socket) and (len(data) > 0):
					self.small_step.addCandidate(self.transition_Root_connected_listening_listen_1, e.parameters)
					return True
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "received_socket") and (e.port == "socket_in"):
				parameters = e.parameters
				socket = parameters[0]
				data = parameters[1]
				if (self.socket == socket) and (len(data) == 0):
					self.small_step.addCandidate(self.transition_Root_connected_listening_listen_2, e.parameters)
					return True
		return False
	
	def generateCandidates_Root_connected_listening_listen(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_listening_listen):
			return self.generateCandidatesCurrent_Root_connected_listening_listen()
		else:
			return True
	
	def transition_Root_connected_listening_listen_1(self, parameters):
		socket = parameters[0]
		data = parameters[1]
		self.exit_Root_connected_listening_listen()
		self.received_data += data
		self.raiseInternalEvent(Event("received_data", None, []))
		self.combo_step.setArenaChanged(self.Root_connected_listening)
		self.enter_Root_connected_listening_listen()
	
	def transition_Root_connected_listening_listen_2(self, parameters):
		socket = parameters[0]
		data = parameters[1]
		self.exit_Root_connected_listening_listen()
		self.raiseInternalEvent(Event("received_data", None, []))
		self.combo_step.setArenaChanged(self.Root_connected_listening)
		self.enter_Root_connected_listening_closed()
	
	def generateCandidates_Root_connected_listening_closed(self):
		return False
	
	def generateCandidatesChildren_Root_connected_sending(self):
		if self.current_state[self.Root_connected_sending][0] == self.Root_connected_sending_waiting_for_data:
			return self.generateCandidates_Root_connected_sending_waiting_for_data()
		elif self.current_state[self.Root_connected_sending][0] == self.Root_connected_sending_transferring:
			return self.generateCandidates_Root_connected_sending_transferring()
		return False
	
	def generateCandidates_Root_connected_sending(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_sending):
			return self.generateCandidatesChildren_Root_connected_sending()
		else:
			return True
	
	def generateCandidatesCurrent_Root_connected_sending_waiting_for_data(self):
		enabled_events = self.getEnabledEvents()
		if len(self.send_data) > 0:
			self.small_step.addCandidate(self.transition_Root_connected_sending_waiting_for_data_1, [])
			return True
		return False
	
	def generateCandidates_Root_connected_sending_waiting_for_data(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_sending_waiting_for_data):
			return self.generateCandidatesCurrent_Root_connected_sending_waiting_for_data()
		else:
			return True
	
	def transition_Root_connected_sending_waiting_for_data_1(self, parameters):
		self.exit_Root_connected_sending_waiting_for_data()
		self.big_step.outputEvent(Event("send_socket", "socket_out", [self.socket, self.send_data]))
		self.combo_step.setArenaChanged(self.Root_connected_sending)
		self.enter_Root_connected_sending_transferring()
	
	def generateCandidatesCurrent_Root_connected_sending_transferring(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if (e.name == "sent_socket") and (e.port == "socket_in"):
				parameters = e.parameters
				socket = parameters[0]
				sent_bytes = parameters[1]
				if self.socket == socket:
					self.small_step.addCandidate(self.transition_Root_connected_sending_transferring_1, e.parameters)
					return True
		return False
	
	def generateCandidates_Root_connected_sending_transferring(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_sending_transferring):
			return self.generateCandidatesCurrent_Root_connected_sending_transferring()
		else:
			return True
	
	def transition_Root_connected_sending_transferring_1(self, parameters):
		socket = parameters[0]
		sent_bytes = parameters[1]
		self.exit_Root_connected_sending_transferring()
		self.send_data = self.send_data[sent_bytes:]
		self.combo_step.setArenaChanged(self.Root_connected_sending)
		self.enter_Root_connected_sending_waiting_for_data()
	
	def generateCandidatesChildren_Root_connected_queueing(self):
		if self.current_state[self.Root_connected_queueing][0] == self.Root_connected_queueing_queueing:
			return self.generateCandidates_Root_connected_queueing_queueing()
		return False
	
	def generateCandidates_Root_connected_queueing(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_queueing):
			return self.generateCandidatesChildren_Root_connected_queueing()
		else:
			return True
	
	def generateCandidatesCurrent_Root_connected_queueing_queueing(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "HTTP_input":
				self.small_step.addCandidate(self.transition_Root_connected_queueing_queueing_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_connected_queueing_queueing(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_queueing_queueing):
			return self.generateCandidatesCurrent_Root_connected_queueing_queueing()
		else:
			return True
	
	def transition_Root_connected_queueing_queueing_1(self, parameters):
		data = parameters[0]
		self.exit_Root_connected_queueing_queueing()
		#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()])
		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)
		self.combo_step.setArenaChanged(self.Root_connected_queueing)
		self.enter_Root_connected_queueing_queueing()
	
	def generateCandidatesChildren_Root_connected_parsing(self):
		if self.current_state[self.Root_connected_parsing][0] == self.Root_connected_parsing_wait_for_header:
			return self.generateCandidates_Root_connected_parsing_wait_for_header()
		elif self.current_state[self.Root_connected_parsing][0] == self.Root_connected_parsing_closing:
			return self.generateCandidates_Root_connected_parsing_closing()
		elif self.current_state[self.Root_connected_parsing][0] == self.Root_connected_parsing_wait_for_payload:
			return self.generateCandidates_Root_connected_parsing_wait_for_payload()
		return False
	
	def generateCandidates_Root_connected_parsing(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_parsing):
			return self.generateCandidatesChildren_Root_connected_parsing()
		else:
			return True
	
	def generateCandidatesCurrent_Root_connected_parsing_wait_for_header(self):
		enabled_events = self.getEnabledEvents()
		if '\r\n\r\n' in self.received_data and self.received_data.startswith('POST'):
			self.small_step.addCandidate(self.transition_Root_connected_parsing_wait_for_header_1, [])
			return True
		enabled_events = self.getEnabledEvents()
		if self.closed and len(self.received_data) == 0:
			self.small_step.addCandidate(self.transition_Root_connected_parsing_wait_for_header_2, [])
			return True
		return False
	
	def generateCandidates_Root_connected_parsing_wait_for_header(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_parsing_wait_for_header):
			return self.generateCandidatesCurrent_Root_connected_parsing_wait_for_header()
		else:
			return True
	
	def transition_Root_connected_parsing_wait_for_header_1(self, parameters):
		self.exit_Root_connected_parsing_wait_for_header()
		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')
		self.combo_step.setArenaChanged(self.Root_connected_parsing)
		self.enter_Root_connected_parsing_wait_for_payload()
	
	def transition_Root_connected_parsing_wait_for_header_2(self, parameters):
		self.exit_Root_connected_parsing_wait_for_header()
		self.combo_step.setArenaChanged(self.Root_connected_parsing)
		self.enter_Root_connected_parsing_closing()
	
	def generateCandidatesCurrent_Root_connected_parsing_closing(self):
		enabled_events = self.getEnabledEvents()
		for e in enabled_events:
			if e.name == "_0after":
				self.small_step.addCandidate(self.transition_Root_connected_parsing_closing_1, e.parameters)
				return True
		return False
	
	def generateCandidates_Root_connected_parsing_closing(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_parsing_closing):
			return self.generateCandidatesCurrent_Root_connected_parsing_closing()
		else:
			return True
	
	def transition_Root_connected_parsing_closing_1(self, parameters):
		self.exit_Root_connected_parsing_closing()
		self.raiseInternalEvent(Event("close", None, []))
		self.combo_step.setArenaChanged(self.Root_connected_parsing)
		self.enter_Root_connected_parsing_closing()
	
	def generateCandidatesCurrent_Root_connected_parsing_wait_for_payload(self):
		enabled_events = self.getEnabledEvents()
		if len(self.received_data) >= self.length or self.closed:
			self.small_step.addCandidate(self.transition_Root_connected_parsing_wait_for_payload_1, [])
			return True
		return False
	
	def generateCandidates_Root_connected_parsing_wait_for_payload(self):
		if not self.combo_step.isArenaChanged(self.Root_connected_parsing_wait_for_payload):
			return self.generateCandidatesCurrent_Root_connected_parsing_wait_for_payload()
		else:
			return True
	
	def transition_Root_connected_parsing_wait_for_payload_1(self, parameters):
		self.exit_Root_connected_parsing_wait_for_payload()
		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:]
		
		# 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])]))
		self.combo_step.setArenaChanged(self.Root_connected_parsing)
		self.enter_Root_connected_parsing_wait_for_header()
	
	def generateCandidates_Root_close(self):
		return False
	
	# Generate transition candidates for current small step
	def generateCandidates(self):
		self.generateCandidates_Root()

class ObjectManager(ObjectManagerBase):
	def __init__(self, controller):
		ObjectManagerBase.__init__(self, controller)
	
	def instantiate(self, class_name, construct_params):
		if class_name == "MvKController":
			instance = MvKController(self.controller, construct_params[0])
			instance.associations = {}
			instance.associations["to_mvi"] = 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("MvKController", 1, 1)
		elif class_name == "Socket":
			instance = Socket(self.controller, construct_params[0])
			instance.associations = {}
			instance.associations["parent"] = Association("Server", 1, 1)
		return instance

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