Add junit coverage to TimedOutException class
[appc.git] / appc-dg / appc-dg-shared / appc-dg-dependency-model / src / main / java / org / onap / appc / dg / dependencymanager / helper / DependencyModelParser.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.appc.dg.dependencymanager.helper;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.fasterxml.jackson.databind.JsonNode;
30 import com.fasterxml.jackson.databind.ObjectMapper;
31 import com.fasterxml.jackson.databind.node.ObjectNode;
32 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
33 import java.io.IOException;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.Map;
39 import java.util.Set;
40 import org.apache.commons.lang3.StringUtils;
41 import org.onap.appc.dg.flowbuilder.exception.InvalidDependencyModelException;
42 import org.onap.appc.dg.objects.Node;
43 import org.onap.appc.dg.objects.VnfcDependencyModel;
44 import org.onap.appc.domainmodel.Vnfc;
45
46 public class DependencyModelParser {
47
48     private final EELFLogger logger = EELFManager.getInstance().getLogger(DependencyModelParser.class);
49
50     private static final String PROPERTIES = "properties";
51     private static final String ACTIVE_ACTIVE = "Active-Active";
52     private static final String ACTIVE_PASSIVE = "Active-Passive";
53     private static final String HIGH_AVAILABLITY = "high_availablity";
54     private static final String MANDATORY = "mandatory";
55     private static final String TOPOLOGY_TEMPLATE = "topology_template";
56     private static final String RELATIONSHIP = "relationship";
57
58     private static Map<String, String> dependencyMap;
59
60     static {
61         Map<String, String> dependencyTypeMappingMap = new HashMap<>();
62         dependencyTypeMappingMap.put("geo-activeactive", ACTIVE_ACTIVE);
63         dependencyTypeMappingMap.put("geo-activestandby", ACTIVE_PASSIVE);
64         dependencyTypeMappingMap.put("local-activeactive", ACTIVE_ACTIVE);
65         dependencyTypeMappingMap.put("local-activestandby", ACTIVE_PASSIVE);
66         dependencyMap = Collections.unmodifiableMap(dependencyTypeMappingMap);
67     }
68
69     public VnfcDependencyModel generateDependencyModel(String vnfModel, String vnfType)
70         throws InvalidDependencyModelException {
71         Set<Node<Vnfc>> dependencies = new HashSet<>();
72         ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
73         boolean mandatory;
74         String resilienceType;
75         String prefix = "org.onap.resource.vfc." + vnfType + ".abstract.nodes.";
76         try {
77             ObjectNode root = (ObjectNode) mapper.readTree(vnfModel);
78
79             if (root.get(TOPOLOGY_TEMPLATE) == null || root.get(TOPOLOGY_TEMPLATE).get("node_templates") == null) {
80                 throw new InvalidDependencyModelException(
81                     "Dependency model is missing 'topology_template' or  'node_templates' elements");
82             }
83
84             JsonNode topologyTemplateNode = root.get(TOPOLOGY_TEMPLATE);
85             JsonNode nodeTemplateNode = topologyTemplateNode.get("node_templates");
86             Iterator<Map.Entry<String, JsonNode>> itretor = nodeTemplateNode.fields();
87             for (JsonNode yamlNode : nodeTemplateNode) {
88                 logger.debug("Processing node: " + yamlNode);
89                 String fullvnfcType = itretor.next().getValue().get("type").textValue();
90                 String vnfcType = getQualifiedVnfcType(fullvnfcType);
91                 String type = yamlNode.get("type").textValue();
92                 type = type.substring(0, type.lastIndexOf('.') + 1);
93                 if (type.concat(vnfcType).toLowerCase().startsWith(prefix.concat(vnfcType).toLowerCase())) {
94
95                     resilienceType = resolveResilienceType(yamlNode);
96                     mandatory = resolveMandatory(yamlNode);
97                     String[] parentList = getDependencyArray(yamlNode, nodeTemplateNode);
98                     Node<Vnfc> vnfcNode = getNode(dependencies, vnfcType);
99
100                     if (vnfcNode != null) {
101                         logger.debug("Dependency node already exists for vnfc Type: " + vnfcType);
102                         if (StringUtils.isEmpty(vnfcNode.getChild().getResilienceType())) {
103                             logger.debug("Updating resilience type, "
104                                 + "dependencies and mandatory attribute for VNFC type: " + vnfcType);
105                             vnfcNode.getChild().setResilienceType(resilienceType);
106                             tryFillNode(dependencies, parentList, vnfcNode);
107                             vnfcNode.getChild().setMandatory(mandatory);
108                         }
109                     } else {
110                         logger.debug("Creating dependency node for  : " + vnfcType);
111                         vnfcNode = new Node<>(createVnfc(mandatory, resilienceType, vnfcType));
112                         tryFillNode(dependencies, parentList, vnfcNode);
113                         logger.debug("Adding VNFC to dependency model : " + vnfcNode);
114                         dependencies.add(vnfcNode);
115                     }
116                 }
117             }
118         } catch (IOException e) {
119             logger.error("Error parsing dependency model : " + vnfModel);
120             logger.error("Error message : " + e);
121             throw new InvalidDependencyModelException("Error parsing dependency model. " + e.getMessage());
122         }
123         return new VnfcDependencyModel(dependencies);
124     }
125
126     private void tryFillNode(Set<Node<Vnfc>> dependencies, String[] parentList, Node<Vnfc> vnfcNode) {
127         if (parentList.length > 0) {
128             fillNode(dependencies, vnfcNode, parentList);
129         }
130     }
131
132     private boolean resolveMandatory(JsonNode yamlNode) {
133         return !mandatoryDoesNotExist(yamlNode) && yamlNode.get(PROPERTIES).findValue(MANDATORY).booleanValue();
134     }
135
136     private boolean mandatoryDoesNotExist(JsonNode yamlNode) {
137         return yamlNode.get(PROPERTIES).findValue(MANDATORY) == null ||
138             yamlNode.get(PROPERTIES).findValue(MANDATORY).asText().isEmpty();
139     }
140
141     private String resolveResilienceType(JsonNode yamlNode) {
142         String resilienceType;
143         if (yamlNode.get(PROPERTIES).findValue(HIGH_AVAILABLITY) == null ||
144             yamlNode.get(PROPERTIES).findValue(HIGH_AVAILABLITY).asText().isEmpty()) {
145
146             resilienceType = ACTIVE_ACTIVE;
147         } else {
148             resilienceType = dependencyMap
149                 .get(yamlNode.get(PROPERTIES).findValue(HIGH_AVAILABLITY).textValue());
150         }
151         return resilienceType;
152     }
153
154     private Vnfc createVnfc(boolean mandatory, String resilienceType, String vnfcType) {
155         Vnfc vnfc = new Vnfc();
156         vnfc.setMandatory(mandatory);
157         vnfc.setResilienceType(resilienceType);
158         vnfc.setVnfcType(vnfcType);
159         return vnfc;
160     }
161
162     private String getQualifiedVnfcType(String fullvnfcType) {
163         return fullvnfcType.substring(fullvnfcType.lastIndexOf('.') + 1, fullvnfcType.length());
164     }
165
166     private void fillNode(Set<Node<Vnfc>> nodes, Node<Vnfc> node, String[] parentList) {
167         for (String type : parentList) {
168             String parentType = getVnfcType(type);
169             Node<Vnfc> parentNode = getNode(nodes, parentType);
170             if (parentNode != null) {
171                 logger.debug("VNFC already exists for VNFC type: " + parentType + ". Adding it to parent list ");
172                 node.addParent(parentNode.getChild());
173             } else {
174                 logger.debug("VNFC does not exist for VNFC type: " + parentType + ". Creating new VNFC ");
175                 parentNode = new Node<>(createVnfc(false, null, parentType));
176                 node.addParent(parentNode.getChild());
177                 logger.debug("Adding VNFC to dependency model : " + parentNode);
178                 nodes.add(parentNode);
179             }
180         }
181     }
182
183     private String[] getDependencyArray(JsonNode node, JsonNode nodeTemplateNode)
184         throws InvalidDependencyModelException {
185         JsonNode requirementsNode = node.get("requirements");
186         Set<String> dependencyList = new HashSet<>();
187         if (requirementsNode != null) {
188             for (JsonNode internalNode : requirementsNode) {
189                 //TODO : In this release we are supporting both relationship = tosca.capabilities.Node  and relationship =tosca.relationships.DependsOn we need to remove one of them in next release post confirming with SDC team
190                 if (verifyNode(internalNode)) {
191                     parseDependencyModel(node, nodeTemplateNode, dependencyList, internalNode);
192                 }
193             }
194             return dependencyList.toArray(new String[0]);
195         } else {
196             return new String[0];
197         }
198     }
199
200     private void parseDependencyModel(JsonNode node, JsonNode nodeTemplateNode, Set<String> dependencyList,
201         JsonNode internalNode) throws InvalidDependencyModelException {
202
203         if (internalNode.findValue("node") != null) {
204             String nodeName = internalNode.findValue("node").asText();
205             String fullVnfcName = nodeTemplateNode.get(nodeName).get("type").asText();
206             dependencyList.add(getQualifiedVnfcType(fullVnfcName));
207         } else {
208             throw new InvalidDependencyModelException(
209                 "Error parsing dependency model. " + "Dependent Node not found for " + node.get("type"));
210         }
211     }
212
213     private boolean verifyNode(JsonNode internalNode) {
214         return nodeNullCheck(internalNode) &&
215             "tosca.capabilities.Node".equalsIgnoreCase(internalNode.findValue("capability").asText()) &&
216             ("tosca.relationships.DependsOn".equalsIgnoreCase(internalNode.findValue(RELATIONSHIP).asText()) ||
217                 "tosca.capabilities.Node".equalsIgnoreCase(internalNode.findValue(RELATIONSHIP).asText()));
218     }
219
220     private boolean nodeNullCheck(JsonNode internalNode) {
221         return internalNode.get("dependency") != null && internalNode.findValue("capability") != null
222             && internalNode.findValue(RELATIONSHIP) != null;
223     }
224
225     private Node<Vnfc> getNode(Set<Node<Vnfc>> nodes, String vnfcType) {
226         Iterator<Node<Vnfc>> itr = nodes.iterator();
227         Node<Vnfc> node;
228         while (itr.hasNext()) {
229             node = itr.next();
230             if (node.getChild().getVnfcType().equalsIgnoreCase(vnfcType)) {
231                 return node;
232             }
233         }
234         return null;
235     }
236     private String getVnfcType(String type) {
237         return type.substring(type.lastIndexOf('.') + 1, type.length());
238     }
239 }