2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
20 * ============LICENSE_END=========================================================
23 package org.openecomp.sdnc.config.params.transformer.tosca;
25 import com.att.eelf.configuration.EELFLogger;
26 import com.att.eelf.configuration.EELFManager;
27 import com.fasterxml.jackson.core.JsonProcessingException;
28 import com.fasterxml.jackson.databind.ObjectMapper;
29 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
30 import org.apache.commons.lang.StringUtils;
32 import org.openecomp.sdc.tosca.datatypes.model.*;
33 import org.openecomp.sdc.tosca.services.YamlUtil;
34 import org.openecomp.sdnc.config.params.data.Parameter;
35 import org.openecomp.sdnc.config.params.data.PropertyDefinition;
36 import org.openecomp.sdnc.config.params.data.RequestKey;
37 import org.openecomp.sdnc.config.params.data.ResponseKey;
38 import org.openecomp.sdnc.config.params.transformer.tosca.exceptions.ArtifactProcessorException;
41 import java.io.IOException;
42 import java.io.OutputStream;
43 import java.io.OutputStreamWriter;
45 import java.util.regex.Matcher;
46 import java.util.regex.Pattern;
48 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
50 public class ArtifactProcessorImpl implements ArtifactProcessor
52 private static final String DERIVEDFROM = "org.openecomp.genericvnf";
53 private static final EELFLogger Log = EELFManager.getInstance().getLogger(ArtifactProcessorImpl.class);
54 private static final String EQUALSENCODING = "=";
55 private static final String COLONENCODING = ":";
56 private static final String COMMAENCODING = ",";
57 private static final String GREATERTHANENCODING = ">";
58 private static final String LESSTHANENCODING = "<";
61 public void generateArtifact(PropertyDefinition artifact, OutputStream stream) throws ArtifactProcessorException
64 MDC.put(MDC_SERVICE_NAME,"ArtifactGenerator");
65 Log.info("Entered into generateArtifact");
66 if(!StringUtils.isBlank(artifact.getKind())) {
67 logArtifact(artifact);
68 ServiceTemplate serviceTemplate = new ServiceTemplate();
70 addNodeType(artifact, serviceTemplate);
72 TopologyTemplate topologyTemplate = new TopologyTemplate();
73 serviceTemplate.setTopology_template(topologyTemplate);
74 addNodeTemplate(artifact, serviceTemplate);
76 String tosca = new YamlUtil().objectToYaml(serviceTemplate);
77 OutputStreamWriter writer = new OutputStreamWriter(stream);
81 } catch (IOException e) {
82 Log.error("Error writing to outputstream", e);
83 throw new ArtifactProcessorException(e);
87 } catch (IOException e) {
88 Log.error("Error while closing outputstream writer", e);
95 Log.error("Kind in PropertyDefinition is blank or null");
96 throw new ArtifactProcessorException("Kind in PropertyDefinition is blank or null");
101 public void generateArtifact(String artifact, OutputStream stream) throws ArtifactProcessorException
103 ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
105 PropertyDefinition pd = mapper.readValue(artifact, PropertyDefinition.class);
106 generateArtifact(pd, stream);
108 catch (IOException e)
110 Log.error("Error parsing property definition content = "+ artifact,e);
111 throw new ArtifactProcessorException(e);
116 public PropertyDefinition readArtifact(String toscaArtifact) throws ArtifactProcessorException{
117 Log.info("Entered into readArtifact.");
118 Log.info("Received ToscaArtifact:\n" + toscaArtifact);
120 PropertyDefinition propertyDefinitionObj = new PropertyDefinition();
121 ServiceTemplate serviceTemplate = new YamlUtil().yamlToObject(toscaArtifact, ServiceTemplate.class);
124 Map<String, NodeType> nodeTypeMap = serviceTemplate.getNode_types();
125 Map<String, NodeTemplate> nodeTemplateMap = serviceTemplate.getTopology_template().getNode_templates();
127 String nodeTemplateName = nodeTemplateMap.keySet().toArray(new String[0])[0];
128 NodeTemplate nodeTemplate = nodeTemplateMap.get(nodeTemplateName);
129 Map<String, Object> nodeTemplateProperties = nodeTemplate.getProperties();
131 String kind = nodeTypeMap.keySet().toArray(new String[0])[0];
132 NodeType nodeType = nodeTypeMap.get(kind);
133 String version = nodeType.getVersion();
134 Log.info("ReadArtifact for "+ kind + " with version "+version);
135 propertyDefinitionObj.setKind(kind);
136 propertyDefinitionObj.setVersion(version);
138 List<Parameter> parameterList = new LinkedList<>();
140 Map<String, org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition> propertyDefinitionFromTOSCA = nodeType.getProperties();
141 if(null != propertyDefinitionFromTOSCA){
142 for (String propertyName : propertyDefinitionFromTOSCA.keySet()) {
143 org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition propertyDefinition = propertyDefinitionFromTOSCA.get(propertyName);
145 Parameter parameter = new Parameter();
146 parameter.setName(propertyName);
148 if (propertyDefinition.get_default() != null) {
149 parameter.setDefaultValue(propertyDefinition.get_default().toString());
151 parameter.setDescription(propertyDefinition.getDescription());
152 if (null != propertyDefinition.getRequired()) {
153 parameter.setRequired(propertyDefinition.getRequired());
155 parameter.setRequired(false);
158 if (StringUtils.isNotEmpty(propertyDefinition.getType())) {
159 parameter.setType(propertyDefinition.getType());
162 String propertValueExpr = (String) nodeTemplateProperties.get(propertyName);
163 String[] stringTokens = parsePropertyValueExpression(propertValueExpr);
164 String ruleType = stringTokens[0].substring(stringTokens[0].indexOf('=')+1,stringTokens[0].length()).replaceAll(">","").trim();
165 String responseExpression = stringTokens[1].substring(stringTokens[1].indexOf('=')+1,stringTokens[1].length());
166 String source = stringTokens[2].substring(stringTokens[2].indexOf('=')+1,stringTokens[2].length()).replaceAll(">","").trim();
167 String requestExpression = stringTokens[3].substring(stringTokens[3].indexOf('=')+1,stringTokens[3].length());
169 List<RequestKey> requestKeys = readRequestKeys(requestExpression);
170 List<ResponseKey> responseKeys = readResponseKeys(responseExpression);
172 parameter.setRuleType(ruleType);
173 parameter.setSource(source);
174 parameter.setRequestKeys(requestKeys);
175 parameter.setResponseKeys(responseKeys);
177 parameterList.add(parameter);
181 propertyDefinitionObj.setParameters(parameterList);
182 Log.info("Exiting from readArtifact. ");
183 return propertyDefinitionObj;
186 private List<ResponseKey> readResponseKeys(String responseExpression) throws ArtifactProcessorException {
187 Log.info("Entered into readResponseKeys.");
188 List<ResponseKey> responseKeyList = null;
190 expression = responseExpression.replaceAll("<", "").replaceAll(">", "").trim();
191 if (StringUtils.isNotEmpty(expression)) {
192 responseKeyList = new ArrayList<>();
194 String[] responseKeys = expression.split(",");
195 for (String responseKeyStr : responseKeys) {
196 ResponseKey responseKey = new ResponseKey();
198 responseKey.setUniqueKeyName(responseKeyStr.split(":")[0].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",").replaceAll(EQUALSENCODING,"=").trim());
199 responseKey.setUniqueKeyValue(responseKeyStr.split(":")[1].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",").replaceAll(EQUALSENCODING,"=").trim());
200 responseKey.setFieldKeyName(responseKeyStr.split(":")[2].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING, ":").replaceAll(COMMAENCODING, ",").replaceAll(EQUALSENCODING,"=").trim());
201 } catch (ArrayIndexOutOfBoundsException e) {
202 Log.error("Invalid response attribute found :" + responseKeyStr + "due to "+e);
203 throw new ArtifactProcessorException("Invalid response attribute found :" + responseKeyStr);
205 responseKeyList.add(responseKey);
208 Log.info("Exiting from readResponseKeys.");
209 return responseKeyList;
212 private List<RequestKey> readRequestKeys(String requestExpression) {
213 Log.info("Entered into readRequestKeys.");
214 List<RequestKey> requestKeyList = null;
216 expression = requestExpression.replaceAll("<","").replaceAll(">","").trim();
217 if(StringUtils.isNotEmpty(expression)){
218 requestKeyList = new ArrayList<>();
219 String[] requestKeys = expression.split(",");
220 for(String responseKeyStr :requestKeys){
221 RequestKey requestKey = new RequestKey();
222 requestKey.setKeyName(responseKeyStr.split(":")[0].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING,":").replaceAll(COMMAENCODING,",").replaceAll(EQUALSENCODING,"=").trim());
223 requestKey.setKeyValue(responseKeyStr.split(":")[1].replaceAll(LESSTHANENCODING, "<").replaceAll(GREATERTHANENCODING, ">").replaceAll(COLONENCODING,":").replaceAll(COMMAENCODING,",").replaceAll(EQUALSENCODING,"=").trim());
224 requestKeyList.add(requestKey);
227 Log.info("Exiting from readRequestKeys.");
228 return requestKeyList;
231 private String[] parsePropertyValueExpression(String propertValueExpr) throws ArtifactProcessorException{
232 Log.info("Entered into parsePropertyValueExpression.");
233 String nodeRegex = "<(.*?)>";
234 Pattern pattern = Pattern.compile(nodeRegex, Pattern.CASE_INSENSITIVE);
235 Matcher matcher = pattern.matcher(propertValueExpr);
236 List<String> stringTokens = new ArrayList<>();
237 while(matcher.find()){
238 stringTokens.add(matcher.group(0));
240 String[] propertiesArr = new String[stringTokens.size()];
241 propertiesArr = stringTokens.toArray(propertiesArr);
242 if(propertiesArr.length!=4){
243 throw new ArtifactProcessorException("Invalid input found " + propertValueExpr);
245 Log.info("Exiting from parsePropertyValueExpression.");
246 return propertiesArr;
249 private void addNodeType(PropertyDefinition artifact, ServiceTemplate toscaTemplate) throws ArtifactProcessorException {
250 //Add basic fields for the node
251 NodeType toscaNodeType = new NodeType();
252 toscaNodeType.setDerived_from(DERIVEDFROM);
253 toscaNodeType.setVersion(artifact.getVersion());
254 toscaNodeType.setDescription("");
255 if(artifact.getParameters()!=null) {
256 Map<String, org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition> toscaPropertyMap = new HashMap<>();
257 toscaNodeType.setProperties(toscaPropertyMap);
259 //Add properties from parameters of PD
260 for (Parameter pdParameter : artifact.getParameters()) {
261 addProperty(toscaNodeType, pdParameter);
265 // This is where it adds node in node Map and adds the map in tosca template
266 Map<String,NodeType> toscaNodeMap = new HashMap<>();
267 toscaNodeMap.put(artifact.getKind(),toscaNodeType);
268 toscaTemplate.setNode_types(toscaNodeMap);
271 private void addProperty(NodeType toscaNodeType, Parameter pdParameter) throws ArtifactProcessorException {
272 if(!StringUtils.isBlank(pdParameter.getName())&& !pdParameter.getName().matches(".*\\s+.*")) {
273 Log.info("Adding parameter " + pdParameter.getName() + " in node type");
274 org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition toscaProperty = new org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition();
276 toscaProperty.setType(StringUtils.isBlank(pdParameter.getType()) ? "string" : pdParameter.getType());
277 toscaProperty.set_default(pdParameter.getDefaultValue());
279 toscaProperty.setDescription(pdParameter.getDescription());
280 toscaProperty.setRequired(pdParameter.isRequired());
282 toscaNodeType.getProperties().put(pdParameter.getName(), toscaProperty);
286 String message ="Parameter name is empty,null or contains whitespace";
288 throw new ArtifactProcessorException(message);
292 private void addNodeTemplate(PropertyDefinition artifact, ServiceTemplate toscaTemplate)
294 NodeTemplate nodeTemplate = new NodeTemplate();
295 nodeTemplate.setType(artifact.getKind());
296 Map<String,Object> templateProperties = new HashMap<>();
297 //Add properties from parameters of PD
298 if(artifact.getParameters()!=null) {
299 for (Parameter pdParameter : artifact.getParameters()) {
300 addTemplateProperty(templateProperties, pdParameter);
302 nodeTemplate.setProperties(templateProperties);
304 Map<String,NodeTemplate> nodeTemplateMap = new HashMap<>();
305 nodeTemplateMap.put(artifact.getKind()+"_Template",nodeTemplate);
306 toscaTemplate.getTopology_template().setNode_templates(nodeTemplateMap);
309 private void addTemplateProperty(Map<String,Object> templateProperties, Parameter pdParameter)
311 Log.info("Adding parameter "+ pdParameter.getName() + " in node templates");
312 String responseKeys = buildResponseKeyExpression(pdParameter.getResponseKeys());
313 String requestKeys = buildRequestKeyExpression(pdParameter.getRequestKeys());
314 String ruleType = buildRuleType(pdParameter.getRuleType());
315 String source = buildSourceSystem(pdParameter.getSource());
316 String properties = ruleType + " " + responseKeys + " " + source + " " + requestKeys;
317 templateProperties.put(pdParameter.getName(),properties);
320 protected String buildResponseKeyExpression(List<ResponseKey> responseKeys)
322 StringBuilder propertyBuilder = new StringBuilder();
323 propertyBuilder.append("<response-keys = ");
324 if(responseKeys!=null) {
325 Iterator<ResponseKey> itr = responseKeys.iterator();
326 while (itr.hasNext()) {
327 ResponseKey res = itr.next();
329 propertyBuilder.append(encode(res.getUniqueKeyName()) + ":" + encode(res.getUniqueKeyValue()) + ":" + encode(res.getFieldKeyName()));
331 propertyBuilder.append(" , ");
334 propertyBuilder.append(">");
335 return propertyBuilder.toString();
338 protected String buildRequestKeyExpression(List<RequestKey> requestKeys)
340 StringBuilder propertyBuilder = new StringBuilder();
341 propertyBuilder.append("<request-keys = ");
342 if(requestKeys!=null) {
343 Iterator<RequestKey> itr = requestKeys.iterator();
344 while (itr.hasNext()) {
345 RequestKey res = itr.next();
347 propertyBuilder.append(encode(res.getKeyName()) + ":" + encode(res.getKeyValue()));
349 propertyBuilder.append(" , ");
352 propertyBuilder.append(">");
353 return propertyBuilder.toString();
356 protected String buildRuleType(String classType)
358 StringBuilder propertyBuilder = new StringBuilder();
359 String encodedClassType = StringUtils.isBlank(encode(classType))?"":encode(classType);
360 propertyBuilder.append("<");
361 propertyBuilder.append("rule-type = "+encodedClassType);
362 propertyBuilder.append(">");
363 return propertyBuilder.toString();
366 protected String buildSourceSystem(String source)
368 StringBuilder sourceBuilder = new StringBuilder();
369 sourceBuilder.append("<source-system = ");
370 sourceBuilder.append(StringUtils.isBlank(encode(source))?"":encode(source));
371 sourceBuilder.append(">");
372 return sourceBuilder.toString();
375 protected String encode(String string)
377 String encodedString = null;
379 encodedString = string.trim().replaceAll("<", "<").replaceAll(">", ">").replaceAll(":",":").replaceAll(",",",").replaceAll("=","=");
381 return encodedString;
384 private void logArtifact(PropertyDefinition artifact)
386 ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
387 String stringArtifact=null;
390 stringArtifact = mapper.writeValueAsString(artifact);
391 Log.info("Received PropertyDefinition:\n" + stringArtifact);
393 catch (JsonProcessingException e)
395 Log.error("Exception while logging artifact:",e);