Merge "Added tests for dcae dispacher services"
[clamp.git] / src / main / java / org / onap / clamp / clds / model / properties / ModelProperties.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
6  *                             reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  * ===================================================================
21  *
22  */
23
24 package org.onap.clamp.clds.model.properties;
25
26 import com.att.eelf.configuration.EELFLogger;
27 import com.att.eelf.configuration.EELFManager;
28 import com.fasterxml.jackson.databind.JsonNode;
29
30 import java.io.IOException;
31 import java.lang.reflect.InvocationTargetException;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.concurrent.ConcurrentHashMap;
37
38 import org.apache.camel.Exchange;
39 import org.onap.clamp.clds.client.req.policy.PolicyClient;
40 import org.onap.clamp.clds.config.ClampProperties;
41 import org.onap.clamp.clds.exception.ModelBpmnException;
42 import org.onap.clamp.clds.model.CldsEvent;
43 import org.onap.clamp.clds.model.CldsModel;
44 import org.onap.clamp.clds.service.CldsService;
45 import org.onap.clamp.clds.util.JacksonUtils;
46
47 /**
48  * Parse model properties.
49  */
50 public class ModelProperties {
51
52     protected static final EELFLogger logger = EELFManager.getInstance().getLogger(CldsService.class);
53     protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
54     private ModelBpmn modelBpmn;
55     private JsonNode modelJson;
56     private final String modelName;
57     private final String controlName;
58     private final String actionCd;
59     // Flag indicate whether it is triggered by Validation Test button from UI
60     private final boolean testOnly;
61     private Global global;
62     private final Map<String, AbstractModelElement> modelElements = new ConcurrentHashMap<>();
63     private String currentModelElementId;
64     private String policyUniqueId;
65     private String guardUniqueId;
66     public static final String POLICY_GUARD_SUFFIX = "_Guard_";
67     private static final Object lock = new Object();
68     private static Map<Class<? extends AbstractModelElement>, String> modelElementClasses = new ConcurrentHashMap<>();
69     static {
70         synchronized (lock) {
71             modelElementClasses.put(Policy.class, Policy.getType());
72             modelElementClasses.put(Tca.class, Tca.getType());
73             modelElementClasses.put(Holmes.class, Holmes.getType());
74         }
75     }
76
77     /**
78      * Retain data required to parse the ModelElement objects. (Rather than
79      * parse them all - parse them on demand if requested.)
80      *
81      * @param modelName
82      *            The model name coming form the UI
83      * @param controlName
84      *            The closed loop name coming from the UI
85      * @param actionCd
86      *            Type of operation PUT,UPDATE,DELETE
87      * @param isATest
88      *            The test flag coming from the UI (for validation only, no
89      *            query are physically executed)
90      * @param modelBpmnText
91      *            The BPMN flow in JSON from the UI
92      * @param modelPropText
93      *            The BPMN parameters for all boxes defined in modelBpmnTest
94      */
95     public ModelProperties(String modelName, String controlName, String actionCd, boolean isATest, String modelBpmnText,
96         String modelPropText) {
97         try {
98             this.modelName = modelName;
99             this.controlName = controlName;
100             this.actionCd = actionCd;
101             this.testOnly = isATest;
102             modelBpmn = ModelBpmn.create(modelBpmnText);
103             modelJson = JacksonUtils.getObjectMapperInstance().readTree(modelPropText);
104             instantiateMissingModelElements();
105         } catch (IOException e) {
106             throw new ModelBpmnException("Exception occurred when trying to decode the BPMN Properties JSON", e);
107         }
108     }
109
110     /**
111      * This method is meant to ensure that one ModelElement instance exists for
112      * each ModelElement class. As new ModelElement classes could have been
113      * registered after instantiation of this ModelProperties, we need to build
114      * the missing ModelElement instances.
115      */
116     private final void instantiateMissingModelElements() {
117         if (modelElementClasses.size() != modelElements.size()) {
118             Set<String> missingTypes = new HashSet<>(modelElementClasses.values());
119             missingTypes.removeAll(modelElements.keySet());
120             // Parse the list of base Model Elements and build up the
121             // ModelElements
122             modelElementClasses.entrySet().stream().parallel()
123             .filter(entry -> (AbstractModelElement.class.isAssignableFrom(entry.getKey())
124                 && missingTypes.contains(entry.getValue())))
125             .forEach(entry -> {
126                 try {
127                     modelElements.put(entry.getValue(),
128                         (entry.getKey()
129                             .getConstructor(ModelProperties.class, ModelBpmn.class, JsonNode.class)
130                             .newInstance(this, modelBpmn, modelJson)));
131                 } catch (InstantiationException | NoSuchMethodException | IllegalAccessException
132                     | InvocationTargetException e) {
133                     logger.warn("Unable to instantiate a ModelElement, exception follows: ", e);
134                 }
135             });
136         }
137     }
138
139     /**
140      * Get the VF for a model. If return null if there is no VF.
141      *
142      * @param model
143      * @return
144      */
145     public static String getVf(CldsModel model) {
146         List<String> vfs = null;
147         try {
148             JsonNode modelJson = JacksonUtils.getObjectMapperInstance().readTree(model.getPropText());
149             Global global = new Global(modelJson);
150             vfs = global.getResourceVf();
151         } catch (IOException e) {
152             logger.warn("no VF found", e);
153         }
154         String vf = null;
155         if (vfs != null && !vfs.isEmpty()) {
156             vf = vfs.get(0);
157         }
158         return vf;
159     }
160
161     /**
162      * Create ModelProperties extracted from a CamelExchange.
163      *
164      * @param camelExchange
165      *            The camel Exchange object that contains all info provided to
166      *            the flow
167      * @return A model Properties created from the parameters found in
168      *         camelExchange object
169      */
170     public static ModelProperties create(Exchange camelExchange) {
171         String modelProp = (String) camelExchange.getProperty("modelProp");
172         String modelBpmnProp = (String) camelExchange.getProperty("modelBpmnProp");
173         String modelName = (String) camelExchange.getProperty("modelName");
174         String controlName = (String) camelExchange.getProperty("controlName");
175         String actionCd = (String) camelExchange.getProperty("actionCd");
176         boolean isTest = (boolean) camelExchange.getProperty("isTest");
177         return new ModelProperties(modelName, controlName, actionCd, isTest, modelBpmnProp, modelProp);
178     }
179
180     /**
181      * return appropriate model element given the type
182      *
183      * @param type
184      * @return
185      */
186     public AbstractModelElement getModelElementByType(String type) {
187         AbstractModelElement modelElement = modelElements.get(type);
188         if (modelElement == null) {
189             throw new IllegalArgumentException("Invalid or not found ModelElement type: " + type);
190         }
191         return modelElement;
192     }
193
194     /**
195      * @return the modelName
196      */
197     public String getModelName() {
198         return modelName;
199     }
200
201     /**
202      * @return the controlName
203      */
204     public String getControlName() {
205         return controlName;
206     }
207
208     /**
209      * @return the controlNameAndPolicyUniqueId
210      */
211     public String getControlNameAndPolicyUniqueId() {
212         return controlName + "_" + policyUniqueId;
213     }
214
215     /**
216      * @return the currentPolicyName
217      */
218     private String getCurrentPolicyName() {
219         return normalizePolicyScopeName(controlName + "_" + currentModelElementId);
220     }
221
222     private String createScopeSeparator(String policyScope) {
223         return policyScope.contains(".") ? "" : ".";
224     }
225
226     /**
227      * @return the currentPolicyScopeAndPolicyName
228      */
229     public String getCurrentPolicyScopeAndPolicyName() {
230         return normalizePolicyScopeName(modelName + createScopeSeparator(modelName) + getCurrentPolicyName());
231     }
232
233     /**
234      * @return The policyName that wil be used in input parameters of DCAE
235      *         deploy
236      */
237     public String getPolicyNameForDcaeDeploy(ClampProperties refProp) {
238         return normalizePolicyScopeName(modelName + createScopeSeparator(modelName)
239         + refProp.getStringValue(PolicyClient.POLICY_MS_NAME_PREFIX_PROPERTY_NAME) + getCurrentPolicyName());
240     }
241
242     /**
243      * @return the policyScopeAndNameWithUniqueId
244      */
245     public String getPolicyScopeAndNameWithUniqueId() {
246         return normalizePolicyScopeName(
247             modelName + createScopeSeparator(modelName) + getCurrentPolicyName() + "_" + policyUniqueId);
248     }
249
250     /**
251      * @return the policyScopeAndNameWithUniqueId
252      */
253     public String getPolicyScopeAndNameWithUniqueGuardId() {
254         return normalizePolicyScopeName(
255             modelName + createScopeSeparator(modelName) + getCurrentPolicyName() + "_" + policyUniqueId+POLICY_GUARD_SUFFIX+guardUniqueId);
256     }
257
258     /**
259      * @return the currentPolicyScopeAndFullPolicyName
260      */
261     public String getCurrentPolicyScopeAndFullPolicyName(String policyNamePrefix) {
262         return normalizePolicyScopeName(
263             modelName + createScopeSeparator(modelName) + policyNamePrefix + getCurrentPolicyName());
264     }
265
266     /**
267      * Replace all '-' with '_' within policy scope and name.
268      *
269      * @param inName
270      * @return
271      */
272     private String normalizePolicyScopeName(String inName) {
273         return inName.replaceAll("-", "_");
274     }
275
276     /**
277      * @return the currentModelElementId
278      */
279     public String getCurrentModelElementId() {
280         return currentModelElementId;
281     }
282
283     /**
284      * When generating a policy request for a model element, must set the id of
285      * that model element using this method. Used to generate the policy name.
286      *
287      * @param currentModelElementId
288      *            the currentModelElementId to set
289      */
290     public void setCurrentModelElementId(String currentModelElementId) {
291         this.currentModelElementId = currentModelElementId;
292     }
293
294     /**
295      * @return the policyUniqueId
296      */
297     public String getPolicyUniqueId() {
298         return policyUniqueId;
299     }
300
301     public String getGuardUniqueId() {
302         return guardUniqueId;
303     }
304
305     public void setGuardUniqueId(String guardUniqueId) {
306         this.guardUniqueId = guardUniqueId;
307     }
308
309     /**
310      * When generating a policy request for a model element, must set the unique
311      * id of that policy using this method. Used to generate the policy name.
312      *
313      * @param policyUniqueId
314      *            the policyUniqueId to set
315      */
316     public void setPolicyUniqueId(String policyUniqueId) {
317         this.policyUniqueId = policyUniqueId;
318     }
319
320     /**
321      * @return the actionCd
322      */
323     public String getActionCd() {
324         return actionCd;
325     }
326
327     /**
328      * @return the testOnly
329      */
330     public boolean isTestOnly() {
331         return testOnly;
332     }
333
334     /**
335      * @return the isCreateRequest
336      */
337     public boolean isCreateRequest() {
338         switch (actionCd) {
339         case CldsEvent.ACTION_SUBMIT:
340         case CldsEvent.ACTION_RESTART:
341             return true;
342         }
343         return false;
344     }
345
346     public boolean isStopRequest() {
347         switch (actionCd) {
348         case CldsEvent.ACTION_STOP:
349             return true;
350         }
351         return false;
352     }
353
354     /**
355      * @return the global
356      */
357     public Global getGlobal() {
358         if (global == null) {
359             global = new Global(modelJson);
360         }
361         return global;
362     }
363
364     public static final synchronized void registerModelElement(Class<? extends AbstractModelElement> modelElementClass,
365         String type) {
366         if (!modelElementClasses.containsKey(modelElementClass.getClass())) {
367             modelElementClasses.put(modelElementClass, type);
368         }
369     }
370
371     public <T extends AbstractModelElement> T getType(Class<T> clazz) {
372         instantiateMissingModelElements();
373         String type = modelElementClasses.get(clazz);
374         return (type != null ? (T) modelElements.get(type) : null);
375     }
376 }