class ActionAffordance(InteractionAffordance):
"""
creates action affordance schema from actions (or methods).
[Schema](https://www.w3.org/TR/wot-thing-description11/#actionaffordance) <br>
[UML Diagram](https://docs.hololinked.dev/UML/PDF/InteractionAffordance.pdf) <br>
[Supported Fields]() <br>
"""
input: JSON = None
output: JSON = None
safe: bool = None
idempotent: bool = None
synchronous: bool = None
def __init__(self, action: typing.Callable | None = None):
super().__init__()
self.action = action
@property
def what(self):
return ResourceTypes.ACTION
def build(self, action, owner) -> None:
self.action = action
self.owner = owner
self.title = self.action.name
if self.action.__doc__:
self.description = self.format_doc(action.__doc__)
if self.action.execution_info.argument_schema:
self.input = self.action.execution_info.argument_schema
if self.action.execution_info.return_value_schema:
self.output = self.action.execution_info.return_value_schema
if (not (hasattr(owner, 'state_machine') and owner.state_machine is not None and
owner.state_machine.has_object(self.action)) and
self.action.execution_info.idempotent):
self.idempotent = self.action.execution_info.idempotent
if self.action.execution_info.synchronous:
self.synchronous = self.action.execution_info.synchronous
if self.action.execution_info.safe:
self.safe = self.action.execution_info.safe
def build_forms(self, protocol: str, authority : str, **protocol_metadata) -> None:
self.forms = []
for method in self.action.execution_info_validator.http_method:
form = Form()
form.op = 'invokeaction'
form.href = f'{authority}/{self.owner.id}/{protocol_metadata.get("path", "")}/{self.action.name}'
form.htv_methodName = method.upper()
form.contentType = 'application/json'
# form.additionalResponses = [AdditionalExpectedResponse().asdict()]
self.forms.append(form.asdict())
@classmethod
def generate(cls, action : typing.Callable, owner, **kwargs) -> JSON:
affordance = ActionAffordance(action=action)
affordance.owner = owner
affordance._build(owner=owner)
if kwargs.get('protocol', None) and kwargs.get('authority', None):
affordance._build_forms(protocol=kwargs['protocol'], authority=kwargs['authority'])
return affordance.asdict()
@classmethod
def from_TD(self, name: str, TD: JSON) -> "ActionAffordance":
action = TD["actions"][name] # type: typing.Dict[str, JSON]
action_affordance = ActionAffordance()
if action.get("title", None):
action_affordance.title = action.get("title", None)
if action.get("description", None):
action_affordance.description = action.get("description", None)
if action.get("input", None):
action_affordance.input = action.get("input", None)
if action.get("output", None):
action_affordance.output = action.get("output", None)
if action.get("safe", None) is not None:
action_affordance.safe = action.get("safe", None)
if action.get("idempotent", None) is not None:
action_affordance.idempotent = action.get("idempotent", None)
if action.get("synchronous", None) is not None:
action_affordance.synchronous = action.get("synchronous", None)
if action.get("forms", None):
action_affordance.forms = action.get("forms", [])
action_affordance._name = name
action_affordance._thing_id = TD["id"]
return action_affordance