Commit 51427967 authored by payno's avatar payno
Browse files

[scheme] rework SubScheme and relative functions.

- add id to SubScheme
- add rlinks, rnodes and rsub_schemes which allows you to access to all links, nodes and sub_schemes recursively
- rework from / to json functions to fit the new description
- move some function to static for conveniance

warning: for now the rnodes and rlinks are created once for all. Only a call to _reset can apply modification to them once created
parent 7cf70c6e
......@@ -225,13 +225,13 @@ class Node(object):
}
@staticmethod
def from_json(json_data):
def load_node_info_from_json(json_data):
"""
load fom json stream the Node Information
:param json_data: node description
:return: New node created from the json description
:rtype: Node
:raise ValueError: if properties or id or processing_pt missing
:return: node id, properties, pointer to the process to run
:rtype: tuple
"""
# load properties
if Node._JSON_PROPERTIES not in json_data:
......@@ -253,7 +253,18 @@ class Node(object):
_process_pt = None
else:
_process_pt = json_data[Node._JSON_PROCESS_PT]
return _id, _properties, _process_pt
@staticmethod
def from_json(json_data):
"""
:param json_data: node description
:return: New node created from the json description
:rtype: Node
:raise ValueError: if properties or id or processing_pt missing
"""
_id, _properties, _process_pt = Node.load_node_info_from_json(json_data)
if _properties is None or _id is None or _process_pt is None:
raise ValueError('Unable to create Node from json, core information '
'are missing')
......
......@@ -48,24 +48,72 @@ class Scheme(object):
"""
class to define a workflow scheme from nodes and links
:param typing.Iterable nodes: set of Node
:param typing.Iterable list links: set of Link
:param typing.Iterable nodes: set of Node contained in this scheme.
note: subschemes are considered as Node.
So if any defined it should be given as a
Node
:param typing.Iterable links: set of Link
:type: typing.Iterable
"""
_JSON_DESCRIPTION = 'description'
_JSON_TITLE = 'title'
_JSON_NODES = 'nodes'
_JSON_LINKS = 'links'
def __init__(self, nodes:typing.Iterable=None, links:typing.Iterable=None,
def __init__(self, nodes: typing.Iterable=None, links: typing.Iterable=None,
description: str=None, title: str=None):
self.__rnodes = None
self.__rlinks = None
self.__rsub_schemes = None
self._reset(nodes=nodes, links=links, description=description,
title=title)
@property
def rnodes(self):
"""All the nodes recursively. So this mean contained in this scheme or
in a subscheme"""
if self.__rnodes is None:
self.__rnodes = list(self.nodes)
for subscheme in self.sub_schemes:
self.__rnodes.extend(subscheme.rnodes)
return self.__rnodes
@property
def rlinks(self):
"""all the links recursively. So this mean contained in this scheme or
in a subscheme"""
if self.__rlinks is None:
self.__rlinks = self.links
for subscheme in self.sub_schemes:
self.__rlinks.update(subscheme.rlinks)
return self.__rlinks
@property
def sub_schemes(self):
"""list of sub schemes contained by this scheme"""
return self.__sub_schemes
@property
def rsub_schemes(self):
"""list of all sub schemes contained in this scheme recursively
"""
if self.__rsub_schemes is None:
self.__rsub_schemes = self.sub_schemes
for sub_scheme in self.sub_schemes:
self.__rsub_schemes.extend(sub_scheme.rsub_schemes)
return self.__rsub_schemes
def _reset(self, nodes, links, description, title):
self.title = title or ''
self.description = description or ''
self.links = {}
"""keys are link ID, values are Link"""
# clear structure
self.links = {} # keys are link ID, values are Link
self.__sub_schemes = []
self.__rnodes = None
self.__rlinks = None
if links is not None:
for link in links:
self.links[link.id] = link
......@@ -73,8 +121,16 @@ class Scheme(object):
"""list of nodes"""
self.nodes_dict = {}
"""dict with node id as key and node as value"""
# register all sub scheme
for node in self.nodes:
if isinstance(node, SubScheme):
self.__sub_schemes.append(node)
self.nodes_dict[node.id] = node
# update nodes for sub_schemes
for node in self.rnodes:
self.nodes_dict[node.id] = node
if links is not None:
self._update_nodes_from_links()
......@@ -85,7 +141,7 @@ class Scheme(object):
control node upstream
"""
res = []
for node in self.nodes:
for node in self.rnodes:
assert isinstance(node, Node)
if node.isfinal():
res.append(node)
......@@ -99,7 +155,7 @@ class Scheme(object):
:rtype: list
"""
res = []
for node in self.nodes:
for node in self.rnodes:
assert isinstance(node, Node)
if node.isstart():
res.append(node)
......@@ -112,7 +168,7 @@ class Scheme(object):
:rtype: list
"""
res = []
for node in self.nodes:
for node in self.rnodes:
assert isinstance(node, Node)
if node.endless is True:
res.append(node)
......@@ -161,21 +217,25 @@ class Scheme(object):
res.append(node.to_json())
return res
def nodes_from_json(self, json_data):
@staticmethod
def nodes_from_json(json_data):
"""
:param json_data: data containing the json definition
:return: list of Node defined by the json data
:rtype: list
:return: nodes, sub_schemes
:rtype: tuple
:raises: ValueError if the json is not a valid Node description
"""
if not self._JSON_NODES in json_data:
raise ValueError('does not contain any Node description')
else:
nodes_json_data = json_data[self._JSON_NODES]
nodes = []
for node_json_data in nodes_json_data:
nodes = []
sub_schemes = []
for node_json_data in json_data:
# if contains a node description then this is a subscheme
if Scheme._JSON_NODES in node_json_data:
sub_scheme = SubScheme.load_from_json(node_json_data)
sub_schemes.append(sub_scheme)
else:
nodes.append(Node.from_json(node_json_data))
return nodes
return nodes, sub_schemes
def links_to_json(self):
"""
......@@ -188,21 +248,18 @@ class Scheme(object):
res.append(link.to_json())
return res
def links_from_json(self, json_data):
@staticmethod
def links_from_json(json_data):
"""
:param json_data: data containing the json definition
:return: list of Link defined by the json data
:rtype: list
"""
if not self._JSON_LINKS in json_data:
raise ValueError('does not contain any Node description')
else:
links_json_data = json_data[self._JSON_LINKS]
links = []
for link_json_data in links_json_data:
links.append(Link.from_json(link_json_data))
return links
links = []
for link_json_data in json_data:
links.append(Link.from_json(link_json_data))
return links
def to_json(self):
"""
......@@ -254,51 +311,64 @@ class Scheme(object):
else:
self.load_from_json(json_data=json_data)
def load_from_json(self, json_data):
@staticmethod
def load_scheme_info_from_json(json_data):
"""
load fom json stream the Scheme Information
:param json_data: scheme description
:raise ValueError: if sink or source channel missing or if link id
missing or if sink or source node missing
:return: nodes, links, sub-schemes, title, description
:rtype: tuple
"""
# load title
if self._JSON_TITLE not in json_data:
if Scheme._JSON_TITLE not in json_data:
_logger.warning('no title found in the json')
title = None
else:
title = json_data[self._JSON_TITLE]
title = json_data[Scheme._JSON_TITLE]
# load description
if self._JSON_DESCRIPTION not in json_data:
if Scheme._JSON_DESCRIPTION not in json_data:
_logger.warning('no description found in the json')
description = None
else:
description = json_data[self._JSON_DESCRIPTION]
description = json_data[Scheme._JSON_DESCRIPTION]
# load links
if self._JSON_LINKS not in json_data:
if Scheme._JSON_LINKS not in json_data:
_logger.error('no link found in the json')
links = None
else:
try:
links = self.links_from_json(json_data=json_data)
links = Scheme.links_from_json(json_data=json_data[Scheme._JSON_LINKS])
except ValueError as e:
_logger.error(e)
links = None
# load nodes
if self._JSON_NODES not in json_data:
nodes, sub_schemes = None, None
if Scheme._JSON_NODES not in json_data:
_logger.error('no nodes found in the json')
nodes = None
else:
try:
nodes = self.nodes_from_json(json_data=json_data)
nodes, sub_schemes = Scheme.nodes_from_json(json_data=json_data[Scheme._JSON_NODES])
except ValueError as e:
_logger.error(e)
nodes = None
return nodes, links, sub_schemes, title, description
def load_from_json(self, json_data):
"""
:param json_data: scheme description
:raise ValueError: if sink or source channel missing or if link id
missing or if sink or source node missing
"""
nodes, links, sub_schemes, title, description = self.load_scheme_info_from_json(json_data)
# create scheme if possible
if nodes is None or links is None:
raise ValueError('unable to load scheme from json description.'
'Information missing')
else:
if sub_schemes is not None:
nodes.extend(sub_schemes)
self._reset(nodes=nodes, links=links, description=description,
title=title)
......@@ -467,11 +537,45 @@ class SubScheme(Scheme, Node):
:param error_handler: ErrorHandler
"""
def __init__(self, nodes: typing.Iterable, links: typing.Iterable,
description: str=None, error_handler=None):
Node.__init__(self, processing_pt=None, error_handler=error_handler)
Scheme.__init__(self, nodes=nodes, links=links, title='',
description: str=None, error_handler=None, title='', id=None):
Node.__init__(self, processing_pt=None, error_handler=error_handler,
id=id)
Scheme.__init__(self, nodes=nodes, links=links, title=title,
description=description)
def to_json(self):
"""
Convert sub scheme to json
:return: json dict
:rtype: dict
"""
desc = Scheme.to_json(self)
desc.update(Node.to_json(self))
return desc
@staticmethod
def load_from_json(json_data):
"""
:param json_data: scheme description
:raise ValueError: if sink or source channel missing or if link id
missing or if sink or source node missing
"""
nodes, links, sub_schemes, title, description = Scheme.load_scheme_info_from_json(json_data)
_id, _properties, _process_pt = Node.load_node_info_from_json(json_data)
if _properties is not None:
_logger.warning('SubScheme properties are not managed')
if _process_pt is not None:
_logger.warning('SubScheme pointer to ptocess is not managed')
# create scheme if possible
if nodes is None or links is None:
raise ValueError('unable to load scheme from json description.'
'Information missing')
sub_scheme = SubScheme(nodes=nodes, links=links,
description=description, title=title, id=_id)
return sub_scheme
def contains_control_nodes(nodes_list: typing.Iterable):
"""
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment