Fix doc config files and dead links
[policy/parent.git] / docs / apex / APEX-Policy-Guide.rst
1  .. This work is licensed under a Creative Commons Attribution 4.0 International License.
2  .. http://creativecommons.org/licenses/by/4.0
3
4 #################
5 APEX Policy Guide
6 #################
7
8
9 .. contents::
10     :depth: 5
11
12 ******************
13 APEX Policy Matrix
14 ******************
15
16 .. container:: paragraph
17
18   APEX offers a lot of flexibility for defining, deploying, and executing policies. Based on a theoretic model, it
19   supports virtually any policy model and supports translation of legacy policies into the APEX execution format.
20   However, the most important aspect for using APEX is to decide what policy is needed, what underlying policy concepts
21   should be used, and how the decision logic should be realized. Once these aspects are decided, APEX can be used to
22   execute the policies. If the policy evolves, say from a simple decision table to a fully adaptable policy, only the
23   policy definition requires change. APEX supports all of that.
24
25 .. container:: paragraph
26
27   The figure below shows a (non-exhaustive) matrix, which will help to decide what policy is required to solve your
28   problem. Read the matrix from left to right choosing one cell in each column.
29
30 .. container:: imageblock
31
32   .. container:: content
33
34     |APEX Policy Matrix|
35
36   .. container:: title
37
38     Figure 1. APEX Policy Matrix
39
40 .. container:: paragraph
41
42   The policy can support one of a number of stimuli with an associated purpose/model of the policy, for instance:
43
44 .. container:: ulist
45
46   -  Configuration, i.e. what should happen. An example is an event that states an intended network configuration
47      and the policy should provide the detailed actions for it. The policy can be realized for instance as an
48      obligation policy, a promise or an intent.
49
50   -  Report, i.e. something did happen. An example is an event about an error or fault and the policy needs to
51      repair that problem. The policy would usually be an obligation, utility function, or goal policy.
52
53   -  Monitoring, i.e. something does happen. An example is a notification about certain network conditions, to
54      which the policy might (or might not) react. The policy will mitigate the monitored events or permit (deny)
55      related actions as an obligation or authorization.
56
57   -  Analysis, i.e. why did something happen. An example is an analytic component sends insights of a situation
58      requiring a policy to act on it. The policy can solve the problem, escalate it, or delegate it as a refrain or
59      delegation policy.
60
61   -  Prediction, i.e. what will happen next. An example are events that a policy uses to predict a future network
62      condition. The policy can prevent or enforce the prediction as an adaptive policy, a utility function, or a goal.
63
64   -  Feedback, i.e. why did something happen or not happen. Similar to analysis, but here the feedback will be in
65      the input event and the policy needs to something with that information. Feedback can be related to history or
66      experience, for instance a previous policy execution. The policy needs to be context-aware or be a meta-policy.
67
68 .. container:: paragraph
69
70   Once the purpose of the policy is decided, the next step is to look into what context information the policy will
71   require to do its job. This can range from very simple to a lot of different information, for instance:
72
73 .. container:: ulist
74
75   -  No context, nothing but a trigger event, e.g. a string or a number, is required
76
77   -  Event context, the incoming event provides all information (more than a string or number) for the policy
78
79   -  Policy context (read only), the policy has access to additional information related to its class but cannot
80      change/alter them
81
82   -  Policy context (read and write), the policy has access to additional information related to its class and can
83      alter this information (for instance to record historic information)
84
85   -  Global context (read only), the policy has access to additional information of any kind but cannot
86      change/alter them
87
88   -  Global context (read and write), the policy the policy has access to additional information of any kind and
89      can alter this information (for instance to record historic information)
90
91 .. container:: paragraph
92
93   The next step is to decide how the policy should do its job, i.e. what flavor it has, how many states are needed,
94   and how many tasks. There are many possible combinations, for instance:
95
96 .. container:: ulist
97
98   -  Simple / God: a simple policy with 1 state and 1 task, which is doing everything for the decision-making. This
99      is the ideal policy for simple situation, e.g. deciding on configuration parameters or simple access control.
100
101   -  Simple sequence: a simple policy with a number of states each having a single task. This is a very good policy
102      for simple decision-making with different steps. For instance, a classic action policy (ECA) would have 3 states
103      (E, C, and A) with some logic (1 task) in each state.
104
105   -  Simple selective: a policy with 1 state but more than one task. Here, the appropriate task (and it’s logic)
106      will be selected at execution time. This policy is very good for dealing with similar (or the same) situation in
107      different contexts. For instance, the tasks can be related to available external software, or to current work load
108      on the compute node, or to time of day.
109
110   -  Selective: any number of states having any number of tasks (usually more than 1 task). This is a combination
111      of the two policies above, for instance an ECA policy with more than one task in E, C, and A.
112
113   -  Classic directed: a policy with more than one state, each having one task, but a non-sequential execution.
114      This means that the sequence of the states is not pre-defined in the policy (as would be for all cases above) but
115      calculated at runtime. This can be good to realize decision trees based on contextual information.
116
117   -  Super Adaptive: using the full potential of the APEX policy model, states and tasks and state execution are
118      fully flexible and calculated at runtime (per policy execution). This policy is very close to a general
119      programming system (with only a few limitations), but can solve very hard problems.
120
121 .. container:: paragraph
122
123   The final step is to select a response that the policy creates. Possible responses have been discussed in the
124   literature for a very long time. A few examples are:
125
126 .. container:: ulist
127
128   -  Obligation (deontic for what should happen)
129
130   -  Authorization (e.g. for rule-based or other access control or security systems)
131
132   -  Intent (instead of providing detailed actions the response is an intent statement and a further system
133      processes that)
134
135   -  Delegation (hand the problem over to someone else, possibly with some information or instructions)
136
137   -  Fail / Error (the policy has encountered a problem, and reports it)
138
139   -  Feedback (why did the policy make a certain decision)
140
141 *****************
142 APEX Policy Model
143 *****************
144
145 .. container:: paragraph
146
147   The APEX policy model is shown in UML notation in the figure below. A policy model can be stored in JSON or XML
148   format in a file or can be held in a database. The APEX editor creates and modifies APEX policy models. APEX
149   deployment deploys policy models, and a policy model is loaded into APEX engines so that the engines can run the
150   policies in the policy model.
151
152 .. container:: paragraph
153
154   The figure shows four different views of the policy model:
155
156 .. container:: ulist
157
158   -  The general model view shows the main parts of a policy: state, state output, event, and task. A task can also
159      have parameters. Data types can be defined on a per-model basis using either standard atomic types (such as
160      character, string, numbers) or complex types from a policy domain.
161
162   -  The logic model view emphasizes how decision-making logic is injected into a policy. There are essentially
163      three different types of logic: task logic (for decision making in a task), task selection logic (to select a task
164      if more than one is defined in a state), and state finalizer logic (to compute the final output event of a state
165      and select an appropriate next state from the policy model).
166
167   -  The context model view shows how context is injected into a policy. States collect all context from their
168      tasks. A task can define what context it requires for the decision making, i.e. what context the task logic will
169      process. Context itself is a collection of items (individual context information) with data types. Context can be
170      templated.
171
172   -  The event and field model view shows the events in the policy model. Tasks define what information they
173      consume (input) and produce (output). This information is modeled as fields, essentially a key/type tuple in the
174      model and a key/type/value triple at execution. Events then are collection of fields.
175
176 .. container:: imageblock
177
178   .. container:: content
179
180     |APEX Policy Model for Execution|
181
182   .. container:: title
183
184     Figure 2. APEX Policy Model for Execution
185
186 Concepts and Keys
187 =================
188
189 .. container:: paragraph
190
191   Each element of the policy model is called a *concept*. Each *concept* is a subclass of the abstract *Concept*
192   class, as shown in the next figure. Every concept implements the following abstract methods:
193
194 .. container:: imageblock
195
196   .. container:: content
197
198     |Concepts and Keys|
199
200   .. container:: title
201
202     Figure 3. Concepts and Keys
203
204 .. container:: ulist
205
206   -  ``getKey()`` - gets the unique key for this concept instance in the system
207
208   -  ``validate()`` - validates the structure of this concept, its sub-concepts and its relationships
209
210   -  ``clean()`` - carries out housekeeping on the concept such as trimming strings, remove any hanging references
211
212   -  ``clone()`` - creates a deep copy of an instance of this concept
213
214   -  ``equals()`` - checks if two instances of this concept are equal
215
216   -  ``toString()`` - returns a string representation of the concept
217
218   -  ``hashCode()`` - returns a hash code for the concept
219
220   -  ``copyTo()`` - carries out a deep copy of one instance of the concept to another instance, overwriting the
221      target fields.
222
223 .. container:: paragraph
224
225  All concepts must have a *key*, which uniquely identifies a concept instance. The *key* of a subclass of an *Concept*
226  must either be an ``ArtifactKey`` or an ``ReferenceKey``. Concepts that have a stand-alone independent existence such
227  as *Policy*, *Task*, and *Event* must have an ``ArtifctKey`` key. Concepts that are contained in other concepts, that
228  do not exist as stand-alone concepts must have an ``ReferenceKey`` key. Examples of such concepts are *State* and
229  *EventParameter*.
230
231 .. container:: paragraph
232
233  An ``ArticactKey`` has two fields; the *Name* of the concept it is the key for and the concept’s *Version*. A
234  concept’s name must be unique in a given PolicyModel. A concept version is represented using the well known
235  *major.minor.path* scheme as used in semantic versioning.
236
237 .. container:: paragraph
238
239   A ``ReferenceKey`` has three fields. The *UserKeyName* and *UserKeyVersion* fields identify the ``ArtifactKey`` of
240   the concept in which the concept keyed by the ``ReferenceKey`` is contained. The *LocalName* field identifies the
241   contained concept instance. The *LocalName* must be unique in the concepts of a given type contained by a parent.
242
243 .. container:: paragraph
244
245   For example, a policy called ``SalesPolicy`` with a Version of ``1.12.4`` has a state called ``Decide``. The
246   ``Decide`` state is linked to the ``SalesPolicy`` with a ``ReferenceKey`` with fields *UserKeyName* of
247   ``SalesPolicy``, *UserKeyVersion* of ``1.12.4``, and *LocalName* of ``Decide``. There must not be another state
248   called ``Decide`` in the policy ``SalesPolicy``. However, there may well be a state called ``Decide`` in some other
249   policy called ``PurchasingPolicy``.
250
251 .. container:: paragraph
252
253   Each concept in the model is also a JPA
254   (`Java Persistence API <https://en.wikipedia.org/wiki/Java_Persistence_API>`__) Entity. This means that every concept
255   can be individually persisted or the entire model can be persisted en-bloc to any persistence mechanism using an JPA
256   framework such as `Hibernate <http://hibernate.org/>`__ or `EclipseLink <http://www.eclipse.org/eclipselink/>`__.
257
258 Concept: PolicyModel
259 ====================
260
261 .. container:: paragraph
262
263   The *PolicyModel* concept is a container that holds the definition of a set of policies and their associated events,
264   context maps, and tasks. A *PolicyModel* is implemented as four maps for policies, events, context maps, and tasks.
265   Each map is indexed by the key of the policy, event, context map, or task. Any non-empty policy model must have at
266   least one entry in its policy, event, and task map because all policies must have at least one input and output event
267   and must execute at least one task.
268
269 .. container:: paragraph
270
271   A *PolicyModel* concept is keyed with an ``ArtifactKey key``. Because a *PolicyModel* is an ``AxConcept``, calling
272   the ``validate()`` method on a policy model validates the concepts, structure, and relationships of the entire policy
273   model.
274
275 Concept: DataType
276 =================
277
278 .. container:: paragraph
279
280   Data types are tightly controlled in APEX in order to provide a very high degree of consistency in policies and to
281   facilitate tracking of changes to context as policies execute. All context is modeled as a *DataType* concept. Each
282   DataType concept instance is keyed with an ``ArtifactKey`` key. The DataType field identifies the Java class of
283   objects that is used to represent concept instances that use this data type. All context has a *DataType*; incoming
284   and outgoing context is represented by *EventField* concepts and all other context is represented by *ContextItem*
285   concepts.
286
287 Concept: Event
288 ==============
289
290 .. container:: paragraph
291
292   An *Event* defines the structure of a message that passes into or out of an APEX engine or that passes between two
293   states in an APEX engine. APEX supports message reception and sending in many formats and all messages are translated
294   into an *Event* prior to processing by an APEX engine. Event concepts are keyed with an ``ArtifactKey`` key. The
295   parameters of an event are held as a map of *EventField* concept instances with each parameter indexed by the
296   *LocalName* of its ``ReferenceKey``. An *Event* has three fields:
297
298 .. container:: ulist
299
300   -  The *NameSpace* identifies the domain of application of the event
301
302   -  The *Source* of the event identifies the system that emitted the event
303
304   -  The *Target* of the event identifies the system that the event was sent to
305
306 .. container:: paragraph
307
308   A *PolicyModel* contains a map of all the events known to a given policy model. Although an empty model may have no
309   events in its event map, any sane policy model must have at least one *Event* defined.
310
311 Concept: EventField
312 ===================
313
314 .. container:: paragraph
315
316   The incoming context and outgoing context of an event are the fields of the event. Each field representing a single
317   piece of incoming or outgoing context. Each field of an *Event* is represented by an instance of the *EventField*
318   concept. Each *EventField* concept instance in an event is keyed with a ``ReferenceKey`` key, which references the
319   event. The *LocalName* field of the ``ReferenceKey`` holds the name of the field A reference to a *DataType* concept
320   defines the data type that values of this parameter have at run time.
321
322 Concept: ContextMap
323 ===================
324
325 .. container:: paragraph
326
327   The set of context that is available for use by the policies of a *PolicyModel* is defined as *ContextMap* concept
328   instances. The *PolicyModel* holds a map of all the *ContextMap* definitions. A *ContextMap* is itself a container
329   for a group of related context items, each of which is represented by a *ContextItem* concept instance. *ContextMap*
330   concepts are keyed with an ``ArtifactKey`` key. A developer can use the APEX Policy Editor to create context maps for
331   their application domain.
332
333 .. container:: paragraph
334
335   A *ContextMap* uses a map to hold the context items. The ContextItem concept instances in the map are indexed by the
336   *LocalName* of their ``ReferenceKey``.
337
338 .. container:: paragraph
339
340   The *ContextMapType* field of a *ContextMap* defines the type of a context map. The type can have either of two
341   values:
342
343 .. container:: ulist
344
345  -  A *BAG* context map is a context map with fixed content. Each possible context item in the context map is
346     defined at design time and is held in the *ContextMap* context instance as *ContextItem* concept definitions and
347     only the values of the context items in the context map can be changed at run time. The context items in a *BAG*
348     context map have mixed types and distinct *ContextItem* concept instances of the same type can be defined. A *BAG*
349     context map is convenient for defining a group of context items that are diverse but are related by domain, such as
350     the characteristics of a device. A fully defined *BAG* context map has a fully populated *ContextItem* map but its
351     *ContextItemTemplate* reference is not defined.
352
353   -  A *SAMETYPE* context map is used to represent a group of *ContextItem* instances of the same type. Unlike a
354      *BAG* context map, the *ContextItem* concept instances of a *SAMETYPE* context map can be added, modified, and
355      deleted at runtime. All *ContextItem* concept instances in a *SAMETYPE* context map must be of the same type, and
356      that context item is defined as a single *ContextItemTemplate* concept instances at design time. At run time, the
357      *ContextItemTemplate* definition is used to create new *ContextItem* concept instances for the context map on
358      demand. A fully defined *SAMETYPE context map has an empty ContextItem map and its ContextItemTemplate\_*
359      reference is defined.
360
361 .. container:: paragraph
362
363   The *Scope* of a *ContextMap* defines the range of applicability of a context map in APEX. The following scopes of
364   applicability are defined:
365
366 .. container:: ulist
367
368   -  *EPHEMERAL* scope means that the context map is owned, used, and modified by a single application but the
369      context map only exists while that application is running
370
371   -  *APPLICATION* scope specifies that the context map is owned, used, and modified by a single application, the
372      context map is persistent
373
374   -  *GLOBAL* scope specifies that the context map is globally owned and is used and modified by any application,
375      the context map is persistent
376
377   -  *EXTERNAL* scope specifies that the context map is owned by an external system and may be used in a read-only
378      manner by any application, the context map is persistent
379
380 .. container:: paragraph
381
382   A much more sophisticated scoping mechanism for context maps is envisaged for Apex in future work. In such a
383   mechanism, the scope of a context map would work somewhat like the way roles work in security authentication systems.
384
385 Concept: ContextItem
386 ====================
387
388 .. container:: paragraph
389
390   Each piece of context in a *ContextMap* is represented by an instance of the *ContextItem* concept. Each
391   *ContextItem* concept instance in a context map keyed with a ``ReferenceKey`` key, which references the context map
392   of the context item. The *LocalName* field of the ``ReferenceKey`` holds the name of the context item in the context
393   map A reference to a *DataType* concept defines the data type that values of this context item have at run time. The
394   *WritableFlag* indicates if the context item is read only or read-write at run time.
395
396 Concept: ContextItemTemplate
397 ============================
398
399 .. container:: paragraph
400
401   In a *SAMETYPE* *ContextMap*, the *ContextItemTemplate* definition provides a template for the *ContextItem*
402   instances that will be created on the context map at run time. Each *ContextItem* concept instance in the context map
403   is created using the *ContextItemTemplate* template. It is keyed with a ``ReferenceKey`` key, which references the
404   context map of the context item. The *LocalName* field of the ``ReferenceKey``, supplied by the creator of the
405   context item at run time, holds the name of the context item in the context map. A reference to a *DataType* concept
406   defines the data type that values of this context item have at run time. The *WritableFlag* indicates if the context
407   item is read only or read-write at run time.
408
409 Concept: Task
410 =============
411
412 .. container:: paragraph
413
414   The smallest unit of logic in a policy is a *Task*. A task encapsulates a single atomic unit of logic, and is
415   designed to be a single indivisible unit of execution. A task may be invoked by a single policy or by many policies.
416   A task has a single trigger event, which is sent to the task when it is invoked. Tasks emit one or more outgoing
417   events, which carry the result of the task execution. Tasks may use or modify context as they execute.
418
419 .. container:: paragraph
420
421   The Task concept definition captures the definition of an APEX task. Task concepts are keyed with an ``ArtifactKey``
422   key. The Trigger of the task is a reference to the *Event* concept that triggers the task. The *OutgoingEvents* of a
423   task are a set of references to *Event* concepts that may be emitted by the task.
424
425 .. container:: paragraph
426
427   All tasks have logic, some code that is programmed to execute the work of the task. The *Logic* concept of the task
428   holds the definition of that logic.
429
430 .. container:: paragraph
431
432   The *Task* definition holds a set of *ContextItem* and *ContextItemTemplate* context items that the task is allow to
433   access, as defined by the task developer at design time. The type of access (read-only or read write) that a task has
434   is determined by the *WritableFlag* flag on the individual context item definitions. At run time, a task may only
435   access the context items specified in its context item set, the APEX engine makes only the context items in the task
436   context item set is available to the task.
437
438 .. container:: paragraph
439
440   A task can be configured with startup parameters. The set of parameters that can be configured on a task are defined
441   as a set of *TaskParameter* concept definitions.
442
443 Concept: TaskParameter
444 ======================
445
446 .. container:: paragraph
447
448   Each configuration parameter of a task are represented as a *Taskparameter* concept keyed with a ``ReferenceKey``
449   key, which references the task. The *LocalName* field of the ``ReferenceKey`` holds the name of the parameter. The
450   *DefaultValue* field defines the default value that the task parameter is set to. The value of *TaskParameter*
451   instances can be overridden at deployment time by specifying their values in the configuration information passed to
452   APEX engines.
453
454 .. container:: paragraph
455
456   The *taskParameters* field is specified under *engineParameters* in the ApexConfig. It can contain one or more task
457   parameters, where each item can contain the parameter key, value as well as the taskId to which it is associated. If
458   the taskId is not specified, then the parameters are added to all tasks.
459
460 Concept: Logic
461 ==============
462
463 .. container:: paragraph
464
465   The *Logic* concept instance holds the actual programmed task logic for a task defined in a *Task* concept or the
466   programmed task selection logic for a state defined in a *State* concept. It is keyed with a ``ReferenceKey`` key,
467   which references the task or state that owns the logic. The *LocalName* field of the Logic concept is the name of the
468   logic.
469
470 .. container:: paragraph
471
472   The *LogicCode* field of a Logic concept definition is a string that holds the program code that is to be executed
473   at run time. The *LogicType* field defines the language of the code. The standard values are the logic languages
474   supported by APEX: `JAVASCRIPT <https://en.wikipedia.org/wiki/JavaScript>`__, `JAVA <https://java.com/en/>`__,
475   `JYTHON <http://www.jython.org/>`__, `JRUBY <http://jruby.org/>`__, or
476   `MVEL <https://en.wikibooks.org/wiki/Transwiki:MVEL_Language_Guide>`__.
477
478 .. container:: paragraph
479
480   The APEX engine uses the *LogicType* field value to decide which language interpreter to use for a task and then
481   sends the logic defined in the *LogicCode* field to that interpreter.
482
483 Concept: Policy
484 ===============
485
486 .. container:: paragraph
487
488   The *Policy* concept defines a policy in APEX. The definition is rather straightforward. A policy is made up of a
489   set of states with the flavor of the policy determining the structure of the policy states and the first state
490   defining what state in the policy executes first. *Policy* concepts are keyed with an ``ArtifactKey`` key.
491
492 .. container:: paragraph
493
494   The *PolicyFlavour* of a *Policy* concept specifies the structure that will be used for the states in the policy. A
495   number of commonly used policy patterns are supported as APEX policy flavors. The standard policy flavors are:
496
497 .. container:: ulist
498
499   -  The *MEDA* flavor supports policies written to the
500      `MEDA policy pattern <https://ieeexplore.ieee.org/document/7367357>`__
501      and require a sequence of four states: namely *Match*, *Establish*, *Decide* and *Act*.
502
503   -  The *OODA* flavor supports policies written to the
504      `OODA loop pattern <https://en.wikipedia.org/wiki/OODA_loop>`__ and require a sequence of four states: namely
505      *Observe*, *Orient*, *Decide* and *Act*.
506
507   -  The *ECA* flavor supports policies written to the
508      `ECA active rule pattern <https://en.wikipedia.org/wiki/Event_condition_action>`__ and require a sequence of three
509      states: namely *Event*, *Condition* and *Action*
510
511   -  The *XACML* flavor supports policies written in `XACML <https://en.wikipedia.org/wiki/XACML>`__ and require a
512      single state: namely *XACML*
513
514   -  The *FREEFORM* flavor supports policies written in an arbitrary style. A user can define a *FREEFORM* policy
515      as an arbitrarily long chain of states.
516
517 .. container:: paragraph
518
519   The *FirstState* field of a *Policy* definition is the starting point for execution of a policy. Therefore, the
520   trigger event of the state referenced in the *FirstState* field is also the trigger event for the entire policy.
521
522 Concept: State
523 ==============
524
525 .. container:: paragraph
526
527   The *State* concept represents a phase or a stage in a policy, with a policy being composed of a series of states.
528   Each state has at least one but may have many tasks and, on each run of execution, a state executes one and only one
529   of its tasks. If a state has more than one task, then its task selection logic is used to select which task to
530   execute. Task selection logic is programmable logic provided by the state designer. That logic can use incoming,
531   policy, global, and external context to select which task best accomplishes the purpose of the state in a give
532   situation if more than one task has been specified on a state. A state calls one and only one task when it is
533   executed.
534
535 .. container:: paragraph
536
537   Each state is triggered by an event, which means that all tasks of a state must also be triggered by that same
538   event. The set of output events for a state is the union of all output events from all tasks for that task. In
539   practice at the moment, because a state can only have a single input event, a state that is not the final state of a
540   policy may only output a single event and all tasks of that state may also only output that single event. In future
541   work, the concept of having a less restrictive trigger pattern will be examined.
542
543 .. container:: paragraph
544
545   A state that is the final state of a policy may output multiple events, and the task associated with the final state
546   outputs those events.
547
548 .. container:: paragraph
549
550   A *State* concept is keyed with a ``ReferenceKey`` key, which references the *Policy* concept that owns the state.
551   The *LocalName* field of the ``ReferenceKey`` holds the name of the state. As a state is part of a chain of states,
552   the *NextState* field of a state holds the ``ReferenceKey`` key of the state in the policy to execute after this
553   state.
554
555 .. container:: paragraph
556
557   The *Trigger* field of a state holds the ``ArtifactKey`` of the event that triggers this state. The *OutgoingEvents*
558   field holds the ``ArtifactKey`` references of all possible events that may be output from the state. This is a set
559   that is the union of all output events of all tasks of the state.
560
561 .. container:: paragraph
562
563   The *Task* concepts that hold the definitions of the task for the state are held as a set of ``ArtifactKey``
564   references in the state. The *DefaultTask* field holds a reference to the default task for the state, a task that is
565   executed if no task selection logic is specified. If the state has only one task, that task is the default task.
566
567 .. container:: paragraph
568
569   The *Logic* concept referenced by a state holds the task selection logic for a state. The task selection logic uses
570   the incoming context (parameters of the incoming event) and other context to determine the best task to use to
571   execute its goals. The state holds a set of references to *ContextItem* and *ContextItemTemplate* definitions for the
572   context used by its task selection logic.
573
574 *************
575 Writing Logic
576 *************
577
578 Writing APEX Task Logic
579 =======================
580
581 .. container:: paragraph
582
583   Task logic specifies the behavior of an Apex Task. This logic can be specified in a number of ways, exploiting
584   Apex’s plug-in architecture to support a range of logic executors. In Apex scripted Task Logic can be written in any
585   of these languages:
586
587 .. container:: ulist
588
589   -  ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__,
590
591   -  ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__,
592
593   -  ```JRuby`` <https://en.wikipedia.org/wiki/JRuby>`__ or
594
595   -  ```Jython`` <https://en.wikipedia.org/wiki/Jython>`__.
596
597 .. container:: paragraph
598
599   These languages were chosen because the scripts can be compiled into Java bytecode at runtime and then efficiently
600   executed natively in the JVM. Task Logic an also be written directly in Java but needs to be compiled, with the
601   resulting classes added to the classpath. There are also a number of other Task Logic types (e.g. Fuzzy Logic), but
602   these are not supported as yet. This guide will focus on the scripted Task Logic approaches, with MVEL and JavaScript
603   being our favorite languages. In particular this guide will focus on the Apex aspects of the scripts. However, this
604   guide does not attempt to teach you about the scripting languages themselves â€¦â€‹ that is up to you!
605
606 .. tip::
607   JVM-based scripting languages For more more information on scripting for the Java platform see:
608   https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
609
610 .. note::
611   What do Tasks do? The function of an Apex Task is to provide the logic that can be executed for an Apex State as one
612   of the steps in an Apex Policy. Each task receives some *incoming fields*, executes some logic (e.g: make a decision
613   based on *shared state* or *context*, *incoming fields*, *external context*, etc.), perhaps set some *shared state*
614   or *context* and then emits *outgoing fields* (in case of a single outgoing event), or a set of *outgoing fields*
615   (in case of multiple outgoing events). The state that uses the task is responsible for extracting the
616   *incoming fields* from the state input event. The state also has an *output mapper* associated with the task, and
617   this *output mapper* is responsible for mapping the *outgoing fields* from the task into an appropriate output event
618   for the state.
619
620 .. container:: paragraph
621
622   First lets start with a sample task, drawn from the "My First Apex Policy" example: The task "MorningBoozeCheck"
623   from the "My First Apex Policy" example is available in both MVEL and JavaScript:
624
625 .. container:: listingblock
626
627   .. container:: title
628
629     Javascript code for the ``MorningBoozeCheck`` task
630
631   .. container:: content
632
633     .. code:: javascript
634       :number-lines:
635
636       /*
637        * ============LICENSE_START=======================================================
638        *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
639        *  Modifications Copyright (C) 2020 Nordix Foundation.
640        * ================================================================================
641        * Licensed under the Apache License, Version 2.0 (the "License");
642        * you may not use this file except in compliance with the License.
643        * You may obtain a copy of the License at
644        *
645        *      http://www.apache.org/licenses/LICENSE-2.0
646        *
647        * Unless required by applicable law or agreed to in writing, software
648        * distributed under the License is distributed on an "AS IS" BASIS,
649        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
650        * See the License for the specific language governing permissions and
651        * limitations under the License.
652        *
653        * SPDX-License-Identifier: Apache-2.0
654        * ============LICENSE_END=========================================================
655        */
656
657       executor.logger.info("Task Execution: '"+executor.subject.id+"'. Input Fields: '"+executor.inFields+"'");
658
659       executor.outFields.put("amount"      , executor.inFields.get("amount"));
660       executor.outFields.put("assistant_ID", executor.inFields.get("assistant_ID"));
661       executor.outFields.put("notes"       , executor.inFields.get("notes"));
662       executor.outFields.put("quantity"    , executor.inFields.get("quantity"));
663       executor.outFields.put("branch_ID"   , executor.inFields.get("branch_ID"));
664       executor.outFields.put("item_ID"     , executor.inFields.get("item_ID"));
665       executor.outFields.put("time"        , executor.inFields.get("time"));
666       executor.outFields.put("sale_ID"     , executor.inFields.get("sale_ID"));
667
668       item_id = executor.inFields.get("item_ID");
669
670       //All times in this script are in GMT/UTC since the policy and events assume time is in GMT.
671       var timenow_gmt =  new Date(Number(executor.inFields.get("time")));
672
673       var midnight_gmt = new Date(Number(executor.inFields.get("time")));
674       midnight_gmt.setUTCHours(0,0,0,0);
675
676       var eleven30_gmt = new Date(Number(executor.inFields.get("time")));
677       eleven30_gmt.setUTCHours(11,30,0,0);
678
679       var timeformatter = new java.text.SimpleDateFormat("HH:mm:ss z");
680
681       var itemisalcohol = false;
682       if(item_id != null && item_id >=1000 && item_id < 2000)
683           itemisalcohol = true;
684
685       if( itemisalcohol
686           && timenow_gmt.getTime() >= midnight_gmt.getTime()
687           && timenow_gmt.getTime() <  eleven30_gmt.getTime()) {
688
689         executor.outFields.put("authorised", false);
690         executor.outFields.put("message", "Sale not authorised by policy task " +
691           executor.subject.taskName+ " for time " + timeformatter.format(timenow_gmt.getTime()) +
692           ". Alcohol can not be sold between " + timeformatter.format(midnight_gmt.getTime()) +
693           " and " + timeformatter.format(eleven30_gmt.getTime()));
694       }
695       else{
696         executor.outFields.put("authorised", true);
697         executor.outFields.put("message", "Sale authorised by policy task " +
698           executor.subject.taskName + " for time "+timeformatter.format(timenow_gmt.getTime()));
699       }
700
701       /*
702       This task checks if a sale request is for an item that is an alcoholic drink.
703       If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not
704       authorised. Otherwise the sale is authorised.
705       In this implementation we assume that items with item_ID value between 1000 and
706       2000 are all alcoholic drinks :-)
707       */
708
709       true;
710
711 .. container:: listingblock
712
713   .. container:: title
714
715     MVEL code for the ``MorningBoozeCheck`` task
716
717   .. container:: content
718
719     .. code:: javascript
720       :number-lines:
721
722       /*
723        * ============LICENSE_START=======================================================
724        *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
725        *  Modifications Copyright (C) 2020 Nordix Foundation.
726        * ================================================================================
727        * Licensed under the Apache License, Version 2.0 (the "License");
728        * you may not use this file except in compliance with the License.
729        * You may obtain a copy of the License at
730        *
731        *      http://www.apache.org/licenses/LICENSE-2.0
732        *
733        * Unless required by applicable law or agreed to in writing, software
734        * distributed under the License is distributed on an "AS IS" BASIS,
735        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
736        * See the License for the specific language governing permissions and
737        * limitations under the License.
738        *
739        * SPDX-License-Identifier: Apache-2.0
740        * ============LICENSE_END=========================================================
741        */
742       import java.util.Date;
743       import java.util.Calendar;
744       import java.util.TimeZone;
745       import java.text.SimpleDateFormat;
746
747       logger.info("Task Execution: '"+subject.id+"'. Input Fields: '"+inFields+"'");
748
749       outFields.put("amount"      , inFields.get("amount"));
750       outFields.put("assistant_ID", inFields.get("assistant_ID"));
751       outFields.put("notes"       , inFields.get("notes"));
752       outFields.put("quantity"    , inFields.get("quantity"));
753       outFields.put("branch_ID"   , inFields.get("branch_ID"));
754       outFields.put("item_ID"     , inFields.get("item_ID"));
755       outFields.put("time"        , inFields.get("time"));
756       outFields.put("sale_ID"     , inFields.get("sale_ID"));
757
758       item_id = inFields.get("item_ID");
759
760       //The events used later to test this task use GMT timezone!
761       gmt = TimeZone.getTimeZone("GMT");
762       timenow = Calendar.getInstance(gmt);
763       df = new SimpleDateFormat("HH:mm:ss z");
764       df.setTimeZone(gmt);
765       timenow.setTimeInMillis(inFields.get("time"));
766
767       midnight = timenow.clone();
768       midnight.set(
769           timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),
770           timenow.get(Calendar.DATE),0,0,0);
771       eleven30 = timenow.clone();
772       eleven30.set(
773           timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),
774           timenow.get(Calendar.DATE),11,30,0);
775
776       itemisalcohol = false;
777       if(item_id != null && item_id >=1000 && item_id < 2000)
778           itemisalcohol = true;
779
780       if( itemisalcohol
781           && timenow.after(midnight) && timenow.before(eleven30)){
782         outFields.put("authorised", false);
783         outFields.put("message", "Sale not authorised by policy task "+subject.taskName+
784           " for time "+df.format(timenow.getTime())+
785           ". Alcohol can not be sold between "+df.format(midnight.getTime())+
786           " and "+df.format(eleven30.getTime()));
787         return true;
788       }
789       else{
790         outFields.put("authorised", true);
791         outFields.put("message", "Sale authorised by policy task "+subject.taskName+
792           " for time "+df.format(timenow.getTime()));
793         return true;
794       }
795
796       /*
797       This task checks if a sale request is for an item that is an alcoholic drink.
798       If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not
799       authorised. Otherwise the sale is authorised.
800       In this implementation we assume that items with item_ID value between 1000 and
801       2000 are all alcoholic drinks :-)
802       */
803
804 .. container:: paragraph
805
806   The role of the task in this simple example is to copy the values in the incoming fields into the outgoing
807   fields, then examine the values in some incoming fields (``item_id`` and ``time``), then set the values in some
808   other outgoing fields (``authorised`` and ``message``).
809
810 .. container:: paragraph
811
812   Both MVEL and JavaScript like most JVM-based scripting languages can use standard Java libraries to perform
813   complex tasks. Towards the top of the scripts you will see how to import Java classes and packages to be used
814   directly in the logic. Another thing to notice is that Task Logic should return a ``java.lang.Boolean`` value
815   ``true`` if the logic executed correctly. If the logic fails for some reason then ``false`` can be returned, but
816   this will cause the policy invoking this task will fail and exit.
817
818 .. note::
819   How to return a value from task logic
820   Some languages explicitly support returning values from the script (e.g. MVEL and JRuby) using an explicit
821   return statement (e.g. ``return true``), other languages do not (e.g. Jython). For
822   languages that do not support the ``return`` statement, a special field called ``returnValue`` must be
823   created to hold the result of the task logic operation (i.e. assign a ``java.lang.Boolean``
824   value to the ``returnValue`` field before completing the task).
825   Also, in MVEL if there is no explicit return statement then the return value of the last executed statement will
826   return (e.g. the statement a=(1+2) will return the value 3).
827
828   For Javascript, the last statement of a script must be a statement that evaluates to *true* or *false*, indicating
829   whether the script executed correctly or not. In the case where the script always executes to compeletion
830   sucessfully, simply add a last line with the statement *true'*. In cases where success or failure is assessed in the
831   script, create a boolean
832   local variable with a name such as ``returnvalue``. In the execution of the script, set ``returnValue`` to be ``true``
833   or ``false`` as appropriate. The last line of the scritp tehn should simply be ``returnValue;``, which returns the
834   value of ``returnValue``.
835
836 .. container:: paragraph
837
838   Besides these imported classes and normal language features Apex provides some natively available parameters
839   and functions that can be used directly. At run-time these parameters are populated by the Apex execution
840   environment and made natively available to logic scripts each time the logic script is invoked. (These can be
841   accessed using the ``executor`` keyword for most languages, or can be accessed directly without the
842   ``executor`` keyword in MVEL):
843
844 Table 1. The ``executor`` Fields / Methods
845
846   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
847   | Name                                                | Type                                                                     | Java type                     | Description                                                                      |
848   +=====================================================+==========================================================================+===============================+==================================================================================+
849   | inFields                                            | Fields                                                                   | java.util.Map <String,Object> |The incoming task fields, implemented as a standard Java (unmodifiable) Map       |
850   |                                                     |                                                                          |                               |                                                                                  |
851   |                                                     |                                                                          |                               |**Example:**                                                                      |
852   |                                                     |                                                                          |                               |                                                                                  |
853   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
854   |                                                     |                                                                          |                               |                                                                                  |
855   |                                                     |                                                                          |                               |  executor.logger.debug("Incoming fields: " +executor.inFields.entrySet());       |
856   |                                                     |                                                                          |                               |  var item_id = executor.incomingFields["item_ID"];                               |
857   |                                                     |                                                                          |                               |  if (item_id >=1000) { ... }                                                     |
858   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
859   | outFields                                           | Fields                                                                   | java.util.Map <String,Object> |The outgoing task fields. This is implemented as a standard initially empty Java  |
860   |                                                     |                                                                          |                               |(modifiable) Map. To create a new schema-compliant instance of a field object     |
861   |                                                     |                                                                          |                               |see the utility method subject.getOutFieldSchemaHelper() below that takes the     |
862   |                                                     |                                                                          |                               |fieldName as an argument.                                                         |
863   |                                                     |                                                                          |                               |                                                                                  |
864   |                                                     |                                                                          |                               |**Example:**                                                                      |
865   |                                                     |                                                                          |                               |                                                                                  |
866   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
867   |                                                     |                                                                          |                               |                                                                                  |
868   |                                                     |                                                                          |                               |  executor.outFields["authorised"] = false;                                       |
869   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
870   | outFieldsList                                       | Fields                                                                   | java.util.Collection          |The collection of outgoing task fields when there are multiple outputs from the   |
871   |                                                     |                                                                          |   <Map<String, Object>>       |final state. To create a new schema-compliant instance of a field, see the        |
872   |                                                     |                                                                          |                               |utility method subject.getOutFieldSchemaHelper() below that takes eventName and   |
873   |                                                     |                                                                          |                               |fieldName as arguments.                                                           |
874   |                                                     |                                                                          |                               |To add the set of output fields to the outFieldsList, the utility method          |
875   |                                                     |                                                                          |                               |executor.addFieldsToOutput can be used as shown below.                            |
876   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
877   | void addFieldsToOutput(Map<String, Object> fields)  |A utility method to add fields to outgoing fields.                        |                               |                                                                                  |
878   |                                                     |When there are multiple output events emitted from the task associated    |                               |                                                                                  |
879   |                                                     |with a final state, this utility method can be used to add the            |                               |                                                                                  |
880   |                                                     |corresponding fields to the outFieldsList.                                |                               |                                                                                  |
881   |                                                     |                                                                          |                               |                                                                                  |
882   |                                                     |**Example:**                                                              |                               |                                                                                  |
883   |                                                     |                                                                          |                               |                                                                                  |
884   |                                                     |.. code:: javascript                                                      |                               |                                                                                  |
885   |                                                     |                                                                          |                               |                                                                                  |
886   |                                                     |  var cdsRequestEventFields = java.util.HashMap();                        |                               |                                                                                  |
887   |                                                     |  var actionIdentifiers = executor.subject.getOutFieldSchemaHelper        |                               |                                                                                  |
888   |                                                     |  ("CDSRequestEvent","actionIdentifiers").createNewInstance();            |                               |                                                                                  |
889   |                                                     |  cdsRequestEventFields.put("actionIdentifiers", actionIdentifiers);      |                               |                                                                                  |
890   |                                                     |  executor.addFieldsToOutput(cdsRequestEventFields);                      |                               |                                                                                  |
891   |                                                     |                                                                          |                               |                                                                                  |
892   |                                                     |  var logEventFields = java.util.HashMap();                               |                               |                                                                                  |
893   |                                                     |  logEventFields.put("status", "FINAL_SUCCESS");                          |                               |                                                                                  |
894   |                                                     |  executor.addFieldsToOutput(logEventFields);                             |                               |                                                                                  |
895   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
896   | logger                                              | Logger                                                                   | org.slf4j.ext.XLogger         |A helpful logger                                                                  |
897   |                                                     |                                                                          |                               |                                                                                  |
898   |                                                     |                                                                          |                               |**Example:**                                                                      |
899   |                                                     |                                                                          |                               |                                                                                  |
900   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
901   |                                                     |                                                                          |                               |                                                                                  |
902   |                                                     |                                                                          |                               |  executor.logger.info("Executing task: " +executor.subject.id);                  |
903   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
904   | TRUE/FALSE                                          | boolean                                                                  | java.lang.Boolean             |2 helpful constants. These are useful to retrieve correct return  values for the  |
905   |                                                     |                                                                          |                               |task logic                                                                        |
906   |                                                     |                                                                          |                               |                                                                                  |
907   |                                                     |                                                                          |                               |**Example:**                                                                      |
908   |                                                     |                                                                          |                               |                                                                                  |
909   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
910   |                                                     |                                                                          |                               |                                                                                  |
911   |                                                     |                                                                          |                               |  var returnValue = executor.isTrue;                                              |
912   |                                                     |                                                                          |                               |  var returnValueType = Java.type("java.lang.Boolean");                           |
913   |                                                     |                                                                          |                               |  var returnValue = new returnValueType(true);                                    |
914   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
915   | subject                                             | Task                                                                     | TaskFacade                    |This provides some useful information about the task that contains this task      |
916   |                                                     |                                                                          |                               |logic. This object has some useful fields and methods :                           |
917   |                                                     |                                                                          |                               |                                                                                  |
918   |                                                     |                                                                          |                               |.. container:: ulist                                                              |
919   |                                                     |                                                                          |                               |                                                                                  |
920   |                                                     |                                                                          |                               |  - **AxTask task** to get access to the full task definition of the host task    |
921   |                                                     |                                                                          |                               |                                                                                  |
922   |                                                     |                                                                          |                               |  - **String getTaskName()** to get the name of the host task                     |
923   |                                                     |                                                                          |                               |                                                                                  |
924   |                                                     |                                                                          |                               |  - **String getId()** to get the ID of the host task                             |
925   |                                                     |                                                                          |                               |                                                                                  |
926   |                                                     |                                                                          |                               |  - **SchemaHelper getInFieldSchemaHelper( String fieldName )** to                |
927   |                                                     |                                                                          |                               |    get a ``SchemaHelper`` helper object to manipulate incoming                   |
928   |                                                     |                                                                          |                               |    task fields in a schema-aware manner                                          |
929   |                                                     |                                                                          |                               |                                                                                  |
930   |                                                     |                                                                          |                               |  - **SchemaHelper getOutFieldSchemaHelper( String fieldName )** to               |
931   |                                                     |                                                                          |                               |    get a ``SchemaHelper`` helper object to manipulate outgoing                   |
932   |                                                     |                                                                          |                               |    task fields in a schema-aware manner, e.g. to instantiate new                 |
933   |                                                     |                                                                          |                               |    schema-compliant field objects to populate the                                |
934   |                                                     |                                                                          |                               |    ``executor.outFields`` outgoing fields map. This can be used only when there  |
935   |                                                     |                                                                          |                               |    is a single outgoing event from a task.                                       |
936   |                                                     |                                                                          |                               |                                                                                  |
937   |                                                     |                                                                          |                               |  - **SchemaHelper getOutFieldSchemaHelper( String eventname, String fieldName )**|
938   |                                                     |                                                                          |                               |    to get a ``SchemaHelper`` helper object to manipulate outgoing                |
939   |                                                     |                                                                          |                               |    task fields in a schema-aware manner, e.g. to instantiate new                 |
940   |                                                     |                                                                          |                               |    schema-compliant field objects to populate the                                |
941   |                                                     |                                                                          |                               |    ``executor.outFieldsList`` collection of outgoing fields map. This must be    |
942   |                                                     |                                                                          |                               |    used in case of multiple outgoing events from a task, as the intention is to  |
943   |                                                     |                                                                          |                               |    fetch the schema of a field associated to one of the expected events.         |
944   |                                                     |                                                                          |                               |    This method works fine in case of single outgoing event too, but the previous |
945   |                                                     |                                                                          |                               |    method is enough as the field anyway belongs to the single event.             |
946   |                                                     |                                                                          |                               |                                                                                  |
947   |                                                     |                                                                          |                               |**Example:**                                                                      |
948   |                                                     |                                                                          |                               |                                                                                  |
949   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
950   |                                                     |                                                                          |                               |                                                                                  |
951   |                                                     |                                                                          |                               |  executor.logger.info("Task name: " + executor.subject.getTaskName());           |
952   |                                                     |                                                                          |                               |  executor.logger.info("Task id: " + executor.subject.getId());                   |
953   |                                                     |                                                                          |                               |  executor.outFields["authorised"] = executor.subject                             |
954   |                                                     |                                                                          |                               |    .getOutFieldSchemaHelper("authorised").createNewInstance("false");            |
955   |                                                     |                                                                          |                               |                                                                                  |
956   |                                                     |                                                                          |                               |  var actionIdentifiers = executor.subject.getOutFieldSchemaHelper                |
957   |                                                     |                                                                          |                               |    ("CDSRequestEvent","actionIdentifiers").createNewInstance();                  |
958   |                                                     |                                                                          |                               |  actionIdentifiers.put("blueprintName", "sample-bp");                            |
959   |                                                     |                                                                          |                               |  var cdsRequestEventFields = java.util.HashMap();                                |
960   |                                                     |                                                                          |                               |  cdsRequestEventFields.put("actionIdentifiers", actionIdentifiers);              |
961   |                                                     |                                                                          |                               |  executor.addFieldsToOutput(cdsRequestEventFields);                              |
962   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
963   | ContextAlbum getContextAlbum(String ctxtAlbumName ) |A utility method to retrieve a ``ContextAlbum`` for use in the task.      |                               |                                                                                  |
964   |                                                     |This is how you access the context used by the task. The returned         |                               |                                                                                  |
965   |                                                     |``ContextAlbum`` implements the ``java.util.Map <String,Object>``         |                               |                                                                                  |
966   |                                                     |interface to get and set context as appropriate. The returned             |                               |                                                                                  |
967   |                                                     |``ContextAlbum`` also has methods to lock context albums, get             |                               |                                                                                  |
968   |                                                     |information about the schema of the items to be stored in a context       |                               |                                                                                  |
969   |                                                     |album, and get a ``SchemaHelper`` to manipulate context album items. How  |                               |                                                                                  |
970   |                                                     |to define and use context in a task is described in the Apex              |                               |                                                                                  |
971   |                                                     |Programmer’s Guide and in the My First Apex Policy guide.                 |                               |                                                                                  |
972   |                                                     |                                                                          |                               |                                                                                  |
973   |                                                     |**Example:**                                                              |                               |                                                                                  |
974   |                                                     |                                                                          |                               |                                                                                  |
975   |                                                     |.. code:: javascript                                                      |                               |                                                                                  |
976   |                                                     |                                                                          |                               |                                                                                  |
977   |                                                     |  var bkey = executor.inFields.get("branch_ID");                          |                               |                                                                                  |
978   |                                                     |  var cnts = executor.getContextMap("BranchCounts");                      |                               |                                                                                  |
979   |                                                     |  cnts.lockForWriting(bkey);                                              |                               |                                                                                  |
980   |                                                     |  cnts.put(bkey, cnts.get(bkey) + 1);                                     |                               |                                                                                  |
981   |                                                     |  cnts.unlockForWriting(bkey);                                            |                               |                                                                                  |
982   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
983
984 Writing APEX Task Selection Logic
985 =================================
986
987 .. container:: paragraph
988
989   The function of Task Selection Logic is to choose which task should be executed for an Apex State as one of
990   the steps in an Apex Policy. Since each state must define a default task there is no need for Task Selection
991   Logic unless the state uses more than one task. This logic can be specified in a number of ways, exploiting
992   Apex’s plug-in architecture to support a range of logic executors. In Apex scripted Task Selection Logic can be
993   written in any of these languages:
994
995 .. container:: ulist
996
997   -  ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__,
998
999   -  ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__,
1000
1001   -  ```JRuby`` <https://en.wikipedia.org/wiki/JRuby>`__ or
1002
1003   -  ```Jython`` <https://en.wikipedia.org/wiki/Jython>`__.
1004
1005 .. container:: paragraph
1006
1007   These languages were chosen because the scripts can be compiled into Java bytecode at runtime and then
1008   efficiently executed natively in the JVM. Task Selection Logic an also be written directly in Java but needs to
1009   be compiled, with the resulting classes added to the classpath. There are also a number of other Task Selection
1010   Logic types but these are not supported as yet. This guide will focus on the scripted Task Selection Logic
1011   approaches, with MVEL and JavaScript being our favorite languages. In particular this guide will focus on the
1012   Apex aspects of the scripts. However, this guide does not attempt to teach you about the scripting languages
1013   themselves â€¦â€‹ that is up to you!
1014
1015 .. tip::
1016   JVM-based scripting languages
1017   For more more information on Scripting for the Java platform see:
1018   https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
1019
1020 .. note::
1021   What does Task Selection Logic do?
1022   When an Apex state references multiple tasks, there must be a way to dynamically decide
1023   which task should be chosen and executed. This can depend on the many factors, e.g. the
1024   *incoming event for the state*, *shared state* or *context*, *external context*,
1025   etc.. This is the function of a state’s Task Selection Logic. Obviously, if there is
1026   only one task then Task only one task then Task Selection Logic is not needed.
1027   Each state must also select one of the tasks a the *default state*. If the Task
1028   Selection Logic is unable to select an appropriate task, then it should select the
1029   *default task*. Once the task has been selected the Apex Engine will then execute that task.
1030
1031 .. container:: paragraph
1032
1033   First lets start with some simple Task Selection Logic, drawn from the "My First Apex Policy" example: The Task
1034   Selection Logic from the "My First Apex Policy" example is specified in JavaScript here:
1035
1036 .. container:: listingblock
1037
1038   .. container:: title
1039
1040     Javascript code for the "My First Policy" Task Selection Logic
1041
1042   .. container:: content
1043
1044     .. code:: javascript
1045
1046       /*
1047        * ============LICENSE_START=======================================================
1048        *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
1049        *  Modifications Copyright (C) 2020 Nordix Foundation.
1050        * ================================================================================
1051        * Licensed under the Apache License, Version 2.0 (the "License");
1052        * you may not use this file except in compliance with the License.
1053        * You may obtain a copy of the License at
1054        *
1055        *      http://www.apache.org/licenses/LICENSE-2.0
1056        *
1057        * Unless required by applicable law or agreed to in writing, software
1058        * distributed under the License is distributed on an "AS IS" BASIS,
1059        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1060        * See the License for the specific language governing permissions and
1061        * limitations under the License.
1062        *
1063        * SPDX-License-Identifier: Apache-2.0
1064        * ============LICENSE_END=========================================================
1065        */
1066
1067       executor.logger.info("Task Selection Execution: '"+executor.subject.id+
1068           "'. Input Event: '"+executor.inFields+"'");
1069
1070       branchid = executor.inFields.get("branch_ID");
1071       taskorig = executor.subject.getTaskKey("MorningBoozeCheck");
1072       taskalt = executor.subject.getTaskKey("MorningBoozeCheckAlt1");
1073       taskdef = executor.subject.getDefaultTaskKey();
1074
1075       if(branchid >=0 && branchid <1000){
1076         taskorig.copyTo(executor.selectedTask);
1077       }
1078       else if (branchid >=1000 && branchid <2000){
1079         taskalt.copyTo(executor.selectedTask);
1080       }
1081       else{
1082         taskdef.copyTo(executor.selectedTask);
1083       }
1084
1085       /*
1086       This task selection logic selects task "MorningBoozeCheck" for branches with
1087       0<=branch_ID<1000 and selects task "MorningBoozeCheckAlt1" for branches with
1088       1000<=branch_ID<2000. Otherwise the default task is selected.
1089       In this case the default task is also "MorningBoozeCheck"
1090       */
1091
1092       true;
1093
1094 .. container:: paragraph
1095
1096   The role of the Task Selection Logic in this simple example is to examine the value in one incoming field
1097   (``branchid``), then depending on that field’s value set the value for the selected task to the appropriate task
1098   (``MorningBoozeCheck``, ``MorningBoozeCheckAlt1``, or the default task).
1099
1100 .. container:: paragraph
1101
1102   Another thing to notice is that Task Selection Logic should return a ``java.lang.Boolean`` value ``true`` if
1103   the logic executed correctly. If the logic fails for some reason then ``false`` can be returned, but this will
1104   cause the policy invoking this task will fail and exit.
1105
1106 .. note::
1107   How to return a value from Task Selection Logic
1108   Some languages explicitly support returning values from the script (e.g. MVEL and
1109   JRuby) using an explicit return statement (e.g. ``return true``), other languages do not (e.g.
1110   JavaScript and Jython). For languages that do not support the ``return`` statement, a special field called
1111   ``returnValue`` must be created to hold the result of the task logic operation (i.e. assign a ``java.lang.Boolean``
1112   value to the ``returnValue`` field before completing the task).
1113   Also, in MVEL if there is not explicit return statement then the return value of the last executed statement will
1114   return (e.g. the statement a=(1+2) will return the value 3).
1115
1116 .. container:: paragraph
1117
1118   Each of the scripting languages used in Apex can import and use standard Java libraries to perform complex tasks.
1119   Besides imported classes and normal language features Apex provides some natively available parameters and functions
1120   that can be used directly. At run-time these parameters are populated by the Apex execution environment and made
1121   natively available to logic scripts each time the logic script is invoked. (These can be accessed using the
1122   ``executor`` keyword for most languages, or can be accessed directly without the ``executor`` keyword in MVEL):
1123
1124 Table 2. The ``executor`` Fields / Methods
1125   +-----------------------------------+------------------------------------+
1126   | Unix, Cygwin                      | Windows                            |
1127   +===================================+====================================+
1128   |.. container:: content             |.. container:: content              |
1129   |                                   |                                    |
1130   |  .. code:: bash                   |  .. code:: bash                    |
1131   |    :number-lines:                 |    :number-lines:                  |
1132   |                                   |                                    |
1133   |    >c:                            |    # cd /usr/local/src/apex-pdp    |
1134   |    >cd \dev\apex                  |    # mvn clean install -DskipTests |
1135   |    >mvn clean install -DskipTests |                                    |
1136   +-----------------------------------+------------------------------------+
1137
1138   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1139   | Name                                                | Type                                                                     | Java type                     | Description                                                                      |
1140   +=====================================================+==========================================================================+===============================+==================================================================================+
1141   | inFields                                            | Fields                                                                   | java.util.Map <String,Object> | All fields in the state’s incoming event. This is implemented as a standard Java |
1142   |                                                     |                                                                          |                               | Java (unmodifiable) Map                                                          |
1143   |                                                     |                                                                          |                               |                                                                                  |
1144   |                                                     |                                                                          |                               | **Example:**                                                                     |
1145   |                                                     |                                                                          |                               |                                                                                  |
1146   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1147   |                                                     |                                                                          |                               |                                                                                  |
1148   |                                                     |                                                                          |                               |   executor.logger.debug("Incoming fields: " + executor.inFields.entrySet());     |
1149   |                                                     |                                                                          |                               |   var item_id = executor.incomingFields["item_ID"];                              |
1150   |                                                     |                                                                          |                               |   if (item_id >=1000) { ... }                                                    |
1151   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1152   | outFields                                           | Fields                                                                   | java.util.Map <String,Object> | The outgoing task fields. This is implemented as a standard initially empty Java |
1153   |                                                     |                                                                          |                               | (modifiable) Map. To create a new schema-compliant instance of a field object    |
1154   |                                                     |                                                                          |                               | see the utility method subject.getOutFieldSchemaHelper() below                   |
1155   |                                                     |                                                                          |                               |                                                                                  |
1156   |                                                     |                                                                          |                               | **Example:**                                                                     |
1157   |                                                     |                                                                          |                               |                                                                                  |
1158   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1159   |                                                     |                                                                          |                               |                                                                                  |
1160   |                                                     |                                                                          |                               |   executor.outFields["authorised"] = false;                                      |
1161   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1162   | logger                                              | Logger                                                                   | org.slf4j.ext.XLogger         | A helpful logger                                                                 |
1163   |                                                     |                                                                          |                               |                                                                                  |
1164   |                                                     |                                                                          |                               | **Example:**                                                                     |
1165   |                                                     |                                                                          |                               |                                                                                  |
1166   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1167   |                                                     |                                                                          |                               |                                                                                  |
1168   |                                                     |                                                                          |                               |   executor.logger.info("Executing task: "                                        |
1169   |                                                     |                                                                          |                               |   +executor.subject.id);                                                         |
1170   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1171   | TRUE/FALSE                                          | boolean                                                                  | java.lang.Boolean             | 2 helpful constants. These are useful to retrieve correct return  values for the |
1172   |                                                     |                                                                          |                               | task logic                                                                       |
1173   |                                                     |                                                                          |                               |                                                                                  |
1174   |                                                     |                                                                          |                               | **Example:**                                                                     |
1175   |                                                     |                                                                          |                               |                                                                                  |
1176   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1177   |                                                     |                                                                          |                               |                                                                                  |
1178   |                                                     |                                                                          |                               |   var returnValue = executor.isTrue;                                             |
1179   |                                                     |                                                                          |                               |   var returnValueType = Java.type("java.lang.Boolean");                          |
1180   |                                                     |                                                                          |                               |   var returnValue = new returnValueType(true);                                   |
1181   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1182   | subject                                             | Task                                                                     | TaskFacade                    | This provides some useful information about the task that contains this task     |
1183   |                                                     |                                                                          |                               | logic. This object has some useful fields and methods :                          |
1184   |                                                     |                                                                          |                               |                                                                                  |
1185   |                                                     |                                                                          |                               | .. container:: ulist                                                             |
1186   |                                                     |                                                                          |                               |                                                                                  |
1187   |                                                     |                                                                          |                               |   - **AxTask task** to get access to the full task definition of the host task   |
1188   |                                                     |                                                                          |                               |                                                                                  |
1189   |                                                     |                                                                          |                               |   - **String getTaskName()** to get the name of the host task                    |
1190   |                                                     |                                                                          |                               |                                                                                  |
1191   |                                                     |                                                                          |                               |   - **String getId()** to get the ID of the host task                            |
1192   |                                                     |                                                                          |                               |                                                                                  |
1193   |                                                     |                                                                          |                               |   - **SchemaHelper getInFieldSchemaHelper( String fieldName )** to               |
1194   |                                                     |                                                                          |                               |     get a ``SchemaHelper`` helper object to manipulate incoming                  |
1195   |                                                     |                                                                          |                               |     task fields in a schema-aware manner                                         |
1196   |                                                     |                                                                          |                               |                                                                                  |
1197   |                                                     |                                                                          |                               |   - **SchemaHelper getOutFieldSchemaHelper( String fieldName )** to              |
1198   |                                                     |                                                                          |                               |     get a ``SchemaHelper`` helper object to manipulate outgoing                  |
1199   |                                                     |                                                                          |                               |     task fields in a schema-aware manner, e.g. to instantiate new                |
1200   |                                                     |                                                                          |                               |     schema-compliant field objects to populate the                               |
1201   |                                                     |                                                                          |                               |     ``executor.outFields`` outgoing fields map                                   |
1202   |                                                     |                                                                          |                               |                                                                                  |
1203   |                                                     |                                                                          |                               | **Example:**                                                                     |
1204   |                                                     |                                                                          |                               |                                                                                  |
1205   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1206   |                                                     |                                                                          |                               |                                                                                  |
1207   |                                                     |                                                                          |                               |   executor.logger.info("Task name: " + executor.subject.getTaskName());          |
1208   |                                                     |                                                                          |                               |   executor.logger.info("Task id: " + executor.subject.getId());                  |
1209   |                                                     |                                                                          |                               |   executor.outFields["authorised"] = executor.subject                            |
1210   |                                                     |                                                                          |                               |     .getOutFieldSchemaHelper("authorised")                                       |
1211   |                                                     |                                                                          |                               |     .createNewInstance("false");                                                 |
1212   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1213   | parameters                                          | Fields                                                                   | java.util.Map <String,String> | All parameters in the current task. This is implemented as a standard Java Map.  |
1214   |                                                     |                                                                          |                               |                                                                                  |
1215   |                                                     |                                                                          |                               | **Example:**                                                                     |
1216   |                                                     |                                                                          |                               |                                                                                  |
1217   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1218   |                                                     |                                                                          |                               |                                                                                  |
1219   |                                                     |                                                                          |                               |   executor.parameters.get("ParameterKey1"))                                      |
1220   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1221   | ContextAlbum getContextAlbum(String ctxtAlbumName ) | A utility method to retrieve a ``ContextAlbum`` for use in the task.     |                               |                                                                                  |
1222   |                                                     | This is how you access the context used by the task. The returned        |                               |                                                                                  |
1223   |                                                     | ``ContextAlbum`` implements the ``java.util.Map <String,Object>``        |                               |                                                                                  |
1224   |                                                     | interface to get and set context as appropriate. The returned            |                               |                                                                                  |
1225   |                                                     | ``ContextAlbum`` also has methods to lock context albums, get            |                               |                                                                                  |
1226   |                                                     | information about the schema of the items to be stored in a context      |                               |                                                                                  |
1227   |                                                     | album, and get a ``SchemaHelper`` to manipulate context album items. How |                               |                                                                                  |
1228   |                                                     | to define and use context in a task is described in the Apex             |                               |                                                                                  |
1229   |                                                     | Programmer’s Guide and in the My First Apex Policy guide.                |                               |                                                                                  |
1230   |                                                     |                                                                          |                               |                                                                                  |
1231   |                                                     | **Example:**                                                             |                               |                                                                                  |
1232   |                                                     |                                                                          |                               |                                                                                  |
1233   |                                                     | .. code:: javascript                                                     |                               |                                                                                  |
1234   |                                                     |                                                                          |                               |                                                                                  |
1235   |                                                     |   var bkey = executor.inFields.get("branch_ID");                         |                               |                                                                                  |
1236   |                                                     |   var cnts = executor.getContextMap("BranchCounts");                     |                               |                                                                                  |
1237   |                                                     |   cnts.lockForWriting(bkey);                                             |                               |                                                                                  |
1238   |                                                     |   cnts.put(bkey, cnts.get(bkey) + 1);                                    |                               |                                                                                  |
1239   |                                                     |   cnts.unlockForWriting(bkey);                                           |                               |                                                                                  |
1240   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1241
1242 Logic Cheat Sheet
1243 =================
1244
1245 .. container:: paragraph
1246
1247   Examples given here use Javascript (if not stated otherwise), other execution environments will be similar.
1248
1249 Finish Logic with Success or Error
1250 ----------------------------------
1251
1252 .. container:: paragraph
1253
1254   To finish logic, i.e. return to APEX, with success use the following line close to the end of the logic.
1255
1256 .. container:: listingblock
1257
1258   .. container:: title
1259
1260     JS Success
1261
1262   .. container:: content
1263
1264     .. code:: javascript
1265
1266       true;
1267
1268 .. container:: paragraph
1269
1270   To notify a problem, finish with an error.
1271
1272   .. container:: listingblock
1273
1274     .. container:: title
1275
1276       JS Fail
1277
1278     .. container:: content
1279
1280       .. code:: javascript
1281
1282         false;
1283
1284 Logic Logging
1285 -------------
1286
1287 .. container:: paragraph
1288
1289   Logging can be made easy using a local variable for the logger. Line 1 below does that. Then we start
1290   with a trace log with the task (or task logic) identifier followed by the infields.
1291
1292 .. container:: listingblock
1293
1294   .. container:: title
1295
1296     JS Logging
1297
1298   .. container:: content
1299
1300     .. code:: javascript
1301
1302       var logger = executor.logger;
1303       logger.trace("start: " + executor.subject.id);
1304       logger.trace("-- infields: " + executor.inFields);
1305
1306 .. container:: paragraph
1307
1308   For larger logging blocks you can use the standard logging API to detect log levels, for instance:
1309
1310   .. container:: listingblock
1311
1312     .. container:: title
1313
1314       JS Logging Blocks
1315
1316     .. container:: content
1317
1318       .. code:: javascript
1319
1320         if(logger.isTraceEnabled()){
1321           // trace logging block here
1322         }
1323
1324 .. container:: paragraph
1325
1326   Note: the shown logger here logs to ``org.onap.policy.apex.executionlogging``. The behavior of the actual logging can
1327   be specified in the ``$APEX_HOME/etc/logback.xml``.
1328
1329 .. container:: paragraph
1330
1331   If you want to log into the APEX root logger (which is sometimes necessary to report serious logic errors to the top),
1332   then import the required class and use this logger.
1333
1334 .. container:: listingblock
1335
1336   .. container:: title
1337
1338     JS Root Logger
1339
1340   .. container:: content
1341
1342     .. code:: javascript
1343
1344       var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
1345       rootLogger.error("Serious error in logic detected: " + executor.subject.id);
1346
1347 Accessing TaskParameters
1348 ------------------------
1349
1350 .. container:: paragraph
1351
1352   TaskParameters available in a Task can be accessed in the logic. The parameters in each task are made
1353   available at the executor level. This example assumes a parameter with key ``ParameterKey1``.
1354
1355   .. container:: listingblock
1356
1357     .. container:: title
1358
1359       JS TaskParameter value
1360
1361     .. container:: content
1362
1363       .. code:: javascript
1364
1365         executor.parameters.get("ParameterKey1"))
1366
1367 .. container:: paragraph
1368
1369   Alternatively, the task parameters can also be accessed from the task object.
1370
1371   .. container:: listingblock
1372
1373     .. container:: title
1374
1375       JS TaskParameter value using task object
1376
1377     .. container:: content
1378
1379       .. code:: javascript
1380
1381         executor.subject.task.getTaskParameters.get("ParameterKey1").getTaskParameterValue()
1382
1383 Local Variable for Infields
1384 ---------------------------
1385
1386 .. container:: paragraph
1387
1388   It is a good idea to use local variables for ``infields``. This avoids long code lines and policy
1389   evolution. The following example assumes infields named ``nodeName`` and ``nodeAlias``.
1390
1391  .. container:: listingblock
1392
1393    .. container:: title
1394
1395      JS Infields Local Var
1396
1397   .. container:: content
1398
1399     .. code:: javascript
1400
1401       var ifNodeName = executor.inFields["nodeName"];
1402       var ifNodeAlias = executor.inFields["nodeAlias"];
1403
1404 Local Variable for Context Albums
1405 ---------------------------------
1406
1407 .. container:: paragraph
1408
1409   Similar to the ``infields`` it is good practice to use local variables for context albums as well. The
1410   following example assumes that a task can access a context album ``albumTopoNodes``. The second line gets a
1411   particular node from this context album.
1412
1413 .. container:: listingblock
1414
1415   .. container:: title
1416
1417     JS Infields Local Var
1418
1419   .. container:: content
1420
1421     .. code:: javascript
1422
1423       var albumTopoNodes = executor.getContextAlbum("albumTopoNodes");
1424       var ctxtNode = albumTopoNodes.get(ifNodeName);
1425
1426 Set Outfields in Logic
1427 ----------------------
1428
1429 .. container:: paragraph
1430
1431   The task logic needs to set outfields with content generated. The exception are outfields that are a
1432   direct copy from an infield of the same name, APEX does that autmatically.
1433
1434 .. container:: listingblock
1435
1436   .. container:: title
1437
1438     JS Set Outfields
1439
1440   .. container:: content
1441
1442     .. code:: javascript
1443
1444       executor.outFields["report"] = "node ctxt :: added node " + ifNodeName;
1445
1446 Create a instance of an Outfield using Schemas
1447 ----------------------------------------------
1448
1449 .. container:: paragraph
1450
1451   If an outfield is not an atomic type (string, integer, etc.) but uses a complex schema (with a Java or
1452   Avro backend), APEX can help to create new instances. The ``executor`` provides a field called ``subject``,
1453   which provides a schem helper with an API for this.
1454
1455 .. container:: paragraph
1456
1457   If the backend is Java, then the Java class implementing the schema needs to be imported.
1458
1459 *Single outgoing event*
1460
1461 .. container:: paragraph
1462
1463   When there is a single outgoing event associated with a task, the fieldName alone is enough to fetch its schema.
1464   The following example assumes an outfield ``situation``. The ``subject`` method ``getOutFieldSchemaHelper()`` is used
1465   to create a new instance.
1466
1467 .. container:: listingblock
1468
1469   .. container:: title
1470
1471     JS Outfield Instance with Schema
1472
1473   .. container:: content
1474
1475     .. code:: javascript
1476
1477       var situation = executor.subject.getOutFieldSchemaHelper("situation").createNewInstance();
1478
1479 .. container:: paragraph
1480
1481   If the schema backend is Java, the new instance will be as implemented in the Java class. If the schema backend is
1482   Avro, the new instance will have all fields from the Avro schema specification, but set to ``null``. So any entry here
1483   needs to be done separately. For instance, the ``situation`` schema has a field ``problemID`` which we set.
1484
1485 .. container:: listingblock
1486
1487   .. container:: title
1488
1489     JS Outfield Instance with Schema, set
1490
1491   .. container:: content
1492
1493     .. code:: javascript
1494
1495       situation.put("problemID", "my-problem");
1496
1497 *Multiple outgoing events*
1498
1499 .. container:: paragraph
1500
1501   When there are multiple outgoing events associated with a task, the fieldName along with the eventName it belongs to
1502   are needed to fetch its schema.
1503   The following example assumes an outfield ``actionIdentifiers`` which belongs to ``CDSRequestEvent``.
1504   The ``subject`` method ``getOutFieldSchemaHelper()`` is used to create a new instance.
1505
1506 .. container:: listingblock
1507
1508   .. container:: content
1509
1510     .. code:: javascript
1511
1512       var actionIdentifiers = executor.subject.getOutFieldSchemaHelper("CDSRequestEvent", "actionIdentifiers").createNewInstance();
1513
1514 Create a instance of an Context Album entry using Schemas
1515 ---------------------------------------------------------
1516
1517 .. container:: paragraph
1518
1519   Context album instances can be created using very similar to the outfields. Here, the schema helper
1520   comes from the context album directly. The API of the schema helper is the same as for outfields.
1521
1522 .. container:: paragraph
1523
1524   If the backend is Java, then the Java class implementing the schema needs to be imported.
1525
1526 .. container:: paragraph
1527
1528   The following example creates a new instance of a context album instance named ``albumProblemMap``.
1529
1530 .. container:: listingblock
1531
1532   .. container:: title
1533
1534     JS Outfield Instance with Schema
1535
1536   .. container:: content
1537
1538     .. code:: javascript
1539
1540       var albumProblemMap = executor.getContextAlbum("albumProblemMap");
1541       var linkProblem = albumProblemMap.getSchemaHelper().createNewInstance();
1542
1543 .. container:: paragraph
1544
1545   This can of course be also done in a single call without the local variable for the context album.
1546
1547 .. container:: listingblock
1548
1549   .. container:: title
1550
1551     JS Outfield Instance with Schema, one line
1552
1553   .. container:: content
1554
1555     .. code:: javascript
1556
1557       var linkProblem = executor.getContextAlbum("albumProblemMap").getSchemaHelper().createNewInstance();
1558
1559 .. container:: paragraph
1560
1561   If the schema backend is Java, the new instance will be as implemented in the Java class. If the schema backend is
1562   Avro, the new instance will have all fields from the Avro schema specification, but set to ``null``. So any entry here
1563   needs to be done separately (see above in outfields for an example).
1564
1565 Enumerates
1566 ----------
1567
1568 .. container:: paragraph
1569
1570   When dealing with enumerates (Avro or Java defined), it is sometimes and in some execution
1571   environments necessary to convert them to a string. For example, assume an Avro enumerate schema as:
1572
1573 .. container:: listingblock
1574
1575   .. container:: title
1576
1577     Avro Enumerate Schema
1578
1579   .. container:: content
1580
1581     .. code:: javascript
1582
1583       {
1584         "type": "enum", "name": "Status", "symbols" : [
1585           "UP", "DOWN"
1586         ]
1587       }
1588
1589 .. container:: paragraph
1590
1591   Using a switch over a field initialized with this enumerate in Javascript will fail. Instead, use the ``toString`` method, for example:
1592
1593 .. container:: listingblock
1594
1595   .. container:: title
1596
1597     JS Outfield Instance with Schema, one line
1598
1599   .. container:: content
1600
1601     .. code:: javascript
1602
1603       var switchTest = executor.inFields["status"]; switch(switchTest.toString()){
1604         case "UP": ...; break; case "DOWN": ...; break; default: ...;
1605       }
1606
1607 MVEL Initialize Outfields First!
1608 --------------------------------
1609
1610 .. container:: paragraph
1611
1612   In MVEL, we observed a problem when accessing (setting) outfields without a prior access to them. So
1613   in any MVEL task logic, before setting any outfield, simply do a get (with any string), to load the outfields
1614   into the MVEL cache.
1615
1616 .. container:: listingblock
1617
1618   .. container:: title
1619
1620     MVEL Outfield Initialization
1621
1622   .. container:: content
1623
1624     .. code:: javascript
1625
1626       outFields.get("initialize outfields");
1627
1628 Using Java in Scripting Logic
1629 -----------------------------
1630
1631 .. container:: paragraph
1632
1633   Since APEX executes the logic inside a JVM, most scripting languages provide access to all standard
1634   Java classes. Simply add an import for the required class and then use it as in actual Java.
1635
1636 .. container:: paragraph
1637
1638   The following example imports ``java.util.arraylist`` into a Javascript logic, and then creates a new
1639   list.
1640
1641 .. container:: listingblock
1642
1643   .. container:: title
1644
1645     JS Import ArrayList
1646
1647   .. container:: content
1648
1649     .. code:: javascript
1650
1651       var myList = new ArrayList();
1652
1653 Converting Javascript scripts from Nashorn to Rhino dialects
1654 ------------------------------------------------------------
1655
1656 The Nashorn Javascript engine was removed from Java in the Java 11 release. Java 11 was introduced into
1657 the Policy Framework in the Frankfurt release, so from Frankfurt on, APEX Javascript scripts use the Rhino
1658 Javascript engine and scripts must be in the Rhino dialect.
1659
1660 There are some minor but important differences between the dialects that users should be aware of so
1661 that they can convert their scripts into the Rhino dialect.
1662
1663 Return Values
1664 ^^^^^^^^^^^^^
1665
1666 APEX scripts must always return a value of ``true`` indicating that the script executed correctly or ``false``
1667 indicating that there was an error in script execution.
1668
1669 *Pre Frankfurt*
1670
1671 In Nashorn dialect scripts, the user had to create a special variable called ``returnValue`` and set the value of
1672 that variable to be the return value for the script.
1673
1674 *Frankfurt and Later*
1675
1676 In Rhino dialect scripts, the return value of the script is the logical result of the last statement. Therefore the
1677 last line of the script must evaluate to either ``true`` or ``false``.
1678
1679 .. container:: listingblock
1680
1681   .. container:: title
1682
1683     JS Rhino script last executed line examples
1684
1685   .. container:: content
1686
1687     .. code:: javascript
1688
1689       true;
1690
1691       returnValue; // Where returnValue is assigned earlier in the script
1692
1693       someValue == 1; // Where the value of someValue is assigned earlier in the script
1694
1695 return statement
1696 ^^^^^^^^^^^^^^^^
1697
1698 The ``return`` statement is not supported from the main script called in the Rhino interpreter.
1699
1700 *Pre Frankfurt*
1701
1702 In Nashorn dialect scripts, the user could return a value of ``true`` or ``false`` at any point in their script.
1703
1704 .. container:: listingblock
1705
1706   .. container:: title
1707
1708     JS Nashorn main script returning ``true`` and ``false``
1709
1710   .. container:: content
1711
1712     .. code:: javascript
1713
1714       var n;
1715
1716       // some code assigns n a value
1717
1718       if (n < 2) {
1719         return false;
1720       } else {
1721         return true;
1722       }
1723
1724 *Frankfurt and Later*
1725
1726 In Rhino dialect scripts, the ``return`` statement cannot be used in the main method, but it can still be used in
1727 functions. If you want to have a ``return`` statement in your code prior to the last statement, encapsulate your code
1728 in a function.
1729
1730 .. container:: listingblock
1731
1732   .. container:: title
1733
1734     JS Rhino script with ``return`` statements in a function
1735
1736   .. container:: content
1737
1738     .. code:: javascript
1739
1740       someFunction();
1741
1742       function someFunction() {
1743         var n;
1744
1745         // some code assigns n a value
1746
1747         if (n < 2) {
1748             return false;
1749         } else {
1750             return true;
1751         }
1752       }
1753
1754 Compatibility Script
1755 ^^^^^^^^^^^^^^^^^^^^
1756
1757 For Nashorn, the user had to call a compatibility script at the beginning of their Javascript script. This is not
1758 required in Rhino.
1759
1760 *Pre Frankfurt*
1761
1762 In Nashorn dialect scripts, the compatibility script must be loaded.
1763
1764 .. container:: listingblock
1765
1766   .. container:: title
1767
1768     Nashorn compatability script loading
1769
1770   .. container:: content
1771
1772     .. code:: javascript
1773
1774       load("nashorn:mozilla_compat.js");
1775
1776 *Frankfurt and Later*
1777
1778 Not required.
1779
1780 Import of Java classes
1781 ^^^^^^^^^^^^^^^^^^^^^^
1782
1783 For Nashorn, the user had explicitly import all the Java packages and classes they wished to use in their Javascript
1784 script. In Rhino, all Java classes on the classpath are available for use.
1785
1786 *Pre Frankfurt*
1787
1788 In Nashorn dialect scripts, Java classes must be imported.
1789
1790 .. container:: listingblock
1791
1792   .. container:: title
1793
1794     Importation of Java packages and classes
1795
1796   .. container:: content
1797
1798     .. code:: javascript
1799
1800       importPackage(java.text);
1801       importClass(java.text.SimpleDateFormat);
1802
1803 *Frankfurt and Later*
1804
1805 Not required.
1806
1807 Using Java Classes and Objects as Variables
1808 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1809
1810 Setting a Javascript variable to hold a Java class or a Java object is more straightforward in Rhino than it is in
1811 Nashorn. The examples below show how to instantiate a Javascript variable as a Java class and how to use that variable
1812 to create an instance of the Java class in another Javascript variable in both dialects.
1813
1814
1815 *Pre Frankfurt*
1816
1817 .. container:: listingblock
1818
1819   .. container:: title
1820
1821     Create Javascript variables to hold a Java class and instance
1822
1823   .. container:: content
1824
1825     .. code:: javascript
1826
1827       var webClientClass = Java.type("org.onap.policy.apex.examples.bbs.WebClient");
1828       var webClientObject = new webClientClass();
1829
1830 *Frankfurt and Later*
1831
1832 .. container:: listingblock
1833
1834   .. container:: title
1835
1836     Create Javascript variables to hold a Java class and instance
1837
1838   .. container:: content
1839
1840     .. code:: javascript
1841
1842       var webClientClass = org.onap.policy.apex.examples.bbs.WebClient;
1843       var webClientObject = new webClientClass();
1844
1845 Equal Value and Equal Type operator ``===``
1846 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1847
1848 The *Equal Value and Equal Type* operator ``===`` is not supported in Rhino. Developers must use the Equal To
1849 operator ``==`` instead. To check types, they may need to explicitly find and check the type of the variables
1850 they are using.
1851
1852 *************************************************
1853 Writing Multiple Output Events from a Final State
1854 *************************************************
1855
1856 .. container:: paragraph
1857
1858   APEX-PDP now supports sending multiple events from a final state in a Policy. The task assocaiated with the final
1859   state can populate the fields of multiple events, and then they can be passed over as the output events from the final
1860   state of a policy.
1861
1862 .. note::
1863   inputfields and outputfields are not needed as part of the task definition anymore. Fields of an event are already
1864   defined as part of the event definition. Input event (single trigger event) and output event/events can be populated
1865   to a task as part of the policy/state definition because the event tagging is done there anyway.
1866
1867 .. container:: paragraph
1868
1869   Consider a simple example where a policy *CDSActionPolicy* has a state *MakeCDSRequestState* which is also a final
1870   state. The state is triggered by an event *AAIEvent*. A task called *HandleCDSActionTask* is associated with
1871   *MakeCDSRequestState*.There are two output events expected from *MakeCDSRequestState* which are *CDSRequestEvent*
1872   (request event sent to CDS) and *LogEvent* (log event sent to DMaaP).
1873   Writing an APEX policy with this example will involve the below changes.
1874
1875 *Command File:*
1876
1877 .. container:: listingblock
1878
1879   .. container:: title
1880
1881     Define all the concepts in the Policy. Only relevant parts for the multiple output support are shown.
1882
1883   .. container:: content
1884
1885     .. code::
1886
1887       ## Define Events
1888       event create name=AAIEvent version=0.0.1 nameSpace=org.onap.policy.apex.test source=AAI target=APEX
1889       ..
1890       event create name=CDSRequestEvent version=0.0.1 nameSpace=org.onap.policy.apex.test source=APEX target=CDS
1891       event parameter create name=CDSRequestEvent parName=actionIdentifiers schemaName=CDSActionIdentifiersType
1892       ..
1893       event create name=LogEvent version=0.0.1 nameSpace=org.onap.policy.apex.test source=APEX target=DMaaP
1894       event parameter create name=LogEvent  parName=status schemaName=SimpleStringType
1895       ..
1896
1897       ## Define Tasks
1898       task create name=HandleCDSActionTask
1899       task contextref create name=HandleCDSActionTask albumName=EventDetailsAlbum
1900       task logic create name=HandleCDSActionTask logicFlavour=JAVASCRIPT logic=LS
1901       #MACROFILE:"src/main/resources/logic/HandleCDSActionTask.js"
1902       LE
1903       ..
1904
1905       ## Define Policies and States
1906       policy create name=CDSActionPolicy template=Freestyle firstState=MakeCDSRequestState
1907       policy state create name=CDSActionPolicy stateName=MakeCDSRequestState triggerName=AAIEvent defaultTaskName=HandleCDSActionTask
1908       # Specify CDSRequestEvent as output
1909       policy state output create name=CDSActionPolicy stateName=MakeCDSRequestState outputName=CDSActionStateOutput eventName=CDSRequestEvent
1910       # Specify LogEvent as output
1911       policy state output create name=CDSActionPolicy stateName=MakeCDSRequestState outputName=CDSActionStateOutput eventName=LogEvent
1912       policy state taskref create name=CDSActionPolicy stateName=MakeCDSRequestState taskName=HandleCDSActionTask outputType=DIRECT outputName=CDSActionStateOutput
1913
1914 *Task Logic File:*
1915
1916 .. container:: listingblock
1917
1918   .. container:: title
1919
1920     Create outfields' instance if required, populate and add them the output events
1921
1922   .. container:: content
1923
1924     .. code:: javascript
1925
1926       ..
1927       var cdsRequestEventFields = java.util.HashMap();
1928       var actionIdentifiers = executor.subject.getOutFieldSchemaHelper("CDSRequestEvent","actionIdentifiers").createNewInstance();
1929       actionIdentifiers.put("blueprintName", "sample-bp");
1930       cdsRequestEventFields.put("actionIdentifiers", actionIdentifiers);
1931       executor.addFieldsToOutput(cdsRequestEventFields);
1932
1933       var logEventFields = java.util.HashMap();
1934       logEventFields.put("status", "FINAL_SUCCESS");
1935       executor.addFieldsToOutput(logEventFields);
1936
1937 .. container:: paragraph
1938
1939   With the above changes, the task populates the fields for both the expected events, and the corresponding state which
1940   is *MakeCDSRequestState* outputs both *CDSRequestEvent* and *LogEvent*
1941
1942 .. |APEX Policy Matrix| image:: images/apex-intro/ApexPolicyMatrix.png
1943 .. |APEX Policy Model for Execution| image:: images/apex-policy-model/UmlPolicyModels.png
1944 .. |Concepts and Keys| image:: images/apex-policy-model/ConceptsKeys.png
1945