5e414b17598cd6ecf84d761af0bf039773e5009b
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.controlloop.participant.intermediary.handler;
22
23 import java.io.Closeable;
24 import java.util.Objects;
25 import lombok.Getter;
26 import lombok.Setter;
27 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant;
28 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantHealthStatus;
29 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantState;
30 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatistics;
31 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantHealthCheck;
32 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessage;
33 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseDetails;
34 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantResponseStatus;
35 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStateChange;
36 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.MessageSender;
37 import org.onap.policy.clamp.controlloop.participant.intermediary.comm.ParticipantStatusPublisher;
38 import org.onap.policy.clamp.controlloop.participant.intermediary.parameters.ParticipantIntermediaryParameters;
39 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * This class is responsible for managing the state of a participant.
45  */
46 @Getter
47 public class ParticipantHandler implements Closeable {
48     private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantHandler.class);
49
50     private final ToscaConceptIdentifier participantType;
51     private final ToscaConceptIdentifier participantId;
52     private final MessageSender sender;
53     private final ControlLoopHandler controlLoopHandler;
54     private final ParticipantStatistics participantStatistics;
55
56     @Setter
57     private ParticipantState state = ParticipantState.UNKNOWN;
58
59     @Setter
60     private ParticipantHealthStatus healthStatus = ParticipantHealthStatus.UNKNOWN;
61
62     /**
63      * Constructor, set the participant ID and sender.
64      *
65      * @param parameters the parameters of the participant
66      * @param publisher the publisher for sending responses to messages
67      */
68     public ParticipantHandler(ParticipantIntermediaryParameters parameters, ParticipantStatusPublisher publisher) {
69         this.participantType = parameters.getParticipantType();
70         this.participantId = parameters.getParticipantId();
71         this.sender = new MessageSender(this, publisher, parameters.getReportingTimeInterval());
72         this.controlLoopHandler = new ControlLoopHandler(parameters, sender);
73         this.participantStatistics = new ParticipantStatistics();
74     }
75
76     @Override
77     public void close() {
78         sender.close();
79         controlLoopHandler.close();
80     }
81
82     /**
83      * Method which handles a participant state change event from clamp.
84      *
85      * @param stateChangeMsg participant state change message
86      */
87     public void handleParticipantStateChange(final ParticipantStateChange stateChangeMsg) {
88
89         if (!stateChangeMsg.appliesTo(participantType, participantId)) {
90             return;
91         }
92
93         var response = new ParticipantResponseDetails(stateChangeMsg);
94
95         switch (stateChangeMsg.getState()) {
96             case PASSIVE:
97                 handlePassiveState(response);
98                 break;
99             case ACTIVE:
100                 handleActiveState(response);
101                 break;
102             case SAFE:
103                 handleSafeState(response);
104                 break;
105             case TEST:
106                 handleTestState(response);
107                 break;
108             case TERMINATED:
109                 handleTerminatedState(response);
110                 break;
111             default:
112                 LOGGER.debug("StateChange message has no state, state is null {}", stateChangeMsg.getParticipantId());
113                 response.setResponseStatus(ParticipantResponseStatus.FAIL);
114                 response.setResponseMessage(
115                         "StateChange message has invalid state for participantId " + stateChangeMsg.getParticipantId());
116                 break;
117         }
118
119         sender.sendResponse(response);
120     }
121
122     /**
123      * Method which handles a participant health check event from clamp.
124      *
125      * @param healthCheckMsg participant health check message
126      */
127     public void handleParticipantHealthCheck(final ParticipantHealthCheck healthCheckMsg) {
128         var response = new ParticipantResponseDetails(healthCheckMsg);
129         response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
130         response.setResponseMessage(healthStatus.toString());
131
132         sender.sendResponse(response);
133     }
134
135     /**
136      * Method to handle when the new state from participant is active.
137      *
138      * @param response participant response
139      */
140     private void handleActiveState(final ParticipantResponseDetails response) {
141         handleStateChange(ParticipantState.ACTIVE, response);
142     }
143
144     /**
145      * Method to handle when the new state from participant is passive.
146      *
147      * @param response participant response
148      */
149     private void handlePassiveState(final ParticipantResponseDetails response) {
150         handleStateChange(ParticipantState.PASSIVE, response);
151     }
152
153     /**
154      * Method to handle when the new state from participant is safe.
155      *
156      * @param response participant response
157      */
158     private void handleSafeState(final ParticipantResponseDetails response) {
159         handleStateChange(ParticipantState.SAFE, response);
160     }
161
162     /**
163      * Method to handle when the new state from participant is TEST.
164      *
165      * @param response participant response
166      */
167     private void handleTestState(final ParticipantResponseDetails response) {
168         handleStateChange(ParticipantState.TEST, response);
169     }
170
171     /**
172      * Method to handle when the new state from participant is Terminated.
173      *
174      * @param response participant response
175      */
176     private void handleTerminatedState(final ParticipantResponseDetails response) {
177         handleStateChange(ParticipantState.TERMINATED, response);
178     }
179
180     private void handleStateChange(ParticipantState newParticipantState, ParticipantResponseDetails response) {
181         if (state.equals(newParticipantState)) {
182             response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
183             response.setResponseMessage("Participant already in state " + newParticipantState);
184         } else {
185             response.setResponseStatus(ParticipantResponseStatus.SUCCESS);
186             response.setResponseMessage("Participant state changed from " + state + " to " + newParticipantState);
187             state = newParticipantState;
188         }
189     }
190
191     /**
192      * Method to update participant state.
193      *
194      * @param definition participant definition
195      * @param participantState participant state
196      * @return the participant
197      */
198     public Participant updateParticipantState(ToscaConceptIdentifier definition, ParticipantState participantState) {
199         if (!Objects.equals(definition, participantId)) {
200             LOGGER.debug("No participant with this ID {}", definition.getName());
201             return null;
202         }
203         var response = new ParticipantResponseDetails();
204         handleStateChange(participantState, response);
205         sender.sendResponse(response);
206         return getParticipant(definition.getName(), definition.getVersion());
207     }
208
209     /**
210      * Get participants as a {@link Participant} class.
211      *
212      * @param name the participant name to get
213      * @param version the version of the participant to get
214      * @return the participant
215      */
216     public Participant getParticipant(String name, String version) {
217         if (participantId.getName().equals(name)) {
218             var participant = new Participant();
219             participant.setDefinition(participantId);
220             participant.setParticipantState(state);
221             participant.setHealthStatus(healthStatus);
222             return participant;
223         }
224         return null;
225     }
226
227     /**
228      * Check if a participant message applies to this participant handler.
229      *
230      * @param partipantMsg the message to check
231      * @return true if it applies, false otherwise
232      */
233     public boolean canHandle(ParticipantMessage partipantMsg) {
234         return partipantMsg.appliesTo(participantType, participantId);
235     }
236 }