Alexander Tivelkov e853cf861b Event Notification pattern implemented
This patch adds an 'Event' class which may be used to issue various
notifications to other MuranoPl classes in an Event-driven manner.

Any object which is going to emit the notifications should declare the
instances of this new class as its public Runtime properties. The
objects going to subscribe for the notifications should pass
themselves into the 'subscribe' method of the Event along with the
names of their methods which will be used to handle the notification.

The specified handler methods must be present in the subscriber class
(if the method name is missing it will be defaulted to the
'handle%Eventname%') and has at least one standard (i.e. non-vararg
or kwarg) argument.

The class going to emit the notification should call the 'notify'
method of the event and pass itself as the first argument. All the
optional parameters of the event may be passed as varargs/kwargs of
the 'notify' call and will be passed all the way to the handler
methods.

Since this approach relies on the reflection this patch also fixes a
bug #1596647 since its fix is required for the argument reflection to
work properly. It also documents new reflection capabilities which
were added as part of the bugfix.

Targets-blueprint: application-development-framework
Closes-Bug: #1596647
Change-Id: Ifa7053e4c7b8456030e8df743f57ed812104b064
2016-07-28 18:50:04 +03:00

6.1 KiB

Reflection capabilities in MuranoPL.

Reflection provides objects that describes MuranoPL classes and packages.

The first important function is typeinfo . Usage:

$typeInfo: typeinfo($someObject)

Now $typeInfo variable contains instance of type of $someObject (MuranoClass instance).

MuranoPL provide following abilities to reflection:

Types

Property Description
name name of MuranoPL class
version version (SemVer) of MuranoPL class.
ancestors list of class ancestors
properties list of class properties. See properties_reflection
package package information. See package_reflection
methods list of methods. See methods_reflection
type reference to type, which can be used as argument in engine functions

Example

- $typeInfo: typeinfo($)
...
# log name, version and package name of this class
- $log.info("This is "{class_name}/{version} from {package}",
     class_name => $typeInfo.name,
     version => str($typeInfo.version),
     package => $typeInfo.package.name))
- $log.info("Ancestors:")
- For: ancestor
  In: $typeInfo.ancestors
  Do:
    #log all ancestors names
    - $log.info("{ancestor_name}", ancestor_name => $ancestor.name)
# log full class version
- $log.info("{version}", version => str($typeInfo.version))
# create object with same class
- $newObject = new($typeInfo.type)

Properties

Property introspection

Property Description
name name of property
hasDefault boolean value. True, if property has default value, False otherwise
usage Usage property's field. See property_usage for details
declaringType type - owner of declared property

Property access

Methods Description
$property.setValue($target, $value) set value of $property for object $target to $value
$property.getValue($target) get value of $property for object $target

Example

- $typeInfo: typeinfo($)
...
# select first property
- $selectedPropety: $typeInfo.properties.first()
# log property name
- $log.info("Hi, my name is {p_name}, p_name => $selectedProperty.name)
# set new property value
- $selectedProperty.setValue($, "new_value")
# log new property value using reflection
- $log.info("My new value is {value}", value => $selectedProperty.getValue($))
# also, if property static, $target can be null
- $log.info("Static property value is {value},
    value => $staticProperty.getValue(null))

Packages

Property Description
types list of types, declared in package
name package name
version package version

Example

- $typeInfo: typeinfo($)
...
- $packageRef: $typeInfo.package
- $log.info("This is package {p_name}/{p_version}",
    p_name => $packageRef.name,
    p_version => str($packageRef.version))
- $log.info("Types in package:")
- For: type_
  In: $packageRef.types
  Do:
    - $log.info("{typename}", typename => type_.name)

Methods

Methods properties

Property Description
name method's name
declaringType type - owner of declared method
arguments list of method's arguments. See arguments_reflection

Method invoking

Methods Description
$method.invoke($target, $arg1, ... $argN, kwarg1 => value1, ..., kwargN => valueN) call $target's method $method with $arg1, ..., $argN positional arguments and kwarg1, .... kwargN named arguments

Example

- $typeInfo: typeinfo($)
...
# select single method by name
- $selectedMethod: $typeInfo.methods.where($.name = sampleMethodName).single()
# log method name
- $log.info("Method name: {m_name}", m_name => $selectedMethod.name)
# log method arguments names
- For: argument
  In: $selectedMethod.arguments
  Do:
     - $log.info("{name}", name => $argument.name)
# call method with positional argument 'bar' and named `baz` == 'baz'
- $selectedMethod.invoke($, 'bar', baz => baz)

Method arguments

Property Description
name argument's name
hasDefault True if argument has default value, False otherwise
declaringMethod method - owner of argument
usage argument's usage type. See method_arguments for details
- $firstArgument: $selectedMethod.arguments.first()
# store argument's name
- $argName: $firstArgument.name
# store owner's name
- $methodName: $firstArgument.declaringMethod.name
- $log.info("Hi, my name is {a_name} ! My owner is {m_name}",
    a_name => $argName,
    m_name => $methodName)