Remove redundant apex-pdp documentation
[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://www.researchgate.net/publication/282576518_Dynamically_Adaptive_Policies_for_Dynamically_Adaptive_Telecommunications_Networks>`__
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* concept is keyed with a ``ReferenceKey`` key, which references the *Policy* concept that owns the state.
546   The *LocalName* field of the ``ReferenceKey`` holds the name of the state. As a state is part of a chain of states,
547   the *NextState* field of a state holds the ``ReferenceKey`` key of the state in the policy to execute after this
548   state.
549
550 .. container:: paragraph
551
552   The *Trigger* field of a state holds the ``ArtifactKey`` of the event that triggers this state. The *OutgoingEvents*
553   field holds the ``ArtifactKey`` references of all possible events that may be output from the state. This is a set
554   that is the union of all output events of all tasks of the state.
555
556 .. container:: paragraph
557
558   The *Task* concepts that hold the definitions of the task for the state are held as a set of ``ArtifactKey``
559   references in the state. The *DefaultTask* field holds a reference to the default task for the state, a task that is
560   executed if no task selection logic is specified. If the state has only one task, that task is the default task.
561
562 .. container:: paragraph
563
564   The *Logic* concept referenced by a state holds the task selection logic for a state. The task selection logic uses
565   the incoming context (parameters of the incoming event) and other context to determine the best task to use to
566   execute its goals. The state holds a set of references to *ContextItem* and *ContextItemTemplate* definitions for the
567   context used by its task selection logic.
568
569 *************
570 Writing Logic
571 *************
572
573 Writing APEX Task Logic
574 =======================
575
576 .. container:: paragraph
577
578   Task logic specifies the behavior of an Apex Task. This logic can be specified in a number of ways, exploiting
579   Apex’s plug-in architecture to support a range of logic executors. In Apex scripted Task Logic can be written in any
580   of these languages:
581
582 .. container:: ulist
583
584   -  ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__,
585
586   -  ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__,
587
588   -  ```JRuby`` <https://en.wikipedia.org/wiki/JRuby>`__ or
589
590   -  ```Jython`` <https://en.wikipedia.org/wiki/Jython>`__.
591
592 .. container:: paragraph
593
594   These languages were chosen because the scripts can be compiled into Java bytecode at runtime and then efficiently
595   executed natively in the JVM. Task Logic an also be written directly in Java but needs to be compiled, with the
596   resulting classes added to the classpath. There are also a number of other Task Logic types (e.g. Fuzzy Logic), but
597   these are not supported as yet. This guide will focus on the scripted Task Logic approaches, with MVEL and JavaScript
598   being our favorite languages. In particular this guide will focus on the Apex aspects of the scripts. However, this
599   guide does not attempt to teach you about the scripting languages themselves â€¦â€‹ that is up to you!
600
601 .. tip::
602   JVM-based scripting languages For more more information on scripting for the Java platform see:
603   https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
604
605 .. note::
606   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
607   of the steps in an Apex Policy. Each task receives some *incoming fields*, executes some logic (e.g: make a decision
608   based on *shared state* or *context*, *incoming fields*, *external context*, etc.), perhaps set some *shared state*
609   or *context* and then emits *outgoing fields*. The state that uses the task is responsible for extracting the
610   *incoming fields* from the state input event. The state also has an *output mapper* associated with the task, and
611   this *output mapper* is responsible for mapping the *outgoing fields* from the task into an appropriate output event
612   for the state.
613
614 .. container:: paragraph
615
616   First lets start with a sample task, drawn from the "My First Apex Policy" example: The task "MorningBoozeCheck"
617   from the "My First Apex Policy" example is available in both MVEL and JavaScript:
618
619 .. container:: listingblock
620
621   .. container:: title
622
623     Javascript code for the ``MorningBoozeCheck`` task
624
625   .. container:: content
626
627     .. code:: javascript
628       :number-lines:
629
630       /*
631        * ============LICENSE_START=======================================================
632        *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
633        *  Modifications Copyright (C) 2020 Nordix Foundation.
634        * ================================================================================
635        * Licensed under the Apache License, Version 2.0 (the "License");
636        * you may not use this file except in compliance with the License.
637        * You may obtain a copy of the License at
638        *
639        *      http://www.apache.org/licenses/LICENSE-2.0
640        *
641        * Unless required by applicable law or agreed to in writing, software
642        * distributed under the License is distributed on an "AS IS" BASIS,
643        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
644        * See the License for the specific language governing permissions and
645        * limitations under the License.
646        *
647        * SPDX-License-Identifier: Apache-2.0
648        * ============LICENSE_END=========================================================
649        */
650
651       executor.logger.info("Task Execution: '"+executor.subject.id+"'. Input Fields: '"+executor.inFields+"'");
652
653       executor.outFields.put("amount"      , executor.inFields.get("amount"));
654       executor.outFields.put("assistant_ID", executor.inFields.get("assistant_ID"));
655       executor.outFields.put("notes"       , executor.inFields.get("notes"));
656       executor.outFields.put("quantity"    , executor.inFields.get("quantity"));
657       executor.outFields.put("branch_ID"   , executor.inFields.get("branch_ID"));
658       executor.outFields.put("item_ID"     , executor.inFields.get("item_ID"));
659       executor.outFields.put("time"        , executor.inFields.get("time"));
660       executor.outFields.put("sale_ID"     , executor.inFields.get("sale_ID"));
661
662       item_id = executor.inFields.get("item_ID");
663
664       //All times in this script are in GMT/UTC since the policy and events assume time is in GMT.
665       var timenow_gmt =  new Date(Number(executor.inFields.get("time")));
666
667       var midnight_gmt = new Date(Number(executor.inFields.get("time")));
668       midnight_gmt.setUTCHours(0,0,0,0);
669
670       var eleven30_gmt = new Date(Number(executor.inFields.get("time")));
671       eleven30_gmt.setUTCHours(11,30,0,0);
672
673       var timeformatter = new java.text.SimpleDateFormat("HH:mm:ss z");
674
675       var itemisalcohol = false;
676       if(item_id != null && item_id >=1000 && item_id < 2000)
677           itemisalcohol = true;
678
679       if( itemisalcohol
680           && timenow_gmt.getTime() >= midnight_gmt.getTime()
681           && timenow_gmt.getTime() <  eleven30_gmt.getTime()) {
682
683         executor.outFields.put("authorised", false);
684         executor.outFields.put("message", "Sale not authorised by policy task " +
685           executor.subject.taskName+ " for time " + timeformatter.format(timenow_gmt.getTime()) +
686           ". Alcohol can not be sold between " + timeformatter.format(midnight_gmt.getTime()) +
687           " and " + timeformatter.format(eleven30_gmt.getTime()));
688       }
689       else{
690         executor.outFields.put("authorised", true);
691         executor.outFields.put("message", "Sale authorised by policy task " +
692           executor.subject.taskName + " for time "+timeformatter.format(timenow_gmt.getTime()));
693       }
694
695       /*
696       This task checks if a sale request is for an item that is an alcoholic drink.
697       If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not
698       authorised. Otherwise the sale is authorised.
699       In this implementation we assume that items with item_ID value between 1000 and
700       2000 are all alcoholic drinks :-)
701       */
702
703       true;
704
705 .. container:: listingblock
706
707   .. container:: title
708
709     MVEL code for the ``MorningBoozeCheck`` task
710
711   .. container:: content
712
713     .. code:: javascript
714       :number-lines:
715
716       /*
717        * ============LICENSE_START=======================================================
718        *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
719        *  Modifications Copyright (C) 2020 Nordix Foundation.
720        * ================================================================================
721        * Licensed under the Apache License, Version 2.0 (the "License");
722        * you may not use this file except in compliance with the License.
723        * You may obtain a copy of the License at
724        *
725        *      http://www.apache.org/licenses/LICENSE-2.0
726        *
727        * Unless required by applicable law or agreed to in writing, software
728        * distributed under the License is distributed on an "AS IS" BASIS,
729        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
730        * See the License for the specific language governing permissions and
731        * limitations under the License.
732        *
733        * SPDX-License-Identifier: Apache-2.0
734        * ============LICENSE_END=========================================================
735        */
736       import java.util.Date;
737       import java.util.Calendar;
738       import java.util.TimeZone;
739       import java.text.SimpleDateFormat;
740
741       logger.info("Task Execution: '"+subject.id+"'. Input Fields: '"+inFields+"'");
742
743       outFields.put("amount"      , inFields.get("amount"));
744       outFields.put("assistant_ID", inFields.get("assistant_ID"));
745       outFields.put("notes"       , inFields.get("notes"));
746       outFields.put("quantity"    , inFields.get("quantity"));
747       outFields.put("branch_ID"   , inFields.get("branch_ID"));
748       outFields.put("item_ID"     , inFields.get("item_ID"));
749       outFields.put("time"        , inFields.get("time"));
750       outFields.put("sale_ID"     , inFields.get("sale_ID"));
751
752       item_id = inFields.get("item_ID");
753
754       //The events used later to test this task use GMT timezone!
755       gmt = TimeZone.getTimeZone("GMT");
756       timenow = Calendar.getInstance(gmt);
757       df = new SimpleDateFormat("HH:mm:ss z");
758       df.setTimeZone(gmt);
759       timenow.setTimeInMillis(inFields.get("time"));
760
761       midnight = timenow.clone();
762       midnight.set(
763           timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),
764           timenow.get(Calendar.DATE),0,0,0);
765       eleven30 = timenow.clone();
766       eleven30.set(
767           timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),
768           timenow.get(Calendar.DATE),11,30,0);
769
770       itemisalcohol = false;
771       if(item_id != null && item_id >=1000 && item_id < 2000)
772           itemisalcohol = true;
773
774       if( itemisalcohol
775           && timenow.after(midnight) && timenow.before(eleven30)){
776         outFields.put("authorised", false);
777         outFields.put("message", "Sale not authorised by policy task "+subject.taskName+
778           " for time "+df.format(timenow.getTime())+
779           ". Alcohol can not be sold between "+df.format(midnight.getTime())+
780           " and "+df.format(eleven30.getTime()));
781         return true;
782       }
783       else{
784         outFields.put("authorised", true);
785         outFields.put("message", "Sale authorised by policy task "+subject.taskName+
786           " for time "+df.format(timenow.getTime()));
787         return true;
788       }
789
790       /*
791       This task checks if a sale request is for an item that is an alcoholic drink.
792       If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not
793       authorised. Otherwise the sale is authorised.
794       In this implementation we assume that items with item_ID value between 1000 and
795       2000 are all alcoholic drinks :-)
796       */
797
798 .. container:: paragraph
799
800   The role of the task in this simple example is to copy the values in the incoming fields into the outgoing
801   fields, then examine the values in some incoming fields (``item_id`` and ``time``), then set the values in some
802   other outgoing fields (``authorised`` and ``message``).
803
804 .. container:: paragraph
805
806   Both MVEL and JavaScript like most JVM-based scripting languages can use standard Java libraries to perform
807   complex tasks. Towards the top of the scripts you will see how to import Java classes and packages to be used
808   directly in the logic. Another thing to notice is that Task Logic should return a ``java.lang.Boolean`` value
809   ``true`` if the logic executed correctly. If the logic fails for some reason then ``false`` can be returned, but
810   this will cause the policy invoking this task will fail and exit.
811
812 .. note::
813   How to return a value from task logic
814   Some languages explicitly support returning values from the script (e.g. MVEL and JRuby) using an explicit
815   return statement (e.g. ``return true``), other languages do not (e.g. Jython). For
816   languages that do not support the ``return`` statement, a special field called ``returnValue`` must be
817   created to hold the result of the task logic operation (i.e. assign a ``java.lang.Boolean``
818   value to the ``returnValue`` field before completing the task).
819   Also, in MVEL if there is no explicit return statement then the return value of the last executed statement will
820   return (e.g. the statement a=(1+2) will return the value 3).
821
822   For Javascript, the last statement of a script must be a statement that evaluates to *true* or *false*, indicating
823   whether the script executed correctly or not. In the case where the script always executes to compeletion
824   sucessfully, simply add a last line with the statement *true'*. In cases where success or failure is assessed in the
825   script, create a boolean
826   local variable with a name such as ``returnvalue``. In the execution of the script, set ``returnValue`` to be ``true``
827   or ``false`` as appropriate. The last line of the scritp tehn should simply be ``returnValue;``, which returns the
828   value of ``returnValue``.
829
830 .. container:: paragraph
831
832   Besides these imported classes and normal language features Apex provides some natively available parameters
833   and functions that can be used directly. At run-time these parameters are populated by the Apex execution
834   environment and made natively available to logic scripts each time the logic script is invoked. (These can be
835   accessed using the ``executor`` keyword for most languages, or can be accessed directly without the
836   ``executor`` keyword in MVEL):
837
838 Table 1. The ``executor`` Fields / Methods
839
840   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
841   | Name                                                | Type                                                                     | Java type                     | Description                                                                      |
842   +=====================================================+==========================================================================+===============================+==================================================================================+
843   | inFields                                            | Fields                                                                   | java.util.Map <String,Object> |The incoming task fields, implemented as a standard Java (unmodifiable) Map       |
844   |                                                     |                                                                          |                               |                                                                                  |
845   |                                                     |                                                                          |                               |**Example:**                                                                      |
846   |                                                     |                                                                          |                               |                                                                                  |
847   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
848   |                                                     |                                                                          |                               |                                                                                  |
849   |                                                     |                                                                          |                               |  executor.logger.debug("Incoming fields: " +executor.inFields.entrySet());       |
850   |                                                     |                                                                          |                               |  var item_id = executor.incomingFields["item_ID"];                               |
851   |                                                     |                                                                          |                               |  if (item_id >=1000) { ... }                                                     |
852   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
853   | outFields                                           | Fields                                                                   | java.util.Map <String,Object> |The outgoing task fields. This is implemented as a standard initially empty Java  |
854   |                                                     |                                                                          |                               |(modifiable) Map. To create a new schema-compliant instance of a field object     |
855   |                                                     |                                                                          |                               |see the utility method subject.getOutFieldSchemaHelper() below                    |
856   |                                                     |                                                                          |                               |                                                                                  |
857   |                                                     |                                                                          |                               |**Example:**                                                                      |
858   |                                                     |                                                                          |                               |                                                                                  |
859   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
860   |                                                     |                                                                          |                               |                                                                                  |
861   |                                                     |                                                                          |                               |  executor.outFields["authorised"] = false;                                       |
862   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
863   | logger                                              | Logger                                                                   | org.slf4j.ext.XLogger         |A helpful logger                                                                  |
864   |                                                     |                                                                          |                               |                                                                                  |
865   |                                                     |                                                                          |                               |**Example:**                                                                      |
866   |                                                     |                                                                          |                               |                                                                                  |
867   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
868   |                                                     |                                                                          |                               |                                                                                  |
869   |                                                     |                                                                          |                               |  executor.logger.info("Executing task: " +executor.subject.id);                  |
870   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
871   | TRUE/FALSE                                          | boolean                                                                  | java.lang.Boolean             |2 helpful constants. These are useful to retrieve correct return  values for the  |
872   |                                                     |                                                                          |                               |task logic                                                                        |
873   |                                                     |                                                                          |                               |                                                                                  |
874   |                                                     |                                                                          |                               |**Example:**                                                                      |
875   |                                                     |                                                                          |                               |                                                                                  |
876   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
877   |                                                     |                                                                          |                               |                                                                                  |
878   |                                                     |                                                                          |                               |  var returnValue = executor.isTrue;                                              |
879   |                                                     |                                                                          |                               |  var returnValueType = Java.type("java.lang.Boolean");                           |
880   |                                                     |                                                                          |                               |  var returnValue = new returnValueType(true);                                    |
881   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
882   | subject                                             | Task                                                                     | TaskFacade                    |This provides some useful information about the task that contains this task      |
883   |                                                     |                                                                          |                               |logic. This object has some useful fields and methods :                           |
884   |                                                     |                                                                          |                               |                                                                                  |
885   |                                                     |                                                                          |                               |.. container:: ulist                                                              |
886   |                                                     |                                                                          |                               |                                                                                  |
887   |                                                     |                                                                          |                               |  - **AxTask task** to get access to the full task definition of the host task    |
888   |                                                     |                                                                          |                               |                                                                                  |
889   |                                                     |                                                                          |                               |  - **String getTaskName()** to get the name of the host task                     |
890   |                                                     |                                                                          |                               |                                                                                  |
891   |                                                     |                                                                          |                               |  - **String getId()** to get the ID of the host task                             |
892   |                                                     |                                                                          |                               |                                                                                  |
893   |                                                     |                                                                          |                               |  - **SchemaHelper getInFieldSchemaHelper( String fieldName )** to                |
894   |                                                     |                                                                          |                               |    get a ``SchemaHelper`` helper object to manipulate incoming                   |
895   |                                                     |                                                                          |                               |    task fields in a schema-aware manner                                          |
896   |                                                     |                                                                          |                               |                                                                                  |
897   |                                                     |                                                                          |                               |  - **SchemaHelper getOutFieldSchemaHelper( String fieldName )** to               |
898   |                                                     |                                                                          |                               |    get a ``SchemaHelper`` helper object to manipulate outgoing                   |
899   |                                                     |                                                                          |                               |    task fields in a schema-aware manner, e.g. to instantiate new                 |
900   |                                                     |                                                                          |                               |    schema-compliant field objects to populate the                                |
901   |                                                     |                                                                          |                               |    ``executor.outFields`` outgoing fields map                                    |
902   |                                                     |                                                                          |                               |                                                                                  |
903   |                                                     |                                                                          |                               |**Example:**                                                                      |
904   |                                                     |                                                                          |                               |                                                                                  |
905   |                                                     |                                                                          |                               |.. code:: javascript                                                              |
906   |                                                     |                                                                          |                               |                                                                                  |
907   |                                                     |                                                                          |                               |  executor.logger.info("Task name: " + executor.subject.getTaskName());           |
908   |                                                     |                                                                          |                               |  executor.logger.info("Task id: " + executor.subject.getId());                   |
909   |                                                     |                                                                          |                               |  executor.logger.info("Task inputs definitions: "                                |
910   |                                                     |                                                                          |                               |    + "executor.subject.task.getInputFieldSet());                                 |
911   |                                                     |                                                                          |                               |  executor.logger.info("Task outputs definitions: "                               |
912   |                                                     |                                                                          |                               |    + "executor.subject.task.getOutputFieldSet());                                |
913   |                                                     |                                                                          |                               |  executor.outFields["authorised"] = executor.subject                             |
914   |                                                     |                                                                          |                               |    .getOutFieldSchemaHelper("authorised").createNewInstance("false");            |
915   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
916   | ContextAlbum getContextAlbum(String ctxtAlbumName ) |A utility method to retrieve a ``ContextAlbum`` for use in the task.      |                               |                                                                                  |
917   |                                                     |This is how you access the context used by the task. The returned         |                               |                                                                                  |
918   |                                                     |``ContextAlbum`` implements the ``java.util.Map <String,Object>``         |                               |                                                                                  |
919   |                                                     |interface to get and set context as appropriate. The returned             |                               |                                                                                  |
920   |                                                     |``ContextAlbum`` also has methods to lock context albums, get             |                               |                                                                                  |
921   |                                                     |information about the schema of the items to be stored in a context       |                               |                                                                                  |
922   |                                                     |album, and get a ``SchemaHelper`` to manipulate context album items. How  |                               |                                                                                  |
923   |                                                     |to define and use context in a task is described in the Apex              |                               |                                                                                  |
924   |                                                     |Programmer’s Guide and in the My First Apex Policy guide.                 |                               |                                                                                  |
925   |                                                     |                                                                          |                               |                                                                                  |
926   |                                                     |**Example:**                                                              |                               |                                                                                  |
927   |                                                     |                                                                          |                               |                                                                                  |
928   |                                                     |.. code:: javascript                                                      |                               |                                                                                  |
929   |                                                     |                                                                          |                               |                                                                                  |
930   |                                                     |  var bkey = executor.inFields.get("branch_ID");                          |                               |                                                                                  |
931   |                                                     |  var cnts = executor.getContextMap("BranchCounts");                      |                               |                                                                                  |
932   |                                                     |  cnts.lockForWriting(bkey);                                              |                               |                                                                                  |
933   |                                                     |  cnts.put(bkey, cnts.get(bkey) + 1);                                     |                               |                                                                                  |
934   |                                                     |  cnts.unlockForWriting(bkey);                                            |                               |                                                                                  |
935   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
936
937 Writing APEX Task Selection Logic
938 =================================
939
940 .. container:: paragraph
941
942   The function of Task Selection Logic is to choose which task should be executed for an Apex State as one of
943   the steps in an Apex Policy. Since each state must define a default task there is no need for Task Selection
944   Logic unless the state uses more than one task. This logic can be specified in a number of ways, exploiting
945   Apex’s plug-in architecture to support a range of logic executors. In Apex scripted Task Selection Logic can be
946   written in any of these languages:
947
948 .. container:: ulist
949
950   -  ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__,
951
952   -  ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__,
953
954   -  ```JRuby`` <https://en.wikipedia.org/wiki/JRuby>`__ or
955
956   -  ```Jython`` <https://en.wikipedia.org/wiki/Jython>`__.
957
958 .. container:: paragraph
959
960   These languages were chosen because the scripts can be compiled into Java bytecode at runtime and then
961   efficiently executed natively in the JVM. Task Selection Logic an also be written directly in Java but needs to
962   be compiled, with the resulting classes added to the classpath. There are also a number of other Task Selection
963   Logic types but these are not supported as yet. This guide will focus on the scripted Task Selection Logic
964   approaches, with MVEL and JavaScript being our favorite languages. In particular this guide will focus on the
965   Apex aspects of the scripts. However, this guide does not attempt to teach you about the scripting languages
966   themselves â€¦â€‹ that is up to you!
967
968 .. tip::
969   JVM-based scripting languages
970   For more more information on Scripting for the Java platform see:
971   https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
972
973 .. note::
974   What does Task Selection Logic do?
975   When an Apex state references multiple tasks, there must be a way to dynamically decide
976   which task should be chosen and executed. This can depend on the many factors, e.g. the
977   *incoming event for the state*, *shared state* or *context*, *external context*,
978   etc.. This is the function of a state’s Task Selection Logic. Obviously, if there is
979   only one task then Task only one task then Task Selection Logic is not needed.
980   Each state must also select one of the tasks a the *default state*. If the Task
981   Selection Logic is unable to select an appropriate task, then it should select the
982   *default task*. Once the task has been selected the Apex Engine will then execute that task.
983
984 .. container:: paragraph
985
986   First lets start with some simple Task Selection Logic, drawn from the "My First Apex Policy" example: The Task
987   Selection Logic from the "My First Apex Policy" example is specified in JavaScript here:
988
989 .. container:: listingblock
990
991   .. container:: title
992
993     Javascript code for the "My First Policy" Task Selection Logic
994
995   .. container:: content
996
997     .. code:: javascript
998
999       /*
1000        * ============LICENSE_START=======================================================
1001        *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
1002        *  Modifications Copyright (C) 2020 Nordix Foundation.
1003        * ================================================================================
1004        * Licensed under the Apache License, Version 2.0 (the "License");
1005        * you may not use this file except in compliance with the License.
1006        * You may obtain a copy of the License at
1007        *
1008        *      http://www.apache.org/licenses/LICENSE-2.0
1009        *
1010        * Unless required by applicable law or agreed to in writing, software
1011        * distributed under the License is distributed on an "AS IS" BASIS,
1012        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1013        * See the License for the specific language governing permissions and
1014        * limitations under the License.
1015        *
1016        * SPDX-License-Identifier: Apache-2.0
1017        * ============LICENSE_END=========================================================
1018        */
1019
1020       executor.logger.info("Task Selection Execution: '"+executor.subject.id+
1021           "'. Input Event: '"+executor.inFields+"'");
1022
1023       branchid = executor.inFields.get("branch_ID");
1024       taskorig = executor.subject.getTaskKey("MorningBoozeCheck");
1025       taskalt = executor.subject.getTaskKey("MorningBoozeCheckAlt1");
1026       taskdef = executor.subject.getDefaultTaskKey();
1027
1028       if(branchid >=0 && branchid <1000){
1029         taskorig.copyTo(executor.selectedTask);
1030       }
1031       else if (branchid >=1000 && branchid <2000){
1032         taskalt.copyTo(executor.selectedTask);
1033       }
1034       else{
1035         taskdef.copyTo(executor.selectedTask);
1036       }
1037
1038       /*
1039       This task selection logic selects task "MorningBoozeCheck" for branches with
1040       0<=branch_ID<1000 and selects task "MorningBoozeCheckAlt1" for branches with
1041       1000<=branch_ID<2000. Otherwise the default task is selected.
1042       In this case the default task is also "MorningBoozeCheck"
1043       */
1044
1045       true;
1046
1047 .. container:: paragraph
1048
1049   The role of the Task Selection Logic in this simple example is to examine the value in one incoming field
1050   (``branchid``), then depending on that field’s value set the value for the selected task to the appropriate task
1051   (``MorningBoozeCheck``, ``MorningBoozeCheckAlt1``, or the default task).
1052
1053 .. container:: paragraph
1054
1055   Another thing to notice is that Task Selection Logic should return a ``java.lang.Boolean`` value ``true`` if
1056   the logic executed correctly. If the logic fails for some reason then ``false`` can be returned, but this will
1057   cause the policy invoking this task will fail and exit.
1058
1059 .. note::
1060   How to return a value from Task Selection Logic
1061   Some languages explicitly support returning values from the script (e.g. MVEL and
1062   JRuby) using an explicit return statement (e.g. ``return true``), other languages do not (e.g.
1063   JavaScript and Jython). For languages that do not support the ``return`` statement, a special field called
1064   ``returnValue`` must be created to hold the result of the task logic operation (i.e. assign a ``java.lang.Boolean``
1065   value to the ``returnValue`` field before completing the task).
1066   Also, in MVEL if there is not explicit return statement then the return value of the last executed statement will
1067   return (e.g. the statement a=(1+2) will return the value 3).
1068
1069 .. container:: paragraph
1070
1071   Each of the scripting languages used in Apex can import and use standard Java libraries to perform complex tasks.
1072   Besides imported classes and normal language features Apex provides some natively available parameters and functions
1073   that can be used directly. At run-time these parameters are populated by the Apex execution environment and made
1074   natively available to logic scripts each time the logic script is invoked. (These can be accessed using the
1075   ``executor`` keyword for most languages, or can be accessed directly without the ``executor`` keyword in MVEL):
1076
1077 Table 2. The ``executor`` Fields / Methods
1078   +-----------------------------------+------------------------------------+
1079   | Unix, Cygwin                      | Windows                            |
1080   +===================================+====================================+
1081   |.. container:: content             |.. container:: content              |
1082   |                                   |                                    |
1083   |  .. code:: bash                   |  .. code:: bash                    |
1084   |    :number-lines:                 |    :number-lines:                  |
1085   |                                   |                                    |
1086   |    >c:                            |    # cd /usr/local/src/apex-pdp    |
1087   |    >cd \dev\apex                  |    # mvn clean install -DskipTests |
1088   |    >mvn clean install -DskipTests |                                    |
1089   +-----------------------------------+------------------------------------+
1090
1091   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1092   | Name                                                | Type                                                                     | Java type                     | Description                                                                      |
1093   +=====================================================+==========================================================================+===============================+==================================================================================+
1094   | inFields                                            | Fields                                                                   | java.util.Map <String,Object> | All fields in the state’s incoming event. This is implemented as a standard Java |
1095   |                                                     |                                                                          |                               | Java (unmodifiable) Map                                                          |
1096   |                                                     |                                                                          |                               |                                                                                  |
1097   |                                                     |                                                                          |                               | **Example:**                                                                     |
1098   |                                                     |                                                                          |                               |                                                                                  |
1099   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1100   |                                                     |                                                                          |                               |                                                                                  |
1101   |                                                     |                                                                          |                               |   executor.logger.debug("Incoming fields: " + executor.inFields.entrySet());     |
1102   |                                                     |                                                                          |                               |   var item_id = executor.incomingFields["item_ID"];                              |
1103   |                                                     |                                                                          |                               |   if (item_id >=1000) { ... }                                                    |
1104   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1105   | outFields                                           | Fields                                                                   | java.util.Map <String,Object> | The outgoing task fields. This is implemented as a standard initially empty Java |
1106   |                                                     |                                                                          |                               | (modifiable) Map. To create a new schema-compliant instance of a field object    |
1107   |                                                     |                                                                          |                               | see the utility method subject.getOutFieldSchemaHelper() below                   |
1108   |                                                     |                                                                          |                               |                                                                                  |
1109   |                                                     |                                                                          |                               | **Example:**                                                                     |
1110   |                                                     |                                                                          |                               |                                                                                  |
1111   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1112   |                                                     |                                                                          |                               |                                                                                  |
1113   |                                                     |                                                                          |                               |   executor.outFields["authorised"] = false;                                      |
1114   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1115   | logger                                              | Logger                                                                   | org.slf4j.ext.XLogger         | A helpful logger                                                                 |
1116   |                                                     |                                                                          |                               |                                                                                  |
1117   |                                                     |                                                                          |                               | **Example:**                                                                     |
1118   |                                                     |                                                                          |                               |                                                                                  |
1119   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1120   |                                                     |                                                                          |                               |                                                                                  |
1121   |                                                     |                                                                          |                               |   executor.logger.info("Executing task: "                                        |
1122   |                                                     |                                                                          |                               |   +executor.subject.id);                                                         |
1123   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1124   | TRUE/FALSE                                          | boolean                                                                  | java.lang.Boolean             | 2 helpful constants. These are useful to retrieve correct return  values for the |
1125   |                                                     |                                                                          |                               | task logic                                                                       |
1126   |                                                     |                                                                          |                               |                                                                                  |
1127   |                                                     |                                                                          |                               | **Example:**                                                                     |
1128   |                                                     |                                                                          |                               |                                                                                  |
1129   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1130   |                                                     |                                                                          |                               |                                                                                  |
1131   |                                                     |                                                                          |                               |   var returnValue = executor.isTrue;                                             |
1132   |                                                     |                                                                          |                               |   var returnValueType = Java.type("java.lang.Boolean");                          |
1133   |                                                     |                                                                          |                               |   var returnValue = new returnValueType(true);                                   |
1134   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1135   | subject                                             | Task                                                                     | TaskFacade                    | This provides some useful information about the task that contains this task     |
1136   |                                                     |                                                                          |                               | logic. This object has some useful fields and methods :                          |
1137   |                                                     |                                                                          |                               |                                                                                  |
1138   |                                                     |                                                                          |                               | .. container:: ulist                                                             |
1139   |                                                     |                                                                          |                               |                                                                                  |
1140   |                                                     |                                                                          |                               |   - **AxTask task** to get access to the full task definition of the host task   |
1141   |                                                     |                                                                          |                               |                                                                                  |
1142   |                                                     |                                                                          |                               |   - **String getTaskName()** to get the name of the host task                    |
1143   |                                                     |                                                                          |                               |                                                                                  |
1144   |                                                     |                                                                          |                               |   - **String getId()** to get the ID of the host task                            |
1145   |                                                     |                                                                          |                               |                                                                                  |
1146   |                                                     |                                                                          |                               |   - **SchemaHelper getInFieldSchemaHelper( String fieldName )** to               |
1147   |                                                     |                                                                          |                               |     get a ``SchemaHelper`` helper object to manipulate incoming                  |
1148   |                                                     |                                                                          |                               |     task fields in a schema-aware manner                                         |
1149   |                                                     |                                                                          |                               |                                                                                  |
1150   |                                                     |                                                                          |                               |   - **SchemaHelper getOutFieldSchemaHelper( String fieldName )** to              |
1151   |                                                     |                                                                          |                               |     get a ``SchemaHelper`` helper object to manipulate outgoing                  |
1152   |                                                     |                                                                          |                               |     task fields in a schema-aware manner, e.g. to instantiate new                |
1153   |                                                     |                                                                          |                               |     schema-compliant field objects to populate the                               |
1154   |                                                     |                                                                          |                               |     ``executor.outFields`` outgoing fields map                                   |
1155   |                                                     |                                                                          |                               |                                                                                  |
1156   |                                                     |                                                                          |                               | **Example:**                                                                     |
1157   |                                                     |                                                                          |                               |                                                                                  |
1158   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1159   |                                                     |                                                                          |                               |                                                                                  |
1160   |                                                     |                                                                          |                               |   executor.logger.info("Task name: " + executor.subject.getTaskName());          |
1161   |                                                     |                                                                          |                               |   executor.logger.info("Task id: " + executor.subject.getId());                  |
1162   |                                                     |                                                                          |                               |   executor.logger.info("Task inputs definitions: "                               |
1163   |                                                     |                                                                          |                               |     + "executor.subject.task.getInputFieldSet());                                |
1164   |                                                     |                                                                          |                               |   executor.logger.info("Task outputs definitions: "                              |
1165   |                                                     |                                                                          |                               |     + "executor.subject.task.getOutputFieldSet());                               |
1166   |                                                     |                                                                          |                               |   executor.outFields["authorised"] = executor.subject                            |
1167   |                                                     |                                                                          |                               |     .getOutFieldSchemaHelper("authorised")                                       |
1168   |                                                     |                                                                          |                               |     .createNewInstance("false");                                                 |
1169   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1170   | parameters                                          | Fields                                                                   | java.util.Map <String,String> | All parameters in the current task. This is implemented as a standard Java Map.  |
1171   |                                                     |                                                                          |                               |                                                                                  |
1172   |                                                     |                                                                          |                               | **Example:**                                                                     |
1173   |                                                     |                                                                          |                               |                                                                                  |
1174   |                                                     |                                                                          |                               | .. code:: javascript                                                             |
1175   |                                                     |                                                                          |                               |                                                                                  |
1176   |                                                     |                                                                          |                               |   executor.parameters.get("ParameterKey1"))                                      |
1177   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1178   | ContextAlbum getContextAlbum(String ctxtAlbumName ) | A utility method to retrieve a ``ContextAlbum`` for use in the task.     |                               |                                                                                  |
1179   |                                                     | This is how you access the context used by the task. The returned        |                               |                                                                                  |
1180   |                                                     | ``ContextAlbum`` implements the ``java.util.Map <String,Object>``        |                               |                                                                                  |
1181   |                                                     | interface to get and set context as appropriate. The returned            |                               |                                                                                  |
1182   |                                                     | ``ContextAlbum`` also has methods to lock context albums, get            |                               |                                                                                  |
1183   |                                                     | information about the schema of the items to be stored in a context      |                               |                                                                                  |
1184   |                                                     | album, and get a ``SchemaHelper`` to manipulate context album items. How |                               |                                                                                  |
1185   |                                                     | to define and use context in a task is described in the Apex             |                               |                                                                                  |
1186   |                                                     | Programmer’s Guide and in the My First Apex Policy guide.                |                               |                                                                                  |
1187   |                                                     |                                                                          |                               |                                                                                  |
1188   |                                                     | **Example:**                                                             |                               |                                                                                  |
1189   |                                                     |                                                                          |                               |                                                                                  |
1190   |                                                     | .. code:: javascript                                                     |                               |                                                                                  |
1191   |                                                     |                                                                          |                               |                                                                                  |
1192   |                                                     |   var bkey = executor.inFields.get("branch_ID");                         |                               |                                                                                  |
1193   |                                                     |   var cnts = executor.getContextMap("BranchCounts");                     |                               |                                                                                  |
1194   |                                                     |   cnts.lockForWriting(bkey);                                             |                               |                                                                                  |
1195   |                                                     |   cnts.put(bkey, cnts.get(bkey) + 1);                                    |                               |                                                                                  |
1196   |                                                     |   cnts.unlockForWriting(bkey);                                           |                               |                                                                                  |
1197   +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
1198
1199 Logic Cheat Sheet
1200 =================
1201
1202 .. container:: paragraph
1203
1204   Examples given here use Javascript (if not stated otherwise), other execution environments will be similar.
1205
1206 Finish Logic with Success or Error
1207 ----------------------------------
1208
1209 .. container:: paragraph
1210
1211   To finish logic, i.e. return to APEX, with success use the following line close to the end of the logic.
1212
1213 .. container:: listingblock
1214
1215   .. container:: title
1216
1217     JS Success
1218
1219   .. container:: content
1220
1221     .. code:: javascript
1222
1223       true;
1224
1225 .. container:: paragraph
1226
1227   To notify a problem, finish with an error.
1228
1229   .. container:: listingblock
1230
1231     .. container:: title
1232
1233       JS Fail
1234
1235     .. container:: content
1236
1237       .. code:: javascript
1238
1239         false;
1240
1241 Logic Logging
1242 -------------
1243
1244 .. container:: paragraph
1245
1246   Logging can be made easy using a local variable for the logger. Line 1 below does that. Then we start
1247   with a trace log with the task (or task logic) identifier followed by the infields.
1248
1249 .. container:: listingblock
1250
1251   .. container:: title
1252
1253     JS Logging
1254
1255   .. container:: content
1256
1257     .. code:: javascript
1258
1259       var logger = executor.logger;
1260       logger.trace("start: " + executor.subject.id);
1261       logger.trace("-- infields: " + executor.inFields);
1262
1263 .. container:: paragraph
1264
1265   For larger logging blocks you can use the standard logging API to detect log levels, for instance:
1266
1267   .. container:: listingblock
1268
1269     .. container:: title
1270
1271       JS Logging Blocks
1272
1273     .. container:: content
1274
1275       .. code:: javascript
1276
1277         if(logger.isTraceEnabled()){
1278           // trace logging block here
1279         }
1280
1281 .. container:: paragraph
1282
1283   Note: the shown logger here logs to ``org.onap.policy.apex.executionlogging``. The behavior of the actual logging can
1284   be specified in the ``$APEX_HOME/etc/logback.xml``.
1285
1286 .. container:: paragraph
1287
1288   If you want to log into the APEX root logger (which is sometimes necessary to report serious logic errors to the top),
1289   then import the required class and use this logger.
1290
1291 .. container:: listingblock
1292
1293   .. container:: title
1294
1295     JS Root Logger
1296
1297   .. container:: content
1298
1299     .. code:: javascript
1300
1301       var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
1302       rootLogger.error("Serious error in logic detected: " + executor.subject.id);
1303
1304 Accessing TaskParameters
1305 ------------------------
1306
1307 .. container:: paragraph
1308
1309   TaskParameters available in a Task can be accessed in the logic. The parameters in each task are made
1310   available at the executor level. This example assumes a parameter with key ``ParameterKey1``.
1311
1312   .. container:: listingblock
1313
1314     .. container:: title
1315
1316       JS TaskParameter value
1317
1318     .. container:: content
1319
1320       .. code:: javascript
1321
1322         executor.parameters.get("ParameterKey1"))
1323
1324 .. container:: paragraph
1325
1326   Alternatively, the task parameters can also be accessed from the task object.
1327
1328   .. container:: listingblock
1329
1330     .. container:: title
1331
1332       JS TaskParameter value using task object
1333
1334     .. container:: content
1335
1336       .. code:: javascript
1337
1338         executor.subject.task.getTaskParameters.get("ParameterKey1").getTaskParameterValue()
1339
1340 Local Variable for Infields
1341 ---------------------------
1342
1343 .. container:: paragraph
1344
1345   It is a good idea to use local variables for ``infields``. This avoids long code lines and policy
1346   evolution. The following example assumes infields named ``nodeName`` and ``nodeAlias``.
1347
1348  .. container:: listingblock
1349
1350    .. container:: title
1351
1352      JS Infields Local Var
1353
1354   .. container:: content
1355
1356     .. code:: javascript
1357
1358       var ifNodeName = executor.inFields["nodeName"];
1359       var ifNodeAlias = executor.inFields["nodeAlias"];
1360
1361 Local Variable for Context Albums
1362 ---------------------------------
1363
1364 .. container:: paragraph
1365
1366   Similar to the ``infields`` it is good practice to use local variables for context albums as well. The
1367   following example assumes that a task can access a context album ``albumTopoNodes``. The second line gets a
1368   particular node from this context album.
1369
1370 .. container:: listingblock
1371
1372   .. container:: title
1373
1374     JS Infields Local Var
1375
1376   .. container:: content
1377
1378     .. code:: javascript
1379
1380       var albumTopoNodes = executor.getContextAlbum("albumTopoNodes");
1381       var ctxtNode = albumTopoNodes.get(ifNodeName);
1382
1383 Set Outfields in Logic
1384 ----------------------
1385
1386 .. container:: paragraph
1387
1388   The task logic needs to set outfields with content generated. The exception are outfields that are a
1389   direct copy from an infield of the same name, APEX does that autmatically.
1390
1391 .. container:: listingblock
1392
1393   .. container:: title
1394
1395     JS Set Outfields
1396
1397   .. container:: content
1398
1399     .. code:: javascript
1400
1401       executor.outFields["report"] = "node ctxt :: added node " + ifNodeName;
1402
1403 Create a instance of an Outfield using Schemas
1404 ----------------------------------------------
1405
1406 .. container:: paragraph
1407
1408   If an outfield is not an atomic type (string, integer, etc.) but uses a complex schema (with a Java or
1409   Avro backend), APEX can help to create new instances. The ``executor`` provides a field called ``subject``,
1410   which provides a schem helper with an API for this. The complete API of the schema helper is documented here:
1411   `API Doc: SchemaHelper <https://ericsson.github.io/apex-docs/javadocs/index.html>`__.
1412
1413 .. container:: paragraph
1414
1415   If the backend is Java, then the Java class implementing the schema needs to be imported.
1416
1417 .. container:: paragraph
1418
1419   The following example assumes an outfield ``situation``. The ``subject`` method ``getOutFieldSchemaHelper()`` is used
1420   to create a new instance.
1421
1422 .. container:: listingblock
1423
1424   .. container:: title
1425
1426     JS Outfield Instance with Schema
1427
1428   .. container:: content
1429
1430     .. code:: javascript
1431
1432       var situation = executor.subject.getOutFieldSchemaHelper("situation").createNewInstance();
1433
1434 .. container:: paragraph
1435
1436   If the schema backend is Java, the new instance will be as implemented in the Java class. If the schema backend is
1437   Avro, the new instance will have all fields from the Avro schema specification, but set to ``null``. So any entry here
1438   needs to be done separately. For instance, the ``situation`` schema has a field ``problemID`` which we set.
1439
1440 .. container:: listingblock
1441
1442   .. container:: title
1443
1444     JS Outfield Instance with Schema, set
1445
1446   .. container:: content
1447
1448     .. code:: javascript
1449
1450       situation.put("problemID", "my-problem");
1451
1452 Create a instance of an Context Album entry using Schemas
1453 ---------------------------------------------------------
1454
1455 .. container:: paragraph
1456
1457   Context album instances can be created using very similar to the outfields. Here, the schema helper
1458   comes from the context album directly. The API of the schema helper is the same as for outfields, see
1459   `API Doc: SchemaHelper <https://ericsson.github.io/apex-docs/javadocs/index.html>`__.
1460
1461 .. container:: paragraph
1462
1463   If the backend is Java, then the Java class implementing the schema needs to be imported.
1464
1465 .. container:: paragraph
1466
1467   The following example creates a new instance of a context album instance named ``albumProblemMap``.
1468
1469 .. container:: listingblock
1470
1471   .. container:: title
1472
1473     JS Outfield Instance with Schema
1474
1475   .. container:: content
1476
1477     .. code:: javascript
1478
1479       var albumProblemMap = executor.getContextAlbum("albumProblemMap");
1480       var linkProblem = albumProblemMap.getSchemaHelper().createNewInstance();
1481
1482 .. container:: paragraph
1483
1484   This can of course be also done in a single call without the local variable for the context album.
1485
1486 .. container:: listingblock
1487
1488   .. container:: title
1489
1490     JS Outfield Instance with Schema, one line
1491
1492   .. container:: content
1493
1494     .. code:: javascript
1495
1496       var linkProblem = executor.getContextAlbum("albumProblemMap").getSchemaHelper().createNewInstance();
1497
1498 .. container:: paragraph
1499
1500   If the schema backend is Java, the new instance will be as implemented in the Java class. If the schema backend is
1501   Avro, the new instance will have all fields from the Avro schema specification, but set to ``null``. So any entry here
1502   needs to be done separately (see above in outfields for an example).
1503
1504 Enumerates
1505 ----------
1506
1507 .. container:: paragraph
1508
1509   When dealing with enumerates (Avro or Java defined), it is sometimes and in some execution
1510   environments necessary to convert them to a string. For example, assume an Avro enumerate schema as:
1511
1512 .. container:: listingblock
1513
1514   .. container:: title
1515
1516     Avro Enumerate Schema
1517
1518   .. container:: content
1519
1520     .. code:: javascript
1521
1522       {
1523         "type": "enum", "name": "Status", "symbols" : [
1524           "UP", "DOWN"
1525         ]
1526       }
1527
1528 .. container:: paragraph
1529
1530   Using a switch over a field initialized with this enumerate in Javascript will fail. Instead, use the ``toString`` method, for example:
1531
1532 .. container:: listingblock
1533
1534   .. container:: title
1535
1536     JS Outfield Instance with Schema, one line
1537
1538   .. container:: content
1539
1540     .. code:: javascript
1541
1542       var switchTest = executor.inFields["status"]; switch(switchTest.toString()){
1543         case "UP": ...; break; case "DOWN": ...; break; default: ...;
1544       }
1545
1546 MVEL Initialize Outfields First!
1547 --------------------------------
1548
1549 .. container:: paragraph
1550
1551   In MVEL, we observed a problem when accessing (setting) outfields without a prior access to them. So
1552   in any MVEL task logic, before setting any outfield, simply do a get (with any string), to load the outfields
1553   into the MVEL cache.
1554
1555 .. container:: listingblock
1556
1557   .. container:: title
1558
1559     MVEL Outfield Initialization
1560
1561   .. container:: content
1562
1563     .. code:: javascript
1564
1565       outFields.get("initialize outfields");
1566
1567 Using Java in Scripting Logic
1568 -----------------------------
1569
1570 .. container:: paragraph
1571
1572   Since APEX executes the logic inside a JVM, most scripting languages provide access to all standard
1573   Java classes. Simply add an import for the required class and then use it as in actual Java.
1574
1575 .. container:: paragraph
1576
1577   The following example imports ``java.util.arraylist`` into a Javascript logic, and then creates a new
1578   list.
1579
1580 .. container:: listingblock
1581
1582   .. container:: title
1583
1584     JS Import ArrayList
1585
1586   .. container:: content
1587
1588     .. code:: javascript
1589
1590       var myList = new ArrayList();
1591
1592 Converting Javascript scripts from Nashorn to Rhino dialects
1593 ------------------------------------------------------------
1594
1595 The Nashorn Javascript engine was removed from Java in the Java 11 release. Java 11 was introduced into
1596 the Policy Framework in the Frankfurt release, so from Frankfurt on, APEX Javascript scripts use the Rhino
1597 Javascript engine and scripts must be in the Rhino dialect.
1598
1599 There are some minor but important differences between the dialects that users should be aware of so
1600 that they can convert their scripts into the Rhino dialect.
1601
1602 Return Values
1603 ^^^^^^^^^^^^^
1604
1605 APEX scripts must always return a value of ``true`` indicating that the script executed correctly or ``false``
1606 indicating that there was an error in script execution.
1607
1608 *Pre Frankfurt*
1609
1610 In Nashorn dialect scripts, the user had to create a special variable called ``returnValue`` and set the value of
1611 that variable to be the return value for the script.
1612
1613 *Frankfurt and Later*
1614
1615 In Rhino dialect scripts, the return value of the script is the logical result of the last statement. Therefore the
1616 last line of the script must evaluate to either ``true`` or ``false``.
1617
1618 .. container:: listingblock
1619
1620   .. container:: title
1621
1622     JS Rhino script last executed line examples
1623
1624   .. container:: content
1625
1626     .. code:: javascript
1627
1628       true;
1629
1630       returnValue; // Where returnValue is assigned earlier in the script
1631
1632       someValue == 1; // Where the value of someValue is assigned earlier in the script
1633
1634 return statement
1635 ^^^^^^^^^^^^^^^^
1636
1637 The ``return`` statement is not supported from the main script called in the Rhino interpreter.
1638
1639 *Pre Frankfurt*
1640
1641 In Nashorn dialect scripts, the user could return a value of ``true`` or ``false`` at any point in their script.
1642
1643 .. container:: listingblock
1644
1645   .. container:: title
1646
1647     JS Nashorn main script returning ``true`` and ``false``
1648
1649   .. container:: content
1650
1651     .. code:: javascript
1652
1653       var n;
1654
1655       // some code assigns n a value
1656
1657       if (n < 2) {
1658         return false;
1659       } else {
1660         return true;
1661       }
1662
1663 *Frankfurt and Later*
1664
1665 In Rhino dialect scripts, the ``return`` statement cannot be used in the main method, but it can still be used in
1666 functions. If you want to have a ``return`` statement in your code prior to the last statement, encapsulate your code
1667 in a function.
1668
1669 .. container:: listingblock
1670
1671   .. container:: title
1672
1673     JS Rhino script with ``return`` statements in a function
1674
1675   .. container:: content
1676
1677     .. code:: javascript
1678
1679       someFunction();
1680
1681       function someFunction() {
1682         var n;
1683
1684         // some code assigns n a value
1685
1686         if (n < 2) {
1687             return false;
1688         } else {
1689             return true;
1690         }
1691       }
1692
1693 Compatibility Script
1694 ^^^^^^^^^^^^^^^^^^^^
1695
1696 For Nashorn, the user had to call a compatibility script at the beginning of their Javascript script. This is not
1697 required in Rhino.
1698
1699 *Pre Frankfurt*
1700
1701 In Nashorn dialect scripts, the compatibility script must be loaded.
1702
1703 .. container:: listingblock
1704
1705   .. container:: title
1706
1707     Nashorn compatability script loading
1708
1709   .. container:: content
1710
1711     .. code:: javascript
1712
1713       load("nashorn:mozilla_compat.js");
1714
1715 *Frankfurt and Later*
1716
1717 Not required.
1718
1719 Import of Java classes
1720 ^^^^^^^^^^^^^^^^^^^^^^
1721
1722 For Nashorn, the user had explicitly import all the Java packages and classes they wished to use in their Javascript
1723 script. In Rhino, all Java classes on the classpath are available for use.
1724
1725 *Pre Frankfurt*
1726
1727 In Nashorn dialect scripts, Java classes must be imported.
1728
1729 .. container:: listingblock
1730
1731   .. container:: title
1732
1733     Importation of Java packages and classes
1734
1735   .. container:: content
1736
1737     .. code:: javascript
1738
1739       importPackage(java.text);
1740       importClass(java.text.SimpleDateFormat);
1741
1742 *Frankfurt and Later*
1743
1744 Not required.
1745
1746 Using Java Classes and Objects as Variables
1747 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1748
1749 Setting a Javascript variable to hold a Java class or a Java object is more straightforward in Rhino than it is in
1750 Nashorn. The examples below show how to instantiate a Javascript variable as a Java class and how to use that variable
1751 to create an instance of the Java class in another Javascript variable in both dialects.
1752
1753
1754 *Pre Frankfurt*
1755
1756 .. container:: listingblock
1757
1758   .. container:: title
1759
1760     Create Javascript variables to hold a Java class and instance
1761
1762   .. container:: content
1763
1764     .. code:: javascript
1765
1766       var webClientClass = Java.type("org.onap.policy.apex.examples.bbs.WebClient");
1767       var webClientObject = new webClientClass();
1768
1769 *Frankfurt and Later*
1770
1771 .. container:: listingblock
1772
1773   .. container:: title
1774
1775     Create Javascript variables to hold a Java class and instance
1776
1777   .. container:: content
1778
1779     .. code:: javascript
1780
1781       var webClientClass = org.onap.policy.apex.examples.bbs.WebClient;
1782       var webClientObject = new webClientClass();
1783
1784 Equal Value and Equal Type operator ``===``
1785 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1786
1787 The *Equal Value and Equal Type* operator ``===`` is not supported in Rhino. Developers must use the Equal To
1788 operator ``==`` instead. To check types, they may need to explicitly find and check the type of the variables
1789 they are using.
1790
1791 .. |APEX Policy Matrix| image:: images/apex-intro/ApexPolicyMatrix.png
1792 .. |APEX Policy Model for Execution| image:: images/apex-policy-model/UmlPolicyModels.png
1793 .. |Concepts and Keys| image:: images/apex-policy-model/ConceptsKeys.png
1794