2 * ============LICENSE_START=======================================================
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.onap.sdnc.config.params.transformer.tosca;
27 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.io.OutputStreamWriter;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.LinkedList;
35 import java.util.List;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
39 import org.apache.commons.lang.StringUtils;
40 import org.onap.sdnc.config.params.data.Parameter;
41 import org.onap.sdnc.config.params.data.PropertyDefinition;
42 import org.onap.sdnc.config.params.data.RequestKey;
43 import org.onap.sdnc.config.params.data.ResponseKey;
44 import org.onap.sdnc.config.params.transformer.tosca.exceptions.ArtifactProcessorException;
45 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
46 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
47 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
48 import org.openecomp.sdc.tosca.datatypes.model.TopologyTemplate;
49 import org.openecomp.sdc.tosca.services.YamlUtil;
51 import com.att.eelf.configuration.EELFLogger;
52 import com.att.eelf.configuration.EELFManager;
53 import com.fasterxml.jackson.core.JsonProcessingException;
54 import com.fasterxml.jackson.databind.ObjectMapper;
55 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
57 public class ArtifactProcessorImpl implements ArtifactProcessor {
58 private static final String DERIVEDFROM = "org.openecomp.genericvnf";
59 private static final EELFLogger Log =
60 EELFManager.getInstance().getLogger(ArtifactProcessorImpl.class);
61 private static final String EQUALSENCODING = "=";
62 private static final String COLONENCODING = ":";
63 private static final String COMMAENCODING = ",";
64 private static final String GREATERTHANENCODING = ">";
65 private static final String LESSTHANENCODING = "<";
68 public void generateArtifact(PropertyDefinition artifact, OutputStream stream)
69 throws ArtifactProcessorException {
71 MDC.put(MDC_SERVICE_NAME, "ArtifactGenerator");
72 Log.info("Entered into generateArtifact");
73 if (!StringUtils.isBlank(artifact.getKind())) {
74 logArtifact(artifact);
75 ServiceTemplate serviceTemplate = new ServiceTemplate();
77 addNodeType(artifact, serviceTemplate);
79 TopologyTemplate topologyTemplate = new TopologyTemplate();
80 serviceTemplate.setTopology_template(topologyTemplate);
81 addNodeTemplate(artifact, serviceTemplate);
83 String tosca = new YamlUtil().objectToYaml(serviceTemplate);
84 OutputStreamWriter writer = new OutputStreamWriter(stream);
88 } catch (IOException e) {
89 Log.error("Error writing to outputstream", e);
90 throw new ArtifactProcessorException(e);
94 } catch (IOException e) {
95 Log.error("Error while closing outputstream writer", e);
100 Log.error("Kind in PropertyDefinition is blank or null");
101 throw new ArtifactProcessorException("Kind in PropertyDefinition is blank or null");
106 public void generateArtifact(String artifact, OutputStream stream)
107 throws ArtifactProcessorException {
108 ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
110 PropertyDefinition pd = mapper.readValue(artifact, PropertyDefinition.class);
111 generateArtifact(pd, stream);
112 } catch (IOException e) {
113 Log.error("Error parsing property definition content = " + artifact, e);
114 throw new ArtifactProcessorException(e);
119 public PropertyDefinition readArtifact(String toscaArtifact) throws ArtifactProcessorException {
120 Log.info("Entered into readArtifact.");
121 Log.info("Received ToscaArtifact:\n" + toscaArtifact);
123 PropertyDefinition propertyDefinitionObj = new PropertyDefinition();
124 ServiceTemplate serviceTemplate =
125 new YamlUtil().yamlToObject(toscaArtifact, ServiceTemplate.class);
127 // mapping parameters
128 Map<String, NodeType> nodeTypeMap = serviceTemplate.getNode_types();
129 Map<String, NodeTemplate> nodeTemplateMap =
130 serviceTemplate.getTopology_template().getNode_templates();
132 String nodeTemplateName = nodeTemplateMap.keySet().toArray(new String[0])[0];
133 NodeTemplate nodeTemplate = nodeTemplateMap.get(nodeTemplateName);
134 Map<String, Object> nodeTemplateProperties = nodeTemplate.getProperties();
136 String kind = nodeTypeMap.keySet().toArray(new String[0])[0];
137 NodeType nodeType = nodeTypeMap.get(kind);
138 String version = nodeType.getVersion();
139 Log.info("ReadArtifact for " + kind + " with version " + version);
140 propertyDefinitionObj.setKind(kind);
141 propertyDefinitionObj.setVersion(version);
143 List<Parameter> parameterList = new LinkedList<>();
145 Map<String, org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition> propertyDefinitionFromTOSCA =
146 nodeType.getProperties();
147 if (null != propertyDefinitionFromTOSCA) {
148 for (String propertyName : propertyDefinitionFromTOSCA.keySet()) {
149 org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition propertyDefinition =
150 propertyDefinitionFromTOSCA.get(propertyName);
152 Parameter parameter = new Parameter();
153 parameter.setName(propertyName);
155 if (propertyDefinition.get_default() != null) {
156 parameter.setDefaultValue(propertyDefinition.get_default().toString());
158 parameter.setDescription(propertyDefinition.getDescription());
159 if (null != propertyDefinition.getRequired()) {
160 parameter.setRequired(propertyDefinition.getRequired());
162 parameter.setRequired(false);
165 if (StringUtils.isNotEmpty(propertyDefinition.getType())) {
166 parameter.setType(propertyDefinition.getType());
169 String propertValueExpr = (String) nodeTemplateProperties.get(propertyName);
170 String[] stringTokens = parsePropertyValueExpression(propertValueExpr);
171 String ruleType = stringTokens[0]
172 .substring(stringTokens[0].indexOf('=') + 1, stringTokens[0].length())
173 .replaceAll(">", "").trim();
174 String responseExpression = stringTokens[1]
175 .substring(stringTokens[1].indexOf('=') + 1, stringTokens[1].length());
176 String source = stringTokens[2]
177 .substring(stringTokens[2].indexOf('=') + 1, stringTokens[2].length())
178 .replaceAll(">", "").trim();
179 String requestExpression = stringTokens[3]
180 .substring(stringTokens[3].indexOf('=') + 1, stringTokens[3].length());
182 List<RequestKey> requestKeys = readRequestKeys(requestExpression);
183 List<ResponseKey> responseKeys = readResponseKeys(responseExpression);
185 parameter.setRuleType(ruleType);
186 parameter.setSource(source);
187 parameter.setRequestKeys(requestKeys);
188 parameter.setResponseKeys(responseKeys);
190 parameterList.add(parameter);
194 propertyDefinitionObj.setParameters(parameterList);
195 Log.info("Exiting from readArtifact. ");
196 return propertyDefinitionObj;
199 private List<ResponseKey> readResponseKeys(String responseExpression)
200 throws ArtifactProcessorException {
201 Log.info("Entered into readResponseKeys.");
202 List<ResponseKey> responseKeyList = null;
204 expression = responseExpression.replaceAll("<", "").replaceAll(">", "").trim();
205 if (StringUtils.isNotEmpty(expression)) {
206 responseKeyList = new ArrayList<>();
208 String[] responseKeys = expression.split(",");
209 for (String responseKeyStr : responseKeys) {
210 ResponseKey responseKey = new ResponseKey();
212 responseKey.setUniqueKeyName(responseKeyStr.split(":")[0]
213 .replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">")
214 .replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",")
215 .replaceAll(EQUALSENCODING, "=").trim());
216 responseKey.setUniqueKeyValue(responseKeyStr.split(":")[1]
217 .replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">")
218 .replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",")
219 .replaceAll(EQUALSENCODING, "=").trim());
220 responseKey.setFieldKeyName(responseKeyStr.split(":")[2]
221 .replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">")
222 .replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",")
223 .replaceAll(EQUALSENCODING, "=").trim());
224 } catch (ArrayIndexOutOfBoundsException e) {
226 "Invalid response attribute found :" + responseKeyStr + "due to " + e);
227 throw new ArtifactProcessorException(
228 "Invalid response attribute found :" + responseKeyStr);
230 responseKeyList.add(responseKey);
233 Log.info("Exiting from readResponseKeys.");
234 return responseKeyList;
237 private List<RequestKey> readRequestKeys(String requestExpression) {
238 Log.info("Entered into readRequestKeys.");
239 List<RequestKey> requestKeyList = null;
241 expression = requestExpression.replaceAll("<", "").replaceAll(">", "").trim();
242 if (StringUtils.isNotEmpty(expression)) {
243 requestKeyList = new ArrayList<>();
244 String[] requestKeys = expression.split(",");
245 for (String responseKeyStr : requestKeys) {
246 RequestKey requestKey = new RequestKey();
247 requestKey.setKeyName(responseKeyStr.split(":")[0].replaceAll(LESSTHANENCODING, "<")
248 .replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING, ":")
249 .replaceAll(COMMAENCODING, ",").replaceAll(EQUALSENCODING, "=").trim());
250 requestKey.setKeyValue(responseKeyStr.split(":")[1]
251 .replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">")
252 .replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",")
253 .replaceAll(EQUALSENCODING, "=").trim());
254 requestKeyList.add(requestKey);
257 Log.info("Exiting from readRequestKeys.");
258 return requestKeyList;
261 private String[] parsePropertyValueExpression(String propertValueExpr)
262 throws ArtifactProcessorException {
263 Log.info("Entered into parsePropertyValueExpression.");
264 String nodeRegex = "<(.*?)>";
265 Pattern pattern = Pattern.compile(nodeRegex, Pattern.CASE_INSENSITIVE);
266 Matcher matcher = pattern.matcher(propertValueExpr);
267 List<String> stringTokens = new ArrayList<>();
268 while (matcher.find()) {
269 stringTokens.add(matcher.group(0));
271 String[] propertiesArr = new String[stringTokens.size()];
272 propertiesArr = stringTokens.toArray(propertiesArr);
273 if (propertiesArr.length != 4) {
274 throw new ArtifactProcessorException("Invalid input found " + propertValueExpr);
276 Log.info("Exiting from parsePropertyValueExpression.");
277 return propertiesArr;
280 private void addNodeType(PropertyDefinition artifact, ServiceTemplate toscaTemplate)
281 throws ArtifactProcessorException {
282 // Add basic fields for the node
283 NodeType toscaNodeType = new NodeType();
284 toscaNodeType.setDerived_from(DERIVEDFROM);
285 toscaNodeType.setVersion(artifact.getVersion());
286 toscaNodeType.setDescription("");
287 if (artifact.getParameters() != null) {
288 Map<String, org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition> toscaPropertyMap =
290 toscaNodeType.setProperties(toscaPropertyMap);
292 // Add properties from parameters of PD
293 for (Parameter pdParameter : artifact.getParameters()) {
294 addProperty(toscaNodeType, pdParameter);
298 // This is where it adds node in node Map and adds the map in tosca template
299 Map<String, NodeType> toscaNodeMap = new HashMap<>();
300 toscaNodeMap.put(artifact.getKind(), toscaNodeType);
301 toscaTemplate.setNode_types(toscaNodeMap);
304 private void addProperty(NodeType toscaNodeType, Parameter pdParameter)
305 throws ArtifactProcessorException {
306 if (!StringUtils.isBlank(pdParameter.getName())
307 && !pdParameter.getName().matches(".*\\s+.*")) {
308 Log.info("Adding parameter " + pdParameter.getName() + " in node type");
309 org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition toscaProperty =
310 new org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition();
312 toscaProperty.setType(
313 StringUtils.isBlank(pdParameter.getType()) ? "string" : pdParameter.getType());
314 toscaProperty.set_default(pdParameter.getDefaultValue());
316 toscaProperty.setDescription(pdParameter.getDescription());
317 toscaProperty.setRequired(pdParameter.isRequired());
319 toscaNodeType.getProperties().put(pdParameter.getName(), toscaProperty);
321 String message = "Parameter name is empty,null or contains whitespace";
323 throw new ArtifactProcessorException(message);
327 private void addNodeTemplate(PropertyDefinition artifact, ServiceTemplate toscaTemplate) {
328 NodeTemplate nodeTemplate = new NodeTemplate();
329 nodeTemplate.setType(artifact.getKind());
330 Map<String, Object> templateProperties = new HashMap<>();
331 // Add properties from parameters of PD
332 if (artifact.getParameters() != null) {
333 for (Parameter pdParameter : artifact.getParameters()) {
334 addTemplateProperty(templateProperties, pdParameter);
336 nodeTemplate.setProperties(templateProperties);
338 Map<String, NodeTemplate> nodeTemplateMap = new HashMap<>();
339 nodeTemplateMap.put(artifact.getKind() + "_Template", nodeTemplate);
340 toscaTemplate.getTopology_template().setNode_templates(nodeTemplateMap);
343 private void addTemplateProperty(Map<String, Object> templateProperties,
344 Parameter pdParameter) {
345 Log.info("Adding parameter " + pdParameter.getName() + " in node templates");
346 String responseKeys = buildResponseKeyExpression(pdParameter.getResponseKeys());
347 String requestKeys = buildRequestKeyExpression(pdParameter.getRequestKeys());
348 String ruleType = buildRuleType(pdParameter.getRuleType());
349 String source = buildSourceSystem(pdParameter.getSource());
350 String properties = ruleType + " " + responseKeys + " " + source + " " + requestKeys;
351 templateProperties.put(pdParameter.getName(), properties);
354 protected String buildResponseKeyExpression(List<ResponseKey> responseKeys) {
355 StringBuilder propertyBuilder = new StringBuilder();
356 propertyBuilder.append("<response-keys = ");
357 if (responseKeys != null) {
358 Iterator<ResponseKey> itr = responseKeys.iterator();
359 while (itr.hasNext()) {
360 ResponseKey res = itr.next();
362 propertyBuilder.append(
363 encode(res.getUniqueKeyName()) + ":" + encode(res.getUniqueKeyValue())
364 + ":" + encode(res.getFieldKeyName()));
366 propertyBuilder.append(" , ");
369 propertyBuilder.append(">");
370 return propertyBuilder.toString();
373 protected String buildRequestKeyExpression(List<RequestKey> requestKeys) {
374 StringBuilder propertyBuilder = new StringBuilder();
375 propertyBuilder.append("<request-keys = ");
376 if (requestKeys != null) {
377 Iterator<RequestKey> itr = requestKeys.iterator();
378 while (itr.hasNext()) {
379 RequestKey res = itr.next();
382 .append(encode(res.getKeyName()) + ":" + encode(res.getKeyValue()));
384 propertyBuilder.append(" , ");
387 propertyBuilder.append(">");
388 return propertyBuilder.toString();
391 protected String buildRuleType(String classType) {
392 StringBuilder propertyBuilder = new StringBuilder();
393 String encodedClassType = StringUtils.isBlank(encode(classType)) ? "" : encode(classType);
394 propertyBuilder.append("<");
395 propertyBuilder.append("rule-type = " + encodedClassType);
396 propertyBuilder.append(">");
397 return propertyBuilder.toString();
400 protected String buildSourceSystem(String source) {
401 StringBuilder sourceBuilder = new StringBuilder();
402 sourceBuilder.append("<source-system = ");
403 sourceBuilder.append(StringUtils.isBlank(encode(source)) ? "" : encode(source));
404 sourceBuilder.append(">");
405 return sourceBuilder.toString();
408 protected String encode(String string) {
409 String encodedString = null;
410 if (string != null) {
411 encodedString = string.trim().replaceAll("<", "<").replaceAll(">", ">")
412 .replaceAll(":", ":").replaceAll(",", ",")
413 .replaceAll("=", "=");
415 return encodedString;
418 private void logArtifact(PropertyDefinition artifact) {
419 ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
420 String stringArtifact = null;
422 stringArtifact = mapper.writeValueAsString(artifact);
423 Log.info("Received PropertyDefinition:\n" + stringArtifact);
424 } catch (JsonProcessingException e) {
425 Log.error("Exception while logging artifact:", e);