diff options
author | a.sreekumar <ajith.sreekumar@bell.ca> | 2021-06-22 15:55:46 +0100 |
---|---|---|
committer | a.sreekumar <ajith.sreekumar@bell.ca> | 2021-06-28 10:36:48 +0100 |
commit | 926646d8e5e86e680a119360f93d7bdb46c89435 (patch) | |
tree | 7ff431e59672b19f658faed87c80b4d147253c9c | |
parent | 63637d939697451d3ac63216d938780a157ff895 (diff) |
Changes to support multiple outputs from a state
This review addresses two main changes:
1) inputFields and outputFields are not tied to task definition anymore.
Instead inputEvent and outputEvents associated to a task is populated
as part of the policy state definition, as the state definition have
the information anyway.
- Clean up of the usage of inputFields and outputFields in task
definition will happen in a future review
- inputFields and outputFields defined in task definition in
policies until honolulu will not make the policy invalid as the
changes are done in backward compatible way.
2) Multiple output events can come out of a final state now.
- Define another policy state output with the relevant eventName in
the command file
- In the task logic, create a map to store the fields of the relevant
outputEvent, and then just call
"executor.addFieldsToOutput(<the_map_of_fields>)"
These 2 steps are enough to send multiple events to relevant
components as per the apex configuration.
Change-Id: Id88ca402704106404f529e595e1a76f6bf167876
Issue-ID: POLICY-3336
Signed-off-by: a.sreekumar <ajith.sreekumar@bell.ca>
47 files changed, 1970 insertions, 1510 deletions
diff --git a/auth/cli-codegen/src/test/java/org/onap/policy/apex/auth/clicodegen/CodeGeneratorCliEditorTest.java b/auth/cli-codegen/src/test/java/org/onap/policy/apex/auth/clicodegen/CodeGeneratorCliEditorTest.java index 921591b32..cec261c2a 100644 --- a/auth/cli-codegen/src/test/java/org/onap/policy/apex/auth/clicodegen/CodeGeneratorCliEditorTest.java +++ b/auth/cli-codegen/src/test/java/org/onap/policy/apex/auth/clicodegen/CodeGeneratorCliEditorTest.java @@ -3,6 +3,7 @@ * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Samsung Electronics Co., Ltd. * Modifications Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -425,8 +426,8 @@ public class CodeGeneratorCliEditorTest { final AxReferenceKey outkey = out.getKey(); final ST val = cg.createPolicyStateOutput(kig.getPName(skey), kig.getPVersion(skey), kig.getLName(skey), - kig.getLName(outkey), kig.getName(out.getOutgingEvent()), - kig.getVersion(out.getOutgingEvent()), kig.getLName(out.getNextState())); + kig.getLName(outkey), kig.getName(out.getOutgoingEvent()), kig.getVersion(out.getOutgoingEvent()), + kig.getLName(out.getNextState())); ret.add(val); } diff --git a/auth/cli-editor/src/test/java/org/onap/policy/apex/auth/clieditor/CommandLineEditorEventsContextTest.java b/auth/cli-editor/src/test/java/org/onap/policy/apex/auth/clieditor/CommandLineEditorEventsContextTest.java index d00a9232b..0e87950d2 100644 --- a/auth/cli-editor/src/test/java/org/onap/policy/apex/auth/clieditor/CommandLineEditorEventsContextTest.java +++ b/auth/cli-editor/src/test/java/org/onap/policy/apex/auth/clieditor/CommandLineEditorEventsContextTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,7 +85,7 @@ public class CommandLineEditorEventsContextTest { final int modelCharCount = modelString.replaceAll(SPACES, EMPTY_STRING).length(); assertEquals(25892, logCharCount); - assertEquals(46048, modelCharCount); + assertEquals(51975, modelCharCount); } /** @@ -114,7 +115,7 @@ public class CommandLineEditorEventsContextTest { final int modelCharCount = modelString.replaceAll(SPACES, EMPTY_STRING).length(); assertEquals(30068, logCharCount); - assertEquals(52596, modelCharCount); + assertEquals(59015, modelCharCount); } diff --git a/auth/cli-editor/src/test/resources/tosca/PolicyModel.json b/auth/cli-editor/src/test/resources/tosca/PolicyModel.json index 0e9cfca11..3672be430 100644 --- a/auth/cli-editor/src/test/resources/tosca/PolicyModel.json +++ b/auth/cli-editor/src/test/resources/tosca/PolicyModel.json @@ -1,952 +1,1274 @@ { - "apexPolicyModel" : { - "key" : { - "name" : "MyFirstPolicyModel", - "version" : "0.0.1" + "apexPolicyModel": { + "key": { + "name": "MyFirstPolicyModel", + "version": "0.0.1" + }, + "keyInformation": { + "key": { + "name": "MyFirstPolicyModel_KeyInfo", + "version": "0.0.1" }, - "keyInformation" : { - "key" : { - "name" : "MyFirstPolicyModel_KeyInfo", - "version" : "0.0.1" - }, - "keyInfoMap" : { - "entry" : [ { - "key" : { - "name" : "MorningBoozeCheck", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MorningBoozeCheck", - "version" : "0.0.1" - }, - "UUID" : "3351b0f4-cf06-4fa2-8823-edf67bd30223", - "description" : "This task checks if the sales request is for an item that contains alcohol. \nIf the local time is between 00:00:00 and 11:30:00 then the sale is not authorised. Otherwise the sale is authorised. \nIn this implementation we assume that all items with item_ID values between 1000 and 2000 contain alcohol :-)" - } - }, { - "key" : { - "name" : "MyFirstPolicy", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MyFirstPolicy", - "version" : "0.0.1" - }, - "UUID" : "6c5e410f-489a-46ff-964e-982ce6e8b6d0", - "description" : "This is my first Apex policy. It checks if a sale should be authorised or not." - } - }, { - "key" : { - "name" : "MyFirstPolicyModel", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MyFirstPolicyModel", - "version" : "0.0.1" - }, - "UUID" : "540226fb-55ee-4f0e-a444-983a0494818e", - "description" : "This is my first Apex Policy Model." - } - }, { - "key" : { - "name" : "MyFirstPolicyModel_Events", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MyFirstPolicyModel_Events", - "version" : "0.0.1" - }, - "UUID" : "ef281318-5ac9-3ef0-8db3-8f9c4e4a81e2", - "description" : "Generated description for concept referred to by key \"MyFirstPolicyModel_Events:0.0.1\"" - } - }, { - "key" : { - "name" : "MyFirstPolicyModel_KeyInfo", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MyFirstPolicyModel_KeyInfo", - "version" : "0.0.1" - }, - "UUID" : "d9248c6f-7c00-38df-8251-611463ba4065", - "description" : "Generated description for concept referred to by key \"MyFirstPolicyModel_KeyInfo:0.0.1\"" - } - }, { - "key" : { - "name" : "MyFirstPolicyModel_Policies", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MyFirstPolicyModel_Policies", - "version" : "0.0.1" - }, - "UUID" : "77c01a6b-510c-3aa9-b640-b4db356aa03b", - "description" : "Generated description for concept referred to by key \"MyFirstPolicyModel_Policies:0.0.1\"" - } - }, { - "key" : { - "name" : "MyFirstPolicyModel_Schemas", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MyFirstPolicyModel_Schemas", - "version" : "0.0.1" - }, - "UUID" : "d0cc3aa0-ea69-3a43-80ff-a0dbb0ebd885", - "description" : "Generated description for concept referred to by key \"MyFirstPolicyModel_Schemas:0.0.1\"" - } - }, { - "key" : { - "name" : "MyFirstPolicyModel_Tasks", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MyFirstPolicyModel_Tasks", - "version" : "0.0.1" - }, - "UUID" : "b02a7e02-2cd0-39e6-b3cb-946fa83a8f08", - "description" : "Generated description for concept referred to by key \"MyFirstPolicyModel_Tasks:0.0.1\"" - } - }, { - "key" : { - "name" : "SALE_AUTH", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "SALE_AUTH", - "version" : "0.0.1" - }, - "UUID" : "c4500941-3f98-4080-a9cc-5b9753ed050b", - "description" : "An event emitted by the Policy to indicate whether the sale of an item has been authorised" - } - }, { - "key" : { - "name" : "SALE_INPUT", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "SALE_INPUT", - "version" : "0.0.1" - }, - "UUID" : "4f04aa98-e917-4f4a-882a-c75ba5a99374", - "description" : "An event raised by the PoS system each time an item is scanned for purchase" - } - }, { - "key" : { - "name" : "assistant_ID_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "assistant_ID_type", - "version" : "0.0.1" - }, - "UUID" : "36df4c71-9616-4206-8b53-976a5cd4bd87", - "description" : "A type for 'assistant_ID' values" - } - }, { - "key" : { - "name" : "authorised_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "authorised_type", - "version" : "0.0.1" - }, - "UUID" : "d48b619e-d00d-4008-b884-02d76ea4350b", - "description" : "A type for 'authorised' values" - } - }, { - "key" : { - "name" : "branch_ID_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "branch_ID_type", - "version" : "0.0.1" - }, - "UUID" : "6468845f-4122-4128-8e49-0f52c26078b5", - "description" : "A type for 'branch_ID' values" - } - }, { - "key" : { - "name" : "item_ID_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "item_ID_type", - "version" : "0.0.1" - }, - "UUID" : "4f227ff1-aee0-453a-b6b6-9a4b2e0da932", - "description" : "A type for 'item_ID' values" - } - }, { - "key" : { - "name" : "message_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "message_type", - "version" : "0.0.1" - }, - "UUID" : "ad1431bb-3155-4e73-b5a3-b89bee498749", - "description" : "A type for 'message' values" - } - }, { - "key" : { - "name" : "notes_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "notes_type", - "version" : "0.0.1" - }, - "UUID" : "eecfde90-896c-4343-8f9c-2603ced94e2d", - "description" : "A type for 'notes' values" - } - }, { - "key" : { - "name" : "price_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "price_type", - "version" : "0.0.1" - }, - "UUID" : "52c2fc45-fd8c-463c-bd6f-d91b0554aea7", - "description" : "A type for 'amount'/'price' values" - } - }, { - "key" : { - "name" : "quantity_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "quantity_type", - "version" : "0.0.1" - }, - "UUID" : "ac3d9842-80af-4a98-951c-bd79a431c613", - "description" : "A type for 'quantity' values" - } - }, { - "key" : { - "name" : "sale_ID_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "sale_ID_type", - "version" : "0.0.1" - }, - "UUID" : "cca47d74-7754-4a61-b163-ca31f66b157b", - "description" : "A type for 'sale_ID' values" - } - }, { - "key" : { - "name" : "timestamp_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "timestamp_type", - "version" : "0.0.1" - }, - "UUID" : "fd594e88-411d-4a94-b2be-697b3a0d7adf", - "description" : "A type for 'time' values" - } - } ] - } + "keyInfoMap": { + "entry": [ + { + "key": { + "name": "MorningBoozeCheck", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MorningBoozeCheck", + "version": "0.0.1" + }, + "UUID": "3351b0f4-cf06-4fa2-8823-edf67bd30223", + "description": "This task checks if the sales request is for an item that contains alcohol. \nIf the local time is between 00:00:00 and 11:30:00 then the sale is not authorised. Otherwise the sale is authorised. \nIn this implementation we assume that all items with item_ID values between 1000 and 2000 contain alcohol :-)" + } + }, + { + "key": { + "name": "MyFirstPolicy", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MyFirstPolicy", + "version": "0.0.1" + }, + "UUID": "6c5e410f-489a-46ff-964e-982ce6e8b6d0", + "description": "This is my first Apex policy. It checks if a sale should be authorised or not." + } + }, + { + "key": { + "name": "MyFirstPolicyModel", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MyFirstPolicyModel", + "version": "0.0.1" + }, + "UUID": "540226fb-55ee-4f0e-a444-983a0494818e", + "description": "This is my first Apex Policy Model." + } + }, + { + "key": { + "name": "MyFirstPolicyModel_Events", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MyFirstPolicyModel_Events", + "version": "0.0.1" + }, + "UUID": "ef281318-5ac9-3ef0-8db3-8f9c4e4a81e2", + "description": "Generated description for concept referred to by key \"MyFirstPolicyModel_Events:0.0.1\"" + } + }, + { + "key": { + "name": "MyFirstPolicyModel_KeyInfo", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MyFirstPolicyModel_KeyInfo", + "version": "0.0.1" + }, + "UUID": "d9248c6f-7c00-38df-8251-611463ba4065", + "description": "Generated description for concept referred to by key \"MyFirstPolicyModel_KeyInfo:0.0.1\"" + } + }, + { + "key": { + "name": "MyFirstPolicyModel_Policies", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MyFirstPolicyModel_Policies", + "version": "0.0.1" + }, + "UUID": "77c01a6b-510c-3aa9-b640-b4db356aa03b", + "description": "Generated description for concept referred to by key \"MyFirstPolicyModel_Policies:0.0.1\"" + } + }, + { + "key": { + "name": "MyFirstPolicyModel_Schemas", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MyFirstPolicyModel_Schemas", + "version": "0.0.1" + }, + "UUID": "d0cc3aa0-ea69-3a43-80ff-a0dbb0ebd885", + "description": "Generated description for concept referred to by key \"MyFirstPolicyModel_Schemas:0.0.1\"" + } + }, + { + "key": { + "name": "MyFirstPolicyModel_Tasks", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MyFirstPolicyModel_Tasks", + "version": "0.0.1" + }, + "UUID": "b02a7e02-2cd0-39e6-b3cb-946fa83a8f08", + "description": "Generated description for concept referred to by key \"MyFirstPolicyModel_Tasks:0.0.1\"" + } + }, + { + "key": { + "name": "SALE_AUTH", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "SALE_AUTH", + "version": "0.0.1" + }, + "UUID": "c4500941-3f98-4080-a9cc-5b9753ed050b", + "description": "An event emitted by the Policy to indicate whether the sale of an item has been authorised" + } + }, + { + "key": { + "name": "SALE_INPUT", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "SALE_INPUT", + "version": "0.0.1" + }, + "UUID": "4f04aa98-e917-4f4a-882a-c75ba5a99374", + "description": "An event raised by the PoS system each time an item is scanned for purchase" + } + }, + { + "key": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "UUID": "36df4c71-9616-4206-8b53-976a5cd4bd87", + "description": "A type for 'assistant_ID' values" + } + }, + { + "key": { + "name": "authorised_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "authorised_type", + "version": "0.0.1" + }, + "UUID": "d48b619e-d00d-4008-b884-02d76ea4350b", + "description": "A type for 'authorised' values" + } + }, + { + "key": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "UUID": "6468845f-4122-4128-8e49-0f52c26078b5", + "description": "A type for 'branch_ID' values" + } + }, + { + "key": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "UUID": "4f227ff1-aee0-453a-b6b6-9a4b2e0da932", + "description": "A type for 'item_ID' values" + } + }, + { + "key": { + "name": "message_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "message_type", + "version": "0.0.1" + }, + "UUID": "ad1431bb-3155-4e73-b5a3-b89bee498749", + "description": "A type for 'message' values" + } + }, + { + "key": { + "name": "notes_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "notes_type", + "version": "0.0.1" + }, + "UUID": "eecfde90-896c-4343-8f9c-2603ced94e2d", + "description": "A type for 'notes' values" + } + }, + { + "key": { + "name": "price_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "price_type", + "version": "0.0.1" + }, + "UUID": "52c2fc45-fd8c-463c-bd6f-d91b0554aea7", + "description": "A type for 'amount'/'price' values" + } + }, + { + "key": { + "name": "quantity_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "quantity_type", + "version": "0.0.1" + }, + "UUID": "ac3d9842-80af-4a98-951c-bd79a431c613", + "description": "A type for 'quantity' values" + } + }, + { + "key": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "UUID": "cca47d74-7754-4a61-b163-ca31f66b157b", + "description": "A type for 'sale_ID' values" + } + }, + { + "key": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "UUID": "fd594e88-411d-4a94-b2be-697b3a0d7adf", + "description": "A type for 'time' values" + } + } + ] + } + }, + "policies": { + "key": { + "name": "MyFirstPolicyModel_Policies", + "version": "0.0.1" }, - "policies" : { - "key" : { - "name" : "MyFirstPolicyModel_Policies", - "version" : "0.0.1" - }, - "policyMap" : { - "entry" : [ { - "key" : { - "name" : "MyFirstPolicy", - "version" : "0.0.1" - }, - "value" : { - "policyKey" : { - "name" : "MyFirstPolicy", - "version" : "0.0.1" - }, - "template" : "FREEFORM", - "state" : { - "entry" : [ { - "key" : "BoozeAuthDecide", - "value" : { - "stateKey" : { - "parentKeyName" : "MyFirstPolicy", - "parentKeyVersion" : "0.0.1", - "parentLocalName" : "NULL", - "localName" : "BoozeAuthDecide" - }, - "trigger" : { - "name" : "SALE_INPUT", - "version" : "0.0.1" - }, - "stateOutputs" : { - "entry" : [ { - "key" : "MorningBoozeCheck_Output_Direct", - "value" : { - "key" : { - "parentKeyName" : "MyFirstPolicy", - "parentKeyVersion" : "0.0.1", - "parentLocalName" : "BoozeAuthDecide", - "localName" : "MorningBoozeCheck_Output_Direct" - }, - "outgoingEvent" : { - "name" : "SALE_AUTH", - "version" : "0.0.1" - }, - "nextState" : { - "parentKeyName" : "NULL", - "parentKeyVersion" : "0.0.0", - "parentLocalName" : "NULL", - "localName" : "NULL" - } - } - } ] - }, - "contextAlbumReference" : [ ], - "taskSelectionLogic" : { - "key" : "NULL", - "logicFlavour" : "UNDEFINED", - "logic" : "" - }, - "stateFinalizerLogicMap" : { - "entry" : [ ] - }, - "defaultTask" : { - "name" : "MorningBoozeCheck", - "version" : "0.0.1" - }, - "taskReferences" : { - "entry" : [ { - "key" : { - "name" : "MorningBoozeCheck", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "parentKeyName" : "MyFirstPolicy", - "parentKeyVersion" : "0.0.1", - "parentLocalName" : "BoozeAuthDecide", - "localName" : "MorningBoozeCheck" - }, - "outputType" : "DIRECT", - "output" : { - "parentKeyName" : "MyFirstPolicy", - "parentKeyVersion" : "0.0.1", - "parentLocalName" : "BoozeAuthDecide", - "localName" : "MorningBoozeCheck_Output_Direct" - } - } - } ] - } - } - } ] - }, - "firstState" : "BoozeAuthDecide" - } - } ] - } + "policyMap": { + "entry": [ + { + "key": { + "name": "MyFirstPolicy", + "version": "0.0.1" + }, + "value": { + "policyKey": { + "name": "MyFirstPolicy", + "version": "0.0.1" + }, + "template": "FREEFORM", + "state": { + "entry": [ + { + "key": "BoozeAuthDecide", + "value": { + "stateKey": { + "parentKeyName": "MyFirstPolicy", + "parentKeyVersion": "0.0.1", + "parentLocalName": "NULL", + "localName": "BoozeAuthDecide" + }, + "trigger": { + "name": "SALE_INPUT", + "version": "0.0.1" + }, + "stateOutputs": { + "entry": [ + { + "key": "MorningBoozeCheck_Output_Direct", + "value": { + "key": { + "parentKeyName": "MyFirstPolicy", + "parentKeyVersion": "0.0.1", + "parentLocalName": "BoozeAuthDecide", + "localName": "MorningBoozeCheck_Output_Direct" + }, + "outgoingEvent": { + "name": "SALE_AUTH", + "version": "0.0.1" + }, + "outgoingEventReference": [ + { + "name": "SALE_AUTH", + "version": "0.0.1" + } + ], + "nextState": { + "parentKeyName": "NULL", + "parentKeyVersion": "0.0.0", + "parentLocalName": "NULL", + "localName": "NULL" + } + } + } + ] + }, + "contextAlbumReference": [], + "taskSelectionLogic": { + "key": "NULL", + "logicFlavour": "UNDEFINED", + "logic": "" + }, + "stateFinalizerLogicMap": { + "entry": [] + }, + "defaultTask": { + "name": "MorningBoozeCheck", + "version": "0.0.1" + }, + "taskReferences": { + "entry": [ + { + "key": { + "name": "MorningBoozeCheck", + "version": "0.0.1" + }, + "value": { + "key": { + "parentKeyName": "MyFirstPolicy", + "parentKeyVersion": "0.0.1", + "parentLocalName": "BoozeAuthDecide", + "localName": "MorningBoozeCheck" + }, + "outputType": "DIRECT", + "output": { + "parentKeyName": "MyFirstPolicy", + "parentKeyVersion": "0.0.1", + "parentLocalName": "BoozeAuthDecide", + "localName": "MorningBoozeCheck_Output_Direct" + } + } + } + ] + } + } + } + ] + }, + "firstState": "BoozeAuthDecide" + } + } + ] + } + }, + "tasks": { + "key": { + "name": "MyFirstPolicyModel_Tasks", + "version": "0.0.1" }, - "tasks" : { - "key" : { - "name" : "MyFirstPolicyModel_Tasks", - "version" : "0.0.1" - }, - "taskMap" : { - "entry" : [ { - "key" : { - "name" : "MorningBoozeCheck", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "MorningBoozeCheck", - "version" : "0.0.1" - }, - "inputFields" : { - "entry" : [ { - "key" : "amount", - "value" : { - "key" : "amount", - "fieldSchemaKey" : { - "name" : "price_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "assistant_ID", - "value" : { - "key" : "assistant_ID", - "fieldSchemaKey" : { - "name" : "assistant_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "branch_ID", - "value" : { - "key" : "branch_ID", - "fieldSchemaKey" : { - "name" : "branch_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "item_ID", - "value" : { - "key" : "item_ID", - "fieldSchemaKey" : { - "name" : "item_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "notes", - "value" : { - "key" : "notes", - "fieldSchemaKey" : { - "name" : "notes_type", - "version" : "0.0.1" - }, - "optional" : true - } - }, { - "key" : "quantity", - "value" : { - "key" : "quantity", - "fieldSchemaKey" : { - "name" : "quantity_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "sale_ID", - "value" : { - "key" : "sale_ID", - "fieldSchemaKey" : { - "name" : "sale_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "time", - "value" : { - "key" : "time", - "fieldSchemaKey" : { - "name" : "timestamp_type", - "version" : "0.0.1" - }, - "optional" : false - } - } ] - }, - "outputFields" : { - "entry" : [ { - "key" : "amount", - "value" : { - "key" : "amount", - "fieldSchemaKey" : { - "name" : "price_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "assistant_ID", - "value" : { - "key" : "assistant_ID", - "fieldSchemaKey" : { - "name" : "assistant_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "authorised", - "value" : { - "key" : "authorised", - "fieldSchemaKey" : { - "name" : "authorised_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "branch_ID", - "value" : { - "key" : "branch_ID", - "fieldSchemaKey" : { - "name" : "branch_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "item_ID", - "value" : { - "key" : "item_ID", - "fieldSchemaKey" : { - "name" : "item_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "message", - "value" : { - "key" : "message", - "fieldSchemaKey" : { - "name" : "message_type", - "version" : "0.0.1" - }, - "optional" : true - } - }, { - "key" : "notes", - "value" : { - "key" : "notes", - "fieldSchemaKey" : { - "name" : "notes_type", - "version" : "0.0.1" - }, - "optional" : true - } - }, { - "key" : "quantity", - "value" : { - "key" : "quantity", - "fieldSchemaKey" : { - "name" : "quantity_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "sale_ID", - "value" : { - "key" : "sale_ID", - "fieldSchemaKey" : { - "name" : "sale_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "time", - "value" : { - "key" : "time", - "fieldSchemaKey" : { - "name" : "timestamp_type", - "version" : "0.0.1" - }, - "optional" : false - } - } ] - }, - "taskParameters" : { - "entry" : [ ] - }, - "contextAlbumReference" : [ ], - "taskLogic" : { - "key" : "TaskLogic", - "logicFlavour" : "MVEL", - "logic" : "/*\n * ============LICENSE_START=======================================================\n * Copyright (C) 2016-2018 Ericsson. All rights reserved.\n * Modifications Copyright (C) 2019 Nordix Foundation.\n * ================================================================================\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * SPDX-License-Identifier: Apache-2.0\n * ============LICENSE_END=========================================================\n */\nimport java.util.Date;\nimport java.util.Calendar;\nimport java.util.TimeZone;\nimport java.text.SimpleDateFormat;\n\nlogger.info(\"Task Execution: '\"+subject.id+\"'. Input Fields: '\"+inFields+\"'\");\n\noutFields.put(\"amount\" , inFields.get(\"amount\"));\noutFields.put(\"assistant_ID\", inFields.get(\"assistant_ID\"));\noutFields.put(\"notes\" , inFields.get(\"notes\"));\noutFields.put(\"quantity\" , inFields.get(\"quantity\"));\noutFields.put(\"branch_ID\" , inFields.get(\"branch_ID\"));\noutFields.put(\"item_ID\" , inFields.get(\"item_ID\"));\noutFields.put(\"time\" , inFields.get(\"time\"));\noutFields.put(\"sale_ID\" , inFields.get(\"sale_ID\"));\n\nitem_id = inFields.get(\"item_ID\");\n\n//The events used later to test this task use GMT timezone!\ngmt = TimeZone.getTimeZone(\"GMT\");\ntimenow = Calendar.getInstance(gmt);\ndf = new SimpleDateFormat(\"HH:mm:ss z\");\ndf.setTimeZone(gmt);\ntimenow.setTimeInMillis(inFields.get(\"time\"));\n\nmidnight = timenow.clone();\nmidnight.set(\n timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),\n timenow.get(Calendar.DATE),0,0,0);\neleven30 = timenow.clone();\neleven30.set(\n timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),\n timenow.get(Calendar.DATE),11,30,0);\n\nitemisalcohol = false;\nif(item_id != null && item_id >=1000 && item_id < 2000)\n itemisalcohol = true;\n\nif( itemisalcohol\n && timenow.after(midnight) && timenow.before(eleven30)){\n outFields.put(\"authorised\", false);\n outFields.put(\"message\", \"Sale not authorised by policy task \"+subject.taskName+\n \" for time \"+df.format(timenow.getTime())+\n \". Alcohol can not be sold between \"+df.format(midnight.getTime())+\n \" and \"+df.format(eleven30.getTime()));\n return true;\n}\nelse{\n outFields.put(\"authorised\", true);\n outFields.put(\"message\", \"Sale authorised by policy task \"+subject.taskName+\n \" for time \"+df.format(timenow.getTime()));\n return true;\n}\n\n/*\nThis task checks if a sale request is for an item that is an alcoholic drink.\nIf the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not\nauthorised. Otherwise the sale is authorised.\nIn this implementation we assume that items with item_ID value between 1000 and\n2000 are all alcoholic drinks :-)\n*/" + "taskMap": { + "entry": [ + { + "key": { + "name": "MorningBoozeCheck", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "MorningBoozeCheck", + "version": "0.0.1" + }, + "inputEvent": { + "key": { + "name": "SALE_INPUT", + "version": "0.0.1" + }, + "nameSpace": "com.hyperm", + "source": "POS", + "target": "APEX", + "parameter": { + "entry": [ + { + "key": "amount", + "value": { + "key": "amount", + "fieldSchemaKey": { + "name": "price_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "assistant_ID", + "value": { + "key": "assistant_ID", + "fieldSchemaKey": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "branch_ID", + "value": { + "key": "branch_ID", + "fieldSchemaKey": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "item_ID", + "value": { + "key": "item_ID", + "fieldSchemaKey": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "notes", + "value": { + "key": "notes", + "fieldSchemaKey": { + "name": "notes_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "quantity", + "value": { + "key": "quantity", + "fieldSchemaKey": { + "name": "quantity_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "sale_ID", + "value": { + "key": "sale_ID", + "fieldSchemaKey": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "time", + "value": { + "key": "time", + "fieldSchemaKey": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "optional": false + } + } + ] + } + }, + "outputEvents": { + "entry": [ + { + "key": "SALE_AUTH", + "value": { + "key": { + "name": "SALE_AUTH", + "version": "0.0.1" + }, + "nameSpace": "com.hyperm", + "source": "APEX", + "target": "POS", + "parameter": { + "entry": [ + { + "key": "amount", + "value": { + "key": "amount", + "fieldSchemaKey": { + "name": "price_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "assistant_ID", + "value": { + "key": "assistant_ID", + "fieldSchemaKey": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "authorised", + "value": { + "key": "authorised", + "fieldSchemaKey": { + "name": "authorised_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "branch_ID", + "value": { + "key": "branch_ID", + "fieldSchemaKey": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "item_ID", + "value": { + "key": "item_ID", + "fieldSchemaKey": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "message", + "value": { + "key": "message", + "fieldSchemaKey": { + "name": "message_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "notes", + "value": { + "key": "notes", + "fieldSchemaKey": { + "name": "notes_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "quantity", + "value": { + "key": "quantity", + "fieldSchemaKey": { + "name": "quantity_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "sale_ID", + "value": { + "key": "sale_ID", + "fieldSchemaKey": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "time", + "value": { + "key": "time", + "fieldSchemaKey": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "optional": false + } + } + ] + } + } + } + ] + }, + "inputFields": { + "entry": [ + { + "key": "amount", + "value": { + "key": "amount", + "fieldSchemaKey": { + "name": "price_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "assistant_ID", + "value": { + "key": "assistant_ID", + "fieldSchemaKey": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "branch_ID", + "value": { + "key": "branch_ID", + "fieldSchemaKey": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "item_ID", + "value": { + "key": "item_ID", + "fieldSchemaKey": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "notes", + "value": { + "key": "notes", + "fieldSchemaKey": { + "name": "notes_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "quantity", + "value": { + "key": "quantity", + "fieldSchemaKey": { + "name": "quantity_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "sale_ID", + "value": { + "key": "sale_ID", + "fieldSchemaKey": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "time", + "value": { + "key": "time", + "fieldSchemaKey": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "optional": false + } } - } - } ] - } + ] + }, + "outputFields": { + "entry": [ + { + "key": "amount", + "value": { + "key": "amount", + "fieldSchemaKey": { + "name": "price_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "assistant_ID", + "value": { + "key": "assistant_ID", + "fieldSchemaKey": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "authorised", + "value": { + "key": "authorised", + "fieldSchemaKey": { + "name": "authorised_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "branch_ID", + "value": { + "key": "branch_ID", + "fieldSchemaKey": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "item_ID", + "value": { + "key": "item_ID", + "fieldSchemaKey": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "message", + "value": { + "key": "message", + "fieldSchemaKey": { + "name": "message_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "notes", + "value": { + "key": "notes", + "fieldSchemaKey": { + "name": "notes_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "quantity", + "value": { + "key": "quantity", + "fieldSchemaKey": { + "name": "quantity_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "sale_ID", + "value": { + "key": "sale_ID", + "fieldSchemaKey": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "time", + "value": { + "key": "time", + "fieldSchemaKey": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "optional": false + } + } + ] + }, + "taskParameters": { + "entry": [] + }, + "contextAlbumReference": [], + "taskLogic": { + "key": "TaskLogic", + "logicFlavour": "MVEL", + "logic": "/*\n * ============LICENSE_START=======================================================\n * Copyright (C) 2016-2018 Ericsson. All rights reserved.\n * Modifications Copyright (C) 2019 Nordix Foundation.\n * ================================================================================\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * SPDX-License-Identifier: Apache-2.0\n * ============LICENSE_END=========================================================\n */\nimport java.util.Date;\nimport java.util.Calendar;\nimport java.util.TimeZone;\nimport java.text.SimpleDateFormat;\n\nlogger.info(\"Task Execution: '\"+subject.id+\"'. Input Fields: '\"+inFields+\"'\");\n\noutFields.put(\"amount\" , inFields.get(\"amount\"));\noutFields.put(\"assistant_ID\", inFields.get(\"assistant_ID\"));\noutFields.put(\"notes\" , inFields.get(\"notes\"));\noutFields.put(\"quantity\" , inFields.get(\"quantity\"));\noutFields.put(\"branch_ID\" , inFields.get(\"branch_ID\"));\noutFields.put(\"item_ID\" , inFields.get(\"item_ID\"));\noutFields.put(\"time\" , inFields.get(\"time\"));\noutFields.put(\"sale_ID\" , inFields.get(\"sale_ID\"));\n\nitem_id = inFields.get(\"item_ID\");\n\n//The events used later to test this task use GMT timezone!\ngmt = TimeZone.getTimeZone(\"GMT\");\ntimenow = Calendar.getInstance(gmt);\ndf = new SimpleDateFormat(\"HH:mm:ss z\");\ndf.setTimeZone(gmt);\ntimenow.setTimeInMillis(inFields.get(\"time\"));\n\nmidnight = timenow.clone();\nmidnight.set(\n timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),\n timenow.get(Calendar.DATE),0,0,0);\neleven30 = timenow.clone();\neleven30.set(\n timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),\n timenow.get(Calendar.DATE),11,30,0);\n\nitemisalcohol = false;\nif(item_id != null && item_id >=1000 && item_id < 2000)\n itemisalcohol = true;\n\nif( itemisalcohol\n && timenow.after(midnight) && timenow.before(eleven30)){\n outFields.put(\"authorised\", false);\n outFields.put(\"message\", \"Sale not authorised by policy task \"+subject.taskName+\n \" for time \"+df.format(timenow.getTime())+\n \". Alcohol can not be sold between \"+df.format(midnight.getTime())+\n \" and \"+df.format(eleven30.getTime()));\n return true;\n}\nelse{\n outFields.put(\"authorised\", true);\n outFields.put(\"message\", \"Sale authorised by policy task \"+subject.taskName+\n \" for time \"+df.format(timenow.getTime()));\n return true;\n}\n\n/*\nThis task checks if a sale request is for an item that is an alcoholic drink.\nIf the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not\nauthorised. Otherwise the sale is authorised.\nIn this implementation we assume that items with item_ID value between 1000 and\n2000 are all alcoholic drinks :-)\n*/" + } + } + } + ] + } + }, + "events": { + "key": { + "name": "MyFirstPolicyModel_Events", + "version": "0.0.1" }, - "events" : { - "key" : { - "name" : "MyFirstPolicyModel_Events", - "version" : "0.0.1" - }, - "eventMap" : { - "entry" : [ { - "key" : { - "name" : "SALE_AUTH", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "SALE_AUTH", - "version" : "0.0.1" - }, - "nameSpace" : "com.hyperm", - "source" : "APEX", - "target" : "POS", - "parameter" : { - "entry" : [ { - "key" : "amount", - "value" : { - "key" : "amount", - "fieldSchemaKey" : { - "name" : "price_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "assistant_ID", - "value" : { - "key" : "assistant_ID", - "fieldSchemaKey" : { - "name" : "assistant_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "authorised", - "value" : { - "key" : "authorised", - "fieldSchemaKey" : { - "name" : "authorised_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "branch_ID", - "value" : { - "key" : "branch_ID", - "fieldSchemaKey" : { - "name" : "branch_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "item_ID", - "value" : { - "key" : "item_ID", - "fieldSchemaKey" : { - "name" : "item_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "message", - "value" : { - "key" : "message", - "fieldSchemaKey" : { - "name" : "message_type", - "version" : "0.0.1" - }, - "optional" : true - } - }, { - "key" : "notes", - "value" : { - "key" : "notes", - "fieldSchemaKey" : { - "name" : "notes_type", - "version" : "0.0.1" - }, - "optional" : true - } - }, { - "key" : "quantity", - "value" : { - "key" : "quantity", - "fieldSchemaKey" : { - "name" : "quantity_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "sale_ID", - "value" : { - "key" : "sale_ID", - "fieldSchemaKey" : { - "name" : "sale_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "time", - "value" : { - "key" : "time", - "fieldSchemaKey" : { - "name" : "timestamp_type", - "version" : "0.0.1" - }, - "optional" : false - } - } ] + "eventMap": { + "entry": [ + { + "key": { + "name": "SALE_AUTH", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "SALE_AUTH", + "version": "0.0.1" + }, + "nameSpace": "com.hyperm", + "source": "APEX", + "target": "POS", + "parameter": { + "entry": [ + { + "key": "amount", + "value": { + "key": "amount", + "fieldSchemaKey": { + "name": "price_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "assistant_ID", + "value": { + "key": "assistant_ID", + "fieldSchemaKey": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "authorised", + "value": { + "key": "authorised", + "fieldSchemaKey": { + "name": "authorised_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "branch_ID", + "value": { + "key": "branch_ID", + "fieldSchemaKey": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "item_ID", + "value": { + "key": "item_ID", + "fieldSchemaKey": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "message", + "value": { + "key": "message", + "fieldSchemaKey": { + "name": "message_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "notes", + "value": { + "key": "notes", + "fieldSchemaKey": { + "name": "notes_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "quantity", + "value": { + "key": "quantity", + "fieldSchemaKey": { + "name": "quantity_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "sale_ID", + "value": { + "key": "sale_ID", + "fieldSchemaKey": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "time", + "value": { + "key": "time", + "fieldSchemaKey": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "optional": false + } } - } - }, { - "key" : { - "name" : "SALE_INPUT", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "SALE_INPUT", - "version" : "0.0.1" - }, - "nameSpace" : "com.hyperm", - "source" : "POS", - "target" : "APEX", - "parameter" : { - "entry" : [ { - "key" : "amount", - "value" : { - "key" : "amount", - "fieldSchemaKey" : { - "name" : "price_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "assistant_ID", - "value" : { - "key" : "assistant_ID", - "fieldSchemaKey" : { - "name" : "assistant_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "branch_ID", - "value" : { - "key" : "branch_ID", - "fieldSchemaKey" : { - "name" : "branch_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "item_ID", - "value" : { - "key" : "item_ID", - "fieldSchemaKey" : { - "name" : "item_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "notes", - "value" : { - "key" : "notes", - "fieldSchemaKey" : { - "name" : "notes_type", - "version" : "0.0.1" - }, - "optional" : true - } - }, { - "key" : "quantity", - "value" : { - "key" : "quantity", - "fieldSchemaKey" : { - "name" : "quantity_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "sale_ID", - "value" : { - "key" : "sale_ID", - "fieldSchemaKey" : { - "name" : "sale_ID_type", - "version" : "0.0.1" - }, - "optional" : false - } - }, { - "key" : "time", - "value" : { - "key" : "time", - "fieldSchemaKey" : { - "name" : "timestamp_type", - "version" : "0.0.1" - }, - "optional" : false - } - } ] + ] + } + } + }, + { + "key": { + "name": "SALE_INPUT", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "SALE_INPUT", + "version": "0.0.1" + }, + "nameSpace": "com.hyperm", + "source": "POS", + "target": "APEX", + "parameter": { + "entry": [ + { + "key": "amount", + "value": { + "key": "amount", + "fieldSchemaKey": { + "name": "price_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "assistant_ID", + "value": { + "key": "assistant_ID", + "fieldSchemaKey": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "branch_ID", + "value": { + "key": "branch_ID", + "fieldSchemaKey": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "item_ID", + "value": { + "key": "item_ID", + "fieldSchemaKey": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "notes", + "value": { + "key": "notes", + "fieldSchemaKey": { + "name": "notes_type", + "version": "0.0.1" + }, + "optional": true + } + }, + { + "key": "quantity", + "value": { + "key": "quantity", + "fieldSchemaKey": { + "name": "quantity_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "sale_ID", + "value": { + "key": "sale_ID", + "fieldSchemaKey": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "optional": false + } + }, + { + "key": "time", + "value": { + "key": "time", + "fieldSchemaKey": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "optional": false + } } - } - } ] - } + ] + } + } + } + ] + } + }, + "schemas": { + "key": { + "name": "MyFirstPolicyModel_Schemas", + "version": "0.0.1" }, - "schemas" : { - "key" : { - "name" : "MyFirstPolicyModel_Schemas", - "version" : "0.0.1" - }, - "schemas" : { - "entry" : [ { - "key" : { - "name" : "assistant_ID_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "assistant_ID_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.Long" - } - }, { - "key" : { - "name" : "authorised_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "authorised_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.Boolean" - } - }, { - "key" : { - "name" : "branch_ID_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "branch_ID_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.Long" - } - }, { - "key" : { - "name" : "item_ID_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "item_ID_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.Long" - } - }, { - "key" : { - "name" : "message_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "message_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.String" - } - }, { - "key" : { - "name" : "notes_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "notes_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.String" - } - }, { - "key" : { - "name" : "price_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "price_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.Long" - } - }, { - "key" : { - "name" : "quantity_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "quantity_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.Integer" - } - }, { - "key" : { - "name" : "sale_ID_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "sale_ID_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.Long" - } - }, { - "key" : { - "name" : "timestamp_type", - "version" : "0.0.1" - }, - "value" : { - "key" : { - "name" : "timestamp_type", - "version" : "0.0.1" - }, - "schemaFlavour" : "Java", - "schemaDefinition" : "java.lang.Long" - } - } ] - } + "schemas": { + "entry": [ + { + "key": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "assistant_ID_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.Long" + } + }, + { + "key": { + "name": "authorised_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "authorised_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.Boolean" + } + }, + { + "key": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "branch_ID_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.Long" + } + }, + { + "key": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "item_ID_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.Long" + } + }, + { + "key": { + "name": "message_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "message_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.String" + } + }, + { + "key": { + "name": "notes_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "notes_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.String" + } + }, + { + "key": { + "name": "price_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "price_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.Long" + } + }, + { + "key": { + "name": "quantity_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "quantity_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.Integer" + } + }, + { + "key": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "sale_ID_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.Long" + } + }, + { + "key": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "value": { + "key": { + "name": "timestamp_type", + "version": "0.0.1" + }, + "schemaFlavour": "Java", + "schemaDefinition": "java.lang.Long" + } + } + ] } - } + } + } } diff --git a/auth/cli-editor/src/test/resources/tosca/ToscaPolicyOutput_compare.json b/auth/cli-editor/src/test/resources/tosca/ToscaPolicyOutput_compare.json index ab2ae890e..55bd95eca 100644 --- a/auth/cli-editor/src/test/resources/tosca/ToscaPolicyOutput_compare.json +++ b/auth/cli-editor/src/test/resources/tosca/ToscaPolicyOutput_compare.json @@ -1 +1 @@ -{"tosca_definitions_version":"tosca_simple_yaml_1_1_0","topology_template":{"policies":[{"native.sampledomain":{"type":"onap.policies.native.Apex","type_version":"1.0.0","name":"native.sampledomain","version":"1.0.0","properties":{"engineServiceParameters":{"name":"MyFirstPolicyApexEngine","version":"0.0.1","id":101,"instanceCount":4,"deploymentPort":12345,"engineParameters":{"executorParameters":{"MVEL":{"parameterClassName":"org.onap.policy.apex.plugins.executor.mvel.MvelExecutorParameters"},"JAVASCRIPT":{"parameterClassName":"org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters"}}},"policy_type_impl":{"apexPolicyModel":{"key":{"name":"MyFirstPolicyModel","version":"0.0.1"},"keyInformation":{"key":{"name":"MyFirstPolicyModel_KeyInfo","version":"0.0.1"},"keyInfoMap":{"entry":[{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"value":{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"UUID":"3351b0f4-cf06-4fa2-8823-edf67bd30223","description":"This task checks if the sales request is for an item that contains alcohol. \nIf the local time is between 00:00:00 and 11:30:00 then the sale is not authorised. Otherwise the sale is authorised. \nIn this implementation we assume that all items with item_ID values between 1000 and 2000 contain alcohol :-)"}},{"key":{"name":"MyFirstPolicy","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicy","version":"0.0.1"},"UUID":"6c5e410f-489a-46ff-964e-982ce6e8b6d0","description":"This is my first Apex policy. It checks if a sale should be authorised or not."}},{"key":{"name":"MyFirstPolicyModel","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel","version":"0.0.1"},"UUID":"540226fb-55ee-4f0e-a444-983a0494818e","description":"This is my first Apex Policy Model."}},{"key":{"name":"MyFirstPolicyModel_Events","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_Events","version":"0.0.1"},"UUID":"ef281318-5ac9-3ef0-8db3-8f9c4e4a81e2","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_Events:0.0.1\""}},{"key":{"name":"MyFirstPolicyModel_KeyInfo","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_KeyInfo","version":"0.0.1"},"UUID":"d9248c6f-7c00-38df-8251-611463ba4065","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_KeyInfo:0.0.1\""}},{"key":{"name":"MyFirstPolicyModel_Policies","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_Policies","version":"0.0.1"},"UUID":"77c01a6b-510c-3aa9-b640-b4db356aa03b","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_Policies:0.0.1\""}},{"key":{"name":"MyFirstPolicyModel_Schemas","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_Schemas","version":"0.0.1"},"UUID":"d0cc3aa0-ea69-3a43-80ff-a0dbb0ebd885","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_Schemas:0.0.1\""}},{"key":{"name":"MyFirstPolicyModel_Tasks","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_Tasks","version":"0.0.1"},"UUID":"b02a7e02-2cd0-39e6-b3cb-946fa83a8f08","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_Tasks:0.0.1\""}},{"key":{"name":"SALE_AUTH","version":"0.0.1"},"value":{"key":{"name":"SALE_AUTH","version":"0.0.1"},"UUID":"c4500941-3f98-4080-a9cc-5b9753ed050b","description":"An event emitted by the Policy to indicate whether the sale of an item has been authorised"}},{"key":{"name":"SALE_INPUT","version":"0.0.1"},"value":{"key":{"name":"SALE_INPUT","version":"0.0.1"},"UUID":"4f04aa98-e917-4f4a-882a-c75ba5a99374","description":"An event raised by the PoS system each time an item is scanned for purchase"}},{"key":{"name":"assistant_ID_type","version":"0.0.1"},"value":{"key":{"name":"assistant_ID_type","version":"0.0.1"},"UUID":"36df4c71-9616-4206-8b53-976a5cd4bd87","description":"A type for 'assistant_ID' values"}},{"key":{"name":"authorised_type","version":"0.0.1"},"value":{"key":{"name":"authorised_type","version":"0.0.1"},"UUID":"d48b619e-d00d-4008-b884-02d76ea4350b","description":"A type for 'authorised' values"}},{"key":{"name":"branch_ID_type","version":"0.0.1"},"value":{"key":{"name":"branch_ID_type","version":"0.0.1"},"UUID":"6468845f-4122-4128-8e49-0f52c26078b5","description":"A type for 'branch_ID' values"}},{"key":{"name":"item_ID_type","version":"0.0.1"},"value":{"key":{"name":"item_ID_type","version":"0.0.1"},"UUID":"4f227ff1-aee0-453a-b6b6-9a4b2e0da932","description":"A type for 'item_ID' values"}},{"key":{"name":"message_type","version":"0.0.1"},"value":{"key":{"name":"message_type","version":"0.0.1"},"UUID":"ad1431bb-3155-4e73-b5a3-b89bee498749","description":"A type for 'message' values"}},{"key":{"name":"notes_type","version":"0.0.1"},"value":{"key":{"name":"notes_type","version":"0.0.1"},"UUID":"eecfde90-896c-4343-8f9c-2603ced94e2d","description":"A type for 'notes' values"}},{"key":{"name":"price_type","version":"0.0.1"},"value":{"key":{"name":"price_type","version":"0.0.1"},"UUID":"52c2fc45-fd8c-463c-bd6f-d91b0554aea7","description":"A type for 'amount'/'price' values"}},{"key":{"name":"quantity_type","version":"0.0.1"},"value":{"key":{"name":"quantity_type","version":"0.0.1"},"UUID":"ac3d9842-80af-4a98-951c-bd79a431c613","description":"A type for 'quantity' values"}},{"key":{"name":"sale_ID_type","version":"0.0.1"},"value":{"key":{"name":"sale_ID_type","version":"0.0.1"},"UUID":"cca47d74-7754-4a61-b163-ca31f66b157b","description":"A type for 'sale_ID' values"}},{"key":{"name":"timestamp_type","version":"0.0.1"},"value":{"key":{"name":"timestamp_type","version":"0.0.1"},"UUID":"fd594e88-411d-4a94-b2be-697b3a0d7adf","description":"A type for 'time' values"}}]}},"policies":{"key":{"name":"MyFirstPolicyModel_Policies","version":"0.0.1"},"policyMap":{"entry":[{"key":{"name":"MyFirstPolicy","version":"0.0.1"},"value":{"policyKey":{"name":"MyFirstPolicy","version":"0.0.1"},"template":"FREEFORM","state":{"entry":[{"key":"BoozeAuthDecide","value":{"stateKey":{"parentKeyName":"MyFirstPolicy","parentKeyVersion":"0.0.1","parentLocalName":"NULL","localName":"BoozeAuthDecide"},"trigger":{"name":"SALE_INPUT","version":"0.0.1"},"stateOutputs":{"entry":[{"key":"MorningBoozeCheck_Output_Direct","value":{"key":{"parentKeyName":"MyFirstPolicy","parentKeyVersion":"0.0.1","parentLocalName":"BoozeAuthDecide","localName":"MorningBoozeCheck_Output_Direct"},"outgoingEvent":{"name":"SALE_AUTH","version":"0.0.1"},"nextState":{"parentKeyName":"NULL","parentKeyVersion":"0.0.0","parentLocalName":"NULL","localName":"NULL"}}}]},"contextAlbumReference":[],"taskSelectionLogic":{"key":"NULL","logicFlavour":"UNDEFINED","logic":""},"stateFinalizerLogicMap":{"entry":[]},"defaultTask":{"name":"MorningBoozeCheck","version":"0.0.1"},"taskReferences":{"entry":[{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"value":{"key":{"parentKeyName":"MyFirstPolicy","parentKeyVersion":"0.0.1","parentLocalName":"BoozeAuthDecide","localName":"MorningBoozeCheck"},"outputType":"DIRECT","output":{"parentKeyName":"MyFirstPolicy","parentKeyVersion":"0.0.1","parentLocalName":"BoozeAuthDecide","localName":"MorningBoozeCheck_Output_Direct"}}}]}}}]},"firstState":"BoozeAuthDecide"}}]}},"tasks":{"key":{"name":"MyFirstPolicyModel_Tasks","version":"0.0.1"},"taskMap":{"entry":[{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"value":{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"inputFields":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]},"outputFields":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"authorised","value":{"key":"authorised","fieldSchemaKey":{"name":"authorised_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"message","value":{"key":"message","fieldSchemaKey":{"name":"message_type","version":"0.0.1"},"optional":true}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]},"taskParameters":{"entry":[]},"contextAlbumReference":[],"taskLogic":{"key":"TaskLogic","logicFlavour":"MVEL","logic":"/*\n * ============LICENSE_START=======================================================\n * Copyright (C) 2016-2018 Ericsson. All rights reserved.\n * Modifications Copyright (C) 2019 Nordix Foundation.\n * ================================================================================\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * SPDX-License-Identifier: Apache-2.0\n * ============LICENSE_END=========================================================\n */\nimport java.util.Date;\nimport java.util.Calendar;\nimport java.util.TimeZone;\nimport java.text.SimpleDateFormat;\n\nlogger.info(\"Task Execution: '\"+subject.id+\"'. Input Fields: '\"+inFields+\"'\");\n\noutFields.put(\"amount\" , inFields.get(\"amount\"));\noutFields.put(\"assistant_ID\", inFields.get(\"assistant_ID\"));\noutFields.put(\"notes\" , inFields.get(\"notes\"));\noutFields.put(\"quantity\" , inFields.get(\"quantity\"));\noutFields.put(\"branch_ID\" , inFields.get(\"branch_ID\"));\noutFields.put(\"item_ID\" , inFields.get(\"item_ID\"));\noutFields.put(\"time\" , inFields.get(\"time\"));\noutFields.put(\"sale_ID\" , inFields.get(\"sale_ID\"));\n\nitem_id = inFields.get(\"item_ID\");\n\n//The events used later to test this task use GMT timezone!\ngmt = TimeZone.getTimeZone(\"GMT\");\ntimenow = Calendar.getInstance(gmt);\ndf = new SimpleDateFormat(\"HH:mm:ss z\");\ndf.setTimeZone(gmt);\ntimenow.setTimeInMillis(inFields.get(\"time\"));\n\nmidnight = timenow.clone();\nmidnight.set(\n timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),\n timenow.get(Calendar.DATE),0,0,0);\neleven30 = timenow.clone();\neleven30.set(\n timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),\n timenow.get(Calendar.DATE),11,30,0);\n\nitemisalcohol = false;\nif(item_id != null && item_id >=1000 && item_id < 2000)\n itemisalcohol = true;\n\nif( itemisalcohol\n && timenow.after(midnight) && timenow.before(eleven30)){\n outFields.put(\"authorised\", false);\n outFields.put(\"message\", \"Sale not authorised by policy task \"+subject.taskName+\n \" for time \"+df.format(timenow.getTime())+\n \". Alcohol can not be sold between \"+df.format(midnight.getTime())+\n \" and \"+df.format(eleven30.getTime()));\n return true;\n}\nelse{\n outFields.put(\"authorised\", true);\n outFields.put(\"message\", \"Sale authorised by policy task \"+subject.taskName+\n \" for time \"+df.format(timenow.getTime()));\n return true;\n}\n\n/*\nThis task checks if a sale request is for an item that is an alcoholic drink.\nIf the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not\nauthorised. Otherwise the sale is authorised.\nIn this implementation we assume that items with item_ID value between 1000 and\n2000 are all alcoholic drinks :-)\n*/"}}}]}},"events":{"key":{"name":"MyFirstPolicyModel_Events","version":"0.0.1"},"eventMap":{"entry":[{"key":{"name":"SALE_AUTH","version":"0.0.1"},"value":{"key":{"name":"SALE_AUTH","version":"0.0.1"},"nameSpace":"com.hyperm","source":"APEX","target":"POS","parameter":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"authorised","value":{"key":"authorised","fieldSchemaKey":{"name":"authorised_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"message","value":{"key":"message","fieldSchemaKey":{"name":"message_type","version":"0.0.1"},"optional":true}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]}}},{"key":{"name":"SALE_INPUT","version":"0.0.1"},"value":{"key":{"name":"SALE_INPUT","version":"0.0.1"},"nameSpace":"com.hyperm","source":"POS","target":"APEX","parameter":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]}}}]}},"schemas":{"key":{"name":"MyFirstPolicyModel_Schemas","version":"0.0.1"},"schemas":{"entry":[{"key":{"name":"assistant_ID_type","version":"0.0.1"},"value":{"key":{"name":"assistant_ID_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"authorised_type","version":"0.0.1"},"value":{"key":{"name":"authorised_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Boolean"}},{"key":{"name":"branch_ID_type","version":"0.0.1"},"value":{"key":{"name":"branch_ID_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"item_ID_type","version":"0.0.1"},"value":{"key":{"name":"item_ID_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"message_type","version":"0.0.1"},"value":{"key":{"name":"message_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.String"}},{"key":{"name":"notes_type","version":"0.0.1"},"value":{"key":{"name":"notes_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.String"}},{"key":{"name":"price_type","version":"0.0.1"},"value":{"key":{"name":"price_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"quantity_type","version":"0.0.1"},"value":{"key":{"name":"quantity_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Integer"}},{"key":{"name":"sale_ID_type","version":"0.0.1"},"value":{"key":{"name":"sale_ID_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"timestamp_type","version":"0.0.1"},"value":{"key":{"name":"timestamp_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}}]}}}}},"eventOutputParameters":{"FirstProducer":{"carrierTechnologyParameters":{"carrierTechnology":"FILE","parameters":{"standardIo":true}},"eventProtocolParameters":{"eventProtocol":"JSON"}}},"eventInputParameters":{"FirstConsumer":{"carrierTechnologyParameters":{"carrierTechnology":"FILE","parameters":{"standardIo":true}},"eventProtocolParameters":{"eventProtocol":"JSON"}}}}}}]}}
\ No newline at end of file +{"tosca_definitions_version":"tosca_simple_yaml_1_1_0","topology_template":{"policies":[{"native.sampledomain":{"type":"onap.policies.native.Apex","type_version":"1.0.0","name":"native.sampledomain","version":"1.0.0","properties":{"engineServiceParameters":{"name":"MyFirstPolicyApexEngine","version":"0.0.1","id":101,"instanceCount":4,"deploymentPort":12345,"engineParameters":{"executorParameters":{"MVEL":{"parameterClassName":"org.onap.policy.apex.plugins.executor.mvel.MvelExecutorParameters"},"JAVASCRIPT":{"parameterClassName":"org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters"}}},"policy_type_impl":{"apexPolicyModel":{"key":{"name":"MyFirstPolicyModel","version":"0.0.1"},"keyInformation":{"key":{"name":"MyFirstPolicyModel_KeyInfo","version":"0.0.1"},"keyInfoMap":{"entry":[{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"value":{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"UUID":"3351b0f4-cf06-4fa2-8823-edf67bd30223","description":"This task checks if the sales request is for an item that contains alcohol. \nIf the local time is between 00:00:00 and 11:30:00 then the sale is not authorised. Otherwise the sale is authorised. \nIn this implementation we assume that all items with item_ID values between 1000 and 2000 contain alcohol :-)"}},{"key":{"name":"MyFirstPolicy","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicy","version":"0.0.1"},"UUID":"6c5e410f-489a-46ff-964e-982ce6e8b6d0","description":"This is my first Apex policy. It checks if a sale should be authorised or not."}},{"key":{"name":"MyFirstPolicyModel","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel","version":"0.0.1"},"UUID":"540226fb-55ee-4f0e-a444-983a0494818e","description":"This is my first Apex Policy Model."}},{"key":{"name":"MyFirstPolicyModel_Events","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_Events","version":"0.0.1"},"UUID":"ef281318-5ac9-3ef0-8db3-8f9c4e4a81e2","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_Events:0.0.1\""}},{"key":{"name":"MyFirstPolicyModel_KeyInfo","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_KeyInfo","version":"0.0.1"},"UUID":"d9248c6f-7c00-38df-8251-611463ba4065","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_KeyInfo:0.0.1\""}},{"key":{"name":"MyFirstPolicyModel_Policies","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_Policies","version":"0.0.1"},"UUID":"77c01a6b-510c-3aa9-b640-b4db356aa03b","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_Policies:0.0.1\""}},{"key":{"name":"MyFirstPolicyModel_Schemas","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_Schemas","version":"0.0.1"},"UUID":"d0cc3aa0-ea69-3a43-80ff-a0dbb0ebd885","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_Schemas:0.0.1\""}},{"key":{"name":"MyFirstPolicyModel_Tasks","version":"0.0.1"},"value":{"key":{"name":"MyFirstPolicyModel_Tasks","version":"0.0.1"},"UUID":"b02a7e02-2cd0-39e6-b3cb-946fa83a8f08","description":"Generated description for concept referred to by key \"MyFirstPolicyModel_Tasks:0.0.1\""}},{"key":{"name":"SALE_AUTH","version":"0.0.1"},"value":{"key":{"name":"SALE_AUTH","version":"0.0.1"},"UUID":"c4500941-3f98-4080-a9cc-5b9753ed050b","description":"An event emitted by the Policy to indicate whether the sale of an item has been authorised"}},{"key":{"name":"SALE_INPUT","version":"0.0.1"},"value":{"key":{"name":"SALE_INPUT","version":"0.0.1"},"UUID":"4f04aa98-e917-4f4a-882a-c75ba5a99374","description":"An event raised by the PoS system each time an item is scanned for purchase"}},{"key":{"name":"assistant_ID_type","version":"0.0.1"},"value":{"key":{"name":"assistant_ID_type","version":"0.0.1"},"UUID":"36df4c71-9616-4206-8b53-976a5cd4bd87","description":"A type for 'assistant_ID' values"}},{"key":{"name":"authorised_type","version":"0.0.1"},"value":{"key":{"name":"authorised_type","version":"0.0.1"},"UUID":"d48b619e-d00d-4008-b884-02d76ea4350b","description":"A type for 'authorised' values"}},{"key":{"name":"branch_ID_type","version":"0.0.1"},"value":{"key":{"name":"branch_ID_type","version":"0.0.1"},"UUID":"6468845f-4122-4128-8e49-0f52c26078b5","description":"A type for 'branch_ID' values"}},{"key":{"name":"item_ID_type","version":"0.0.1"},"value":{"key":{"name":"item_ID_type","version":"0.0.1"},"UUID":"4f227ff1-aee0-453a-b6b6-9a4b2e0da932","description":"A type for 'item_ID' values"}},{"key":{"name":"message_type","version":"0.0.1"},"value":{"key":{"name":"message_type","version":"0.0.1"},"UUID":"ad1431bb-3155-4e73-b5a3-b89bee498749","description":"A type for 'message' values"}},{"key":{"name":"notes_type","version":"0.0.1"},"value":{"key":{"name":"notes_type","version":"0.0.1"},"UUID":"eecfde90-896c-4343-8f9c-2603ced94e2d","description":"A type for 'notes' values"}},{"key":{"name":"price_type","version":"0.0.1"},"value":{"key":{"name":"price_type","version":"0.0.1"},"UUID":"52c2fc45-fd8c-463c-bd6f-d91b0554aea7","description":"A type for 'amount'/'price' values"}},{"key":{"name":"quantity_type","version":"0.0.1"},"value":{"key":{"name":"quantity_type","version":"0.0.1"},"UUID":"ac3d9842-80af-4a98-951c-bd79a431c613","description":"A type for 'quantity' values"}},{"key":{"name":"sale_ID_type","version":"0.0.1"},"value":{"key":{"name":"sale_ID_type","version":"0.0.1"},"UUID":"cca47d74-7754-4a61-b163-ca31f66b157b","description":"A type for 'sale_ID' values"}},{"key":{"name":"timestamp_type","version":"0.0.1"},"value":{"key":{"name":"timestamp_type","version":"0.0.1"},"UUID":"fd594e88-411d-4a94-b2be-697b3a0d7adf","description":"A type for 'time' values"}}]}},"policies":{"key":{"name":"MyFirstPolicyModel_Policies","version":"0.0.1"},"policyMap":{"entry":[{"key":{"name":"MyFirstPolicy","version":"0.0.1"},"value":{"policyKey":{"name":"MyFirstPolicy","version":"0.0.1"},"template":"FREEFORM","state":{"entry":[{"key":"BoozeAuthDecide","value":{"stateKey":{"parentKeyName":"MyFirstPolicy","parentKeyVersion":"0.0.1","parentLocalName":"NULL","localName":"BoozeAuthDecide"},"trigger":{"name":"SALE_INPUT","version":"0.0.1"},"stateOutputs":{"entry":[{"key":"MorningBoozeCheck_Output_Direct","value":{"key":{"parentKeyName":"MyFirstPolicy","parentKeyVersion":"0.0.1","parentLocalName":"BoozeAuthDecide","localName":"MorningBoozeCheck_Output_Direct"},"outgoingEvent":{"name":"SALE_AUTH","version":"0.0.1"},"outgoingEventReference":[{"name":"SALE_AUTH","version":"0.0.1"}],"nextState":{"parentKeyName":"NULL","parentKeyVersion":"0.0.0","parentLocalName":"NULL","localName":"NULL"}}}]},"contextAlbumReference":[],"taskSelectionLogic":{"key":"NULL","logicFlavour":"UNDEFINED","logic":""},"stateFinalizerLogicMap":{"entry":[]},"defaultTask":{"name":"MorningBoozeCheck","version":"0.0.1"},"taskReferences":{"entry":[{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"value":{"key":{"parentKeyName":"MyFirstPolicy","parentKeyVersion":"0.0.1","parentLocalName":"BoozeAuthDecide","localName":"MorningBoozeCheck"},"outputType":"DIRECT","output":{"parentKeyName":"MyFirstPolicy","parentKeyVersion":"0.0.1","parentLocalName":"BoozeAuthDecide","localName":"MorningBoozeCheck_Output_Direct"}}}]}}}]},"firstState":"BoozeAuthDecide"}}]}},"tasks":{"key":{"name":"MyFirstPolicyModel_Tasks","version":"0.0.1"},"taskMap":{"entry":[{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"value":{"key":{"name":"MorningBoozeCheck","version":"0.0.1"},"inputEvent":{"key":{"name":"SALE_INPUT","version":"0.0.1"},"nameSpace":"com.hyperm","source":"POS","target":"APEX","parameter":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]}},"outputEvents":{"entry":[{"key":"SALE_AUTH","value":{"key":{"name":"SALE_AUTH","version":"0.0.1"},"nameSpace":"com.hyperm","source":"APEX","target":"POS","parameter":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"authorised","value":{"key":"authorised","fieldSchemaKey":{"name":"authorised_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"message","value":{"key":"message","fieldSchemaKey":{"name":"message_type","version":"0.0.1"},"optional":true}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]}}}]},"inputFields":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]},"outputFields":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"authorised","value":{"key":"authorised","fieldSchemaKey":{"name":"authorised_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"message","value":{"key":"message","fieldSchemaKey":{"name":"message_type","version":"0.0.1"},"optional":true}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]},"taskParameters":{"entry":[]},"contextAlbumReference":[],"taskLogic":{"key":"TaskLogic","logicFlavour":"MVEL","logic":"/*\n * ============LICENSE_START=======================================================\n * Copyright (C) 2016-2018 Ericsson. All rights reserved.\n * Modifications Copyright (C) 2019 Nordix Foundation.\n * ================================================================================\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * SPDX-License-Identifier: Apache-2.0\n * ============LICENSE_END=========================================================\n */\nimport java.util.Date;\nimport java.util.Calendar;\nimport java.util.TimeZone;\nimport java.text.SimpleDateFormat;\n\nlogger.info(\"Task Execution: '\"+subject.id+\"'. Input Fields: '\"+inFields+\"'\");\n\noutFields.put(\"amount\" , inFields.get(\"amount\"));\noutFields.put(\"assistant_ID\", inFields.get(\"assistant_ID\"));\noutFields.put(\"notes\" , inFields.get(\"notes\"));\noutFields.put(\"quantity\" , inFields.get(\"quantity\"));\noutFields.put(\"branch_ID\" , inFields.get(\"branch_ID\"));\noutFields.put(\"item_ID\" , inFields.get(\"item_ID\"));\noutFields.put(\"time\" , inFields.get(\"time\"));\noutFields.put(\"sale_ID\" , inFields.get(\"sale_ID\"));\n\nitem_id = inFields.get(\"item_ID\");\n\n//The events used later to test this task use GMT timezone!\ngmt = TimeZone.getTimeZone(\"GMT\");\ntimenow = Calendar.getInstance(gmt);\ndf = new SimpleDateFormat(\"HH:mm:ss z\");\ndf.setTimeZone(gmt);\ntimenow.setTimeInMillis(inFields.get(\"time\"));\n\nmidnight = timenow.clone();\nmidnight.set(\n timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),\n timenow.get(Calendar.DATE),0,0,0);\neleven30 = timenow.clone();\neleven30.set(\n timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH),\n timenow.get(Calendar.DATE),11,30,0);\n\nitemisalcohol = false;\nif(item_id != null && item_id >=1000 && item_id < 2000)\n itemisalcohol = true;\n\nif( itemisalcohol\n && timenow.after(midnight) && timenow.before(eleven30)){\n outFields.put(\"authorised\", false);\n outFields.put(\"message\", \"Sale not authorised by policy task \"+subject.taskName+\n \" for time \"+df.format(timenow.getTime())+\n \". Alcohol can not be sold between \"+df.format(midnight.getTime())+\n \" and \"+df.format(eleven30.getTime()));\n return true;\n}\nelse{\n outFields.put(\"authorised\", true);\n outFields.put(\"message\", \"Sale authorised by policy task \"+subject.taskName+\n \" for time \"+df.format(timenow.getTime()));\n return true;\n}\n\n/*\nThis task checks if a sale request is for an item that is an alcoholic drink.\nIf the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not\nauthorised. Otherwise the sale is authorised.\nIn this implementation we assume that items with item_ID value between 1000 and\n2000 are all alcoholic drinks :-)\n*/"}}}]}},"events":{"key":{"name":"MyFirstPolicyModel_Events","version":"0.0.1"},"eventMap":{"entry":[{"key":{"name":"SALE_AUTH","version":"0.0.1"},"value":{"key":{"name":"SALE_AUTH","version":"0.0.1"},"nameSpace":"com.hyperm","source":"APEX","target":"POS","parameter":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"authorised","value":{"key":"authorised","fieldSchemaKey":{"name":"authorised_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"message","value":{"key":"message","fieldSchemaKey":{"name":"message_type","version":"0.0.1"},"optional":true}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]}}},{"key":{"name":"SALE_INPUT","version":"0.0.1"},"value":{"key":{"name":"SALE_INPUT","version":"0.0.1"},"nameSpace":"com.hyperm","source":"POS","target":"APEX","parameter":{"entry":[{"key":"amount","value":{"key":"amount","fieldSchemaKey":{"name":"price_type","version":"0.0.1"},"optional":false}},{"key":"assistant_ID","value":{"key":"assistant_ID","fieldSchemaKey":{"name":"assistant_ID_type","version":"0.0.1"},"optional":false}},{"key":"branch_ID","value":{"key":"branch_ID","fieldSchemaKey":{"name":"branch_ID_type","version":"0.0.1"},"optional":false}},{"key":"item_ID","value":{"key":"item_ID","fieldSchemaKey":{"name":"item_ID_type","version":"0.0.1"},"optional":false}},{"key":"notes","value":{"key":"notes","fieldSchemaKey":{"name":"notes_type","version":"0.0.1"},"optional":true}},{"key":"quantity","value":{"key":"quantity","fieldSchemaKey":{"name":"quantity_type","version":"0.0.1"},"optional":false}},{"key":"sale_ID","value":{"key":"sale_ID","fieldSchemaKey":{"name":"sale_ID_type","version":"0.0.1"},"optional":false}},{"key":"time","value":{"key":"time","fieldSchemaKey":{"name":"timestamp_type","version":"0.0.1"},"optional":false}}]}}}]}},"schemas":{"key":{"name":"MyFirstPolicyModel_Schemas","version":"0.0.1"},"schemas":{"entry":[{"key":{"name":"assistant_ID_type","version":"0.0.1"},"value":{"key":{"name":"assistant_ID_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"authorised_type","version":"0.0.1"},"value":{"key":{"name":"authorised_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Boolean"}},{"key":{"name":"branch_ID_type","version":"0.0.1"},"value":{"key":{"name":"branch_ID_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"item_ID_type","version":"0.0.1"},"value":{"key":{"name":"item_ID_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"message_type","version":"0.0.1"},"value":{"key":{"name":"message_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.String"}},{"key":{"name":"notes_type","version":"0.0.1"},"value":{"key":{"name":"notes_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.String"}},{"key":{"name":"price_type","version":"0.0.1"},"value":{"key":{"name":"price_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"quantity_type","version":"0.0.1"},"value":{"key":{"name":"quantity_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Integer"}},{"key":{"name":"sale_ID_type","version":"0.0.1"},"value":{"key":{"name":"sale_ID_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}},{"key":{"name":"timestamp_type","version":"0.0.1"},"value":{"key":{"name":"timestamp_type","version":"0.0.1"},"schemaFlavour":"Java","schemaDefinition":"java.lang.Long"}}]}}}}},"eventOutputParameters":{"FirstProducer":{"carrierTechnologyParameters":{"carrierTechnology":"FILE","parameters":{"standardIo":true}},"eventProtocolParameters":{"eventProtocol":"JSON"}}},"eventInputParameters":{"FirstConsumer":{"carrierTechnologyParameters":{"carrierTechnology":"FILE","parameters":{"standardIo":true}},"eventProtocolParameters":{"eventProtocol":"JSON"}}}}}}]}}
\ No newline at end of file diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java index fd5fe131f..878d5277a 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/ApexEngineImpl.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,9 +24,13 @@ package org.onap.policy.apex.core.engine.engine.impl; import static org.onap.policy.common.utils.validation.Assertions.argumentNotNull; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; import org.onap.policy.apex.context.ContextAlbum; import org.onap.policy.apex.context.ContextException; import org.onap.policy.apex.core.engine.context.ApexInternalContext; @@ -41,7 +46,12 @@ import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; import org.onap.policy.apex.model.enginemodel.concepts.AxEngineModel; import org.onap.policy.apex.model.enginemodel.concepts.AxEngineState; import org.onap.policy.apex.model.enginemodel.concepts.AxEngineStats; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel; +import org.onap.policy.apex.model.policymodel.concepts.AxState; +import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput; +import org.onap.policy.apex.model.policymodel.concepts.AxStateTaskReference; +import org.onap.policy.apex.model.policymodel.concepts.AxTask; import org.slf4j.ext.XLogger; import org.slf4j.ext.XLoggerFactory; @@ -122,6 +132,8 @@ public class ApexEngineImpl implements ApexEngine { } } + populateIoEventsToTask(apexModel); + // Create new internal context or update the existing one try { if (internalContext == null) { @@ -149,6 +161,48 @@ public class ApexEngineImpl implements ApexEngine { LOGGER.exit(UPDATE_MODEL + key.getId()); } + + private void populateIoEventsToTask(AxPolicyModel apexPolicyModel) { + Set<AxArtifactKey> updatedTasks = new TreeSet<>(); + for (var axPolicy : apexPolicyModel.getPolicies().getPolicyMap().values()) { + for (var axState : axPolicy.getStateMap().values()) { + AxEvent triggerEvent = apexPolicyModel.getEvents().get(axState.getTrigger()); + axState.getTaskReferences().forEach((taskKey, taskRef) -> { + AxTask task = apexPolicyModel.getTasks().getTaskMap().get(taskKey); + task.setInputEvent(triggerEvent); + updateTaskBasedOnStateOutput(apexPolicyModel, updatedTasks, axState, taskKey, taskRef, task); + updatedTasks.add(taskKey); + }); + } + } + } + + private void updateTaskBasedOnStateOutput(AxPolicyModel apexPolicyModel, Set<AxArtifactKey> updatedTasks, + AxState state, AxArtifactKey taskKey, AxStateTaskReference taskRef, AxTask task) { + Map<String, AxEvent> outputEvents = new TreeMap<>(); + AxStateOutput stateOutput = state.getStateOutputs().get(taskRef.getOutput().getLocalName()); + if (null == stateOutput.getOutgoingEventSet() || stateOutput.getOutgoingEventSet().isEmpty()) { + Set<AxArtifactKey> outEventSet = new TreeSet<>(); + outEventSet.add(stateOutput.getOutgoingEvent()); + stateOutput.setOutgoingEventSet(outEventSet); + } + if (state.getNextStateSet().isEmpty() + || state.getNextStateSet().contains(AxReferenceKey.getNullKey().getLocalName())) { + stateOutput.getOutgoingEventSet().forEach(outgoingEventKey -> outputEvents.put(outgoingEventKey.getName(), + apexPolicyModel.getEvents().get(outgoingEventKey))); + } else { + AxArtifactKey outgoingEventKey = stateOutput.getOutgoingEvent(); + outputEvents.put(outgoingEventKey.getName(), apexPolicyModel.getEvents().get(outgoingEventKey)); + } + if (updatedTasks.contains(taskKey)) { + // this happens only when same task is used by multiple policies + // with different eventName but same fields + task.getOutputEvents().putAll(outputEvents); + } else { + task.setOutputEvents(outputEvents); + } + } + /** * {@inheritDoc}. */ @@ -288,7 +342,7 @@ public class ApexEngineImpl implements ApexEngine { */ @Override public boolean handleEvent(final EnEvent incomingEvent) { - boolean ret = false; + var ret = false; if (incomingEvent == null) { LOGGER.warn("handleEvent()<-{},{}, cannot run engine, incoming event is null", key.getId(), state); return ret; @@ -307,17 +361,17 @@ public class ApexEngineImpl implements ApexEngine { LOGGER.debug(message); // By default we return a null event on errors - EnEvent outgoingEvent = null; + Collection<EnEvent> outgoingEvents = null; try { engineStats.executionEnter(incomingEvent.getKey()); - outgoingEvent = stateMachineHandler.execute(incomingEvent); + outgoingEvents = stateMachineHandler.execute(incomingEvent); engineStats.executionExit(); ret = true; } catch (final StateMachineException e) { LOGGER.warn("handleEvent()<-{},{}, engine execution error: ", key.getId(), state, e); // Create an exception return event - outgoingEvent = createExceptionEvent(incomingEvent, e); + outgoingEvents = createExceptionEvent(incomingEvent, e); } // Publish the outgoing event @@ -325,10 +379,12 @@ public class ApexEngineImpl implements ApexEngine { synchronized (eventListeners) { if (eventListeners.isEmpty()) { LOGGER.debug("handleEvent()<-{},{}, There is no listener registered to recieve outgoing event: {}", - key.getId(), state, outgoingEvent); + key.getId(), state, outgoingEvents); } for (final EnEventListener axEventListener : eventListeners.values()) { - axEventListener.onEnEvent(outgoingEvent); + for (var outgoingEvent : outgoingEvents) { + axEventListener.onEnEvent(outgoingEvent); + } } } } catch (final ApexException e) { @@ -398,7 +454,7 @@ public class ApexEngineImpl implements ApexEngine { */ @Override public AxEngineModel getEngineStatus() { - final AxEngineModel engineModel = new AxEngineModel(key); + final var engineModel = new AxEngineModel(key); engineModel.setTimestamp(System.currentTimeMillis()); engineModel.setState(state); engineModel.setStats(engineStats); @@ -440,14 +496,14 @@ public class ApexEngineImpl implements ApexEngine { * @param eventException The exception that was thrown * @return the exception event */ - private EnEvent createExceptionEvent(final EnEvent incomingEvent, final Exception eventException) { + private Set<EnEvent> createExceptionEvent(final EnEvent incomingEvent, final Exception eventException) { // The exception event is a clone of the incoming event with the exception suffix added to // its name and an extra // field "ExceptionMessage" added final EnEvent exceptionEvent = (EnEvent) incomingEvent.clone(); // Create the cascaded message string - final StringBuilder exceptionMessageStringBuilder = new StringBuilder(); + final var exceptionMessageStringBuilder = new StringBuilder(); exceptionMessageStringBuilder.append(eventException.getMessage()); Throwable subException = eventException.getCause(); @@ -460,6 +516,6 @@ public class ApexEngineImpl implements ApexEngine { // Set the exception message on the event exceptionEvent.setExceptionMessage(exceptionMessageStringBuilder.toString()); - return exceptionEvent; + return Set.of(exceptionEvent); } } diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/StateMachineHandler.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/StateMachineHandler.java index 32f86e465..c173d1f09 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/StateMachineHandler.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/engine/impl/StateMachineHandler.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +21,9 @@ package org.onap.policy.apex.core.engine.engine.impl; +import java.util.Collection; import java.util.HashMap; +import java.util.Set; import org.onap.policy.apex.core.engine.context.ApexInternalContext; import org.onap.policy.apex.core.engine.event.EnEvent; import org.onap.policy.apex.core.engine.executor.ExecutorFactory; @@ -79,8 +82,7 @@ public class StateMachineHandler { // Iterate over the policies in the policy model and create a state machine for each one for (final AxPolicy policy : ModelService.getModel(AxPolicies.class).getPolicyMap().values()) { // Create a state machine for this policy - final StateMachineExecutor thisStateMachineExecutor = - new StateMachineExecutor(executorFactory, policy.getKey()); + final var thisStateMachineExecutor = new StateMachineExecutor(executorFactory, policy.getKey()); // This executor is the top executor so has no parent thisStateMachineExecutor.setContext(null, policy, internalContext); @@ -90,8 +92,7 @@ public class StateMachineHandler { .get(policy.getStateMap().get(policy.getFirstState()).getTrigger()); // Put the state machine executor on the map for this trigger - final StateMachineExecutor lastStateMachineExecutor = - stateMachineExecutorMap.put(triggerEvent, thisStateMachineExecutor); + final var lastStateMachineExecutor = stateMachineExecutorMap.put(triggerEvent, thisStateMachineExecutor); if (lastStateMachineExecutor != null && lastStateMachineExecutor.getSubject() != thisStateMachineExecutor.getSubject()) { LOGGER.error("No more than one policy in a model can have the same trigger event. In model " @@ -138,32 +139,32 @@ public class StateMachineHandler { * @return The result of the state machine execution run * @throws StateMachineException On execution errors in a state machine */ - protected EnEvent execute(final EnEvent event) throws StateMachineException { + protected Collection<EnEvent> execute(final EnEvent event) throws StateMachineException { LOGGER.entry("execute()->" + event.getName()); // Try to execute the state machine for the trigger - final StateMachineExecutor stateMachineExecutor = stateMachineExecutorMap.get(event.getAxEvent()); + final var stateMachineExecutor = stateMachineExecutorMap.get(event.getAxEvent()); if (stateMachineExecutor == null) { final String exceptionMessage = - "state machine execution not possible, policy not found for trigger event " + event.getName(); + "state machine execution not possible, policy not found for trigger event " + event.getName(); LOGGER.warn(exceptionMessage); event.setExceptionMessage(exceptionMessage); - return event; + return Set.of(event); } // Run the state machine try { LOGGER.debug("execute(): state machine \"{}\" execution starting . . .", stateMachineExecutor); - final EnEvent outputObject = - stateMachineExecutor.execute(event.getExecutionId(), event.getExecutionProperties(), event); + final Collection<EnEvent> outputEvents = + stateMachineExecutor.execute(event.getExecutionId(), event.getExecutionProperties(), event); LOGGER.debug("execute()<-: state machine \"{}\" execution completed", stateMachineExecutor); - return outputObject; + return outputEvents; } catch (final Exception e) { LOGGER.warn("execute()<-: state machine \"" + stateMachineExecutor + "\" execution failed", e); throw new StateMachineException("execute()<-: execution failed on state machine " + stateMachineExecutor, - e); + e); } } diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateExecutor.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateExecutor.java index b04c354e5..11d0aa1c9 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateExecutor.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -196,7 +197,7 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap // Execute the task final TreeMap<String, Object> incomingValues = new TreeMap<>(); incomingValues.putAll(incomingEvent); - final Map<String, Object> taskExecutionResultMap = + final Map<String, Map<String, Object>> taskExecutionResultMap = taskExecutorMap.get(taskKey).execute(executionId, executionProperties, incomingValues); final AxTask task = taskExecutorMap.get(taskKey).getSubject(); @@ -215,8 +216,9 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap // Execute the state finalizer logic to select a state output and to adjust the // taskExecutionResultMap - stateOutputName = - finalizerLogicExecutor.execute(executionId, executionProperties, taskExecutionResultMap); + // Multiple event outputs are possible only from final state, otherwise there will be only 1 outputevent + stateOutputName = finalizerLogicExecutor.execute(executionId, executionProperties, + taskExecutionResultMap.values().iterator().next()); } // Now look up the the actual state output @@ -227,19 +229,19 @@ public class StateExecutor implements Executor<EnEvent, StateOutput, AxState, Ap } // Create the state output and transfer all the fields across to its event - final StateOutput stateOutput = new StateOutput(stateOutputDefinition); + final var stateOutput = new StateOutput(stateOutputDefinition); this.lastStateOutput = stateOutput; - stateOutput.setEventFields(task.getRawOutputFields(), taskExecutionResultMap); + stateOutput.setEventFields(task.getOutputEvents(), taskExecutionResultMap); // Copy across fields from the incoming event that are not set on the outgoing event stateOutput.copyUnsetFields(incomingEvent); // Set the ExecutionID for the outgoing event to the value in the incoming event. - if (stateOutput.getOutputEvent() != null) { - stateOutput.getOutputEvent().setExecutionId(incomingEvent.getExecutionId()); - stateOutput.getOutputEvent().setExecutionProperties(incomingEvent.getExecutionProperties()); - } + stateOutput.getOutputEvents().values().forEach(outputEvent -> { + outputEvent.setExecutionId(incomingEvent.getExecutionId()); + outputEvent.setExecutionProperties(incomingEvent.getExecutionProperties()); + }); // That's it, the state execution is complete return stateOutput; diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java index 67a3e6d79..52429a215 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,8 @@ package org.onap.policy.apex.core.engine.executor; +import java.util.Collection; +import java.util.Collections; import java.util.Map; import java.util.Properties; import java.util.TreeMap; @@ -41,7 +44,7 @@ import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput; * @author Sven van der Meer (sven.van.der.meer@ericsson.com) * @author Liam Fallon (liam.fallon@ericsson.com) */ -public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> { +public class StateMachineExecutor implements Executor<EnEvent, Collection<EnEvent>, AxPolicy, ApexInternalContext> { // The Apex Policy and context for this state machine private AxPolicy axPolicy = null; private Executor<?, ?, ?, ?> parent = null; @@ -54,7 +57,7 @@ public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy private StateExecutor firstExecutor = null; // The next state machine executor - private Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> nextExecutor = null; + private Executor<EnEvent, Collection<EnEvent>, AxPolicy, ApexInternalContext> nextExecutor = null; // The executor factory private ExecutorFactory executorFactory = null; @@ -120,8 +123,8 @@ public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy * {@inheritDoc}. */ @Override - public EnEvent execute(final long executionId, final Properties executionProperties, final EnEvent incomingEvent) - throws StateMachineException, ContextException { + public Collection<EnEvent> execute(final long executionId, final Properties executionProperties, + final EnEvent incomingEvent) throws StateMachineException, ContextException { // Check if there are any states on the state machine if (stateExecutorMap.size() == 0) { throw new StateMachineException("no states defined on state machine"); @@ -139,8 +142,10 @@ public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy incomingEvent.getKey(), firstExecutor.getSubject().getKey()), incomingEvent); while (true) { - // Execute the state, it returns an output or throws an exception - stateOutput = stateExecutor.execute(executionId, executionProperties, stateOutput.getOutputEvent()); + // OutputEventSet in a stateoutput can contain multiple events only when it is of the final state + // otherwise, there can be only 1 item in outputEventSet + stateOutput = stateExecutor.execute(executionId, executionProperties, + stateOutput.getOutputEvents().values().iterator().next()); // Use the next state of the state output to find if all the states have executed if (stateOutput.getNextState().equals(AxReferenceKey.getNullKey())) { @@ -155,7 +160,7 @@ public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy } } - return stateOutput.getOutputEvent(); + return stateOutput.getOutputEvents().values(); } /** @@ -229,15 +234,16 @@ public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy * {@inheritDoc}. */ @Override - public final EnEvent getOutgoing() { - return null; + public final Collection<EnEvent> getOutgoing() { + return Collections.emptyList(); } /** * {@inheritDoc}. */ @Override - public final void setNext(final Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> newNextExecutor) { + public final void setNext( + final Executor<EnEvent, Collection<EnEvent>, AxPolicy, ApexInternalContext> newNextExecutor) { this.nextExecutor = newNextExecutor; } @@ -245,7 +251,7 @@ public class StateMachineExecutor implements Executor<EnEvent, EnEvent, AxPolicy * {@inheritDoc}. */ @Override - public final Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> getNext() { + public final Executor<EnEvent, Collection<EnEvent>, AxPolicy, ApexInternalContext> getNext() { return nextExecutor; } diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateOutput.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateOutput.java index 9c3c6f893..535565415 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateOutput.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/StateOutput.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +24,15 @@ package org.onap.policy.apex.core.engine.executor; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.stream.Collectors; +import lombok.Getter; import org.onap.policy.apex.core.engine.event.EnEvent; import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; +import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; import org.onap.policy.apex.model.basicmodel.service.ModelService; import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; @@ -38,11 +46,12 @@ import org.onap.policy.common.utils.validation.Assertions; * * @author Liam Fallon (liam.fallon@ericsson.com) */ +@Getter public class StateOutput { // The state output has a state and an event private final AxStateOutput stateOutputDefinition; - private final AxEvent outputEventDef; - private final EnEvent outputEvent; + private AxEvent outputEventDef; + private final Map<AxArtifactKey, EnEvent> outputEvents; /** * Create a new state output from a state output definition. @@ -50,7 +59,7 @@ public class StateOutput { * @param axStateOutput the state output definition */ public StateOutput(final AxStateOutput axStateOutput) { - this(axStateOutput, new EnEvent(axStateOutput.getOutgingEvent())); + this(axStateOutput, new EnEvent(axStateOutput.getOutgoingEvent())); } /** @@ -64,8 +73,15 @@ public class StateOutput { Assertions.argumentNotNull(outputEvent, "outputEvent may not be null"); this.stateOutputDefinition = stateOutputDefinition; - this.outputEvent = outputEvent; - outputEventDef = ModelService.getModel(AxEvents.class).get(stateOutputDefinition.getOutgingEvent()); + this.outputEvents = new TreeMap<>(); + if (stateOutputDefinition.getOutgoingEventSet() != null + && !stateOutputDefinition.getOutgoingEventSet().isEmpty()) { + stateOutputDefinition.getOutgoingEventSet() + .forEach(outEvent -> outputEvents.put(outEvent, new EnEvent(outEvent))); + } else { + outputEvents.put(outputEvent.getKey(), outputEvent); + } + outputEventDef = ModelService.getModel(AxEvents.class).get(stateOutputDefinition.getOutgoingEvent()); } /** @@ -78,52 +94,89 @@ public class StateOutput { } /** - * Gets the state output definition. - * - * @return the state output definition - */ - public AxStateOutput getStateOutputDefinition() { - return stateOutputDefinition; - } - - /** - * Gets the output event. - * - * @return the output event - */ - public EnEvent getOutputEvent() { - return outputEvent; - } - - /** * Transfer the fields from the incoming field map into the event. * - * @param incomingFieldDefinitionMap definitions of the incoming fields - * @param eventFieldMap the event field map + * @param incomingEventDefinitionMap definitions of the incoming fields + * @param eventFieldMaps the event field map * @throws StateMachineException on errors populating the event fields */ - public void setEventFields(final Map<String, AxField> incomingFieldDefinitionMap, - final Map<String, Object> eventFieldMap) throws StateMachineException { - Assertions.argumentNotNull(incomingFieldDefinitionMap, "incomingFieldDefinitionMap may not be null"); - Assertions.argumentNotNull(eventFieldMap, "eventFieldMap may not be null"); - - if (!incomingFieldDefinitionMap.keySet().equals(eventFieldMap.keySet())) { - throw new StateMachineException( - "field definitions and values do not match for event " + outputEventDef.getId() + '\n' - + incomingFieldDefinitionMap.keySet() + '\n' + eventFieldMap.keySet()); + public void setEventFields(final Map<String, AxEvent> incomingEventDefinitionMap, + final Map<String, Map<String, Object>> eventFieldMaps) throws StateMachineException { + Assertions.argumentNotNull(incomingEventDefinitionMap, "incomingFieldDefinitionMap may not be null"); + Assertions.argumentNotNull(eventFieldMaps, "eventFieldMaps may not be null"); + + for (Entry<String, AxEvent> incomingEventDefinitionEntry : incomingEventDefinitionMap.entrySet()) { + String eventName = incomingEventDefinitionEntry.getKey(); + AxEvent eventDef = incomingEventDefinitionEntry.getValue(); + if (!eventDef.getParameterMap().keySet().equals(eventFieldMaps.get(eventName).keySet())) { + throw new StateMachineException( + "field definitions and values do not match for event " + eventDef.getId() + '\n' + + eventDef.getParameterMap().keySet() + '\n' + eventFieldMaps.get(eventName).keySet()); + } + } + var updateOnceFlag = false; + if (!outputEvents.keySet().stream().map(AxArtifactKey::getName).collect(Collectors.toSet()) + .equals(eventFieldMaps.keySet())) { + // when same task is used by multiple policies with different eventName but same fields, + // state outputs and task output events may be different + // in this case, update the output fields in the state output only once to avoid overwriting. + updateOnceFlag = true; } - for (final Entry<String, Object> incomingFieldEntry : eventFieldMap.entrySet()) { - final String fieldName = incomingFieldEntry.getKey(); - final AxField fieldDef = incomingFieldDefinitionMap.get(fieldName); + for (Entry<String, Map<String, Object>> eventFieldMapEntry : eventFieldMaps.entrySet()) { + String eventName = eventFieldMapEntry.getKey(); + Map<String, Object> outputEventFields = eventFieldMapEntry.getValue(); + AxEvent taskOutputEvent = incomingEventDefinitionMap.get(eventName); + EnEvent outputEventToUpdate = outputEvents.get(taskOutputEvent.getKey()); + + if (null == outputEventToUpdate) { + // happens only when same task is used by multiple policies with different eventName but same fields + // in this case, just match the fields and get the event in the stateOutput + Set<String> outputEventFieldNames = outputEventFields.keySet(); + Optional<EnEvent> outputEventOpt = outputEvents.values().stream().filter(outputEvent -> outputEvent + .getAxEvent().getParameterMap().keySet().equals(outputEventFieldNames)).findFirst(); + if (outputEventOpt.isEmpty()) { + throw new StateMachineException( + "Task output event field definition and state output event field doesn't match"); + } else { + outputEventToUpdate = outputEventOpt.get(); + } + } + updateOutputEventFields(taskOutputEvent, outputEventFields, outputEventToUpdate); + if (updateOnceFlag) { + break; + } + } + } + private void updateOutputEventFields(AxEvent taskOutputEvent, Map<String, Object> outputEventFields, + EnEvent outputEventToUpdate) throws StateMachineException { + for (Entry<String, Object> outputEventFieldEntry : outputEventFields.entrySet()) { + String fieldName = outputEventFieldEntry.getKey(); + Object fieldValue = outputEventFieldEntry.getValue(); + final AxField fieldDef = taskOutputEvent.getParameterMap().get(fieldName); + + Set<AxArtifactKey> outgoingEventSet = new TreeSet<>(); + if (null == stateOutputDefinition.getOutgoingEventSet() + || stateOutputDefinition.getOutgoingEventSet().isEmpty()) { + // if current state is not the final state, then the set could be empty. + // Just take the outgoingEvent field in this case + outgoingEventSet.add(stateOutputDefinition.getOutgoingEvent()); + } else { + outgoingEventSet.addAll(stateOutputDefinition.getOutgoingEventSet()); + } // Check if this field is a field in the event - if (!outputEventDef.getFields().contains(fieldDef)) { - throw new StateMachineException("field \"" + fieldName + "\" does not exist on event \"" - + outputEventDef.getId() + "\""); + for (AxArtifactKey outputEventKey : outgoingEventSet) { + if (outputEventKey.equals(taskOutputEvent.getKey())) { + outputEventDef = ModelService.getModel(AxEvents.class).get(outputEventKey); + // Check if this field is a field in the state output event + if (!outputEventDef.getFields().contains(fieldDef)) { + throw new StateMachineException( + "field \"" + fieldName + "\" does not exist on event \"" + outputEventDef.getId() + "\""); + } + } } - - // Set the value in the output event - outputEvent.put(fieldName, incomingFieldEntry.getValue()); + // Set the value in the correct output event + outputEventToUpdate.put(fieldName, fieldValue); } } @@ -135,25 +188,30 @@ public class StateOutput { */ public void copyUnsetFields(final EnEvent incomingEvent) { Assertions.argumentNotNull(incomingEvent, "incomingEvent may not be null"); - - for (final Entry<String, Object> incomingField : incomingEvent.entrySet()) { - final String fieldName = incomingField.getKey(); - - // Check if the field exists on the outgoing event - if ((!outputEventDef.getParameterMap().containsKey(fieldName)) - - // Check if the field is set on the outgoing event - || (outputEvent.containsKey(fieldName)) - - // Now, check the fields have the same type - || (!incomingEvent.getAxEvent().getParameterMap().get(fieldName) - .equals(outputEvent.getAxEvent().getParameterMap().get(fieldName)))) { - continue; - } - - // All checks done, we can copy the value - outputEvent.put(fieldName, incomingField.getValue()); + Set<AxArtifactKey> outgoingEventSet = new TreeSet<>(); + if (null == stateOutputDefinition.getOutgoingEventSet() + || stateOutputDefinition.getOutgoingEventSet().isEmpty()) { + // if current state is not the final state, then the set could be empty. + // Just take the outgoingEvent field in this case + outgoingEventSet.add(stateOutputDefinition.getOutgoingEvent()); + } else { + outgoingEventSet.addAll(stateOutputDefinition.getOutgoingEventSet()); } - + incomingEvent.forEach((inFieldName, inFieldValue) -> { + for (AxArtifactKey outputEventKey : outgoingEventSet) { + outputEventDef = ModelService.getModel(AxEvents.class).get(outputEventKey); + // Check if the field exists on the outgoing event + if (!outputEventDef.getParameterMap().containsKey(inFieldName) + // Check if the field is set in the outgoing event + || outputEvents.get(outputEventKey).containsKey(inFieldName) + // Now, check the fields have the same type + || !incomingEvent.getAxEvent().getParameterMap().get(inFieldName) + .equals(outputEvents.get(outputEventKey).getAxEvent().getParameterMap().get(inFieldName))) { + continue; + } + // All checks done, we can copy the value + outputEvents.get(outputEventKey).put(inFieldName, inFieldValue); + } + }); } } diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java index 0150b65b2..31e27d244 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/TaskExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +25,6 @@ package org.onap.policy.apex.core.engine.executor; import static org.onap.policy.common.utils.validation.Assertions.argumentOfClassNotNull; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; @@ -41,8 +41,7 @@ import org.onap.policy.apex.core.engine.executor.context.TaskExecutionContext; import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; -import org.onap.policy.apex.model.eventmodel.concepts.AxInputField; -import org.onap.policy.apex.model.eventmodel.concepts.AxOutputField; +import org.onap.policy.apex.model.eventmodel.concepts.AxField; import org.onap.policy.apex.model.policymodel.concepts.AxTask; import org.onap.policy.apex.model.policymodel.concepts.AxTaskParameter; import org.slf4j.ext.XLogger; @@ -56,7 +55,7 @@ import org.slf4j.ext.XLoggerFactory; * @author Liam Fallon (liam.fallon@ericsson.com) */ public abstract class TaskExecutor - implements Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> { + implements Executor<Map<String, Object>, Map<String, Map<String, Object>>, AxTask, ApexInternalContext> { // Logger for this class private static final XLogger LOGGER = XLoggerFactory.getXLogger(TaskExecutor.class); @@ -67,10 +66,11 @@ public abstract class TaskExecutor // Holds the incoming and outgoing fields private Map<String, Object> incomingFields = null; - private Map<String, Object> outgoingFields = null; + private Map<String, Map<String, Object>> outgoingFieldsMap = null; // The next task executor - private Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> nextExecutor = null; + private Executor<Map<String, Object>, Map<String, Map<String, Object>>, AxTask, ApexInternalContext> nextExecutor = + null; // The task execution context; contains the facades for events and context to be used by tasks // executed by this task @@ -104,7 +104,7 @@ public abstract class TaskExecutor * {@inheritDoc}. */ @Override - public Map<String, Object> execute(final long executionId, final Properties executionProperties, + public Map<String, Map<String, Object>> execute(final long executionId, final Properties executionProperties, final Map<String, Object> newIncomingFields) throws StateMachineException, ContextException { throw new StateMachineException( "execute() not implemented on abstract TaskExecutor class, only on its subclasses"); @@ -120,19 +120,13 @@ public abstract class TaskExecutor + getSubject().getKey().getId() + "," + getSubject().getTaskLogic().getLogic()); // Check that the incoming event has all the input fields for this state - final Set<String> missingTaskInputFields = new TreeSet<>(axTask.getInputFields().keySet()); + Map<String, AxField> inputEventParameterMap = axTask.getInputEvent().getParameterMap(); + final Set<String> missingTaskInputFields = new TreeSet<>(inputEventParameterMap.keySet()); missingTaskInputFields.removeAll(newIncomingFields.keySet()); // Remove fields from the set that are optional - final Set<String> optionalFields = new TreeSet<>(); - for (final Iterator<String> missingFieldIterator = missingTaskInputFields.iterator(); missingFieldIterator - .hasNext();) { - final String missingField = missingFieldIterator.next(); - if (axTask.getInputFields().get(missingField).getOptional()) { - optionalFields.add(missingField); - } - } - missingTaskInputFields.removeAll(optionalFields); + missingTaskInputFields.removeIf(missingField -> inputEventParameterMap.get(missingField).getOptional()); + if (!missingTaskInputFields.isEmpty()) { throw new StateMachineException("task input fields \"" + missingTaskInputFields + "\" are missing for task \"" + axTask.getKey().getId() + "\""); @@ -142,14 +136,15 @@ public abstract class TaskExecutor this.incomingFields = newIncomingFields; // Initiate the outgoing fields - outgoingFields = new TreeMap<>(); - for (final String outputFieldName : getSubject().getOutputFields().keySet()) { - outgoingFields.put(outputFieldName, null); + outgoingFieldsMap = new TreeMap<>(); + for (var outputEventEntry: axTask.getOutputEvents().entrySet()) { + Map<String, Object> outgoingFields = new TreeMap<>(); + outputEventEntry.getValue().getParameterMap().keySet().forEach(field -> outgoingFields.put(field, null)); + outgoingFieldsMap.put(outputEventEntry.getKey(), outgoingFields); } - // Get task context object executionContext = new TaskExecutionContext(this, executionId, executionProperties, getSubject(), getIncoming(), - getOutgoing(), getContext()); + outgoingFieldsMap.values(), getContext()); } /** @@ -167,71 +162,77 @@ public abstract class TaskExecutor throw new StateMachineException(errorMessage); } - // Copy any unset fields from the input to the output if their data type and names are - // identical - for (final String field : axTask.getOutputFields().keySet()) { - copyInputField2Output(field); - } + // Copy any unset fields from the input to the output if their data type and names are identical + axTask.getOutputEvents().entrySet().forEach(outputEventEntry -> outputEventEntry.getValue().getParameterMap() + .keySet().forEach(field -> copyInputField2Output(outputEventEntry.getKey(), field))); // Finally, check that the outgoing fields have all the output fields defined for this state - // and, if not, output - // a list of missing fields - final Set<String> missingTaskOutputFields = new TreeSet<>(axTask.getOutputFields().keySet()); - missingTaskOutputFields.removeAll(outgoingFields.keySet()); + // and, if not, output a list of missing fields + Map<String, Set<String>> missingTaskOutputFieldsMap = new TreeMap<>(); + axTask.getOutputEvents().entrySet().forEach(outputEventEntry -> { + Set<String> missingTaskOutputFields = new TreeSet<>(); + missingTaskOutputFields.addAll(outputEventEntry.getValue().getParameterMap().keySet()); + String key = outputEventEntry.getKey(); + missingTaskOutputFields.removeAll(outgoingFieldsMap.get(key).keySet()); + missingTaskOutputFieldsMap.put(key, missingTaskOutputFields); + }); // Remove fields from the set that are optional - final Set<String> optionalOrCopiedFields = new TreeSet<>(); - for (final Iterator<String> missingFieldIterator = missingTaskOutputFields.iterator(); missingFieldIterator - .hasNext();) { - final String missingField = missingFieldIterator.next(); - if (axTask.getInputFields().containsKey(missingField) - || axTask.getOutputFields().get(missingField).getOptional()) { - optionalOrCopiedFields.add(missingField); - } - } - missingTaskOutputFields.removeAll(optionalOrCopiedFields); - if (!missingTaskOutputFields.isEmpty()) { - throw new StateMachineException("task output fields \"" + missingTaskOutputFields - + "\" are missing for task \"" + axTask.getKey().getId() + "\""); + missingTaskOutputFieldsMap.entrySet() + .forEach(missingTaskOutputFieldsEntry -> missingTaskOutputFieldsEntry.getValue() + .removeIf(missingField -> axTask.getInputEvent().getParameterMap().containsKey(missingField) + || axTask.getOutputEvents().get(missingTaskOutputFieldsEntry.getKey()).getParameterMap() + .get(missingField).getOptional())); + missingTaskOutputFieldsMap.entrySet() + .removeIf(missingTaskOutputFieldsEntry -> missingTaskOutputFieldsEntry.getValue().isEmpty()); + if (!missingTaskOutputFieldsMap.isEmpty()) { + throw new StateMachineException("Fields for task output events \"" + missingTaskOutputFieldsMap.keySet() + + "\" are missing for task \"" + axTask.getKey().getId() + "\""); + } // Finally, check that the outgoing field map don't have any extra fields, if present, raise - // exception with the - // list of extra fields - final Set<String> extraTaskOutputFields = new TreeSet<>(outgoingFields.keySet()); - extraTaskOutputFields.removeAll(axTask.getOutputFields().keySet()); - if (!extraTaskOutputFields.isEmpty()) { - throw new StateMachineException("task output fields \"" + extraTaskOutputFields - + "\" are unwanted for task \"" + axTask.getKey().getId() + "\""); + // exception with the list of extra fields + final Map<String, Set<String>> extraTaskOutputFieldsMap = new TreeMap<>(); + outgoingFieldsMap.entrySet().forEach(outgoingFieldsEntry -> extraTaskOutputFieldsMap + .put(outgoingFieldsEntry.getKey(), new TreeSet<>(outgoingFieldsEntry.getValue().keySet()))); + extraTaskOutputFieldsMap.entrySet().forEach(extraTaskOutputFieldsEntry -> extraTaskOutputFieldsEntry.getValue() + .removeAll(axTask.getOutputEvents().get(extraTaskOutputFieldsEntry.getKey()).getParameterMap().keySet())); + extraTaskOutputFieldsMap.entrySet() + .removeIf(extraTaskOutputFieldsEntry -> extraTaskOutputFieldsEntry.getValue().isEmpty()); + if (!extraTaskOutputFieldsMap.isEmpty()) { + throw new StateMachineException("task output event \"" + extraTaskOutputFieldsMap.keySet() + + "\" contains fields that are unwanted for task \"" + axTask.getKey().getId() + "\""); } - String message = "execute-post:" + axTask.getKey().getId() + ", returning fields " + outgoingFields.toString(); + String message = + "execute-post:" + axTask.getKey().getId() + ", returning fields " + outgoingFieldsMap.toString(); LOGGER.debug(message); } /** * If the input field exists on the output and it is not set in the task, then it should be copied to the output. * + * @param eventName the event name * @param field the input field */ - private void copyInputField2Output(String field) { + private void copyInputField2Output(String eventName, String field) { + Map<String, Object> outgoingFields = outgoingFieldsMap.get(eventName); // Check if the field exists and is not set on the output - if (getOutgoing().containsKey(field) && getOutgoing().get(field) != null) { + if (outgoingFields.get(field) != null) { return; } // This field is not in the output, check if it's on the input and is the same type - // (Note here, the output - // field definition has to exist so it's not - // null checked) - final AxInputField inputFieldDef = axTask.getInputFields().get(field); - final AxOutputField outputFieldDef = axTask.getOutputFields().get(field); + // (Note here, the output field definition has to exist so it's not null checked) + final AxField inputFieldDef = axTask.getInputEvent().getParameterMap().get(field); + final AxField outputFieldDef = axTask.getOutputEvents().get(eventName).getParameterMap().get(field); if (inputFieldDef == null || !inputFieldDef.getSchema().equals(outputFieldDef.getSchema())) { return; } // We have an input field that matches our output field, copy the value across - getOutgoing().put(field, getIncoming().get(field)); + outgoingFields.put(field, getIncoming().get(field)); } /** @@ -308,15 +309,16 @@ public abstract class TaskExecutor * {@inheritDoc}. */ @Override - public Map<String, Object> getOutgoing() { - return outgoingFields; + public Map<String, Map<String, Object>> getOutgoing() { + return outgoingFieldsMap; } /** * {@inheritDoc}. */ @Override - public void setNext(final Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> nextEx) { + public void setNext( + final Executor<Map<String, Object>, Map<String, Map<String, Object>>, AxTask, ApexInternalContext> nextEx) { this.nextExecutor = nextEx; } @@ -324,7 +326,7 @@ public abstract class TaskExecutor * {@inheritDoc}. */ @Override - public Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> getNext() { + public Executor<Map<String, Object>, Map<String, Map<String, Object>>, AxTask, ApexInternalContext> getNext() { return nextExecutor; } diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java index f3906213f..5f39bcd56 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacade.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,18 +85,34 @@ public class AxTaskFacade { */ public SchemaHelper getInFieldSchemaHelper(final String fieldName) { // Find the field for the field name - return getFieldSchemaHelper(fieldName, task.getInputFields().get(fieldName), "incoming"); + return getFieldSchemaHelper(fieldName, task.getInputEvent().getParameterMap().get(fieldName), "incoming"); } /** * Creates a schema helper for an outgoing field of this task. + * This method can be used only when there is a single event output as part of a task * * @param fieldName The name of the field to get a schema helper for * @return the schema helper for this field */ public SchemaHelper getOutFieldSchemaHelper(final String fieldName) { // Find the field for the field name - return getFieldSchemaHelper(fieldName, task.getOutputFields().get(fieldName), "outgoing"); + return getFieldSchemaHelper(fieldName, + task.getOutputEvents().values().iterator().next().getParameterMap().get(fieldName), "outgoing"); + } + + /** + * Creates a schema helper for an outgoing field of this task. + * This method can be used when there are multiple event outputs from a task + * + * @param eventName the name of the event to which the field belongs to + * @param fieldName The name of the field to get a schema helper for + * @return the schema helper for this field + */ + public SchemaHelper getOutFieldSchemaHelper(final String eventName, final String fieldName) { + // Find the field for the field name + return getFieldSchemaHelper(fieldName, task.getOutputEvents().get(eventName).getParameterMap().get(fieldName), + "outgoing"); } /** diff --git a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContext.java b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContext.java index 49459dfae..a54252e05 100644 --- a/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContext.java +++ b/core/core-engine/src/main/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContext.java @@ -3,6 +3,7 @@ * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +24,7 @@ package org.onap.policy.apex.core.engine.executor.context; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -73,6 +75,12 @@ public class TaskExecutionContext extends AbstractExecutionContext { public final Map<String, Object> outFields; /** + * The outgoing fields from the task. The task logic can access and set these fields with its logic. A task outputs + * its result using these fields. + */ + public final Collection<Map<String, Object>> outFieldsList; + + /** * Logger for task execution, task logic can use this field to access and log to Apex logging. */ public final XLogger logger = EXECUTION_LOGGER; @@ -97,12 +105,12 @@ public class TaskExecutionContext extends AbstractExecutionContext { * @param executionProperties the execution properties for task execution * @param axTask the task definition that is the subject of execution * @param inFields the in fields - * @param outFields the out fields + * @param outFieldsList collection of the out fields * @param internalContext the execution context of the Apex engine in which the task is being executed */ public TaskExecutionContext(final TaskExecutor taskExecutor, final long executionId, final Properties executionProperties, final AxTask axTask, final Map<String, Object> inFields, - final Map<String, Object> outFields, final ApexInternalContext internalContext) { + final Collection<Map<String, Object>> outFieldsList, final ApexInternalContext internalContext) { super(executionId, executionProperties); // The subject is the task definition @@ -113,7 +121,13 @@ public class TaskExecutionContext extends AbstractExecutionContext { // The input and output fields this.inFields = Collections.unmodifiableMap(inFields); - this.outFields = outFields; + this.outFieldsList = outFieldsList; + // if only a single output event needs to fired from a task, the outFields alone can be used too + if (outFieldsList.isEmpty()) { + this.outFields = new TreeMap<>(); + } else { + this.outFields = outFieldsList.iterator().next(); + } // Set up the context albums for this task context = new TreeMap<>(); @@ -156,7 +170,7 @@ public class TaskExecutionContext extends AbstractExecutionContext { */ public ContextAlbum getContextAlbum(final String contextAlbumName) { // Find the context album - final ContextAlbum foundContextAlbum = context.get(contextAlbumName); + final var foundContextAlbum = context.get(contextAlbumName); // Check if the context album exists if (foundContextAlbum != null) { @@ -166,4 +180,16 @@ public class TaskExecutionContext extends AbstractExecutionContext { + "\" on task \"" + subject.getId() + "\""); } } + + /** + * Method to add fields to the output event list. + * @param fields the fields to be added + */ + public void addFieldsToOutput(Map<String, Object> fields) { + for (Map<String, Object> outputFields : outFieldsList) { + if (outputFields.keySet().containsAll(fields.keySet())) { + outputFields.replaceAll((name, value) -> fields.get(name)); + } + } + } } diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummySmExecutor.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummySmExecutor.java index 18d32140b..df4d9279e 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummySmExecutor.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/engine/impl/DummySmExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,8 @@ package org.onap.policy.apex.core.engine.engine.impl; +import java.util.Collection; +import java.util.List; import java.util.Properties; import org.onap.policy.apex.core.engine.event.EnEvent; import org.onap.policy.apex.core.engine.executor.ExecutorFactory; @@ -62,8 +65,9 @@ public class DummySmExecutor extends StateMachineExecutor { * {@inheritDoc}. */ @Override - public EnEvent execute(final long executionId, final Properties executionProperties, final EnEvent incomingEvent) { - return incomingEvent; + public Collection<EnEvent> execute(final long executionId, final Properties executionProperties, + final EnEvent incomingEvent) { + return List.of(incomingEvent); } /** diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskExecutor.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskExecutor.java index 8d1aa5f0d..75c4c0d7c 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskExecutor.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/DummyTaskExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,12 +28,14 @@ import org.onap.policy.apex.context.ContextException; import org.onap.policy.apex.core.engine.event.EnEvent; import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; import org.onap.policy.apex.model.policymodel.concepts.AxTask; /** * Dummy task executor for testing. */ public class DummyTaskExecutor extends TaskExecutor { + private static final String EVENT_KEY = "Event1:0.0.1"; private boolean override; public DummyTaskExecutor() { @@ -54,14 +57,14 @@ public class DummyTaskExecutor extends TaskExecutor { * {@inheritDoc}. */ @Override - public Map<String, Object> execute(final long executionId, final Properties executionProperties, + public Map<String, Map<String, Object>> execute(final long executionId, final Properties executionProperties, final Map<String, Object> newIncomingFields) throws StateMachineException, ContextException { if (!override) { super.execute(executionId, executionProperties, newIncomingFields); } - AxArtifactKey event0Key = new AxArtifactKey("Event0:0.0.1"); - return new EnEvent(event0Key); + AxArtifactKey eventKey = new AxArtifactKey(EVENT_KEY); + return Map.of(eventKey.getName(), new EnEvent(eventKey)); } /** @@ -74,7 +77,9 @@ public class DummyTaskExecutor extends TaskExecutor { } AxArtifactKey taskKey = new AxArtifactKey("FirstTask:0.0.1"); - return new AxTask(taskKey); + AxTask task = new AxTask(taskKey); + task.setOutputEvents(Map.of("Event1", new AxEvent(new AxArtifactKey(EVENT_KEY)))); + return task; } /** diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java index 2acb57681..2d274bd2e 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/StateMachineExecutorTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +25,10 @@ package org.onap.policy.apex.core.engine.executor; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import org.junit.After; @@ -65,7 +69,7 @@ public class StateMachineExecutorTest { private ApexInternalContext internalContextMock; @Mock - private Executor<EnEvent, EnEvent, AxPolicy, ApexInternalContext> nextExecutorMock; + private Executor<EnEvent, Collection<EnEvent>, AxPolicy, ApexInternalContext> nextExecutorMock; @Mock private ExecutorFactory executorFactoryMock; @@ -191,18 +195,18 @@ public class StateMachineExecutorTest { .hasMessage("no states defined on state machine"); executor.setContext(null, axPolicy, internalContextMock); assertEquals("Policy:0.0.1", executor.getKey().getId()); - assertEquals(null, executor.getParent()); + assertNull(executor.getParent()); assertEquals(internalContextMock, executor.getContext()); - assertEquals(null, executor.getNext()); - assertEquals(null, executor.getIncoming()); - assertEquals(null, executor.getOutgoing()); + assertNull(executor.getNext()); + assertNull(executor.getIncoming()); + assertTrue(executor.getOutgoing().isEmpty()); assertEquals(axPolicy, executor.getSubject()); executor.setParameters(new ExecutorParameters()); executor.setNext(nextExecutorMock); assertEquals(nextExecutorMock, executor.getNext()); executor.setNext(null); - assertEquals(null, executor.getNext()); + assertNull(executor.getNext()); assertThatThrownBy(() -> executor.executePre(0, null, null)) .hasMessage("execution pre work not implemented on class"); @@ -294,34 +298,37 @@ public class StateMachineExecutorTest { assertThatThrownBy(() -> output.setEventFields(null, null)) .hasMessage("incomingFieldDefinitionMap may not be null"); - Map<String, AxField> incomingFieldDefinitionMap = new LinkedHashMap<>(); + Map<String, AxEvent> incomingFieldDefinitionMap = new LinkedHashMap<>(); assertThatThrownBy(() -> output.setEventFields(incomingFieldDefinitionMap, null)) - .hasMessage("eventFieldMap may not be null"); - Map<String, Object> eventFieldMap = new LinkedHashMap<>(); - output.setEventFields(incomingFieldDefinitionMap, eventFieldMap); - - eventFieldMap.put("key", "Value"); - assertThatThrownBy(() -> output.setEventFields(incomingFieldDefinitionMap, eventFieldMap)) - .hasMessage("field definitions and values do not match for event Event1:0.0.1\n[]\n[key]"); - AxField axBadFieldDefinition = new AxField(); - incomingFieldDefinitionMap.put("key", axBadFieldDefinition); - assertThatThrownBy(() -> output.setEventFields(incomingFieldDefinitionMap, eventFieldMap)) + .hasMessage("eventFieldMaps may not be null"); + Map<String, Map<String, Object>> eventFieldMaps = new LinkedHashMap<>(); + output.setEventFields(incomingFieldDefinitionMap, eventFieldMaps); + AxEvent event = new AxEvent(new AxArtifactKey("Event1", "0.0.1")); + event.setParameterMap(Map.of("key", new AxField())); + incomingFieldDefinitionMap.put("Event1", event); + eventFieldMaps.put("Event1", Map.of("key2", "value")); + assertThatThrownBy(() -> output.setEventFields(incomingFieldDefinitionMap, eventFieldMaps)) + .hasMessage("field definitions and values do not match for event Event1:0.0.1\n[key]\n[key2]"); + + eventFieldMaps.put("Event1", Map.of("key", "value")); + assertThatThrownBy(() -> output.setEventFields(incomingFieldDefinitionMap, eventFieldMaps)) .hasMessage("field \"key\" does not exist on event \"Event1:0.0.1\""); + incomingFieldDefinitionMap.clear(); - eventFieldMap.clear(); + eventFieldMaps.clear(); AxArtifactKey stringSchemaKey = new AxArtifactKey("StringSchema:0.0.1"); AxReferenceKey fieldKey = new AxReferenceKey("Event1:0.0.1:event:Field0"); AxField event1Field0Definition = new AxField(fieldKey, stringSchemaKey); - incomingFieldDefinitionMap.put("Event1Field0", event1Field0Definition); - eventFieldMap.put("Event1Field0", "Value"); - output.setEventFields(incomingFieldDefinitionMap, eventFieldMap); + event.setParameterMap(Map.of("Event1Field0", event1Field0Definition)); + incomingFieldDefinitionMap.put("Event1", event); + eventFieldMaps.put("Event1", Map.of("Event1Field0", "Value")); + output.setEventFields(incomingFieldDefinitionMap, eventFieldMaps); StateOutput outputCopy = new StateOutput(axPolicy.getStateMap().get("State0") .getStateOutputs().get("stateOutput0")); EnEvent incomingEvent = new EnEvent(new AxArtifactKey("Event0:0.0.1")); outputCopy.copyUnsetFields(incomingEvent); - incomingEvent.put("Event1Field0", "Hello"); outputCopy.copyUnsetFields(incomingEvent); } diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java index bbedb886c..1ddc3f5b5 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/TaskExecutorTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +33,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.TreeMap; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -44,6 +46,8 @@ import org.onap.policy.apex.core.engine.context.ApexInternalContext; import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; +import org.onap.policy.apex.model.eventmodel.concepts.AxField; import org.onap.policy.apex.model.eventmodel.concepts.AxInputField; import org.onap.policy.apex.model.eventmodel.concepts.AxOutputField; import org.onap.policy.apex.model.policymodel.concepts.AxTask; @@ -76,14 +80,16 @@ public class TaskExecutorTest { private AxOutputField axMissingOutputFieldMock; @Mock - private Executor<Map<String, Object>, Map<String, Object>, AxTask, ApexInternalContext> nextExecutorMock; + private Executor<Map<String, Object>, Map<String, Map<String, Object>>, AxTask, + ApexInternalContext> nextExecutorMock; @Mock private AxTaskLogic taskLogicMock; - private LinkedHashMap<String, Object> inFieldMap; - private LinkedHashMap<String, Object> outFieldMap; + private Map<String, AxField> inFieldMap; + private Map<String, AxField> outFieldMap; private List<TaskParameters> taskParametersFromConfig; + private Map<String, AxEvent> outEvents = new TreeMap<>(); /** * Set up mocking. @@ -96,13 +102,17 @@ public class TaskExecutorTest { Mockito.doReturn(task0Key).when(axTaskMock).getKey(); Mockito.doReturn(task0Key.getId()).when(axTaskMock).getId(); - inFieldMap = new LinkedHashMap<>(); + inFieldMap = Map.of("InField0", axInputFieldMock, "InField1", axOptionalInputFieldMock); outFieldMap = new LinkedHashMap<>(); - inFieldMap.put("InField0", axInputFieldMock); - inFieldMap.put("InField1", axOptionalInputFieldMock); outFieldMap.put("OutField0", axOutputFieldMock); - outFieldMap.put("OutField0", axOptionalOutputFieldMock); + outFieldMap.put("OutField1", axOptionalOutputFieldMock); + + AxEvent inEvent = new AxEvent(); + inEvent.setParameterMap(inFieldMap); + AxEvent outEvent = new AxEvent(new AxArtifactKey("outputEvent:1.0.0")); + outEvent.setParameterMap(outFieldMap); + outEvents.put(outEvent.getKey().getName(), outEvent); AxArtifactKey schemaKey = new AxArtifactKey("Schema:0.0.1"); Mockito.doReturn(schemaKey).when(axInputFieldMock).getSchema(); @@ -119,6 +129,9 @@ public class TaskExecutorTest { Mockito.doReturn(outFieldMap).when(axTaskMock).getOutputFields(); Mockito.doReturn(taskLogicMock).when(axTaskMock).getTaskLogic(); + Mockito.doReturn(inEvent).when(axTaskMock).getInputEvent(); + Mockito.doReturn(outEvents).when(axTaskMock).getOutputEvents(); + Mockito.doReturn(new AxArtifactKey("Context:0.0.1")).when(internalContextMock).getKey(); Map<String, AxTaskParameter> taskParameters = new HashMap<>(); @@ -162,9 +175,6 @@ public class TaskExecutorTest { Map<String, Object> incomingFields = new LinkedHashMap<>(); - assertThatThrownBy(() -> executor.executePre(0, new Properties(), incomingFields)) - .hasMessageContaining("task input fields \"[InField0]\" are missing for task \"Task0:0.0.1\""); - incomingFields.put("InField0", "A Value"); executor.executePre(0, new Properties(), incomingFields); @@ -184,15 +194,16 @@ public class TaskExecutorTest { executor.executePost(true); outFieldMap.put("MissingField", axMissingOutputFieldMock); - - assertThatThrownBy(() -> executor.executePost(true)) - .hasMessageContaining("task output fields \"[MissingField]\" are missing for task \"Task0:0.0.1\""); + outEvents.get("outputEvent").getParameterMap().put("MissingField", axMissingOutputFieldMock); + assertThatThrownBy(() -> executor.executePost(true)).hasMessageContaining( + "Fields for task output events \"[outputEvent]\" are missing for task \"Task0:0.0.1\""); outFieldMap.remove("MissingField"); + outEvents.get("outputEvent").getParameterMap().remove("MissingField"); executor.getExecutionContext().outFields.put("BadExtraField", "Howdy!"); - assertThatThrownBy(() -> executor.executePost(true)) - .hasMessageContaining("task output fields \"[BadExtraField]\" are unwanted for task \"Task0:0.0.1\""); + assertThatThrownBy(() -> executor.executePost(true)).hasMessageContaining( + "task output event \"[outputEvent]\" contains fields that are unwanted for task \"Task0:0.0.1\""); executor.getExecutionContext().outFields.remove("BadExtraField"); outFieldMap.put("InField1", axMissingOutputFieldMock); @@ -202,6 +213,7 @@ public class TaskExecutorTest { executor.executePost(true); executor.getExecutionContext().outFields.put("InField0", "Output Value"); + outEvents.get("outputEvent").getParameterMap().put("InField0", axMissingOutputFieldMock); executor.executePost(true); executor.getExecutionContext().outFields.remove("InField0"); diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacadeTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacadeTest.java index 8ef78efe9..6f8402e55 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacadeTest.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/AxTaskFacadeTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,8 +26,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import java.util.LinkedHashMap; import java.util.Map; +import java.util.TreeMap; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -40,6 +41,8 @@ import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; import org.onap.policy.apex.model.basicmodel.service.ModelService; import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema; import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; +import org.onap.policy.apex.model.eventmodel.concepts.AxField; import org.onap.policy.apex.model.eventmodel.concepts.AxInputField; import org.onap.policy.apex.model.eventmodel.concepts.AxOutputField; import org.onap.policy.apex.model.policymodel.concepts.AxTask; @@ -83,13 +86,18 @@ public class AxTaskFacadeTest { Mockito.doReturn(task0Key).when(axTaskMock).getKey(); Mockito.doReturn(task0Key.getId()).when(axTaskMock).getId(); - Map<String, AxInputField> inFieldMap = new LinkedHashMap<>(); - Map<String, AxOutputField> outFieldMap = new LinkedHashMap<>(); + Map<String, AxField> inFieldMap = Map.of("InField0", axInputFieldMock, "InFieldBad", axInputFieldBadMock); + Map<String, AxField> outFieldMap = Map.of("OutField0", axOutputFieldMock, "OutFieldBad", axOutputFieldBadMock); - inFieldMap.put("InField0", axInputFieldMock); - inFieldMap.put("InFieldBad", axInputFieldBadMock); - outFieldMap.put("OutField0", axOutputFieldMock); - outFieldMap.put("OutFieldBad", axOutputFieldBadMock); + AxEvent inEvent = new AxEvent(); + inEvent.setParameterMap(inFieldMap); + AxEvent outEvent = new AxEvent(new AxArtifactKey("outputEvent:1.0.0")); + outEvent.setParameterMap(outFieldMap); + Map<String, AxEvent> outEvents = new TreeMap<>(); + outEvents.put(outEvent.getKey().getName(), outEvent); + + Mockito.doReturn(inEvent).when(axTaskMock).getInputEvent(); + Mockito.doReturn(outEvents).when(axTaskMock).getOutputEvents(); Mockito.doReturn(inFieldMap).when(axTaskMock).getInputFields(); Mockito.doReturn(outFieldMap).when(axTaskMock).getOutputFields(); diff --git a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContextTest.java b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContextTest.java index f8bdc4bdd..24c504822 100644 --- a/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContextTest.java +++ b/core/core-engine/src/test/java/org/onap/policy/apex/core/engine/executor/context/TaskExecutionContextTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +29,8 @@ import static org.junit.Assert.assertNotNull; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Before; @@ -93,10 +96,10 @@ public class TaskExecutionContextTest { @Test public void test() { final Map<String, Object> inFields = new LinkedHashMap<>(); - final Map<String, Object> outFields = new LinkedHashMap<>(); + final List<Map<String, Object>> outFieldsList = new LinkedList<>(); - TaskExecutionContext tec = new TaskExecutionContext(taskExecutorMock, 0, null, axTaskMock, inFields, outFields, - internalContextMock); + TaskExecutionContext tec = new TaskExecutionContext(taskExecutorMock, 0, null, axTaskMock, inFields, + outFieldsList, internalContextMock); assertNotNull(tec); tec.setMessage("TEC Message"); diff --git a/examples/examples-grpc/src/main/resources/examples/config/APEXgRPC/ApexConfig.json b/examples/examples-grpc/src/main/resources/examples/config/APEXgRPC/ApexConfig.json index fb1c38014..c34f9e33f 100644 --- a/examples/examples-grpc/src/main/resources/examples/config/APEXgRPC/ApexConfig.json +++ b/examples/examples-grpc/src/main/resources/examples/config/APEXgRPC/ApexConfig.json @@ -106,7 +106,7 @@ "eventProtocolParameters": { "eventProtocol": "JSON" }, - "eventNameFilter": "CDSResponseStatusEvent" + "eventNameFilter": "(LogEvent|CDSResponseStatusEvent)" } } -}
\ No newline at end of file +} diff --git a/examples/examples-grpc/src/main/resources/examples/events/APEXgRPC/CDSResponseStatusEvent.json b/examples/examples-grpc/src/main/resources/examples/events/APEXgRPC/CDSResponseStatusEvent.json new file mode 100644 index 000000000..938983362 --- /dev/null +++ b/examples/examples-grpc/src/main/resources/examples/events/APEXgRPC/CDSResponseStatusEvent.json @@ -0,0 +1,13 @@ +{ + "name": "CDSResponseStatusEvent", + "version": "0.0.1", + "nameSpace": "org.onap.policy.apex.onap.pmcontrol", + "source": "APEX", + "target": "DCAE", + "status": { + "subscriptionName": "testPolicyB", + "nfName": "pnf300", + "changeType": "CREATE", + "message": "success" + } +} diff --git a/examples/examples-grpc/src/main/resources/examples/events/APEXgRPC/LogEvent.json b/examples/examples-grpc/src/main/resources/examples/events/APEXgRPC/LogEvent.json index a86ccd1d7..e227b6699 100644 --- a/examples/examples-grpc/src/main/resources/examples/events/APEXgRPC/LogEvent.json +++ b/examples/examples-grpc/src/main/resources/examples/events/APEXgRPC/LogEvent.json @@ -1,13 +1,9 @@ { - "name": "CDSResponseStatusEvent", + "name": "LogEvent", "version": "0.0.1", "nameSpace": "org.onap.policy.apex.onap.pmcontrol", "source": "APEX", "target": "DCAE", - "status": { - "subscriptionName": "testPolicyB", - "nfName": "pnf300", - "changeType": "CREATE", - "message": "success" - } -}
\ No newline at end of file + "final_status": "FINAL_SUCCESS", + "message": "Operation successfully completed." +} diff --git a/examples/examples-grpc/src/main/resources/logic/ResponseTask.js b/examples/examples-grpc/src/main/resources/logic/ResponseTask.js index 04517763a..dc4948990 100644 --- a/examples/examples-grpc/src/main/resources/logic/ResponseTask.js +++ b/examples/examples-grpc/src/main/resources/logic/ResponseTask.js @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +26,7 @@ var albumID = uuidType.fromString("d0050623-18e5-46c9-9298-9a567990cd7c"); var pmSubscriptionInfo = executor.getContextAlbum("PMSubscriptionAlbum").get(albumID.toString()); -var responseStatus = executor.subject.getOutFieldSchemaHelper("status").createNewInstance(); +var responseStatus = executor.subject.getOutFieldSchemaHelper("CDSResponseStatusEvent", "status").createNewInstance(); responseStatus.put("subscriptionName", pmSubscriptionInfo.get("subscription").get("subscriptionName")) responseStatus.put("nfName", pmSubscriptionInfo.get("nfName")) @@ -39,6 +40,12 @@ if ("failure".equals(response.get("create_DasH_subscription_DasH_response").get( responseStatus.put("message", "success") } -executor.outFields.put("status", responseStatus) +var cdsResponseEventFields = java.util.HashMap(); +cdsResponseEventFields.put("status", responseStatus); +executor.addFieldsToOutput(cdsResponseEventFields); +var logEventFields = java.util.HashMap(); +logEventFields.put("final_status", "FINAL_SUCCESS"); +logEventFields.put("message", "Operation successfully completed."); +executor.addFieldsToOutput(logEventFields); true; diff --git a/examples/examples-grpc/src/main/resources/policy/APEXgRPCPolicy.apex b/examples/examples-grpc/src/main/resources/policy/APEXgRPCPolicy.apex index b0cbcb7c0..636c74b80 100644 --- a/examples/examples-grpc/src/main/resources/policy/APEXgRPCPolicy.apex +++ b/examples/examples-grpc/src/main/resources/policy/APEXgRPCPolicy.apex @@ -1,6 +1,7 @@ #------------------------------------------------------------------------------- # ============LICENSE_START======================================================= # Copyright (C) 2020 Nordix Foundation. +# Modifications Copyright (C) 2021 Bell Canada. All rights reserved. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -111,69 +112,46 @@ event parameter create name=CDSResponseEvent parName=payload schemaName=CDSRespo event create name=CDSResponseStatusEvent nameSpace=org.onap.policy.apex.onap.pmcontrol source=APEX target=DCAE event parameter create name=CDSResponseStatusEvent parName=status schemaName=SubscriptionStatusType +event create name=LogEvent nameSpace=org.onap.policy.apex.onap.pmcontrol source=APEX target=DCAE +event parameter create name=LogEvent parName=final_status schemaName=SimpleStringType +event parameter create name=LogEvent parName=message schemaName=SimpleStringType + ## ## TASKS ## task create name=ReceivePMSubscriptionTask -task inputfield create name=ReceivePMSubscriptionTask fieldName=subscription schemaName=SubscriptionType -task inputfield create name=ReceivePMSubscriptionTask fieldName=nfName schemaName=SimpleStringType -task inputfield create name=ReceivePMSubscriptionTask fieldName=policyName schemaName=SimpleStringType -task inputfield create name=ReceivePMSubscriptionTask fieldName=changeType schemaName=SimpleStringType -task inputfield create name=ReceivePMSubscriptionTask fieldName=closedLoopControlName schemaName=SimpleStringType -task outputfield create name=ReceivePMSubscriptionTask fieldName=albumID schemaName=UUIDType task contextref create name=ReceivePMSubscriptionTask albumName=PMSubscriptionAlbum task logic create name=ReceivePMSubscriptionTask logicFlavour=JAVASCRIPT logic=LS #MACROFILE:"src/main/resources/logic/ReceivePMSubscriptionTask.js" LE task create name=CreateSubscriptionPayloadTask -task inputfield create name=CreateSubscriptionPayloadTask fieldName=albumID schemaName=UUIDType -task outputfield create name=CreateSubscriptionPayloadTask fieldName=payload schemaName=CDSCreateSubscriptionPayloadType -task outputfield create name=CreateSubscriptionPayloadTask fieldName=albumID schemaName=UUIDType task contextref create name=CreateSubscriptionPayloadTask albumName=PMSubscriptionAlbum task logic create name=CreateSubscriptionPayloadTask logicFlavour=JAVASCRIPT logic=LS #MACROFILE:"src/main/resources/logic/CreateSubscriptionPayloadTask.js" LE task create name=DeleteSubscriptionPayloadTask -task inputfield create name=DeleteSubscriptionPayloadTask fieldName=albumID schemaName=UUIDType -task outputfield create name=DeleteSubscriptionPayloadTask fieldName=payload schemaName=CDSDeleteSubscriptionPayloadType -task outputfield create name=DeleteSubscriptionPayloadTask fieldName=albumID schemaName=UUIDType task contextref create name=DeleteSubscriptionPayloadTask albumName=PMSubscriptionAlbum task logic create name=DeleteSubscriptionPayloadTask logicFlavour=JAVASCRIPT logic=LS #MACROFILE:"src/main/resources/logic/DeleteSubscriptionPayloadTask.js" LE task create name=CreateSubscriptionRequestTask -task inputfield create name=CreateSubscriptionRequestTask fieldName=albumID schemaName=UUIDType -task inputfield create name=CreateSubscriptionRequestTask fieldName=payload schemaName=CDSCreateSubscriptionPayloadType -task outputfield create name=CreateSubscriptionRequestTask fieldName=commonHeader schemaName=CDSRequestCommonHeaderType -task outputfield create name=CreateSubscriptionRequestTask fieldName=actionIdentifiers schemaName=CDSActionIdentifiersType -task outputfield create name=CreateSubscriptionRequestTask fieldName=payload schemaName=CDSCreateSubscriptionPayloadType task contextref create name=CreateSubscriptionRequestTask albumName=PMSubscriptionAlbum task logic create name=CreateSubscriptionRequestTask logicFlavour=JAVASCRIPT logic=LS #MACROFILE:"src/main/resources/logic/CreateSubscriptionRequestTask.js" LE task create name=DeleteSubscriptionRequestTask -task inputfield create name=DeleteSubscriptionRequestTask fieldName=albumID schemaName=UUIDType -task inputfield create name=DeleteSubscriptionRequestTask fieldName=payload schemaName=CDSDeleteSubscriptionPayloadType -task outputfield create name=DeleteSubscriptionRequestTask fieldName=commonHeader schemaName=CDSRequestCommonHeaderType -task outputfield create name=DeleteSubscriptionRequestTask fieldName=actionIdentifiers schemaName=CDSActionIdentifiersType -task outputfield create name=DeleteSubscriptionRequestTask fieldName=payload schemaName=CDSDeleteSubscriptionPayloadType task contextref create name=DeleteSubscriptionRequestTask albumName=PMSubscriptionAlbum task logic create name=DeleteSubscriptionRequestTask logicFlavour=JAVASCRIPT logic=LS #MACROFILE:"src/main/resources/logic/DeleteSubscriptionRequestTask.js" LE task create name=CDSResponseTask -task inputfield create name=CDSResponseTask fieldName=commonHeader schemaName=CDSResponseCommonHeaderType -task inputfield create name=CDSResponseTask fieldName=actionIdentifiers schemaName=CDSActionIdentifiersType -task inputfield create name=CDSResponseTask fieldName=status schemaName=CDSResponseStatusType -task inputfield create name=CDSResponseTask fieldName=payload schemaName=CDSResponsePayloadType -task outputfield create name=CDSResponseTask fieldName=status schemaName=SubscriptionStatusType task contextref create name=CDSResponseTask albumName=PMSubscriptionAlbum task logic create name=CDSResponseTask logicFlavour=JAVASCRIPT logic=LS #MACROFILE:"src/main/resources/logic/ResponseTask.js" @@ -227,6 +205,7 @@ policy create name=CDSResponsePolicy template=Freestyle firstState=CDSResponseSt # State CDSResponseState policy state create name=CDSResponsePolicy stateName=CDSResponseState triggerName=CDSResponseEvent defaultTaskName=CDSResponseTask policy state output create name=CDSResponsePolicy stateName=CDSResponseState outputName=ResponseOutput eventName=CDSResponseStatusEvent +policy state output create name=CDSResponsePolicy stateName=CDSResponseState outputName=ResponseOutput eventName=LogEvent policy state taskref create name=CDSResponsePolicy stateName=CDSResponseState taskName=CDSResponseTask outputType=DIRECT outputName=ResponseOutput validate
\ No newline at end of file diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java index 4e88afe83..17b99c986 100644 --- a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/GrpcTestRestSimEndpoint.java @@ -68,7 +68,7 @@ public class GrpcTestRestSimEndpoint { public Response policyLogRequest(final String jsonString) { LOGGER.info("\n*** POLICY LOG ENTRY START ***\n {} \n *** POLICY LOG ENTRY END ***", jsonString); synchronized (lock) { - loggedOutputEvent = jsonString; + loggedOutputEvent += jsonString + "\n"; } return Response.status(200).build(); } diff --git a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java index 7f799c24f..a197432ba 100644 --- a/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java +++ b/examples/examples-grpc/src/test/java/org/onap/policy/apex/examples/grpc/TestApexGrpcExample.java @@ -1,7 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation. - * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. + * Modifications Copyright (C) 2020-2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,8 @@ package org.onap.policy.apex.examples.grpc; +import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.junit.Assert.assertEquals; import java.nio.file.Files; import java.nio.file.Paths; @@ -85,9 +85,12 @@ public class TestApexGrpcExample { Response response = client.target(getLoggedEventUrl).request("application/json").get(); sim.tearDown(); String responseEntity = response.readEntity(String.class); - String expectedLoggedOutputEvent = Files .readString(Paths.get("src/main/resources/examples/events/APEXgRPC/LogEvent.json")).replaceAll("\r", ""); - assertEquals(expectedLoggedOutputEvent, responseEntity); + String expectedStatusEvent = + Files.readString(Paths.get("src/main/resources/examples/events/APEXgRPC/CDSResponseStatusEvent.json")) + .replaceAll("\r", ""); + // Both LogEvent and CDSResponseStatusEvent are generated from the final state in the policy + assertThat(responseEntity).contains(expectedStatusEvent + expectedLoggedOutputEvent); } } diff --git a/model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/impl/ApexModelImpl.java b/model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/impl/ApexModelImpl.java index e66322801..5e8d1a5c7 100644 --- a/model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/impl/ApexModelImpl.java +++ b/model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/impl/ApexModelImpl.java @@ -3,6 +3,7 @@ * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Samsung Electronics Co., Ltd. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +28,8 @@ import org.onap.policy.apex.model.basicmodel.dao.DaoParameters; import org.onap.policy.apex.model.modelapi.ApexApiResult; import org.onap.policy.apex.model.modelapi.ApexModel; import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This class is an implementation of a facade on an Apex model for editors of Apex models. @@ -34,6 +37,13 @@ import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel; * @author Liam Fallon (liam.fallon@ericsson.com) */ public final class ApexModelImpl implements ApexModel { + + private static final String FIELDS_DEPRECATED_WARN_MSG = + "inputFields and outputFields are deprecated from Task definition and will be removed. " + + "Instead, inputEvent and outputEvents are automatically populated to Tasks based on State definition"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ApexModelImpl.class); + // The policy model being acted upon private AxPolicyModel policyModel = new AxPolicyModel(); @@ -436,6 +446,7 @@ public final class ApexModelImpl implements ApexModel { @Override public ApexApiResult createTaskInputField(final String name, final String version, final String fieldName, final String dataTypeName, final String dataTypeVersion, final boolean optional) { + LOGGER.warn(FIELDS_DEPRECATED_WARN_MSG); return taskFacade.createTaskInputField(name, version, fieldName, dataTypeName, dataTypeVersion, optional); } @@ -444,6 +455,7 @@ public final class ApexModelImpl implements ApexModel { */ @Override public ApexApiResult listTaskInputField(final String name, final String version, final String fieldName) { + LOGGER.warn(FIELDS_DEPRECATED_WARN_MSG); return taskFacade.listTaskInputField(name, version, fieldName); } @@ -452,6 +464,7 @@ public final class ApexModelImpl implements ApexModel { */ @Override public ApexApiResult deleteTaskInputField(final String name, final String version, final String fieldName) { + LOGGER.warn(FIELDS_DEPRECATED_WARN_MSG); return taskFacade.deleteTaskInputField(name, version, fieldName); } @@ -461,6 +474,7 @@ public final class ApexModelImpl implements ApexModel { @Override public ApexApiResult createTaskOutputField(final String name, final String version, final String fieldName, final String dataTypeName, final String dataTypeVersion, final boolean optional) { + LOGGER.warn(FIELDS_DEPRECATED_WARN_MSG); return taskFacade.createTaskOutputField(name, version, fieldName, dataTypeName, dataTypeVersion, optional); } @@ -469,6 +483,7 @@ public final class ApexModelImpl implements ApexModel { */ @Override public ApexApiResult listTaskOutputField(final String name, final String version, final String fieldName) { + LOGGER.warn(FIELDS_DEPRECATED_WARN_MSG); return taskFacade.listTaskOutputField(name, version, fieldName); } @@ -477,6 +492,7 @@ public final class ApexModelImpl implements ApexModel { */ @Override public ApexApiResult deleteTaskOutputField(final String name, final String version, final String fieldName) { + LOGGER.warn(FIELDS_DEPRECATED_WARN_MSG); return taskFacade.deleteTaskOutputField(name, version, fieldName); } diff --git a/model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/impl/PolicyFacade.java b/model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/impl/PolicyFacade.java index 0c0a51691..9480702ac 100644 --- a/model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/impl/PolicyFacade.java +++ b/model/model-api/src/main/java/org/onap/policy/apex/model/modelapi/impl/PolicyFacade.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +26,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; +import java.util.TreeMap; import java.util.TreeSet; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxKey; @@ -655,9 +657,11 @@ public class PolicyFacade { } final AxReferenceKey refKey = new AxReferenceKey(state.getKey(), outputName); - if (state.getStateOutputs().containsKey(refKey.getLocalName())) { + // There can be multipe state outputs only when the current state is the final state + if (nextState != null && !AxReferenceKey.getNullKey().getLocalName().equals(nextState) + && state.getStateOutputs().containsKey(refKey.getLocalName())) { return new ApexApiResult(ApexApiResult.Result.CONCEPT_EXISTS, - "Output concept " + refKey.getId() + ALREADY_EXISTS); + "Output concept " + refKey.getId() + ALREADY_EXISTS); } final AxEvent event = apexModel.getPolicyModel().getEvents().get(eventName, eventVersion); @@ -680,13 +684,35 @@ public class PolicyFacade { } } - state.getStateOutputs().put(refKey.getLocalName(), new AxStateOutput(refKey, event.getKey(), nextStateKey)); + populateStateOuputInfo(nextState, state, refKey, event, nextStateKey); return new ApexApiResult(); } catch (final Exception e) { return new ApexApiResult(ApexApiResult.Result.FAILED, e); } } + private void populateStateOuputInfo(final String nextState, final AxState state, final AxReferenceKey refKey, + final AxEvent event, AxReferenceKey nextStateKey) { + // nextState is null. There could be multiple events coming out of the state + if ((nextState == null || AxReferenceKey.getNullKey().getLocalName().equals(nextState)) + && state.getStateOutputs().containsKey(refKey.getLocalName())) { + AxStateOutput existingStateOutput = state.getStateOutputs().get(refKey.getLocalName()); + if (null == existingStateOutput.getOutgoingEventSet() + || existingStateOutput.getOutgoingEventSet().isEmpty()) { + Set<AxArtifactKey> eventSet = new TreeSet<>(); + eventSet.add(existingStateOutput.getOutgoingEvent()); + existingStateOutput.setOutgoingEventSet(eventSet); + } + existingStateOutput.getOutgoingEventSet().add(event.getKey()); + } else { + AxStateOutput axStateOutput = new AxStateOutput(refKey, event.getKey(), nextStateKey); + Set<AxArtifactKey> eventSet = new TreeSet<>(); + eventSet.add(axStateOutput.getOutgoingEvent()); + axStateOutput.setOutgoingEventSet(eventSet); + state.getStateOutputs().put(refKey.getLocalName(), axStateOutput); + } + } + /** * List policy state outputs. * @@ -1086,15 +1112,36 @@ public class PolicyFacade { ApexApiResult.Result.FAILED, "output type " + builder.getOutputType() + " invalid"); } - state - .getTaskReferences() - .put(task.getKey(), new AxStateTaskReference(refKey, stateTaskOutputType, outputRefKey)); + // add input and output events to the task based on state definition + if (state.getStateOutputs().containsKey(outputRefKey.getLocalName())) { + populateIoEventsToTask(state, task, outputRefKey); + } + state.getTaskReferences().put(task.getKey(), + new AxStateTaskReference(refKey, stateTaskOutputType, outputRefKey)); return new ApexApiResult(); } catch (final Exception e) { return new ApexApiResult(ApexApiResult.Result.FAILED, e); } } + private void populateIoEventsToTask(final AxState state, final AxTask task, final AxReferenceKey outputRefKey) { + AxEvent triggerEvent = apexModel.getPolicyModel().getEvents().get(state.getTrigger()); + task.setInputEvent(triggerEvent); + Map<String, AxEvent> outputEvents = new TreeMap<>(); + if (state.getNextStateSet().isEmpty() + || state.getNextStateSet().contains(AxReferenceKey.getNullKey().getLocalName())) { + state.getStateOutputs().get(outputRefKey.getLocalName()).getOutgoingEventSet() + .forEach(outgoingEventKey -> outputEvents.put(outgoingEventKey.getName(), + apexModel.getPolicyModel().getEvents().get(outgoingEventKey))); + } else { + AxArtifactKey outgoingEventKey = + state.getStateOutputs().get(outputRefKey.getLocalName()).getOutgoingEvent(); + outputEvents.put(outgoingEventKey.getName(), + apexModel.getPolicyModel().getEvents().get(outgoingEventKey)); + } + task.setOutputEvents(outputEvents); + } + /** * List policy state task references. * diff --git a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxPolicyModel.java b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxPolicyModel.java index d55fbd329..4ee176d97 100644 --- a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxPolicyModel.java +++ b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxPolicyModel.java @@ -3,6 +3,7 @@ * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -502,9 +503,9 @@ public class AxPolicyModel extends AxModel { } for (final AxStateOutput stateOutput : state.getStateOutputs().values()) { - if (events.getEventMap().get(stateOutput.getOutgingEvent()) == null) { + if (events.getEventMap().get(stateOutput.getOutgoingEvent()) == null) { result.addValidationMessage(new AxValidationMessage(stateOutput.getKey(), this.getClass(), - ValidationResult.INVALID, "output event " + stateOutput.getOutgingEvent().getId() + ValidationResult.INVALID, "output event " + stateOutput.getOutgoingEvent().getId() + " for state output " + stateOutput.getId() + DOES_NOT_EXIST)); } } @@ -555,10 +556,10 @@ public class AxPolicyModel extends AxModel { ValidationResult.INVALID, "state output on task reference for task " + task.getId() + " is null")); } else { - final AxEvent usedEvent = events.getEventMap().get(stateOutput.getOutgingEvent()); + final AxEvent usedEvent = events.getEventMap().get(stateOutput.getOutgoingEvent()); if (usedEvent == null) { result.addValidationMessage(new AxValidationMessage(stateOutput.getKey(), this.getClass(), - ValidationResult.INVALID, "output event " + stateOutput.getOutgingEvent().getId() + ValidationResult.INVALID, "output event " + stateOutput.getOutgoingEvent().getId() + " for state output " + stateOutput.getId() + DOES_NOT_EXIST)); } diff --git a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxStateOutput.java b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxStateOutput.java index 27c187356..1337e2417 100644 --- a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxStateOutput.java +++ b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxStateOutput.java @@ -3,6 +3,7 @@ * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,17 +24,24 @@ package org.onap.policy.apex.model.policymodel.concepts; import java.util.List; +import java.util.Set; import javax.persistence.AttributeOverride; +import javax.persistence.CollectionTable; import javax.persistence.Column; +import javax.persistence.ElementCollection; import javax.persistence.Embedded; import javax.persistence.EmbeddedId; import javax.persistence.Entity; +import javax.persistence.JoinColumn; import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; import org.onap.policy.apex.model.basicmodel.concepts.AxKey; @@ -68,13 +76,15 @@ import org.onap.policy.common.utils.validation.Assertions; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "apexStateOutput", namespace = "http://www.onap.org/policy/apex-pdp") @XmlType(name = "AxStateOutput", namespace = "http://www.onap.org/policy/apex-pdp", - propOrder = {"key", "outgoingEvent", "nextState"}) - + propOrder = {"key", "outgoingEvent", "outgoingEventSet", "nextState"}) +@Getter +@Setter public class AxStateOutput extends AxConcept { private static final long serialVersionUID = 8041771382337655535L; @EmbeddedId @XmlElement(name = "key", required = true) + @NonNull private AxReferenceKey key; // @formatter:off @@ -83,8 +93,17 @@ public class AxStateOutput extends AxConcept { @AttributeOverride(name = "version", column = @Column(name = "outgoingEventVersion")) @Column(name = "outgoingEvent") @XmlElement(required = true) + @NonNull private AxArtifactKey outgoingEvent; + @ElementCollection + @CollectionTable(joinColumns = {@JoinColumn(name = "stateParentKeyName", referencedColumnName = "parentKeyName"), + @JoinColumn(name = "stateParentKeyVersion", referencedColumnName = "parentKeyVersion"), + @JoinColumn(name = "stateParentLocalName", referencedColumnName = "parentLocalName"), + @JoinColumn(name = "stateLocalName", referencedColumnName = "localName")}) + @XmlElement(name = "outgoingEventReference", required = false) + private Set<AxArtifactKey> outgoingEventSet; + @Embedded @AttributeOverride(name = "parentKeyName", column = @Column(name = "nextStateParentKeyName")) @AttributeOverride(name = "parentKeyVersion", column = @Column(name = "nextStateParentKeyVersion")) @@ -92,6 +111,7 @@ public class AxStateOutput extends AxConcept { @AttributeOverride(name = "localName", column = @Column(name = "nextStateLocalName")) @Column(name = "nextState") @XmlElement(required = true) + @NonNull private AxReferenceKey nextState; // @formatter:on @@ -164,14 +184,6 @@ public class AxStateOutput extends AxConcept { * {@inheritDoc}. */ @Override - public AxReferenceKey getKey() { - return key; - } - - /** - * {@inheritDoc}. - */ - @Override public List<AxKey> getKeys() { final List<AxKey> keyList = key.getKeys(); keyList.add(new AxKeyUse(outgoingEvent)); @@ -184,54 +196,6 @@ public class AxStateOutput extends AxConcept { } /** - * Sets the reference key for the state output. - * - * @param key the reference key for the state output - */ - public void setKey(final AxReferenceKey key) { - Assertions.argumentNotNull(key, "key may not be null"); - this.key = key; - } - - /** - * Gets the outgoing event emitted on use of this state output. - * - * @return the outgoing event emitted on use of this state output - */ - public AxArtifactKey getOutgingEvent() { - return outgoingEvent; - } - - /** - * Sets the outgoing event emitted on use of this state output. - * - * @param outgoingEvent the outgoing event emitted on use of this state output - */ - public void setOutgoingEvent(final AxArtifactKey outgoingEvent) { - Assertions.argumentNotNull(outgoingEvent, "outgoingEvent may not be null"); - this.outgoingEvent = outgoingEvent; - } - - /** - * Gets the next state to which execution will pass on use of this state output. - * - * @return the next state to which execution will pass on use of this state output - */ - public AxReferenceKey getNextState() { - return nextState; - } - - /** - * Sets the next state to which execution will pass on use of this state output. - * - * @param nextState the next state to which execution will pass on use of this state output - */ - public void setNextState(final AxReferenceKey nextState) { - Assertions.argumentNotNull(nextState, "nextState may not be null"); - this.nextState = nextState; - } - - /** * {@inheritDoc}. */ @Override diff --git a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxTask.java b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxTask.java index 04b40e44b..a30a80acc 100644 --- a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxTask.java +++ b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/concepts/AxTask.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2021 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +34,7 @@ import javax.persistence.ElementCollection; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.Table; @@ -42,6 +44,9 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxConcept; import org.onap.policy.apex.model.basicmodel.concepts.AxKey; @@ -50,6 +55,7 @@ import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationMessage; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; import org.onap.policy.apex.model.eventmodel.concepts.AxField; import org.onap.policy.apex.model.eventmodel.concepts.AxInputField; import org.onap.policy.apex.model.eventmodel.concepts.AxOutputField; @@ -90,9 +96,13 @@ import org.onap.policy.common.utils.validation.Assertions; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "apexTask", namespace = "http://www.onap.org/policy/apex-pdp") -@XmlType(name = "AxTask", namespace = "http://www.onap.org/policy/apex-pdp", - propOrder = {"key", "inputFields", "outputFields", "taskParameters", "contextAlbumReferenceSet", "taskLogic"}) - +@XmlType( + name = "AxTask", + namespace = "http://www.onap.org/policy/apex-pdp", + propOrder = {"key", "inputEvent", "outputEvents", "inputFields", "outputFields", "taskParameters", + "contextAlbumReferenceSet", "taskLogic"}) +@Getter +@Setter public class AxTask extends AxConcept { private static final String DOES_NOT_EQUAL_TASK_KEY = " does not equal task key"; @@ -100,8 +110,25 @@ public class AxTask extends AxConcept { @EmbeddedId @XmlElement(name = "key", required = true) + @NonNull private AxArtifactKey key; + @OneToOne(cascade = CascadeType.ALL) + @JoinTable( + name = "INPUT_EVENT_JT", + joinColumns = {@JoinColumn(name = "inEventTaskName", referencedColumnName = "name", updatable = false), + @JoinColumn(name = "inEventTaskVersion", referencedColumnName = "version", updatable = false)}) + @XmlElement(name = "inputEvent", required = false) + private AxEvent inputEvent; + + @OneToMany(cascade = CascadeType.ALL) + @JoinTable( + name = "OUTPUT_EVENT_JT", + joinColumns = {@JoinColumn(name = "outEventTaskName", referencedColumnName = "name", updatable = false), + @JoinColumn(name = "outEventTaskVersion", referencedColumnName = "version", updatable = false)}) + @XmlElement(name = "outputEvents", required = false) + private Map<String, AxEvent> outputEvents; + @OneToMany(cascade = CascadeType.ALL) @XmlElement(name = "inputFields", required = true) private Map<String, AxInputField> inputFields; @@ -119,11 +146,13 @@ public class AxTask extends AxConcept { @CollectionTable(joinColumns = {@JoinColumn(name = "contextAlbumName", referencedColumnName = "name"), @JoinColumn(name = "contextAlbumVersion", referencedColumnName = "version")}) @XmlElement(name = "contextAlbumReference") + @NonNull private Set<AxArtifactKey> contextAlbumReferenceSet; // @formatter:on @OneToOne(cascade = CascadeType.ALL) @XmlElement(required = true) + @NonNull private AxTaskLogic taskLogic; /** @@ -219,14 +248,6 @@ public class AxTask extends AxConcept { * {@inheritDoc}. */ @Override - public AxArtifactKey getKey() { - return key; - } - - /** - * {@inheritDoc}. - */ - @Override public List<AxKey> getKeys() { final List<AxKey> keyList = key.getKeys(); for (final AxInputField inputField : inputFields.values()) { @@ -246,25 +267,6 @@ public class AxTask extends AxConcept { } /** - * Sets the key of the task. - * - * @param key the key of the task - */ - public void setKey(final AxArtifactKey key) { - Assertions.argumentNotNull(key, "key may not be null"); - this.key = key; - } - - /** - * Gets the input fields that the task expects. - * - * @return the input fields that the task expects - */ - public Map<String, AxInputField> getInputFields() { - return inputFields; - } - - /** * Gets the raw input fields that the task expects as a tree map. * * @return the raw input fields that the task expects @@ -287,16 +289,6 @@ public class AxTask extends AxConcept { } /** - * Sets the input fields that the task expects. - * - * @param inputFields the input fields that the task expects - */ - public void setInputFields(final Map<String, AxInputField> inputFields) { - Assertions.argumentNotNull(inputFields, "inputFields may not be null"); - this.inputFields = inputFields; - } - - /** * Copy the input fields from the given map into the task. This method is used to get a copy of * the input fields, which can be useful for unit testing of policies and tasks. * @@ -314,15 +306,6 @@ public class AxTask extends AxConcept { } /** - * Gets the output fields that the task emits. - * - * @return the output fields that the task emits - */ - public Map<String, AxOutputField> getOutputFields() { - return outputFields; - } - - /** * Gets the raw output fields that the task emits as a tree map. * * @return the raw output fields as a tree map @@ -345,16 +328,6 @@ public class AxTask extends AxConcept { } /** - * Sets the output fields that the task emits. - * - * @param outputFields the output fields that the task emits - */ - public void setOutputFields(final Map<String, AxOutputField> outputFields) { - Assertions.argumentNotNull(outputFields, "outputFields may not be null"); - this.outputFields = outputFields; - } - - /** * Copy the output fields from the given map into the task. This method is used to get a copy of * the output fields, which can be useful for unit testing of policies and tasks. * @@ -371,24 +344,6 @@ public class AxTask extends AxConcept { } } - /** - * Gets the task parameters that are used to initialize tasks of this type. - * - * @return the task parameters that are used to initialize tasks of this type - */ - public Map<String, AxTaskParameter> getTaskParameters() { - return taskParameters; - } - - /** - * Sets the task parameters that are used to initialize tasks of this type. - * - * @param taskParameters the task parameters that are used to initialize tasks of this type - */ - public void setTaskParameters(final Map<String, AxTaskParameter> taskParameters) { - Assertions.argumentNotNull(taskParameters, "taskParameters may not be null"); - this.taskParameters = taskParameters; - } /** * Gets the context album reference set defines the context that may be used by Task Logic in @@ -414,25 +369,6 @@ public class AxTask extends AxConcept { } /** - * Gets the task logic that performs the domain specific work of the task. - * - * @return the task logic that performs the domain specific work of the task - */ - public AxTaskLogic getTaskLogic() { - return taskLogic; - } - - /** - * Sets the task logic that performs the domain specific work of the task. - * - * @param taskLogic the task logic that performs the domain specific work of the task - */ - public void setTaskLogic(final AxTaskLogic taskLogic) { - Assertions.argumentNotNull(taskLogic, "taskLogic may not be null"); - this.taskLogic = taskLogic; - } - - /** * {@inheritDoc}. */ @Override @@ -446,30 +382,12 @@ public class AxTask extends AxConcept { result = key.validate(result); - if (inputFields.size() == 0) { - result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, - "inputFields may not be empty")); - } else { - for (final Entry<String, AxInputField> inputFieldEntry : inputFields.entrySet()) { - result = validateField(inputFieldEntry.getKey(), inputFieldEntry.getValue(), "input", result); - } - } - - if (outputFields.size() == 0) { - result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, - "outputFields may not be empty")); - } else { - for (final Entry<String, AxOutputField> outputFieldEntry : outputFields.entrySet()) { - result = validateField(outputFieldEntry.getKey(), outputFieldEntry.getValue(), "input", result); - } - } - for (final Entry<String, AxTaskParameter> taskParameterEntry : taskParameters.entrySet()) { - result = vaildateTaskParameterEntry(taskParameterEntry, result); + result = validateTaskParameterEntry(taskParameterEntry, result); } for (final AxArtifactKey contextAlbumReference : contextAlbumReferenceSet) { - result = vaildateContextAlbumReference(contextAlbumReference, result); + result = validateContextAlbumReference(contextAlbumReference, result); } if (!taskLogic.getKey().getParentArtifactKey().equals(key)) { @@ -481,39 +399,13 @@ public class AxTask extends AxConcept { } /** - * Validate a field. - * - * @param fieldKey the key of the field to validate - * @param field the field to validate - * @param direction The direction of the field - * @param result The validation result to append to - * @return The result of the validation - */ - private AxValidationResult validateField(final String fieldKey, final AxField field, final String direction, - AxValidationResult result) { - if (field == null) { - result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, - "null " + direction + " field value found on " + direction + " field " + fieldKey)); - } else { - if (!field.getKey().getParentArtifactKey().equals(key)) { - result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, - "parent key on " + direction + " field " + fieldKey + DOES_NOT_EQUAL_TASK_KEY)); - } - - result = field.validate(result); - } - - return result; - } - - /** * Validate a task parameter entry. * * @param taskParameterEntry the task parameter entry to validate * @param result The validation result to append to * @return The result of the validation */ - private AxValidationResult vaildateTaskParameterEntry(final Entry<String, AxTaskParameter> taskParameterEntry, + private AxValidationResult validateTaskParameterEntry(final Entry<String, AxTaskParameter> taskParameterEntry, AxValidationResult result) { if (taskParameterEntry.getValue() == null) { result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, @@ -537,7 +429,7 @@ public class AxTask extends AxConcept { * @param result The validation result to append to * @return The result of the validation */ - private AxValidationResult vaildateContextAlbumReference(final AxArtifactKey contextAlbumReference, + private AxValidationResult validateContextAlbumReference(final AxArtifactKey contextAlbumReference, AxValidationResult result) { if (contextAlbumReference.equals(AxArtifactKey.getNullKey())) { result.addValidationMessage(new AxValidationMessage(key, this.getClass(), ValidationResult.INVALID, diff --git a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyAnalyser.java b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyAnalyser.java index 4d076cfda..3a4c36bc5 100644 --- a/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyAnalyser.java +++ b/model/policy-model/src/main/java/org/onap/policy/apex/model/policymodel/handling/PolicyAnalyser.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -137,7 +138,7 @@ public class PolicyAnalyser { // Event usage by state result.getEventUsage().get(state.getTrigger()).add(state.getKey()); for (final AxStateOutput stateOutput : state.getStateOutputs().values()) { - result.getEventUsage().get(stateOutput.getOutgingEvent()).add(state.getKey()); + result.getEventUsage().get(stateOutput.getOutgoingEvent()).add(state.getKey()); } // State Context Usage diff --git a/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/PolicyModelTest.java b/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/PolicyModelTest.java index 86bbf3e93..48022e878 100644 --- a/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/PolicyModelTest.java +++ b/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/PolicyModelTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -335,7 +336,7 @@ public class PolicyModelTest { final AxStateOutput so = model.getPolicies().get("policy").getStateMap().get("state").getStateOutputs() .get(savedStateOutputName); - final AxArtifactKey savedOutEvent = so.getOutgingEvent(); + final AxArtifactKey savedOutEvent = so.getOutgoingEvent(); so.setOutgoingEvent(new AxArtifactKey("NonExistantEvent", "0.0.1")); result = new AxValidationResult(); result = model.validate(result); diff --git a/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/StateOutputTest.java b/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/StateOutputTest.java index 8bd29fc55..049783a7f 100644 --- a/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/StateOutputTest.java +++ b/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/StateOutputTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,20 +54,20 @@ public class StateOutputTest { final AxArtifactKey eKey = new AxArtifactKey("EventName", "0.0.1"); assertThatThrownBy(() -> so.setKey(null)) - .hasMessage("key may not be null"); + .hasMessage("key is marked non-null but is null"); so.setKey(soKey); assertEquals("SOStateParent:0.0.1:SOState:SOName", so.getKey().getId()); assertEquals("SOStateParent:0.0.1:SOState:SOName", so.getKeys().get(0).getId()); assertThatThrownBy(() -> so.setNextState(null)) - .hasMessage("nextState may not be null"); + .hasMessage("nextState is marked non-null but is null"); so.setNextState(nsKey); assertEquals(nsKey, so.getNextState()); assertThatThrownBy(() -> so.setOutgoingEvent(null)) - .hasMessage("outgoingEvent may not be null"); + .hasMessage("outgoingEvent is marked non-null but is null"); so.setOutgoingEvent(eKey); - assertEquals(eKey, so.getOutgingEvent()); + assertEquals(eKey, so.getOutgoingEvent()); AxValidationResult result = new AxValidationResult(); result = so.validate(result); diff --git a/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/TasksTest.java b/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/TasksTest.java index 100adb9fd..95266acc8 100644 --- a/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/TasksTest.java +++ b/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/concepts/TasksTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +27,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; import org.junit.Test; @@ -33,6 +35,7 @@ import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult; import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult.ValidationResult; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; import org.onap.policy.apex.model.eventmodel.concepts.AxField; import org.onap.policy.apex.model.eventmodel.concepts.AxInputField; import org.onap.policy.apex.model.eventmodel.concepts.AxOutputField; @@ -91,7 +94,8 @@ public class TasksTest { assertEquals(ofMap, task.getOutputFields()); assertTrue(task.getOutputFieldSet().contains(of0)); assertTrue(task.getRawOutputFields().keySet().contains(of0.getKey().getLocalName())); - + task.setInputEvent(new AxEvent()); + task.setOutputEvents(Map.of("Event", new AxEvent())); final TreeMap<String, AxField> ifDupMap = new TreeMap<>(); final TreeMap<String, AxField> ofDupMap = new TreeMap<>(); ifDupMap.put(if1.getKey().getLocalName(), if1); @@ -131,46 +135,6 @@ public class TasksTest { result = task.validate(result); assertEquals(ValidationResult.VALID, result.getValidationResult()); - task.setInputFields(ifEmptyMap); - result = new AxValidationResult(); - result = task.validate(result); - assertEquals(ValidationResult.INVALID, result.getValidationResult()); - - task.setInputFields(ifMap); - result = new AxValidationResult(); - result = task.validate(result); - assertEquals(ValidationResult.VALID, result.getValidationResult()); - - ifMap.put("NullField", null); - result = new AxValidationResult(); - result = task.validate(result); - assertEquals(ValidationResult.INVALID, result.getValidationResult()); - - ifMap.remove("NullField"); - result = new AxValidationResult(); - result = task.validate(result); - assertEquals(ValidationResult.VALID, result.getValidationResult()); - - task.setOutputFields(ofEmptyMap); - result = new AxValidationResult(); - result = task.validate(result); - assertEquals(ValidationResult.INVALID, result.getValidationResult()); - - task.setOutputFields(ofMap); - result = new AxValidationResult(); - result = task.validate(result); - assertEquals(ValidationResult.VALID, result.getValidationResult()); - - ofMap.put("NullField", null); - result = new AxValidationResult(); - result = task.validate(result); - assertEquals(ValidationResult.INVALID, result.getValidationResult()); - - ofMap.remove("NullField"); - result = new AxValidationResult(); - result = task.validate(result); - assertEquals(ValidationResult.VALID, result.getValidationResult()); - // Empty task parameter map is OK task.setTaskParameters(tpEmptyMap); result = new AxValidationResult(); diff --git a/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/handling/SupportApexPolicyModelCreator.java b/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/handling/SupportApexPolicyModelCreator.java index 3fca39739..ea2de8603 100644 --- a/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/handling/SupportApexPolicyModelCreator.java +++ b/model/policy-model/src/test/java/org/onap/policy/apex/model/policymodel/handling/SupportApexPolicyModelCreator.java @@ -1,25 +1,27 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * + * * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ package org.onap.policy.apex.model.policymodel.handling; +import java.util.Map; import java.util.UUID; import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey; import org.onap.policy.apex.model.basicmodel.concepts.AxKeyInfo; @@ -52,7 +54,7 @@ import org.onap.policy.apex.model.policymodel.concepts.AxTasks; /** * Model creator for model tests. - * + * * @author Liam Fallon (liam.fallon@ericsson.com) */ public class SupportApexPolicyModelCreator implements TestApexModelCreator<AxPolicyModel> { @@ -136,6 +138,9 @@ public class SupportApexPolicyModelCreator implements TestApexModelCreator<AxPol task.getOutputFields().put(outputField.getKey().getLocalName(), outputField); } + task.setInputEvent(inEvent); + task.setOutputEvents(Map.of(outEvent0.getId(), outEvent0, outEvent1.getId(), outEvent1)); + final AxTaskParameter taskPar0 = new AxTaskParameter(new AxReferenceKey(task.getKey(), "taskParameter0"), "Task parameter 0 value"); final AxTaskParameter taskPar1 = new AxTaskParameter(new AxReferenceKey(task.getKey(), "taskParameter1"), @@ -206,7 +211,7 @@ public class SupportApexPolicyModelCreator implements TestApexModelCreator<AxPol /** * Gets another policy model. - * + * * @return the model */ public AxPolicyModel getAnotherModel() { @@ -287,6 +292,9 @@ public class SupportApexPolicyModelCreator implements TestApexModelCreator<AxPol task.getOutputFields().put(outputField.getKey().getLocalName(), outputField); } + task.setInputEvent(inEvent); + task.setOutputEvents(Map.of(outEvent0.getId(), outEvent0, outEvent1.getId(), outEvent1)); + final AxTaskParameter taskPar0 = new AxTaskParameter(new AxReferenceKey(task.getKey(), "taskParameterA0"), "Task parameter 0 value"); final AxTaskParameter taskPar1 = new AxTaskParameter(new AxReferenceKey(task.getKey(), "taskParameterA1"), @@ -406,6 +414,8 @@ public class SupportApexPolicyModelCreator implements TestApexModelCreator<AxPol anotherTask.getOutputFields().put(outputField.getKey().getLocalName(), outputField); } + anotherTask.setInputEvent(inEvent); + anotherTask.setOutputEvents(Map.of(outEvent0.getId(), outEvent0)); final AxTaskParameter taskPar0 = new AxTaskParameter(new AxReferenceKey(anotherTask.getKey(), "taskParameter0"), "Task parameter 0 value"); final AxTaskParameter taskPar1 = new AxTaskParameter(new AxReferenceKey(anotherTask.getKey(), "taskParameter1"), diff --git a/plugins/plugins-executor/plugins-executor-java/src/main/java/org/onap/policy/apex/plugins/executor/java/JavaTaskExecutor.java b/plugins/plugins-executor/plugins-executor-java/src/main/java/org/onap/policy/apex/plugins/executor/java/JavaTaskExecutor.java index 2ccddcf0f..736249efd 100644 --- a/plugins/plugins-executor/plugins-executor-java/src/main/java/org/onap/policy/apex/plugins/executor/java/JavaTaskExecutor.java +++ b/plugins/plugins-executor/plugins-executor-java/src/main/java/org/onap/policy/apex/plugins/executor/java/JavaTaskExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,7 +77,7 @@ public class JavaTaskExecutor extends TaskExecutor { * @throws ContextException on context errors */ @Override - public Map<String, Object> execute(final long executionId, final Properties executionProperties, + public Map<String, Map<String, Object>> execute(final long executionId, final Properties executionProperties, final Map<String, Object> incomingFields) throws StateMachineException, ContextException { // Do execution pre work executePre(executionId, executionProperties, incomingFields); diff --git a/plugins/plugins-executor/plugins-executor-java/src/test/java/org/onap/policy/apex/plugins/executor/java/JavaTaskExecutorTest.java b/plugins/plugins-executor/plugins-executor-java/src/test/java/org/onap/policy/apex/plugins/executor/java/JavaTaskExecutorTest.java index 7f263245c..96bc6bb3d 100644 --- a/plugins/plugins-executor/plugins-executor-java/src/test/java/org/onap/policy/apex/plugins/executor/java/JavaTaskExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-java/src/test/java/org/onap/policy/apex/plugins/executor/java/JavaTaskExecutorTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +29,7 @@ import static org.junit.Assert.assertNotNull; import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.TreeMap; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -38,6 +40,7 @@ import org.onap.policy.apex.context.parameters.LockManagerParameters; import org.onap.policy.apex.context.parameters.PersistorParameters; import org.onap.policy.apex.core.engine.context.ApexInternalContext; import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel; import org.onap.policy.apex.model.policymodel.concepts.AxTask; import org.onap.policy.common.parameters.ParameterService; @@ -83,7 +86,8 @@ public class JavaTaskExecutorTest { assertThatThrownBy(jte::prepare) .hasMessage("instantiation error on Java class \"\""); task.getTaskLogic().setLogic("java.lang.String"); - + task.setInputEvent(new AxEvent()); + task.setOutputEvents(new TreeMap<>()); jte.prepare(); assertThatThrownBy(() -> jte.execute(-1, new Properties(), null)) @@ -96,7 +100,7 @@ public class JavaTaskExecutorTest { assertThatThrownBy(() -> jte.execute(-1, new Properties(), incomingParameters)) .hasMessage("execute-post: task logic execution failure on task \"NULL\" in model NULL:0.0.0"); jte.prepare(); - Map<String, Object> returnMap = jte.execute(0, new Properties(), incomingParameters); + Map<String, Map<String, Object>> returnMap = jte.execute(0, new Properties(), incomingParameters); assertEquals(0, returnMap.size()); jte.cleanUp(); diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java index a25dca0c6..f88e3ef1e 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/main/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019-2020 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,7 +67,7 @@ public class JavascriptTaskExecutor extends TaskExecutor { * @throws ContextException on context errors */ @Override - public Map<String, Object> execute(final long executionId, final Properties executionProperties, + public Map<String, Map<String, Object>> execute(final long executionId, final Properties executionProperties, final Map<String, Object> incomingFields) throws StateMachineException, ContextException { executePre(executionId, executionProperties, incomingFields); boolean result = javascriptExecutor.execute(getExecutionContext()); diff --git a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java index 991c89bcb..fbf7db864 100644 --- a/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-javascript/src/test/java/org/onap/policy/apex/plugins/executor/javascript/JavascriptTaskExecutorTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2019-2020 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +30,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; +import java.util.TreeMap; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -47,6 +49,8 @@ import org.onap.policy.apex.model.basicmodel.service.ModelService; import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum; import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchema; import org.onap.policy.apex.model.contextmodel.concepts.AxContextSchemas; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; +import org.onap.policy.apex.model.eventmodel.concepts.AxField; import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel; import org.onap.policy.apex.model.policymodel.concepts.AxTask; import org.onap.policy.common.parameters.ParameterService; @@ -123,7 +127,8 @@ public class JavascriptTaskExecutorTest { jte.execute(-1, props, null); }).isInstanceOf(NullPointerException.class); jte.cleanUp(); - + task.setInputEvent(new AxEvent()); + task.setOutputEvents(new TreeMap<>()); task.getTaskLogic().setLogic("var returnValue = false;\nreturnValue;"); Map<String, Object> incomingParameters = new HashMap<>(); @@ -138,13 +143,14 @@ public class JavascriptTaskExecutorTest { task.getTaskLogic().setLogic("var returnValue = true;\nreturnValue;"); jte.prepare(); - Map<String, Object> returnMap = jte.execute(0, new Properties(), incomingParameters); + Map<String, Map<String, Object>> returnMap = jte.execute(0, new Properties(), incomingParameters); assertEquals(0, returnMap.size()); jte.cleanUp(); } @Test public void testJavascriptTaskExecutorLogic() throws Exception { + JavascriptTaskExecutor jte = new JavascriptTaskExecutor(); assertNotNull(jte); @@ -160,16 +166,25 @@ public class JavascriptTaskExecutorTest { internalContext.getContextAlbums().put(contextAlbum.getKey(), contextAlbum); task.getContextAlbumReferences().add(contextAlbum.getKey()); - task.getOutputFields().put("par0", null); - task.getOutputFields().put("par1", null); + String parKey0 = "par0"; + task.getOutputFields().put(parKey0, null); + String parKey1 = "par1"; + task.getOutputFields().put(parKey1, null); jte.setContext(null, task, internalContext); Map<String, Object> incomingParameters = new HashMap<>(); - incomingParameters.put("par0", "value0"); + incomingParameters.put(parKey0, "value0"); - task.getTaskLogic().setLogic(TextFileUtils.getTextFileAsString("src/test/resources/javascript/TestLogic00.js")); + AxEvent inEvent = new AxEvent(); + inEvent.setParameterMap(Map.of(parKey0, new AxField())); + task.setInputEvent(inEvent); + AxEvent outEvent = new AxEvent(); + outEvent.setParameterMap(Map.of(parKey0, new AxField(), parKey1, new AxField())); + final String eventName = "event1"; + task.setOutputEvents(Map.of(eventName, outEvent)); + task.getTaskLogic().setLogic(TextFileUtils.getTextFileAsString("src/test/resources/javascript/TestLogic00.js")); jte.prepare(); jte.execute(-1, new Properties(), incomingParameters); jte.cleanUp(); @@ -177,11 +192,11 @@ public class JavascriptTaskExecutorTest { task.getTaskLogic().setLogic(TextFileUtils.getTextFileAsString("src/test/resources/javascript/TestLogic01.js")); jte.prepare(); - Map<String, Object> outcomingParameters = jte.execute(-1, new Properties(), incomingParameters); + Map<String, Map<String, Object>> outcomingParameters = jte.execute(-1, new Properties(), incomingParameters); jte.cleanUp(); - assertEquals("returnVal0", outcomingParameters.get("par0")); - assertEquals("returnVal1", outcomingParameters.get("par1")); + assertEquals("returnVal0", outcomingParameters.get(eventName).get(parKey0)); + assertEquals("returnVal1", outcomingParameters.get(eventName).get(parKey1)); } private ContextAlbum createTestContextAlbum() throws ContextException { diff --git a/plugins/plugins-executor/plugins-executor-jruby/src/main/java/org/onap/policy/apex/plugins/executor/jruby/JrubyTaskExecutor.java b/plugins/plugins-executor/plugins-executor-jruby/src/main/java/org/onap/policy/apex/plugins/executor/jruby/JrubyTaskExecutor.java index 02504c670..aa5700433 100644 --- a/plugins/plugins-executor/plugins-executor-jruby/src/main/java/org/onap/policy/apex/plugins/executor/jruby/JrubyTaskExecutor.java +++ b/plugins/plugins-executor/plugins-executor-jruby/src/main/java/org/onap/policy/apex/plugins/executor/jruby/JrubyTaskExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,7 +81,7 @@ public class JrubyTaskExecutor extends TaskExecutor { * @throws ContextException on context errors */ @Override - public Map<String, Object> execute(final long executionId, final Properties executionProperties, + public Map<String, Map<String, Object>> execute(final long executionId, final Properties executionProperties, final Map<String, Object> incomingFields) throws StateMachineException, ContextException { // Do execution pre work executePre(executionId, executionProperties, incomingFields); diff --git a/plugins/plugins-executor/plugins-executor-jruby/src/test/java/org/onap/policy/apex/plugins/executor/jruby/JrubyTaskExecutorTest.java b/plugins/plugins-executor/plugins-executor-jruby/src/test/java/org/onap/policy/apex/plugins/executor/jruby/JrubyTaskExecutorTest.java index e2785d816..0cc476425 100644 --- a/plugins/plugins-executor/plugins-executor-jruby/src/test/java/org/onap/policy/apex/plugins/executor/jruby/JrubyTaskExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-jruby/src/test/java/org/onap/policy/apex/plugins/executor/jruby/JrubyTaskExecutorTest.java @@ -1,7 +1,7 @@ /*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2019 Nordix Foundation.
- * Modifications Copyright (C) 2019-2020 Nordix Foundation.
+ * Copyright (C) 2019-2020 Nordix Foundation.
+ * Modifications Copyright (C) 2021 Bell Canada. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ import java.lang.reflect.Field; import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
+import java.util.TreeMap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -39,6 +40,7 @@ import org.onap.policy.apex.context.parameters.LockManagerParameters; import org.onap.policy.apex.context.parameters.PersistorParameters;
import org.onap.policy.apex.core.engine.context.ApexInternalContext;
import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
+import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
import org.onap.policy.apex.model.policymodel.concepts.AxTask;
import org.onap.policy.common.parameters.ParameterService;
@@ -91,7 +93,8 @@ public class JrubyTaskExecutorTest { AxTask task = new AxTask();
ApexInternalContext internalContext = null;
internalContext = new ApexInternalContext(new AxPolicyModel());
-
+ task.setInputEvent(new AxEvent());
+ task.setOutputEvents(new TreeMap<>());
jte.setContext(null, task, internalContext);
jte.prepare();
@@ -102,14 +105,13 @@ public class JrubyTaskExecutorTest { final String jrubyLogic = "if executor.executionId == -1" + "\n return false" + "\n else " + "\n return true"
+ "\n end";
task.getTaskLogic().setLogic(jrubyLogic);
-
jte.prepare();
- Map<String, Object> returnMap = jte.execute(0, new Properties(), incomingParameters);
+ Map<String, Map<String, Object>> returnMap = jte.execute(0, new Properties(), incomingParameters);
assertEquals(0, returnMap.size());
jte.cleanUp();
jte.prepare();
- Map<String, Object> returnMap1 = jte.execute(0, new Properties(), incomingParameters);
+ Map<String, Map<String, Object>> returnMap1 = jte.execute(0, new Properties(), incomingParameters);
assertEquals(0, returnMap1.size());
jte.cleanUp();
}
diff --git a/plugins/plugins-executor/plugins-executor-mvel/src/main/java/org/onap/policy/apex/plugins/executor/mvel/MvelTaskExecutor.java b/plugins/plugins-executor/plugins-executor-mvel/src/main/java/org/onap/policy/apex/plugins/executor/mvel/MvelTaskExecutor.java index 179462bb1..07a287f4d 100644 --- a/plugins/plugins-executor/plugins-executor-mvel/src/main/java/org/onap/policy/apex/plugins/executor/mvel/MvelTaskExecutor.java +++ b/plugins/plugins-executor/plugins-executor-mvel/src/main/java/org/onap/policy/apex/plugins/executor/mvel/MvelTaskExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,7 +78,7 @@ public class MvelTaskExecutor extends TaskExecutor { * @throws ContextException on context errors */ @Override - public Map<String, Object> execute(final long executionId, final Properties executionProperties, + public Map<String, Map<String, Object>> execute(final long executionId, final Properties executionProperties, final Map<String, Object> incomingFields) throws StateMachineException, ContextException { // Do execution pre work executePre(executionId, executionProperties, incomingFields); diff --git a/plugins/plugins-executor/plugins-executor-mvel/src/test/java/org/onap/policy/apex/plugins/executor/mvel/MvelTaskExecutorTest.java b/plugins/plugins-executor/plugins-executor-mvel/src/test/java/org/onap/policy/apex/plugins/executor/mvel/MvelTaskExecutorTest.java index a4d2cbf2b..3d59c4b21 100644 --- a/plugins/plugins-executor/plugins-executor-mvel/src/test/java/org/onap/policy/apex/plugins/executor/mvel/MvelTaskExecutorTest.java +++ b/plugins/plugins-executor/plugins-executor-mvel/src/test/java/org/onap/policy/apex/plugins/executor/mvel/MvelTaskExecutorTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2019 Nordix Foundation. * Modifications Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +29,7 @@ import static org.junit.Assert.assertNotNull; import java.util.HashMap; import java.util.Map; import java.util.Properties; +import java.util.TreeMap; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -38,6 +40,7 @@ import org.onap.policy.apex.context.parameters.LockManagerParameters; import org.onap.policy.apex.context.parameters.PersistorParameters; import org.onap.policy.apex.core.engine.context.ApexInternalContext; import org.onap.policy.apex.core.engine.executor.exception.StateMachineException; +import org.onap.policy.apex.model.eventmodel.concepts.AxEvent; import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel; import org.onap.policy.apex.model.policymodel.concepts.AxTask; import org.onap.policy.common.parameters.ParameterService; @@ -77,6 +80,8 @@ public class MvelTaskExecutorTest { AxTask task = new AxTask(); ApexInternalContext internalContext = null; internalContext = new ApexInternalContext(new AxPolicyModel()); + task.setInputEvent(new AxEvent()); + task.setOutputEvents(new TreeMap<>()); mte.setContext(null, task, internalContext); task.getTaskLogic().setLogic("x > 1 2 ()"); @@ -97,7 +102,7 @@ public class MvelTaskExecutorTest { .hasMessage("execute-post: task logic execution failure on task \"NULL\" in model NULL:0.0.0"); mte.prepare(); - Map<String, Object> returnMap = mte.execute(0, new Properties(), incomingParameters); + Map<String, Map<String, Object>> returnMap = mte.execute(0, new Properties(), incomingParameters); assertEquals(0, returnMap.size()); mte.cleanUp(); } diff --git a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/DummyTaskExecutor.java b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/DummyTaskExecutor.java index fb2dea58b..56f0af5c6 100644 --- a/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/DummyTaskExecutor.java +++ b/services/services-engine/src/test/java/org/onap/policy/apex/service/engine/parameters/dummyclasses/DummyTaskExecutor.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,11 +44,11 @@ public class DummyTaskExecutor extends TaskExecutor { } @Override - public Map<String, Object> execute(final long executionId, final Properties executorProperties, + public Map<String, Map<String, Object>> execute(final long executionId, final Properties executorProperties, final Map<String, Object> newIncomingFields) throws StateMachineException, ContextException { AxArtifactKey event0Key = new AxArtifactKey("Event0:0.0.1"); - return new EnEvent(event0Key); + return Map.of(event0Key.getName(), new EnEvent(event0Key)); } @Override diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskExecutor.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskExecutor.java index d89fd2eb8..01f45a53e 100644 --- a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskExecutor.java +++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/parameters/dummyclasses/DummyTaskExecutor.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,11 +45,11 @@ public class DummyTaskExecutor extends TaskExecutor { } @Override - public Map<String, Object> execute(final long executionId, final Properties executorProperties, + public Map<String, Map<String, Object>> execute(final long executionId, final Properties executorProperties, final Map<String, Object> newIncomingFields) throws StateMachineException, ContextException { AxArtifactKey event0Key = new AxArtifactKey("Event0:0.0.1"); - return new EnEvent(event0Key); + return Map.of(event0Key.getName(), new EnEvent(event0Key)); } @Override diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Model2Cli.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Model2Cli.java index 321f64993..81d897762 100644 --- a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Model2Cli.java +++ b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2cli/Model2Cli.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2019 Samsung Electronics Co., Ltd. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -490,7 +491,7 @@ public class Model2Cli { final AxReferenceKey outkey = out.getKey(); final ST val = cg.createPolicyStateOutput(kig.getPName(skey), kig.getPVersion(skey), kig.getLName(skey), - kig.getLName(outkey), kig.getName(out.getOutgingEvent()), kig.getVersion(out.getOutgingEvent()), + kig.getLName(outkey), kig.getName(out.getOutgoingEvent()), kig.getVersion(out.getOutgoingEvent()), kig.getLName(out.getNextState())); ret.add(val); diff --git a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Model2JsonEventSchema.java b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Model2JsonEventSchema.java index e48c233e2..ad0f3b613 100644 --- a/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Model2JsonEventSchema.java +++ b/tools/model-generator/src/main/java/org/onap/policy/apex/tools/model/generator/model2event/Model2JsonEventSchema.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2016-2018 Ericsson. All rights reserved. * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021 Bell Canada. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -307,7 +308,7 @@ public class Model2JsonEventSchema { for (final AxState state : policy.getStateMap().values()) { if ("NULL".equals(state.getNextStateSet().iterator().next())) { for (final AxStateOutput output : state.getStateOutputs().values()) { - eventKeys.add(output.getOutgingEvent()); + eventKeys.add(output.getOutgoingEvent()); } } } @@ -342,7 +343,7 @@ public class Model2JsonEventSchema { return; } for (final AxStateOutput output : state.getStateOutputs().values()) { - eventKeys.add(output.getOutgingEvent()); + eventKeys.add(output.getOutgoingEvent()); } } |