diff options
51 files changed, 1985 insertions, 1521 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..59433dccd 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/main/java/org/onap/policy/apex/services/onappf/ApexStarterActivator.java b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/ApexStarterActivator.java index b9424c274..abd8d4436 100644 --- a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/ApexStarterActivator.java +++ b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/ApexStarterActivator.java @@ -80,6 +80,9 @@ public class ApexStarterActivator { @Getter private List<ToscaConceptIdentifier> supportedPolicyTypes; + @Getter + private final String instanceId; + /** * Instantiate the activator for onappf PDP-A. * @@ -93,7 +96,7 @@ public class ApexStarterActivator { topicSources = TopicEndpointManager.getManager() .addTopicSources(apexStarterParameterGroup.getTopicParameterGroup().getTopicSources()); - final String instanceId = NetworkUtil.getHostname(); + instanceId = NetworkUtil.genUniqueName("apex"); LOGGER.debug("ApexStarterActivator initializing with instance id: {}", instanceId); try { this.apexStarterParameterGroup = apexStarterParameterGroup; diff --git a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/rest/HealthCheckProvider.java b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/rest/HealthCheckProvider.java index 12a34ef57..1c6b88700 100644 --- a/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/rest/HealthCheckProvider.java +++ b/services/services-onappf/src/main/java/org/onap/policy/apex/services/onappf/rest/HealthCheckProvider.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 AT&T Intellectual Property. 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. @@ -35,7 +36,6 @@ public class HealthCheckProvider { private static final String NOT_ALIVE = "not alive"; private static final String ALIVE = "alive"; private static final String URL = "self"; - private static final String NAME = "Policy PDP-A"; /** * Performs the health check of PAP service. @@ -43,13 +43,13 @@ public class HealthCheckProvider { * @return Report containing health check status */ public HealthCheckReport performHealthCheck() { + final ApexStarterActivator activator = + Registry.get(ApexStarterConstants.REG_APEX_STARTER_ACTIVATOR, ApexStarterActivator.class); + final boolean alive = activator.isAlive(); + final HealthCheckReport report = new HealthCheckReport(); - report.setName(NAME); + report.setName(activator.getInstanceId()); report.setUrl(URL); - - final boolean alive = - Registry.get(ApexStarterConstants.REG_APEX_STARTER_ACTIVATOR, ApexStarterActivator.class).isAlive(); - report.setHealthy(alive); report.setCode(alive ? 200 : 500); report.setMessage(alive ? ALIVE : NOT_ALIVE); 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/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/rest/CommonApexStarterRestServer.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/rest/CommonApexStarterRestServer.java index 283134087..65d901d41 100644 --- a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/rest/CommonApexStarterRestServer.java +++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/rest/CommonApexStarterRestServer.java @@ -71,7 +71,6 @@ public class CommonApexStarterRestServer { public static final String NOT_ALIVE = "not alive"; public static final String ALIVE = "alive"; public static final String SELF = "self"; - public static final String NAME = "Policy PDP-A"; public static final String ENDPOINT_PREFIX = "policy/apex-pdp/v1/"; private static int port; diff --git a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/rest/TestHealthCheckRestControllerV1.java b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/rest/TestHealthCheckRestControllerV1.java index 100db5d8d..7ccfe85b3 100644 --- a/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/rest/TestHealthCheckRestControllerV1.java +++ b/services/services-onappf/src/test/java/org/onap/policy/apex/services/onappf/rest/TestHealthCheckRestControllerV1.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2019 Nordix Foundation. + * Modifications Copyright (C) 2021 AT&T Intellectual Property. 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,6 +21,7 @@ package org.onap.policy.apex.services.onappf.rest; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import javax.ws.rs.client.Invocation; @@ -44,15 +46,15 @@ public class TestHealthCheckRestControllerV1 extends CommonApexStarterRestServer public void testHealthCheckSuccess() throws Exception { final Invocation.Builder invocationBuilder = sendRequest(HEALTHCHECK_ENDPOINT); final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class); - validateHealthCheckReport(NAME, SELF, true, 200, ALIVE, report); + validateHealthCheckReport(SELF, true, 200, ALIVE, report); // verify it fails when no authorization info is included checkUnauthRequest(HEALTHCHECK_ENDPOINT, req -> req.get()); } - private void validateHealthCheckReport(final String name, final String url, final boolean healthy, final int code, + private void validateHealthCheckReport(final String url, final boolean healthy, final int code, final String message, final HealthCheckReport report) { - assertEquals(name, report.getName()); + assertThat(report.getName()).isNotBlank(); assertEquals(url, report.getUrl()); assertEquals(healthy, report.isHealthy()); assertEquals(code, report.getCode()); 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()); } } |