123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- from abc import ABC, abstractmethod
- from typing import Any, List, Tuple, Optional, Union
- import uuid
- primitive_types = (int, float, str, bool)
- INTEGER = {"type": "Integer"}
- FLOAT = {"type": "Float"}
- STRING = {"type": "String"}
- BOOLEAN = {"type": "Boolean"}
- TYPE = {"type": "Type"}
- NODE = {"type": "Node"}
- EDGE = {"type": "Edge"}
- type_values = (INTEGER, FLOAT, STRING, BOOLEAN, TYPE, NODE, EDGE)
- Node = str
- Edge = str
- Element = Union[Node, Edge]
- class State(ABC):
- """
- Abstract base class for MvS CRUD interface defined in:
- http://msdl.cs.mcgill.ca/people/yentl/files/thesis.pdf
- This code is based on:
- https://msdl.uantwerpen.be/git/yentl/modelverse/src/master/state/modelverse_state
- """
- @staticmethod
- def new_id() -> str:
- """
- Generates a new UUID
- """
- return str(uuid.uuid4())
- @staticmethod
- def is_valid_datavalue(value: Any) -> bool:
- """
- Checks whether value type is supported.
- Args:
- value: value whose type needs to be checked
- Returns:
- True if value type is supported, False otherwise.
- """
- if isinstance(value, dict) and value in type_values:
- return True
- if not isinstance(value, primitive_types):
- return False
- elif isinstance(value, int) and not (-2**63 <= value <= 2**63 - 1):
- return False
- return True
- def purge(self):
- """
- Implements a garbage collection routine for implementations that don't have automatic garbage collection.
- """
- pass
- # =========================================================================
- # CREATE
- # =========================================================================
- @abstractmethod
- def create_node(self) -> Node:
- """
- Creates node.
- Returns:
- The created node.
- """
- pass
- @abstractmethod
- def create_edge(self, source: Element, target: Element) -> Optional[Edge]:
- """
- Creates edge. Source and target elements should already exist.
- Args:
- source: source element of edge
- target: target element of edge
- Returns:
- The created edge, None if source or target element doesn't exist.
- """
- pass
- @abstractmethod
- def create_nodevalue(self, value: Any) -> Optional[Node]:
- """
- Creates node containing value.
- Args:
- value: value to assign to new node
- Returns:
- The created node, None if type of value is not supported.
- """
- pass
- @abstractmethod
- def create_dict(self, source: Element, value: Any, target: Element) -> None:
- """
- Creates named edge between two graph elements.
- Args:
- source: source element of edge
- value: edge label
- target: target element of edge
- Returns:
- Nothing.
- """
- pass
- # =========================================================================
- # READ
- # =========================================================================
- @abstractmethod
- def read_root(self) -> Node:
- """
- Reads state's root node.
- Returns:
- The state's root node.
- """
- pass
- @abstractmethod
- def read_value(self, node: Node) -> Optional[Any]:
- """
- Reads value of given node.
- Args:
- node: node whose value to read
- Returns:
- I node exists, value stored in node, else None.
- """
- pass
- @abstractmethod
- def read_outgoing(self, elem: Element) -> Optional[List[Edge]]:
- """
- Retrieves edges whose source is given element.
- Args:
- elem: source element of edges to retrieve
- Returns:
- If elem exists, list of edges whose source is elem, else None.
- """
- pass
- @abstractmethod
- def read_incoming(self, elem: Element) -> Optional[List[Edge]]:
- """
- Retrieves edges whose target is given element.
- Args:
- elem: target element of edges to retrieve
- Returns:
- If elem exists, list of edges whose target is elem, else None.
- """
- pass
- @abstractmethod
- def read_edge(self, edge: Edge) -> Tuple[Optional[Node], Optional[Node]]:
- """
- Reads source and target of given edge.
- Args:
- edge: edge whose source and target to read
- Returns:
- If edge exists, tuple containing source (first) and target (second) node, else (None, None)
- """
- pass
- @abstractmethod
- def read_dict(self, elem: Element, value: Any) -> Optional[Element]:
- """
- Reads element connected to given element through edge with label = value.
- Args:
- elem: source element
- value: edge label
- Returns:
- If elem doesn't exist or no edge is found with given label, None, else target element of edge with label = value originating from source.
- """
- pass
- @abstractmethod
- def read_dict_keys(self, elem: Element) -> Optional[List[Any]]:
- """
- Reads labels of outgoing edges starting in given node.
- Args:
- elem: source element
- Returns:
- If elem exists, list of (unique) edge labels, else None.
- """
- pass
- @abstractmethod
- def read_dict_edge(self, elem: Element, value: Any) -> Optional[Edge]:
- """
- Reads edge between two elements connected through edge with label = value.
- Args:
- elem: source element
- value: edge label
- Returns:
- If elem doesn't exist or no edge is found with given label, None, else edge with label = value originating from source.
- """
- pass
- @abstractmethod
- def read_dict_node(self, elem: Element, value_node: Node) -> Optional[Element]:
- """
- Reads element connected to given element through edge with label node = value_node.
- Args:
- elem: source element
- value_node: edge label node
- Returns:
- If elem exists, target element of edge with label stored in value_node originating from elem, else None.
- """
- pass
- @abstractmethod
- def read_dict_node_edge(self, elem: Element, value_node: Node) -> Optional[Edge]:
- """
- Reads edge connecting two elements through edge with label node = value_node.
- Args:
- elem: source element
- value_node: edge label node
- Returns:
- If elem exists, edge with label node = value_node, originating from source, else None.
- """
- pass
- @abstractmethod
- def read_reverse_dict(self, elem: Element, value: Any) -> Optional[List[Element]]:
- """
- Retrieves a list of all elements that have an outgoing edge, having label = value, towards the passed element.
- Args:
- elem: target element
- value: edge label
- Returns:
- If elem exists, list of elements with an outgoing edge with label = value towards elem, else None.
- """
- pass
- # =========================================================================
- # UPDATE
- # =========================================================================
- """
- Updates are done by performing subsequent CREATE and DELETE operations:
- http://msdl.cs.mcgill.ca/people/yentl/files/thesis.pdf
- """
- # =========================================================================
- # DELETE
- # =========================================================================
- @abstractmethod
- def delete_node(self, node: Node) -> None:
- """
- Deletes given node from state graph.
- Args:
- node: node to be deleted
- Returns:
- None
- """
- pass
- @abstractmethod
- def delete_edge(self, edge: Edge) -> None:
- """
- Deletes given edge from state graph.
- Args:
- edge: edge to be deleted
- Returns:
- None
- """
- pass
|