40de843eae767abde10027c8edf2f8fdfe14cb1d
[policy/apex-pdp.git] / core / core-engine / src / main / java / org / onap / policy / apex / core / engine / executor / StateOutput.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2019 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.core.engine.executor;
23
24 import java.util.Map;
25 import java.util.Map.Entry;
26
27 import org.onap.policy.apex.core.engine.event.EnEvent;
28 import org.onap.policy.apex.core.engine.executor.exception.StateMachineException;
29 import org.onap.policy.apex.model.basicmodel.concepts.AxReferenceKey;
30 import org.onap.policy.apex.model.basicmodel.service.ModelService;
31 import org.onap.policy.apex.model.eventmodel.concepts.AxEvent;
32 import org.onap.policy.apex.model.eventmodel.concepts.AxEvents;
33 import org.onap.policy.apex.model.eventmodel.concepts.AxField;
34 import org.onap.policy.apex.model.policymodel.concepts.AxStateOutput;
35 import org.onap.policy.common.utils.validation.Assertions;
36
37 /**
38  * This class is the output of a state, and is used by the engine to decide what the next state for execution is.
39  *
40  * @author Liam Fallon (liam.fallon@ericsson.com)
41  */
42 public class StateOutput {
43     // The state output has a state and an event
44     private final AxStateOutput stateOutputDefinition;
45     private final AxEvent outputEventDef;
46     private final EnEvent outputEvent;
47
48     /**
49      * Create a new state output from a state output definition.
50      *
51      * @param axStateOutput the state output definition
52      */
53     public StateOutput(final AxStateOutput axStateOutput) {
54         this(axStateOutput, new EnEvent(axStateOutput.getOutgingEvent()));
55     }
56
57     /**
58      * Create a new state output with the given definition and event key.
59      *
60      * @param stateOutputDefinition the state output definition
61      * @param outputEvent the output event
62      */
63     public StateOutput(final AxStateOutput stateOutputDefinition, final EnEvent outputEvent) {
64         Assertions.argumentNotNull(stateOutputDefinition, "stateOutputDefinition may not be null");
65         Assertions.argumentNotNull(outputEvent, "outputEvent may not be null");
66
67         this.stateOutputDefinition = stateOutputDefinition;
68         this.outputEvent = outputEvent;
69         outputEventDef = ModelService.getModel(AxEvents.class).get(stateOutputDefinition.getOutgingEvent());
70     }
71
72     /**
73      * Gets the next state.
74      *
75      * @return the next state
76      */
77     public AxReferenceKey getNextState() {
78         return stateOutputDefinition.getNextState();
79     }
80
81     /**
82      * Gets the state output definition.
83      *
84      * @return the state output definition
85      */
86     public AxStateOutput getStateOutputDefinition() {
87         return stateOutputDefinition;
88     }
89
90     /**
91      * Gets the output event.
92      *
93      * @return the output event
94      */
95     public EnEvent getOutputEvent() {
96         return outputEvent;
97     }
98
99     /**
100      * Transfer the fields from the incoming field map into the event.
101      *
102      * @param incomingFieldDefinitionMap definitions of the incoming fields
103      * @param eventFieldMap the event field map
104      * @throws StateMachineException on errors populating the event fields
105      */
106     public void setEventFields(final Map<String, AxField> incomingFieldDefinitionMap,
107                     final Map<String, Object> eventFieldMap) throws StateMachineException {
108         Assertions.argumentNotNull(incomingFieldDefinitionMap, "incomingFieldDefinitionMap may not be null");
109         Assertions.argumentNotNull(eventFieldMap, "eventFieldMap may not be null");
110
111         if (!incomingFieldDefinitionMap.keySet().equals(eventFieldMap.keySet())) {
112             throw new StateMachineException(
113                             "field definitions and values do not match for event " + outputEventDef.getId() + '\n'
114                                             + incomingFieldDefinitionMap.keySet() + '\n' + eventFieldMap.keySet());
115         }
116         for (final Entry<String, Object> incomingFieldEntry : eventFieldMap.entrySet()) {
117             final String fieldName = incomingFieldEntry.getKey();
118             final AxField fieldDef = incomingFieldDefinitionMap.get(fieldName);
119
120             // Check if this field is a field in the event
121             if (!outputEventDef.getFields().contains(fieldDef)) {
122                 throw new StateMachineException("field \"" + fieldName + "\" does not exist on event \""
123                                 + outputEventDef.getId() + "\"");
124             }
125
126             // Set the value in the output event
127             outputEvent.put(fieldName, incomingFieldEntry.getValue());
128         }
129     }
130
131     /**
132      * This method copies any fields that exist on the input event that also exist on the output event if they are not
133      * set on the output event.
134      *
135      * @param incomingEvent The incoming event to copy from
136      */
137     public void copyUnsetFields(final EnEvent incomingEvent) {
138         Assertions.argumentNotNull(incomingEvent, "incomingEvent may not be null");
139
140         for (final Entry<String, Object> incomingField : incomingEvent.entrySet()) {
141             final String fieldName = incomingField.getKey();
142
143             // Check if the field exists on the outgoing event
144             if ((!outputEventDef.getParameterMap().containsKey(fieldName))
145
146                             // Check if the field is set on the outgoing event
147                             || (outputEvent.containsKey(fieldName))
148
149                             // Now, check the fields have the same type
150                             || (!incomingEvent.getAxEvent().getParameterMap().get(fieldName)
151                                             .equals(outputEvent.getAxEvent().getParameterMap().get(fieldName)))) {
152                 continue;
153             }
154
155             // All checks done, we can copy the value
156             outputEvent.put(fieldName, incomingField.getValue());
157         }
158
159     }
160 }