2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 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 * ============LICENSE_END=========================================================
24 package org.onap.sdnc.config.params.transformer.tosca;
26 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
27 import java.io.IOException;
28 import java.io.OutputStream;
29 import java.io.OutputStreamWriter;
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.LinkedList;
34 import java.util.List;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
38 import org.apache.commons.lang.StringUtils;
39 import org.onap.sdnc.config.params.data.Parameter;
40 import org.onap.sdnc.config.params.data.PropertyDefinition;
41 import org.onap.sdnc.config.params.data.RequestKey;
42 import org.onap.sdnc.config.params.data.ResponseKey;
43 import org.onap.sdnc.config.params.transformer.tosca.exceptions.ArtifactProcessorException;
44 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
45 import org.onap.sdc.tosca.datatypes.model.NodeType;
46 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
47 import org.onap.sdc.tosca.datatypes.model.TopologyTemplate;
48 import org.onap.sdc.tosca.services.YamlUtil;
50 import com.att.eelf.configuration.EELFLogger;
51 import com.att.eelf.configuration.EELFManager;
52 import com.fasterxml.jackson.core.JsonProcessingException;
53 import com.fasterxml.jackson.databind.ObjectMapper;
54 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
56 public class ArtifactProcessorImpl implements ArtifactProcessor {
57 private static final String DERIVEDFROM = "org.openecomp.genericvnf";
58 private static final EELFLogger Log =
59 EELFManager.getInstance().getLogger(ArtifactProcessorImpl.class);
60 private static final String EQUALSENCODING = "=";
61 private static final String COLONENCODING = ":";
62 private static final String COMMAENCODING = ",";
63 private static final String GREATERTHANENCODING = ">";
64 private static final String LESSTHANENCODING = "<";
67 public void generateArtifact(PropertyDefinition artifact, OutputStream stream)
68 throws ArtifactProcessorException {
70 MDC.put(MDC_SERVICE_NAME, "ArtifactGenerator");
71 Log.info("Entered into generateArtifact");
72 if (!StringUtils.isBlank(artifact.getKind())) {
73 logArtifact(artifact);
74 ServiceTemplate serviceTemplate = new ServiceTemplate();
76 addNodeType(artifact, serviceTemplate);
78 TopologyTemplate topologyTemplate = new TopologyTemplate();
79 serviceTemplate.setTopology_template(topologyTemplate);
80 addNodeTemplate(artifact, serviceTemplate);
82 String tosca = new YamlUtil().objectToYaml(serviceTemplate);
83 OutputStreamWriter writer = new OutputStreamWriter(stream);
87 } catch (IOException e) {
88 Log.error("Error writing to outputstream", e);
89 throw new ArtifactProcessorException(e);
93 } catch (IOException e) {
94 Log.error("Error while closing outputstream writer", e);
99 Log.error("Kind in PropertyDefinition is blank or null");
100 throw new ArtifactProcessorException("Kind in PropertyDefinition is blank or null");
105 public void generateArtifact(String artifact, OutputStream stream)
106 throws ArtifactProcessorException {
107 ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
109 PropertyDefinition pd = mapper.readValue(artifact, PropertyDefinition.class);
110 generateArtifact(pd, stream);
111 } catch (IOException e) {
112 Log.error("Error parsing property definition content = " + artifact, e);
113 throw new ArtifactProcessorException(e);
118 public PropertyDefinition readArtifact(String toscaArtifact) throws ArtifactProcessorException {
119 Log.info("Entered into readArtifact.");
120 Log.info("Received ToscaArtifact:\n" + toscaArtifact);
122 PropertyDefinition propertyDefinitionObj = new PropertyDefinition();
123 ServiceTemplate serviceTemplate =
124 new YamlUtil().yamlToObject(toscaArtifact, ServiceTemplate.class);
126 // mapping parameters
127 Map<String, NodeType> nodeTypeMap = serviceTemplate.getNode_types();
128 Map<String, NodeTemplate> nodeTemplateMap =
129 serviceTemplate.getTopology_template().getNode_templates();
131 String nodeTemplateName = nodeTemplateMap.keySet().toArray(new String[0])[0];
132 NodeTemplate nodeTemplate = nodeTemplateMap.get(nodeTemplateName);
133 Map<String, Object> nodeTemplateProperties = nodeTemplate.getProperties();
135 String kind = nodeTypeMap.keySet().toArray(new String[0])[0];
136 NodeType nodeType = nodeTypeMap.get(kind);
137 String version = nodeType.getVersion();
138 Log.info("ReadArtifact for " + kind + " with version " + version);
139 propertyDefinitionObj.setKind(kind);
140 propertyDefinitionObj.setVersion(version);
142 List<Parameter> parameterList = new LinkedList<>();
144 Map<String, org.onap.sdc.tosca.datatypes.model.PropertyDefinition> propertyDefinitionFromTOSCA =
145 nodeType.getProperties();
146 if (null != propertyDefinitionFromTOSCA) {
147 for (String propertyName : propertyDefinitionFromTOSCA.keySet()) {
148 org.onap.sdc.tosca.datatypes.model.PropertyDefinition propertyDefinition =
149 propertyDefinitionFromTOSCA.get(propertyName);
151 Parameter parameter = new Parameter();
152 parameter.setName(propertyName);
154 if (propertyDefinition.get_default() != null) {
155 parameter.setDefaultValue(propertyDefinition.get_default().toString());
157 parameter.setDescription(propertyDefinition.getDescription());
158 if (null != propertyDefinition.getRequired()) {
159 parameter.setRequired(propertyDefinition.getRequired());
161 parameter.setRequired(false);
164 if (StringUtils.isNotEmpty(propertyDefinition.getType())) {
165 parameter.setType(propertyDefinition.getType());
168 String propertValueExpr = (String) nodeTemplateProperties.get(propertyName);
169 String[] stringTokens = parsePropertyValueExpression(propertValueExpr);
170 String ruleType = stringTokens[0]
171 .substring(stringTokens[0].indexOf('=') + 1, stringTokens[0].length())
172 .replaceAll(">", "").trim();
173 String responseExpression = stringTokens[1]
174 .substring(stringTokens[1].indexOf('=') + 1, stringTokens[1].length());
175 String source = stringTokens[2]
176 .substring(stringTokens[2].indexOf('=') + 1, stringTokens[2].length())
177 .replaceAll(">", "").trim();
178 String requestExpression = stringTokens[3]
179 .substring(stringTokens[3].indexOf('=') + 1, stringTokens[3].length());
181 List<RequestKey> requestKeys = readRequestKeys(requestExpression);
182 List<ResponseKey> responseKeys = readResponseKeys(responseExpression);
184 parameter.setRuleType(ruleType);
185 parameter.setSource(source);
186 parameter.setRequestKeys(requestKeys);
187 parameter.setResponseKeys(responseKeys);
189 parameterList.add(parameter);
193 propertyDefinitionObj.setParameters(parameterList);
194 Log.info("Exiting from readArtifact. ");
195 return propertyDefinitionObj;
198 private List<ResponseKey> readResponseKeys(String responseExpression)
199 throws ArtifactProcessorException {
200 Log.info("Entered into readResponseKeys.");
201 List<ResponseKey> responseKeyList = null;
203 expression = responseExpression.replaceAll("<", "").replaceAll(">", "").trim();
204 if (StringUtils.isNotEmpty(expression)) {
205 responseKeyList = new ArrayList<>();
207 String[] responseKeys = expression.split(",");
208 for (String responseKeyStr : responseKeys) {
209 ResponseKey responseKey = new ResponseKey();
211 responseKey.setUniqueKeyName(responseKeyStr.split(":")[0]
212 .replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">")
213 .replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",")
214 .replaceAll(EQUALSENCODING, "=").trim());
215 responseKey.setUniqueKeyValue(responseKeyStr.split(":")[1]
216 .replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">")
217 .replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",")
218 .replaceAll(EQUALSENCODING, "=").trim());
219 responseKey.setFieldKeyName(responseKeyStr.split(":")[2]
220 .replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">")
221 .replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",")
222 .replaceAll(EQUALSENCODING, "=").trim());
223 } catch (ArrayIndexOutOfBoundsException e) {
225 "Invalid response attribute found :" + responseKeyStr + "due to " + e);
226 throw new ArtifactProcessorException(
227 "Invalid response attribute found :" + responseKeyStr);
229 responseKeyList.add(responseKey);
232 Log.info("Exiting from readResponseKeys.");
233 return responseKeyList;
236 private List<RequestKey> readRequestKeys(String requestExpression) {
237 Log.info("Entered into readRequestKeys.");
238 List<RequestKey> requestKeyList = null;
240 expression = requestExpression.replaceAll("<", "").replaceAll(">", "").trim();
241 if (StringUtils.isNotEmpty(expression)) {
242 requestKeyList = new ArrayList<>();
243 String[] requestKeys = expression.split(",");
244 for (String responseKeyStr : requestKeys) {
245 RequestKey requestKey = new RequestKey();
246 requestKey.setKeyName(responseKeyStr.split(":")[0].replaceAll(LESSTHANENCODING, "<")
247 .replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING, ":")
248 .replaceAll(COMMAENCODING, ",").replaceAll(EQUALSENCODING, "=").trim());
249 requestKey.setKeyValue(responseKeyStr.split(":")[1]
250 .replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">")
251 .replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",")
252 .replaceAll(EQUALSENCODING, "=").trim());
253 requestKeyList.add(requestKey);
256 Log.info("Exiting from readRequestKeys.");
257 return requestKeyList;
260 private String[] parsePropertyValueExpression(String propertValueExpr)
261 throws ArtifactProcessorException {
262 Log.info("Entered into parsePropertyValueExpression.");
263 String nodeRegex = "<(.*?)>";
264 Pattern pattern = Pattern.compile(nodeRegex, Pattern.CASE_INSENSITIVE);
265 Matcher matcher = pattern.matcher(propertValueExpr);
266 List<String> stringTokens = new ArrayList<>();
267 while (matcher.find()) {
268 stringTokens.add(matcher.group(0));
270 String[] propertiesArr = new String[stringTokens.size()];
271 propertiesArr = stringTokens.toArray(propertiesArr);
272 if (propertiesArr.length != 4) {
273 throw new ArtifactProcessorException("Invalid input found " + propertValueExpr);
275 Log.info("Exiting from parsePropertyValueExpression.");
276 return propertiesArr;
279 private void addNodeType(PropertyDefinition artifact, ServiceTemplate toscaTemplate)
280 throws ArtifactProcessorException {
281 // Add basic fields for the node
282 NodeType toscaNodeType = new NodeType();
283 toscaNodeType.setDerived_from(DERIVEDFROM);
284 toscaNodeType.setVersion(artifact.getVersion());
285 toscaNodeType.setDescription("");
286 if (artifact.getParameters() != null) {
287 Map<String, org.onap.sdc.tosca.datatypes.model.PropertyDefinition> toscaPropertyMap =
289 toscaNodeType.setProperties(toscaPropertyMap);
291 // Add properties from parameters of PD
292 for (Parameter pdParameter : artifact.getParameters()) {
293 addProperty(toscaNodeType, pdParameter);
297 // This is where it adds node in node Map and adds the map in tosca template
298 Map<String, NodeType> toscaNodeMap = new HashMap<>();
299 toscaNodeMap.put(artifact.getKind(), toscaNodeType);
300 toscaTemplate.setNode_types(toscaNodeMap);
303 private void addProperty(NodeType toscaNodeType, Parameter pdParameter)
304 throws ArtifactProcessorException {
305 if (!StringUtils.isBlank(pdParameter.getName())
306 && !pdParameter.getName().matches(".*\\s+.*")) {
307 Log.info("Adding parameter " + pdParameter.getName() + " in node type");
308 org.onap.sdc.tosca.datatypes.model.PropertyDefinition toscaProperty =
309 new org.onap.sdc.tosca.datatypes.model.PropertyDefinition();
311 toscaProperty.setType(
312 StringUtils.isBlank(pdParameter.getType()) ? "string" : pdParameter.getType());
313 toscaProperty.set_default(pdParameter.getDefaultValue());
315 toscaProperty.setDescription(pdParameter.getDescription());
316 toscaProperty.setRequired(pdParameter.isRequired());
318 toscaNodeType.getProperties().put(pdParameter.getName(), toscaProperty);
320 String message = "Parameter name is empty,null or contains whitespace";
322 throw new ArtifactProcessorException(message);
326 private void addNodeTemplate(PropertyDefinition artifact, ServiceTemplate toscaTemplate) {
327 NodeTemplate nodeTemplate = new NodeTemplate();
328 nodeTemplate.setType(artifact.getKind());
329 Map<String, Object> templateProperties = new HashMap<>();
330 // Add properties from parameters of PD
331 if (artifact.getParameters() != null) {
332 for (Parameter pdParameter : artifact.getParameters()) {
333 addTemplateProperty(templateProperties, pdParameter);
335 nodeTemplate.setProperties(templateProperties);
337 Map<String, NodeTemplate> nodeTemplateMap = new HashMap<>();
338 nodeTemplateMap.put(artifact.getKind() + "_Template", nodeTemplate);
339 toscaTemplate.getTopology_template().setNode_templates(nodeTemplateMap);
342 private void addTemplateProperty(Map<String, Object> templateProperties,
343 Parameter pdParameter) {
344 Log.info("Adding parameter " + pdParameter.getName() + " in node templates");
345 String responseKeys = buildResponseKeyExpression(pdParameter.getResponseKeys());
346 String requestKeys = buildRequestKeyExpression(pdParameter.getRequestKeys());
347 String ruleType = buildRuleType(pdParameter.getRuleType());
348 String source = buildSourceSystem(pdParameter.getSource());
349 String properties = ruleType + " " + responseKeys + " " + source + " " + requestKeys;
350 templateProperties.put(pdParameter.getName(), properties);
353 protected String buildResponseKeyExpression(List<ResponseKey> responseKeys) {
354 StringBuilder propertyBuilder = new StringBuilder();
355 propertyBuilder.append("<response-keys = ");
356 if (responseKeys != null) {
357 Iterator<ResponseKey> itr = responseKeys.iterator();
358 while (itr.hasNext()) {
359 ResponseKey res = itr.next();
361 propertyBuilder.append(
362 encode(res.getUniqueKeyName()) + ":" + encode(res.getUniqueKeyValue())
363 + ":" + encode(res.getFieldKeyName()));
365 propertyBuilder.append(" , ");
368 propertyBuilder.append(">");
369 return propertyBuilder.toString();
372 protected String buildRequestKeyExpression(List<RequestKey> requestKeys) {
373 StringBuilder propertyBuilder = new StringBuilder();
374 propertyBuilder.append("<request-keys = ");
375 if (requestKeys != null) {
376 Iterator<RequestKey> itr = requestKeys.iterator();
377 while (itr.hasNext()) {
378 RequestKey res = itr.next();
381 .append(encode(res.getKeyName()) + ":" + encode(res.getKeyValue()));
383 propertyBuilder.append(" , ");
386 propertyBuilder.append(">");
387 return propertyBuilder.toString();
390 protected String buildRuleType(String classType) {
391 StringBuilder propertyBuilder = new StringBuilder();
392 String encodedClassType = StringUtils.isBlank(encode(classType)) ? "" : encode(classType);
393 propertyBuilder.append("<");
394 propertyBuilder.append("rule-type = " + encodedClassType);
395 propertyBuilder.append(">");
396 return propertyBuilder.toString();
399 protected String buildSourceSystem(String source) {
400 StringBuilder sourceBuilder = new StringBuilder();
401 sourceBuilder.append("<source-system = ");
402 sourceBuilder.append(StringUtils.isBlank(encode(source)) ? "" : encode(source));
403 sourceBuilder.append(">");
404 return sourceBuilder.toString();
407 protected String encode(String string) {
408 String encodedString = null;
409 if (string != null) {
410 encodedString = string.trim().replaceAll("<", "<").replaceAll(">", ">")
411 .replaceAll(":", ":").replaceAll(",", ",")
412 .replaceAll("=", "=");
414 return encodedString;
417 private void logArtifact(PropertyDefinition artifact) {
418 ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
419 String stringArtifact = null;
421 stringArtifact = mapper.writeValueAsString(artifact);
422 Log.info("Received PropertyDefinition:\n" + stringArtifact);
423 } catch (JsonProcessingException e) {
424 Log.error("Exception while logging artifact:", e);