051270f6fbe03430ed01841dd2f2d5fe2d0a55e0
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.controlloop.common.rules.test;
22
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.util.LinkedList;
26 import java.util.List;
27 import java.util.function.Function;
28 import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
29 import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
30 import org.onap.policy.common.utils.coder.Coder;
31 import org.onap.policy.common.utils.coder.CoderException;
32 import org.onap.policy.common.utils.resources.ResourceUtils;
33 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
34 import org.onap.policy.drools.protocol.coders.EventProtocolCoderConstants;
35 import org.onap.policy.drools.system.PolicyController;
36
37 /**
38  * Mechanism by which junit tests can manage topic messages.
39  */
40 public class Topics {
41     /**
42      * Wherever this string appears within an input file, it is replaced by a value passed
43      * as a parameter to the {@link #inject(String, String, String)} method.
44      */
45     private static final String REPLACE_ME = "${replaceMe}";
46
47     /**
48      * Listeners that have been created and registered by "this" object.
49      */
50     private final List<Listener<?>> listeners = new LinkedList<>();
51
52     /**
53      * Unregisters all of the listeners.
54      */
55     public void destroy() {
56         listeners.forEach(Listener::unregister);
57     }
58
59     /**
60      * Injects the content of the given file onto a NOOP topic SOURCE.
61      *
62      * @param topicName topic on which to inject
63      * @param file file whose content is to be injected
64      */
65     public void inject(String topicName, String file) {
66         inject(topicName, file, REPLACE_ME);
67     }
68
69     /**
70      * Injects the content of the given file onto a NOOP topic SOURCE, with the given
71      * substitution.
72      *
73      * @param topicName topic on which to inject
74      * @param file file whose content is to be injected
75      * @param newText text to be substituted for occurrences of "${replaceMe}" in the
76      *        source file
77      */
78     public void inject(String topicName, String file, String newText) {
79         try {
80             var text = ResourceUtils.getResourceAsString(file);
81             if (text == null) {
82                 throw new FileNotFoundException(file);
83             }
84             text = text.replace(REPLACE_ME, newText);
85             getTopicManager().getNoopTopicSource(topicName).offer(text);
86         } catch (IOException e) {
87             throw new TopicException(e);
88         }
89     }
90
91     /**
92      * Creates a listener for messages published on a NOOP topic SINK. Messages are
93      * decoded using the coder associated with the controller.
94      *
95      * @param <T> message type
96      * @param topicName name of the topic on which to listen
97      * @param expectedClass type of message expected
98      * @param controller controller whose decoders are to be used
99      * @return a new listener
100      */
101     public <T> Listener<T> createListener(String topicName, Class<T> expectedClass, PolicyController controller) {
102         EventProtocolCoder mgr = getProtocolCoder();
103         String groupId = controller.getDrools().getGroupId();
104         String artifactId = controller.getDrools().getArtifactId();
105
106         // @formatter:off
107         return createListener(topicName,
108             event -> expectedClass.cast(mgr.decode(groupId, artifactId, topicName, event)));
109         // @formatter:on
110     }
111
112     /**
113      * Creates a listener for messages published on a NOOP topic SINK. Messages are
114      * decoded using the specified coder.
115      *
116      * @param <T> message type
117      * @param topicName name of the topic on which to listen
118      * @param expectedClass type of message expected
119      * @param coder coder to decode the messages
120      * @return a new listener
121      */
122     public <T> Listener<T> createListener(String topicName, Class<T> expectedClass, Coder coder) {
123         Function<String, T> decoder = event -> {
124             try {
125                 return coder.decode(event, expectedClass);
126             } catch (CoderException e) {
127                 throw new IllegalArgumentException("cannot decode message", e);
128             }
129         };
130
131         return createListener(topicName, decoder);
132     }
133
134     /**
135      * Creates a listener for messages published on a NOOP topic SINK. Messages are
136      * decoded using the specified decoder.
137      *
138      * @param <T> message type
139      * @param topicName name of the topic on which to listen
140      * @param decoder function that takes a message and decodes it into the desired type
141      * @return a new listener
142      */
143     public <T> Listener<T> createListener(String topicName, Function<String, T> decoder) {
144         Listener<T> listener = makeListener(topicName, decoder);
145         listeners.add(listener);
146
147         return listener;
148     }
149
150     // these methods may be overridden by junit tests
151
152     protected TopicEndpoint getTopicManager() {
153         return TopicEndpointManager.getManager();
154     }
155
156     protected EventProtocolCoder getProtocolCoder() {
157         return EventProtocolCoderConstants.getManager();
158     }
159
160     protected <T> Listener<T> makeListener(String topicName, Function<String, T> decoder) {
161         return new Listener<>(topicName, decoder) {
162             @Override
163             protected TopicEndpoint getTopicManager() {
164                 return Topics.this.getTopicManager();
165             }
166         };
167     }
168 }